--- a/dom/media/mediasource/ContainerParser.cpp
+++ b/dom/media/mediasource/ContainerParser.cpp
@@ -30,16 +30,18 @@ extern mozilla::LogModule* GetMediaSourc
#define TOSTRING(x) STRINGIFY(x)
#define MSE_DEBUG(name, arg, ...) MOZ_LOG(GetMediaSourceSamplesLog(), mozilla::LogLevel::Debug, (TOSTRING(name) "(%p:%s)::%s: " arg, this, mType.OriginalString().Data(), __func__, ##__VA_ARGS__))
#define MSE_DEBUGV(name, arg, ...) MOZ_LOG(GetMediaSourceSamplesLog(), mozilla::LogLevel::Verbose, (TOSTRING(name) "(%p:%s)::%s: " arg, this, mType.OriginalString().Data(), __func__, ##__VA_ARGS__))
namespace mozilla {
ContainerParser::ContainerParser(const MediaContainerType& aType)
: mHasInitData(false)
+ , mTotalParsed(0)
+ , mGlobalOffset(0)
, mType(aType)
{
}
ContainerParser::~ContainerParser() = default;
MediaResult
ContainerParser::IsInitSegmentPresent(MediaByteBuffer* aData)
@@ -192,33 +194,35 @@ public:
bool initSegment = NS_SUCCEEDED(IsInitSegmentPresent(aData));
if (mLastMapping &&
(initSegment || NS_SUCCEEDED(IsMediaSegmentPresent(aData)))) {
// The last data contained a complete cluster but we can only detect it
// now that a new one is starting.
// We use mOffset as end position to ensure that any blocks not reported
// by WebMBufferParser are properly skipped.
- mCompleteMediaSegmentRange = MediaByteRange(mLastMapping.ref().mSyncOffset,
- mOffset);
+ mCompleteMediaSegmentRange =
+ MediaByteRange(mLastMapping.ref().mSyncOffset, mOffset) + mGlobalOffset;
mLastMapping.reset();
MSE_DEBUG(WebMContainerParser,
"New cluster found at start, ending previous one");
return NS_ERROR_NOT_AVAILABLE;
}
if (initSegment) {
mOffset = 0;
mParser = WebMBufferedParser(0);
mOverlappedMapping.Clear();
mInitData = new MediaByteBuffer();
mResource = new SourceBufferResource(
MediaContainerType(MEDIAMIMETYPE("video/webm")));
+ mCompleteInitSegmentRange = MediaByteRange();
mCompleteMediaHeaderRange = MediaByteRange();
mCompleteMediaSegmentRange = MediaByteRange();
+ mGlobalOffset = mTotalParsed;
}
// XXX if it only adds new mappings, overlapped but not available
// (e.g. overlap < 0) frames are "lost" from the reported mappings here.
nsTArray<WebMTimeDataOffset> mapping;
mapping.AppendElements(mOverlappedMapping);
mOverlappedMapping.Clear();
ReentrantMonitor dummy("dummy");
@@ -232,28 +236,30 @@ public:
// We should be more precise.
if (initSegment || !HasCompleteInitData()) {
if (mParser.mInitEndOffset > 0) {
MOZ_ASSERT(mParser.mInitEndOffset <= mResource->GetLength());
if (!mInitData->SetLength(mParser.mInitEndOffset, fallible)) {
// Super unlikely OOM
return NS_ERROR_OUT_OF_MEMORY;
}
- mCompleteInitSegmentRange = MediaByteRange(0, mParser.mInitEndOffset);
+ mCompleteInitSegmentRange =
+ MediaByteRange(0, mParser.mInitEndOffset) + mGlobalOffset;
char* buffer = reinterpret_cast<char*>(mInitData->Elements());
mResource->ReadFromCache(buffer, 0, mParser.mInitEndOffset);
MSE_DEBUG(WebMContainerParser, "Stashed init of %" PRId64 " bytes.",
mParser.mInitEndOffset);
mResource = nullptr;
} else {
MSE_DEBUG(WebMContainerParser, "Incomplete init found.");
}
mHasInitData = true;
}
mOffset += aData->Length();
+ mTotalParsed += aData->Length();
if (mapping.IsEmpty()) {
return NS_ERROR_NOT_AVAILABLE;
}
// Calculate media range for first media segment.
// Check if we have a cluster finishing in the current data.
@@ -276,34 +282,37 @@ public:
mapping.Length() - completeIdx - 1);
if (completeIdx < 0) {
mLastMapping.reset();
return NS_ERROR_NOT_AVAILABLE;
}
if (mCompleteMediaHeaderRange.IsEmpty()) {
- mCompleteMediaHeaderRange = MediaByteRange(mapping[0].mSyncOffset,
- mapping[0].mEndOffset);
+ mCompleteMediaHeaderRange =
+ MediaByteRange(mapping[0].mSyncOffset, mapping[0].mEndOffset) +
+ mGlobalOffset;
}
if (foundNewCluster && mOffset >= mapping[endIdx].mEndOffset) {
// We now have all information required to delimit a complete cluster.
int64_t endOffset = mapping[endIdx+1].mSyncOffset;
if (mapping[endIdx+1].mInitOffset > mapping[endIdx].mInitOffset) {
// We have a new init segment before this cluster.
endOffset = mapping[endIdx+1].mInitOffset;
}
- mCompleteMediaSegmentRange = MediaByteRange(mapping[endIdx].mSyncOffset,
- endOffset);
+ mCompleteMediaSegmentRange =
+ MediaByteRange(mapping[endIdx].mSyncOffset, endOffset) + mGlobalOffset;
} else if (mapping[endIdx].mClusterEndOffset >= 0 &&
mOffset >= mapping[endIdx].mClusterEndOffset) {
- mCompleteMediaSegmentRange = MediaByteRange(
- mapping[endIdx].mSyncOffset,
- mParser.EndSegmentOffset(mapping[endIdx].mClusterEndOffset));
+ mCompleteMediaSegmentRange =
+ MediaByteRange(
+ mapping[endIdx].mSyncOffset,
+ mParser.EndSegmentOffset(mapping[endIdx].mClusterEndOffset))
+ + mGlobalOffset;
}
Maybe<WebMTimeDataOffset> previousMapping;
if (completeIdx) {
previousMapping = Some(mapping[completeIdx - 1]);
} else {
previousMapping = mLastMapping;
}
@@ -491,49 +500,58 @@ public:
MediaContainerType(MEDIAMIMETYPE("video/mp4")));
mStream = new MP4Stream(mResource);
// We use a timestampOffset of 0 for ContainerParser, and require
// consumers of ParseStartAndEndTimestamps to add their timestamp offset
// manually. This allows the ContainerParser to be shared across different
// timestampOffsets.
mParser = new mp4_demuxer::MoofParser(mStream, 0, /* aIsAudio = */ false);
mInitData = new MediaByteBuffer();
+ mCompleteInitSegmentRange = MediaByteRange();
+ mCompleteMediaHeaderRange = MediaByteRange();
+ mCompleteMediaSegmentRange = MediaByteRange();
+ mGlobalOffset = mTotalParsed;
} else if (!mStream || !mParser) {
+ mTotalParsed += aData->Length();
return NS_ERROR_NOT_AVAILABLE;
}
mResource->AppendData(aData);
MediaByteRangeSet byteRanges;
byteRanges +=
MediaByteRange(int64_t(mParser->mOffset), mResource->GetLength());
mParser->RebuildFragmentedIndex(byteRanges);
if (initSegment || !HasCompleteInitData()) {
MediaByteRange& range = mParser->mInitRange;
if (range.Length()) {
- mCompleteInitSegmentRange = range;
+ mCompleteInitSegmentRange = range + mGlobalOffset;
if (!mInitData->SetLength(range.Length(), fallible)) {
// Super unlikely OOM
return NS_ERROR_OUT_OF_MEMORY;
}
char* buffer = reinterpret_cast<char*>(mInitData->Elements());
mResource->ReadFromCache(buffer, range.mStart, range.Length());
MSE_DEBUG(MP4ContainerParser ,"Stashed init of %" PRIu64 " bytes.",
range.Length());
} else {
MSE_DEBUG(MP4ContainerParser, "Incomplete init found.");
}
mHasInitData = true;
}
+ mTotalParsed += aData->Length();
mp4_demuxer::Interval<mp4_demuxer::Microseconds> compositionRange =
mParser->GetCompositionRange(byteRanges);
- mCompleteMediaHeaderRange = mParser->FirstCompleteMediaHeader();
- mCompleteMediaSegmentRange = mParser->FirstCompleteMediaSegment();
+ mCompleteMediaHeaderRange =
+ mParser->FirstCompleteMediaHeader() + mGlobalOffset;
+ mCompleteMediaSegmentRange =
+ mParser->FirstCompleteMediaSegment() + mGlobalOffset;
+
ErrorResult rv;
if (HasCompleteInitData()) {
mResource->EvictData(mParser->mOffset, mParser->mOffset, rv);
}
if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException();
return NS_ERROR_OUT_OF_MEMORY;
}