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