Bug 1275538: P2. Drop decoded frames that we know are already too late. r=kamidphish

MozReview-Commit-ID: EZ2Ql2DtTKa

--HG--
extra : rebase_source : 4dbffc3538e86562a6bb347354f4ff377e484f04
This commit is contained in:
Jean-Yves Avenard 2016-05-26 14:58:48 +10:00
parent ca37fb4d46
commit 48f24d3464
2 changed files with 39 additions and 5 deletions

View File

@ -1422,6 +1422,27 @@ MediaFormatReader::Reset(TrackType aTrack)
LOG("Reset(%s) END", TrackTypeToStr(aTrack));
}
void
MediaFormatReader::DropDecodedSamples(TrackType aTrack)
{
MOZ_ASSERT(OnTaskQueue());
auto& decoder = GetDecoderData(aTrack);
size_t lengthDecodedQueue = decoder.mOutput.Length();
if (lengthDecodedQueue && decoder.mTimeThreshold.isSome()) {
TimeUnit time =
TimeUnit::FromMicroseconds(decoder.mOutput.LastElement()->mTime);
if (time >= decoder.mTimeThreshold.ref().Time()) {
// We would have reached our internal seek target.
decoder.mTimeThreshold.reset();
}
}
decoder.mOutput.Clear();
decoder.mSizeOfQueue -= lengthDecodedQueue;
if (aTrack == TrackInfo::kVideoTrack && mDecoder) {
mDecoder->NotifyDecodedFrames(0, 0, lengthDecodedQueue);
}
}
void
MediaFormatReader::SkipVideoDemuxToNextKeyFrame(media::TimeUnit aTimeThreshold)
{
@ -1429,6 +1450,15 @@ MediaFormatReader::SkipVideoDemuxToNextKeyFrame(media::TimeUnit aTimeThreshold)
MOZ_ASSERT(mVideo.HasPromise());
LOG("Skipping up to %lld", aTimeThreshold.ToMicroseconds());
// We've reached SkipVideoDemuxToNextKeyFrame when our decoding is late.
// As such we can drop all already decoded samples and discard all pending
// samples.
// TODO: Ideally we should set mOutputRequested to false so that all pending
// frames are dropped too. However, we can't do such thing as the code assumes
// that the decoder just got flushed. Once bug 1257107 land, we could set the
// decoder threshold to the value of currentTime.
DropDecodedSamples(TrackInfo::kVideoTrack);
mSkipRequest.Begin(mVideo.mTrackDemuxer->SkipToNextRandomAccessPoint(aTimeThreshold)
->Then(OwnerThread(), __func__, this,
&MediaFormatReader::OnVideoSkipCompleted,
@ -1440,11 +1470,11 @@ void
MediaFormatReader::VideoSkipReset(uint32_t aSkipped)
{
MOZ_ASSERT(OnTaskQueue());
// I think it's still possible for an output to have been sent from the decoder
// and is currently sitting in our event queue waiting to be processed. The following
// flush won't clear it, and when we return to the event loop it'll be added to our
// output queue and be used.
// This code will count that as dropped, which was the intent, but not quite true.
// Some frames may have been output by the decoder since we initiated the
// videoskip process and we know they would be late.
DropDecodedSamples(TrackInfo::kVideoTrack);
// Report the pending frames as dropped.
if (mDecoder) {
mDecoder->NotifyDecodedFrames(0, 0, SizeOfVideoQueueInFrames());
}
@ -1483,6 +1513,9 @@ MediaFormatReader::OnVideoSkipFailed(MediaTrackDemuxer::SkipFailureHolder aFailu
switch (aFailure.mFailure) {
case DemuxerFailureReason::END_OF_STREAM: MOZ_FALLTHROUGH;
case DemuxerFailureReason::WAITING_FOR_DATA:
// Some frames may have been output by the decoder since we initiated the
// videoskip process and we know they would be late.
DropDecodedSamples(TrackInfo::kVideoTrack);
// We can't complete the skip operation, will just service a video frame
// normally.
NotifyDecodingRequested(TrackInfo::kVideoTrack);

View File

@ -179,6 +179,7 @@ private:
void Error(TrackType aTrack);
void Reset(TrackType aTrack);
void DrainComplete(TrackType aTrack);
void DropDecodedSamples(TrackType aTrack);
bool ShouldSkip(bool aSkipToNextKeyframe, media::TimeUnit aTimeThreshold);