1 /*
2  * Copyright 2024, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifdef __LP64__
18 #define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
19 #endif
20 
21 //#define LOG_NDEBUG 0
22 #define LOG_TAG "C2OMXNODE"
23 #include <log/log.h>
24 
25 #include <OMX_Component.h>
26 #include <OMX_Index.h>
27 #include <OMX_IndexExt.h>
28 
29 #include <media/stagefright/MediaErrors.h>
30 
31 #include "C2OMXNode.h"
32 #include "C2NodeImpl.h"
33 
34 namespace android {
35 
36 namespace {
37 
38 constexpr OMX_U32 kPortIndexInput = 0;
39 
40 } // anomymous namespace
41 
42 using ::android::media::BUFFERFLAG_ENDOFFRAME;
43 using ::android::media::BUFFERFLAG_EOS;
44 
45 using ::aidl::android::media::IAidlNode;
46 
C2OMXNode(const std::shared_ptr<Codec2Client::Component> & comp)47 C2OMXNode::C2OMXNode(const std::shared_ptr<Codec2Client::Component> &comp)
48     : mImpl(new C2NodeImpl(comp, false)) {}
49 
freeNode()50 status_t C2OMXNode::freeNode() {
51     return mImpl->freeNode();
52 }
53 
sendCommand(OMX_COMMANDTYPE cmd,OMX_S32 param)54 status_t C2OMXNode::sendCommand(OMX_COMMANDTYPE cmd, OMX_S32 param) {
55     if (cmd == OMX_CommandStateSet && param == OMX_StateLoaded) {
56         // Reset first input frame so if C2OMXNode is recycled, the timestamp does not become
57         // negative. This is a workaround for HW codecs that do not handle timestamp rollover.
58         mImpl->onFirstInputFrame();
59     }
60     return ERROR_UNSUPPORTED;
61 }
62 
getParameter(OMX_INDEXTYPE index,void * params,size_t size)63 status_t C2OMXNode::getParameter(OMX_INDEXTYPE index, void *params, size_t size) {
64     status_t err = ERROR_UNSUPPORTED;
65     switch ((uint32_t)index) {
66         case OMX_IndexParamConsumerUsageBits: {
67             OMX_U32 *usage = (OMX_U32 *)params;
68             uint64_t val;
69             mImpl->getConsumerUsageBits(&val);
70             *usage = static_cast<uint32_t>(val & 0xFFFFFFFF);
71             ALOGW("retrieving usage bits in 32 bits %llu -> %u",
72                   (unsigned long long)val, (unsigned int)*usage);
73             err = OK;
74             break;
75         }
76         case OMX_IndexParamConsumerUsageBits64: {
77             OMX_U64 *usage = (OMX_U64 *)params;
78             uint64_t val;
79             mImpl->getConsumerUsageBits(&val);
80             *usage = val;
81             err = OK;
82             break;
83         }
84         case OMX_IndexParamPortDefinition: {
85             if (size < sizeof(OMX_PARAM_PORTDEFINITIONTYPE)) {
86                 return BAD_VALUE;
87             }
88             OMX_PARAM_PORTDEFINITIONTYPE *pDef = (OMX_PARAM_PORTDEFINITIONTYPE *)params;
89             if (pDef->nPortIndex != kPortIndexInput) {
90                 break;
91             }
92             IAidlNode::InputBufferParams bufferParams;
93             mImpl->getInputBufferParams(&bufferParams);
94             pDef->nBufferCountActual = bufferParams.bufferCountActual;
95             pDef->eDomain = OMX_PortDomainVideo;
96             pDef->format.video.nFrameWidth = bufferParams.frameWidth;
97             pDef->format.video.nFrameHeight = bufferParams.frameHeight;
98             pDef->format.video.eColorFormat = OMX_COLOR_FormatAndroidOpaque;
99             err = OK;
100             break;
101         }
102         default:
103             break;
104     }
105     return err;
106 }
107 
setParameter(OMX_INDEXTYPE index,const void * params,size_t size)108 status_t C2OMXNode::setParameter(OMX_INDEXTYPE index, const void *params, size_t size) {
109     if (params == NULL) {
110         return BAD_VALUE;
111     }
112     switch ((uint32_t)index) {
113         case OMX_IndexParamMaxFrameDurationForBitrateControl: {
114             // handle max/fixed frame duration control
115             if (size != sizeof(OMX_PARAM_U32TYPE)) {
116                 return BAD_VALUE;
117             }
118             // The incoming number is an int32_t contained in OMX_U32.
119             int32_t gapUs = (int32_t)((OMX_PARAM_U32TYPE*)params)->nU32;
120             mImpl->setAdjustTimestampGapUs(gapUs);
121             return OK;
122         }
123         case OMX_IndexParamConsumerUsageBits: {
124             if (size != sizeof(OMX_U32)) {
125                 return BAD_VALUE;
126             }
127             uint32_t usage = *((OMX_U32 *)params);
128             mImpl->setConsumerUsageBits(static_cast<uint64_t>(usage));
129             return OK;
130         }
131         case OMX_IndexParamConsumerUsageBits64: {
132             if (size != sizeof(OMX_U64)) {
133                 return BAD_VALUE;
134             }
135             uint64_t usagell = *((OMX_U64 *)params);
136             mImpl->setConsumerUsageBits(usagell);
137             return OK;
138         }
139         default:
140             break;
141     }
142     return ERROR_UNSUPPORTED;
143 }
144 
getConfig(OMX_INDEXTYPE index,void * config,size_t size)145 status_t C2OMXNode::getConfig(OMX_INDEXTYPE index, void *config, size_t size) {
146     (void)index;
147     (void)config;
148     (void)size;
149     return ERROR_UNSUPPORTED;
150 }
151 
setConfig(OMX_INDEXTYPE index,const void * config,size_t size)152 status_t C2OMXNode::setConfig(OMX_INDEXTYPE index, const void *config, size_t size) {
153     (void)index;
154     (void)config;
155     (void)size;
156     return ERROR_UNSUPPORTED;
157 }
158 
setPortMode(OMX_U32 portIndex,IOMX::PortMode mode)159 status_t C2OMXNode::setPortMode(OMX_U32 portIndex, IOMX::PortMode mode) {
160     (void)portIndex;
161     (void)mode;
162     return ERROR_UNSUPPORTED;
163 }
164 
prepareForAdaptivePlayback(OMX_U32 portIndex,OMX_BOOL enable,OMX_U32 maxFrameWidth,OMX_U32 maxFrameHeight)165 status_t C2OMXNode::prepareForAdaptivePlayback(
166         OMX_U32 portIndex, OMX_BOOL enable,
167         OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) {
168     (void)portIndex;
169     (void)enable;
170     (void)maxFrameWidth;
171     (void)maxFrameHeight;
172     return ERROR_UNSUPPORTED;
173 }
174 
configureVideoTunnelMode(OMX_U32 portIndex,OMX_BOOL tunneled,OMX_U32 audioHwSync,native_handle_t ** sidebandHandle)175 status_t C2OMXNode::configureVideoTunnelMode(
176         OMX_U32 portIndex, OMX_BOOL tunneled,
177         OMX_U32 audioHwSync, native_handle_t **sidebandHandle) {
178     (void)portIndex;
179     (void)tunneled;
180     (void)audioHwSync;
181     *sidebandHandle = nullptr;
182     return ERROR_UNSUPPORTED;
183 }
184 
getGraphicBufferUsage(OMX_U32 portIndex,OMX_U32 * usage)185 status_t C2OMXNode::getGraphicBufferUsage(OMX_U32 portIndex, OMX_U32* usage) {
186     (void)portIndex;
187     *usage = 0;
188     return ERROR_UNSUPPORTED;
189 }
190 
setInputSurface(const sp<IOMXBufferSource> & bufferSource)191 status_t C2OMXNode::setInputSurface(const sp<IOMXBufferSource> &bufferSource) {
192     return mImpl->setInputSurface(bufferSource);
193 }
194 
allocateSecureBuffer(OMX_U32 portIndex,size_t size,buffer_id * buffer,void ** bufferData,sp<NativeHandle> * nativeHandle)195 status_t C2OMXNode::allocateSecureBuffer(
196         OMX_U32 portIndex, size_t size, buffer_id *buffer,
197         void **bufferData, sp<NativeHandle> *nativeHandle) {
198     (void)portIndex;
199     (void)size;
200     (void)nativeHandle;
201     *buffer = 0;
202     *bufferData = nullptr;
203     return ERROR_UNSUPPORTED;
204 }
205 
useBuffer(OMX_U32 portIndex,const OMXBuffer & omxBuf,buffer_id * buffer)206 status_t C2OMXNode::useBuffer(
207         OMX_U32 portIndex, const OMXBuffer &omxBuf, buffer_id *buffer) {
208     (void)portIndex;
209     (void)omxBuf;
210     *buffer = 0;
211     return ERROR_UNSUPPORTED;
212 }
213 
freeBuffer(OMX_U32 portIndex,buffer_id buffer)214 status_t C2OMXNode::freeBuffer(OMX_U32 portIndex, buffer_id buffer) {
215     (void)portIndex;
216     (void)buffer;
217     return ERROR_UNSUPPORTED;
218 }
219 
fillBuffer(buffer_id buffer,const OMXBuffer & omxBuf,int fenceFd)220 status_t C2OMXNode::fillBuffer(
221         buffer_id buffer, const OMXBuffer &omxBuf, int fenceFd) {
222     (void)buffer;
223     (void)omxBuf;
224     (void)fenceFd;
225     return ERROR_UNSUPPORTED;
226 }
227 
228 namespace {
toNodeFlags(OMX_U32 flags)229     uint32_t toNodeFlags(OMX_U32 flags) {
230         uint32_t retFlags = 0;
231         if (flags & OMX_BUFFERFLAG_ENDOFFRAME) {
232             retFlags |= BUFFERFLAG_ENDOFFRAME;
233         }
234         if (flags & OMX_BUFFERFLAG_EOS) {
235             retFlags |= BUFFERFLAG_EOS;
236         }
237         return retFlags;
238     }
toNodeTimestamp(OMX_TICKS ticks)239     int64_t toNodeTimestamp(OMX_TICKS ticks) {
240         int64_t timestamp = 0;
241 #ifndef OMX_SKIP64BIT
242         timestamp = ticks;
243 #else
244         timestamp = ((ticks.nHighPart << 32) | ticks.nLowPart);
245 #endif
246         return timestamp;
247     }
248 } // anonymous namespace
249 
emptyBuffer(buffer_id buffer,const OMXBuffer & omxBuf,OMX_U32 flags,OMX_TICKS timestamp,int fenceFd)250 status_t C2OMXNode::emptyBuffer(
251         buffer_id buffer, const OMXBuffer &omxBuf,
252         OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
253     if (omxBuf.mBufferType == OMXBuffer::kBufferTypeANWBuffer
254             && omxBuf.mGraphicBuffer != nullptr) {
255         return mImpl->submitBuffer(buffer, omxBuf.mGraphicBuffer, toNodeFlags(flags),
256                                   toNodeTimestamp(timestamp), fenceFd);
257     }
258     sp<GraphicBuffer> gBuf;
259     return mImpl->submitBuffer(buffer, gBuf, toNodeFlags(flags),
260                               toNodeTimestamp(timestamp), fenceFd);
261 }
262 
getExtensionIndex(const char * parameterName,OMX_INDEXTYPE * index)263 status_t C2OMXNode::getExtensionIndex(
264         const char *parameterName, OMX_INDEXTYPE *index) {
265     (void)parameterName;
266     *index = OMX_IndexMax;
267     return ERROR_UNSUPPORTED;
268 }
269 
dispatchMessage(const omx_message & msg)270 status_t C2OMXNode::dispatchMessage(const omx_message& msg) {
271     if (msg.type != omx_message::EVENT) {
272         return ERROR_UNSUPPORTED;
273     }
274     if (msg.u.event_data.event != OMX_EventDataSpaceChanged) {
275         return ERROR_UNSUPPORTED;
276     }
277     return mImpl->onDataspaceChanged(
278             msg.u.event_data.data1,
279             msg.u.event_data.data3);
280 }
281 
getSource()282 sp<IOMXBufferSource> C2OMXNode::getSource() {
283     return mImpl->getSource();
284 }
285 
setFrameSize(uint32_t width,uint32_t height)286 void C2OMXNode::setFrameSize(uint32_t width, uint32_t height) {
287     return mImpl->setFrameSize(width, height);
288 }
289 
onInputBufferDone(c2_cntr64_t index)290 void C2OMXNode::onInputBufferDone(c2_cntr64_t index) {
291     return mImpl->onInputBufferDone(index);
292 }
293 
onInputBufferEmptied()294 void C2OMXNode::onInputBufferEmptied() {
295     return mImpl->onInputBufferEmptied();
296 }
297 
getDataspace()298 android_dataspace C2OMXNode::getDataspace() {
299     return mImpl->getDataspace();
300 }
301 
getPixelFormat()302 uint32_t C2OMXNode::getPixelFormat() {
303     return mImpl->getPixelFormat();
304 }
305 
setPriority(int priority)306 void C2OMXNode::setPriority(int priority) {
307     return mImpl->setPriority(priority);
308 }
309 
310 }  // namespace android
311