diff options
author | Andy Hung <hunga@google.com> | 2014-09-23 14:59:01 -0700 |
---|---|---|
committer | Andy Hung <hunga@google.com> | 2014-09-24 18:46:49 -0700 |
commit | cf31f1eecf46d599428e115dfee8dd47b76c83fc (patch) | |
tree | c28c387f27388abc22a1658f40adf0395afb4262 /media | |
parent | 80ec934ae7d4e3a78af87554fdb77a58f6386ba0 (diff) | |
download | frameworks_av-cf31f1eecf46d599428e115dfee8dd47b76c83fc.zip frameworks_av-cf31f1eecf46d599428e115dfee8dd47b76c83fc.tar.gz frameworks_av-cf31f1eecf46d599428e115dfee8dd47b76c83fc.tar.bz2 |
NuPlayer: Fix decoder error handling
Upon error, release MediaCodec after flushing data.
Report errors when they occur with ALOGE.
Fix onInputBufferFilled mInputBufferIsDequeued check.
Bug: 17423087
Bug: 17622642
Change-Id: I316601a19d5ec95cf8e14f5bc0418a05ec423041
Diffstat (limited to 'media')
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 19 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp | 34 | ||||
-rw-r--r-- | media/libstagefright/foundation/AMessage.cpp | 2 |
3 files changed, 40 insertions, 15 deletions
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index ceedb40..ef4abd4 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -832,24 +832,31 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { finishFlushIfPossible(); } else if (what == Decoder::kWhatError) { - ALOGE("Received error from %s decoder, aborting playback.", - audio ? "audio" : "video"); - status_t err; if (!msg->findInt32("err", &err)) { err = UNKNOWN_ERROR; } - mRenderer->queueEOS(audio, err); + ALOGE("received error from %s decoder %#x", audio ? "audio" : "video", err); + + ALOGI("shutting down %s", audio ? "audio" : "video"); if (audio && mFlushingAudio != NONE) { + mRenderer->queueEOS(audio, err); mAudioDecoder.clear(); ++mAudioDecoderGeneration; mFlushingAudio = SHUT_DOWN; - } else if (!audio && mFlushingVideo != NONE){ + finishFlushIfPossible(); + } else if (!audio && mFlushingVideo != NONE) { + mRenderer->queueEOS(audio, err); mVideoDecoder.clear(); ++mVideoDecoderGeneration; mFlushingVideo = SHUT_DOWN; + finishFlushIfPossible(); + } else { + mDeferredActions.push_back( + new ShutdownDecoderAction(audio, !audio /* video */)); + processDeferredActions(); + notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); } - finishFlushIfPossible(); } else if (what == Decoder::kWhatDrainThisBuffer) { renderBuffer(audio, msg); } else { diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp index cdb860c..ed6f674 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp @@ -223,7 +223,11 @@ status_t NuPlayer::Decoder::getInputBuffers(Vector<sp<ABuffer> > *buffers) const void NuPlayer::Decoder::handleError(int32_t err) { - mCodec->release(); + // We cannot immediately release the codec due to buffers still outstanding + // in the renderer. We signal to the player the error so it can shutdown/release the + // decoder after flushing and increment the generation to discard unnecessary messages. + + ++mBufferGeneration; sp<AMessage> notify = mNotify->dup(); notify->setInt32("what", kWhatError); @@ -238,6 +242,8 @@ bool NuPlayer::Decoder::handleAnInputBuffer() { mComponentName.c_str(), res == OK ? (int)bufferIx : res); if (res != OK) { if (res != -EAGAIN) { + ALOGE("Failed to dequeue input buffer for %s (err=%d)", + mComponentName.c_str(), res); handleError(res); } return false; @@ -311,7 +317,7 @@ void android::NuPlayer::Decoder::onInputBufferFilled(const sp<AMessage> &msg) { } } - mInputBufferIsDequeued.editItemAt(bufferIx) = false; + if (buffer == NULL /* includes !hasBuffer */) { int32_t streamErr = ERROR_END_OF_STREAM; @@ -329,12 +335,18 @@ void android::NuPlayer::Decoder::onInputBufferFilled(const sp<AMessage> &msg) { 0, 0, MediaCodec::BUFFER_FLAG_EOS); - if (streamErr == ERROR_END_OF_STREAM && err != OK) { + if (err == OK) { + mInputBufferIsDequeued.editItemAt(bufferIx) = false; + } else if (streamErr == ERROR_END_OF_STREAM) { streamErr = err; // err will not be ERROR_END_OF_STREAM } if (streamErr != ERROR_END_OF_STREAM) { + ALOGE("Stream error for %s (err=%d), EOS %s queued", + mComponentName.c_str(), + streamErr, + err == OK ? "successfully" : "unsuccessfully"); handleError(streamErr); } } else { @@ -364,14 +376,18 @@ void android::NuPlayer::Decoder::onInputBufferFilled(const sp<AMessage> &msg) { timeUs, flags); if (err != OK) { + if (mediaBuffer != NULL) { + mediaBuffer->release(); + } ALOGE("Failed to queue input buffer for %s (err=%d)", mComponentName.c_str(), err); handleError(err); - } - - if (mediaBuffer != NULL) { - CHECK(mMediaBuffers[bufferIx] == NULL); - mMediaBuffers.editItemAt(bufferIx) = mediaBuffer; + } else { + mInputBufferIsDequeued.editItemAt(bufferIx) = false; + if (mediaBuffer != NULL) { + CHECK(mMediaBuffers[bufferIx] == NULL); + mMediaBuffers.editItemAt(bufferIx) = mediaBuffer; + } } } } @@ -422,6 +438,8 @@ bool NuPlayer::Decoder::handleAnOutputBuffer() { return true; } else if (res != OK) { if (res != -EAGAIN) { + ALOGE("Failed to dequeue output buffer for %s (err=%d)", + mComponentName.c_str(), res); handleError(res); } return false; diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp index bc3e3fb..795e8a6 100644 --- a/media/libstagefright/foundation/AMessage.cpp +++ b/media/libstagefright/foundation/AMessage.cpp @@ -485,7 +485,7 @@ AString AMessage::debugString(int32_t indent) const { { sp<ABuffer> buffer = static_cast<ABuffer *>(item.u.refValue); - if (buffer != NULL && buffer->size() <= 64) { + if (buffer != NULL && buffer->data() != NULL && buffer->size() <= 64) { tmp = StringPrintf("Buffer %s = {\n", item.mName); hexdump(buffer->data(), buffer->size(), indent + 4, &tmp); appendIndent(&tmp, indent + 2); |