diff --git a/dom/media/fmp4/MP4Demuxer.cpp b/dom/media/fmp4/MP4Demuxer.cpp index 2034a58f38c1..75ad66b15893 100644 --- a/dom/media/fmp4/MP4Demuxer.cpp +++ b/dom/media/fmp4/MP4Demuxer.cpp @@ -37,7 +37,7 @@ class MP4TrackDemuxer : public MediaTrackDemuxer public: MP4TrackDemuxer(MP4Demuxer* aParent, UniquePtr&& aInfo, - const nsTArray& indices); + const mp4_demuxer::IndiceWrapper& aIndices); UniquePtr GetInfo() const override; @@ -152,9 +152,10 @@ MP4Demuxer::Init() UniquePtr info = metadata.GetTrackInfo(TrackInfo::kAudioTrack, i); if (info) { - FallibleTArray indices; - if (metadata.ReadTrackIndex(indices, info->mTrackId)) { - mAudioDemuxers[i] = new MP4TrackDemuxer(this, Move(info), indices); + UniquePtr indices = + metadata.GetTrackIndice(info->mTrackId); + if (indices) { + mAudioDemuxers[i] = new MP4TrackDemuxer(this, Move(info), *indices.get()); } } } @@ -166,9 +167,10 @@ MP4Demuxer::Init() UniquePtr info = metadata.GetTrackInfo(TrackInfo::kVideoTrack, i); if (info) { - FallibleTArray indices; - if (metadata.ReadTrackIndex(indices, info->mTrackId)) { - mVideoDemuxers[i] = new MP4TrackDemuxer(this, Move(info), indices); + UniquePtr indices = + metadata.GetTrackIndice(info->mTrackId); + if (indices) { + mVideoDemuxers[i] = new MP4TrackDemuxer(this, Move(info), *indices.get()); } } } @@ -263,11 +265,11 @@ MP4Demuxer::GetCrypto() MP4TrackDemuxer::MP4TrackDemuxer(MP4Demuxer* aParent, UniquePtr&& aInfo, - const nsTArray& 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())) diff --git a/media/libstagefright/binding/Index.cpp b/media/libstagefright/binding/Index.cpp index 2d39f351bcdf..f533b8818121 100644 --- a/media/libstagefright/binding/Index.cpp +++ b/media/libstagefright/binding/Index.cpp @@ -5,6 +5,7 @@ #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" @@ -297,17 +298,17 @@ SampleIterator::GetNextKeyframeTime() return -1; } -Index::Index(const nsTArray& 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; } @@ -316,8 +317,12 @@ Index::Index(const nsTArray& aIndex, 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; } @@ -364,8 +369,12 @@ Index::Index(const nsTArray& aIndex, } 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(intervalTime.GetStart(), intervalTime.GetEnd()); } else { mDataOffset.Clear(); diff --git a/media/libstagefright/binding/MP4Metadata.cpp b/media/libstagefright/binding/MP4Metadata.cpp index 50abbd6a31f5..a2157128ca6a 100644 --- a/media/libstagefright/binding/MP4Metadata.cpp +++ b/media/libstagefright/binding/MP4Metadata.cpp @@ -146,6 +146,87 @@ private: mozilla::UniquePtr mRustParser; }; +class IndiceWrapperStagefright : public IndiceWrapper { +public: + size_t Length() const override; + + bool GetIndice(size_t aIndex, Index::Indice& aIndice) const override; + + explicit IndiceWrapperStagefright(FallibleTArray& aIndice); + +protected: + FallibleTArray mIndice; +}; + +IndiceWrapperStagefright::IndiceWrapperStagefright(FallibleTArray& 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 mIndice; +}; + +IndiceWrapperRust::IndiceWrapperRust(mp4parse_byte_data& aRustIndice) + : mIndice(mozilla::MakeUnique()) +{ + 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(aSource)) , mRust(MakeUnique(aSource)) @@ -334,29 +415,42 @@ MP4Metadata::Crypto() const return crypto; } -bool -MP4Metadata::ReadTrackIndex(FallibleTArray& aDest, mozilla::TrackID aTrackID) +mozilla::UniquePtr +MP4Metadata::GetTrackIndice(mozilla::TrackID aTrackID) { - bool ret = mStagefright->ReadTrackIndex(aDest, aTrackID); + FallibleTArray 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 indice; + if (mPreferRust) { + indice = mozilla::MakeUnique(indiceRust); + } else { + indice = mozilla::MakeUnique(indiceSF); + } + + return indice; } static inline bool diff --git a/media/libstagefright/binding/include/mp4_demuxer/Index.h b/media/libstagefright/binding/include/mp4_demuxer/Index.h index 768dedc5bbe6..8a18acdaaed1 100644 --- a/media/libstagefright/binding/include/mp4_demuxer/Index.h +++ b/media/libstagefright/binding/include/mp4_demuxer/Index.h @@ -19,6 +19,7 @@ namespace mp4_demuxer { class Index; +class IndiceWrapper; typedef int64_t Microseconds; @@ -92,7 +93,7 @@ public: Interval mTime; }; - Index(const nsTArray& aIndex, + Index(const IndiceWrapper& aIndices, Stream* aSource, uint32_t aTrackId, bool aIsAudio); diff --git a/media/libstagefright/binding/include/mp4_demuxer/MP4Metadata.h b/media/libstagefright/binding/include/mp4_demuxer/MP4Metadata.h index 492c9c1c1bc3..687ba02e9eaa 100644 --- a/media/libstagefright/binding/include/mp4_demuxer/MP4Metadata.h +++ b/media/libstagefright/binding/include/mp4_demuxer/MP4Metadata.h @@ -11,6 +11,7 @@ #include "MediaData.h" #include "MediaInfo.h" #include "Stream.h" +#include "mp4parse.h" namespace mp4_demuxer { @@ -18,6 +19,17 @@ 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: @@ -32,7 +44,7 @@ public: const CryptoFile& Crypto() const; - bool ReadTrackIndex(FallibleTArray& aDest, mozilla::TrackID aTrackID); + mozilla::UniquePtr GetTrackIndice(mozilla::TrackID aTrackID); private: UniquePtr mStagefright; diff --git a/media/libstagefright/gtest/TestParser.cpp b/media/libstagefright/gtest/TestParser.cpp index bc46c2a3ce00..f88a3d6cc661 100644 --- a/media/libstagefright/gtest/TestParser.cpp +++ b/media/libstagefright/gtest/TestParser.cpp @@ -236,11 +236,14 @@ TEST(stagefright_MPEG4Metadata, test_case_mp4) EXPECT_EQ(testFiles[test].mVideoDuration, videoInfo->mDuration); EXPECT_EQ(testFiles[test].mWidth, videoInfo->mDisplay.width); EXPECT_EQ(testFiles[test].mHeight, videoInfo->mDisplay.height); - FallibleTArray 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 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); @@ -254,11 +257,14 @@ TEST(stagefright_MPEG4Metadata, test_case_mp4) EXPECT_TRUE(audioInfo->IsAudio()); EXPECT_EQ(testFiles[test].mAudioDuration, audioInfo->mDuration); EXPECT_EQ(testFiles[test].mAudioProfile, audioInfo->mProfile); - FallibleTArray 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 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));