CCodec: Move qpOffsetMap from param list to info buffers

Bug: 325549730
Bug: 299191092
Test: Build

Change-Id: Ie03a3df03c7232889d0dbc662c5eaa223e125896
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 5396d25..463b63f 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1424,7 +1424,7 @@
                     if (!msg->contains(PARAMETER_KEY_QP_OFFSET_MAP) &&
                         !msg->contains(PARAMETER_KEY_QP_OFFSET_RECTS)) {
                         msg->setString(PARAMETER_KEY_QP_OFFSET_RECTS,
-                                       AStringPrintf("%d,%d-%d,%d=%d;", 0, 0, 16, 16, 0));
+                                       AStringPrintf("%d,%d-%d,%d=%d;", 0, 0, height, width, 0));
                     }
                 }
             }
@@ -2553,6 +2553,40 @@
         }
     }
 
+    /**
+     * Handle ROI QP map configuration. Recover the QP map configuration from AMessage as an
+     * ABuffer and configure to CCodecBufferChannel as a C2InfoBuffer
+     */
+    if (android::media::codec::provider_->region_of_interest()
+            && android::media::codec::provider_->region_of_interest_support()) {
+        sp<ABuffer> qpOffsetMap;
+        if ((config->mDomain & (Config::IS_VIDEO | Config::IS_IMAGE))
+                && (config->mDomain & Config::IS_ENCODER)
+                &&  params->findBuffer(PARAMETER_KEY_QP_OFFSET_MAP, &qpOffsetMap)) {
+            std::shared_ptr<C2BlockPool> pool;
+            // TODO(b/331443865) Use pooled block pool to improve efficiency
+            c2_status_t status = GetCodec2BlockPool(C2BlockPool::BASIC_LINEAR, nullptr, &pool);
+
+            if (status == C2_OK) {
+                size_t mapSize = qpOffsetMap->size();
+                std::shared_ptr<C2LinearBlock> block;
+                status = pool->fetchLinearBlock(mapSize,
+                        C2MemoryUsage{C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block);
+                if (status == C2_OK && !block->map().get().error()) {
+                    C2WriteView wView = block->map().get();
+                    uint8_t* outData = wView.data();
+                    memcpy(outData, qpOffsetMap->data(), mapSize);
+                    C2InfoBuffer info = C2InfoBuffer::CreateLinearBuffer(
+                            kParamIndexQpOffsetMapBuffer,
+                            block->share(0, mapSize, C2Fence()));
+                    mChannel->setInfoBuffer(std::make_shared<C2InfoBuffer>(info));
+                }
+            }
+            params->removeEntryByName(PARAMETER_KEY_QP_OFFSET_MAP);
+        }
+    }
+
+
     std::vector<std::unique_ptr<C2Param>> configUpdate;
     (void)config->getConfigUpdateFromSdkParams(
             comp, params, Config::IS_PARAM, C2_MAY_BLOCK, &configUpdate);
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index f58dc65..3984b83 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -28,6 +28,8 @@
 #include <thread>
 #include <chrono>
 
+#include <android_media_codec.h>
+
 #include <C2AllocatorGralloc.h>
 #include <C2PlatformSupport.h>
 #include <C2BlockInternal.h>
@@ -370,7 +372,17 @@
         }
     } else {
         work->input.flags = (C2FrameData::flags_t)flags;
+
         // TODO: fill info's
+        if (android::media::codec::provider_->region_of_interest()
+                && android::media::codec::provider_->region_of_interest_support()) {
+            if (mInfoBuffers.size()) {
+                for (auto infoBuffer : mInfoBuffers) {
+                    work->input.infoBuffers.emplace_back(*infoBuffer);
+                }
+                mInfoBuffers.clear();
+            }
+        }
 
         work->input.configUpdate = std::move(mParamsToBeSet);
         if (tunnelFirstFrame) {
@@ -2058,6 +2070,7 @@
 void CCodecBufferChannel::stop() {
     mSync.stop();
     mFirstValidFrameIndex = mFrameIndex.load(std::memory_order_relaxed);
+    mInfoBuffers.clear();
 }
 
 void CCodecBufferChannel::stopUseOutputSurface(bool pushBlankBuffer) {
@@ -2099,6 +2112,7 @@
 }
 
 void CCodecBufferChannel::release() {
+    mInfoBuffers.clear();
     mComponent.reset();
     mInputAllocator.reset();
     mOutputSurface.lock()->surface.clear();
@@ -2164,6 +2178,7 @@
             output->buffers->flushStash();
         }
     }
+    mInfoBuffers.clear();
 }
 
 void CCodecBufferChannel::onWorkDone(
@@ -2768,6 +2783,10 @@
     }
 }
 
+void CCodecBufferChannel::setInfoBuffer(const std::shared_ptr<C2InfoBuffer> &buffer) {
+    mInfoBuffers.push_back(buffer);
+}
+
 status_t toStatusT(c2_status_t c2s, c2_operation_t c2op) {
     // C2_OK is always translated to OK.
     if (c2s == C2_OK) {
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h
index b470655..94a5998 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.h
+++ b/media/codec2/sfplugin/CCodecBufferChannel.h
@@ -227,6 +227,14 @@
 
     void resetBuffersPixelFormat(bool isEncoder);
 
+    /**
+     * Queue a C2 info buffer that will be sent to codec in the subsequent
+     * queueInputBuffer
+     *
+     * @param buffer C2 info buffer
+     */
+    void setInfoBuffer(const std::shared_ptr<C2InfoBuffer> &buffer);
+
 private:
     uint32_t getInputBuffersPixelFormat();
 
@@ -400,6 +408,8 @@
     std::atomic_bool mSendEncryptedInfoBuffer;
 
     std::atomic_bool mTunneled;
+
+    std::vector<std::shared_ptr<C2InfoBuffer>> mInfoBuffers;
 };
 
 // Conversion of a c2_status_t value to a status_t value may depend on the