OMXClient.cpp revision 8b1be2ca7cee71a4920d5d31fdcbad2b1d4ca49d
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#include <utils/Log.h>
20
21#include <binder/IServiceManager.h>
22#include <media/IMediaPlayerService.h>
23#include <media/stagefright/foundation/ADebug.h>
24#include <media/stagefright/OMXClient.h>
25#include <utils/KeyedVector.h>
26
27#include "include/OMX.h"
28
29namespace android {
30
31struct MuxOMX : public IOMX {
32    MuxOMX(const sp<IOMX> &remoteOMX);
33    virtual ~MuxOMX();
34
35    virtual IBinder *onAsBinder() { return mRemoteOMX->asBinder().get(); }
36
37    virtual bool livesLocally(node_id node, pid_t pid);
38
39    virtual status_t listNodes(List<ComponentInfo> *list);
40
41    virtual status_t allocateNode(
42            const char *name, const sp<IOMXObserver> &observer,
43            node_id *node);
44
45    virtual status_t freeNode(node_id node);
46
47    virtual status_t sendCommand(
48            node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param);
49
50    virtual status_t getParameter(
51            node_id node, OMX_INDEXTYPE index,
52            void *params, size_t size);
53
54    virtual status_t setParameter(
55            node_id node, OMX_INDEXTYPE index,
56            const void *params, size_t size);
57
58    virtual status_t getConfig(
59            node_id node, OMX_INDEXTYPE index,
60            void *params, size_t size);
61
62    virtual status_t setConfig(
63            node_id node, OMX_INDEXTYPE index,
64            const void *params, size_t size);
65
66    virtual status_t getState(
67            node_id node, OMX_STATETYPE* state);
68
69    virtual status_t storeMetaDataInBuffers(
70            node_id node, OMX_U32 port_index, OMX_BOOL enable);
71
72    virtual status_t prepareForAdaptivePlayback(
73            node_id node, OMX_U32 port_index, OMX_BOOL enable,
74            OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight);
75
76    virtual status_t enableGraphicBuffers(
77            node_id node, OMX_U32 port_index, OMX_BOOL enable);
78
79    virtual status_t getGraphicBufferUsage(
80            node_id node, OMX_U32 port_index, OMX_U32* usage);
81
82    virtual status_t useBuffer(
83            node_id node, OMX_U32 port_index, const sp<IMemory> &params,
84            buffer_id *buffer);
85
86    virtual status_t useGraphicBuffer(
87            node_id node, OMX_U32 port_index,
88            const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer);
89
90    virtual status_t updateGraphicBufferInMeta(
91            node_id node, OMX_U32 port_index,
92            const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer);
93
94    virtual status_t createInputSurface(
95            node_id node, OMX_U32 port_index,
96            sp<IGraphicBufferProducer> *bufferProducer);
97
98    virtual status_t signalEndOfInputStream(node_id node);
99
100    virtual status_t allocateBuffer(
101            node_id node, OMX_U32 port_index, size_t size,
102            buffer_id *buffer, void **buffer_data);
103
104    virtual status_t allocateBufferWithBackup(
105            node_id node, OMX_U32 port_index, const sp<IMemory> &params,
106            buffer_id *buffer);
107
108    virtual status_t freeBuffer(
109            node_id node, OMX_U32 port_index, buffer_id buffer);
110
111    virtual status_t fillBuffer(node_id node, buffer_id buffer);
112
113    virtual status_t emptyBuffer(
114            node_id node,
115            buffer_id buffer,
116            OMX_U32 range_offset, OMX_U32 range_length,
117            OMX_U32 flags, OMX_TICKS timestamp);
118
119    virtual status_t getExtensionIndex(
120            node_id node,
121            const char *parameter_name,
122            OMX_INDEXTYPE *index);
123
124    virtual status_t setInternalOption(
125            node_id node,
126            OMX_U32 port_index,
127            InternalOptionType type,
128            const void *data,
129            size_t size);
130
131private:
132    mutable Mutex mLock;
133
134    sp<IOMX> mRemoteOMX;
135    sp<IOMX> mLocalOMX;
136
137    KeyedVector<node_id, bool> mIsLocalNode;
138
139    bool isLocalNode(node_id node) const;
140    bool isLocalNode_l(node_id node) const;
141    const sp<IOMX> &getOMX(node_id node) const;
142    const sp<IOMX> &getOMX_l(node_id node) const;
143
144    static bool CanLiveLocally(const char *name);
145
146    DISALLOW_EVIL_CONSTRUCTORS(MuxOMX);
147};
148
149MuxOMX::MuxOMX(const sp<IOMX> &remoteOMX)
150    : mRemoteOMX(remoteOMX) {
151}
152
153MuxOMX::~MuxOMX() {
154}
155
156bool MuxOMX::isLocalNode(node_id node) const {
157    Mutex::Autolock autoLock(mLock);
158
159    return isLocalNode_l(node);
160}
161
162bool MuxOMX::isLocalNode_l(node_id node) const {
163    return mIsLocalNode.indexOfKey(node) >= 0;
164}
165
166// static
167bool MuxOMX::CanLiveLocally(const char *name) {
168    return !strncasecmp(name, "OMX.google.", 11);
169}
170
171const sp<IOMX> &MuxOMX::getOMX(node_id node) const {
172    return isLocalNode(node) ? mLocalOMX : mRemoteOMX;
173}
174
175const sp<IOMX> &MuxOMX::getOMX_l(node_id node) const {
176    return isLocalNode_l(node) ? mLocalOMX : mRemoteOMX;
177}
178
179bool MuxOMX::livesLocally(node_id node, pid_t pid) {
180    return getOMX(node)->livesLocally(node, pid);
181}
182
183status_t MuxOMX::listNodes(List<ComponentInfo> *list) {
184    Mutex::Autolock autoLock(mLock);
185
186    if (mLocalOMX == NULL) {
187        mLocalOMX = new OMX;
188    }
189
190    return mLocalOMX->listNodes(list);
191}
192
193status_t MuxOMX::allocateNode(
194        const char *name, const sp<IOMXObserver> &observer,
195        node_id *node) {
196    Mutex::Autolock autoLock(mLock);
197
198    sp<IOMX> omx;
199
200    if (CanLiveLocally(name)) {
201        if (mLocalOMX == NULL) {
202            mLocalOMX = new OMX;
203        }
204        omx = mLocalOMX;
205    } else {
206        omx = mRemoteOMX;
207    }
208
209    status_t err = omx->allocateNode(name, observer, node);
210
211    if (err != OK) {
212        return err;
213    }
214
215    if (omx == mLocalOMX) {
216        mIsLocalNode.add(*node, true);
217    }
218
219    return OK;
220}
221
222status_t MuxOMX::freeNode(node_id node) {
223    Mutex::Autolock autoLock(mLock);
224
225    status_t err = getOMX_l(node)->freeNode(node);
226
227    if (err != OK) {
228        return err;
229    }
230
231    mIsLocalNode.removeItem(node);
232
233    return OK;
234}
235
236status_t MuxOMX::sendCommand(
237        node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
238    return getOMX(node)->sendCommand(node, cmd, param);
239}
240
241status_t MuxOMX::getParameter(
242        node_id node, OMX_INDEXTYPE index,
243        void *params, size_t size) {
244    return getOMX(node)->getParameter(node, index, params, size);
245}
246
247status_t MuxOMX::setParameter(
248        node_id node, OMX_INDEXTYPE index,
249        const void *params, size_t size) {
250    return getOMX(node)->setParameter(node, index, params, size);
251}
252
253status_t MuxOMX::getConfig(
254        node_id node, OMX_INDEXTYPE index,
255        void *params, size_t size) {
256    return getOMX(node)->getConfig(node, index, params, size);
257}
258
259status_t MuxOMX::setConfig(
260        node_id node, OMX_INDEXTYPE index,
261        const void *params, size_t size) {
262    return getOMX(node)->setConfig(node, index, params, size);
263}
264
265status_t MuxOMX::getState(
266        node_id node, OMX_STATETYPE* state) {
267    return getOMX(node)->getState(node, state);
268}
269
270status_t MuxOMX::storeMetaDataInBuffers(
271        node_id node, OMX_U32 port_index, OMX_BOOL enable) {
272    return getOMX(node)->storeMetaDataInBuffers(node, port_index, enable);
273}
274
275status_t MuxOMX::prepareForAdaptivePlayback(
276        node_id node, OMX_U32 port_index, OMX_BOOL enable,
277        OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) {
278    return getOMX(node)->prepareForAdaptivePlayback(
279            node, port_index, enable, maxFrameWidth, maxFrameHeight);
280}
281
282status_t MuxOMX::enableGraphicBuffers(
283        node_id node, OMX_U32 port_index, OMX_BOOL enable) {
284    return getOMX(node)->enableGraphicBuffers(node, port_index, enable);
285}
286
287status_t MuxOMX::getGraphicBufferUsage(
288        node_id node, OMX_U32 port_index, OMX_U32* usage) {
289    return getOMX(node)->getGraphicBufferUsage(node, port_index, usage);
290}
291
292status_t MuxOMX::useBuffer(
293        node_id node, OMX_U32 port_index, const sp<IMemory> &params,
294        buffer_id *buffer) {
295    return getOMX(node)->useBuffer(node, port_index, params, buffer);
296}
297
298status_t MuxOMX::useGraphicBuffer(
299        node_id node, OMX_U32 port_index,
300        const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
301    return getOMX(node)->useGraphicBuffer(
302            node, port_index, graphicBuffer, buffer);
303}
304
305status_t MuxOMX::updateGraphicBufferInMeta(
306        node_id node, OMX_U32 port_index,
307        const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) {
308    return getOMX(node)->updateGraphicBufferInMeta(
309            node, port_index, graphicBuffer, buffer);
310}
311
312status_t MuxOMX::createInputSurface(
313        node_id node, OMX_U32 port_index,
314        sp<IGraphicBufferProducer> *bufferProducer) {
315    status_t err = getOMX(node)->createInputSurface(
316            node, port_index, bufferProducer);
317    return err;
318}
319
320status_t MuxOMX::signalEndOfInputStream(node_id node) {
321    return getOMX(node)->signalEndOfInputStream(node);
322}
323
324status_t MuxOMX::allocateBuffer(
325        node_id node, OMX_U32 port_index, size_t size,
326        buffer_id *buffer, void **buffer_data) {
327    return getOMX(node)->allocateBuffer(
328            node, port_index, size, buffer, buffer_data);
329}
330
331status_t MuxOMX::allocateBufferWithBackup(
332        node_id node, OMX_U32 port_index, const sp<IMemory> &params,
333        buffer_id *buffer) {
334    return getOMX(node)->allocateBufferWithBackup(
335            node, port_index, params, buffer);
336}
337
338status_t MuxOMX::freeBuffer(
339        node_id node, OMX_U32 port_index, buffer_id buffer) {
340    return getOMX(node)->freeBuffer(node, port_index, buffer);
341}
342
343status_t MuxOMX::fillBuffer(node_id node, buffer_id buffer) {
344    return getOMX(node)->fillBuffer(node, buffer);
345}
346
347status_t MuxOMX::emptyBuffer(
348        node_id node,
349        buffer_id buffer,
350        OMX_U32 range_offset, OMX_U32 range_length,
351        OMX_U32 flags, OMX_TICKS timestamp) {
352    return getOMX(node)->emptyBuffer(
353            node, buffer, range_offset, range_length, flags, timestamp);
354}
355
356status_t MuxOMX::getExtensionIndex(
357        node_id node,
358        const char *parameter_name,
359        OMX_INDEXTYPE *index) {
360    return getOMX(node)->getExtensionIndex(node, parameter_name, index);
361}
362
363status_t MuxOMX::setInternalOption(
364        node_id node,
365        OMX_U32 port_index,
366        InternalOptionType type,
367        const void *data,
368        size_t size) {
369    return getOMX(node)->setInternalOption(node, port_index, type, data, size);
370}
371
372OMXClient::OMXClient() {
373}
374
375status_t OMXClient::connect() {
376    sp<IServiceManager> sm = defaultServiceManager();
377    sp<IBinder> binder = sm->getService(String16("media.player"));
378    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
379
380    CHECK(service.get() != NULL);
381
382    mOMX = service->getOMX();
383    CHECK(mOMX.get() != NULL);
384
385    if (!mOMX->livesLocally(0 /* node */, getpid())) {
386        ALOGI("Using client-side OMX mux.");
387        mOMX = new MuxOMX(mOMX);
388    }
389
390    return OK;
391}
392
393void OMXClient::disconnect() {
394    if (mOMX.get() != NULL) {
395        mOMX.clear();
396        mOMX = NULL;
397    }
398}
399
400}  // namespace android
401