OMXClient.cpp revision 5a446aafff3020d607ad6fb14cc7ae76dd8f7947
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 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
140private:
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
158MuxOMX::MuxOMX(const sp<IOMX> &remoteOMX)
159    : mRemoteOMX(remoteOMX) {
160}
161
162MuxOMX::~MuxOMX() {
163}
164
165bool MuxOMX::isLocalNode(node_id node) const {
166    Mutex::Autolock autoLock(mLock);
167
168    return isLocalNode_l(node);
169}
170
171bool MuxOMX::isLocalNode_l(node_id node) const {
172    return mIsLocalNode.indexOfKey(node) >= 0;
173}
174
175// static
176bool 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
187const sp<IOMX> &MuxOMX::getOMX(node_id node) const {
188    return isLocalNode(node) ? mLocalOMX : mRemoteOMX;
189}
190
191const sp<IOMX> &MuxOMX::getOMX_l(node_id node) const {
192    return isLocalNode_l(node) ? mLocalOMX : mRemoteOMX;
193}
194
195bool MuxOMX::livesLocally(node_id node, pid_t pid) {
196    return getOMX(node)->livesLocally(node, pid);
197}
198
199status_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
209status_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
238status_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
252status_t MuxOMX::sendCommand(
253        node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
254    return getOMX(node)->sendCommand(node, cmd, param);
255}
256
257status_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
263status_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
269status_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
275status_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
281status_t MuxOMX::getState(
282        node_id node, OMX_STATETYPE* state) {
283    return getOMX(node)->getState(node, state);
284}
285
286status_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
291status_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
298status_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
305status_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
310status_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
315status_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
321status_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
328status_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
335status_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
343status_t MuxOMX::signalEndOfInputStream(node_id node) {
344    return getOMX(node)->signalEndOfInputStream(node);
345}
346
347status_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
354status_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
361status_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
366status_t MuxOMX::fillBuffer(node_id node, buffer_id buffer) {
367    return getOMX(node)->fillBuffer(node, buffer);
368}
369
370status_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
379status_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
386status_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
395OMXClient::OMXClient() {
396}
397
398status_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
416void OMXClient::disconnect() {
417    if (mOMX.get() != NULL) {
418        mOMX.clear();
419        mOMX = NULL;
420    }
421}
422
423}  // namespace android
424