MediaCodec: add renderAndReleaseOutputBuffer() method with timestamp

Bug: 11784827
Change-Id: Ia1dcbd6c1d1a4380db04b750c0eb3fa0bd58d7b4
diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h
index 276543b..39e57de 100644
--- a/include/media/stagefright/MediaCodec.h
+++ b/include/media/stagefright/MediaCodec.h
@@ -100,6 +100,7 @@
             uint32_t *flags,
             int64_t timeoutUs = 0ll);
 
+    status_t renderOutputBufferAndRelease(size_t index, int64_t timestampNs);
     status_t renderOutputBufferAndRelease(size_t index);
     status_t releaseOutputBuffer(size_t index);
 
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 537d9de..0a3a3b6 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -3670,7 +3670,28 @@
         ATRACE_NAME("render");
         // The client wants this buffer to be rendered.
 
+        int64_t timestampNs = 0;
+        if (!msg->findInt64("timestampNs", &timestampNs)) {
+            // TODO: it seems like we should use the timestamp
+            // in the (media)buffer as it potentially came from
+            // an input surface, but we did not propagate it prior to
+            // API 20.  Perhaps check for target SDK version.
+#if 0
+            if (info->mData->meta()->findInt64("timeUs", &timestampNs)) {
+                ALOGI("using buffer PTS of %" PRId64, timestampNs);
+                timestampNs *= 1000;
+            }
+#endif
+        }
+
         status_t err;
+        err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs);
+        if (err != OK) {
+            ALOGW("failed to set buffer timestamp: %d", err);
+        } else {
+            ALOGI("set PTS to %" PRId64, timestampNs);
+        }
+
         if ((err = mCodec->mNativeWindow->queueBuffer(
                     mCodec->mNativeWindow.get(),
                     info->mGraphicBuffer.get(), -1)) == OK) {
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 601dccf..5b525f2 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -17,6 +17,7 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "MediaCodec"
 #include <utils/Log.h>
+#include <inttypes.h>
 
 #include <media/stagefright/MediaCodec.h>
 
@@ -323,6 +324,16 @@
     return PostAndAwaitResponse(msg, &response);
 }
 
+status_t MediaCodec::renderOutputBufferAndRelease(size_t index, int64_t timestampNs) {
+    sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
+    msg->setSize("index", index);
+    msg->setInt32("render", true);
+    msg->setInt64("timestampNs", timestampNs);
+
+    sp<AMessage> response;
+    return PostAndAwaitResponse(msg, &response);
+}
+
 status_t MediaCodec::releaseOutputBuffer(size_t index) {
     sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
     msg->setSize("index", index);
@@ -1707,9 +1718,25 @@
     if (render && info->mData != NULL && info->mData->size() != 0) {
         info->mNotify->setInt32("render", true);
 
+        int64_t timestampNs = 0;
+        if (msg->findInt64("timestampNs", &timestampNs)) {
+            info->mNotify->setInt64("timestampNs", timestampNs);
+        } else {
+            // TODO: it seems like we should use the timestamp
+            // in the (media)buffer as it potentially came from
+            // an input surface, but we did not propagate it prior to
+            // API 20.  Perhaps check for target SDK version.
+#if 0
+            if (info->mData->meta()->findInt64("timeUs", &timestampNs)) {
+                ALOGI("using buffer PTS of %" PRId64, timestampNs);
+                timestampNs *= 1000;
+            }
+#endif
+        }
+
         if (mSoftRenderer != NULL) {
             mSoftRenderer->render(
-                    info->mData->data(), info->mData->size(), NULL);
+                    info->mData->data(), info->mData->size(), timestampNs, NULL);
         }
     }