blob: d1dbc5c03cbd6e441aeac627852eb35698591f8e [file] [log] [blame]
Andreas Huber20111aa2009-07-14 16:56:47 -07001//#define LOG_NDEBUG 0
2#define LOG_TAG "IOMX"
3#include <utils/Log.h>
4
5#include <binder/IMemory.h>
6#include <binder/Parcel.h>
7#include <media/IOMX.h>
Andreas Huber8b938cd2009-07-31 11:52:50 -07008#include <ui/ISurface.h>
Andreas Huberf4148b52009-08-07 12:01:29 -07009#include <ui/Surface.h>
Andreas Huber20111aa2009-07-14 16:56:47 -070010
11namespace android {
12
13enum {
14 CONNECT = IBinder::FIRST_CALL_TRANSACTION,
15 LIST_NODES,
16 ALLOCATE_NODE,
17 FREE_NODE,
18 SEND_COMMAND,
19 GET_PARAMETER,
20 SET_PARAMETER,
21 USE_BUFFER,
22 ALLOC_BUFFER,
23 ALLOC_BUFFER_WITH_BACKUP,
24 FREE_BUFFER,
25 OBSERVE_NODE,
26 FILL_BUFFER,
27 EMPTY_BUFFER,
Andreas Huber8b938cd2009-07-31 11:52:50 -070028 CREATE_RENDERER,
Andreas Huber20111aa2009-07-14 16:56:47 -070029 OBSERVER_ON_MSG,
Andreas Huber8b938cd2009-07-31 11:52:50 -070030 RENDERER_RENDER,
Andreas Huber20111aa2009-07-14 16:56:47 -070031};
32
Andreas Huberf4148b52009-08-07 12:01:29 -070033sp<IOMXRenderer> IOMX::createRenderer(
34 const sp<Surface> &surface,
35 const char *componentName,
36 OMX_COLOR_FORMATTYPE colorFormat,
37 size_t encodedWidth, size_t encodedHeight,
38 size_t displayWidth, size_t displayHeight) {
39 return createRenderer(
40 surface->getISurface(),
41 componentName, colorFormat, encodedWidth, encodedHeight,
42 displayWidth, displayHeight);
43}
44
Andreas Huber20111aa2009-07-14 16:56:47 -070045static void *readVoidStar(const Parcel *parcel) {
46 // FIX if sizeof(void *) != sizeof(int32)
47 return (void *)parcel->readInt32();
48}
49
50static void writeVoidStar(void *x, Parcel *parcel) {
51 // FIX if sizeof(void *) != sizeof(int32)
52 parcel->writeInt32((int32_t)x);
53}
54
55class BpOMX : public BpInterface<IOMX> {
56public:
57 BpOMX(const sp<IBinder> &impl)
58 : BpInterface<IOMX>(impl) {
59 }
60
Andreas Huber20111aa2009-07-14 16:56:47 -070061 virtual status_t list_nodes(List<String8> *list) {
62 list->clear();
63
64 Parcel data, reply;
65 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
66 remote()->transact(LIST_NODES, data, &reply);
67
68 int32_t n = reply.readInt32();
69 for (int32_t i = 0; i < n; ++i) {
70 String8 s = reply.readString8();
71
72 list->push_back(s);
73 }
74
75 return OK;
76 }
77
78 virtual status_t allocate_node(const char *name, node_id *node) {
79 Parcel data, reply;
80 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
81 data.writeCString(name);
82 remote()->transact(ALLOCATE_NODE, data, &reply);
83
84 status_t err = reply.readInt32();
85 if (err == OK) {
86 *node = readVoidStar(&reply);
87 } else {
88 *node = 0;
89 }
90
91 return err;
92 }
93
94 virtual status_t free_node(node_id node) {
95 Parcel data, reply;
96 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
97 writeVoidStar(node, &data);
98 remote()->transact(FREE_NODE, data, &reply);
99
100 return reply.readInt32();
101 }
102
103 virtual status_t send_command(
104 node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
105 Parcel data, reply;
106 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
107 writeVoidStar(node, &data);
108 data.writeInt32(cmd);
109 data.writeInt32(param);
110 remote()->transact(SEND_COMMAND, data, &reply);
111
112 return reply.readInt32();
113 }
114
115 virtual status_t get_parameter(
116 node_id node, OMX_INDEXTYPE index,
117 void *params, size_t size) {
118 Parcel data, reply;
119 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
120 writeVoidStar(node, &data);
121 data.writeInt32(index);
122 data.writeInt32(size);
123 data.write(params, size);
124 remote()->transact(GET_PARAMETER, data, &reply);
125
126 status_t err = reply.readInt32();
127 if (err != OK) {
128 return err;
129 }
130
131 reply.read(params, size);
132
133 return OK;
134 }
135
136 virtual status_t set_parameter(
137 node_id node, OMX_INDEXTYPE index,
138 const void *params, size_t size) {
139 Parcel data, reply;
140 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
141 writeVoidStar(node, &data);
142 data.writeInt32(index);
143 data.writeInt32(size);
144 data.write(params, size);
145 remote()->transact(SET_PARAMETER, data, &reply);
146
147 return reply.readInt32();
148 }
149
150 virtual status_t use_buffer(
151 node_id node, OMX_U32 port_index, const sp<IMemory> &params,
152 buffer_id *buffer) {
153 Parcel data, reply;
154 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
155 writeVoidStar(node, &data);
156 data.writeInt32(port_index);
157 data.writeStrongBinder(params->asBinder());
158 remote()->transact(USE_BUFFER, data, &reply);
159
160 status_t err = reply.readInt32();
161 if (err != OK) {
162 *buffer = 0;
163
164 return err;
165 }
166
167 *buffer = readVoidStar(&reply);
168
169 return err;
170 }
171
172 virtual status_t allocate_buffer(
173 node_id node, OMX_U32 port_index, size_t size,
174 buffer_id *buffer) {
175 Parcel data, reply;
176 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
177 writeVoidStar(node, &data);
178 data.writeInt32(port_index);
179 data.writeInt32(size);
180 remote()->transact(ALLOC_BUFFER, data, &reply);
181
182 status_t err = reply.readInt32();
183 if (err != OK) {
184 *buffer = 0;
185
186 return err;
187 }
188
189 *buffer = readVoidStar(&reply);
190
191 return err;
192 }
193
194 virtual status_t allocate_buffer_with_backup(
195 node_id node, OMX_U32 port_index, const sp<IMemory> &params,
196 buffer_id *buffer) {
197 Parcel data, reply;
198 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
199 writeVoidStar(node, &data);
200 data.writeInt32(port_index);
201 data.writeStrongBinder(params->asBinder());
202 remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply);
203
204 status_t err = reply.readInt32();
205 if (err != OK) {
206 *buffer = 0;
207
208 return err;
209 }
210
211 *buffer = readVoidStar(&reply);
212
213 return err;
214 }
215
216 virtual status_t free_buffer(
217 node_id node, OMX_U32 port_index, buffer_id buffer) {
218 Parcel data, reply;
219 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
220 writeVoidStar(node, &data);
221 data.writeInt32(port_index);
222 writeVoidStar(buffer, &data);
223 remote()->transact(FREE_BUFFER, data, &reply);
224
225 return reply.readInt32();
226 }
227
Andreas Huber20111aa2009-07-14 16:56:47 -0700228 virtual status_t observe_node(
229 node_id node, const sp<IOMXObserver> &observer) {
230 Parcel data, reply;
231 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
232 writeVoidStar(node, &data);
233 data.writeStrongBinder(observer->asBinder());
234 remote()->transact(OBSERVE_NODE, data, &reply);
235
236 return reply.readInt32();
237 }
238
239 virtual void fill_buffer(node_id node, buffer_id buffer) {
240 Parcel data, reply;
241 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
242 writeVoidStar(node, &data);
243 writeVoidStar(buffer, &data);
244 remote()->transact(FILL_BUFFER, data, &reply, IBinder::FLAG_ONEWAY);
245 }
246
247 virtual void empty_buffer(
248 node_id node,
249 buffer_id buffer,
250 OMX_U32 range_offset, OMX_U32 range_length,
251 OMX_U32 flags, OMX_TICKS timestamp) {
252 Parcel data, reply;
253 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
254 writeVoidStar(node, &data);
255 writeVoidStar(buffer, &data);
256 data.writeInt32(range_offset);
257 data.writeInt32(range_length);
258 data.writeInt32(flags);
259 data.writeInt64(timestamp);
260 remote()->transact(EMPTY_BUFFER, data, &reply, IBinder::FLAG_ONEWAY);
261 }
Andreas Huber8b938cd2009-07-31 11:52:50 -0700262
263 virtual sp<IOMXRenderer> createRenderer(
264 const sp<ISurface> &surface,
265 const char *componentName,
266 OMX_COLOR_FORMATTYPE colorFormat,
267 size_t encodedWidth, size_t encodedHeight,
268 size_t displayWidth, size_t displayHeight) {
269 Parcel data, reply;
270 data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
271
272 data.writeStrongBinder(surface->asBinder());
273 data.writeCString(componentName);
274 data.writeInt32(colorFormat);
275 data.writeInt32(encodedWidth);
276 data.writeInt32(encodedHeight);
277 data.writeInt32(displayWidth);
278 data.writeInt32(displayHeight);
279
280 remote()->transact(CREATE_RENDERER, data, &reply);
281
282 return interface_cast<IOMXRenderer>(reply.readStrongBinder());
283 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700284};
285
286IMPLEMENT_META_INTERFACE(OMX, "android.hardware.IOMX");
287
288////////////////////////////////////////////////////////////////////////////////
289
290#define CHECK_INTERFACE(interface, data, reply) \
291 do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
292 LOGW("Call incorrectly routed to " #interface); \
293 return PERMISSION_DENIED; \
294 } } while (0)
295
296status_t BnOMX::onTransact(
297 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
298 switch (code) {
Andreas Huber20111aa2009-07-14 16:56:47 -0700299 case LIST_NODES:
300 {
301 CHECK_INTERFACE(IOMX, data, reply);
302
303 List<String8> list;
304 list_nodes(&list);
305
306 reply->writeInt32(list.size());
307 for (List<String8>::iterator it = list.begin();
308 it != list.end(); ++it) {
309 reply->writeString8(*it);
310 }
311
312 return NO_ERROR;
313 }
314
315 case ALLOCATE_NODE:
316 {
317 CHECK_INTERFACE(IOMX, data, reply);
318
319 node_id node;
320 status_t err = allocate_node(data.readCString(), &node);
321 reply->writeInt32(err);
322 if (err == OK) {
323 writeVoidStar(node, reply);
324 }
325
326 return NO_ERROR;
327 }
328
329 case FREE_NODE:
330 {
331 CHECK_INTERFACE(IOMX, data, reply);
332
333 node_id node = readVoidStar(&data);
334
335 reply->writeInt32(free_node(node));
336
337 return NO_ERROR;
338 }
339
340 case SEND_COMMAND:
341 {
342 CHECK_INTERFACE(IOMX, data, reply);
343
344 node_id node = readVoidStar(&data);
345
346 OMX_COMMANDTYPE cmd =
347 static_cast<OMX_COMMANDTYPE>(data.readInt32());
348
349 OMX_S32 param = data.readInt32();
350 reply->writeInt32(send_command(node, cmd, param));
351
352 return NO_ERROR;
353 }
354
355 case GET_PARAMETER:
356 {
357 CHECK_INTERFACE(IOMX, data, reply);
358
359 node_id node = readVoidStar(&data);
360 OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
361
362 size_t size = data.readInt32();
363
364 // XXX I am not happy with this but Parcel::readInplace didn't work.
365 void *params = malloc(size);
366 data.read(params, size);
367
368 status_t err = get_parameter(node, index, params, size);
369
370 reply->writeInt32(err);
371
372 if (err == OK) {
373 reply->write(params, size);
374 }
375
376 free(params);
377 params = NULL;
378
379 return NO_ERROR;
380 }
381
382 case SET_PARAMETER:
383 {
384 CHECK_INTERFACE(IOMX, data, reply);
385
386 node_id node = readVoidStar(&data);
387 OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
388
389 size_t size = data.readInt32();
390 void *params = const_cast<void *>(data.readInplace(size));
391
392 reply->writeInt32(set_parameter(node, index, params, size));
393
394 return NO_ERROR;
395 }
396
397 case USE_BUFFER:
398 {
399 CHECK_INTERFACE(IOMX, data, reply);
400
401 node_id node = readVoidStar(&data);
402 OMX_U32 port_index = data.readInt32();
403 sp<IMemory> params =
404 interface_cast<IMemory>(data.readStrongBinder());
405
406 buffer_id buffer;
407 status_t err = use_buffer(node, port_index, params, &buffer);
408 reply->writeInt32(err);
409
410 if (err == OK) {
411 writeVoidStar(buffer, reply);
412 }
413
414 return NO_ERROR;
415 }
416
417 case ALLOC_BUFFER:
418 {
419 CHECK_INTERFACE(IOMX, data, reply);
420
421 node_id node = readVoidStar(&data);
422 OMX_U32 port_index = data.readInt32();
423 size_t size = data.readInt32();
424
425 buffer_id buffer;
426 status_t err = allocate_buffer(node, port_index, size, &buffer);
427 reply->writeInt32(err);
428
429 if (err == OK) {
430 writeVoidStar(buffer, reply);
431 }
432
433 return NO_ERROR;
434 }
435
436 case ALLOC_BUFFER_WITH_BACKUP:
437 {
438 CHECK_INTERFACE(IOMX, data, reply);
439
440 node_id node = readVoidStar(&data);
441 OMX_U32 port_index = data.readInt32();
442 sp<IMemory> params =
443 interface_cast<IMemory>(data.readStrongBinder());
444
445 buffer_id buffer;
446 status_t err = allocate_buffer_with_backup(
447 node, port_index, params, &buffer);
448
449 reply->writeInt32(err);
450
451 if (err == OK) {
452 writeVoidStar(buffer, reply);
453 }
454
455 return NO_ERROR;
456 }
457
458 case FREE_BUFFER:
459 {
460 CHECK_INTERFACE(IOMX, data, reply);
461
462 node_id node = readVoidStar(&data);
463 OMX_U32 port_index = data.readInt32();
464 buffer_id buffer = readVoidStar(&data);
465 reply->writeInt32(free_buffer(node, port_index, buffer));
466
467 return NO_ERROR;
468 }
469
Andreas Huber20111aa2009-07-14 16:56:47 -0700470 case OBSERVE_NODE:
471 {
472 CHECK_INTERFACE(IOMX, data, reply);
473
474 node_id node = readVoidStar(&data);
475 sp<IOMXObserver> observer =
476 interface_cast<IOMXObserver>(data.readStrongBinder());
477 reply->writeInt32(observe_node(node, observer));
478
479 return NO_ERROR;
480 }
481
482 case FILL_BUFFER:
483 {
484 CHECK_INTERFACE(IOMX, data, reply);
485
486 node_id node = readVoidStar(&data);
487 buffer_id buffer = readVoidStar(&data);
488 fill_buffer(node, buffer);
489
490 return NO_ERROR;
491 }
492
493 case EMPTY_BUFFER:
494 {
495 CHECK_INTERFACE(IOMX, data, reply);
496
497 node_id node = readVoidStar(&data);
498 buffer_id buffer = readVoidStar(&data);
499 OMX_U32 range_offset = data.readInt32();
500 OMX_U32 range_length = data.readInt32();
501 OMX_U32 flags = data.readInt32();
502 OMX_TICKS timestamp = data.readInt64();
503
504 empty_buffer(
505 node, buffer, range_offset, range_length,
506 flags, timestamp);
507
508 return NO_ERROR;
509 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700510
Andreas Huber8b938cd2009-07-31 11:52:50 -0700511 case CREATE_RENDERER:
512 {
513 CHECK_INTERFACE(IOMX, data, reply);
514
515 sp<ISurface> isurface =
516 interface_cast<ISurface>(data.readStrongBinder());
517
518 const char *componentName = data.readCString();
519
520 OMX_COLOR_FORMATTYPE colorFormat =
521 static_cast<OMX_COLOR_FORMATTYPE>(data.readInt32());
522
523 size_t encodedWidth = (size_t)data.readInt32();
524 size_t encodedHeight = (size_t)data.readInt32();
525 size_t displayWidth = (size_t)data.readInt32();
526 size_t displayHeight = (size_t)data.readInt32();
527
528 sp<IOMXRenderer> renderer =
529 createRenderer(isurface, componentName, colorFormat,
530 encodedWidth, encodedHeight,
531 displayWidth, displayHeight);
532
533 reply->writeStrongBinder(renderer->asBinder());
534
535 return OK;
536 }
537
Andreas Huber20111aa2009-07-14 16:56:47 -0700538 default:
539 return BBinder::onTransact(code, data, reply, flags);
540 }
541}
542
543////////////////////////////////////////////////////////////////////////////////
544
545class BpOMXObserver : public BpInterface<IOMXObserver> {
546public:
547 BpOMXObserver(const sp<IBinder> &impl)
548 : BpInterface<IOMXObserver>(impl) {
549 }
550
551 virtual void on_message(const omx_message &msg) {
552 Parcel data, reply;
553 data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor());
554 data.write(&msg, sizeof(msg));
555
556 remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY);
557 }
558};
559
560IMPLEMENT_META_INTERFACE(OMXObserver, "android.hardware.IOMXObserver");
561
562status_t BnOMXObserver::onTransact(
563 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
564 switch (code) {
565 case OBSERVER_ON_MSG:
566 {
567 CHECK_INTERFACE(IOMXObserver, data, reply);
568
569 omx_message msg;
570 data.read(&msg, sizeof(msg));
571
572 // XXX Could use readInplace maybe?
573 on_message(msg);
574
575 return NO_ERROR;
576 }
577
578 default:
579 return BBinder::onTransact(code, data, reply, flags);
580 }
581}
582
Andreas Huber8b938cd2009-07-31 11:52:50 -0700583////////////////////////////////////////////////////////////////////////////////
584
585class BpOMXRenderer : public BpInterface<IOMXRenderer> {
586public:
587 BpOMXRenderer(const sp<IBinder> &impl)
588 : BpInterface<IOMXRenderer>(impl) {
589 }
590
591 virtual void render(IOMX::buffer_id buffer) {
592 Parcel data, reply;
593 data.writeInterfaceToken(IOMXRenderer::getInterfaceDescriptor());
594 writeVoidStar(buffer, &data);
595
596 // NOTE: Do NOT make this a ONE_WAY call, it must be synchronous
597 // so that the caller knows when to recycle the buffer.
598 remote()->transact(RENDERER_RENDER, data, &reply);
599 }
600};
601
602IMPLEMENT_META_INTERFACE(OMXRenderer, "android.hardware.IOMXRenderer");
603
604status_t BnOMXRenderer::onTransact(
605 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
606 switch (code) {
607 case RENDERER_RENDER:
608 {
609 CHECK_INTERFACE(IOMXRenderer, data, reply);
610
611 IOMX::buffer_id buffer = readVoidStar(&data);
612
613 render(buffer);
614
615 return NO_ERROR;
616 }
617
618 default:
619 return BBinder::onTransact(code, data, reply, flags);
620 }
621}
622
Andreas Huber20111aa2009-07-14 16:56:47 -0700623} // namespace android