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;