mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-06-01 00:09:57 +00:00
Properly search for the required MP4 Atoms rather than make assumptions
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user