diff --git a/components/VideoFramePool.cpp b/components/VideoFramePool.cpp index 05e22a625cf935031214c844b083c2c6fc705745..c8ea84267c9bd98eb37ca761e29f880ec01d5fb1 100644 --- a/components/VideoFramePool.cpp +++ b/components/VideoFramePool.cpp @@ -91,16 +91,19 @@ std::unique_ptr<VideoFramePool> VideoFramePool::Create( 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 @@ void VideoFramePool::destroyTask() { 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 @@ void VideoFramePool::getVideoFrameTask() { &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 @@ void VideoFramePool::getVideoFrameTask() { 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 2978eed036c72b2892f52e0872af5e7254b339ca..4e1537e434971438473a10d7413ca79887d07bb5 100644 --- a/components/include/v4l2_codec2/components/VideoFramePool.h +++ b/components/include/v4l2_codec2/components/VideoFramePool.h @@ -44,12 +44,13 @@ public: 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 @@ private: 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 @@ private: 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;