зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changesets b8e0173c9c47, b087e84a99f1, and 66c055120ca7 (bug 1049133) for Android and B2G bustage.
CLOSED TREE
This commit is contained in:
Родитель
564dd7ae57
Коммит
e5df4919ce
|
@ -159,7 +159,6 @@ public:
|
||||||
// Only used by WebMReader and MediaOmxReader for now, so stub here rather
|
// Only used by WebMReader and MediaOmxReader for now, so stub here rather
|
||||||
// than in every reader than inherits from MediaDecoderReader.
|
// than in every reader than inherits from MediaDecoderReader.
|
||||||
virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset) {}
|
virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset) {}
|
||||||
virtual int64_t GetEvictionOffset(double aTime) { return -1; }
|
|
||||||
|
|
||||||
virtual MediaQueue<AudioData>& AudioQueue() { return mAudioQueue; }
|
virtual MediaQueue<AudioData>& AudioQueue() { return mAudioQueue; }
|
||||||
virtual MediaQueue<VideoData>& VideoQueue() { return mVideoQueue; }
|
virtual MediaQueue<VideoData>& VideoQueue() { return mVideoQueue; }
|
||||||
|
|
|
@ -109,6 +109,7 @@ MP4Reader::MP4Reader(AbstractMediaDecoder* aDecoder)
|
||||||
, mVideo("MP4 video decoder data", Preferences::GetUint("media.mp4-video-decode-ahead", 2))
|
, mVideo("MP4 video decoder data", Preferences::GetUint("media.mp4-video-decode-ahead", 2))
|
||||||
, mLastReportedNumDecodedFrames(0)
|
, mLastReportedNumDecodedFrames(0)
|
||||||
, mLayersBackendType(layers::LayersBackend::LAYERS_NONE)
|
, mLayersBackendType(layers::LayersBackend::LAYERS_NONE)
|
||||||
|
, mTimeRangesMonitor("MP4Reader::TimeRanges")
|
||||||
, mDemuxerInitialized(false)
|
, mDemuxerInitialized(false)
|
||||||
, mIsEncrypted(false)
|
, mIsEncrypted(false)
|
||||||
{
|
{
|
||||||
|
@ -768,36 +769,29 @@ MP4Reader::NotifyDataArrived(const char* aBuffer, uint32_t aLength,
|
||||||
void
|
void
|
||||||
MP4Reader::UpdateIndex()
|
MP4Reader::UpdateIndex()
|
||||||
{
|
{
|
||||||
|
nsTArray<MediaByteRange> ranges;
|
||||||
|
nsTArray<Interval<Microseconds>> timeRanges;
|
||||||
|
|
||||||
MediaResource* resource = mDecoder->GetResource();
|
MediaResource* resource = mDecoder->GetResource();
|
||||||
resource->Pin();
|
resource->Pin();
|
||||||
nsTArray<MediaByteRange> ranges;
|
|
||||||
if (NS_SUCCEEDED(resource->GetCachedRanges(ranges))) {
|
if (NS_SUCCEEDED(resource->GetCachedRanges(ranges))) {
|
||||||
mDemuxer->UpdateIndex(ranges);
|
mDemuxer->ConvertByteRangesToTime(ranges, &timeRanges);
|
||||||
}
|
}
|
||||||
resource->Unpin();
|
resource->Unpin();
|
||||||
|
|
||||||
|
MonitorAutoLock mon(mTimeRangesMonitor);
|
||||||
|
mTimeRanges = timeRanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t
|
|
||||||
MP4Reader::GetEvictionOffset(double aTime)
|
|
||||||
{
|
|
||||||
return mDemuxer->GetEvictionOffset(aTime * 1000000.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
MP4Reader::GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime)
|
MP4Reader::GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime)
|
||||||
{
|
{
|
||||||
MediaResource* resource = mDecoder->GetResource();
|
MonitorAutoLock mon(mTimeRangesMonitor);
|
||||||
resource->Pin();
|
for (size_t i = 0; i < mTimeRanges.Length(); i++) {
|
||||||
nsTArray<MediaByteRange> ranges;
|
aBuffered->Add((mTimeRanges[i].start - aStartTime) / 1000000.0,
|
||||||
if (NS_SUCCEEDED(resource->GetCachedRanges(ranges))) {
|
(mTimeRanges[i].end - aStartTime) / 1000000.0);
|
||||||
nsTArray<Interval<Microseconds>> timeRanges;
|
|
||||||
mDemuxer->ConvertByteRangesToTime(ranges, &timeRanges);
|
|
||||||
for (size_t i = 0; i < timeRanges.Length(); i++) {
|
|
||||||
aBuffered->Add((timeRanges[i].start - aStartTime) / 1000000.0,
|
|
||||||
(timeRanges[i].end - aStartTime) / 1000000.0);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
resource->Unpin();
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,8 +55,6 @@ public:
|
||||||
virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength,
|
virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength,
|
||||||
int64_t aOffset) MOZ_OVERRIDE;
|
int64_t aOffset) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual int64_t GetEvictionOffset(double aTime) MOZ_OVERRIDE;
|
|
||||||
|
|
||||||
virtual nsresult GetBuffered(dom::TimeRanges* aBuffered,
|
virtual nsresult GetBuffered(dom::TimeRanges* aBuffered,
|
||||||
int64_t aStartTime) MOZ_OVERRIDE;
|
int64_t aStartTime) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
@ -182,6 +180,8 @@ private:
|
||||||
layers::LayersBackend mLayersBackendType;
|
layers::LayersBackend mLayersBackendType;
|
||||||
|
|
||||||
nsTArray<nsTArray<uint8_t>> mInitDataEncountered;
|
nsTArray<nsTArray<uint8_t>> mInitDataEncountered;
|
||||||
|
Monitor mTimeRangesMonitor;
|
||||||
|
nsTArray<mp4_demuxer::Interval<Microseconds>> mTimeRanges;
|
||||||
|
|
||||||
// True if we've read the streams' metadata.
|
// True if we've read the streams' metadata.
|
||||||
bool mDemuxerInitialized;
|
bool mDemuxerInitialized;
|
||||||
|
|
|
@ -112,16 +112,11 @@ SubBufferDecoder::GetBuffered(dom::TimeRanges* aBuffered)
|
||||||
int64_t
|
int64_t
|
||||||
SubBufferDecoder::ConvertToByteOffset(double aTime)
|
SubBufferDecoder::ConvertToByteOffset(double aTime)
|
||||||
{
|
{
|
||||||
int64_t readerOffset = mReader->GetEvictionOffset(aTime);
|
|
||||||
if (readerOffset >= 0) {
|
|
||||||
return readerOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uses a conversion based on (aTime/duration) * length. For the
|
// Uses a conversion based on (aTime/duration) * length. For the
|
||||||
// purposes of eviction this should be adequate since we have the
|
// purposes of eviction this should be adequate since we have the
|
||||||
// byte threshold as well to ensure data actually gets evicted and
|
// byte threshold as well to ensure data actually gets evicted and
|
||||||
// we ensure we don't evict before the current playable point.
|
// we ensure we don't evict before the current playable point.
|
||||||
if (mMediaDuration <= 0) {
|
if (mMediaDuration == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int64_t length = GetResource()->GetLength();
|
int64_t length = GetResource()->GetLength();
|
||||||
|
|
|
@ -85,55 +85,44 @@ Index::Index(const stagefright::Vector<MediaSource::Indice>& aIndex,
|
||||||
|
|
||||||
Index::~Index() {}
|
Index::~Index() {}
|
||||||
|
|
||||||
void
|
|
||||||
Index::UpdateMoofIndex(const nsTArray<MediaByteRange>& aByteRanges)
|
|
||||||
{
|
|
||||||
if (!mMoofParser) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
MonitorAutoLock mon(mMonitor);
|
|
||||||
mMoofParser->RebuildFragmentedIndex(aByteRanges);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Index::ConvertByteRangesToTimeRanges(
|
Index::ConvertByteRangesToTimeRanges(
|
||||||
const nsTArray<MediaByteRange>& aByteRanges,
|
const nsTArray<MediaByteRange>& aByteRanges,
|
||||||
nsTArray<Interval<Microseconds>>* aTimeRanges)
|
nsTArray<Interval<Microseconds>>* aTimeRanges)
|
||||||
{
|
{
|
||||||
MonitorAutoLock mon(mMonitor);
|
|
||||||
|
|
||||||
RangeFinder rangeFinder(aByteRanges);
|
RangeFinder rangeFinder(aByteRanges);
|
||||||
nsTArray<Interval<Microseconds>> timeRanges;
|
nsTArray<Interval<Microseconds>> timeRanges;
|
||||||
|
|
||||||
nsTArray<nsTArray<stagefright::MediaSource::Indice>*> indexes;
|
nsTArray<stagefright::MediaSource::Indice> moofIndex;
|
||||||
|
nsTArray<stagefright::MediaSource::Indice>* index;
|
||||||
if (mMoofParser) {
|
if (mMoofParser) {
|
||||||
|
{
|
||||||
|
MonitorAutoLock mon(mMonitor);
|
||||||
|
mMoofParser->RebuildFragmentedIndex(aByteRanges);
|
||||||
|
|
||||||
// We take the index out of the moof parser and move it into a local
|
// 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
|
// variable so we don't get concurrency issues. It gets freed when we
|
||||||
// exit this function.
|
// exit this function.
|
||||||
for (int i = 0; i < mMoofParser->mMoofs.Length(); i++) {
|
for (int i = 0; i < mMoofParser->mMoofs.Length(); i++) {
|
||||||
Moof& moof = mMoofParser->mMoofs[i];
|
Moof& moof = mMoofParser->mMoofs[i];
|
||||||
|
if (rangeFinder.Contains(moof.mRange) &&
|
||||||
// We need the entire moof in order to play anything
|
rangeFinder.Contains(moof.mMdatRange)) {
|
||||||
if (rangeFinder.Contains(moof.mRange)) {
|
|
||||||
if (rangeFinder.Contains(moof.mMdatRange)) {
|
|
||||||
timeRanges.AppendElements(moof.mTimeRanges);
|
timeRanges.AppendElements(moof.mTimeRanges);
|
||||||
} else {
|
} else {
|
||||||
indexes.AppendElement(&moof.mIndex);
|
moofIndex.AppendElements(mMoofParser->mMoofs[i].mIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
index = &moofIndex;
|
||||||
} else {
|
} else {
|
||||||
indexes.AppendElement(&mIndex);
|
index = &mIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasSync = false;
|
bool hasSync = false;
|
||||||
for (size_t i = 0; i < indexes.Length(); i++) {
|
for (size_t i = 0; i < index->Length(); i++) {
|
||||||
nsTArray<stagefright::MediaSource::Indice>* index = indexes[i];
|
const MediaSource::Indice& indice = (*index)[i];
|
||||||
for (size_t j = 0; j < index->Length(); j++) {
|
if (!rangeFinder.Contains(MediaByteRange(indice.start_offset,
|
||||||
const MediaSource::Indice& indice = (*index)[j];
|
indice.end_offset))) {
|
||||||
if (!rangeFinder.Contains(
|
|
||||||
MediaByteRange(indice.start_offset, indice.end_offset))) {
|
|
||||||
// We process the index in decode order so we clear hasSync when we hit
|
// We process the index in decode order so we clear hasSync when we hit
|
||||||
// a range that isn't buffered.
|
// a range that isn't buffered.
|
||||||
hasSync = false;
|
hasSync = false;
|
||||||
|
@ -145,8 +134,13 @@ Index::ConvertByteRangesToTimeRanges(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Interval<Microseconds>::SemiNormalAppend(
|
// This is an optimisation for when the file is decoded in composition
|
||||||
timeRanges, Interval<Microseconds>(indice.start_composition,
|
// order. It means that Normalise() below doesn't need to do a sort.
|
||||||
|
size_t s = timeRanges.Length();
|
||||||
|
if (s && timeRanges[s - 1].end == indice.start_composition) {
|
||||||
|
timeRanges[s - 1].end = indice.end_composition;
|
||||||
|
} else {
|
||||||
|
timeRanges.AppendElement(Interval<Microseconds>(indice.start_composition,
|
||||||
indice.end_composition));
|
indice.end_composition));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,32 +148,4 @@ Index::ConvertByteRangesToTimeRanges(
|
||||||
// This fixes up when the compositon order differs from the byte range order
|
// This fixes up when the compositon order differs from the byte range order
|
||||||
Interval<Microseconds>::Normalize(timeRanges, aTimeRanges);
|
Interval<Microseconds>::Normalize(timeRanges, aTimeRanges);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
|
||||||
Index::GetEvictionOffset(Microseconds aTime)
|
|
||||||
{
|
|
||||||
uint64_t offset = std::numeric_limits<uint64_t>::max();
|
|
||||||
if (mMoofParser) {
|
|
||||||
// We need to keep the whole moof if we're keeping any of it because the
|
|
||||||
// parser doesn't keep parsed moofs.
|
|
||||||
for (int i = 0; i < mMoofParser->mMoofs.Length(); i++) {
|
|
||||||
Moof& moof = mMoofParser->mMoofs[i];
|
|
||||||
|
|
||||||
if (!moof.mTimeRanges.IsEmpty() && moof.mTimeRanges[0].end > aTime) {
|
|
||||||
offset = std::min(offset, uint64_t(std::min(moof.mRange.mStart,
|
|
||||||
moof.mMdatRange.mStart)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,11 +22,9 @@ public:
|
||||||
Stream* aSource, uint32_t aTrackId);
|
Stream* aSource, uint32_t aTrackId);
|
||||||
~Index();
|
~Index();
|
||||||
|
|
||||||
void UpdateMoofIndex(const nsTArray<mozilla::MediaByteRange>& aByteRanges);
|
|
||||||
void ConvertByteRangesToTimeRanges(
|
void ConvertByteRangesToTimeRanges(
|
||||||
const nsTArray<mozilla::MediaByteRange>& aByteRanges,
|
const nsTArray<mozilla::MediaByteRange>& aByteRanges,
|
||||||
nsTArray<Interval<Microseconds>>* aTimeRanges);
|
nsTArray<Interval<Microseconds>>* aTimeRanges);
|
||||||
uint64_t GetEvictionOffset(Microseconds aTime);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mozilla::Monitor mMonitor;
|
mozilla::Monitor mMonitor;
|
||||||
|
|
|
@ -61,7 +61,7 @@ struct Interval
|
||||||
}
|
}
|
||||||
MOZ_ASSERT(aNormalized->IsEmpty());
|
MOZ_ASSERT(aNormalized->IsEmpty());
|
||||||
|
|
||||||
nsTArray<Interval<T>> sorted;
|
nsTArray<Interval<T> > sorted;
|
||||||
sorted = aIntervals;
|
sorted = aIntervals;
|
||||||
sorted.Sort(Compare());
|
sorted.Sort(Compare());
|
||||||
|
|
||||||
|
@ -81,9 +81,9 @@ struct Interval
|
||||||
aNormalized->AppendElement(current);
|
aNormalized->AppendElement(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Intersection(const nsTArray<Interval<T>>& a0,
|
static void Intersection(const nsTArray<Interval<T> >& a0,
|
||||||
const nsTArray<Interval<T>>& a1,
|
const nsTArray<Interval<T> >& a1,
|
||||||
nsTArray<Interval<T>>* aIntersection)
|
nsTArray<Interval<T> >* aIntersection)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(IsNormalized(a0));
|
MOZ_ASSERT(IsNormalized(a0));
|
||||||
MOZ_ASSERT(IsNormalized(a1));
|
MOZ_ASSERT(IsNormalized(a1));
|
||||||
|
@ -106,7 +106,7 @@ struct Interval
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsNormalized(const nsTArray<Interval<T>>& aIntervals)
|
static bool IsNormalized(const nsTArray<Interval<T> >& aIntervals)
|
||||||
{
|
{
|
||||||
for (size_t i = 1; i < aIntervals.Length(); i++) {
|
for (size_t i = 1; i < aIntervals.Length(); i++) {
|
||||||
if (aIntervals[i - 1].end >= aIntervals[i].start) {
|
if (aIntervals[i - 1].end >= aIntervals[i].start) {
|
||||||
|
|
|
@ -59,13 +59,9 @@ public:
|
||||||
const AudioDecoderConfig& AudioConfig() { return mAudioConfig; }
|
const AudioDecoderConfig& AudioConfig() { return mAudioConfig; }
|
||||||
const VideoDecoderConfig& VideoConfig() { return mVideoConfig; }
|
const VideoDecoderConfig& VideoConfig() { return mVideoConfig; }
|
||||||
|
|
||||||
void UpdateIndex(const nsTArray<mozilla::MediaByteRange>& aByteRanges);
|
|
||||||
|
|
||||||
void ConvertByteRangesToTime(
|
void ConvertByteRangesToTime(
|
||||||
const nsTArray<mozilla::MediaByteRange>& aByteRanges,
|
const nsTArray<mozilla::MediaByteRange>& aByteRanges,
|
||||||
nsTArray<Interval<Microseconds>>* aIntervals);
|
nsTArray<Interval<Microseconds> >* aIntervals);
|
||||||
|
|
||||||
int64_t GetEvictionOffset(Microseconds aTime);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AudioDecoderConfig mAudioConfig;
|
AudioDecoderConfig mAudioConfig;
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
|
||||||
|
|
||||||
using namespace stagefright;
|
using namespace stagefright;
|
||||||
|
|
||||||
|
@ -195,14 +194,6 @@ MP4Demuxer::DemuxVideoSample()
|
||||||
return sample.forget();
|
return sample.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
MP4Demuxer::UpdateIndex(const nsTArray<mozilla::MediaByteRange>& aByteRanges)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < mPrivate->mIndexes.Length(); i++) {
|
|
||||||
mPrivate->mIndexes[i]->UpdateMoofIndex(aByteRanges);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MP4Demuxer::ConvertByteRangesToTime(
|
MP4Demuxer::ConvertByteRangesToTime(
|
||||||
const nsTArray<mozilla::MediaByteRange>& aByteRanges,
|
const nsTArray<mozilla::MediaByteRange>& aByteRanges,
|
||||||
|
@ -224,18 +215,4 @@ MP4Demuxer::ConvertByteRangesToTime(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t
|
|
||||||
MP4Demuxer::GetEvictionOffset(Microseconds aTime)
|
|
||||||
{
|
|
||||||
if (mPrivate->mIndexes.IsEmpty()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t offset = std::numeric_limits<uint64_t>::max();
|
|
||||||
for (int i = 0; i < mPrivate->mIndexes.Length(); i++) {
|
|
||||||
offset = std::min(offset, mPrivate->mIndexes[i]->GetEvictionOffset(aTime));
|
|
||||||
}
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace mp4_demuxer
|
} // namespace mp4_demuxer
|
||||||
|
|
Загрузка…
Ссылка в новой задаче