VideoFramePool: limit the number of provided buffers

This CL moves limitation logic from C2VdaPooledBufferPool to
VideoFramePool. This will allow removal of C2VdaPooledBufferPool.

Bug: 268301611
Bug: 268305422
Bug: 270329448
Bug: 238710012
Bug: 238390060
Bug: 270331759
Bug: 238709912
Test: CtsMediaCodecTestCases
Test: CtsMediaDecoderTestCases
Test: CtsMediaV2TestCases
Test: GtsExoPlayerTestCases com.google.android.exoplayer.gts.CommonEncryptionDrmTest#cencSchemeTypeV*
Change-Id: I78abfdbcda6f9b3de2a6d5bcfd705a7028490f9b
(cherry picked from commit b9a66dedb0c92d411e7d5f6b2199934f6664eaba)
diff --git a/components/VideoFramePool.cpp b/components/VideoFramePool.cpp
index 05e22a6..c8ea842 100644
--- a/components/VideoFramePool.cpp
+++ b/components/VideoFramePool.cpp
@@ -91,16 +91,19 @@
         return nullptr;
     }
 
-    std::unique_ptr<VideoFramePool> pool = ::base::WrapUnique(new VideoFramePool(
-            std::move(blockPool), size, pixelFormat, memoryUsage, std::move(taskRunner)));
+    std::unique_ptr<VideoFramePool> pool =
+            ::base::WrapUnique(new VideoFramePool(std::move(blockPool), numBuffers, size,
+                                                  pixelFormat, memoryUsage, std::move(taskRunner)));
     if (!pool->initialize()) return nullptr;
     return pool;
 }
 
-VideoFramePool::VideoFramePool(std::shared_ptr<C2BlockPool> blockPool, const ui::Size& size,
-                               HalPixelFormat pixelFormat, C2MemoryUsage memoryUsage,
+VideoFramePool::VideoFramePool(std::shared_ptr<C2BlockPool> blockPool, const size_t maxBufferCount,
+                               const ui::Size& size, HalPixelFormat pixelFormat,
+                               C2MemoryUsage memoryUsage,
                                scoped_refptr<::base::SequencedTaskRunner> taskRunner)
       : mBlockPool(std::move(blockPool)),
+        mMaxBufferCount(maxBufferCount),
         mSize(size),
         mPixelFormat(pixelFormat),
         mMemoryUsage(memoryUsage),
@@ -144,6 +147,18 @@
     mFetchWeakThisFactory.InvalidateWeakPtrs();
 }
 
+bool VideoFramePool::shouldDropBuffer(uint32_t bufferId) {
+    if (mBuffers.size() < mMaxBufferCount) {
+        return false;
+    }
+
+    if (mBuffers.find(bufferId) != mBuffers.end()) {
+        return false;
+    }
+
+    return true;
+}
+
 bool VideoFramePool::getVideoFrame(GetVideoFrameCB cb) {
     ALOGV("%s()", __func__);
     ALOG_ASSERT(mClientTaskRunner->RunsTasksInCurrentSequence());
@@ -202,6 +217,23 @@
                                             &block);
     }
 
+    std::optional<uint32_t> bufferId;
+    if (err == C2_OK) {
+        bufferId = getBufferIdFromGraphicBlock(*mBlockPool, *block);
+
+        if (bufferId) {
+            ALOGV("%s(): Got buffer with id = %u", __func__, *bufferId);
+
+            if (shouldDropBuffer(*bufferId)) {
+                // We drop buffer, since we got more then needed.
+                ALOGV("%s(): Dropping allocated buffer with id = %u", __func__, *bufferId);
+                bufferId = std::nullopt;
+                block.reset();
+                err = C2_TIMED_OUT;
+            }
+        }
+    }
+
     if (err == C2_TIMED_OUT || err == C2_BLOCKING) {
         ALOGV("%s(): fetchGraphicBlock() timeout, waiting %zuus (%zu retry)", __func__, sDelay,
               sNumRetries + 1);
@@ -226,18 +258,12 @@
     ALOG_ASSERT(block != nullptr);
     std::unique_ptr<VideoFrame> frame = VideoFrame::Create(std::move(block));
     std::optional<FrameWithBlockId> frameWithBlockId;
-    std::optional<uint32_t> bufferId;
 
     if (bufferId && frame) {
-        bufferId = getBufferIdFromGraphicBlock(*mBlockPool, *block);
-
-        if (bufferId) {
-            ALOGV("%s(): Got buffer with id = %u", __func__, *bufferId);
-        }
-
         // Only pass the frame + id pair if both have successfully been obtained.
         // Otherwise exit the loop so a nullopt is passed to the client.
         frameWithBlockId = std::make_pair(std::move(frame), *bufferId);
+        mBuffers.insert(*bufferId);
     } else {
         ALOGE("%s(): Failed to generate VideoFrame or get the buffer id.", __func__);
     }
diff --git a/components/include/v4l2_codec2/components/VideoFramePool.h b/components/include/v4l2_codec2/components/VideoFramePool.h
index 2978eed..4e1537e 100644
--- a/components/include/v4l2_codec2/components/VideoFramePool.h
+++ b/components/include/v4l2_codec2/components/VideoFramePool.h
@@ -44,12 +44,13 @@
 
 private:
     // |blockPool| is the C2BlockPool that we fetch graphic blocks from.
+    // |maxBufferCount| maximum number of buffer that should should provide to client
     // |size| is the resolution size of the required graphic blocks.
     // |pixelFormat| is the pixel format of the required graphic blocks.
     // |isSecure| indicates the video stream is encrypted or not.
     // All public methods and the callbacks should be run on |taskRunner|.
-    VideoFramePool(std::shared_ptr<C2BlockPool> blockPool, const ui::Size& size,
-                   HalPixelFormat pixelFormat, C2MemoryUsage memoryUsage,
+    VideoFramePool(std::shared_ptr<C2BlockPool> blockPool, const size_t maxBufferCount,
+                   const ui::Size& size, HalPixelFormat pixelFormat, C2MemoryUsage memoryUsage,
                    scoped_refptr<::base::SequencedTaskRunner> taskRunner);
     bool initialize();
     void destroyTask();
@@ -59,6 +60,9 @@
     void getVideoFrameTask();
     void onVideoFrameReady(std::optional<FrameWithBlockId> frameWithBlockId);
 
+    // Returns true if a buffer shall not be handed to client.
+    bool shouldDropBuffer(uint32_t bufferId);
+
     // Ask |blockPool| to allocate the specified number of buffers.
     // |bufferCount| is the number of requested buffers.
     static c2_status_t requestNewBufferSet(C2BlockPool& blockPool, int32_t bufferCount,
@@ -73,6 +77,13 @@
     static bool setNotifyBlockAvailableCb(C2BlockPool& blockPool, ::base::OnceClosure cb);
 
     std::shared_ptr<C2BlockPool> mBlockPool;
+
+    // Holds the number of maximum amount of buffers that VideoFramePool
+    // should provide to client.
+    size_t mMaxBufferCount;
+    // Contains known buffer ids that are valid for the pool.
+    std::set<uint32_t> mBuffers;
+
     const ui::Size mSize;
     const HalPixelFormat mPixelFormat;
     const C2MemoryUsage mMemoryUsage;