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