Bug 1173657: Drain decoder when discontinuity encountered. r=cpearce

A discontinuity can be when waiting for data, decoding error or reaching end of stream.
This commit is contained in:
Jean-Yves Avenard 2015-07-13 16:21:04 +10:00
Родитель 3db4cce1f9
Коммит 8ca249040e
2 изменённых файлов: 36 добавлений и 27 удалений

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

@ -720,6 +720,7 @@ MediaFormatReader::NotifyError(TrackType aTrack)
LOGV("%s Decoding error", TrackTypeToStr(aTrack));
auto& decoder = GetDecoderData(aTrack);
decoder.mError = true;
decoder.mNeedDraining = true;
ScheduleUpdate(aTrack);
}
@ -729,6 +730,7 @@ MediaFormatReader::NotifyWaitingForData(TrackType aTrack)
MOZ_ASSERT(OnTaskQueue());
auto& decoder = GetDecoderData(aTrack);
decoder.mWaitingForData = true;
decoder.mNeedDraining = true;
ScheduleUpdate(aTrack);
}
@ -738,6 +740,7 @@ MediaFormatReader::NotifyEndOfStream(TrackType aTrack)
MOZ_ASSERT(OnTaskQueue());
auto& decoder = GetDecoderData(aTrack);
decoder.mDemuxEOS = true;
decoder.mNeedDraining = true;
ScheduleUpdate(aTrack);
}
@ -798,7 +801,6 @@ MediaFormatReader::UpdateReceivedNewData(TrackType aTrack)
(!hasLastEnd || decoder.mTimeRanges.GetEnd() > lastEnd)) {
// New data was added after our previous end, we can clear the EOS flag.
decoder.mDemuxEOS = false;
decoder.mDemuxEOSServiced = false;
}
if (decoder.mError) {
@ -945,6 +947,21 @@ MediaFormatReader::DecodeDemuxedSamples(TrackType aTrack,
decoder.mInputExhausted = false;
}
void
MediaFormatReader::DrainDecoder(TrackType aTrack)
{
MOZ_ASSERT(OnTaskQueue());
auto& decoder = GetDecoderData(aTrack);
if (!decoder.mNeedDraining) {
return;
}
decoder.mOutputRequested = true;
decoder.mDecoder->Drain();
decoder.mNeedDraining = false;
LOG("Requesting %s decoder to drain", TrackTypeToStr(aTrack));
}
void
MediaFormatReader::Update(TrackType aTrack)
{
@ -966,23 +983,6 @@ MediaFormatReader::Update(TrackType aTrack)
return;
}
if (decoder.HasPromise()) {
// Handle pending requests from the MediaDecoderStateMachine.
if (decoder.mError) {
LOG("Decoding Error");
decoder.RejectPromise(DECODE_ERROR, __func__);
return;
}
if (decoder.mWaitingForData) {
LOG("Waiting For Data");
decoder.RejectPromise(WAITING_FOR_DATA, __func__);
}
} else if (decoder.mWaitingForData) {
// Nothing more we can do at present.
LOGV("Still waiting for data.");
return;
}
// Record number of frames decoded and parsed. Automatically update the
// stats counters using the AutoNotifyDecoded stack-based class.
AbstractMediaDecoder::AutoNotifyDecoded a(mDecoder);
@ -993,6 +993,7 @@ MediaFormatReader::Update(TrackType aTrack)
a.mDecoded = static_cast<uint32_t>(delta);
mLastReportedNumDecodedFrames = decoder.mNumSamplesOutput;
}
if (decoder.HasPromise()) {
needOutput = true;
if (!decoder.mOutput.IsEmpty()) {
@ -1011,16 +1012,22 @@ MediaFormatReader::Update(TrackType aTrack)
output->mKeyframe);
}
} else if (decoder.mDrainComplete) {
decoder.RejectPromise(END_OF_STREAM, __func__);
decoder.mDrainComplete = false;
if (decoder.mError) {
LOG("Decoding Error");
decoder.RejectPromise(DECODE_ERROR, __func__);
return;
} else if (decoder.mDemuxEOS) {
decoder.RejectPromise(END_OF_STREAM, __func__);
} else if (decoder.mWaitingForData) {
LOG("Waiting For Data");
decoder.RejectPromise(WAITING_FOR_DATA, __func__);
}
}
}
if (decoder.mDemuxEOS && !decoder.mDemuxEOSServiced) {
decoder.mOutputRequested = true;
decoder.mDecoder->Drain();
decoder.mDemuxEOSServiced = true;
LOGV("Requesting decoder to drain");
if (decoder.mError || decoder.mDemuxEOS || decoder.mWaitingForData) {
DrainDecoder(aTrack);
return;
}

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

@ -118,6 +118,8 @@ private:
// Decode any pending already demuxed samples.
void DecodeDemuxedSamples(TrackType aTrack,
AbstractMediaDecoder::AutoNotifyDecoded& aA);
// Drain the current decoder.
void DrainDecoder(TrackType aTrack);
void NotifyNewOutput(TrackType aTrack, MediaData* aSample);
void NotifyInputExhausted(TrackType aTrack);
void NotifyDrainComplete(TrackType aTrack);
@ -188,13 +190,13 @@ private:
, mForceDecodeAhead(false)
, mUpdateScheduled(false)
, mDemuxEOS(false)
, mDemuxEOSServiced(false)
, mWaitingForData(false)
, mReceivedNewData(false)
, mDiscontinuity(true)
, mOutputRequested(false)
, mInputExhausted(false)
, mError(false)
, mNeedDraining(false)
, mDrainComplete(false)
, mNumSamplesInput(0)
, mNumSamplesOutput(0)
@ -219,7 +221,6 @@ private:
bool mForceDecodeAhead;
bool mUpdateScheduled;
bool mDemuxEOS;
bool mDemuxEOSServiced;
bool mWaitingForData;
bool mReceivedNewData;
bool mDiscontinuity;
@ -241,6 +242,7 @@ private:
bool mOutputRequested;
bool mInputExhausted;
bool mError;
bool mNeedDraining;
bool mDrainComplete;
// If set, all decoded samples prior mTimeThreshold will be dropped.
// Used for internal seeking when a change of stream is detected.
@ -270,13 +272,13 @@ private:
MOZ_ASSERT(mOwner->OnTaskQueue());
mForceDecodeAhead = false;
mDemuxEOS = false;
mDemuxEOSServiced = false;
mWaitingForData = false;
mReceivedNewData = false;
mDiscontinuity = true;
mQueuedSamples.Clear();
mOutputRequested = false;
mInputExhausted = false;
mNeedDraining = false;
mDrainComplete = false;
mTimeThreshold.reset();
mOutput.Clear();