author | Alfredo.Yang <ayang@mozilla.com> |
Wed, 01 Mar 2017 10:53:49 +0800 | |
changeset 347469 | b1c8b28b9fa2a8424db940d4b657eb59b3f01ff3 |
parent 347468 | 95c1e899eab6eadae8abc9981dd4dbf4e0ad516d |
child 347470 | 2fcd6a97a1b82a8bdf46113f3e0b9a9e5fc0cf3c |
push id | 31496 |
push user | cbook@mozilla.com |
push date | Tue, 14 Mar 2017 13:21:57 +0000 |
treeherder | mozilla-central@9a26ed658fdc [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | gerald |
bugs | 1343461 |
milestone | 55.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/media/fmp4/MP4Demuxer.cpp +++ b/dom/media/fmp4/MP4Demuxer.cpp @@ -32,17 +32,17 @@ mozilla::LogModule* GetDemuxerLog() namespace mozilla { class MP4TrackDemuxer : public MediaTrackDemuxer { public: MP4TrackDemuxer(MP4Demuxer* aParent, UniquePtr<TrackInfo>&& aInfo, - const nsTArray<mp4_demuxer::Index::Indice>& indices); + const mp4_demuxer::IndiceWrapper& aIndices); UniquePtr<TrackInfo> GetInfo() const override; RefPtr<SeekPromise> Seek(const media::TimeUnit& aTime) override; RefPtr<SamplesPromise> GetSamples(int32_t aNumSamples = 1) override; void Reset() override; @@ -147,33 +147,35 @@ MP4Demuxer::Init() } if (audioTrackCount != 0) { mAudioDemuxers.SetLength(audioTrackCount); for (size_t i = 0; i < audioTrackCount; i++) { UniquePtr<TrackInfo> info = metadata.GetTrackInfo(TrackInfo::kAudioTrack, i); if (info) { - FallibleTArray<mp4_demuxer::Index::Indice> indices; - if (metadata.ReadTrackIndex(indices, info->mTrackId)) { - mAudioDemuxers[i] = new MP4TrackDemuxer(this, Move(info), indices); + UniquePtr<mp4_demuxer::IndiceWrapper> indices = + metadata.GetTrackIndice(info->mTrackId); + if (indices) { + mAudioDemuxers[i] = new MP4TrackDemuxer(this, Move(info), *indices.get()); } } } } if (videoTrackCount != 0) { mVideoDemuxers.SetLength(videoTrackCount); for (size_t i = 0; i < videoTrackCount; i++) { UniquePtr<TrackInfo> info = metadata.GetTrackInfo(TrackInfo::kVideoTrack, i); if (info) { - FallibleTArray<mp4_demuxer::Index::Indice> indices; - if (metadata.ReadTrackIndex(indices, info->mTrackId)) { - mVideoDemuxers[i] = new MP4TrackDemuxer(this, Move(info), indices); + UniquePtr<mp4_demuxer::IndiceWrapper> indices = + metadata.GetTrackIndice(info->mTrackId); + if (indices) { + mVideoDemuxers[i] = new MP4TrackDemuxer(this, Move(info), *indices.get()); } } } } const mp4_demuxer::CryptoFile& cryptoFile = metadata.Crypto(); if (cryptoFile.valid) { const nsTArray<mp4_demuxer::PsshInfo>& psshs = cryptoFile.pssh; @@ -258,21 +260,21 @@ MP4Demuxer::GetCrypto() crypto.reset(new EncryptionInfo{}); crypto->AddInitData(NS_LITERAL_STRING("cenc"), mCryptoInitData); } return crypto; } MP4TrackDemuxer::MP4TrackDemuxer(MP4Demuxer* aParent, UniquePtr<TrackInfo>&& aInfo, - const nsTArray<mp4_demuxer::Index::Indice>& indices) + const mp4_demuxer::IndiceWrapper& aIndices) : mParent(aParent) , mStream(new mp4_demuxer::ResourceStream(mParent->mResource)) , mInfo(Move(aInfo)) - , mIndex(new mp4_demuxer::Index(indices, + , mIndex(new mp4_demuxer::Index(aIndices, mStream, mInfo->mTrackId, mInfo->IsAudio())) , mIterator(MakeUnique<mp4_demuxer::SampleIterator>(mIndex)) , mNeedReIndex(true) { EnsureUpToDateIndex(); // Force update of index
--- a/media/libstagefright/binding/Index.cpp +++ b/media/libstagefright/binding/Index.cpp @@ -1,15 +1,16 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mp4_demuxer/ByteReader.h" #include "mp4_demuxer/Index.h" #include "mp4_demuxer/Interval.h" +#include "mp4_demuxer/MP4Metadata.h" #include "mp4_demuxer/SinfParser.h" #include "nsAutoPtr.h" #include "mozilla/RefPtr.h" #include <algorithm> #include <limits> using namespace stagefright; @@ -292,37 +293,41 @@ SampleIterator::GetNextKeyframeTime() if (sample->mSync) { return sample->mCompositionRange.start; } itr.Next(); } return -1; } -Index::Index(const nsTArray<Indice>& aIndex, +Index::Index(const IndiceWrapper& aIndices, Stream* aSource, uint32_t aTrackId, bool aIsAudio) : mSource(aSource) , mIsAudio(aIsAudio) { - if (aIndex.IsEmpty()) { + if (!aIndices.Length()) { mMoofParser = new MoofParser(aSource, aTrackId, aIsAudio); } else { - if (!mIndex.SetCapacity(aIndex.Length(), fallible)) { + if (!mIndex.SetCapacity(aIndices.Length(), fallible)) { // OOM. return; } media::IntervalSet<int64_t> intervalTime; MediaByteRange intervalRange; bool haveSync = false; bool progressive = true; int64_t lastOffset = 0; - for (size_t i = 0; i < aIndex.Length(); i++) { - const Indice& indice = aIndex[i]; + for (size_t i = 0; i < aIndices.Length(); i++) { + Indice indice; + if (!aIndices.GetIndice(i, indice)) { + // Out of index? + return; + } if (indice.sync || mIsAudio) { haveSync = true; } if (!haveSync) { continue; } Sample sample; @@ -359,18 +364,22 @@ Index::Index(const nsTArray<Indice>& aIn intervalRange = MediaByteRange(); } intervalTime += media::Interval<int64_t>(sample.mCompositionRange.start, sample.mCompositionRange.end); intervalRange = intervalRange.Span(sample.mByteRange); } if (mDataOffset.Length() && progressive) { + Indice indice; + if (!aIndices.GetIndice(aIndices.Length() - 1, indice)) { + return; + } auto& last = mDataOffset.LastElement(); - last.mEndOffset = aIndex.LastElement().end_offset; + last.mEndOffset = indice.end_offset; last.mTime = Interval<int64_t>(intervalTime.GetStart(), intervalTime.GetEnd()); } else { mDataOffset.Clear(); } } } Index::~Index() {}
--- a/media/libstagefright/binding/MP4Metadata.cpp +++ b/media/libstagefright/binding/MP4Metadata.cpp @@ -141,16 +141,97 @@ private: Maybe<uint32_t> TrackTypeToGlobalTrackIndex(mozilla::TrackInfo::TrackType aType, size_t aTrackNumber) const; CryptoFile mCrypto; RefPtr<Stream> mSource; RustStreamAdaptor mRustSource; mozilla::UniquePtr<mp4parse_parser, FreeMP4Parser> mRustParser; }; +class IndiceWrapperStagefright : public IndiceWrapper { +public: + size_t Length() const override; + + bool GetIndice(size_t aIndex, Index::Indice& aIndice) const override; + + explicit IndiceWrapperStagefright(FallibleTArray<Index::Indice>& aIndice); + +protected: + FallibleTArray<Index::Indice> mIndice; +}; + +IndiceWrapperStagefright::IndiceWrapperStagefright(FallibleTArray<Index::Indice>& aIndice) +{ + mIndice.SwapElements(aIndice); +} + +size_t +IndiceWrapperStagefright::Length() const +{ + return mIndice.Length(); +} + +bool +IndiceWrapperStagefright::GetIndice(size_t aIndex, Index::Indice& aIndice) const +{ + if (aIndex >= mIndice.Length()) { + MOZ_LOG(sLog, LogLevel::Error, ("Index overflow in indice")); + return false; + } + + aIndice = mIndice[aIndex]; + return true; +} + +// the owner of mIndice is rust mp4 paser, so lifetime of this class +// SHOULD NOT longer than rust parser. +class IndiceWrapperRust : public IndiceWrapper +{ +public: + size_t Length() const override; + + bool GetIndice(size_t aIndex, Index::Indice& aIndice) const override; + + explicit IndiceWrapperRust(mp4parse_byte_data& aRustIndice); + +protected: + UniquePtr<mp4parse_byte_data> mIndice; +}; + +IndiceWrapperRust::IndiceWrapperRust(mp4parse_byte_data& aRustIndice) + : mIndice(mozilla::MakeUnique<mp4parse_byte_data>()) +{ + mIndice->length = aRustIndice.length; + mIndice->indices = aRustIndice.indices; +} + +size_t +IndiceWrapperRust::Length() const +{ + return mIndice->length; +} + +bool +IndiceWrapperRust::GetIndice(size_t aIndex, Index::Indice& aIndice) const +{ + if (aIndex >= mIndice->length) { + MOZ_LOG(sLog, LogLevel::Error, ("Index overflow in indice")); + return false; + } + + const mp4parse_indice* indice = &mIndice->indices[aIndex]; + aIndice.start_offset = indice->start_offset; + aIndice.end_offset = indice->end_offset; + aIndice.start_composition = indice->start_composition; + aIndice.end_composition = indice->end_composition; + aIndice.start_decode = indice->start_decode; + aIndice.sync = indice->sync; + return true; +} + MP4Metadata::MP4Metadata(Stream* aSource) : mStagefright(MakeUnique<MP4MetadataStagefright>(aSource)) , mRust(MakeUnique<MP4MetadataRust>(aSource)) , mPreferRust(false) , mReportedAudioTrackTelemetry(false) , mReportedVideoTrackTelemetry(false) #ifndef RELEASE_OR_BETA , mRustTestMode(MediaPrefs::RustTestMode()) @@ -329,39 +410,52 @@ MP4Metadata::Crypto() const if (mPreferRust) { return rustCrypto; } return crypto; } -bool -MP4Metadata::ReadTrackIndex(FallibleTArray<Index::Indice>& aDest, mozilla::TrackID aTrackID) +mozilla::UniquePtr<IndiceWrapper> +MP4Metadata::GetTrackIndice(mozilla::TrackID aTrackID) { - bool ret = mStagefright->ReadTrackIndex(aDest, aTrackID); + FallibleTArray<Index::Indice> indiceSF; + if(!mStagefright->ReadTrackIndex(indiceSF, aTrackID)) { + return nullptr; + } + + mp4parse_byte_data indiceRust = {}; + if ((mPreferRust || mRustTestMode) && + !mRust->ReadTrackIndice(&indiceRust, aTrackID)) { + return nullptr; + } #ifndef RELEASE_OR_BETA - if (mRustTestMode && ret && mRust) { - mp4parse_byte_data data = {}; - bool rustRet = mRust->ReadTrackIndice(&data, aTrackID); - MOZ_DIAGNOSTIC_ASSERT(rustRet); - MOZ_DIAGNOSTIC_ASSERT(data.length == aDest.Length()); - for (uint32_t i = 0; i < data.length; i++) { - MOZ_DIAGNOSTIC_ASSERT(data.indices[i].start_offset == aDest[i].start_offset); - MOZ_DIAGNOSTIC_ASSERT(data.indices[i].end_offset == aDest[i].end_offset); - MOZ_DIAGNOSTIC_ASSERT(llabs(data.indices[i].start_composition - int64_t(aDest[i].start_composition)) <= 1); - MOZ_DIAGNOSTIC_ASSERT(llabs(data.indices[i].end_composition - int64_t(aDest[i].end_composition)) <= 1); - MOZ_DIAGNOSTIC_ASSERT(llabs(data.indices[i].start_decode - int64_t(aDest[i].start_decode)) <= 1); - MOZ_DIAGNOSTIC_ASSERT(data.indices[i].sync == aDest[i].sync); + if (mRustTestMode) { + MOZ_DIAGNOSTIC_ASSERT(indiceRust.length == indiceSF.Length()); + for (uint32_t i = 0; i < indiceRust.length; i++) { + MOZ_DIAGNOSTIC_ASSERT(indiceRust.indices[i].start_offset == indiceSF[i].start_offset); + MOZ_DIAGNOSTIC_ASSERT(indiceRust.indices[i].end_offset == indiceSF[i].end_offset); + MOZ_DIAGNOSTIC_ASSERT(llabs(indiceRust.indices[i].start_composition - int64_t(indiceSF[i].start_composition)) <= 1); + MOZ_DIAGNOSTIC_ASSERT(llabs(indiceRust.indices[i].end_composition - int64_t(indiceSF[i].end_composition)) <= 1); + MOZ_DIAGNOSTIC_ASSERT(llabs(indiceRust.indices[i].start_decode - int64_t(indiceSF[i].start_decode)) <= 1); + MOZ_DIAGNOSTIC_ASSERT(indiceRust.indices[i].sync == indiceSF[i].sync); } } #endif - return ret; + UniquePtr<IndiceWrapper> indice; + if (mPreferRust) { + indice = mozilla::MakeUnique<IndiceWrapperRust>(indiceRust); + } else { + indice = mozilla::MakeUnique<IndiceWrapperStagefright>(indiceSF); + } + + return indice; } static inline bool ConvertIndex(FallibleTArray<Index::Indice>& aDest, const nsTArray<stagefright::MediaSource::Indice>& aIndex, int64_t aMediaTime) { if (!aDest.SetCapacity(aIndex.Length(), mozilla::fallible)) {
--- a/media/libstagefright/binding/include/mp4_demuxer/Index.h +++ b/media/libstagefright/binding/include/mp4_demuxer/Index.h @@ -14,16 +14,17 @@ #include "nsISupportsImpl.h" template<class T> class nsAutoPtr; namespace mp4_demuxer { class Index; +class IndiceWrapper; typedef int64_t Microseconds; class SampleIterator { public: explicit SampleIterator(Index* aIndex); already_AddRefed<mozilla::MediaRawData> GetNext(); @@ -87,17 +88,17 @@ public: }; uint32_t mIndex; int64_t mStartOffset; int64_t mEndOffset; Interval<Microseconds> mTime; }; - Index(const nsTArray<Indice>& aIndex, + Index(const IndiceWrapper& aIndices, Stream* aSource, uint32_t aTrackId, bool aIsAudio); void UpdateMoofIndex(const mozilla::MediaByteRangeSet& aByteRanges); Microseconds GetEndCompositionIfBuffered( const mozilla::MediaByteRangeSet& aByteRanges); mozilla::media::TimeIntervals ConvertByteRangesToTimeRanges(
--- a/media/libstagefright/binding/include/mp4_demuxer/MP4Metadata.h +++ b/media/libstagefright/binding/include/mp4_demuxer/MP4Metadata.h @@ -6,38 +6,50 @@ #define MP4METADATA_H_ #include "mozilla/UniquePtr.h" #include "mp4_demuxer/DecoderData.h" #include "mp4_demuxer/Index.h" #include "MediaData.h" #include "MediaInfo.h" #include "Stream.h" +#include "mp4parse.h" namespace mp4_demuxer { class MP4MetadataStagefright; class MP4MetadataRust; +class IndiceWrapper { +public: + virtual size_t Length() const = 0; + + // TODO: Index::Indice is from stagefright, we should use another struct once + // stagefrigth is removed. + virtual bool GetIndice(size_t aIndex, Index::Indice& aIndice) const = 0; + + virtual ~IndiceWrapper() {} +}; + class MP4Metadata { public: explicit MP4Metadata(Stream* aSource); ~MP4Metadata(); static already_AddRefed<mozilla::MediaByteBuffer> Metadata(Stream* aSource); uint32_t GetNumberTracks(mozilla::TrackInfo::TrackType aType) const; mozilla::UniquePtr<mozilla::TrackInfo> GetTrackInfo(mozilla::TrackInfo::TrackType aType, size_t aTrackNumber) const; bool CanSeek() const; const CryptoFile& Crypto() const; - bool ReadTrackIndex(FallibleTArray<Index::Indice>& aDest, mozilla::TrackID aTrackID); + mozilla::UniquePtr<IndiceWrapper> GetTrackIndice(mozilla::TrackID aTrackID); private: UniquePtr<MP4MetadataStagefright> mStagefright; UniquePtr<MP4MetadataRust> mRust; mutable bool mPreferRust; mutable bool mReportedAudioTrackTelemetry; mutable bool mReportedVideoTrackTelemetry; #ifndef RELEASE_OR_BETA
--- a/media/libstagefright/gtest/TestParser.cpp +++ b/media/libstagefright/gtest/TestParser.cpp @@ -231,39 +231,45 @@ TEST(stagefright_MPEG4Metadata, test_cas ASSERT_TRUE(!!trackInfo); const VideoInfo* videoInfo = trackInfo->GetAsVideoInfo(); ASSERT_TRUE(!!videoInfo); EXPECT_TRUE(videoInfo->IsValid()); EXPECT_TRUE(videoInfo->IsVideo()); EXPECT_EQ(testFiles[test].mVideoDuration, videoInfo->mDuration); EXPECT_EQ(testFiles[test].mWidth, videoInfo->mDisplay.width); EXPECT_EQ(testFiles[test].mHeight, videoInfo->mDisplay.height); - FallibleTArray<mp4_demuxer::Index::Indice> indices; - EXPECT_TRUE(metadata.ReadTrackIndex(indices, videoInfo->mTrackId)); - for (const mp4_demuxer::Index::Indice& indice : indices) { - EXPECT_TRUE(indice.start_offset <= indice.end_offset); - EXPECT_TRUE(indice.start_composition <= indice.end_composition); + + UniquePtr<IndiceWrapper> indices = metadata.GetTrackIndice(videoInfo->mTrackId); + EXPECT_TRUE(!!indices); + for (size_t i = 0; i < indices->Length(); i++) { + Index::Indice data; + EXPECT_TRUE(indices->GetIndice(i, data)); + EXPECT_TRUE(data.start_offset <= data.end_offset); + EXPECT_TRUE(data.start_composition <= data.end_composition); } } trackInfo = metadata.GetTrackInfo(TrackInfo::kAudioTrack, 0); if (testFiles[test].mNumberAudioTracks == 0) { EXPECT_TRUE(!trackInfo); } else { ASSERT_TRUE(!!trackInfo); const AudioInfo* audioInfo = trackInfo->GetAsAudioInfo(); ASSERT_TRUE(!!audioInfo); EXPECT_TRUE(audioInfo->IsValid()); EXPECT_TRUE(audioInfo->IsAudio()); EXPECT_EQ(testFiles[test].mAudioDuration, audioInfo->mDuration); EXPECT_EQ(testFiles[test].mAudioProfile, audioInfo->mProfile); - FallibleTArray<mp4_demuxer::Index::Indice> indices; - EXPECT_TRUE(metadata.ReadTrackIndex(indices, audioInfo->mTrackId)); - for (const mp4_demuxer::Index::Indice& indice : indices) { - EXPECT_TRUE(indice.start_offset <= indice.end_offset); - EXPECT_TRUE(indice.start_composition <= indice.end_composition); + + UniquePtr<IndiceWrapper> indices = metadata.GetTrackIndice(audioInfo->mTrackId); + EXPECT_TRUE(!!indices); + for (size_t i = 0; i < indices->Length(); i++) { + Index::Indice data; + EXPECT_TRUE(indices->GetIndice(i, data)); + EXPECT_TRUE(data.start_offset <= data.end_offset); + EXPECT_TRUE(data.start_composition <= data.end_composition); } } EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kTextTrack, 0)); EXPECT_FALSE(metadata.GetTrackInfo(static_cast<TrackInfo::TrackType>(-1), 0)); // We can see anywhere in any MPEG4. EXPECT_TRUE(metadata.CanSeek()); EXPECT_EQ(testFiles[test].mHasCrypto, metadata.Crypto().valid); }