From add5343beb09f23bc0265cd717794240ad63304a Mon Sep 17 00:00:00 2001
From: Tao Wu <lepton@google.com>
Date: Mon, 27 Feb 2023 19:18:43 -0800
Subject: [PATCH] V4L2EncodeComponent: force sync gpu buffer

Android encoder framework reuses the same gpu buffers as
inputs and doesn't call lock/unlock explicitly between writes.
If there is format conversion, this is fine since we will
read back what we've written first and then put it in another
buffer. Whenever there is no format conversion, this causes
sync issue on ARCVM since host side buffers never get updated.
Fix this by explicitly calling lock/unlock before sending buffer
to encoder.

Bug: 268317650
Test: atest com.google.android.media.gts.RtcVideoCodecTest#testDynamicBitrateChangeVp8
Change-Id: Ia1750aa37c2d879ddff0301814e489974f218f5c
---
 components/V4L2EncodeComponent.cpp | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/components/V4L2EncodeComponent.cpp b/components/V4L2EncodeComponent.cpp
index f9d735d..da61217 100644
--- a/components/V4L2EncodeComponent.cpp
+++ b/components/V4L2EncodeComponent.cpp
@@ -517,6 +517,27 @@ void V4L2EncodeComponent::queueTask(std::unique_ptr<C2Work> work) {
                 reportError(status);
                 return;
             }
+        } else {
+            // Android encoder framework reuses the same gpu buffers as
+            // inputs and doesn't call lock/unlock explicitly between writes.
+            // If there is format conversion, this is fine since we will
+            // read back what we've written first and then put it in another
+            // buffer. Whenever there is no format conversion, this causes
+            // sync issue on ARCVM since host side buffers never get updated.
+            // Fix this by explicitly calling lock/unlock before sending buffer
+            // to encoder.
+            const C2Handle* handle = inputBlock.handle();
+            uint32_t width, height, format, stride, generation, igbpSlot;
+            uint64_t usage, igbpId;
+            _UnwrapNativeCodec2GrallocMetadata(handle, &width, &height, &format, &usage, &stride,
+                                               &generation, &igbpId, &igbpSlot);
+            native_handle_t* gralloc_handle = UnwrapNativeCodec2GrallocHandle(handle);
+            sp<GraphicBuffer> buffer =
+                    new GraphicBuffer(gralloc_handle, GraphicBuffer::CLONE_HANDLE, width, height,
+                                      format, 1, usage, stride);
+            void* pixels;
+            buffer->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, &pixels);
+            buffer->unlock();
         }
         if (!encode(inputBlock, index, timestamp)) {
             return;
-- 
GitLab