diff --git a/content/media/MediaDecoderReader.h b/content/media/MediaDecoderReader.h index d2bea4387a4a..713c275ef464 100644 --- a/content/media/MediaDecoderReader.h +++ b/content/media/MediaDecoderReader.h @@ -159,7 +159,6 @@ public: // Only used by WebMReader and MediaOmxReader for now, so stub here rather // than in every reader than inherits from MediaDecoderReader. virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset) {} - virtual int64_t GetEvictionOffset(double aTime) { return -1; } virtual MediaQueue& AudioQueue() { return mAudioQueue; } virtual MediaQueue& VideoQueue() { return mVideoQueue; } diff --git a/content/media/fmp4/MP4Reader.cpp b/content/media/fmp4/MP4Reader.cpp index 541e3e9c0004..5f2f536ffa45 100644 --- a/content/media/fmp4/MP4Reader.cpp +++ b/content/media/fmp4/MP4Reader.cpp @@ -109,6 +109,7 @@ MP4Reader::MP4Reader(AbstractMediaDecoder* aDecoder) , mVideo("MP4 video decoder data", Preferences::GetUint("media.mp4-video-decode-ahead", 2)) , mLastReportedNumDecodedFrames(0) , mLayersBackendType(layers::LayersBackend::LAYERS_NONE) + , mTimeRangesMonitor("MP4Reader::TimeRanges") , mDemuxerInitialized(false) , mIsEncrypted(false) { @@ -768,36 +769,29 @@ MP4Reader::NotifyDataArrived(const char* aBuffer, uint32_t aLength, void MP4Reader::UpdateIndex() { + nsTArray ranges; + nsTArray> timeRanges; + MediaResource* resource = mDecoder->GetResource(); resource->Pin(); - nsTArray ranges; if (NS_SUCCEEDED(resource->GetCachedRanges(ranges))) { - mDemuxer->UpdateIndex(ranges); + mDemuxer->ConvertByteRangesToTime(ranges, &timeRanges); } resource->Unpin(); + + MonitorAutoLock mon(mTimeRangesMonitor); + mTimeRanges = timeRanges; } -int64_t -MP4Reader::GetEvictionOffset(double aTime) -{ - return mDemuxer->GetEvictionOffset(aTime * 1000000.0); -} nsresult MP4Reader::GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime) { - MediaResource* resource = mDecoder->GetResource(); - resource->Pin(); - nsTArray ranges; - if (NS_SUCCEEDED(resource->GetCachedRanges(ranges))) { - nsTArray> timeRanges; - mDemuxer->ConvertByteRangesToTime(ranges, &timeRanges); - for (size_t i = 0; i < timeRanges.Length(); i++) { - aBuffered->Add((timeRanges[i].start - aStartTime) / 1000000.0, - (timeRanges[i].end - aStartTime) / 1000000.0); - } + MonitorAutoLock mon(mTimeRangesMonitor); + for (size_t i = 0; i < mTimeRanges.Length(); i++) { + aBuffered->Add((mTimeRanges[i].start - aStartTime) / 1000000.0, + (mTimeRanges[i].end - aStartTime) / 1000000.0); } - resource->Unpin(); return NS_OK; } diff --git a/content/media/fmp4/MP4Reader.h b/content/media/fmp4/MP4Reader.h index a073d3fbb4cf..6bc00ad18b31 100644 --- a/content/media/fmp4/MP4Reader.h +++ b/content/media/fmp4/MP4Reader.h @@ -55,8 +55,6 @@ public: virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset) MOZ_OVERRIDE; - virtual int64_t GetEvictionOffset(double aTime) MOZ_OVERRIDE; - virtual nsresult GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime) MOZ_OVERRIDE; @@ -182,6 +180,8 @@ private: layers::LayersBackend mLayersBackendType; nsTArray> mInitDataEncountered; + Monitor mTimeRangesMonitor; + nsTArray> mTimeRanges; // True if we've read the streams' metadata. bool mDemuxerInitialized; diff --git a/content/media/mediasource/SubBufferDecoder.cpp b/content/media/mediasource/SubBufferDecoder.cpp index 195997451cf9..9456dc40ae15 100644 --- a/content/media/mediasource/SubBufferDecoder.cpp +++ b/content/media/mediasource/SubBufferDecoder.cpp @@ -112,16 +112,11 @@ SubBufferDecoder::GetBuffered(dom::TimeRanges* aBuffered) int64_t SubBufferDecoder::ConvertToByteOffset(double aTime) { - int64_t readerOffset = mReader->GetEvictionOffset(aTime); - if (readerOffset >= 0) { - return readerOffset; - } - // Uses a conversion based on (aTime/duration) * length. For the // purposes of eviction this should be adequate since we have the // byte threshold as well to ensure data actually gets evicted and // we ensure we don't evict before the current playable point. - if (mMediaDuration <= 0) { + if (mMediaDuration == -1) { return -1; } int64_t length = GetResource()->GetLength(); diff --git a/media/libstagefright/binding/Index.cpp b/media/libstagefright/binding/Index.cpp index e11f00985fef..eaed3b2c16f0 100644 --- a/media/libstagefright/binding/Index.cpp +++ b/media/libstagefright/binding/Index.cpp @@ -85,101 +85,67 @@ Index::Index(const stagefright::Vector& aIndex, Index::~Index() {} -void -Index::UpdateMoofIndex(const nsTArray& aByteRanges) -{ - if (!mMoofParser) { - return; - } - - MonitorAutoLock mon(mMonitor); - mMoofParser->RebuildFragmentedIndex(aByteRanges); -} - void Index::ConvertByteRangesToTimeRanges( const nsTArray& aByteRanges, nsTArray>* aTimeRanges) { - MonitorAutoLock mon(mMonitor); - RangeFinder rangeFinder(aByteRanges); nsTArray> timeRanges; - nsTArray*> indexes; + nsTArray moofIndex; + nsTArray* index; if (mMoofParser) { - // We take the index out of the moof parser and move it into a local - // variable so we don't get concurrency issues. It gets freed when we - // exit this function. - for (int i = 0; i < mMoofParser->mMoofs.Length(); i++) { - Moof& moof = mMoofParser->mMoofs[i]; + { + MonitorAutoLock mon(mMonitor); + mMoofParser->RebuildFragmentedIndex(aByteRanges); - // We need the entire moof in order to play anything - if (rangeFinder.Contains(moof.mRange)) { - if (rangeFinder.Contains(moof.mMdatRange)) { + // We take the index out of the moof parser and move it into a local + // variable so we don't get concurrency issues. It gets freed when we + // exit this function. + for (int i = 0; i < mMoofParser->mMoofs.Length(); i++) { + Moof& moof = mMoofParser->mMoofs[i]; + if (rangeFinder.Contains(moof.mRange) && + rangeFinder.Contains(moof.mMdatRange)) { timeRanges.AppendElements(moof.mTimeRanges); } else { - indexes.AppendElement(&moof.mIndex); + moofIndex.AppendElements(mMoofParser->mMoofs[i].mIndex); } } } + index = &moofIndex; } else { - indexes.AppendElement(&mIndex); + index = &mIndex; } bool hasSync = false; - for (size_t i = 0; i < indexes.Length(); i++) { - nsTArray* index = indexes[i]; - for (size_t j = 0; j < index->Length(); j++) { - const MediaSource::Indice& indice = (*index)[j]; - if (!rangeFinder.Contains( - MediaByteRange(indice.start_offset, indice.end_offset))) { - // We process the index in decode order so we clear hasSync when we hit - // a range that isn't buffered. - hasSync = false; - continue; - } + for (size_t i = 0; i < index->Length(); i++) { + const MediaSource::Indice& indice = (*index)[i]; + if (!rangeFinder.Contains(MediaByteRange(indice.start_offset, + indice.end_offset))) { + // We process the index in decode order so we clear hasSync when we hit + // a range that isn't buffered. + hasSync = false; + continue; + } - hasSync |= indice.sync; - if (!hasSync) { - continue; - } + hasSync |= indice.sync; + if (!hasSync) { + continue; + } - Interval::SemiNormalAppend( - timeRanges, Interval(indice.start_composition, - indice.end_composition)); + // This is an optimisation for when the file is decoded in composition + // order. It means that Normalise() below doesn't need to do a sort. + size_t s = timeRanges.Length(); + if (s && timeRanges[s - 1].end == indice.start_composition) { + timeRanges[s - 1].end = indice.end_composition; + } else { + timeRanges.AppendElement(Interval(indice.start_composition, + indice.end_composition)); } } // This fixes up when the compositon order differs from the byte range order Interval::Normalize(timeRanges, aTimeRanges); } - -uint64_t -Index::GetEvictionOffset(Microseconds aTime) -{ - uint64_t offset = std::numeric_limits::max(); - if (mMoofParser) { - // We need to keep the whole moof if we're keeping any of it because the - // parser doesn't keep parsed moofs. - for (int i = 0; i < mMoofParser->mMoofs.Length(); i++) { - Moof& moof = mMoofParser->mMoofs[i]; - - if (!moof.mTimeRanges.IsEmpty() && moof.mTimeRanges[0].end > aTime) { - offset = std::min(offset, uint64_t(std::min(moof.mRange.mStart, - moof.mMdatRange.mStart))); - } - } - } else { - // We've already parsed and stored the moov so we don't need to keep it. - // All we need to keep is the sample data itself. - for (size_t i = 0; i < mIndex.Length(); i++) { - const MediaSource::Indice& indice = mIndex[i]; - if (aTime >= indice.start_composition) { - offset = std::min(offset, indice.start_offset); - } - } - } - return offset; -} } diff --git a/media/libstagefright/binding/include/mp4_demuxer/Index.h b/media/libstagefright/binding/include/mp4_demuxer/Index.h index eaeccfbba2be..618a905d4c75 100644 --- a/media/libstagefright/binding/include/mp4_demuxer/Index.h +++ b/media/libstagefright/binding/include/mp4_demuxer/Index.h @@ -22,11 +22,9 @@ public: Stream* aSource, uint32_t aTrackId); ~Index(); - void UpdateMoofIndex(const nsTArray& aByteRanges); void ConvertByteRangesToTimeRanges( const nsTArray& aByteRanges, nsTArray>* aTimeRanges); - uint64_t GetEvictionOffset(Microseconds aTime); private: mozilla::Monitor mMonitor; diff --git a/media/libstagefright/binding/include/mp4_demuxer/Interval.h b/media/libstagefright/binding/include/mp4_demuxer/Interval.h index 77f5f01fd025..61268acdb8a4 100644 --- a/media/libstagefright/binding/include/mp4_demuxer/Interval.h +++ b/media/libstagefright/binding/include/mp4_demuxer/Interval.h @@ -61,7 +61,7 @@ struct Interval } MOZ_ASSERT(aNormalized->IsEmpty()); - nsTArray> sorted; + nsTArray > sorted; sorted = aIntervals; sorted.Sort(Compare()); @@ -81,9 +81,9 @@ struct Interval aNormalized->AppendElement(current); } - static void Intersection(const nsTArray>& a0, - const nsTArray>& a1, - nsTArray>* aIntersection) + static void Intersection(const nsTArray >& a0, + const nsTArray >& a1, + nsTArray >* aIntersection) { MOZ_ASSERT(IsNormalized(a0)); MOZ_ASSERT(IsNormalized(a1)); @@ -106,7 +106,7 @@ struct Interval } } - static bool IsNormalized(const nsTArray>& aIntervals) + static bool IsNormalized(const nsTArray >& aIntervals) { for (size_t i = 1; i < aIntervals.Length(); i++) { if (aIntervals[i - 1].end >= aIntervals[i].start) { diff --git a/media/libstagefright/binding/include/mp4_demuxer/mp4_demuxer.h b/media/libstagefright/binding/include/mp4_demuxer/mp4_demuxer.h index 0105b9c97b32..72fa4c6690c8 100644 --- a/media/libstagefright/binding/include/mp4_demuxer/mp4_demuxer.h +++ b/media/libstagefright/binding/include/mp4_demuxer/mp4_demuxer.h @@ -59,13 +59,9 @@ public: const AudioDecoderConfig& AudioConfig() { return mAudioConfig; } const VideoDecoderConfig& VideoConfig() { return mVideoConfig; } - void UpdateIndex(const nsTArray& aByteRanges); - void ConvertByteRangesToTime( const nsTArray& aByteRanges, - nsTArray>* aIntervals); - - int64_t GetEvictionOffset(Microseconds aTime); + nsTArray >* aIntervals); private: AudioDecoderConfig mAudioConfig; diff --git a/media/libstagefright/binding/mp4_demuxer.cpp b/media/libstagefright/binding/mp4_demuxer.cpp index 105ede19b356..5daf7dd75bf9 100644 --- a/media/libstagefright/binding/mp4_demuxer.cpp +++ b/media/libstagefright/binding/mp4_demuxer.cpp @@ -12,7 +12,6 @@ #include #include -#include using namespace stagefright; @@ -195,14 +194,6 @@ MP4Demuxer::DemuxVideoSample() return sample.forget(); } -void -MP4Demuxer::UpdateIndex(const nsTArray& aByteRanges) -{ - for (int i = 0; i < mPrivate->mIndexes.Length(); i++) { - mPrivate->mIndexes[i]->UpdateMoofIndex(aByteRanges); - } -} - void MP4Demuxer::ConvertByteRangesToTime( const nsTArray& aByteRanges, @@ -224,18 +215,4 @@ MP4Demuxer::ConvertByteRangesToTime( } } -int64_t -MP4Demuxer::GetEvictionOffset(Microseconds aTime) -{ - if (mPrivate->mIndexes.IsEmpty()) { - return 0; - } - - uint64_t offset = std::numeric_limits::max(); - for (int i = 0; i < mPrivate->mIndexes.Length(); i++) { - offset = std::min(offset, mPrivate->mIndexes[i]->GetEvictionOffset(aTime)); - } - return offset; -} - } // namespace mp4_demuxer