xref: /aosp_15_r20/external/v4l2_codec2/components/VideoFramePool.cpp (revision 0ec5a0ec62797f775085659156625e7f1bdb369f)
1*0ec5a0ecSAndroid Build Coastguard Worker // Copyright 2020 The Chromium Authors. All rights reserved.
2*0ec5a0ecSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*0ec5a0ecSAndroid Build Coastguard Worker // found in the LICENSE file.
4*0ec5a0ecSAndroid Build Coastguard Worker 
5*0ec5a0ecSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
6*0ec5a0ecSAndroid Build Coastguard Worker #define LOG_TAG "VideoFramePool"
7*0ec5a0ecSAndroid Build Coastguard Worker 
8*0ec5a0ecSAndroid Build Coastguard Worker #include <v4l2_codec2/components/VideoFramePool.h>
9*0ec5a0ecSAndroid Build Coastguard Worker 
10*0ec5a0ecSAndroid Build Coastguard Worker #include <stdint.h>
11*0ec5a0ecSAndroid Build Coastguard Worker #include <memory>
12*0ec5a0ecSAndroid Build Coastguard Worker 
13*0ec5a0ecSAndroid Build Coastguard Worker #include <C2BlockInternal.h>
14*0ec5a0ecSAndroid Build Coastguard Worker #include <bufferpool/BufferPoolTypes.h>
15*0ec5a0ecSAndroid Build Coastguard Worker 
16*0ec5a0ecSAndroid Build Coastguard Worker #include <android/hardware/graphics/common/1.0/types.h>
17*0ec5a0ecSAndroid Build Coastguard Worker #include <base/bind.h>
18*0ec5a0ecSAndroid Build Coastguard Worker #include <base/memory/ptr_util.h>
19*0ec5a0ecSAndroid Build Coastguard Worker #include <base/time/time.h>
20*0ec5a0ecSAndroid Build Coastguard Worker #include <log/log.h>
21*0ec5a0ecSAndroid Build Coastguard Worker 
22*0ec5a0ecSAndroid Build Coastguard Worker #include <v4l2_codec2/common/VideoTypes.h>
23*0ec5a0ecSAndroid Build Coastguard Worker #include <v4l2_codec2/plugin_store/DmabufHelpers.h>
24*0ec5a0ecSAndroid Build Coastguard Worker #include <v4l2_codec2/plugin_store/V4L2AllocatorId.h>
25*0ec5a0ecSAndroid Build Coastguard Worker 
26*0ec5a0ecSAndroid Build Coastguard Worker using android::hardware::graphics::common::V1_0::BufferUsage;
27*0ec5a0ecSAndroid Build Coastguard Worker using android::hardware::media::bufferpool::BufferPoolData;
28*0ec5a0ecSAndroid Build Coastguard Worker 
29*0ec5a0ecSAndroid Build Coastguard Worker namespace android {
30*0ec5a0ecSAndroid Build Coastguard Worker 
31*0ec5a0ecSAndroid Build Coastguard Worker // static
getBufferIdFromGraphicBlock(C2BlockPool & blockPool,const C2Block2D & block)32*0ec5a0ecSAndroid Build Coastguard Worker std::optional<uint32_t> VideoFramePool::getBufferIdFromGraphicBlock(C2BlockPool& blockPool,
33*0ec5a0ecSAndroid Build Coastguard Worker                                                                     const C2Block2D& block) {
34*0ec5a0ecSAndroid Build Coastguard Worker     ALOGV("%s() blockPool.getAllocatorId() = %u", __func__, blockPool.getAllocatorId());
35*0ec5a0ecSAndroid Build Coastguard Worker 
36*0ec5a0ecSAndroid Build Coastguard Worker     switch (blockPool.getAllocatorId()) {
37*0ec5a0ecSAndroid Build Coastguard Worker     case V4L2AllocatorId::SECURE_GRAPHIC:
38*0ec5a0ecSAndroid Build Coastguard Worker         FALLTHROUGH;
39*0ec5a0ecSAndroid Build Coastguard Worker     case C2PlatformAllocatorStore::BUFFERQUEUE: {
40*0ec5a0ecSAndroid Build Coastguard Worker         auto dmabufId = android::getDmabufId(block.handle()->data[0]);
41*0ec5a0ecSAndroid Build Coastguard Worker         if (!dmabufId) {
42*0ec5a0ecSAndroid Build Coastguard Worker             return std::nullopt;
43*0ec5a0ecSAndroid Build Coastguard Worker         }
44*0ec5a0ecSAndroid Build Coastguard Worker         return dmabufId.value();
45*0ec5a0ecSAndroid Build Coastguard Worker     }
46*0ec5a0ecSAndroid Build Coastguard Worker     case C2PlatformAllocatorStore::GRALLOC:
47*0ec5a0ecSAndroid Build Coastguard Worker         FALLTHROUGH;
48*0ec5a0ecSAndroid Build Coastguard Worker     case V4L2AllocatorId::SECURE_LINEAR: {
49*0ec5a0ecSAndroid Build Coastguard Worker         std::shared_ptr<_C2BlockPoolData> blockPoolData =
50*0ec5a0ecSAndroid Build Coastguard Worker                 _C2BlockFactory::GetGraphicBlockPoolData(block);
51*0ec5a0ecSAndroid Build Coastguard Worker         if (blockPoolData->getType() != _C2BlockPoolData::TYPE_BUFFERPOOL) {
52*0ec5a0ecSAndroid Build Coastguard Worker             ALOGE("Obtained C2GraphicBlock is not bufferpool-backed.");
53*0ec5a0ecSAndroid Build Coastguard Worker             return std::nullopt;
54*0ec5a0ecSAndroid Build Coastguard Worker         }
55*0ec5a0ecSAndroid Build Coastguard Worker         std::shared_ptr<BufferPoolData> bpData;
56*0ec5a0ecSAndroid Build Coastguard Worker         if (!_C2BlockFactory::GetBufferPoolData(blockPoolData, &bpData) || !bpData) {
57*0ec5a0ecSAndroid Build Coastguard Worker             ALOGE("BufferPoolData unavailable in block.");
58*0ec5a0ecSAndroid Build Coastguard Worker             return std::nullopt;
59*0ec5a0ecSAndroid Build Coastguard Worker         }
60*0ec5a0ecSAndroid Build Coastguard Worker         return bpData->mId;
61*0ec5a0ecSAndroid Build Coastguard Worker     }
62*0ec5a0ecSAndroid Build Coastguard Worker     }
63*0ec5a0ecSAndroid Build Coastguard Worker 
64*0ec5a0ecSAndroid Build Coastguard Worker     ALOGE("%s(): unknown allocator ID: %u", __func__, blockPool.getAllocatorId());
65*0ec5a0ecSAndroid Build Coastguard Worker     return std::nullopt;
66*0ec5a0ecSAndroid Build Coastguard Worker }
67*0ec5a0ecSAndroid Build Coastguard Worker 
68*0ec5a0ecSAndroid Build Coastguard Worker // static
Create(std::shared_ptr<C2BlockPool> blockPool,const size_t numBuffers,const ui::Size & size,HalPixelFormat pixelFormat,bool isSecure,scoped_refptr<::base::SequencedTaskRunner> taskRunner)69*0ec5a0ecSAndroid Build Coastguard Worker std::unique_ptr<VideoFramePool> VideoFramePool::Create(
70*0ec5a0ecSAndroid Build Coastguard Worker         std::shared_ptr<C2BlockPool> blockPool, const size_t numBuffers, const ui::Size& size,
71*0ec5a0ecSAndroid Build Coastguard Worker         HalPixelFormat pixelFormat, bool isSecure,
72*0ec5a0ecSAndroid Build Coastguard Worker         scoped_refptr<::base::SequencedTaskRunner> taskRunner) {
73*0ec5a0ecSAndroid Build Coastguard Worker     ALOG_ASSERT(blockPool != nullptr);
74*0ec5a0ecSAndroid Build Coastguard Worker 
75*0ec5a0ecSAndroid Build Coastguard Worker     uint64_t usage = static_cast<uint64_t>(BufferUsage::VIDEO_DECODER);
76*0ec5a0ecSAndroid Build Coastguard Worker     if (isSecure) {
77*0ec5a0ecSAndroid Build Coastguard Worker         usage |= C2MemoryUsage::READ_PROTECTED;
78*0ec5a0ecSAndroid Build Coastguard Worker     } else if (blockPool->getAllocatorId() == C2PlatformAllocatorStore::GRALLOC) {
79*0ec5a0ecSAndroid Build Coastguard Worker         // CPU access to buffers is only required in byte buffer mode.
80*0ec5a0ecSAndroid Build Coastguard Worker         usage |= C2MemoryUsage::CPU_READ;
81*0ec5a0ecSAndroid Build Coastguard Worker     }
82*0ec5a0ecSAndroid Build Coastguard Worker     const C2MemoryUsage memoryUsage(usage);
83*0ec5a0ecSAndroid Build Coastguard Worker 
84*0ec5a0ecSAndroid Build Coastguard Worker     std::unique_ptr<VideoFramePool> pool =
85*0ec5a0ecSAndroid Build Coastguard Worker             ::base::WrapUnique(new VideoFramePool(std::move(blockPool), numBuffers, size,
86*0ec5a0ecSAndroid Build Coastguard Worker                                                   pixelFormat, memoryUsage, std::move(taskRunner)));
87*0ec5a0ecSAndroid Build Coastguard Worker     if (!pool->initialize()) return nullptr;
88*0ec5a0ecSAndroid Build Coastguard Worker     return pool;
89*0ec5a0ecSAndroid Build Coastguard Worker }
90*0ec5a0ecSAndroid Build Coastguard Worker 
VideoFramePool(std::shared_ptr<C2BlockPool> blockPool,const size_t maxBufferCount,const ui::Size & size,HalPixelFormat pixelFormat,C2MemoryUsage memoryUsage,scoped_refptr<::base::SequencedTaskRunner> taskRunner)91*0ec5a0ecSAndroid Build Coastguard Worker VideoFramePool::VideoFramePool(std::shared_ptr<C2BlockPool> blockPool, const size_t maxBufferCount,
92*0ec5a0ecSAndroid Build Coastguard Worker                                const ui::Size& size, HalPixelFormat pixelFormat,
93*0ec5a0ecSAndroid Build Coastguard Worker                                C2MemoryUsage memoryUsage,
94*0ec5a0ecSAndroid Build Coastguard Worker                                scoped_refptr<::base::SequencedTaskRunner> taskRunner)
95*0ec5a0ecSAndroid Build Coastguard Worker       : mBlockPool(std::move(blockPool)),
96*0ec5a0ecSAndroid Build Coastguard Worker         mMaxBufferCount(maxBufferCount),
97*0ec5a0ecSAndroid Build Coastguard Worker         mSize(size),
98*0ec5a0ecSAndroid Build Coastguard Worker         mPixelFormat(pixelFormat),
99*0ec5a0ecSAndroid Build Coastguard Worker         mMemoryUsage(memoryUsage),
100*0ec5a0ecSAndroid Build Coastguard Worker         mClientTaskRunner(std::move(taskRunner)) {
101*0ec5a0ecSAndroid Build Coastguard Worker     ALOGV("%s(size=%dx%d)", __func__, size.width, size.height);
102*0ec5a0ecSAndroid Build Coastguard Worker     ALOG_ASSERT(mClientTaskRunner->RunsTasksInCurrentSequence());
103*0ec5a0ecSAndroid Build Coastguard Worker     DCHECK(mBlockPool);
104*0ec5a0ecSAndroid Build Coastguard Worker     DCHECK(mClientTaskRunner);
105*0ec5a0ecSAndroid Build Coastguard Worker }
106*0ec5a0ecSAndroid Build Coastguard Worker 
initialize()107*0ec5a0ecSAndroid Build Coastguard Worker bool VideoFramePool::initialize() {
108*0ec5a0ecSAndroid Build Coastguard Worker     if (!mFetchThread.Start()) {
109*0ec5a0ecSAndroid Build Coastguard Worker         ALOGE("Fetch thread failed to start.");
110*0ec5a0ecSAndroid Build Coastguard Worker         return false;
111*0ec5a0ecSAndroid Build Coastguard Worker     }
112*0ec5a0ecSAndroid Build Coastguard Worker     mFetchTaskRunner = mFetchThread.task_runner();
113*0ec5a0ecSAndroid Build Coastguard Worker 
114*0ec5a0ecSAndroid Build Coastguard Worker     mClientWeakThis = mClientWeakThisFactory.GetWeakPtr();
115*0ec5a0ecSAndroid Build Coastguard Worker     mFetchWeakThis = mFetchWeakThisFactory.GetWeakPtr();
116*0ec5a0ecSAndroid Build Coastguard Worker 
117*0ec5a0ecSAndroid Build Coastguard Worker     return true;
118*0ec5a0ecSAndroid Build Coastguard Worker }
119*0ec5a0ecSAndroid Build Coastguard Worker 
~VideoFramePool()120*0ec5a0ecSAndroid Build Coastguard Worker VideoFramePool::~VideoFramePool() {
121*0ec5a0ecSAndroid Build Coastguard Worker     ALOGV("%s()", __func__);
122*0ec5a0ecSAndroid Build Coastguard Worker     ALOG_ASSERT(mClientTaskRunner->RunsTasksInCurrentSequence());
123*0ec5a0ecSAndroid Build Coastguard Worker 
124*0ec5a0ecSAndroid Build Coastguard Worker     mClientWeakThisFactory.InvalidateWeakPtrs();
125*0ec5a0ecSAndroid Build Coastguard Worker 
126*0ec5a0ecSAndroid Build Coastguard Worker     if (mFetchThread.IsRunning()) {
127*0ec5a0ecSAndroid Build Coastguard Worker         mFetchTaskRunner->PostTask(FROM_HERE,
128*0ec5a0ecSAndroid Build Coastguard Worker                                    ::base::BindOnce(&VideoFramePool::destroyTask, mFetchWeakThis));
129*0ec5a0ecSAndroid Build Coastguard Worker         mFetchThread.Stop();
130*0ec5a0ecSAndroid Build Coastguard Worker     }
131*0ec5a0ecSAndroid Build Coastguard Worker }
132*0ec5a0ecSAndroid Build Coastguard Worker 
destroyTask()133*0ec5a0ecSAndroid Build Coastguard Worker void VideoFramePool::destroyTask() {
134*0ec5a0ecSAndroid Build Coastguard Worker     ALOGV("%s()", __func__);
135*0ec5a0ecSAndroid Build Coastguard Worker     ALOG_ASSERT(mFetchTaskRunner->RunsTasksInCurrentSequence());
136*0ec5a0ecSAndroid Build Coastguard Worker 
137*0ec5a0ecSAndroid Build Coastguard Worker     mFetchWeakThisFactory.InvalidateWeakPtrs();
138*0ec5a0ecSAndroid Build Coastguard Worker }
139*0ec5a0ecSAndroid Build Coastguard Worker 
shouldDropBuffer(uint32_t bufferId)140*0ec5a0ecSAndroid Build Coastguard Worker bool VideoFramePool::shouldDropBuffer(uint32_t bufferId) {
141*0ec5a0ecSAndroid Build Coastguard Worker     if (mBuffers.size() < mMaxBufferCount) {
142*0ec5a0ecSAndroid Build Coastguard Worker         return false;
143*0ec5a0ecSAndroid Build Coastguard Worker     }
144*0ec5a0ecSAndroid Build Coastguard Worker 
145*0ec5a0ecSAndroid Build Coastguard Worker     if (mBuffers.find(bufferId) != mBuffers.end()) {
146*0ec5a0ecSAndroid Build Coastguard Worker         return false;
147*0ec5a0ecSAndroid Build Coastguard Worker     }
148*0ec5a0ecSAndroid Build Coastguard Worker 
149*0ec5a0ecSAndroid Build Coastguard Worker     return true;
150*0ec5a0ecSAndroid Build Coastguard Worker }
151*0ec5a0ecSAndroid Build Coastguard Worker 
getVideoFrame(GetVideoFrameCB cb)152*0ec5a0ecSAndroid Build Coastguard Worker bool VideoFramePool::getVideoFrame(GetVideoFrameCB cb) {
153*0ec5a0ecSAndroid Build Coastguard Worker     ALOGV("%s()", __func__);
154*0ec5a0ecSAndroid Build Coastguard Worker     ALOG_ASSERT(mClientTaskRunner->RunsTasksInCurrentSequence());
155*0ec5a0ecSAndroid Build Coastguard Worker 
156*0ec5a0ecSAndroid Build Coastguard Worker     if (mOutputCb) {
157*0ec5a0ecSAndroid Build Coastguard Worker         return false;
158*0ec5a0ecSAndroid Build Coastguard Worker     }
159*0ec5a0ecSAndroid Build Coastguard Worker 
160*0ec5a0ecSAndroid Build Coastguard Worker     mOutputCb = std::move(cb);
161*0ec5a0ecSAndroid Build Coastguard Worker     mFetchTaskRunner->PostTask(
162*0ec5a0ecSAndroid Build Coastguard Worker             FROM_HERE, ::base::BindOnce(&VideoFramePool::getVideoFrameTask, mFetchWeakThis));
163*0ec5a0ecSAndroid Build Coastguard Worker     return true;
164*0ec5a0ecSAndroid Build Coastguard Worker }
165*0ec5a0ecSAndroid Build Coastguard Worker 
166*0ec5a0ecSAndroid Build Coastguard Worker // static
getVideoFrameTaskThunk(scoped_refptr<::base::SequencedTaskRunner> taskRunner,std::optional<::base::WeakPtr<VideoFramePool>> weakPool)167*0ec5a0ecSAndroid Build Coastguard Worker void VideoFramePool::getVideoFrameTaskThunk(
168*0ec5a0ecSAndroid Build Coastguard Worker         scoped_refptr<::base::SequencedTaskRunner> taskRunner,
169*0ec5a0ecSAndroid Build Coastguard Worker         std::optional<::base::WeakPtr<VideoFramePool>> weakPool) {
170*0ec5a0ecSAndroid Build Coastguard Worker     ALOGV("%s()", __func__);
171*0ec5a0ecSAndroid Build Coastguard Worker     ALOG_ASSERT(weakPool);
172*0ec5a0ecSAndroid Build Coastguard Worker 
173*0ec5a0ecSAndroid Build Coastguard Worker     taskRunner->PostTask(FROM_HERE,
174*0ec5a0ecSAndroid Build Coastguard Worker                          ::base::BindOnce(&VideoFramePool::getVideoFrameTask, *weakPool));
175*0ec5a0ecSAndroid Build Coastguard Worker }
176*0ec5a0ecSAndroid Build Coastguard Worker 
getVideoFrameTask()177*0ec5a0ecSAndroid Build Coastguard Worker void VideoFramePool::getVideoFrameTask() {
178*0ec5a0ecSAndroid Build Coastguard Worker     ALOGV("%s()", __func__);
179*0ec5a0ecSAndroid Build Coastguard Worker     ALOG_ASSERT(mFetchTaskRunner->RunsTasksInCurrentSequence());
180*0ec5a0ecSAndroid Build Coastguard Worker 
181*0ec5a0ecSAndroid Build Coastguard Worker     // Variables used to exponential backoff retry when buffer fetching times out.
182*0ec5a0ecSAndroid Build Coastguard Worker     constexpr size_t kFetchRetryDelayInit = 256;   // Initial delay: 256us
183*0ec5a0ecSAndroid Build Coastguard Worker     constexpr size_t kFetchRetryDelayMax = 16384;  // Max delay: 16ms (1 frame at 60fps)
184*0ec5a0ecSAndroid Build Coastguard Worker     constexpr size_t kFenceWaitTimeoutNs = 16000000;  // 16ms (1 frame at 60fps)
185*0ec5a0ecSAndroid Build Coastguard Worker     static size_t sNumRetries = 0;
186*0ec5a0ecSAndroid Build Coastguard Worker     static size_t sDelay = kFetchRetryDelayInit;
187*0ec5a0ecSAndroid Build Coastguard Worker 
188*0ec5a0ecSAndroid Build Coastguard Worker     C2Fence fence;
189*0ec5a0ecSAndroid Build Coastguard Worker     std::shared_ptr<C2GraphicBlock> block;
190*0ec5a0ecSAndroid Build Coastguard Worker     c2_status_t err = mBlockPool->fetchGraphicBlock(mSize.width, mSize.height,
191*0ec5a0ecSAndroid Build Coastguard Worker                                                     static_cast<uint32_t>(mPixelFormat),
192*0ec5a0ecSAndroid Build Coastguard Worker                                                     mMemoryUsage, &block, &fence);
193*0ec5a0ecSAndroid Build Coastguard Worker     // C2_BLOCKING can be returned either based on the state of the block pool itself
194*0ec5a0ecSAndroid Build Coastguard Worker     // or the state of the underlying buffer queue. If the cause is the underlying
195*0ec5a0ecSAndroid Build Coastguard Worker     // buffer queue, then the block pool returns a null fence. Since a null fence is
196*0ec5a0ecSAndroid Build Coastguard Worker     // immediately ready, we need to delay instead of trying to wait on the fence, to
197*0ec5a0ecSAndroid Build Coastguard Worker     // avoid spinning.
198*0ec5a0ecSAndroid Build Coastguard Worker     //
199*0ec5a0ecSAndroid Build Coastguard Worker     // Unfortunately, a null fence is considered a valid fence, so the best we can do
200*0ec5a0ecSAndroid Build Coastguard Worker     // to detect a null fence is to assume that any fence that is immediately ready
201*0ec5a0ecSAndroid Build Coastguard Worker     // is the null fence. A false positive by racing with a real fence can result in
202*0ec5a0ecSAndroid Build Coastguard Worker     // an unnecessary delay, but the only alternative is to ignore fences altogether
203*0ec5a0ecSAndroid Build Coastguard Worker     // and always delay.
204*0ec5a0ecSAndroid Build Coastguard Worker     if (err == C2_BLOCKING && !fence.ready()) {
205*0ec5a0ecSAndroid Build Coastguard Worker         err = fence.wait(kFenceWaitTimeoutNs);
206*0ec5a0ecSAndroid Build Coastguard Worker         if (err == C2_OK) {
207*0ec5a0ecSAndroid Build Coastguard Worker             ALOGV("%s(): fence wait succeded, retrying now", __func__);
208*0ec5a0ecSAndroid Build Coastguard Worker             mFetchTaskRunner->PostTask(
209*0ec5a0ecSAndroid Build Coastguard Worker                     FROM_HERE,
210*0ec5a0ecSAndroid Build Coastguard Worker                     ::base::BindOnce(&VideoFramePool::getVideoFrameTask, mFetchWeakThis));
211*0ec5a0ecSAndroid Build Coastguard Worker             return;
212*0ec5a0ecSAndroid Build Coastguard Worker         }
213*0ec5a0ecSAndroid Build Coastguard Worker         ALOGV("%s(): fence wait unsucessful err=%d", __func__, err);
214*0ec5a0ecSAndroid Build Coastguard Worker     } else if (err == C2_OMITTED) {
215*0ec5a0ecSAndroid Build Coastguard Worker         // Fenced version is not supported, try legacy version.
216*0ec5a0ecSAndroid Build Coastguard Worker         err = mBlockPool->fetchGraphicBlock(mSize.width, mSize.height,
217*0ec5a0ecSAndroid Build Coastguard Worker                                             static_cast<uint32_t>(mPixelFormat), mMemoryUsage,
218*0ec5a0ecSAndroid Build Coastguard Worker                                             &block);
219*0ec5a0ecSAndroid Build Coastguard Worker     }
220*0ec5a0ecSAndroid Build Coastguard Worker 
221*0ec5a0ecSAndroid Build Coastguard Worker     std::optional<uint32_t> bufferId;
222*0ec5a0ecSAndroid Build Coastguard Worker     if (err == C2_OK) {
223*0ec5a0ecSAndroid Build Coastguard Worker         bufferId = getBufferIdFromGraphicBlock(*mBlockPool, *block);
224*0ec5a0ecSAndroid Build Coastguard Worker 
225*0ec5a0ecSAndroid Build Coastguard Worker         if (bufferId) {
226*0ec5a0ecSAndroid Build Coastguard Worker             ALOGV("%s(): Got buffer with id = %u", __func__, *bufferId);
227*0ec5a0ecSAndroid Build Coastguard Worker 
228*0ec5a0ecSAndroid Build Coastguard Worker             if (shouldDropBuffer(*bufferId)) {
229*0ec5a0ecSAndroid Build Coastguard Worker                 // We drop buffer, since we got more then needed.
230*0ec5a0ecSAndroid Build Coastguard Worker                 ALOGV("%s(): Dropping allocated buffer with id = %u", __func__, *bufferId);
231*0ec5a0ecSAndroid Build Coastguard Worker                 bufferId = std::nullopt;
232*0ec5a0ecSAndroid Build Coastguard Worker                 block.reset();
233*0ec5a0ecSAndroid Build Coastguard Worker                 err = C2_TIMED_OUT;
234*0ec5a0ecSAndroid Build Coastguard Worker             }
235*0ec5a0ecSAndroid Build Coastguard Worker         }
236*0ec5a0ecSAndroid Build Coastguard Worker     }
237*0ec5a0ecSAndroid Build Coastguard Worker 
238*0ec5a0ecSAndroid Build Coastguard Worker     if (err == C2_TIMED_OUT || err == C2_BLOCKING) {
239*0ec5a0ecSAndroid Build Coastguard Worker         ALOGV("%s(): fetchGraphicBlock() timeout, waiting %zuus (%zu retry)", __func__, sDelay,
240*0ec5a0ecSAndroid Build Coastguard Worker               sNumRetries + 1);
241*0ec5a0ecSAndroid Build Coastguard Worker         mFetchTaskRunner->PostDelayedTask(
242*0ec5a0ecSAndroid Build Coastguard Worker                 FROM_HERE, ::base::BindOnce(&VideoFramePool::getVideoFrameTask, mFetchWeakThis),
243*0ec5a0ecSAndroid Build Coastguard Worker                 ::base::TimeDelta::FromMicroseconds(sDelay));
244*0ec5a0ecSAndroid Build Coastguard Worker 
245*0ec5a0ecSAndroid Build Coastguard Worker         sDelay = std::min(sDelay * 4, kFetchRetryDelayMax);  // Exponential backoff
246*0ec5a0ecSAndroid Build Coastguard Worker         sNumRetries++;
247*0ec5a0ecSAndroid Build Coastguard Worker         return;
248*0ec5a0ecSAndroid Build Coastguard Worker     }
249*0ec5a0ecSAndroid Build Coastguard Worker 
250*0ec5a0ecSAndroid Build Coastguard Worker     // Reset to the default value.
251*0ec5a0ecSAndroid Build Coastguard Worker     sNumRetries = 0;
252*0ec5a0ecSAndroid Build Coastguard Worker     sDelay = kFetchRetryDelayInit;
253*0ec5a0ecSAndroid Build Coastguard Worker 
254*0ec5a0ecSAndroid Build Coastguard Worker     if (err != C2_OK) {
255*0ec5a0ecSAndroid Build Coastguard Worker         ALOGE("%s(): Failed to fetch block, err=%d", __func__, err);
256*0ec5a0ecSAndroid Build Coastguard Worker         return;
257*0ec5a0ecSAndroid Build Coastguard Worker     }
258*0ec5a0ecSAndroid Build Coastguard Worker 
259*0ec5a0ecSAndroid Build Coastguard Worker     ALOG_ASSERT(block != nullptr);
260*0ec5a0ecSAndroid Build Coastguard Worker     std::unique_ptr<VideoFrame> frame = VideoFrame::Create(std::move(block));
261*0ec5a0ecSAndroid Build Coastguard Worker     std::optional<FrameWithBlockId> frameWithBlockId;
262*0ec5a0ecSAndroid Build Coastguard Worker 
263*0ec5a0ecSAndroid Build Coastguard Worker     if (bufferId && frame) {
264*0ec5a0ecSAndroid Build Coastguard Worker         // Only pass the frame + id pair if both have successfully been obtained.
265*0ec5a0ecSAndroid Build Coastguard Worker         // Otherwise exit the loop so a nullopt is passed to the client.
266*0ec5a0ecSAndroid Build Coastguard Worker         frameWithBlockId = std::make_pair(std::move(frame), *bufferId);
267*0ec5a0ecSAndroid Build Coastguard Worker         mBuffers.insert(*bufferId);
268*0ec5a0ecSAndroid Build Coastguard Worker     } else {
269*0ec5a0ecSAndroid Build Coastguard Worker         ALOGE("%s(): Failed to generate VideoFrame or get the buffer id.", __func__);
270*0ec5a0ecSAndroid Build Coastguard Worker     }
271*0ec5a0ecSAndroid Build Coastguard Worker 
272*0ec5a0ecSAndroid Build Coastguard Worker     mClientTaskRunner->PostTask(
273*0ec5a0ecSAndroid Build Coastguard Worker             FROM_HERE, ::base::BindOnce(&VideoFramePool::onVideoFrameReady, mClientWeakThis,
274*0ec5a0ecSAndroid Build Coastguard Worker                                         std::move(frameWithBlockId)));
275*0ec5a0ecSAndroid Build Coastguard Worker }
276*0ec5a0ecSAndroid Build Coastguard Worker 
onVideoFrameReady(std::optional<FrameWithBlockId> frameWithBlockId)277*0ec5a0ecSAndroid Build Coastguard Worker void VideoFramePool::onVideoFrameReady(std::optional<FrameWithBlockId> frameWithBlockId) {
278*0ec5a0ecSAndroid Build Coastguard Worker     ALOGV("%s()", __func__);
279*0ec5a0ecSAndroid Build Coastguard Worker     ALOG_ASSERT(mClientTaskRunner->RunsTasksInCurrentSequence());
280*0ec5a0ecSAndroid Build Coastguard Worker 
281*0ec5a0ecSAndroid Build Coastguard Worker     if (!frameWithBlockId) {
282*0ec5a0ecSAndroid Build Coastguard Worker         ALOGE("Failed to get GraphicBlock, abandoning all pending requests.");
283*0ec5a0ecSAndroid Build Coastguard Worker         mClientWeakThisFactory.InvalidateWeakPtrs();
284*0ec5a0ecSAndroid Build Coastguard Worker         mClientWeakThis = mClientWeakThisFactory.GetWeakPtr();
285*0ec5a0ecSAndroid Build Coastguard Worker     }
286*0ec5a0ecSAndroid Build Coastguard Worker 
287*0ec5a0ecSAndroid Build Coastguard Worker     ALOG_ASSERT(mOutputCb);
288*0ec5a0ecSAndroid Build Coastguard Worker     std::move(mOutputCb).Run(std::move(frameWithBlockId));
289*0ec5a0ecSAndroid Build Coastguard Worker }
290*0ec5a0ecSAndroid Build Coastguard Worker 
291*0ec5a0ecSAndroid Build Coastguard Worker }  // namespace android
292