Bug 1057203 - Remove MoofParser dependency on stagefright; r=edwin

This commit is contained in:
Anthony Jones 2014-08-26 16:53:48 +12:00
Родитель ee0e0c98ea
Коммит b5c59c078b
9 изменённых файлов: 149 добавлений и 44 удалений

Просмотреть файл

@ -154,6 +154,9 @@ public:
MediaByteRange Extents(const MediaByteRange& aByteRange) const
{
if (IsNull()) {
return aByteRange;
}
return MediaByteRange(std::min(mStart, aByteRange.mStart),
std::max(mEnd, aByteRange.mEnd));
}

Просмотреть файл

@ -0,0 +1,35 @@
/* 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/BufferStream.h"
#include <algorithm>
namespace mp4_demuxer {
BufferStream::BufferStream(const uint8_t* aData, size_t aLength)
: mData(aData), mLength(aLength)
{
}
/*virtual*/ bool
BufferStream::ReadAt(int64_t aOffset, void* aData, size_t aLength,
size_t* aBytesRead)
{
if (aOffset > mLength) {
return false;
}
*aBytesRead = std::min(aLength, mLength - (size_t) aOffset);
memcpy(aData, mData + aOffset, *aBytesRead);
return true;
}
/*virtual*/ bool
BufferStream::Length(int64_t* aLength)
{
*aLength = mLength;
return true;
}
}

Просмотреть файл

@ -81,7 +81,16 @@ Index::Index(const stagefright::Vector<MediaSource::Indice>& aIndex,
if (aIndex.isEmpty()) {
mMoofParser = new MoofParser(aSource, aTrackId);
} else {
mIndex.AppendElements(&aIndex[0], aIndex.size());
for (size_t i = 0; i < aIndex.size(); i++) {
const MediaSource::Indice& indice = aIndex[i];
Sample sample;
sample.mByteRange = MediaByteRange(indice.start_offset,
indice.end_offset);
sample.mCompositionRange = Interval<Microseconds>(indice.start_composition,
indice.end_composition);
sample.mSync = indice.sync;
mIndex.AppendElement(sample);
}
}
}
@ -100,7 +109,7 @@ Index::UpdateMoofIndex(const nsTArray<MediaByteRange>& aByteRanges)
Microseconds
Index::GetEndCompositionIfBuffered(const nsTArray<MediaByteRange>& aByteRanges)
{
nsTArray<stagefright::MediaSource::Indice>* index;
nsTArray<Sample>* index;
if (mMoofParser) {
if (!mMoofParser->ReachedEnd() || mMoofParser->mMoofs.IsEmpty()) {
return 0;
@ -113,14 +122,12 @@ Index::GetEndCompositionIfBuffered(const nsTArray<MediaByteRange>& aByteRanges)
Microseconds lastComposition = 0;
RangeFinder rangeFinder(aByteRanges);
for (size_t i = index->Length(); i--;) {
const MediaSource::Indice& indice = (*index)[i];
if (!rangeFinder.Contains(
MediaByteRange(indice.start_offset, indice.end_offset))) {
const Sample& sample = (*index)[i];
if (!rangeFinder.Contains(sample.mByteRange)) {
return 0;
}
lastComposition =
std::max(lastComposition, (Microseconds)indice.end_composition);
if (indice.sync) {
lastComposition = std::max(lastComposition, sample.mCompositionRange.end);
if (sample.mSync) {
return lastComposition;
}
}
@ -135,7 +142,7 @@ Index::ConvertByteRangesToTimeRanges(
RangeFinder rangeFinder(aByteRanges);
nsTArray<Interval<Microseconds>> timeRanges;
nsTArray<nsTArray<stagefright::MediaSource::Indice>*> indexes;
nsTArray<nsTArray<Sample>*> indexes;
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
@ -158,25 +165,23 @@ Index::ConvertByteRangesToTimeRanges(
bool hasSync = false;
for (size_t i = 0; i < indexes.Length(); i++) {
nsTArray<stagefright::MediaSource::Indice>* index = indexes[i];
nsTArray<Sample>* 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))) {
const Sample& sample = (*index)[j];
if (!rangeFinder.Contains(sample.mByteRange)) {
// 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;
hasSync |= sample.mSync;
if (!hasSync) {
continue;
}
Interval<Microseconds>::SemiNormalAppend(
timeRanges, Interval<Microseconds>(indice.start_composition,
indice.end_composition));
Interval<Microseconds>::SemiNormalAppend(timeRanges,
sample.mCompositionRange);
}
}
@ -203,9 +208,9 @@ Index::GetEvictionOffset(Microseconds aTime)
// 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);
const Sample& sample = mIndex[i];
if (aTime >= sample.mCompositionRange.end) {
offset = std::min(offset, uint64_t(sample.mByteRange.mEnd));
}
}
}

Просмотреть файл

@ -27,6 +27,19 @@ MoofParser::RebuildFragmentedIndex(const nsTArray<MediaByteRange>& aByteRanges)
}
}
Interval<Microseconds>
MoofParser::GetCompositionRange()
{
Interval<Microseconds> compositionRange;
for (size_t i = 0; i < mMoofs.Length(); i++) {
nsTArray<Interval<Microseconds>>& compositionRanges = mMoofs[i].mTimeRanges;
for (int j = 0; j < compositionRanges.Length(); j++) {
compositionRange = compositionRange.Extents(compositionRanges[j]);
}
}
return compositionRange;
}
bool
MoofParser::ReachedEnd()
{
@ -54,7 +67,7 @@ MoofParser::ParseTrak(Box& aBox)
if (box.IsType("tkhd")) {
tkhd = Tkhd(box);
} else if (box.IsType("mdia")) {
if (tkhd.mTrackId == mTrex.mTrackId) {
if (!mTrex.mTrackId || tkhd.mTrackId == mTrex.mTrackId) {
ParseMdia(box, tkhd);
}
}
@ -77,7 +90,7 @@ MoofParser::ParseMvex(Box& aBox)
for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
if (box.IsType("trex")) {
Trex trex = Trex(box);
if (trex.mTrackId == mTrex.mTrackId) {
if (!mTrex.mTrackId || trex.mTrackId == mTrex.mTrackId) {
mTrex = trex;
}
}
@ -104,7 +117,7 @@ Moof::ParseTraf(Box& aBox, Trex& aTrex, Mdhd& aMdhd)
} else if (box.IsType("tfdt")) {
tfdt = Tfdt(box);
} else if (box.IsType("trun")) {
if (tfhd.mTrackId == aTrex.mTrackId) {
if (!aTrex.mTrackId || tfhd.mTrackId == aTrex.mTrackId) {
ParseTrun(box, tfhd, tfdt, aMdhd);
}
}
@ -143,30 +156,22 @@ Moof::ParseTrun(Box& aBox, Tfhd& aTfhd, Tfdt& aTfdt, Mdhd& aMdhd)
: aTfhd.mDefaultSampleFlags;
uint32_t ctsOffset = flags & 0x800 ? reader->ReadU32() : 0;
MediaSource::Indice indice;
indice.start_offset = offset;
Sample sample;
sample.mByteRange = MediaByteRange(offset, offset + sampleSize);
offset += sampleSize;
indice.end_offset = offset;
indice.start_composition =
((decodeTime + ctsOffset) * 1000000ll) / aMdhd.mTimescale;
sample.mCompositionRange = Interval<Microseconds>(
((decodeTime + ctsOffset) * 1000000ll) / aMdhd.mTimescale,
((decodeTime + sampleDuration + ctsOffset) * 1000000ll) / aMdhd.mTimescale);
decodeTime += sampleDuration;
indice.end_composition =
((decodeTime + ctsOffset) * 1000000ll) / aMdhd.mTimescale;
indice.sync = !(sampleFlags & 0x1010000);
sample.mSync = !(sampleFlags & 0x1010000);
mIndex.AppendElement(indice);
mIndex.AppendElement(sample);
MediaByteRange compositionRange(indice.start_offset, indice.end_offset);
if (mMdatRange.IsNull()) {
mMdatRange = compositionRange;
} else {
mMdatRange = mMdatRange.Extents(compositionRange);
}
Interval<Microseconds>::SemiNormalAppend(
timeRanges,
Interval<Microseconds>(indice.start_composition, indice.end_composition));
mMdatRange = mMdatRange.Extents(sample.mByteRange);
Interval<Microseconds>::SemiNormalAppend(timeRanges,
sample.mCompositionRange);
}
Interval<Microseconds>::Normalize(timeRanges, &mTimeRanges);
}

Просмотреть файл

@ -0,0 +1,30 @@
/* 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/. */
#ifndef BUFFER_STREAM_H_
#define BUFFER_STREAM_H_
#include "mp4_demuxer/mp4_demuxer.h"
namespace mp4_demuxer {
class BufferStream : public Stream
{
public:
/* BufferStream does not take ownership of aData nor does it make a copy.
* Therefore BufferStream shouldn't get used after aData is destroyed.
*/
BufferStream(const uint8_t* aData, size_t aLength);
virtual bool ReadAt(int64_t aOffset, void* aData, size_t aLength,
size_t* aBytesRead) MOZ_OVERRIDE;
virtual bool Length(int64_t* aLength) MOZ_OVERRIDE;
private:
const uint8_t* mData;
size_t mLength;
};
}
#endif

Просмотреть файл

@ -14,6 +14,7 @@ namespace mp4_demuxer
template <typename T> class Interval;
class MoofParser;
class Sample;
class Index
{
@ -31,7 +32,7 @@ public:
uint64_t GetEvictionOffset(Microseconds aTime);
private:
nsTArray<stagefright::MediaSource::Indice> mIndex;
nsTArray<Sample> mIndex;
nsAutoPtr<MoofParser> mMoofParser;
};
}

Просмотреть файл

@ -6,6 +6,7 @@
#define INTERVAL_H_
#include "nsTArray.h"
#include <algorithm>
namespace mp4_demuxer
{
@ -37,6 +38,18 @@ struct Interval
return start == aOther.start && end == aOther.end;
}
bool operator!=(const Interval& aOther) const { return !(*this == aOther); }
bool IsNull() const
{
return end == start;
}
Interval Extents(const Interval& aOther) const
{
if (IsNull()) {
return aOther;
}
return Interval(std::min(start, aOther.start),
std::max(end, aOther.end));
}
T start;
T end;

Просмотреть файл

@ -5,7 +5,6 @@
#ifndef MOOF_PARSER_H_
#define MOOF_PARSER_H_
#include "media/stagefright/MediaSource.h"
#include "mp4_demuxer/mp4_demuxer.h"
#include "MediaResource.h"
@ -92,6 +91,13 @@ public:
uint64_t mBaseMediaDecodeTime;
};
struct Sample
{
mozilla::MediaByteRange mByteRange;
Interval<Microseconds> mCompositionRange;
bool mSync;
};
class Moof
{
public:
@ -102,7 +108,7 @@ public:
mozilla::MediaByteRange mRange;
mozilla::MediaByteRange mMdatRange;
nsTArray<Interval<Microseconds>> mTimeRanges;
nsTArray<stagefright::MediaSource::Indice> mIndex;
nsTArray<Sample> mIndex;
};
class MoofParser
@ -111,9 +117,12 @@ public:
MoofParser(Stream* aSource, uint32_t aTrackId)
: mSource(aSource), mOffset(0), mTrex(aTrackId)
{
// Setting the mTrex.mTrackId to 0 is a nasty work around for calculating
// the composition range for MSE. We need an array of tracks.
}
void RebuildFragmentedIndex(
const nsTArray<mozilla::MediaByteRange>& aByteRanges);
Interval<Microseconds> GetCompositionRange();
bool ReachedEnd();
void ParseMoov(Box& aBox);
void ParseTrak(Box& aBox);

Просмотреть файл

@ -49,8 +49,11 @@ if CONFIG['OS_TARGET'] != 'Android':
EXPORTS.mp4_demuxer += [
'binding/include/mp4_demuxer/AnnexB.h',
'binding/include/mp4_demuxer/BufferStream.h',
'binding/include/mp4_demuxer/ByteReader.h',
'binding/include/mp4_demuxer/DecoderData.h',
'binding/include/mp4_demuxer/Interval.h',
'binding/include/mp4_demuxer/MoofParser.h',
'binding/include/mp4_demuxer/mp4_demuxer.h',
]
@ -67,6 +70,7 @@ UNIFIED_SOURCES += [
'binding/Adts.cpp',
'binding/AnnexB.cpp',
'binding/Box.cpp',
'binding/BufferStream.cpp',
'binding/DecoderData.cpp',
'binding/Index.cpp',
'binding/MoofParser.cpp',