Bug 1367128: P2. Add methods to trim index. r=gerald

The MoofParser's used by the MP4Demuxer, can grow very large as it keeps adding new tables and is never reset.

Once we have demuxed all data present in the MP4 media segment, we no longer require the samples table for that media segment and we can drop it from the index.

Unfortunately. some websites (in particular some using live video) use media segments containing a single sample in order to (incorrectly) reduce latency. While this is a very bad approach from a performance perspective it does happen in the wild.

MozReview-Commit-ID: I66jxcScmKM

--HG--
extra : rebase_source : d0029b74df94b92dc0a115c77f6e560b30e5ed5c
This commit is contained in:
Jean-Yves Avenard 2017-06-02 21:15:10 +02:00
parent 1e3d2193d7
commit fe9bd75acb
4 changed files with 75 additions and 5 deletions

View File

@ -83,6 +83,12 @@ SampleIterator::SampleIterator(Index* aIndex)
, mCurrentMoof(0)
, mCurrentSample(0)
{
mIndex->RegisterIterator(this);
}
SampleIterator::~SampleIterator()
{
mIndex->UnregisterIterator(this);
}
already_AddRefed<MediaRawData> SampleIterator::GetNext()
@ -386,12 +392,37 @@ Index::~Index() {}
void
Index::UpdateMoofIndex(const MediaByteRangeSet& aByteRanges)
{
UpdateMoofIndex(aByteRanges, false);
}
void
Index::UpdateMoofIndex(const MediaByteRangeSet& aByteRanges, bool aCanEvict)
{
if (!mMoofParser) {
return;
}
mMoofParser->RebuildFragmentedIndex(aByteRanges);
size_t moofs = mMoofParser->Moofs().Length();
bool canEvict = aCanEvict && moofs > 1;
if (canEvict) {
// Check that we can trim the mMoofParser. We can only do so if all
// iterators have demuxed all possible samples.
for (const SampleIterator* iterator : mIterators) {
if ((iterator->mCurrentSample == 0 && iterator->mCurrentMoof == moofs) ||
iterator->mCurrentMoof == moofs - 1) {
continue;
}
canEvict = false;
break;
}
}
mMoofParser->RebuildFragmentedIndex(aByteRanges, &canEvict);
if (canEvict) {
// The moofparser got trimmed. Adjust all registered iterators.
for (SampleIterator* iterator : mIterators) {
iterator->mCurrentMoof -= moofs - 1;
}
}
}
Microseconds
@ -559,4 +590,17 @@ Index::GetEvictionOffset(Microseconds aTime)
}
return offset;
}
void
Index::RegisterIterator(SampleIterator* aIterator)
{
mIterators.AppendElement(aIterator);
}
void
Index::UnregisterIterator(SampleIterator* aIterator)
{
mIterators.RemoveElement(aIterator);
}
}

View File

@ -31,13 +31,28 @@ using namespace mozilla;
const uint32_t kKeyIdSize = 16;
bool
MoofParser::RebuildFragmentedIndex(
const MediaByteRangeSet& aByteRanges)
MoofParser::RebuildFragmentedIndex(const MediaByteRangeSet& aByteRanges)
{
BoxContext context(mSource, aByteRanges);
return RebuildFragmentedIndex(context);
}
bool
MoofParser::RebuildFragmentedIndex(
const MediaByteRangeSet& aByteRanges, bool* aCanEvict)
{
MOZ_ASSERT(aCanEvict);
if (*aCanEvict && mMoofs.Length() > 1) {
MOZ_ASSERT(mMoofs.Length() == mMediaRanges.Length());
mMoofs.RemoveElementsAt(0, mMoofs.Length() - 1);
mMediaRanges.RemoveElementsAt(0, mMediaRanges.Length() - 1);
*aCanEvict = true;
} else {
*aCanEvict = false;
}
return RebuildFragmentedIndex(aByteRanges);
}
bool
MoofParser::RebuildFragmentedIndex(BoxContext& aContext)
{

View File

@ -27,10 +27,10 @@ class SampleIterator
{
public:
explicit SampleIterator(Index* aIndex);
~SampleIterator();
already_AddRefed<mozilla::MediaRawData> GetNext();
void Seek(Microseconds aTime);
Microseconds GetNextKeyframeTime();
private:
Sample* Get();
@ -38,6 +38,7 @@ private:
void Next();
RefPtr<Index> mIndex;
friend class Index;
size_t mCurrentMoof;
size_t mCurrentSample;
};
@ -98,6 +99,8 @@ public:
uint32_t aTrackId,
bool aIsAudio);
void UpdateMoofIndex(const mozilla::MediaByteRangeSet& aByteRanges,
bool aCanEvict);
void UpdateMoofIndex(const mozilla::MediaByteRangeSet& aByteRanges);
Microseconds GetEndCompositionIfBuffered(
const mozilla::MediaByteRangeSet& aByteRanges);
@ -110,11 +113,14 @@ public:
private:
~Index();
void RegisterIterator(SampleIterator* aIterator);
void UnregisterIterator(SampleIterator* aIterator);
Stream* mSource;
FallibleTArray<Sample> mIndex;
FallibleTArray<MP4DataOffset> mDataOffset;
nsAutoPtr<MoofParser> mMoofParser;
nsTArray<SampleIterator*> mIterators;
// ConvertByteRangesToTimeRanges cache
mozilla::MediaByteRangeSet mLastCachedRanges;

View File

@ -262,6 +262,11 @@ public:
}
bool RebuildFragmentedIndex(
const mozilla::MediaByteRangeSet& aByteRanges);
// If *aCanEvict is set to true. then will remove all moofs already parsed
// from index then rebuild the index. *aCanEvict is set to true upon return if
// some moofs were removed.
bool RebuildFragmentedIndex(
const mozilla::MediaByteRangeSet& aByteRanges, bool* aCanEvict);
bool RebuildFragmentedIndex(BoxContext& aContext);
Interval<Microseconds> GetCompositionRange(
const mozilla::MediaByteRangeSet& aByteRanges);