OMXClient.cpp revision d291c222357303b9611cab89d0c3b047584ef377
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
34namespace android {
35
36struct MuxOMX : public IOMX {
37    MuxOMX(const sp<IOMX> &remoteOMX);
38    virtual ~MuxOMX();
39
40    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);
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 createPersistentInputSurface(
108            sp<IGraphicBufferProducer> *bufferProducer,
109            sp<IGraphicBufferConsumer> *bufferConsumer);
110
111    virtual status_t usePersistentInputSurface(
112            node_id node, OMX_U32 port_index,
113            const sp<IGraphicBufferConsumer> &bufferConsumer);
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);
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);
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);
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
148private:
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
166MuxOMX::MuxOMX(const sp<IOMX> &remoteOMX)
167    : mRemoteOMX(remoteOMX) {
168}
169
170MuxOMX::~MuxOMX() {
171}
172
173bool MuxOMX::isLocalNode(node_id node) const {
174    Mutex::Autolock autoLock(mLock);
175
176    return isLocalNode_l(node);
177}
178
179bool MuxOMX::isLocalNode_l(node_id node) const {
180    return mIsLocalNode.indexOfKey(node) >= 0;
181}
182
183// static
184bool 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
195const sp<IOMX> &MuxOMX::getOMX(node_id node) const {
196    return isLocalNode(node) ? mLocalOMX : mRemoteOMX;
197}
198
199const sp<IOMX> &MuxOMX::getOMX_l(node_id node) const {
200    return isLocalNode_l(node) ? mLocalOMX : mRemoteOMX;
201}
202
203bool MuxOMX::livesLocally(node_id node, pid_t pid) {
204    return getOMX(node)->livesLocally(node, pid);
205}
206
207status_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
217status_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
246status_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
260status_t MuxOMX::sendCommand(
261        node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
262    return getOMX(node)->sendCommand(node, cmd, param);
263}
264
265status_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
271status_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
277status_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
283status_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
289status_t MuxOMX::getState(
290        node_id node, OMX_STATETYPE* state) {
291    return getOMX(node)->getState(node, state);
292}
293
294status_t MuxOMX::storeMetaDataInBuffers(
295        node_id node, OMX_U32 port_index, OMX_BOOL enable) {
296    return getOMX(node)->storeMetaDataInBuffers(node, port_index, enable);
297}
298
299status_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
306status_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
313status_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
318status_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
323status_t MuxOMX::useBuffer(
324        node_id node, OMX_U32 port_index, const sp<IMemory> &params,
325        buffer_id *buffer) {
326    return getOMX(node)->useBuffer(node, port_index, params, buffer);
327}
328
329status_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
336status_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
343status_t MuxOMX::createInputSurface(
344        node_id node, OMX_U32 port_index,
345        sp<IGraphicBufferProducer> *bufferProducer) {
346    status_t err = getOMX(node)->createInputSurface(
347            node, port_index, bufferProducer);
348    return err;
349}
350
351status_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
359status_t MuxOMX::usePersistentInputSurface(
360        node_id node, OMX_U32 port_index,
361        const sp<IGraphicBufferConsumer> &bufferConsumer) {
362    return getOMX(node)->usePersistentInputSurface(
363            node, port_index, bufferConsumer);
364}
365
366status_t MuxOMX::signalEndOfInputStream(node_id node) {
367    return getOMX(node)->signalEndOfInputStream(node);
368}
369
370status_t MuxOMX::allocateBuffer(
371        node_id node, OMX_U32 port_index, size_t size,
372        buffer_id *buffer, void **buffer_data) {
373    return getOMX(node)->allocateBuffer(
374            node, port_index, size, buffer, buffer_data);
375}
376
377status_t MuxOMX::allocateBufferWithBackup(
378        node_id node, OMX_U32 port_index, const sp<IMemory> &params,
379        buffer_id *buffer) {
380    return getOMX(node)->allocateBufferWithBackup(
381            node, port_index, params, buffer);
382}
383
384status_t MuxOMX::freeBuffer(
385        node_id node, OMX_U32 port_index, buffer_id buffer) {
386    return getOMX(node)->freeBuffer(node, port_index, buffer);
387}
388
389status_t MuxOMX::fillBuffer(node_id node, buffer_id buffer) {
390    return getOMX(node)->fillBuffer(node, buffer);
391}
392
393status_t MuxOMX::emptyBuffer(
394        node_id node,
395        buffer_id buffer,
396        OMX_U32 range_offset, OMX_U32 range_length,
397        OMX_U32 flags, OMX_TICKS timestamp) {
398    return getOMX(node)->emptyBuffer(
399            node, buffer, range_offset, range_length, flags, timestamp);
400}
401
402status_t MuxOMX::getExtensionIndex(
403        node_id node,
404        const char *parameter_name,
405        OMX_INDEXTYPE *index) {
406    return getOMX(node)->getExtensionIndex(node, parameter_name, index);
407}
408
409status_t MuxOMX::setInternalOption(
410        node_id node,
411        OMX_U32 port_index,
412        InternalOptionType type,
413        const void *data,
414        size_t size) {
415    return getOMX(node)->setInternalOption(node, port_index, type, data, size);
416}
417
418OMXClient::OMXClient() {
419}
420
421status_t OMXClient::connect() {
422    sp<IServiceManager> sm = defaultServiceManager();
423    sp<IBinder> binder = sm->getService(String16("media.player"));
424    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
425
426    if (service.get() == NULL) {
427        ALOGE("Cannot obtain IMediaPlayerService");
428        return NO_INIT;
429    }
430
431    mOMX = service->getOMX();
432    if (mOMX.get() == NULL) {
433        ALOGE("Cannot obtain IOMX");
434        return NO_INIT;
435    }
436
437    if (!mOMX->livesLocally(0 /* node */, getpid())) {
438        ALOGI("Using client-side OMX mux.");
439        mOMX = new MuxOMX(mOMX);
440    }
441
442    return OK;
443}
444
445void OMXClient::disconnect() {
446    if (mOMX.get() != NULL) {
447        mOMX.clear();
448        mOMX = NULL;
449    }
450}
451
452}  // namespace android
453