NuPlayer: tunnel decoder with renderer for data buffer passing.

Bug: 18342383

Change-Id: I182928007814c146c01a86196c4fda1d46e74ea4
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 <media/ICrypto.h>
 #include <media/stagefright/foundation/ABitReader.h>
 #include <media/stagefright/foundation/ABuffer.h>
@@ -35,9 +38,14 @@
 
 NuPlayer::Decoder::Decoder(
         const sp<AMessage> &notify,
+        const sp<Source> &source,
+        const sp<Renderer> &renderer,
         const sp<NativeWindowWrapper> &nativeWindow)
     : mNotify(notify),
       mNativeWindow(nativeWindow),
+      mSource(source),
+      mRenderer(renderer),
+      mSkipRenderingUntilMediaTimeUs(-1ll),
       mBufferGeneration(0),
       mPaused(true),
       mComponentName("decoder") {
@@ -169,7 +177,9 @@
             mInputBuffers.size(),
             mOutputBuffers.size());
 
-    requestCodecNotification();
+    if (mRenderer != NULL) {
+        requestCodecNotification();
+    }
     mPaused = false;
 }
 
@@ -191,6 +201,7 @@
     }
 
     mPendingInputMessages.clear();
+    mSkipRenderingUntilMediaTimeUs = -1;
 }
 
 void NuPlayer::Decoder::requestCodecNotification() {
@@ -217,6 +228,12 @@
     msg->post();
 }
 
+void NuPlayer::Decoder::setRenderer(const sp<Renderer> &renderer) {
+    sp<AMessage> msg = new AMessage(kWhatSetRenderer, id());
+    msg->setObject("renderer", renderer);
+    msg->post();
+}
+
 void NuPlayer::Decoder::signalUpdateFormat(const sp<AMessage> &format) {
     sp<AMessage> msg = new AMessage(kWhatUpdateFormat, id());
     msg->setMessage("format", format);
@@ -342,8 +359,6 @@
         }
     }
 
-
-
     if (buffer == NULL /* includes !hasBuffer */) {
         int32_t streamErr = ERROR_END_OF_STREAM;
         CHECK(msg->findInt32("err", &streamErr) || !hasBuffer);
@@ -375,6 +390,17 @@
             handleError(streamErr);
         }
     } else {
+        sp<AMessage> 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 @@
             return false;
         }
 
-        sp<AMessage> notify = mNotify->dup();
-        notify->setInt32("what", kWhatOutputFormatChanged);
-        notify->setMessage("format", format);
-        notify->post();
+        if (isVideo()) {
+            sp<AMessage> 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 @@
     reply->setSize("buffer-ix", bufferIx);
     reply->setInt32("generation", mBufferGeneration);
 
-    sp<AMessage> 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<AMessage> 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 @@
     int32_t render;
     size_t bufferIx;
     CHECK(msg->findSize("buffer-ix", &bufferIx));
+
+    if (isVideo()) {
+        int64_t timeUs;
+        sp<ABuffer> buffer = mOutputBuffers[bufferIx];
+        buffer->meta()->findInt64("timeUs", &timeUs);
+        sp<AMessage> 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", &timestampNs));
@@ -523,6 +582,10 @@
 }
 
 void NuPlayer::Decoder::onFlush() {
+    if (mRenderer != NULL) {
+        mRenderer->flush(!isVideo());
+    }
+
     status_t err = OK;
     if (mCodec != NULL) {
         err = mCodec->flush();
@@ -594,6 +657,18 @@
             break;
         }
 
+        case kWhatSetRenderer:
+        {
+            bool hadNoRenderer = (mRenderer == NULL);
+            sp<RefBase> obj;
+            CHECK(msg->findObject("renderer", &obj));
+            mRenderer = static_cast<Renderer *>(obj.get());
+            if (hadNoRenderer && mRenderer != NULL) {
+                requestCodecNotification();
+            }
+            break;
+        }
+
         case kWhatUpdateFormat:
         {
             sp<AMessage> format;
@@ -772,6 +847,10 @@
     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) {