blob: c2f68fc04f7eebb80c1adb0e853d476d922cddfd [file] [log] [blame]
Chih-Yu Huang6a7255a2020-03-25 17:01:47 +09001// Copyright 2020 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//#define LOG_NDEBUG 0
6#define LOG_TAG "VideoFramePool"
7
8#include <v4l2_codec2/components/VideoFramePool.h>
9
10#include <stdint.h>
11#include <memory>
12
13#include <android/hardware/graphics/common/1.0/types.h>
14#include <base/bind.h>
15#include <base/time/time.h>
16#include <log/log.h>
17
18#include <v4l2_codec2/components/VideoTypes.h>
19
20using android::hardware::graphics::common::V1_0::BufferUsage;
21
22namespace android {
23namespace {
24constexpr size_t kAllocateBufferMaxRetries = 32;
25constexpr size_t kFetchRetryDelayUs = 500;
26} // namespace
27
28VideoFramePool::VideoFramePool(std::shared_ptr<C2BlockPool> blockPool, const media::Size& size,
29 HalPixelFormat pixelFormat, bool isSecure,
30 scoped_refptr<::base::SequencedTaskRunner> taskRunner)
31 : mBlockPool(std::move(blockPool)),
32 mSize(size),
33 mPixelFormat(pixelFormat),
34 mMemoryUsage(isSecure ? C2MemoryUsage::READ_PROTECTED : C2MemoryUsage::CPU_READ,
35 static_cast<uint64_t>(BufferUsage::VIDEO_DECODER)),
36 mTaskRunner(std::move(taskRunner)) {
37 ALOGV("%s()", __func__);
38 ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
39 DCHECK(mBlockPool);
40 DCHECK(mTaskRunner);
41
42 mWeakThis = mWeakThisFactory.GetWeakPtr();
43}
44
45VideoFramePool::~VideoFramePool() {
46 ALOGV("%s()", __func__);
47 ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
48
49 mWeakThisFactory.InvalidateWeakPtrs();
50}
51
52void VideoFramePool::getVideoFrame(GetVideoFrameCB cb) {
53 ALOGV("%s()", __func__);
54 ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
55
56 bool isRunning = !mCbQueue.empty();
57 mCbQueue.push(std::move(cb));
58 if (!isRunning) tryFetchGraphicBlock();
59}
60
61bool VideoFramePool::hasPendingRequests() const {
62 return !mCbQueue.empty();
63}
64
65void VideoFramePool::tryFetchGraphicBlock() {
66 ALOGV("%s()", __func__);
67 ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
68
69 if (mCbQueue.empty()) return;
70
71 std::shared_ptr<C2GraphicBlock> block;
72 auto err = mBlockPool->fetchGraphicBlock(mSize.width(), mSize.height(),
73 static_cast<uint32_t>(mPixelFormat), mMemoryUsage,
74 &block);
75
76 if ((err == C2_TIMED_OUT || err == C2_BLOCKING) && mNumRetries++ < kAllocateBufferMaxRetries) {
77 ALOGD("fetchGraphicBlock() timeout. retry %zu times", mNumRetries);
78 mTaskRunner->PostDelayedTask(
79 FROM_HERE, ::base::BindOnce(&VideoFramePool::tryFetchGraphicBlock, mWeakThis),
80 ::base::TimeDelta::FromMicroseconds(kFetchRetryDelayUs));
81 } else if (err != C2_OK) {
82 ALOGE("Failed to fetch block, err=%d, retry %zu times", err, mNumRetries);
83 sendVideoFrame(nullptr);
84 } else {
85 mNumRetries = 0;
86 sendVideoFrame(VideoFrame::Create(std::move(block)));
87
88 if (!mCbQueue.empty()) {
89 mTaskRunner->PostTask(
90 FROM_HERE, ::base::BindOnce(&VideoFramePool::tryFetchGraphicBlock, mWeakThis));
91 }
92 }
93}
94
95void VideoFramePool::sendVideoFrame(std::unique_ptr<VideoFrame> frame) {
96 ALOGV("%s()", __func__);
97 ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
98 ALOG_ASSERT(!mCbQueue.empty());
99
100 auto cb = std::move(mCbQueue.front());
101 mCbQueue.pop();
102 std::move(cb).Run(std::move(frame));
103}
104
105} // namespace android