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