1 /*
2 * Copyright (C) 2009 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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "OMXClient"
19
20 #ifdef __LP64__
21 #define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
22 #endif
23
24 #include <utils/Log.h>
25
26 #include <binder/IServiceManager.h>
27 #include <media/IMediaPlayerService.h>
28 #include <media/stagefright/foundation/ADebug.h>
29 #include <media/stagefright/OMXClient.h>
30 #include <utils/KeyedVector.h>
31
32 #include "include/OMX.h"
33
34 namespace android {
35
36 struct MuxOMX : public IOMX {
37 MuxOMX(const sp<IOMX> &remoteOMX);
38 virtual ~MuxOMX();
39
onAsBinderandroid::MuxOMX40 virtual IBinder *onAsBinder() { return IInterface::asBinder(mRemoteOMX).get(); }
41
42 virtual bool livesLocally(node_id node, pid_t pid);
43
44 virtual status_t listNodes(List<ComponentInfo> *list);
45
46 virtual status_t allocateNode(
47 const char *name, const sp<IOMXObserver> &observer,
48 node_id *node);
49
50 virtual status_t freeNode(node_id node);
51
52 virtual status_t sendCommand(
53 node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param);
54
55 virtual status_t getParameter(
56 node_id node, OMX_INDEXTYPE index,
57 void *params, size_t size);
58
59 virtual status_t setParameter(
60 node_id node, OMX_INDEXTYPE index,
61 const void *params, size_t size);
62
63 virtual status_t getConfig(
64 node_id node, OMX_INDEXTYPE index,
65 void *params, size_t size);
66
67 virtual status_t setConfig(
68 node_id node, OMX_INDEXTYPE index,
69 const void *params, size_t size);
70
71 virtual status_t getState(
72 node_id node, OMX_STATETYPE* state);
73
74 virtual status_t storeMetaDataInBuffers(
75 node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type);
76
77 virtual status_t prepareForAdaptivePlayback(
78 node_id node, OMX_U32 port_index, OMX_BOOL enable,
79 OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight);
80
81 virtual status_t configureVideoTunnelMode(
82 node_id node, OMX_U32 portIndex, OMX_BOOL tunneled,
83 OMX_U32 audioHwSync, native_handle_t **sidebandHandle);
84
85 virtual status_t enableGraphicBuffers(
86 node_id node, OMX_U32 port_index, OMX_BOOL enable);
87
88 virtual status_t getGraphicBufferUsage(
89 node_id node, OMX_U32 port_index, OMX_U32* usage);
90
91 virtual status_t useBuffer(
92 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
93 buffer_id *buffer, OMX_U32 allottedSize);
94
95 virtual status_t useGraphicBuffer(
96 node_id node, OMX_U32 port_index,
97 const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer);
98
99 virtual status_t updateGraphicBufferInMeta(
100 node_id node, OMX_U32 port_index,
101 const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer);
102
103 virtual status_t createInputSurface(
104 node_id node, OMX_U32 port_index,
105 sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type);
106
107 virtual status_t createPersistentInputSurface(
108 sp<IGraphicBufferProducer> *bufferProducer,
109 sp<IGraphicBufferConsumer> *bufferConsumer);
110
111 virtual status_t setInputSurface(
112 node_id node, OMX_U32 port_index,
113 const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type);
114
115 virtual status_t signalEndOfInputStream(node_id node);
116
117 virtual status_t allocateBuffer(
118 node_id node, OMX_U32 port_index, size_t size,
119 buffer_id *buffer, void **buffer_data);
120
121 virtual status_t allocateBufferWithBackup(
122 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
123 buffer_id *buffer, OMX_U32 allottedSize);
124
125 virtual status_t freeBuffer(
126 node_id node, OMX_U32 port_index, buffer_id buffer);
127
128 virtual status_t fillBuffer(node_id node, buffer_id buffer, int fenceFd);
129
130 virtual status_t emptyBuffer(
131 node_id node,
132 buffer_id buffer,
133 OMX_U32 range_offset, OMX_U32 range_length,
134 OMX_U32 flags, OMX_TICKS timestamp, int fenceFd);
135
136 virtual status_t getExtensionIndex(
137 node_id node,
138 const char *parameter_name,
139 OMX_INDEXTYPE *index);
140
141 virtual status_t setInternalOption(
142 node_id node,
143 OMX_U32 port_index,
144 InternalOptionType type,
145 const void *data,
146 size_t size);
147
148 private:
149 mutable Mutex mLock;
150
151 sp<IOMX> mRemoteOMX;
152 sp<IOMX> mLocalOMX;
153
154 KeyedVector<node_id, bool> mIsLocalNode;
155
156 bool isLocalNode(node_id node) const;
157 bool isLocalNode_l(node_id node) const;
158 const sp<IOMX> &getOMX(node_id node) const;
159 const sp<IOMX> &getOMX_l(node_id node) const;
160
161 static bool CanLiveLocally(const char *name);
162
163 DISALLOW_EVIL_CONSTRUCTORS(MuxOMX);
164 };
165
MuxOMX(const sp<IOMX> & remoteOMX)166 MuxOMX::MuxOMX(const sp<IOMX> &remoteOMX)
167 : mRemoteOMX(remoteOMX) {
168 }
169
~MuxOMX()170 MuxOMX::~MuxOMX() {
171 }
172
isLocalNode(node_id node) const173 bool MuxOMX::isLocalNode(node_id node) const {
174 Mutex::Autolock autoLock(mLock);
175
176 return isLocalNode_l(node);
177 }
178
isLocalNode_l(node_id node) const179 bool MuxOMX::isLocalNode_l(node_id node) const {
180 return mIsLocalNode.indexOfKey(node) >= 0;
181 }
182
183 // static
CanLiveLocally(const char * name)184 bool MuxOMX::CanLiveLocally(const char *name) {
185 #ifdef __LP64__
186 (void)name; // disable unused parameter warning
187 // 64 bit processes always run OMX remote on MediaServer
188 return false;
189 #else
190 // 32 bit processes run only OMX.google.* components locally
191 return !strncasecmp(name, "OMX.google.", 11);
192 #endif
193 }
194
getOMX(node_id node) const195 const sp<IOMX> &MuxOMX::getOMX(node_id node) const {
196 return isLocalNode(node) ? mLocalOMX : mRemoteOMX;
197 }
198
getOMX_l(node_id node) const199 const sp<IOMX> &MuxOMX::getOMX_l(node_id node) const {
200 return isLocalNode_l(node) ? mLocalOMX : mRemoteOMX;
201 }
202
livesLocally(node_id node,pid_t pid)203 bool MuxOMX::livesLocally(node_id node, pid_t pid) {
204 return getOMX(node)->livesLocally(node, pid);
205 }
206
listNodes(List<ComponentInfo> * list)207 status_t MuxOMX::listNodes(List<ComponentInfo> *list) {
208 Mutex::Autolock autoLock(mLock);
209
210 if (mLocalOMX == NULL) {
211 mLocalOMX = new OMX;
212 }
213
214 return mLocalOMX->listNodes(list);
215 }
216
allocateNode(const char * name,const sp<IOMXObserver> & observer,node_id * node)217 status_t MuxOMX::allocateNode(
218 const char *name, const sp<IOMXObserver> &observer,
219 node_id *node) {
220 Mutex::Autolock autoLock(mLock);
221
222 sp<IOMX> omx;
223
224 if (CanLiveLocally(name)) {
225 if (mLocalOMX == NULL) {
226 mLocalOMX = new OMX;
227 }
228 omx = mLocalOMX;
229 } else {
230 omx = mRemoteOMX;
231 }
232
233 status_t err = omx->allocateNode(name, observer, node);
234
235 if (err != OK) {
236 return err;
237 }
238
239 if (omx == mLocalOMX) {
240 mIsLocalNode.add(*node, true);
241 }
242
243 return OK;
244 }
245
freeNode(node_id node)246 status_t MuxOMX::freeNode(node_id node) {
247 Mutex::Autolock autoLock(mLock);
248
249 status_t err = getOMX_l(node)->freeNode(node);
250
251 if (err != OK) {
252 return err;
253 }
254
255 mIsLocalNode.removeItem(node);
256
257 return OK;
258 }
259
sendCommand(node_id node,OMX_COMMANDTYPE cmd,OMX_S32 param)260 status_t MuxOMX::sendCommand(
261 node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
262 return getOMX(node)->sendCommand(node, cmd, param);
263 }
264
getParameter(node_id node,OMX_INDEXTYPE index,void * params,size_t size)265 status_t MuxOMX::getParameter(
266 node_id node, OMX_INDEXTYPE index,
267 void *params, size_t size) {
268 return getOMX(node)->getParameter(node, index, params, size);
269 }
270
setParameter(node_id node,OMX_INDEXTYPE index,const void * params,size_t size)271 status_t MuxOMX::setParameter(
272 node_id node, OMX_INDEXTYPE index,
273 const void *params, size_t size) {
274 return getOMX(node)->setParameter(node, index, params, size);
275 }
276
getConfig(node_id node,OMX_INDEXTYPE index,void * params,size_t size)277 status_t MuxOMX::getConfig(
278 node_id node, OMX_INDEXTYPE index,
279 void *params, size_t size) {
280 return getOMX(node)->getConfig(node, index, params, size);
281 }
282
setConfig(node_id node,OMX_INDEXTYPE index,const void * params,size_t size)283 status_t MuxOMX::setConfig(
284 node_id node, OMX_INDEXTYPE index,
285 const void *params, size_t size) {
286 return getOMX(node)->setConfig(node, index, params, size);
287 }
288
getState(node_id node,OMX_STATETYPE * state)289 status_t MuxOMX::getState(
290 node_id node, OMX_STATETYPE* state) {
291 return getOMX(node)->getState(node, state);
292 }
293
storeMetaDataInBuffers(node_id node,OMX_U32 port_index,OMX_BOOL enable,MetadataBufferType * type)294 status_t MuxOMX::storeMetaDataInBuffers(
295 node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type) {
296 return getOMX(node)->storeMetaDataInBuffers(node, port_index, enable, type);
297 }
298
prepareForAdaptivePlayback(node_id node,OMX_U32 port_index,OMX_BOOL enable,OMX_U32 maxFrameWidth,OMX_U32 maxFrameHeight)299 status_t MuxOMX::prepareForAdaptivePlayback(
300 node_id node, OMX_U32 port_index, OMX_BOOL enable,
301 OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) {
302 return getOMX(node)->prepareForAdaptivePlayback(
303 node, port_index, enable, maxFrameWidth, maxFrameHeight);
304 }
305
configureVideoTunnelMode(node_id node,OMX_U32 portIndex,OMX_BOOL enable,OMX_U32 audioHwSync,native_handle_t ** sidebandHandle)306 status_t MuxOMX::configureVideoTunnelMode(
307 node_id node, OMX_U32 portIndex, OMX_BOOL enable,
308 OMX_U32 audioHwSync, native_handle_t **sidebandHandle) {
309 return getOMX(node)->configureVideoTunnelMode(
310 node, portIndex, enable, audioHwSync, sidebandHandle);
311 }
312
enableGraphicBuffers(node_id node,OMX_U32 port_index,OMX_BOOL enable)313 status_t MuxOMX::enableGraphicBuffers(
314 node_id node, OMX_U32 port_index, OMX_BOOL enable) {
315 return getOMX(node)->enableGraphicBuffers(node, port_index, enable);
316 }
317
getGraphicBufferUsage(node_id node,OMX_U32 port_index,OMX_U32 * usage)318 status_t MuxOMX::getGraphicBufferUsage(
319 node_id node, OMX_U32 port_index, OMX_U32* usage) {
320 return getOMX(node)->getGraphicBufferUsage(node, port_index, usage);
321 }
322
useBuffer(node_id node,OMX_U32 port_index,const sp<IMemory> & params,buffer_id * buffer,OMX_U32 allottedSize)323 status_t MuxOMX::useBuffer(
324 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
325 buffer_id *buffer, OMX_U32 allottedSize) {
326 return getOMX(node)->useBuffer(node, port_index, params, buffer, allottedSize);
327 }
328
useGraphicBuffer(node_id node,OMX_U32 port_index,const sp<GraphicBuffer> & graphicBuffer,buffer_id * buffer)329 status_t MuxOMX::useGraphicBuffer(
330 node_id node, OMX_U32 port_index,
331 const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
332 return getOMX(node)->useGraphicBuffer(
333 node, port_index, graphicBuffer, buffer);
334 }
335
updateGraphicBufferInMeta(node_id node,OMX_U32 port_index,const sp<GraphicBuffer> & graphicBuffer,buffer_id buffer)336 status_t MuxOMX::updateGraphicBufferInMeta(
337 node_id node, OMX_U32 port_index,
338 const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) {
339 return getOMX(node)->updateGraphicBufferInMeta(
340 node, port_index, graphicBuffer, buffer);
341 }
342
createInputSurface(node_id node,OMX_U32 port_index,sp<IGraphicBufferProducer> * bufferProducer,MetadataBufferType * type)343 status_t MuxOMX::createInputSurface(
344 node_id node, OMX_U32 port_index,
345 sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) {
346 status_t err = getOMX(node)->createInputSurface(
347 node, port_index, bufferProducer, type);
348 return err;
349 }
350
createPersistentInputSurface(sp<IGraphicBufferProducer> * bufferProducer,sp<IGraphicBufferConsumer> * bufferConsumer)351 status_t MuxOMX::createPersistentInputSurface(
352 sp<IGraphicBufferProducer> *bufferProducer,
353 sp<IGraphicBufferConsumer> *bufferConsumer) {
354 // TODO: local or remote? Always use remote for now
355 return mRemoteOMX->createPersistentInputSurface(
356 bufferProducer, bufferConsumer);
357 }
358
setInputSurface(node_id node,OMX_U32 port_index,const sp<IGraphicBufferConsumer> & bufferConsumer,MetadataBufferType * type)359 status_t MuxOMX::setInputSurface(
360 node_id node, OMX_U32 port_index,
361 const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type) {
362 return getOMX(node)->setInputSurface(node, port_index, bufferConsumer, type);
363 }
364
signalEndOfInputStream(node_id node)365 status_t MuxOMX::signalEndOfInputStream(node_id node) {
366 return getOMX(node)->signalEndOfInputStream(node);
367 }
368
allocateBuffer(node_id node,OMX_U32 port_index,size_t size,buffer_id * buffer,void ** buffer_data)369 status_t MuxOMX::allocateBuffer(
370 node_id node, OMX_U32 port_index, size_t size,
371 buffer_id *buffer, void **buffer_data) {
372 return getOMX(node)->allocateBuffer(
373 node, port_index, size, buffer, buffer_data);
374 }
375
allocateBufferWithBackup(node_id node,OMX_U32 port_index,const sp<IMemory> & params,buffer_id * buffer,OMX_U32 allottedSize)376 status_t MuxOMX::allocateBufferWithBackup(
377 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
378 buffer_id *buffer, OMX_U32 allottedSize) {
379 return getOMX(node)->allocateBufferWithBackup(
380 node, port_index, params, buffer, allottedSize);
381 }
382
freeBuffer(node_id node,OMX_U32 port_index,buffer_id buffer)383 status_t MuxOMX::freeBuffer(
384 node_id node, OMX_U32 port_index, buffer_id buffer) {
385 return getOMX(node)->freeBuffer(node, port_index, buffer);
386 }
387
fillBuffer(node_id node,buffer_id buffer,int fenceFd)388 status_t MuxOMX::fillBuffer(node_id node, buffer_id buffer, int fenceFd) {
389 return getOMX(node)->fillBuffer(node, buffer, fenceFd);
390 }
391
emptyBuffer(node_id node,buffer_id buffer,OMX_U32 range_offset,OMX_U32 range_length,OMX_U32 flags,OMX_TICKS timestamp,int fenceFd)392 status_t MuxOMX::emptyBuffer(
393 node_id node,
394 buffer_id buffer,
395 OMX_U32 range_offset, OMX_U32 range_length,
396 OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
397 return getOMX(node)->emptyBuffer(
398 node, buffer, range_offset, range_length, flags, timestamp, fenceFd);
399 }
400
getExtensionIndex(node_id node,const char * parameter_name,OMX_INDEXTYPE * index)401 status_t MuxOMX::getExtensionIndex(
402 node_id node,
403 const char *parameter_name,
404 OMX_INDEXTYPE *index) {
405 return getOMX(node)->getExtensionIndex(node, parameter_name, index);
406 }
407
setInternalOption(node_id node,OMX_U32 port_index,InternalOptionType type,const void * data,size_t size)408 status_t MuxOMX::setInternalOption(
409 node_id node,
410 OMX_U32 port_index,
411 InternalOptionType type,
412 const void *data,
413 size_t size) {
414 return getOMX(node)->setInternalOption(node, port_index, type, data, size);
415 }
416
OMXClient()417 OMXClient::OMXClient() {
418 }
419
connect()420 status_t OMXClient::connect() {
421 sp<IServiceManager> sm = defaultServiceManager();
422 sp<IBinder> binder = sm->getService(String16("media.player"));
423 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
424
425 if (service.get() == NULL) {
426 ALOGE("Cannot obtain IMediaPlayerService");
427 return NO_INIT;
428 }
429
430 mOMX = service->getOMX();
431 if (mOMX.get() == NULL) {
432 ALOGE("Cannot obtain IOMX");
433 return NO_INIT;
434 }
435
436 if (!mOMX->livesLocally(0 /* node */, getpid())) {
437 ALOGI("Using client-side OMX mux.");
438 mOMX = new MuxOMX(mOMX);
439 }
440
441 return OK;
442 }
443
disconnect()444 void OMXClient::disconnect() {
445 if (mOMX.get() != NULL) {
446 mOMX.clear();
447 mOMX = NULL;
448 }
449 }
450
451 } // namespace android
452