blob: ff72e0e20ab3972bfb19e04fd3b47f95e65f3725 [file] [log] [blame]
Andreas Huber20111aa2009-07-14 16:56:47 -07001/*
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
Andreas Huber20111aa2009-07-14 16:56:47 -070021#include <binder/IServiceManager.h>
22#include <media/IMediaPlayerService.h>
Andreas Hubere9c52da2012-01-30 11:48:02 -080023#include <media/stagefright/foundation/ADebug.h>
Andreas Huber20111aa2009-07-14 16:56:47 -070024#include <media/stagefright/OMXClient.h>
Andreas Hubere9c52da2012-01-30 11:48:02 -080025#include <utils/KeyedVector.h>
26
27#include "include/OMX.h"
Andreas Huber20111aa2009-07-14 16:56:47 -070028
29namespace android {
30
Andreas Hubere9c52da2012-01-30 11:48:02 -080031struct MuxOMX : public IOMX {
32 MuxOMX(const sp<IOMX> &remoteOMX);
33 virtual ~MuxOMX();
34
35 virtual IBinder *onAsBinder() { return NULL; }
36
Andreas Huberd459b482012-01-31 11:16:24 -080037 virtual bool livesLocally(node_id node, pid_t pid);
Andreas Hubere9c52da2012-01-30 11:48:02 -080038
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
Andy McFaddenf779bb52013-02-19 07:28:30 -080086 virtual status_t createInputSurface(
87 node_id node, OMX_U32 port_index,
88 sp<IGraphicBufferProducer> *bufferProducer);
89
90 virtual status_t signalEndOfInputStream(node_id node);
91
Andreas Hubere9c52da2012-01-30 11:48:02 -080092 virtual status_t allocateBuffer(
93 node_id node, OMX_U32 port_index, size_t size,
94 buffer_id *buffer, void **buffer_data);
95
96 virtual status_t allocateBufferWithBackup(
97 node_id node, OMX_U32 port_index, const sp<IMemory> &params,
98 buffer_id *buffer);
99
100 virtual status_t freeBuffer(
101 node_id node, OMX_U32 port_index, buffer_id buffer);
102
103 virtual status_t fillBuffer(node_id node, buffer_id buffer);
104
105 virtual status_t emptyBuffer(
106 node_id node,
107 buffer_id buffer,
108 OMX_U32 range_offset, OMX_U32 range_length,
109 OMX_U32 flags, OMX_TICKS timestamp);
110
111 virtual status_t getExtensionIndex(
112 node_id node,
113 const char *parameter_name,
114 OMX_INDEXTYPE *index);
115
116private:
117 mutable Mutex mLock;
118
119 sp<IOMX> mRemoteOMX;
120 sp<IOMX> mLocalOMX;
121
122 KeyedVector<node_id, bool> mIsLocalNode;
123
124 bool isLocalNode(node_id node) const;
125 bool isLocalNode_l(node_id node) const;
126 const sp<IOMX> &getOMX(node_id node) const;
127 const sp<IOMX> &getOMX_l(node_id node) const;
128
129 static bool IsSoftwareComponent(const char *name);
130
131 DISALLOW_EVIL_CONSTRUCTORS(MuxOMX);
132};
133
134MuxOMX::MuxOMX(const sp<IOMX> &remoteOMX)
135 : mRemoteOMX(remoteOMX) {
136}
137
138MuxOMX::~MuxOMX() {
139}
140
141bool MuxOMX::isLocalNode(node_id node) const {
142 Mutex::Autolock autoLock(mLock);
143
144 return isLocalNode_l(node);
145}
146
147bool MuxOMX::isLocalNode_l(node_id node) const {
148 return mIsLocalNode.indexOfKey(node) >= 0;
149}
150
151// static
152bool MuxOMX::IsSoftwareComponent(const char *name) {
153 return !strncasecmp(name, "OMX.google.", 11);
154}
155
156const sp<IOMX> &MuxOMX::getOMX(node_id node) const {
157 return isLocalNode(node) ? mLocalOMX : mRemoteOMX;
158}
159
160const sp<IOMX> &MuxOMX::getOMX_l(node_id node) const {
161 return isLocalNode_l(node) ? mLocalOMX : mRemoteOMX;
162}
163
Andreas Huberd459b482012-01-31 11:16:24 -0800164bool MuxOMX::livesLocally(node_id node, pid_t pid) {
165 return getOMX(node)->livesLocally(node, pid);
Andreas Hubere9c52da2012-01-30 11:48:02 -0800166}
167
168status_t MuxOMX::listNodes(List<ComponentInfo> *list) {
169 Mutex::Autolock autoLock(mLock);
170
171 if (mLocalOMX == NULL) {
172 mLocalOMX = new OMX;
173 }
174
175 return mLocalOMX->listNodes(list);
176}
177
178status_t MuxOMX::allocateNode(
179 const char *name, const sp<IOMXObserver> &observer,
180 node_id *node) {
181 Mutex::Autolock autoLock(mLock);
182
183 sp<IOMX> omx;
184
185 if (IsSoftwareComponent(name)) {
186 if (mLocalOMX == NULL) {
187 mLocalOMX = new OMX;
188 }
189 omx = mLocalOMX;
190 } else {
191 omx = mRemoteOMX;
192 }
193
194 status_t err = omx->allocateNode(name, observer, node);
195
196 if (err != OK) {
197 return err;
198 }
199
200 if (omx == mLocalOMX) {
201 mIsLocalNode.add(*node, true);
202 }
203
204 return OK;
205}
206
207status_t MuxOMX::freeNode(node_id node) {
208 Mutex::Autolock autoLock(mLock);
209
210 status_t err = getOMX_l(node)->freeNode(node);
211
212 if (err != OK) {
213 return err;
214 }
215
216 mIsLocalNode.removeItem(node);
217
218 return OK;
219}
220
221status_t MuxOMX::sendCommand(
222 node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
223 return getOMX(node)->sendCommand(node, cmd, param);
224}
225
226status_t MuxOMX::getParameter(
227 node_id node, OMX_INDEXTYPE index,
228 void *params, size_t size) {
229 return getOMX(node)->getParameter(node, index, params, size);
230}
231
232status_t MuxOMX::setParameter(
233 node_id node, OMX_INDEXTYPE index,
234 const void *params, size_t size) {
235 return getOMX(node)->setParameter(node, index, params, size);
236}
237
238status_t MuxOMX::getConfig(
239 node_id node, OMX_INDEXTYPE index,
240 void *params, size_t size) {
241 return getOMX(node)->getConfig(node, index, params, size);
242}
243
244status_t MuxOMX::setConfig(
245 node_id node, OMX_INDEXTYPE index,
246 const void *params, size_t size) {
247 return getOMX(node)->setConfig(node, index, params, size);
248}
249
250status_t MuxOMX::getState(
251 node_id node, OMX_STATETYPE* state) {
252 return getOMX(node)->getState(node, state);
253}
254
255status_t MuxOMX::storeMetaDataInBuffers(
256 node_id node, OMX_U32 port_index, OMX_BOOL enable) {
257 return getOMX(node)->storeMetaDataInBuffers(node, port_index, enable);
258}
259
260status_t MuxOMX::enableGraphicBuffers(
261 node_id node, OMX_U32 port_index, OMX_BOOL enable) {
262 return getOMX(node)->enableGraphicBuffers(node, port_index, enable);
263}
264
265status_t MuxOMX::getGraphicBufferUsage(
266 node_id node, OMX_U32 port_index, OMX_U32* usage) {
267 return getOMX(node)->getGraphicBufferUsage(node, port_index, usage);
268}
269
270status_t MuxOMX::useBuffer(
271 node_id node, OMX_U32 port_index, const sp<IMemory> &params,
272 buffer_id *buffer) {
273 return getOMX(node)->useBuffer(node, port_index, params, buffer);
274}
275
276status_t MuxOMX::useGraphicBuffer(
277 node_id node, OMX_U32 port_index,
278 const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
279 return getOMX(node)->useGraphicBuffer(
280 node, port_index, graphicBuffer, buffer);
281}
282
Andy McFaddenf779bb52013-02-19 07:28:30 -0800283status_t MuxOMX::createInputSurface(
284 node_id node, OMX_U32 port_index,
285 sp<IGraphicBufferProducer> *bufferProducer) {
286 status_t err = getOMX(node)->createInputSurface(
287 node, port_index, bufferProducer);
288 return err;
289}
290
291status_t MuxOMX::signalEndOfInputStream(node_id node) {
292 return getOMX(node)->signalEndOfInputStream(node);
293}
294
Andreas Hubere9c52da2012-01-30 11:48:02 -0800295status_t MuxOMX::allocateBuffer(
296 node_id node, OMX_U32 port_index, size_t size,
297 buffer_id *buffer, void **buffer_data) {
298 return getOMX(node)->allocateBuffer(
299 node, port_index, size, buffer, buffer_data);
300}
301
302status_t MuxOMX::allocateBufferWithBackup(
303 node_id node, OMX_U32 port_index, const sp<IMemory> &params,
304 buffer_id *buffer) {
305 return getOMX(node)->allocateBufferWithBackup(
306 node, port_index, params, buffer);
307}
308
309status_t MuxOMX::freeBuffer(
310 node_id node, OMX_U32 port_index, buffer_id buffer) {
311 return getOMX(node)->freeBuffer(node, port_index, buffer);
312}
313
314status_t MuxOMX::fillBuffer(node_id node, buffer_id buffer) {
315 return getOMX(node)->fillBuffer(node, buffer);
316}
317
318status_t MuxOMX::emptyBuffer(
319 node_id node,
320 buffer_id buffer,
321 OMX_U32 range_offset, OMX_U32 range_length,
322 OMX_U32 flags, OMX_TICKS timestamp) {
323 return getOMX(node)->emptyBuffer(
324 node, buffer, range_offset, range_length, flags, timestamp);
325}
326
327status_t MuxOMX::getExtensionIndex(
328 node_id node,
329 const char *parameter_name,
330 OMX_INDEXTYPE *index) {
331 return getOMX(node)->getExtensionIndex(node, parameter_name, index);
332}
333
Andreas Huber408b8e12009-08-07 13:45:06 -0700334OMXClient::OMXClient() {
Andreas Huber20111aa2009-07-14 16:56:47 -0700335}
336
Andreas Huber20111aa2009-07-14 16:56:47 -0700337status_t OMXClient::connect() {
Andreas Huber20111aa2009-07-14 16:56:47 -0700338 sp<IServiceManager> sm = defaultServiceManager();
339 sp<IBinder> binder = sm->getService(String16("media.player"));
340 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
341
Andreas Huber0c891992009-08-26 14:48:20 -0700342 CHECK(service.get() != NULL);
Andreas Huber20111aa2009-07-14 16:56:47 -0700343
Andreas Huber318ad9c2009-10-15 13:46:54 -0700344 mOMX = service->getOMX();
Andreas Huber0c891992009-08-26 14:48:20 -0700345 CHECK(mOMX.get() != NULL);
Andreas Huber20111aa2009-07-14 16:56:47 -0700346
Andreas Huberd459b482012-01-31 11:16:24 -0800347 if (!mOMX->livesLocally(NULL /* node */, getpid())) {
Andreas Hubere9c52da2012-01-30 11:48:02 -0800348 ALOGI("Using client-side OMX mux.");
349 mOMX = new MuxOMX(mOMX);
350 }
351
Andreas Huber20111aa2009-07-14 16:56:47 -0700352 return OK;
353}
354
355void OMXClient::disconnect() {
James Dong04394b12012-02-23 12:23:57 -0800356 if (mOMX.get() != NULL) {
357 mOMX.clear();
358 mOMX = NULL;
359 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700360}
361
362} // namespace android