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> &params,
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> &params,
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> &params,
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> &params,
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