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