From c6cfd70f24a11b946859485ce398a189c301a4e2 Mon Sep 17 00:00:00 2001 From: Wei Jia Date: Tue, 11 Nov 2014 16:33:20 -0800 Subject: NuPlayer: tunnel decoder with renderer for data buffer passing. Bug: 18342383 Change-Id: I182928007814c146c01a86196c4fda1d46e74ea4 --- .../nuplayer/NuPlayerDecoder.cpp | 119 +++++++++++++++++---- 1 file changed, 99 insertions(+), 20 deletions(-) (limited to 'media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp') diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp index 27f6131..e695c43 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp @@ -21,6 +21,9 @@ #include "NuPlayerDecoder.h" +#include "NuPlayerRenderer.h" +#include "NuPlayerSource.h" + #include #include #include @@ -35,9 +38,14 @@ namespace android { NuPlayer::Decoder::Decoder( const sp ¬ify, + const sp &source, + const sp &renderer, const sp &nativeWindow) : mNotify(notify), mNativeWindow(nativeWindow), + mSource(source), + mRenderer(renderer), + mSkipRenderingUntilMediaTimeUs(-1ll), mBufferGeneration(0), mPaused(true), mComponentName("decoder") { @@ -169,7 +177,9 @@ void NuPlayer::Decoder::onConfigure(const sp &format) { mInputBuffers.size(), mOutputBuffers.size()); - requestCodecNotification(); + if (mRenderer != NULL) { + requestCodecNotification(); + } mPaused = false; } @@ -191,6 +201,7 @@ void NuPlayer::Decoder::releaseAndResetMediaBuffers() { } mPendingInputMessages.clear(); + mSkipRenderingUntilMediaTimeUs = -1; } void NuPlayer::Decoder::requestCodecNotification() { @@ -217,6 +228,12 @@ void NuPlayer::Decoder::configure(const sp &format) { msg->post(); } +void NuPlayer::Decoder::setRenderer(const sp &renderer) { + sp msg = new AMessage(kWhatSetRenderer, id()); + msg->setObject("renderer", renderer); + msg->post(); +} + void NuPlayer::Decoder::signalUpdateFormat(const sp &format) { sp msg = new AMessage(kWhatUpdateFormat, id()); msg->setMessage("format", format); @@ -342,8 +359,6 @@ bool android::NuPlayer::Decoder::onInputBufferFilled(const sp &msg) { } } - - if (buffer == NULL /* includes !hasBuffer */) { int32_t streamErr = ERROR_END_OF_STREAM; CHECK(msg->findInt32("err", &streamErr) || !hasBuffer); @@ -375,6 +390,17 @@ bool android::NuPlayer::Decoder::onInputBufferFilled(const sp &msg) { handleError(streamErr); } } else { + sp extra; + if (buffer->meta()->findMessage("extra", &extra) && extra != NULL) { + int64_t resumeAtMediaTimeUs; + if (extra->findInt64( + "resume-at-mediaTimeUs", &resumeAtMediaTimeUs)) { + ALOGI("[%s] suppressing rendering until %lld us", + mComponentName.c_str(), (long long)resumeAtMediaTimeUs); + mSkipRenderingUntilMediaTimeUs = resumeAtMediaTimeUs; + } + } + int64_t timeUs = 0; uint32_t flags = 0; CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); @@ -454,10 +480,27 @@ bool NuPlayer::Decoder::handleAnOutputBuffer() { return false; } - sp notify = mNotify->dup(); - notify->setInt32("what", kWhatOutputFormatChanged); - notify->setMessage("format", format); - notify->post(); + if (isVideo()) { + sp notify = mNotify->dup(); + notify->setInt32("what", kWhatVideoSizeChanged); + notify->setMessage("format", format); + notify->post(); + } else if (mRenderer != NULL) { + uint32_t flags; + int64_t durationUs; + bool hasVideo = (mSource->getFormat(false /* audio */) != NULL); + if (!hasVideo && + mSource->getDuration(&durationUs) == OK && + durationUs + > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) { + flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER; + } else { + flags = AUDIO_OUTPUT_FLAG_NONE; + } + + mRenderer->openAudioSink( + format, false /* offloadOnly */, hasVideo, flags); + } return true; } else if (res == INFO_DISCONTINUITY) { // nothing to do @@ -485,21 +528,26 @@ bool NuPlayer::Decoder::handleAnOutputBuffer() { reply->setSize("buffer-ix", bufferIx); reply->setInt32("generation", mBufferGeneration); - sp notify = mNotify->dup(); - notify->setInt32("what", kWhatDrainThisBuffer); - notify->setBuffer("buffer", buffer); - notify->setMessage("reply", reply); - notify->post(); + if (mSkipRenderingUntilMediaTimeUs >= 0) { + if (timeUs < mSkipRenderingUntilMediaTimeUs) { + ALOGV("[%s] dropping buffer at time %lld as requested.", + mComponentName.c_str(), (long long)timeUs); - // FIXME: This should be handled after rendering is complete, - // but Renderer needs it now - if (flags & MediaCodec::BUFFER_FLAG_EOS) { - ALOGV("queueing eos [%s]", mComponentName.c_str()); - sp notify = mNotify->dup(); - notify->setInt32("what", kWhatEOS); - notify->setInt32("err", ERROR_END_OF_STREAM); - notify->post(); + reply->post(); + return true; + } + + mSkipRenderingUntilMediaTimeUs = -1; + } + + if (mRenderer != NULL) { + // send the buffer to renderer. + mRenderer->queueBuffer(!isVideo(), buffer, reply); + if (flags & MediaCodec::BUFFER_FLAG_EOS) { + mRenderer->queueEOS(!isVideo(), ERROR_END_OF_STREAM); + } } + return true; } @@ -508,6 +556,17 @@ void NuPlayer::Decoder::onRenderBuffer(const sp &msg) { int32_t render; size_t bufferIx; CHECK(msg->findSize("buffer-ix", &bufferIx)); + + if (isVideo()) { + int64_t timeUs; + sp buffer = mOutputBuffers[bufferIx]; + buffer->meta()->findInt64("timeUs", &timeUs); + sp notify = mNotify->dup(); + notify->setInt32("what", kWhatRenderBufferTime); + notify->setInt64("timeUs", timeUs); + notify->post(); + } + if (msg->findInt32("render", &render) && render) { int64_t timestampNs; CHECK(msg->findInt64("timestampNs", ×tampNs)); @@ -523,6 +582,10 @@ void NuPlayer::Decoder::onRenderBuffer(const sp &msg) { } void NuPlayer::Decoder::onFlush() { + if (mRenderer != NULL) { + mRenderer->flush(!isVideo()); + } + status_t err = OK; if (mCodec != NULL) { err = mCodec->flush(); @@ -594,6 +657,18 @@ void NuPlayer::Decoder::onMessageReceived(const sp &msg) { break; } + case kWhatSetRenderer: + { + bool hadNoRenderer = (mRenderer == NULL); + sp obj; + CHECK(msg->findObject("renderer", &obj)); + mRenderer = static_cast(obj.get()); + if (hadNoRenderer && mRenderer != NULL) { + requestCodecNotification(); + } + break; + } + case kWhatUpdateFormat: { sp format; @@ -772,6 +847,10 @@ bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp &targetF return seamless; } +bool NuPlayer::Decoder::isVideo() { + return mNativeWindow != NULL; +} + struct CCData { CCData(uint8_t type, uint8_t data1, uint8_t data2) : mType(type), mData1(data1), mData2(data2) { -- cgit v1.1