1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright 2024, The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker *
4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker *
8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker *
10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker */
16*ec779b8eSAndroid Build Coastguard Worker
17*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
18*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "C2NodeImpl"
19*ec779b8eSAndroid Build Coastguard Worker #include <log/log.h>
20*ec779b8eSAndroid Build Coastguard Worker
21*ec779b8eSAndroid Build Coastguard Worker #include <C2AllocatorGralloc.h>
22*ec779b8eSAndroid Build Coastguard Worker #include <C2BlockInternal.h>
23*ec779b8eSAndroid Build Coastguard Worker #include <C2Component.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <C2Config.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <C2Debug.h>
26*ec779b8eSAndroid Build Coastguard Worker #include <C2PlatformSupport.h>
27*ec779b8eSAndroid Build Coastguard Worker
28*ec779b8eSAndroid Build Coastguard Worker #include <android_media_codec.h>
29*ec779b8eSAndroid Build Coastguard Worker #include <android/fdsan.h>
30*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ColorUtils.h>
31*ec779b8eSAndroid Build Coastguard Worker #include <ui/Fence.h>
32*ec779b8eSAndroid Build Coastguard Worker #include <ui/GraphicBuffer.h>
33*ec779b8eSAndroid Build Coastguard Worker #include <utils/Errors.h>
34*ec779b8eSAndroid Build Coastguard Worker #include <utils/Thread.h>
35*ec779b8eSAndroid Build Coastguard Worker
36*ec779b8eSAndroid Build Coastguard Worker #include "utils/Codec2Mapper.h"
37*ec779b8eSAndroid Build Coastguard Worker #include "C2NodeImpl.h"
38*ec779b8eSAndroid Build Coastguard Worker #include "Codec2Buffer.h"
39*ec779b8eSAndroid Build Coastguard Worker
40*ec779b8eSAndroid Build Coastguard Worker namespace android {
41*ec779b8eSAndroid Build Coastguard Worker
42*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::media::IAidlBufferSource;
43*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::media::IAidlNode;
44*ec779b8eSAndroid Build Coastguard Worker
45*ec779b8eSAndroid Build Coastguard Worker using ::android::media::BUFFERFLAG_EOS;
46*ec779b8eSAndroid Build Coastguard Worker
47*ec779b8eSAndroid Build Coastguard Worker namespace {
48*ec779b8eSAndroid Build Coastguard Worker
49*ec779b8eSAndroid Build Coastguard Worker class Buffer2D : public C2Buffer {
50*ec779b8eSAndroid Build Coastguard Worker public:
Buffer2D(C2ConstGraphicBlock block)51*ec779b8eSAndroid Build Coastguard Worker explicit Buffer2D(C2ConstGraphicBlock block) : C2Buffer({ block }) {}
52*ec779b8eSAndroid Build Coastguard Worker };
53*ec779b8eSAndroid Build Coastguard Worker
54*ec779b8eSAndroid Build Coastguard Worker } // namespace
55*ec779b8eSAndroid Build Coastguard Worker
56*ec779b8eSAndroid Build Coastguard Worker class C2NodeImpl::QueueThread : public Thread {
57*ec779b8eSAndroid Build Coastguard Worker public:
QueueThread()58*ec779b8eSAndroid Build Coastguard Worker QueueThread() : Thread(false) {}
59*ec779b8eSAndroid Build Coastguard Worker ~QueueThread() override = default;
queue(const std::shared_ptr<Codec2Client::Component> & comp,int fenceFd,std::unique_ptr<C2Work> && work,android::base::unique_fd && fd0,android::base::unique_fd && fd1)60*ec779b8eSAndroid Build Coastguard Worker void queue(
61*ec779b8eSAndroid Build Coastguard Worker const std::shared_ptr<Codec2Client::Component> &comp,
62*ec779b8eSAndroid Build Coastguard Worker int fenceFd,
63*ec779b8eSAndroid Build Coastguard Worker std::unique_ptr<C2Work> &&work,
64*ec779b8eSAndroid Build Coastguard Worker android::base::unique_fd &&fd0,
65*ec779b8eSAndroid Build Coastguard Worker android::base::unique_fd &&fd1) {
66*ec779b8eSAndroid Build Coastguard Worker Mutexed<Jobs>::Locked jobs(mJobs);
67*ec779b8eSAndroid Build Coastguard Worker auto it = jobs->queues.try_emplace(comp, comp).first;
68*ec779b8eSAndroid Build Coastguard Worker it->second.workList.emplace_back(
69*ec779b8eSAndroid Build Coastguard Worker std::move(work), fenceFd, std::move(fd0), std::move(fd1));
70*ec779b8eSAndroid Build Coastguard Worker jobs->cond.broadcast();
71*ec779b8eSAndroid Build Coastguard Worker }
72*ec779b8eSAndroid Build Coastguard Worker
setDataspace(android_dataspace dataspace)73*ec779b8eSAndroid Build Coastguard Worker void setDataspace(android_dataspace dataspace) {
74*ec779b8eSAndroid Build Coastguard Worker Mutexed<Jobs>::Locked jobs(mJobs);
75*ec779b8eSAndroid Build Coastguard Worker ColorUtils::convertDataSpaceToV0(dataspace);
76*ec779b8eSAndroid Build Coastguard Worker jobs->configUpdate.emplace_back(new C2StreamDataSpaceInfo::input(0u, dataspace));
77*ec779b8eSAndroid Build Coastguard Worker int32_t standard;
78*ec779b8eSAndroid Build Coastguard Worker int32_t transfer;
79*ec779b8eSAndroid Build Coastguard Worker int32_t range;
80*ec779b8eSAndroid Build Coastguard Worker ColorUtils::getColorConfigFromDataSpace(dataspace, &range, &standard, &transfer);
81*ec779b8eSAndroid Build Coastguard Worker std::unique_ptr<C2StreamColorAspectsInfo::input> colorAspects =
82*ec779b8eSAndroid Build Coastguard Worker std::make_unique<C2StreamColorAspectsInfo::input>(0u);
83*ec779b8eSAndroid Build Coastguard Worker if (C2Mapper::map(standard, &colorAspects->primaries, &colorAspects->matrix)
84*ec779b8eSAndroid Build Coastguard Worker && C2Mapper::map(transfer, &colorAspects->transfer)
85*ec779b8eSAndroid Build Coastguard Worker && C2Mapper::map(range, &colorAspects->range)) {
86*ec779b8eSAndroid Build Coastguard Worker jobs->configUpdate.push_back(std::move(colorAspects));
87*ec779b8eSAndroid Build Coastguard Worker }
88*ec779b8eSAndroid Build Coastguard Worker }
89*ec779b8eSAndroid Build Coastguard Worker
setPriority(int priority)90*ec779b8eSAndroid Build Coastguard Worker void setPriority(int priority) {
91*ec779b8eSAndroid Build Coastguard Worker androidSetThreadPriority(getTid(), priority);
92*ec779b8eSAndroid Build Coastguard Worker }
93*ec779b8eSAndroid Build Coastguard Worker
94*ec779b8eSAndroid Build Coastguard Worker protected:
threadLoop()95*ec779b8eSAndroid Build Coastguard Worker bool threadLoop() override {
96*ec779b8eSAndroid Build Coastguard Worker constexpr nsecs_t kIntervalNs = nsecs_t(10) * 1000 * 1000; // 10ms
97*ec779b8eSAndroid Build Coastguard Worker constexpr nsecs_t kWaitNs = kIntervalNs * 2;
98*ec779b8eSAndroid Build Coastguard Worker for (int i = 0; i < 2; ++i) {
99*ec779b8eSAndroid Build Coastguard Worker Mutexed<Jobs>::Locked jobs(mJobs);
100*ec779b8eSAndroid Build Coastguard Worker nsecs_t nowNs = systemTime();
101*ec779b8eSAndroid Build Coastguard Worker bool queued = false;
102*ec779b8eSAndroid Build Coastguard Worker for (auto it = jobs->queues.begin(); it != jobs->queues.end(); ) {
103*ec779b8eSAndroid Build Coastguard Worker Queue &queue = it->second;
104*ec779b8eSAndroid Build Coastguard Worker if (queue.workList.empty()
105*ec779b8eSAndroid Build Coastguard Worker || (queue.lastQueuedTimestampNs != 0 &&
106*ec779b8eSAndroid Build Coastguard Worker nowNs - queue.lastQueuedTimestampNs < kIntervalNs)) {
107*ec779b8eSAndroid Build Coastguard Worker ++it;
108*ec779b8eSAndroid Build Coastguard Worker continue;
109*ec779b8eSAndroid Build Coastguard Worker }
110*ec779b8eSAndroid Build Coastguard Worker std::shared_ptr<Codec2Client::Component> comp = queue.component.lock();
111*ec779b8eSAndroid Build Coastguard Worker if (!comp) {
112*ec779b8eSAndroid Build Coastguard Worker it = jobs->queues.erase(it);
113*ec779b8eSAndroid Build Coastguard Worker continue;
114*ec779b8eSAndroid Build Coastguard Worker }
115*ec779b8eSAndroid Build Coastguard Worker std::list<std::unique_ptr<C2Work>> items;
116*ec779b8eSAndroid Build Coastguard Worker std::vector<int> fenceFds;
117*ec779b8eSAndroid Build Coastguard Worker std::vector<android::base::unique_fd> uniqueFds;
118*ec779b8eSAndroid Build Coastguard Worker while (!queue.workList.empty()) {
119*ec779b8eSAndroid Build Coastguard Worker items.push_back(std::move(queue.workList.front().work));
120*ec779b8eSAndroid Build Coastguard Worker fenceFds.push_back(queue.workList.front().fenceFd);
121*ec779b8eSAndroid Build Coastguard Worker uniqueFds.push_back(std::move(queue.workList.front().fd0));
122*ec779b8eSAndroid Build Coastguard Worker uniqueFds.push_back(std::move(queue.workList.front().fd1));
123*ec779b8eSAndroid Build Coastguard Worker queue.workList.pop_front();
124*ec779b8eSAndroid Build Coastguard Worker }
125*ec779b8eSAndroid Build Coastguard Worker for (const std::unique_ptr<C2Param> ¶m : jobs->configUpdate) {
126*ec779b8eSAndroid Build Coastguard Worker items.front()->input.configUpdate.emplace_back(C2Param::Copy(*param));
127*ec779b8eSAndroid Build Coastguard Worker }
128*ec779b8eSAndroid Build Coastguard Worker
129*ec779b8eSAndroid Build Coastguard Worker jobs.unlock();
130*ec779b8eSAndroid Build Coastguard Worker for (int fenceFd : fenceFds) {
131*ec779b8eSAndroid Build Coastguard Worker sp<Fence> fence(new Fence(fenceFd));
132*ec779b8eSAndroid Build Coastguard Worker fence->waitForever(LOG_TAG);
133*ec779b8eSAndroid Build Coastguard Worker }
134*ec779b8eSAndroid Build Coastguard Worker queue.lastQueuedTimestampNs = nowNs;
135*ec779b8eSAndroid Build Coastguard Worker comp->queue(&items);
136*ec779b8eSAndroid Build Coastguard Worker for (android::base::unique_fd &ufd : uniqueFds) {
137*ec779b8eSAndroid Build Coastguard Worker (void)ufd.release();
138*ec779b8eSAndroid Build Coastguard Worker }
139*ec779b8eSAndroid Build Coastguard Worker jobs.lock();
140*ec779b8eSAndroid Build Coastguard Worker
141*ec779b8eSAndroid Build Coastguard Worker it = jobs->queues.upper_bound(comp);
142*ec779b8eSAndroid Build Coastguard Worker queued = true;
143*ec779b8eSAndroid Build Coastguard Worker }
144*ec779b8eSAndroid Build Coastguard Worker if (queued) {
145*ec779b8eSAndroid Build Coastguard Worker jobs->configUpdate.clear();
146*ec779b8eSAndroid Build Coastguard Worker return true;
147*ec779b8eSAndroid Build Coastguard Worker }
148*ec779b8eSAndroid Build Coastguard Worker if (i == 0) {
149*ec779b8eSAndroid Build Coastguard Worker jobs.waitForConditionRelative(jobs->cond, kWaitNs);
150*ec779b8eSAndroid Build Coastguard Worker }
151*ec779b8eSAndroid Build Coastguard Worker }
152*ec779b8eSAndroid Build Coastguard Worker return true;
153*ec779b8eSAndroid Build Coastguard Worker }
154*ec779b8eSAndroid Build Coastguard Worker
155*ec779b8eSAndroid Build Coastguard Worker private:
156*ec779b8eSAndroid Build Coastguard Worker struct WorkFence {
WorkFenceandroid::C2NodeImpl::QueueThread::WorkFence157*ec779b8eSAndroid Build Coastguard Worker WorkFence(std::unique_ptr<C2Work> &&w, int fd) : work(std::move(w)), fenceFd(fd) {}
158*ec779b8eSAndroid Build Coastguard Worker
WorkFenceandroid::C2NodeImpl::QueueThread::WorkFence159*ec779b8eSAndroid Build Coastguard Worker WorkFence(
160*ec779b8eSAndroid Build Coastguard Worker std::unique_ptr<C2Work> &&w,
161*ec779b8eSAndroid Build Coastguard Worker int fd,
162*ec779b8eSAndroid Build Coastguard Worker android::base::unique_fd &&uniqueFd0,
163*ec779b8eSAndroid Build Coastguard Worker android::base::unique_fd &&uniqueFd1)
164*ec779b8eSAndroid Build Coastguard Worker : work(std::move(w)),
165*ec779b8eSAndroid Build Coastguard Worker fenceFd(fd),
166*ec779b8eSAndroid Build Coastguard Worker fd0(std::move(uniqueFd0)),
167*ec779b8eSAndroid Build Coastguard Worker fd1(std::move(uniqueFd1)) {}
168*ec779b8eSAndroid Build Coastguard Worker
169*ec779b8eSAndroid Build Coastguard Worker std::unique_ptr<C2Work> work;
170*ec779b8eSAndroid Build Coastguard Worker int fenceFd;
171*ec779b8eSAndroid Build Coastguard Worker android::base::unique_fd fd0;
172*ec779b8eSAndroid Build Coastguard Worker android::base::unique_fd fd1;
173*ec779b8eSAndroid Build Coastguard Worker };
174*ec779b8eSAndroid Build Coastguard Worker struct Queue {
Queueandroid::C2NodeImpl::QueueThread::Queue175*ec779b8eSAndroid Build Coastguard Worker Queue(const std::shared_ptr<Codec2Client::Component> &comp)
176*ec779b8eSAndroid Build Coastguard Worker : component(comp), lastQueuedTimestampNs(0) {}
177*ec779b8eSAndroid Build Coastguard Worker Queue(const Queue &) = delete;
178*ec779b8eSAndroid Build Coastguard Worker Queue &operator =(const Queue &) = delete;
179*ec779b8eSAndroid Build Coastguard Worker
180*ec779b8eSAndroid Build Coastguard Worker std::weak_ptr<Codec2Client::Component> component;
181*ec779b8eSAndroid Build Coastguard Worker std::list<WorkFence> workList;
182*ec779b8eSAndroid Build Coastguard Worker nsecs_t lastQueuedTimestampNs;
183*ec779b8eSAndroid Build Coastguard Worker };
184*ec779b8eSAndroid Build Coastguard Worker struct Jobs {
185*ec779b8eSAndroid Build Coastguard Worker std::map<std::weak_ptr<Codec2Client::Component>,
186*ec779b8eSAndroid Build Coastguard Worker Queue,
187*ec779b8eSAndroid Build Coastguard Worker std::owner_less<std::weak_ptr<Codec2Client::Component>>> queues;
188*ec779b8eSAndroid Build Coastguard Worker std::vector<std::unique_ptr<C2Param>> configUpdate;
189*ec779b8eSAndroid Build Coastguard Worker Condition cond;
190*ec779b8eSAndroid Build Coastguard Worker };
191*ec779b8eSAndroid Build Coastguard Worker Mutexed<Jobs> mJobs;
192*ec779b8eSAndroid Build Coastguard Worker };
193*ec779b8eSAndroid Build Coastguard Worker
C2NodeImpl(const std::shared_ptr<Codec2Client::Component> & comp,bool aidl)194*ec779b8eSAndroid Build Coastguard Worker C2NodeImpl::C2NodeImpl(const std::shared_ptr<Codec2Client::Component> &comp, bool aidl)
195*ec779b8eSAndroid Build Coastguard Worker : mComp(comp), mFrameIndex(0), mWidth(0), mHeight(0), mUsage(0),
196*ec779b8eSAndroid Build Coastguard Worker mAdjustTimestampGapUs(0), mFirstInputFrame(true),
197*ec779b8eSAndroid Build Coastguard Worker mQueueThread(new QueueThread), mAidlHal(aidl) {
198*ec779b8eSAndroid Build Coastguard Worker android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ALWAYS);
199*ec779b8eSAndroid Build Coastguard Worker mQueueThread->run("C2NodeImpl", PRIORITY_AUDIO);
200*ec779b8eSAndroid Build Coastguard Worker
201*ec779b8eSAndroid Build Coastguard Worker android_dataspace ds = HAL_DATASPACE_UNKNOWN;
202*ec779b8eSAndroid Build Coastguard Worker mDataspace.lock().set(ds);
203*ec779b8eSAndroid Build Coastguard Worker uint32_t pf = PIXEL_FORMAT_UNKNOWN;
204*ec779b8eSAndroid Build Coastguard Worker mPixelFormat.lock().set(pf);
205*ec779b8eSAndroid Build Coastguard Worker }
206*ec779b8eSAndroid Build Coastguard Worker
~C2NodeImpl()207*ec779b8eSAndroid Build Coastguard Worker C2NodeImpl::~C2NodeImpl() {
208*ec779b8eSAndroid Build Coastguard Worker }
209*ec779b8eSAndroid Build Coastguard Worker
freeNode()210*ec779b8eSAndroid Build Coastguard Worker status_t C2NodeImpl::freeNode() {
211*ec779b8eSAndroid Build Coastguard Worker mComp.reset();
212*ec779b8eSAndroid Build Coastguard Worker android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE);
213*ec779b8eSAndroid Build Coastguard Worker return mQueueThread->requestExitAndWait();
214*ec779b8eSAndroid Build Coastguard Worker }
215*ec779b8eSAndroid Build Coastguard Worker
onFirstInputFrame()216*ec779b8eSAndroid Build Coastguard Worker void C2NodeImpl::onFirstInputFrame() {
217*ec779b8eSAndroid Build Coastguard Worker mFirstInputFrame = true;
218*ec779b8eSAndroid Build Coastguard Worker }
219*ec779b8eSAndroid Build Coastguard Worker
getConsumerUsageBits(uint64_t * usage)220*ec779b8eSAndroid Build Coastguard Worker void C2NodeImpl::getConsumerUsageBits(uint64_t *usage) {
221*ec779b8eSAndroid Build Coastguard Worker *usage = mUsage;
222*ec779b8eSAndroid Build Coastguard Worker }
223*ec779b8eSAndroid Build Coastguard Worker
getInputBufferParams(IAidlNode::InputBufferParams * params)224*ec779b8eSAndroid Build Coastguard Worker void C2NodeImpl::getInputBufferParams(IAidlNode::InputBufferParams *params) {
225*ec779b8eSAndroid Build Coastguard Worker params->bufferCountActual = 16;
226*ec779b8eSAndroid Build Coastguard Worker
227*ec779b8eSAndroid Build Coastguard Worker // WORKAROUND: having more slots improve performance while consuming
228*ec779b8eSAndroid Build Coastguard Worker // more memory. This is a temporary workaround to reduce memory for
229*ec779b8eSAndroid Build Coastguard Worker // larger-than-4K scenario.
230*ec779b8eSAndroid Build Coastguard Worker if (mWidth * mHeight > 4096 * 2340) {
231*ec779b8eSAndroid Build Coastguard Worker std::shared_ptr<Codec2Client::Component> comp = mComp.lock();
232*ec779b8eSAndroid Build Coastguard Worker C2PortActualDelayTuning::input inputDelay(0);
233*ec779b8eSAndroid Build Coastguard Worker C2ActualPipelineDelayTuning pipelineDelay(0);
234*ec779b8eSAndroid Build Coastguard Worker c2_status_t c2err = C2_NOT_FOUND;
235*ec779b8eSAndroid Build Coastguard Worker if (comp) {
236*ec779b8eSAndroid Build Coastguard Worker c2err = comp->query(
237*ec779b8eSAndroid Build Coastguard Worker {&inputDelay, &pipelineDelay}, {}, C2_DONT_BLOCK, nullptr);
238*ec779b8eSAndroid Build Coastguard Worker }
239*ec779b8eSAndroid Build Coastguard Worker if (c2err == C2_OK || c2err == C2_BAD_INDEX) {
240*ec779b8eSAndroid Build Coastguard Worker params->bufferCountActual = 4;
241*ec779b8eSAndroid Build Coastguard Worker params->bufferCountActual += (inputDelay ? inputDelay.value : 0u);
242*ec779b8eSAndroid Build Coastguard Worker params->bufferCountActual += (pipelineDelay ? pipelineDelay.value : 0u);
243*ec779b8eSAndroid Build Coastguard Worker }
244*ec779b8eSAndroid Build Coastguard Worker }
245*ec779b8eSAndroid Build Coastguard Worker
246*ec779b8eSAndroid Build Coastguard Worker params->frameWidth = mWidth;
247*ec779b8eSAndroid Build Coastguard Worker params->frameHeight = mHeight;
248*ec779b8eSAndroid Build Coastguard Worker }
249*ec779b8eSAndroid Build Coastguard Worker
setConsumerUsageBits(uint64_t usage)250*ec779b8eSAndroid Build Coastguard Worker void C2NodeImpl::setConsumerUsageBits(uint64_t usage) {
251*ec779b8eSAndroid Build Coastguard Worker mUsage = usage;
252*ec779b8eSAndroid Build Coastguard Worker }
253*ec779b8eSAndroid Build Coastguard Worker
setAdjustTimestampGapUs(int32_t gapUs)254*ec779b8eSAndroid Build Coastguard Worker void C2NodeImpl::setAdjustTimestampGapUs(int32_t gapUs) {
255*ec779b8eSAndroid Build Coastguard Worker mAdjustTimestampGapUs = gapUs;
256*ec779b8eSAndroid Build Coastguard Worker }
257*ec779b8eSAndroid Build Coastguard Worker
setInputSurface(const sp<IOMXBufferSource> & bufferSource)258*ec779b8eSAndroid Build Coastguard Worker status_t C2NodeImpl::setInputSurface(const sp<IOMXBufferSource> &bufferSource) {
259*ec779b8eSAndroid Build Coastguard Worker c2_status_t err = GetCodec2PlatformAllocatorStore()->fetchAllocator(
260*ec779b8eSAndroid Build Coastguard Worker C2PlatformAllocatorStore::GRALLOC,
261*ec779b8eSAndroid Build Coastguard Worker &mAllocator);
262*ec779b8eSAndroid Build Coastguard Worker if (err != OK) {
263*ec779b8eSAndroid Build Coastguard Worker return UNKNOWN_ERROR;
264*ec779b8eSAndroid Build Coastguard Worker }
265*ec779b8eSAndroid Build Coastguard Worker CHECK(!mAidlHal);
266*ec779b8eSAndroid Build Coastguard Worker mBufferSource = bufferSource;
267*ec779b8eSAndroid Build Coastguard Worker return OK;
268*ec779b8eSAndroid Build Coastguard Worker }
269*ec779b8eSAndroid Build Coastguard Worker
setAidlInputSurface(const std::shared_ptr<IAidlBufferSource> & aidlBufferSource)270*ec779b8eSAndroid Build Coastguard Worker status_t C2NodeImpl::setAidlInputSurface(
271*ec779b8eSAndroid Build Coastguard Worker const std::shared_ptr<IAidlBufferSource> &aidlBufferSource) {
272*ec779b8eSAndroid Build Coastguard Worker c2_status_t err = GetCodec2PlatformAllocatorStore()->fetchAllocator(
273*ec779b8eSAndroid Build Coastguard Worker C2PlatformAllocatorStore::GRALLOC,
274*ec779b8eSAndroid Build Coastguard Worker &mAllocator);
275*ec779b8eSAndroid Build Coastguard Worker if (err != OK) {
276*ec779b8eSAndroid Build Coastguard Worker return UNKNOWN_ERROR;
277*ec779b8eSAndroid Build Coastguard Worker }
278*ec779b8eSAndroid Build Coastguard Worker CHECK(mAidlHal);
279*ec779b8eSAndroid Build Coastguard Worker mAidlBufferSource = aidlBufferSource;
280*ec779b8eSAndroid Build Coastguard Worker return OK;
281*ec779b8eSAndroid Build Coastguard Worker }
282*ec779b8eSAndroid Build Coastguard Worker
submitBuffer(uint32_t buffer,const sp<GraphicBuffer> & graphicBuffer,uint32_t flags,int64_t timestamp,int fenceFd)283*ec779b8eSAndroid Build Coastguard Worker status_t C2NodeImpl::submitBuffer(
284*ec779b8eSAndroid Build Coastguard Worker uint32_t buffer, const sp<GraphicBuffer> &graphicBuffer,
285*ec779b8eSAndroid Build Coastguard Worker uint32_t flags, int64_t timestamp, int fenceFd) {
286*ec779b8eSAndroid Build Coastguard Worker std::shared_ptr<Codec2Client::Component> comp = mComp.lock();
287*ec779b8eSAndroid Build Coastguard Worker if (!comp) {
288*ec779b8eSAndroid Build Coastguard Worker return NO_INIT;
289*ec779b8eSAndroid Build Coastguard Worker }
290*ec779b8eSAndroid Build Coastguard Worker
291*ec779b8eSAndroid Build Coastguard Worker uint32_t c2Flags = (flags & BUFFERFLAG_EOS)
292*ec779b8eSAndroid Build Coastguard Worker ? C2FrameData::FLAG_END_OF_STREAM : 0;
293*ec779b8eSAndroid Build Coastguard Worker std::shared_ptr<C2GraphicBlock> block;
294*ec779b8eSAndroid Build Coastguard Worker
295*ec779b8eSAndroid Build Coastguard Worker android::base::unique_fd fd0, fd1;
296*ec779b8eSAndroid Build Coastguard Worker C2Handle *handle = nullptr;
297*ec779b8eSAndroid Build Coastguard Worker if (graphicBuffer) {
298*ec779b8eSAndroid Build Coastguard Worker std::shared_ptr<C2GraphicAllocation> alloc;
299*ec779b8eSAndroid Build Coastguard Worker handle = WrapNativeCodec2GrallocHandle(
300*ec779b8eSAndroid Build Coastguard Worker graphicBuffer->handle,
301*ec779b8eSAndroid Build Coastguard Worker graphicBuffer->width,
302*ec779b8eSAndroid Build Coastguard Worker graphicBuffer->height,
303*ec779b8eSAndroid Build Coastguard Worker graphicBuffer->format,
304*ec779b8eSAndroid Build Coastguard Worker graphicBuffer->usage,
305*ec779b8eSAndroid Build Coastguard Worker graphicBuffer->stride);
306*ec779b8eSAndroid Build Coastguard Worker if (handle != nullptr) {
307*ec779b8eSAndroid Build Coastguard Worker // unique_fd takes ownership of the fds, we'll get warning if these
308*ec779b8eSAndroid Build Coastguard Worker // fds get closed by somebody else. Onwership will be released before
309*ec779b8eSAndroid Build Coastguard Worker // we return, so that the fds get closed as usually when this function
310*ec779b8eSAndroid Build Coastguard Worker // goes out of scope (when both items and block are gone).
311*ec779b8eSAndroid Build Coastguard Worker native_handle_t *nativeHandle = reinterpret_cast<native_handle_t*>(handle);
312*ec779b8eSAndroid Build Coastguard Worker fd0.reset(nativeHandle->numFds > 0 ? nativeHandle->data[0] : -1);
313*ec779b8eSAndroid Build Coastguard Worker fd1.reset(nativeHandle->numFds > 1 ? nativeHandle->data[1] : -1);
314*ec779b8eSAndroid Build Coastguard Worker }
315*ec779b8eSAndroid Build Coastguard Worker c2_status_t err = mAllocator->priorGraphicAllocation(handle, &alloc);
316*ec779b8eSAndroid Build Coastguard Worker if (err != OK) {
317*ec779b8eSAndroid Build Coastguard Worker (void)fd0.release();
318*ec779b8eSAndroid Build Coastguard Worker (void)fd1.release();
319*ec779b8eSAndroid Build Coastguard Worker native_handle_close(handle);
320*ec779b8eSAndroid Build Coastguard Worker native_handle_delete(handle);
321*ec779b8eSAndroid Build Coastguard Worker return UNKNOWN_ERROR;
322*ec779b8eSAndroid Build Coastguard Worker }
323*ec779b8eSAndroid Build Coastguard Worker block = _C2BlockFactory::CreateGraphicBlock(alloc);
324*ec779b8eSAndroid Build Coastguard Worker } else if (!(flags & BUFFERFLAG_EOS)) {
325*ec779b8eSAndroid Build Coastguard Worker return BAD_VALUE;
326*ec779b8eSAndroid Build Coastguard Worker }
327*ec779b8eSAndroid Build Coastguard Worker
328*ec779b8eSAndroid Build Coastguard Worker std::unique_ptr<C2Work> work(new C2Work);
329*ec779b8eSAndroid Build Coastguard Worker work->input.flags = (C2FrameData::flags_t)c2Flags;
330*ec779b8eSAndroid Build Coastguard Worker work->input.ordinal.timestamp = timestamp;
331*ec779b8eSAndroid Build Coastguard Worker
332*ec779b8eSAndroid Build Coastguard Worker // WORKAROUND: adjust timestamp based on gapUs
333*ec779b8eSAndroid Build Coastguard Worker {
334*ec779b8eSAndroid Build Coastguard Worker work->input.ordinal.customOrdinal = timestamp; // save input timestamp
335*ec779b8eSAndroid Build Coastguard Worker if (mFirstInputFrame) {
336*ec779b8eSAndroid Build Coastguard Worker // grab timestamps on first frame
337*ec779b8eSAndroid Build Coastguard Worker mPrevInputTimestamp = timestamp;
338*ec779b8eSAndroid Build Coastguard Worker mPrevCodecTimestamp = timestamp;
339*ec779b8eSAndroid Build Coastguard Worker mFirstInputFrame = false;
340*ec779b8eSAndroid Build Coastguard Worker } else if (mAdjustTimestampGapUs > 0) {
341*ec779b8eSAndroid Build Coastguard Worker work->input.ordinal.timestamp =
342*ec779b8eSAndroid Build Coastguard Worker mPrevCodecTimestamp
343*ec779b8eSAndroid Build Coastguard Worker + c2_min((timestamp - mPrevInputTimestamp).peek(), mAdjustTimestampGapUs);
344*ec779b8eSAndroid Build Coastguard Worker } else if (mAdjustTimestampGapUs < 0) {
345*ec779b8eSAndroid Build Coastguard Worker work->input.ordinal.timestamp = mPrevCodecTimestamp - mAdjustTimestampGapUs;
346*ec779b8eSAndroid Build Coastguard Worker }
347*ec779b8eSAndroid Build Coastguard Worker mPrevInputTimestamp = work->input.ordinal.customOrdinal;
348*ec779b8eSAndroid Build Coastguard Worker mPrevCodecTimestamp = work->input.ordinal.timestamp;
349*ec779b8eSAndroid Build Coastguard Worker ALOGV("adjusting %lld to %lld (gap=%lld)",
350*ec779b8eSAndroid Build Coastguard Worker work->input.ordinal.customOrdinal.peekll(),
351*ec779b8eSAndroid Build Coastguard Worker work->input.ordinal.timestamp.peekll(),
352*ec779b8eSAndroid Build Coastguard Worker (long long)mAdjustTimestampGapUs);
353*ec779b8eSAndroid Build Coastguard Worker }
354*ec779b8eSAndroid Build Coastguard Worker
355*ec779b8eSAndroid Build Coastguard Worker work->input.ordinal.frameIndex = mFrameIndex++;
356*ec779b8eSAndroid Build Coastguard Worker work->input.buffers.clear();
357*ec779b8eSAndroid Build Coastguard Worker if (block) {
358*ec779b8eSAndroid Build Coastguard Worker std::shared_ptr<C2Buffer> c2Buffer(
359*ec779b8eSAndroid Build Coastguard Worker new Buffer2D(block->share(
360*ec779b8eSAndroid Build Coastguard Worker C2Rect(block->width(), block->height()), ::C2Fence())));
361*ec779b8eSAndroid Build Coastguard Worker work->input.buffers.push_back(c2Buffer);
362*ec779b8eSAndroid Build Coastguard Worker std::shared_ptr<C2StreamHdrStaticInfo::input> staticInfo;
363*ec779b8eSAndroid Build Coastguard Worker std::shared_ptr<C2StreamHdrDynamicMetadataInfo::input> dynamicInfo;
364*ec779b8eSAndroid Build Coastguard Worker GetHdrMetadataFromGralloc4Handle(
365*ec779b8eSAndroid Build Coastguard Worker block->handle(),
366*ec779b8eSAndroid Build Coastguard Worker &staticInfo,
367*ec779b8eSAndroid Build Coastguard Worker &dynamicInfo);
368*ec779b8eSAndroid Build Coastguard Worker if (staticInfo && *staticInfo) {
369*ec779b8eSAndroid Build Coastguard Worker c2Buffer->setInfo(staticInfo);
370*ec779b8eSAndroid Build Coastguard Worker }
371*ec779b8eSAndroid Build Coastguard Worker if (dynamicInfo && *dynamicInfo) {
372*ec779b8eSAndroid Build Coastguard Worker c2Buffer->setInfo(dynamicInfo);
373*ec779b8eSAndroid Build Coastguard Worker }
374*ec779b8eSAndroid Build Coastguard Worker }
375*ec779b8eSAndroid Build Coastguard Worker work->worklets.clear();
376*ec779b8eSAndroid Build Coastguard Worker work->worklets.emplace_back(new C2Worklet);
377*ec779b8eSAndroid Build Coastguard Worker {
378*ec779b8eSAndroid Build Coastguard Worker Mutexed<BuffersTracker>::Locked buffers(mBuffersTracker);
379*ec779b8eSAndroid Build Coastguard Worker buffers->mIdsInUse.emplace(work->input.ordinal.frameIndex.peeku(), buffer);
380*ec779b8eSAndroid Build Coastguard Worker }
381*ec779b8eSAndroid Build Coastguard Worker mQueueThread->queue(comp, fenceFd, std::move(work), std::move(fd0), std::move(fd1));
382*ec779b8eSAndroid Build Coastguard Worker
383*ec779b8eSAndroid Build Coastguard Worker return OK;
384*ec779b8eSAndroid Build Coastguard Worker }
385*ec779b8eSAndroid Build Coastguard Worker
onDataspaceChanged(uint32_t dataSpace,uint32_t pixelFormat)386*ec779b8eSAndroid Build Coastguard Worker status_t C2NodeImpl::onDataspaceChanged(uint32_t dataSpace, uint32_t pixelFormat) {
387*ec779b8eSAndroid Build Coastguard Worker ALOGD("dataspace changed to %#x pixel format: %#x", dataSpace, pixelFormat);
388*ec779b8eSAndroid Build Coastguard Worker android_dataspace d = (android_dataspace)dataSpace;
389*ec779b8eSAndroid Build Coastguard Worker mQueueThread->setDataspace(d);
390*ec779b8eSAndroid Build Coastguard Worker
391*ec779b8eSAndroid Build Coastguard Worker mDataspace.lock().set(d);
392*ec779b8eSAndroid Build Coastguard Worker mPixelFormat.lock().set(pixelFormat);
393*ec779b8eSAndroid Build Coastguard Worker return OK;
394*ec779b8eSAndroid Build Coastguard Worker }
395*ec779b8eSAndroid Build Coastguard Worker
getSource()396*ec779b8eSAndroid Build Coastguard Worker sp<IOMXBufferSource> C2NodeImpl::getSource() {
397*ec779b8eSAndroid Build Coastguard Worker CHECK(!mAidlHal);
398*ec779b8eSAndroid Build Coastguard Worker return mBufferSource;
399*ec779b8eSAndroid Build Coastguard Worker }
400*ec779b8eSAndroid Build Coastguard Worker
getAidlSource()401*ec779b8eSAndroid Build Coastguard Worker std::shared_ptr<IAidlBufferSource> C2NodeImpl::getAidlSource() {
402*ec779b8eSAndroid Build Coastguard Worker CHECK(mAidlHal);
403*ec779b8eSAndroid Build Coastguard Worker return mAidlBufferSource;
404*ec779b8eSAndroid Build Coastguard Worker }
405*ec779b8eSAndroid Build Coastguard Worker
setFrameSize(uint32_t width,uint32_t height)406*ec779b8eSAndroid Build Coastguard Worker void C2NodeImpl::setFrameSize(uint32_t width, uint32_t height) {
407*ec779b8eSAndroid Build Coastguard Worker mWidth = width;
408*ec779b8eSAndroid Build Coastguard Worker mHeight = height;
409*ec779b8eSAndroid Build Coastguard Worker }
410*ec779b8eSAndroid Build Coastguard Worker
onInputBufferDone(c2_cntr64_t index)411*ec779b8eSAndroid Build Coastguard Worker void C2NodeImpl::onInputBufferDone(c2_cntr64_t index) {
412*ec779b8eSAndroid Build Coastguard Worker if (android::media::codec::provider_->input_surface_throttle()) {
413*ec779b8eSAndroid Build Coastguard Worker Mutexed<BuffersTracker>::Locked buffers(mBuffersTracker);
414*ec779b8eSAndroid Build Coastguard Worker auto it = buffers->mIdsInUse.find(index.peeku());
415*ec779b8eSAndroid Build Coastguard Worker if (it == buffers->mIdsInUse.end()) {
416*ec779b8eSAndroid Build Coastguard Worker ALOGV("Untracked input index %llu (maybe already removed)", index.peekull());
417*ec779b8eSAndroid Build Coastguard Worker return;
418*ec779b8eSAndroid Build Coastguard Worker }
419*ec779b8eSAndroid Build Coastguard Worker int32_t bufferId = it->second;
420*ec779b8eSAndroid Build Coastguard Worker (void)buffers->mIdsInUse.erase(it);
421*ec779b8eSAndroid Build Coastguard Worker buffers->mAvailableIds.push_back(bufferId);
422*ec779b8eSAndroid Build Coastguard Worker } else {
423*ec779b8eSAndroid Build Coastguard Worker if (!hasBufferSource()) {
424*ec779b8eSAndroid Build Coastguard Worker return;
425*ec779b8eSAndroid Build Coastguard Worker }
426*ec779b8eSAndroid Build Coastguard Worker int32_t bufferId = 0;
427*ec779b8eSAndroid Build Coastguard Worker {
428*ec779b8eSAndroid Build Coastguard Worker Mutexed<BuffersTracker>::Locked buffers(mBuffersTracker);
429*ec779b8eSAndroid Build Coastguard Worker auto it = buffers->mIdsInUse.find(index.peeku());
430*ec779b8eSAndroid Build Coastguard Worker if (it == buffers->mIdsInUse.end()) {
431*ec779b8eSAndroid Build Coastguard Worker ALOGV("Untracked input index %llu (maybe already removed)", index.peekull());
432*ec779b8eSAndroid Build Coastguard Worker return;
433*ec779b8eSAndroid Build Coastguard Worker }
434*ec779b8eSAndroid Build Coastguard Worker bufferId = it->second;
435*ec779b8eSAndroid Build Coastguard Worker (void)buffers->mIdsInUse.erase(it);
436*ec779b8eSAndroid Build Coastguard Worker }
437*ec779b8eSAndroid Build Coastguard Worker notifyInputBufferEmptied(bufferId);
438*ec779b8eSAndroid Build Coastguard Worker }
439*ec779b8eSAndroid Build Coastguard Worker }
440*ec779b8eSAndroid Build Coastguard Worker
onInputBufferEmptied()441*ec779b8eSAndroid Build Coastguard Worker void C2NodeImpl::onInputBufferEmptied() {
442*ec779b8eSAndroid Build Coastguard Worker if (!android::media::codec::provider_->input_surface_throttle()) {
443*ec779b8eSAndroid Build Coastguard Worker ALOGE("onInputBufferEmptied should not be called "
444*ec779b8eSAndroid Build Coastguard Worker "when input_surface_throttle is false");
445*ec779b8eSAndroid Build Coastguard Worker return;
446*ec779b8eSAndroid Build Coastguard Worker }
447*ec779b8eSAndroid Build Coastguard Worker if (!hasBufferSource()) {
448*ec779b8eSAndroid Build Coastguard Worker return;
449*ec779b8eSAndroid Build Coastguard Worker }
450*ec779b8eSAndroid Build Coastguard Worker int32_t bufferId = 0;
451*ec779b8eSAndroid Build Coastguard Worker {
452*ec779b8eSAndroid Build Coastguard Worker Mutexed<BuffersTracker>::Locked buffers(mBuffersTracker);
453*ec779b8eSAndroid Build Coastguard Worker if (buffers->mAvailableIds.empty()) {
454*ec779b8eSAndroid Build Coastguard Worker ALOGV("The codec is ready to take more input buffers "
455*ec779b8eSAndroid Build Coastguard Worker "but no input buffers are ready yet.");
456*ec779b8eSAndroid Build Coastguard Worker return;
457*ec779b8eSAndroid Build Coastguard Worker }
458*ec779b8eSAndroid Build Coastguard Worker bufferId = buffers->mAvailableIds.front();
459*ec779b8eSAndroid Build Coastguard Worker buffers->mAvailableIds.pop_front();
460*ec779b8eSAndroid Build Coastguard Worker }
461*ec779b8eSAndroid Build Coastguard Worker notifyInputBufferEmptied(bufferId);
462*ec779b8eSAndroid Build Coastguard Worker }
463*ec779b8eSAndroid Build Coastguard Worker
hasBufferSource()464*ec779b8eSAndroid Build Coastguard Worker bool C2NodeImpl::hasBufferSource() {
465*ec779b8eSAndroid Build Coastguard Worker if (mAidlHal) {
466*ec779b8eSAndroid Build Coastguard Worker if (!mAidlBufferSource) {
467*ec779b8eSAndroid Build Coastguard Worker ALOGD("Buffer source not set");
468*ec779b8eSAndroid Build Coastguard Worker return false;
469*ec779b8eSAndroid Build Coastguard Worker }
470*ec779b8eSAndroid Build Coastguard Worker } else {
471*ec779b8eSAndroid Build Coastguard Worker if (!mBufferSource) {
472*ec779b8eSAndroid Build Coastguard Worker ALOGD("Buffer source not set");
473*ec779b8eSAndroid Build Coastguard Worker return false;
474*ec779b8eSAndroid Build Coastguard Worker }
475*ec779b8eSAndroid Build Coastguard Worker }
476*ec779b8eSAndroid Build Coastguard Worker return true;
477*ec779b8eSAndroid Build Coastguard Worker }
478*ec779b8eSAndroid Build Coastguard Worker
notifyInputBufferEmptied(int32_t bufferId)479*ec779b8eSAndroid Build Coastguard Worker void C2NodeImpl::notifyInputBufferEmptied(int32_t bufferId) {
480*ec779b8eSAndroid Build Coastguard Worker if (mAidlHal) {
481*ec779b8eSAndroid Build Coastguard Worker ::ndk::ScopedFileDescriptor nullFence;
482*ec779b8eSAndroid Build Coastguard Worker (void)mAidlBufferSource->onInputBufferEmptied(bufferId, nullFence);
483*ec779b8eSAndroid Build Coastguard Worker } else {
484*ec779b8eSAndroid Build Coastguard Worker (void)mBufferSource->onInputBufferEmptied(bufferId, -1);
485*ec779b8eSAndroid Build Coastguard Worker }
486*ec779b8eSAndroid Build Coastguard Worker }
487*ec779b8eSAndroid Build Coastguard Worker
getDataspace()488*ec779b8eSAndroid Build Coastguard Worker android_dataspace C2NodeImpl::getDataspace() {
489*ec779b8eSAndroid Build Coastguard Worker return *mDataspace.lock();
490*ec779b8eSAndroid Build Coastguard Worker }
491*ec779b8eSAndroid Build Coastguard Worker
getPixelFormat()492*ec779b8eSAndroid Build Coastguard Worker uint32_t C2NodeImpl::getPixelFormat() {
493*ec779b8eSAndroid Build Coastguard Worker return *mPixelFormat.lock();
494*ec779b8eSAndroid Build Coastguard Worker }
495*ec779b8eSAndroid Build Coastguard Worker
setPriority(int priority)496*ec779b8eSAndroid Build Coastguard Worker void C2NodeImpl::setPriority(int priority) {
497*ec779b8eSAndroid Build Coastguard Worker mQueueThread->setPriority(priority);
498*ec779b8eSAndroid Build Coastguard Worker }
499*ec779b8eSAndroid Build Coastguard Worker
500*ec779b8eSAndroid Build Coastguard Worker } // namespace android
501