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 mRemoteOMX->asBinder().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);
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);
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);
106 
107     virtual status_t signalEndOfInputStream(node_id node);
108 
109     virtual status_t allocateBuffer(
110             node_id node, OMX_U32 port_index, size_t size,
111             buffer_id *buffer, void **buffer_data);
112 
113     virtual status_t allocateBufferWithBackup(
114             node_id node, OMX_U32 port_index, const sp<IMemory> &params,
115             buffer_id *buffer);
116 
117     virtual status_t freeBuffer(
118             node_id node, OMX_U32 port_index, buffer_id buffer);
119 
120     virtual status_t fillBuffer(node_id node, buffer_id buffer);
121 
122     virtual status_t emptyBuffer(
123             node_id node,
124             buffer_id buffer,
125             OMX_U32 range_offset, OMX_U32 range_length,
126             OMX_U32 flags, OMX_TICKS timestamp);
127 
128     virtual status_t getExtensionIndex(
129             node_id node,
130             const char *parameter_name,
131             OMX_INDEXTYPE *index);
132 
133     virtual status_t setInternalOption(
134             node_id node,
135             OMX_U32 port_index,
136             InternalOptionType type,
137             const void *data,
138             size_t size);
139 
140 private:
141     mutable Mutex mLock;
142 
143     sp<IOMX> mRemoteOMX;
144     sp<IOMX> mLocalOMX;
145 
146     KeyedVector<node_id, bool> mIsLocalNode;
147 
148     bool isLocalNode(node_id node) const;
149     bool isLocalNode_l(node_id node) const;
150     const sp<IOMX> &getOMX(node_id node) const;
151     const sp<IOMX> &getOMX_l(node_id node) const;
152 
153     static bool CanLiveLocally(const char *name);
154 
155     DISALLOW_EVIL_CONSTRUCTORS(MuxOMX);
156 };
157 
MuxOMX(const sp<IOMX> & remoteOMX)158 MuxOMX::MuxOMX(const sp<IOMX> &remoteOMX)
159     : mRemoteOMX(remoteOMX) {
160 }
161 
~MuxOMX()162 MuxOMX::~MuxOMX() {
163 }
164 
isLocalNode(node_id node) const165 bool MuxOMX::isLocalNode(node_id node) const {
166     Mutex::Autolock autoLock(mLock);
167 
168     return isLocalNode_l(node);
169 }
170 
isLocalNode_l(node_id node) const171 bool MuxOMX::isLocalNode_l(node_id node) const {
172     return mIsLocalNode.indexOfKey(node) >= 0;
173 }
174 
175 // static
CanLiveLocally(const char * name)176 bool MuxOMX::CanLiveLocally(const char *name) {
177 #ifdef __LP64__
178     (void)name; // disable unused parameter warning
179     // 64 bit processes always run OMX remote on MediaServer
180     return false;
181 #else
182     // 32 bit processes run only OMX.google.* components locally
183     return !strncasecmp(name, "OMX.google.", 11);
184 #endif
185 }
186 
getOMX(node_id node) const187 const sp<IOMX> &MuxOMX::getOMX(node_id node) const {
188     return isLocalNode(node) ? mLocalOMX : mRemoteOMX;
189 }
190 
getOMX_l(node_id node) const191 const sp<IOMX> &MuxOMX::getOMX_l(node_id node) const {
192     return isLocalNode_l(node) ? mLocalOMX : mRemoteOMX;
193 }
194 
livesLocally(node_id node,pid_t pid)195 bool MuxOMX::livesLocally(node_id node, pid_t pid) {
196     return getOMX(node)->livesLocally(node, pid);
197 }
198 
listNodes(List<ComponentInfo> * list)199 status_t MuxOMX::listNodes(List<ComponentInfo> *list) {
200     Mutex::Autolock autoLock(mLock);
201 
202     if (mLocalOMX == NULL) {
203         mLocalOMX = new OMX;
204     }
205 
206     return mLocalOMX->listNodes(list);
207 }
208 
allocateNode(const char * name,const sp<IOMXObserver> & observer,node_id * node)209 status_t MuxOMX::allocateNode(
210         const char *name, const sp<IOMXObserver> &observer,
211         node_id *node) {
212     Mutex::Autolock autoLock(mLock);
213 
214     sp<IOMX> omx;
215 
216     if (CanLiveLocally(name)) {
217         if (mLocalOMX == NULL) {
218             mLocalOMX = new OMX;
219         }
220         omx = mLocalOMX;
221     } else {
222         omx = mRemoteOMX;
223     }
224 
225     status_t err = omx->allocateNode(name, observer, node);
226 
227     if (err != OK) {
228         return err;
229     }
230 
231     if (omx == mLocalOMX) {
232         mIsLocalNode.add(*node, true);
233     }
234 
235     return OK;
236 }
237 
freeNode(node_id node)238 status_t MuxOMX::freeNode(node_id node) {
239     Mutex::Autolock autoLock(mLock);
240 
241     status_t err = getOMX_l(node)->freeNode(node);
242 
243     if (err != OK) {
244         return err;
245     }
246 
247     mIsLocalNode.removeItem(node);
248 
249     return OK;
250 }
251 
sendCommand(node_id node,OMX_COMMANDTYPE cmd,OMX_S32 param)252 status_t MuxOMX::sendCommand(
253         node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
254     return getOMX(node)->sendCommand(node, cmd, param);
255 }
256 
getParameter(node_id node,OMX_INDEXTYPE index,void * params,size_t size)257 status_t MuxOMX::getParameter(
258         node_id node, OMX_INDEXTYPE index,
259         void *params, size_t size) {
260     return getOMX(node)->getParameter(node, index, params, size);
261 }
262 
setParameter(node_id node,OMX_INDEXTYPE index,const void * params,size_t size)263 status_t MuxOMX::setParameter(
264         node_id node, OMX_INDEXTYPE index,
265         const void *params, size_t size) {
266     return getOMX(node)->setParameter(node, index, params, size);
267 }
268 
getConfig(node_id node,OMX_INDEXTYPE index,void * params,size_t size)269 status_t MuxOMX::getConfig(
270         node_id node, OMX_INDEXTYPE index,
271         void *params, size_t size) {
272     return getOMX(node)->getConfig(node, index, params, size);
273 }
274 
setConfig(node_id node,OMX_INDEXTYPE index,const void * params,size_t size)275 status_t MuxOMX::setConfig(
276         node_id node, OMX_INDEXTYPE index,
277         const void *params, size_t size) {
278     return getOMX(node)->setConfig(node, index, params, size);
279 }
280 
getState(node_id node,OMX_STATETYPE * state)281 status_t MuxOMX::getState(
282         node_id node, OMX_STATETYPE* state) {
283     return getOMX(node)->getState(node, state);
284 }
285 
storeMetaDataInBuffers(node_id node,OMX_U32 port_index,OMX_BOOL enable)286 status_t MuxOMX::storeMetaDataInBuffers(
287         node_id node, OMX_U32 port_index, OMX_BOOL enable) {
288     return getOMX(node)->storeMetaDataInBuffers(node, port_index, enable);
289 }
290 
prepareForAdaptivePlayback(node_id node,OMX_U32 port_index,OMX_BOOL enable,OMX_U32 maxFrameWidth,OMX_U32 maxFrameHeight)291 status_t MuxOMX::prepareForAdaptivePlayback(
292         node_id node, OMX_U32 port_index, OMX_BOOL enable,
293         OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) {
294     return getOMX(node)->prepareForAdaptivePlayback(
295             node, port_index, enable, maxFrameWidth, maxFrameHeight);
296 }
297 
configureVideoTunnelMode(node_id node,OMX_U32 portIndex,OMX_BOOL enable,OMX_U32 audioHwSync,native_handle_t ** sidebandHandle)298 status_t MuxOMX::configureVideoTunnelMode(
299         node_id node, OMX_U32 portIndex, OMX_BOOL enable,
300         OMX_U32 audioHwSync, native_handle_t **sidebandHandle) {
301     return getOMX(node)->configureVideoTunnelMode(
302             node, portIndex, enable, audioHwSync, sidebandHandle);
303 }
304 
enableGraphicBuffers(node_id node,OMX_U32 port_index,OMX_BOOL enable)305 status_t MuxOMX::enableGraphicBuffers(
306         node_id node, OMX_U32 port_index, OMX_BOOL enable) {
307     return getOMX(node)->enableGraphicBuffers(node, port_index, enable);
308 }
309 
getGraphicBufferUsage(node_id node,OMX_U32 port_index,OMX_U32 * usage)310 status_t MuxOMX::getGraphicBufferUsage(
311         node_id node, OMX_U32 port_index, OMX_U32* usage) {
312     return getOMX(node)->getGraphicBufferUsage(node, port_index, usage);
313 }
314 
useBuffer(node_id node,OMX_U32 port_index,const sp<IMemory> & params,buffer_id * buffer)315 status_t MuxOMX::useBuffer(
316         node_id node, OMX_U32 port_index, const sp<IMemory> &params,
317         buffer_id *buffer) {
318     return getOMX(node)->useBuffer(node, port_index, params, buffer);
319 }
320 
useGraphicBuffer(node_id node,OMX_U32 port_index,const sp<GraphicBuffer> & graphicBuffer,buffer_id * buffer)321 status_t MuxOMX::useGraphicBuffer(
322         node_id node, OMX_U32 port_index,
323         const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
324     return getOMX(node)->useGraphicBuffer(
325             node, port_index, graphicBuffer, buffer);
326 }
327 
updateGraphicBufferInMeta(node_id node,OMX_U32 port_index,const sp<GraphicBuffer> & graphicBuffer,buffer_id buffer)328 status_t MuxOMX::updateGraphicBufferInMeta(
329         node_id node, OMX_U32 port_index,
330         const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) {
331     return getOMX(node)->updateGraphicBufferInMeta(
332             node, port_index, graphicBuffer, buffer);
333 }
334 
createInputSurface(node_id node,OMX_U32 port_index,sp<IGraphicBufferProducer> * bufferProducer)335 status_t MuxOMX::createInputSurface(
336         node_id node, OMX_U32 port_index,
337         sp<IGraphicBufferProducer> *bufferProducer) {
338     status_t err = getOMX(node)->createInputSurface(
339             node, port_index, bufferProducer);
340     return err;
341 }
342 
signalEndOfInputStream(node_id node)343 status_t MuxOMX::signalEndOfInputStream(node_id node) {
344     return getOMX(node)->signalEndOfInputStream(node);
345 }
346 
allocateBuffer(node_id node,OMX_U32 port_index,size_t size,buffer_id * buffer,void ** buffer_data)347 status_t MuxOMX::allocateBuffer(
348         node_id node, OMX_U32 port_index, size_t size,
349         buffer_id *buffer, void **buffer_data) {
350     return getOMX(node)->allocateBuffer(
351             node, port_index, size, buffer, buffer_data);
352 }
353 
allocateBufferWithBackup(node_id node,OMX_U32 port_index,const sp<IMemory> & params,buffer_id * buffer)354 status_t MuxOMX::allocateBufferWithBackup(
355         node_id node, OMX_U32 port_index, const sp<IMemory> &params,
356         buffer_id *buffer) {
357     return getOMX(node)->allocateBufferWithBackup(
358             node, port_index, params, buffer);
359 }
360 
freeBuffer(node_id node,OMX_U32 port_index,buffer_id buffer)361 status_t MuxOMX::freeBuffer(
362         node_id node, OMX_U32 port_index, buffer_id buffer) {
363     return getOMX(node)->freeBuffer(node, port_index, buffer);
364 }
365 
fillBuffer(node_id node,buffer_id buffer)366 status_t MuxOMX::fillBuffer(node_id node, buffer_id buffer) {
367     return getOMX(node)->fillBuffer(node, buffer);
368 }
369 
emptyBuffer(node_id node,buffer_id buffer,OMX_U32 range_offset,OMX_U32 range_length,OMX_U32 flags,OMX_TICKS timestamp)370 status_t MuxOMX::emptyBuffer(
371         node_id node,
372         buffer_id buffer,
373         OMX_U32 range_offset, OMX_U32 range_length,
374         OMX_U32 flags, OMX_TICKS timestamp) {
375     return getOMX(node)->emptyBuffer(
376             node, buffer, range_offset, range_length, flags, timestamp);
377 }
378 
getExtensionIndex(node_id node,const char * parameter_name,OMX_INDEXTYPE * index)379 status_t MuxOMX::getExtensionIndex(
380         node_id node,
381         const char *parameter_name,
382         OMX_INDEXTYPE *index) {
383     return getOMX(node)->getExtensionIndex(node, parameter_name, index);
384 }
385 
setInternalOption(node_id node,OMX_U32 port_index,InternalOptionType type,const void * data,size_t size)386 status_t MuxOMX::setInternalOption(
387         node_id node,
388         OMX_U32 port_index,
389         InternalOptionType type,
390         const void *data,
391         size_t size) {
392     return getOMX(node)->setInternalOption(node, port_index, type, data, size);
393 }
394 
OMXClient()395 OMXClient::OMXClient() {
396 }
397 
connect()398 status_t OMXClient::connect() {
399     sp<IServiceManager> sm = defaultServiceManager();
400     sp<IBinder> binder = sm->getService(String16("media.player"));
401     sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
402 
403     CHECK(service.get() != NULL);
404 
405     mOMX = service->getOMX();
406     CHECK(mOMX.get() != NULL);
407 
408     if (!mOMX->livesLocally(0 /* node */, getpid())) {
409         ALOGI("Using client-side OMX mux.");
410         mOMX = new MuxOMX(mOMX);
411     }
412 
413     return OK;
414 }
415 
disconnect()416 void OMXClient::disconnect() {
417     if (mOMX.get() != NULL) {
418         mOMX.clear();
419         mOMX = NULL;
420     }
421 }
422 
423 }  // namespace android
424