Bug 1097116 - Correctly implement Drain() in AndroidDecoderModule r=cpearce

--HG--
extra : rebase_source : 8764f15761c68a6f07a1ce5e0ccd842d56274519
This commit is contained in:
James Willcox 2014-11-18 19:28:24 -06:00
parent 085398bba7
commit 2bcf8c03d0
2 changed files with 56 additions and 9 deletions

View File

@ -242,6 +242,7 @@ MediaCodecDataDecoder::MediaCodecDataDecoder(MediaData::Type aType,
, mInputBuffers(nullptr)
, mOutputBuffers(nullptr)
, mMonitor("MediaCodecDataDecoder::mMonitor")
, mFlushing(false)
, mDraining(false)
, mStopping(false)
{
@ -313,6 +314,9 @@ void MediaCodecDataDecoder::DecoderLoop()
{
bool outputDone = false;
bool draining = false;
bool waitingEOF = false;
JNIEnv* env = GetJNIForThread();
mp4_demuxer::MP4Sample* sample = nullptr;
@ -322,7 +326,7 @@ void MediaCodecDataDecoder::DecoderLoop()
for (;;) {
{
MonitorAutoLock lock(mMonitor);
while (!mStopping && !mDraining && mQueue.empty()) {
while (!mStopping && !mDraining && !mFlushing && mQueue.empty()) {
if (mQueue.empty()) {
// We could be waiting here forever if we don't signal that we need more input
mCallback->InputExhausted();
@ -335,20 +339,40 @@ void MediaCodecDataDecoder::DecoderLoop()
break;
}
if (mDraining) {
if (mFlushing) {
mDecoder->Flush();
ClearQueue();
mDraining = false;
mFlushing = false;
lock.Notify();
continue;
}
if (mDraining && !sample && !waitingEOF) {
draining = true;
}
// We're not stopping or draining, so try to get a sample
if (!mQueue.empty()) {
sample = mQueue.front();
}
}
if (draining && !waitingEOF) {
MOZ_ASSERT(!sample, "Shouldn't have a sample when pushing EOF frame");
int inputIndex = mDecoder->DequeueInputBuffer(DECODER_TIMEOUT, &res);
if (NS_FAILED(res)) {
NS_WARNING("exiting decoder loop due to exception while dequeuing input\n");
mCallback->Error();
break;
}
if (inputIndex >= 0) {
mDecoder->QueueInputBuffer(inputIndex, 0, 0, 0, MediaCodec::getBUFFER_FLAG_END_OF_STREAM(), &res);
waitingEOF = true;
}
}
if (sample) {
// We have a sample, try to feed it to the decoder
int inputIndex = mDecoder->DequeueInputBuffer(DECODER_TIMEOUT, &res);
@ -417,7 +441,23 @@ void MediaCodecDataDecoder::DecoderLoop()
} else {
// We have a valid buffer index >= 0 here
if (bufferInfo.getFlags() & MediaCodec::getBUFFER_FLAG_END_OF_STREAM()) {
if (draining) {
draining = false;
waitingEOF = false;
mMonitor.Lock();
mDraining = false;
mMonitor.Notify();
mMonitor.Unlock();
mCallback->DrainComplete();
}
mDecoder->ReleaseOutputBuffer(outputStatus, false);
outputDone = true;
// We only queue empty EOF frames, so we're done for now
continue;
}
MOZ_ASSERT(!mDurations.empty(), "Should have had a duration queued");
@ -509,20 +549,26 @@ nsresult MediaCodecDataDecoder::ResetOutputBuffers()
}
nsresult MediaCodecDataDecoder::Flush() {
Drain();
MonitorAutoLock lock(mMonitor);
mFlushing = true;
lock.Notify();
while (mFlushing) {
lock.Wait();
}
return NS_OK;
}
nsresult MediaCodecDataDecoder::Drain() {
MonitorAutoLock lock(mMonitor);
if (mDraining) {
return NS_OK;
}
mDraining = true;
lock.Notify();
while (mDraining) {
lock.Wait();
}
mCallback->DrainComplete();
return NS_OK;
}

View File

@ -87,6 +87,7 @@ protected:
// Only these members are protected by mMonitor.
Monitor mMonitor;
bool mFlushing;
bool mDraining;
bool mStopping;