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