зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1123498 - Make MP4Reader skip-to-next-keyframe less aggressively. r=mattwoodrow
This commit is contained in:
Родитель
b52e9b0fd5
Коммит
8a239a32e3
|
@ -107,7 +107,6 @@ InvokeAndRetry(ThisType* aThisVal, ReturnType(ThisType::*aMethod)(), MP4Stream*
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
MP4Reader::MP4Reader(AbstractMediaDecoder* aDecoder)
|
||||
: MediaDecoderReader(aDecoder)
|
||||
, mAudio(MediaData::AUDIO_DATA, Preferences::GetUint("media.mp4-audio-decode-ahead", 2))
|
||||
|
@ -196,6 +195,7 @@ MP4Reader::InitLayersBackendType()
|
|||
}
|
||||
|
||||
static bool sIsEMEEnabled = false;
|
||||
static bool sDemuxSkipToNextKeyframe = true;
|
||||
|
||||
nsresult
|
||||
MP4Reader::Init(MediaDecoderReader* aCloneDonor)
|
||||
|
@ -217,6 +217,7 @@ MP4Reader::Init(MediaDecoderReader* aCloneDonor)
|
|||
if (!sSetupPrefCache) {
|
||||
sSetupPrefCache = true;
|
||||
Preferences::AddBoolVarCache(&sIsEMEEnabled, "media.eme.enabled", false);
|
||||
Preferences::AddBoolVarCache(&sDemuxSkipToNextKeyframe, "media.fmp4.demux-skip", true);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -519,6 +520,29 @@ MP4Reader::GetDecoderData(TrackType aTrack)
|
|||
return mVideo;
|
||||
}
|
||||
|
||||
Microseconds
|
||||
MP4Reader::GetNextKeyframeTime()
|
||||
{
|
||||
MonitorAutoLock mon(mDemuxerMonitor);
|
||||
return mDemuxer->GetNextKeyframeTime();
|
||||
}
|
||||
|
||||
bool
|
||||
MP4Reader::ShouldSkip(bool aSkipToNextKeyframe, int64_t aTimeThreshold)
|
||||
{
|
||||
// The MP4Reader doesn't do normal skip-to-next-keyframe if the demuxer
|
||||
// has exposes where the next keyframe is. We can then instead skip only
|
||||
// if the time threshold (the current playback position) is after the next
|
||||
// keyframe in the stream. This means we'll only skip frames that we have
|
||||
// no hope of ever playing.
|
||||
Microseconds nextKeyframe = -1;
|
||||
if (!sDemuxSkipToNextKeyframe ||
|
||||
(nextKeyframe = GetNextKeyframeTime()) == -1) {
|
||||
return aSkipToNextKeyframe;
|
||||
}
|
||||
return nextKeyframe < aTimeThreshold;
|
||||
}
|
||||
|
||||
nsRefPtr<MediaDecoderReader::VideoDataPromise>
|
||||
MP4Reader::RequestVideoData(bool aSkipToNextKeyframe,
|
||||
int64_t aTimeThreshold)
|
||||
|
@ -537,7 +561,7 @@ MP4Reader::RequestVideoData(bool aSkipToNextKeyframe,
|
|||
MOZ_ASSERT(HasVideo() && mPlatform && mVideo.mDecoder);
|
||||
|
||||
bool eos = false;
|
||||
if (aSkipToNextKeyframe) {
|
||||
if (ShouldSkip(aSkipToNextKeyframe, aTimeThreshold)) {
|
||||
uint32_t parsed = 0;
|
||||
eos = !SkipVideoDemuxToNextKeyFrame(aTimeThreshold, parsed);
|
||||
if (!eos && NS_FAILED(mVideo.mDecoder->Flush())) {
|
||||
|
|
|
@ -121,6 +121,9 @@ private:
|
|||
bool IsWaitingOnCodecResource();
|
||||
virtual bool IsWaitingOnCDMResource() MOZ_OVERRIDE;
|
||||
|
||||
Microseconds GetNextKeyframeTime();
|
||||
bool ShouldSkip(bool aSkipToNextKeyframe, int64_t aTimeThreshold);
|
||||
|
||||
size_t SizeOfQueue(TrackType aTrack);
|
||||
|
||||
nsRefPtr<MP4Stream> mStream;
|
||||
|
|
|
@ -186,6 +186,31 @@ void SampleIterator::Seek(Microseconds aTime)
|
|||
mCurrentSample = syncSample;
|
||||
}
|
||||
|
||||
Microseconds
|
||||
SampleIterator::GetNextKeyframeTime()
|
||||
{
|
||||
nsTArray<Moof>& moofs = mIndex->mMoofParser->Moofs();
|
||||
size_t sample = mCurrentSample + 1;
|
||||
size_t moof = mCurrentMoof;
|
||||
while (true) {
|
||||
while (true) {
|
||||
if (moof == moofs.Length()) {
|
||||
return -1;
|
||||
}
|
||||
if (sample < moofs[moof].mIndex.Length()) {
|
||||
break;
|
||||
}
|
||||
sample = 0;
|
||||
++moof;
|
||||
}
|
||||
if (moofs[moof].mIndex[sample].mSync) {
|
||||
return moofs[moof].mIndex[sample].mDecodeTime;
|
||||
}
|
||||
++sample;
|
||||
}
|
||||
MOZ_ASSERT(false); // should not be reached.
|
||||
}
|
||||
|
||||
Index::Index(const stagefright::Vector<MediaSource::Indice>& aIndex,
|
||||
Stream* aSource, uint32_t aTrackId, Microseconds aTimestampOffset,
|
||||
Monitor* aMonitor)
|
||||
|
|
|
@ -22,6 +22,7 @@ public:
|
|||
explicit SampleIterator(Index* aIndex);
|
||||
MP4Sample* GetNext();
|
||||
void Seek(Microseconds aTime);
|
||||
Microseconds GetNextKeyframeTime();
|
||||
|
||||
private:
|
||||
Sample* Get();
|
||||
|
|
|
@ -73,6 +73,10 @@ public:
|
|||
|
||||
int64_t GetEvictionOffset(Microseconds aTime);
|
||||
|
||||
// Returns timestamp of next keyframe, or -1 if demuxer can't
|
||||
// report this.
|
||||
Microseconds GetNextKeyframeTime();
|
||||
|
||||
private:
|
||||
AudioDecoderConfig mAudioConfig;
|
||||
VideoDecoderConfig mVideoConfig;
|
||||
|
@ -84,6 +88,7 @@ private:
|
|||
nsTArray<Interval<Microseconds>> mCachedTimeRanges;
|
||||
Microseconds mTimestampOffset;
|
||||
Monitor* mMonitor;
|
||||
Microseconds mNextKeyframeTime;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -75,7 +75,8 @@ private:
|
|||
|
||||
MP4Demuxer::MP4Demuxer(Stream* source, Microseconds aTimestampOffset, Monitor* aMonitor)
|
||||
: mPrivate(new StageFrightPrivate()), mSource(source),
|
||||
mTimestampOffset(aTimestampOffset), mMonitor(aMonitor)
|
||||
mTimestampOffset(aTimestampOffset), mMonitor(aMonitor),
|
||||
mNextKeyframeTime(-1)
|
||||
{
|
||||
mPrivate->mExtractor = new MPEG4Extractor(new DataSourceAdapter(source));
|
||||
}
|
||||
|
@ -248,6 +249,9 @@ MP4Demuxer::DemuxVideoSample()
|
|||
sample->crypto.mode = mVideoConfig.crypto.mode;
|
||||
sample->crypto.key.AppendElements(mVideoConfig.crypto.key);
|
||||
}
|
||||
if (sample->composition_timestamp >= mNextKeyframeTime) {
|
||||
mNextKeyframeTime = mPrivate->mVideoIterator->GetNextKeyframeTime();
|
||||
}
|
||||
}
|
||||
return sample.forget();
|
||||
}
|
||||
|
@ -333,4 +337,14 @@ MP4Demuxer::GetEvictionOffset(Microseconds aTime)
|
|||
return offset == std::numeric_limits<uint64_t>::max() ? -1 : offset;
|
||||
}
|
||||
|
||||
Microseconds
|
||||
MP4Demuxer::GetNextKeyframeTime()
|
||||
{
|
||||
mMonitor->AssertCurrentThreadOwns();
|
||||
if (!mPrivate->mVideoIterator) {
|
||||
return -1;
|
||||
}
|
||||
return mNextKeyframeTime;
|
||||
}
|
||||
|
||||
} // namespace mp4_demuxer
|
||||
|
|
Загрузка…
Ссылка в новой задаче