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