зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1057203 - Remove MoofParser dependency on stagefright; r=edwin
This commit is contained in:
Родитель
ee0e0c98ea
Коммит
b5c59c078b
|
@ -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',
|
||||
|
|
Загрузка…
Ссылка в новой задаче