xref: /aosp_15_r20/frameworks/av/media/codec2/sfplugin/C2NodeImpl.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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> &param : 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