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/IMediaCodecService.h>
29#include <media/stagefright/foundation/ADebug.h>
30#include <media/stagefright/OMXClient.h>
31#include <cutils/properties.h>
32#include <utils/KeyedVector.h>
33
34#include "include/OMX.h"
35
36namespace android {
37
38static bool sCodecProcessEnabled = true;
39
40struct MuxOMX : public IOMX {
41    MuxOMX(const sp<IOMX> &mediaServerOMX, const sp<IOMX> &mediaCodecOMX);
42    virtual ~MuxOMX();
43
44    // Nobody should be calling this. In case someone does anyway, just
45    // return the media server IOMX.
46    // TODO: return NULL
47    virtual IBinder *onAsBinder() {
48        ALOGE("MuxOMX::onAsBinder should not be called");
49        return IInterface::asBinder(mMediaServerOMX).get();
50    }
51
52    virtual bool livesLocally(node_id node, pid_t pid);
53
54    virtual status_t listNodes(List<ComponentInfo> *list);
55
56    virtual status_t allocateNode(
57            const char *name, const sp<IOMXObserver> &observer,
58            sp<IBinder> *nodeBinder,
59            node_id *node);
60
61    virtual status_t freeNode(node_id node);
62
63    virtual status_t sendCommand(
64            node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param);
65
66    virtual status_t getParameter(
67            node_id node, OMX_INDEXTYPE index,
68            void *params, size_t size);
69
70    virtual status_t setParameter(
71            node_id node, OMX_INDEXTYPE index,
72            const void *params, size_t size);
73
74    virtual status_t getConfig(
75            node_id node, OMX_INDEXTYPE index,
76            void *params, size_t size);
77
78    virtual status_t setConfig(
79            node_id node, OMX_INDEXTYPE index,
80            const void *params, size_t size);
81
82    virtual status_t getState(
83            node_id node, OMX_STATETYPE* state);
84
85    virtual status_t storeMetaDataInBuffers(
86            node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type);
87
88    virtual status_t prepareForAdaptivePlayback(
89            node_id node, OMX_U32 port_index, OMX_BOOL enable,
90            OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight);
91
92    virtual status_t configureVideoTunnelMode(
93            node_id node, OMX_U32 portIndex, OMX_BOOL tunneled,
94            OMX_U32 audioHwSync, native_handle_t **sidebandHandle);
95
96    virtual status_t enableNativeBuffers(
97            node_id node, OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable);
98
99    virtual status_t getGraphicBufferUsage(
100            node_id node, OMX_U32 port_index, OMX_U32* usage);
101
102    virtual status_t useBuffer(
103            node_id node, OMX_U32 port_index, const sp<IMemory> &params,
104            buffer_id *buffer, OMX_U32 allottedSize);
105
106    virtual status_t useGraphicBuffer(
107            node_id node, OMX_U32 port_index,
108            const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer);
109
110    virtual status_t updateGraphicBufferInMeta(
111            node_id node, OMX_U32 port_index,
112            const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer);
113
114    virtual status_t updateNativeHandleInMeta(
115            node_id node, OMX_U32 port_index,
116            const sp<NativeHandle> &nativeHandle, buffer_id buffer);
117
118    virtual status_t createInputSurface(
119            node_id node, OMX_U32 port_index, android_dataspace dataSpace,
120            sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type);
121
122    virtual status_t createPersistentInputSurface(
123            sp<IGraphicBufferProducer> *bufferProducer,
124            sp<IGraphicBufferConsumer> *bufferConsumer);
125
126    virtual status_t setInputSurface(
127            node_id node, OMX_U32 port_index,
128            const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type);
129
130    virtual status_t signalEndOfInputStream(node_id node);
131
132    virtual status_t allocateSecureBuffer(
133            node_id node, OMX_U32 port_index, size_t size,
134            buffer_id *buffer, void **buffer_data, sp<NativeHandle> *native_handle);
135
136    virtual status_t allocateBufferWithBackup(
137            node_id node, OMX_U32 port_index, const sp<IMemory> &params,
138            buffer_id *buffer, OMX_U32 allottedSize);
139
140    virtual status_t freeBuffer(
141            node_id node, OMX_U32 port_index, buffer_id buffer);
142
143    virtual status_t fillBuffer(node_id node, buffer_id buffer, int fenceFd);
144
145    virtual status_t emptyBuffer(
146            node_id node,
147            buffer_id buffer,
148            OMX_U32 range_offset, OMX_U32 range_length,
149            OMX_U32 flags, OMX_TICKS timestamp, int fenceFd);
150
151    virtual status_t getExtensionIndex(
152            node_id node,
153            const char *parameter_name,
154            OMX_INDEXTYPE *index);
155
156    virtual status_t setInternalOption(
157            node_id node,
158            OMX_U32 port_index,
159            InternalOptionType type,
160            const void *data,
161            size_t size);
162
163private:
164    mutable Mutex mLock;
165
166    sp<IOMX> mMediaServerOMX;
167    sp<IOMX> mMediaCodecOMX;
168    sp<IOMX> mLocalOMX;
169
170    typedef enum {
171        LOCAL,
172        MEDIAPROCESS,
173        CODECPROCESS
174    } node_location;
175
176    KeyedVector<node_id, node_location> mNodeLocation;
177
178    bool isLocalNode(node_id node) const;
179    bool isLocalNode_l(node_id node) const;
180    const sp<IOMX> &getOMX(node_id node) const;
181    const sp<IOMX> &getOMX_l(node_id node) const;
182
183    static node_location getPreferredCodecLocation(const char *name);
184
185    DISALLOW_EVIL_CONSTRUCTORS(MuxOMX);
186};
187
188MuxOMX::MuxOMX(const sp<IOMX> &mediaServerOMX, const sp<IOMX> &mediaCodecOMX)
189    : mMediaServerOMX(mediaServerOMX),
190      mMediaCodecOMX(mediaCodecOMX) {
191    ALOGI("MuxOMX ctor");
192}
193
194MuxOMX::~MuxOMX() {
195}
196
197bool MuxOMX::isLocalNode(node_id node) const {
198    Mutex::Autolock autoLock(mLock);
199
200    return isLocalNode_l(node);
201}
202
203bool MuxOMX::isLocalNode_l(node_id node) const {
204    return mNodeLocation.valueFor(node) == LOCAL;
205}
206
207// static
208MuxOMX::node_location MuxOMX::getPreferredCodecLocation(const char *name) {
209    if (sCodecProcessEnabled) {
210        // all codecs go to codec process unless excluded using system property, in which case
211        // all non-secure decoders, OMX.google.* codecs and encoders can go in the codec process
212        // (non-OMX.google.* encoders can be excluded using system property.)
213        if ((strcasestr(name, "decoder")
214                        && strcasestr(name, ".secure") != name + strlen(name) - 7)
215                || (strcasestr(name, "encoder")
216                        && !property_get_bool("media.stagefright.legacyencoder", false))
217                || !property_get_bool("media.stagefright.less-secure", false)
218                || !strncasecmp(name, "OMX.google.", 11)) {
219            return CODECPROCESS;
220        }
221        // everything else runs in the media server
222        return MEDIAPROCESS;
223    } else {
224#ifdef __LP64__
225        // 64 bit processes always run OMX remote on MediaServer
226        return MEDIAPROCESS;
227#else
228        // 32 bit processes run only OMX.google.* components locally
229        if (!strncasecmp(name, "OMX.google.", 11)) {
230            return LOCAL;
231        }
232        return MEDIAPROCESS;
233#endif
234    }
235}
236
237const sp<IOMX> &MuxOMX::getOMX(node_id node) const {
238    Mutex::Autolock autoLock(mLock);
239    return getOMX_l(node);
240}
241
242const sp<IOMX> &MuxOMX::getOMX_l(node_id node) const {
243    node_location loc = mNodeLocation.valueFor(node);
244    if (loc == LOCAL) {
245        return mLocalOMX;
246    } else if (loc == MEDIAPROCESS) {
247        return mMediaServerOMX;
248    } else if (loc == CODECPROCESS) {
249        return mMediaCodecOMX;
250    }
251    ALOGE("Couldn't determine node location for node %d: %d, using local", node, loc);
252    return mLocalOMX;
253}
254
255bool MuxOMX::livesLocally(node_id node, pid_t pid) {
256    return getOMX(node)->livesLocally(node, pid);
257}
258
259status_t MuxOMX::listNodes(List<ComponentInfo> *list) {
260    Mutex::Autolock autoLock(mLock);
261
262    if (mLocalOMX == NULL) {
263        mLocalOMX = new OMX;
264    }
265
266    return mLocalOMX->listNodes(list);
267}
268
269status_t MuxOMX::allocateNode(
270        const char *name, const sp<IOMXObserver> &observer,
271        sp<IBinder> *nodeBinder,
272        node_id *node) {
273    Mutex::Autolock autoLock(mLock);
274
275    sp<IOMX> omx;
276
277    node_location loc = getPreferredCodecLocation(name);
278    if (loc == CODECPROCESS) {
279        omx = mMediaCodecOMX;
280    } else if (loc == MEDIAPROCESS) {
281        omx = mMediaServerOMX;
282    } else {
283        if (mLocalOMX == NULL) {
284            mLocalOMX = new OMX;
285        }
286        omx = mLocalOMX;
287    }
288
289    status_t err = omx->allocateNode(name, observer, nodeBinder, node);
290    ALOGV("allocated node_id %x on %s OMX", *node, omx == mMediaCodecOMX ? "codecprocess" :
291            omx == mMediaServerOMX ? "mediaserver" : "local");
292
293
294    if (err != OK) {
295        return err;
296    }
297
298    mNodeLocation.add(*node, loc);
299
300    return OK;
301}
302
303status_t MuxOMX::freeNode(node_id node) {
304    Mutex::Autolock autoLock(mLock);
305
306    status_t err = getOMX_l(node)->freeNode(node);
307
308    if (err != OK) {
309        return err;
310    }
311
312    mNodeLocation.removeItem(node);
313
314    return OK;
315}
316
317status_t MuxOMX::sendCommand(
318        node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
319    return getOMX(node)->sendCommand(node, cmd, param);
320}
321
322status_t MuxOMX::getParameter(
323        node_id node, OMX_INDEXTYPE index,
324        void *params, size_t size) {
325    return getOMX(node)->getParameter(node, index, params, size);
326}
327
328status_t MuxOMX::setParameter(
329        node_id node, OMX_INDEXTYPE index,
330        const void *params, size_t size) {
331    return getOMX(node)->setParameter(node, index, params, size);
332}
333
334status_t MuxOMX::getConfig(
335        node_id node, OMX_INDEXTYPE index,
336        void *params, size_t size) {
337    return getOMX(node)->getConfig(node, index, params, size);
338}
339
340status_t MuxOMX::setConfig(
341        node_id node, OMX_INDEXTYPE index,
342        const void *params, size_t size) {
343    return getOMX(node)->setConfig(node, index, params, size);
344}
345
346status_t MuxOMX::getState(
347        node_id node, OMX_STATETYPE* state) {
348    return getOMX(node)->getState(node, state);
349}
350
351status_t MuxOMX::storeMetaDataInBuffers(
352        node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type) {
353    return getOMX(node)->storeMetaDataInBuffers(node, port_index, enable, type);
354}
355
356status_t MuxOMX::prepareForAdaptivePlayback(
357        node_id node, OMX_U32 port_index, OMX_BOOL enable,
358        OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) {
359    return getOMX(node)->prepareForAdaptivePlayback(
360            node, port_index, enable, maxFrameWidth, maxFrameHeight);
361}
362
363status_t MuxOMX::configureVideoTunnelMode(
364        node_id node, OMX_U32 portIndex, OMX_BOOL enable,
365        OMX_U32 audioHwSync, native_handle_t **sidebandHandle) {
366    return getOMX(node)->configureVideoTunnelMode(
367            node, portIndex, enable, audioHwSync, sidebandHandle);
368}
369
370status_t MuxOMX::enableNativeBuffers(
371        node_id node, OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable) {
372    return getOMX(node)->enableNativeBuffers(node, port_index, graphic, enable);
373}
374
375status_t MuxOMX::getGraphicBufferUsage(
376        node_id node, OMX_U32 port_index, OMX_U32* usage) {
377    return getOMX(node)->getGraphicBufferUsage(node, port_index, usage);
378}
379
380status_t MuxOMX::useBuffer(
381        node_id node, OMX_U32 port_index, const sp<IMemory> &params,
382        buffer_id *buffer, OMX_U32 allottedSize) {
383    return getOMX(node)->useBuffer(node, port_index, params, buffer, allottedSize);
384}
385
386status_t MuxOMX::useGraphicBuffer(
387        node_id node, OMX_U32 port_index,
388        const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
389    return getOMX(node)->useGraphicBuffer(
390            node, port_index, graphicBuffer, buffer);
391}
392
393status_t MuxOMX::updateGraphicBufferInMeta(
394        node_id node, OMX_U32 port_index,
395        const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) {
396    return getOMX(node)->updateGraphicBufferInMeta(
397            node, port_index, graphicBuffer, buffer);
398}
399
400status_t MuxOMX::updateNativeHandleInMeta(
401        node_id node, OMX_U32 port_index,
402        const sp<NativeHandle> &nativeHandle, buffer_id buffer) {
403    return getOMX(node)->updateNativeHandleInMeta(
404            node, port_index, nativeHandle, buffer);
405}
406
407status_t MuxOMX::createInputSurface(
408        node_id node, OMX_U32 port_index, android_dataspace dataSpace,
409        sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) {
410    status_t err = getOMX(node)->createInputSurface(
411            node, port_index, dataSpace, bufferProducer, type);
412    return err;
413}
414
415status_t MuxOMX::createPersistentInputSurface(
416        sp<IGraphicBufferProducer> *bufferProducer,
417        sp<IGraphicBufferConsumer> *bufferConsumer) {
418    sp<IOMX> omx;
419    {
420        Mutex::Autolock autoLock(mLock);
421        if (property_get_bool("media.stagefright.legacyencoder", false)) {
422            omx = mMediaServerOMX;
423        } else {
424            omx = mMediaCodecOMX;
425        }
426    }
427    return omx->createPersistentInputSurface(
428            bufferProducer, bufferConsumer);
429}
430
431status_t MuxOMX::setInputSurface(
432        node_id node, OMX_U32 port_index,
433        const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type) {
434    return getOMX(node)->setInputSurface(node, port_index, bufferConsumer, type);
435}
436
437status_t MuxOMX::signalEndOfInputStream(node_id node) {
438    return getOMX(node)->signalEndOfInputStream(node);
439}
440
441status_t MuxOMX::allocateSecureBuffer(
442        node_id node, OMX_U32 port_index, size_t size,
443        buffer_id *buffer, void **buffer_data, sp<NativeHandle> *native_handle) {
444    return getOMX(node)->allocateSecureBuffer(
445            node, port_index, size, buffer, buffer_data, native_handle);
446}
447
448status_t MuxOMX::allocateBufferWithBackup(
449        node_id node, OMX_U32 port_index, const sp<IMemory> &params,
450        buffer_id *buffer, OMX_U32 allottedSize) {
451    return getOMX(node)->allocateBufferWithBackup(
452            node, port_index, params, buffer, allottedSize);
453}
454
455status_t MuxOMX::freeBuffer(
456        node_id node, OMX_U32 port_index, buffer_id buffer) {
457    return getOMX(node)->freeBuffer(node, port_index, buffer);
458}
459
460status_t MuxOMX::fillBuffer(node_id node, buffer_id buffer, int fenceFd) {
461    return getOMX(node)->fillBuffer(node, buffer, fenceFd);
462}
463
464status_t MuxOMX::emptyBuffer(
465        node_id node,
466        buffer_id buffer,
467        OMX_U32 range_offset, OMX_U32 range_length,
468        OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
469    return getOMX(node)->emptyBuffer(
470            node, buffer, range_offset, range_length, flags, timestamp, fenceFd);
471}
472
473status_t MuxOMX::getExtensionIndex(
474        node_id node,
475        const char *parameter_name,
476        OMX_INDEXTYPE *index) {
477    return getOMX(node)->getExtensionIndex(node, parameter_name, index);
478}
479
480status_t MuxOMX::setInternalOption(
481        node_id node,
482        OMX_U32 port_index,
483        InternalOptionType type,
484        const void *data,
485        size_t size) {
486    return getOMX(node)->setInternalOption(node, port_index, type, data, size);
487}
488
489OMXClient::OMXClient() {
490    char value[PROPERTY_VALUE_MAX];
491    if (property_get("media.stagefright.codecremote", value, NULL)
492            && (!strcmp("0", value) || !strcasecmp("false", value))) {
493        sCodecProcessEnabled = false;
494    }
495}
496
497status_t OMXClient::connect() {
498    sp<IServiceManager> sm = defaultServiceManager();
499    sp<IBinder> playerbinder = sm->getService(String16("media.player"));
500    sp<IMediaPlayerService> mediaservice = interface_cast<IMediaPlayerService>(playerbinder);
501
502    if (mediaservice.get() == NULL) {
503        ALOGE("Cannot obtain IMediaPlayerService");
504        return NO_INIT;
505    }
506
507    sp<IOMX> mediaServerOMX = mediaservice->getOMX();
508    if (mediaServerOMX.get() == NULL) {
509        ALOGE("Cannot obtain mediaserver IOMX");
510        return NO_INIT;
511    }
512
513    // If we don't want to use the codec process, and the media server OMX
514    // is local, use it directly instead of going through MuxOMX
515    if (!sCodecProcessEnabled &&
516            mediaServerOMX->livesLocally(0 /* node */, getpid())) {
517        mOMX = mediaServerOMX;
518        return OK;
519    }
520
521    sp<IBinder> codecbinder = sm->getService(String16("media.codec"));
522    sp<IMediaCodecService> codecservice = interface_cast<IMediaCodecService>(codecbinder);
523
524    if (codecservice.get() == NULL) {
525        ALOGE("Cannot obtain IMediaCodecService");
526        return NO_INIT;
527    }
528
529    sp<IOMX> mediaCodecOMX = codecservice->getOMX();
530    if (mediaCodecOMX.get() == NULL) {
531        ALOGE("Cannot obtain mediacodec IOMX");
532        return NO_INIT;
533    }
534
535    mOMX = new MuxOMX(mediaServerOMX, mediaCodecOMX);
536
537    return OK;
538}
539
540void OMXClient::disconnect() {
541    if (mOMX.get() != NULL) {
542        mOMX.clear();
543        mOMX = NULL;
544    }
545}
546
547}  // namespace android
548