Properly search for the required MP4 Atoms rather than make assumptions

This commit is contained in:
trav90
2017-05-04 02:34:04 -05:00
committed by roytam1
parent 9bdd979cfc
commit 26cd7523aa
2 changed files with 52 additions and 32 deletions
+40 -27
View File
@@ -13,6 +13,8 @@
#include "MediaData.h"
#ifdef MOZ_FMP4
#include "MP4Stream.h"
#include "mp4_demuxer/AtomType.h"
#include "mp4_demuxer/ByteReader.h"
#endif
#include "SourceBufferResource.h"
@@ -27,6 +29,7 @@ extern PRLogModuleInfo* GetMediaSourceLog();
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define MSE_DEBUG(name, arg, ...) PR_LOG(GetMediaSourceLog(), PR_LOG_DEBUG, (TOSTRING(name) "(%p:%s)::%s: " arg, this, mType.get(), __func__, ##__VA_ARGS__))
#define MSE_DEBUGV(name, arg, ...) PR_LOG(GetMediaSourceLog(), PR_LOG_DEBUG, (TOSTRING(name) "(%p:%s)::%s: " arg, this, mType.get(), __func__, ##__VA_ARGS__))
#else
#define MSE_DEBUG(...)
#endif
@@ -281,44 +284,53 @@ public:
, mMonitor("MP4ContainerParser Index Monitor")
{}
bool HasAtom(const mp4_demuxer::AtomType& aAtom, const MediaLargeByteBuffer* aData) {
mp4_demuxer::ByteReader reader(aData);
while (reader.Remaining() >= 8) {
uint64_t size = reader.ReadU32();
const uint8_t* typec = reader.Peek(4);
uint32_t type = reader.ReadU32();
MSE_DEBUGV(MP4ContainerParser ,"Checking atom:'%c%c%c%c'",
typec[0], typec[1], typec[2], typec[3]);
if (mp4_demuxer::AtomType(type) == aAtom) {
reader.DiscardRemaining();
return true;
}
if (size == 1) {
// 64 bits size.
if (!reader.CanReadType<uint64_t>()) {
break;
}
size = reader.ReadU64();
} else if (size == 0) {
// Atom extends to the end of the buffer, it can't have what we're
// looking for.
break;
}
if (reader.Remaining() < size - 8) {
// Incomplete atom.
break;
}
reader.Read(size - 8);
}
reader.DiscardRemaining();
return false;
}
bool IsInitSegmentPresent(MediaLargeByteBuffer* aData) override
{
ContainerParser::IsInitSegmentPresent(aData);
// Each MP4 atom has a chunk size and chunk type. The root chunk in an MP4
// file is the 'ftyp' atom followed by a file type. We just check for a
// vaguely valid 'ftyp' atom.
if (aData->Length() < 8) {
return false;
}
uint32_t chunk_size = BigEndian::readUint32(aData->Elements());
if (chunk_size < 8) {
return false;
}
return (*aData)[4] == 'f' && (*aData)[5] == 't' && (*aData)[6] == 'y' &&
(*aData)[7] == 'p';
return HasAtom(mp4_demuxer::AtomType("ftyp"), aData);
}
bool IsMediaSegmentPresent(MediaLargeByteBuffer* aData) override
{
ContainerParser::IsMediaSegmentPresent(aData);
if (aData->Length() < 8) {
return false;
}
uint32_t chunk_size = BigEndian::readUint32(aData->Elements());
if (chunk_size < 8) {
return false;
}
return ((*aData)[4] == 'm' && (*aData)[5] == 'o' && (*aData)[6] == 'o' &&
(*aData)[7] == 'f') ||
((*aData)[4] == 's' && (*aData)[5] == 't' && (*aData)[6] == 'y' &&
(*aData)[7] == 'p') ||
((*aData)[4] == 's' && (*aData)[5] == 'i' && (*aData)[6] == 'd' &&
(*aData)[7] == 'x');
return HasAtom(mp4_demuxer::AtomType("moof"), aData);
}
bool ParseStartAndEndTimestamps(MediaLargeByteBuffer* aData,
@@ -414,5 +426,6 @@ ContainerParser::CreateForMIMEType(const nsACString& aType)
}
#undef MSE_DEBUG
#undef MSE_DEBUGV
} // namespace mozilla
+12 -5
View File
@@ -563,7 +563,9 @@ TrackBuffersManager::SegmentParserLoop()
// 3. Remove any bytes that the byte stream format specifications say must be
// ignored from the start of the input buffer.
// TODO
// We do not remove bytes from our input buffer. Instead we enforce that
// our ContainerParser is able to skip over all data that is supposed to be
// ignored.
// 4. If the append state equals WAITING_FOR_SEGMENT, then run the following
// steps:
@@ -577,9 +579,10 @@ TrackBuffersManager::SegmentParserLoop()
continue;
}
// We have neither an init segment nor a media segment, this is invalid
// data.
MSE_DEBUG("Found invalid data");
RejectAppend(NS_ERROR_FAILURE, __func__);
// data. We can ignore it.
MSE_DEBUG("Found invalid data, ignoring.");
mInputBuffer = nullptr;
NeedMoreData();
return;
}
@@ -693,7 +696,11 @@ TrackBuffersManager::InitializationSegmentReceived()
mCurrentInputBuffer->AppendData(mParser->InitData());
uint32_t length =
mParser->InitSegmentRange().mEnd - (mProcessedInput - mInputBuffer->Length());
mInputBuffer->RemoveElementsAt(0, length);
if (mInputBuffer->Length() == length) {
mInputBuffer = nullptr;
} else {
mInputBuffer->RemoveElementsAt(0, length);
}
CreateDemuxerforMIMEType();
if (!mInputDemuxer) {
MOZ_ASSERT(false, "TODO type not supported");