IOMX.cpp revision 1b84df1a0823fbcb9cec754311f53eaccfe85ae3
1//#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>
8#include <ui/ISurface.h>
9#include <ui/Surface.h>
10
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    GET_CONFIG,
22    SET_CONFIG,
23    USE_BUFFER,
24    ALLOC_BUFFER,
25    ALLOC_BUFFER_WITH_BACKUP,
26    FREE_BUFFER,
27    OBSERVE_NODE,
28    FILL_BUFFER,
29    EMPTY_BUFFER,
30    GET_EXTENSION_INDEX,
31    CREATE_RENDERER,
32    OBSERVER_ON_MSG,
33    RENDERER_RENDER,
34};
35
36sp<IOMXRenderer> IOMX::createRenderer(
37        const sp<Surface> &surface,
38        const char *componentName,
39        OMX_COLOR_FORMATTYPE colorFormat,
40        size_t encodedWidth, size_t encodedHeight,
41        size_t displayWidth, size_t displayHeight) {
42    return createRenderer(
43            surface->getISurface(),
44            componentName, colorFormat, encodedWidth, encodedHeight,
45            displayWidth, displayHeight);
46}
47
48sp<IOMXRenderer> IOMX::createRendererFromJavaSurface(
49        JNIEnv *env, jobject javaSurface,
50        const char *componentName,
51        OMX_COLOR_FORMATTYPE colorFormat,
52        size_t encodedWidth, size_t encodedHeight,
53        size_t displayWidth, size_t displayHeight) {
54    jclass surfaceClass = env->FindClass("android/view/Surface");
55    if (surfaceClass == NULL) {
56        LOGE("Can't find android/view/Surface");
57        return NULL;
58    }
59
60    jfieldID surfaceID = env->GetFieldID(surfaceClass, "mSurface", "I");
61    if (surfaceID == NULL) {
62        LOGE("Can't find Surface.mSurface");
63        return NULL;
64    }
65
66    sp<Surface> surface = (Surface *)env->GetIntField(javaSurface, surfaceID);
67
68    return createRenderer(
69            surface, componentName, colorFormat, encodedWidth,
70            encodedHeight, displayWidth, displayHeight);
71}
72
73class BpOMX : public BpInterface<IOMX> {
74public:
75    BpOMX(const sp<IBinder> &impl)
76        : BpInterface<IOMX>(impl) {
77    }
78
79    virtual status_t list_nodes(List<String8> *list) {
80        list->clear();
81
82        Parcel data, reply;
83        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
84        remote()->transact(LIST_NODES, data, &reply);
85
86        int32_t n = reply.readInt32();
87        for (int32_t i = 0; i < n; ++i) {
88            String8 s = reply.readString8();
89
90            list->push_back(s);
91        }
92
93        return OK;
94    }
95
96    virtual status_t allocate_node(const char *name, node_id *node) {
97        Parcel data, reply;
98        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
99        data.writeCString(name);
100        remote()->transact(ALLOCATE_NODE, data, &reply);
101
102        status_t err = reply.readInt32();
103        if (err == OK) {
104            *node = (void*)reply.readIntPtr();
105        } else {
106            *node = 0;
107        }
108
109        return err;
110    }
111
112    virtual status_t free_node(node_id node) {
113        Parcel data, reply;
114        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
115        data.writeIntPtr((intptr_t)node);
116        remote()->transact(FREE_NODE, data, &reply);
117
118        return reply.readInt32();
119    }
120
121    virtual status_t send_command(
122            node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
123        Parcel data, reply;
124        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
125        data.writeIntPtr((intptr_t)node);
126        data.writeInt32(cmd);
127        data.writeInt32(param);
128        remote()->transact(SEND_COMMAND, data, &reply);
129
130        return reply.readInt32();
131    }
132
133    virtual status_t get_parameter(
134            node_id node, OMX_INDEXTYPE index,
135            void *params, size_t size) {
136        Parcel data, reply;
137        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
138        data.writeIntPtr((intptr_t)node);
139        data.writeInt32(index);
140        data.writeInt32(size);
141        data.write(params, size);
142        remote()->transact(GET_PARAMETER, data, &reply);
143
144        status_t err = reply.readInt32();
145        if (err != OK) {
146            return err;
147        }
148
149        reply.read(params, size);
150
151        return OK;
152    }
153
154    virtual status_t set_parameter(
155            node_id node, OMX_INDEXTYPE index,
156            const void *params, size_t size) {
157        Parcel data, reply;
158        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
159        data.writeIntPtr((intptr_t)node);
160        data.writeInt32(index);
161        data.writeInt32(size);
162        data.write(params, size);
163        remote()->transact(SET_PARAMETER, data, &reply);
164
165        return reply.readInt32();
166    }
167
168    virtual status_t get_config(
169            node_id node, OMX_INDEXTYPE index,
170            void *params, size_t size) {
171        Parcel data, reply;
172        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
173        data.writeIntPtr((intptr_t)node);
174        data.writeInt32(index);
175        data.writeInt32(size);
176        data.write(params, size);
177        remote()->transact(GET_CONFIG, data, &reply);
178
179        status_t err = reply.readInt32();
180        if (err != OK) {
181            return err;
182        }
183
184        reply.read(params, size);
185
186        return OK;
187    }
188
189    virtual status_t set_config(
190            node_id node, OMX_INDEXTYPE index,
191            const void *params, size_t size) {
192        Parcel data, reply;
193        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
194        data.writeIntPtr((intptr_t)node);
195        data.writeInt32(index);
196        data.writeInt32(size);
197        data.write(params, size);
198        remote()->transact(SET_CONFIG, data, &reply);
199
200        return reply.readInt32();
201    }
202
203    virtual status_t use_buffer(
204            node_id node, OMX_U32 port_index, const sp<IMemory> &params,
205            buffer_id *buffer) {
206        Parcel data, reply;
207        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
208        data.writeIntPtr((intptr_t)node);
209        data.writeInt32(port_index);
210        data.writeStrongBinder(params->asBinder());
211        remote()->transact(USE_BUFFER, data, &reply);
212
213        status_t err = reply.readInt32();
214        if (err != OK) {
215            *buffer = 0;
216
217            return err;
218        }
219
220        *buffer = (void*)reply.readIntPtr();
221
222        return err;
223    }
224
225    virtual status_t allocate_buffer(
226            node_id node, OMX_U32 port_index, size_t size,
227            buffer_id *buffer) {
228        Parcel data, reply;
229        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
230        data.writeIntPtr((intptr_t)node);
231        data.writeInt32(port_index);
232        data.writeInt32(size);
233        remote()->transact(ALLOC_BUFFER, data, &reply);
234
235        status_t err = reply.readInt32();
236        if (err != OK) {
237            *buffer = 0;
238
239            return err;
240        }
241
242        *buffer = (void*)reply.readIntPtr();
243
244        return err;
245    }
246
247    virtual status_t allocate_buffer_with_backup(
248            node_id node, OMX_U32 port_index, const sp<IMemory> &params,
249            buffer_id *buffer) {
250        Parcel data, reply;
251        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
252        data.writeIntPtr((intptr_t)node);
253        data.writeInt32(port_index);
254        data.writeStrongBinder(params->asBinder());
255        remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply);
256
257        status_t err = reply.readInt32();
258        if (err != OK) {
259            *buffer = 0;
260
261            return err;
262        }
263
264        *buffer = (void*)reply.readIntPtr();
265
266        return err;
267    }
268
269    virtual status_t free_buffer(
270            node_id node, OMX_U32 port_index, buffer_id buffer) {
271        Parcel data, reply;
272        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
273        data.writeIntPtr((intptr_t)node);
274        data.writeInt32(port_index);
275        data.writeIntPtr((intptr_t)buffer);
276        remote()->transact(FREE_BUFFER, data, &reply);
277
278        return reply.readInt32();
279    }
280
281    virtual status_t observe_node(
282            node_id node, const sp<IOMXObserver> &observer) {
283        Parcel data, reply;
284        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
285        data.writeIntPtr((intptr_t)node);
286        data.writeStrongBinder(observer->asBinder());
287        remote()->transact(OBSERVE_NODE, data, &reply);
288
289        return reply.readInt32();
290    }
291
292    virtual void fill_buffer(node_id node, buffer_id buffer) {
293        Parcel data, reply;
294        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
295        data.writeIntPtr((intptr_t)node);
296        data.writeIntPtr((intptr_t)buffer);
297        remote()->transact(FILL_BUFFER, data, &reply, IBinder::FLAG_ONEWAY);
298    }
299
300    virtual void empty_buffer(
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        Parcel data, reply;
306        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
307        data.writeIntPtr((intptr_t)node);
308        data.writeIntPtr((intptr_t)buffer);
309        data.writeInt32(range_offset);
310        data.writeInt32(range_length);
311        data.writeInt32(flags);
312        data.writeInt64(timestamp);
313        remote()->transact(EMPTY_BUFFER, data, &reply, IBinder::FLAG_ONEWAY);
314    }
315
316    virtual status_t get_extension_index(
317            node_id node,
318            const char *parameter_name,
319            OMX_INDEXTYPE *index) {
320        Parcel data, reply;
321        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
322        data.writeIntPtr((intptr_t)node);
323        data.writeCString(parameter_name);
324
325        remote()->transact(GET_EXTENSION_INDEX, data, &reply);
326
327        status_t err = reply.readInt32();
328        if (err == OK) {
329            *index = static_cast<OMX_INDEXTYPE>(reply.readInt32());
330        } else {
331            *index = OMX_IndexComponentStartUnused;
332        }
333
334        return err;
335    }
336
337    virtual sp<IOMXRenderer> createRenderer(
338            const sp<ISurface> &surface,
339            const char *componentName,
340            OMX_COLOR_FORMATTYPE colorFormat,
341            size_t encodedWidth, size_t encodedHeight,
342            size_t displayWidth, size_t displayHeight) {
343        Parcel data, reply;
344        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
345
346        data.writeStrongBinder(surface->asBinder());
347        data.writeCString(componentName);
348        data.writeInt32(colorFormat);
349        data.writeInt32(encodedWidth);
350        data.writeInt32(encodedHeight);
351        data.writeInt32(displayWidth);
352        data.writeInt32(displayHeight);
353
354        remote()->transact(CREATE_RENDERER, data, &reply);
355
356        return interface_cast<IOMXRenderer>(reply.readStrongBinder());
357    }
358};
359
360IMPLEMENT_META_INTERFACE(OMX, "android.hardware.IOMX");
361
362////////////////////////////////////////////////////////////////////////////////
363
364#define CHECK_INTERFACE(interface, data, reply) \
365        do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
366            LOGW("Call incorrectly routed to " #interface); \
367            return PERMISSION_DENIED; \
368        } } while (0)
369
370status_t BnOMX::onTransact(
371    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
372    switch (code) {
373        case LIST_NODES:
374        {
375            CHECK_INTERFACE(IOMX, data, reply);
376
377            List<String8> list;
378            list_nodes(&list);
379
380            reply->writeInt32(list.size());
381            for (List<String8>::iterator it = list.begin();
382                 it != list.end(); ++it) {
383                reply->writeString8(*it);
384            }
385
386            return NO_ERROR;
387        }
388
389        case ALLOCATE_NODE:
390        {
391            CHECK_INTERFACE(IOMX, data, reply);
392
393            node_id node;
394            status_t err = allocate_node(data.readCString(), &node);
395            reply->writeInt32(err);
396            if (err == OK) {
397                reply->writeIntPtr((intptr_t)node);
398            }
399
400            return NO_ERROR;
401        }
402
403        case FREE_NODE:
404        {
405            CHECK_INTERFACE(IOMX, data, reply);
406
407            node_id node = (void*)data.readIntPtr();
408
409            reply->writeInt32(free_node(node));
410
411            return NO_ERROR;
412        }
413
414        case SEND_COMMAND:
415        {
416            CHECK_INTERFACE(IOMX, data, reply);
417
418            node_id node = (void*)data.readIntPtr();
419
420            OMX_COMMANDTYPE cmd =
421                static_cast<OMX_COMMANDTYPE>(data.readInt32());
422
423            OMX_S32 param = data.readInt32();
424            reply->writeInt32(send_command(node, cmd, param));
425
426            return NO_ERROR;
427        }
428
429        case GET_PARAMETER:
430        {
431            CHECK_INTERFACE(IOMX, data, reply);
432
433            node_id node = (void*)data.readIntPtr();
434            OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
435
436            size_t size = data.readInt32();
437
438            // XXX I am not happy with this but Parcel::readInplace didn't work.
439            void *params = malloc(size);
440            data.read(params, size);
441
442            status_t err = get_parameter(node, index, params, size);
443
444            reply->writeInt32(err);
445
446            if (err == OK) {
447                reply->write(params, size);
448            }
449
450            free(params);
451            params = NULL;
452
453            return NO_ERROR;
454        }
455
456        case SET_PARAMETER:
457        {
458            CHECK_INTERFACE(IOMX, data, reply);
459
460            node_id node = (void*)data.readIntPtr();
461            OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
462
463            size_t size = data.readInt32();
464            void *params = const_cast<void *>(data.readInplace(size));
465
466            reply->writeInt32(set_parameter(node, index, params, size));
467
468            return NO_ERROR;
469        }
470
471        case GET_CONFIG:
472        {
473            CHECK_INTERFACE(IOMX, data, reply);
474
475            node_id node = (void*)data.readIntPtr();
476            OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
477
478            size_t size = data.readInt32();
479
480            // XXX I am not happy with this but Parcel::readInplace didn't work.
481            void *params = malloc(size);
482            data.read(params, size);
483
484            status_t err = get_config(node, index, params, size);
485
486            reply->writeInt32(err);
487
488            if (err == OK) {
489                reply->write(params, size);
490            }
491
492            free(params);
493            params = NULL;
494
495            return NO_ERROR;
496        }
497
498        case SET_CONFIG:
499        {
500            CHECK_INTERFACE(IOMX, data, reply);
501
502            node_id node = (void*)data.readIntPtr();
503            OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
504
505            size_t size = data.readInt32();
506            void *params = const_cast<void *>(data.readInplace(size));
507
508            reply->writeInt32(set_config(node, index, params, size));
509
510            return NO_ERROR;
511        }
512
513        case USE_BUFFER:
514        {
515            CHECK_INTERFACE(IOMX, data, reply);
516
517            node_id node = (void*)data.readIntPtr();
518            OMX_U32 port_index = data.readInt32();
519            sp<IMemory> params =
520                interface_cast<IMemory>(data.readStrongBinder());
521
522            buffer_id buffer;
523            status_t err = use_buffer(node, port_index, params, &buffer);
524            reply->writeInt32(err);
525
526            if (err == OK) {
527                reply->writeIntPtr((intptr_t)buffer);
528            }
529
530            return NO_ERROR;
531        }
532
533        case ALLOC_BUFFER:
534        {
535            CHECK_INTERFACE(IOMX, data, reply);
536
537            node_id node = (void*)data.readIntPtr();
538            OMX_U32 port_index = data.readInt32();
539            size_t size = data.readInt32();
540
541            buffer_id buffer;
542            status_t err = allocate_buffer(node, port_index, size, &buffer);
543            reply->writeInt32(err);
544
545            if (err == OK) {
546                reply->writeIntPtr((intptr_t)buffer);
547            }
548
549            return NO_ERROR;
550        }
551
552        case ALLOC_BUFFER_WITH_BACKUP:
553        {
554            CHECK_INTERFACE(IOMX, data, reply);
555
556            node_id node = (void*)data.readIntPtr();
557            OMX_U32 port_index = data.readInt32();
558            sp<IMemory> params =
559                interface_cast<IMemory>(data.readStrongBinder());
560
561            buffer_id buffer;
562            status_t err = allocate_buffer_with_backup(
563                    node, port_index, params, &buffer);
564
565            reply->writeInt32(err);
566
567            if (err == OK) {
568                reply->writeIntPtr((intptr_t)buffer);
569            }
570
571            return NO_ERROR;
572        }
573
574        case FREE_BUFFER:
575        {
576            CHECK_INTERFACE(IOMX, data, reply);
577
578            node_id node = (void*)data.readIntPtr();
579            OMX_U32 port_index = data.readInt32();
580            buffer_id buffer = (void*)data.readIntPtr();
581            reply->writeInt32(free_buffer(node, port_index, buffer));
582
583            return NO_ERROR;
584        }
585
586        case OBSERVE_NODE:
587        {
588            CHECK_INTERFACE(IOMX, data, reply);
589
590            node_id node = (void*)data.readIntPtr();
591            sp<IOMXObserver> observer =
592                interface_cast<IOMXObserver>(data.readStrongBinder());
593            reply->writeInt32(observe_node(node, observer));
594
595            return NO_ERROR;
596        }
597
598        case FILL_BUFFER:
599        {
600            CHECK_INTERFACE(IOMX, data, reply);
601
602            node_id node = (void*)data.readIntPtr();
603            buffer_id buffer = (void*)data.readIntPtr();
604            fill_buffer(node, buffer);
605
606            return NO_ERROR;
607        }
608
609        case EMPTY_BUFFER:
610        {
611            CHECK_INTERFACE(IOMX, data, reply);
612
613            node_id node = (void*)data.readIntPtr();
614            buffer_id buffer = (void*)data.readIntPtr();
615            OMX_U32 range_offset = data.readInt32();
616            OMX_U32 range_length = data.readInt32();
617            OMX_U32 flags = data.readInt32();
618            OMX_TICKS timestamp = data.readInt64();
619
620            empty_buffer(
621                    node, buffer, range_offset, range_length,
622                    flags, timestamp);
623
624            return NO_ERROR;
625        }
626
627        case GET_EXTENSION_INDEX:
628        {
629            CHECK_INTERFACE(IOMX, data, reply);
630
631            node_id node = (void*)data.readIntPtr();
632            const char *parameter_name = data.readCString();
633
634            OMX_INDEXTYPE index;
635            status_t err = get_extension_index(node, parameter_name, &index);
636
637            reply->writeInt32(err);
638
639            if (err == OK) {
640                reply->writeInt32(index);
641            }
642
643            return OK;
644        }
645
646        case CREATE_RENDERER:
647        {
648            CHECK_INTERFACE(IOMX, data, reply);
649
650            sp<ISurface> isurface =
651                interface_cast<ISurface>(data.readStrongBinder());
652
653            const char *componentName = data.readCString();
654
655            OMX_COLOR_FORMATTYPE colorFormat =
656                static_cast<OMX_COLOR_FORMATTYPE>(data.readInt32());
657
658            size_t encodedWidth = (size_t)data.readInt32();
659            size_t encodedHeight = (size_t)data.readInt32();
660            size_t displayWidth = (size_t)data.readInt32();
661            size_t displayHeight = (size_t)data.readInt32();
662
663            sp<IOMXRenderer> renderer =
664                createRenderer(isurface, componentName, colorFormat,
665                               encodedWidth, encodedHeight,
666                               displayWidth, displayHeight);
667
668            reply->writeStrongBinder(renderer->asBinder());
669
670            return OK;
671        }
672
673        default:
674            return BBinder::onTransact(code, data, reply, flags);
675    }
676}
677
678////////////////////////////////////////////////////////////////////////////////
679
680class BpOMXObserver : public BpInterface<IOMXObserver> {
681public:
682    BpOMXObserver(const sp<IBinder> &impl)
683        : BpInterface<IOMXObserver>(impl) {
684    }
685
686    virtual void on_message(const omx_message &msg) {
687        Parcel data, reply;
688        data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor());
689        data.write(&msg, sizeof(msg));
690
691        remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY);
692    }
693};
694
695IMPLEMENT_META_INTERFACE(OMXObserver, "android.hardware.IOMXObserver");
696
697status_t BnOMXObserver::onTransact(
698    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
699    switch (code) {
700        case OBSERVER_ON_MSG:
701        {
702            CHECK_INTERFACE(IOMXObserver, data, reply);
703
704            omx_message msg;
705            data.read(&msg, sizeof(msg));
706
707            // XXX Could use readInplace maybe?
708            on_message(msg);
709
710            return NO_ERROR;
711        }
712
713        default:
714            return BBinder::onTransact(code, data, reply, flags);
715    }
716}
717
718////////////////////////////////////////////////////////////////////////////////
719
720class BpOMXRenderer : public BpInterface<IOMXRenderer> {
721public:
722    BpOMXRenderer(const sp<IBinder> &impl)
723        : BpInterface<IOMXRenderer>(impl) {
724    }
725
726    virtual void render(IOMX::buffer_id buffer) {
727        Parcel data, reply;
728        data.writeInterfaceToken(IOMXRenderer::getInterfaceDescriptor());
729        data.writeIntPtr((intptr_t)buffer);
730
731        // NOTE: Do NOT make this a ONE_WAY call, it must be synchronous
732        // so that the caller knows when to recycle the buffer.
733        remote()->transact(RENDERER_RENDER, data, &reply);
734    }
735};
736
737IMPLEMENT_META_INTERFACE(OMXRenderer, "android.hardware.IOMXRenderer");
738
739status_t BnOMXRenderer::onTransact(
740    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
741    switch (code) {
742        case RENDERER_RENDER:
743        {
744            CHECK_INTERFACE(IOMXRenderer, data, reply);
745
746            IOMX::buffer_id buffer = (void*)data.readIntPtr();
747
748            render(buffer);
749
750            return NO_ERROR;
751        }
752
753        default:
754            return BBinder::onTransact(code, data, reply, flags);
755    }
756}
757
758}  // namespace android
759