diff --git a/dom/media/mediasource/ContainerParser.cpp b/dom/media/mediasource/ContainerParser.cpp index e3dae3b1d4..3bcab78f6f 100644 --- a/dom/media/mediasource/ContainerParser.cpp +++ b/dom/media/mediasource/ContainerParser.cpp @@ -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()) { + 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 diff --git a/dom/media/mediasource/TrackBuffersManager.cpp b/dom/media/mediasource/TrackBuffersManager.cpp index 8e83a8dd43..5fea90e3c2 100644 --- a/dom/media/mediasource/TrackBuffersManager.cpp +++ b/dom/media/mediasource/TrackBuffersManager.cpp @@ -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");