componentbase.cpp revision 20d24dd0df20095a26ad14d06e0eb2a301f7f6a8
1/*
2 * Copyright (C) 2009 Wind River Systems.
3 */
4
5#include <stdlib.h>
6#include <string.h>
7
8#include <pthread.h>
9
10#include <OMX_Core.h>
11#include <OMX_Component.h>
12
13#include <componentbase.h>
14
15#include <queue.h>
16#include <workqueue.h>
17
18#define LOG_TAG "componentbase"
19#include <log.h>
20
21/*
22 * CmdProcessWork
23 */
24CmdProcessWork::CmdProcessWork(CmdHandlerInterface *ci)
25{
26    this->ci = ci;
27
28    workq = new WorkQueue;
29
30    __queue_init(&q);
31    pthread_mutex_init(&lock, NULL);
32
33    workq->StartWork();
34}
35
36CmdProcessWork::~CmdProcessWork()
37{
38    workq->StopWork();
39    delete workq;
40
41    pthread_mutex_lock(&lock);
42    queue_free_all(&q);
43    pthread_mutex_unlock(&lock);
44
45    pthread_mutex_destroy(&lock);
46}
47
48OMX_ERRORTYPE CmdProcessWork::PushCmdQueue(struct cmd_s *cmd)
49{
50    int ret;
51
52    pthread_mutex_lock(&lock);
53    ret = queue_push_tail(&q, cmd);
54    if (ret) {
55        pthread_mutex_unlock(&lock);
56        return OMX_ErrorInsufficientResources;
57    }
58
59    workq->ScheduleWork(this);
60    pthread_mutex_unlock(&lock);
61
62    return OMX_ErrorNone;
63}
64
65struct cmd_s *CmdProcessWork::PopCmdQueue(void)
66{
67    struct cmd_s *cmd;
68
69    pthread_mutex_lock(&lock);
70    cmd = (struct cmd_s *)queue_pop_head(&q);
71    pthread_mutex_unlock(&lock);
72
73    return cmd;
74}
75
76void CmdProcessWork::ScheduleIfAvailable(void)
77{
78    bool avail;
79
80    pthread_mutex_lock(&lock);
81    avail = queue_length(&q) ? true : false;
82    pthread_mutex_unlock(&lock);
83
84    if (avail)
85        workq->ScheduleWork(this);
86}
87
88void CmdProcessWork::Work(void)
89{
90    struct cmd_s *cmd;
91
92    cmd = PopCmdQueue();
93    if (cmd) {
94        ci->CmdHandler(cmd);
95        free(cmd);
96    }
97    ScheduleIfAvailable();
98}
99
100/* end of CmdProcessWork */
101
102/*
103 * ComponentBase
104 */
105/*
106 * constructor & destructor
107 */
108void ComponentBase::__ComponentBase(void)
109{
110    memset(name, 0, OMX_MAX_STRINGNAME_SIZE);
111    cmodule = NULL;
112    handle = NULL;
113
114    roles = NULL;
115    nr_roles = 0;
116
117    working_role = NULL;
118
119    ports = NULL;
120    nr_ports = 0;
121    memset(&portparam, 0, sizeof(portparam));
122
123    state = OMX_StateUnloaded;
124
125    cmdwork = new CmdProcessWork(this);
126
127    executing = false;
128    pthread_mutex_init(&executing_lock, NULL);
129    pthread_cond_init(&executing_wait, NULL);
130
131    bufferwork = new WorkQueue();
132
133    pthread_mutex_init(&ports_block, NULL);
134}
135
136ComponentBase::ComponentBase()
137{
138    __ComponentBase();
139}
140
141ComponentBase::ComponentBase(const OMX_STRING name)
142{
143    __ComponentBase();
144    SetName(name);
145}
146
147ComponentBase::~ComponentBase()
148{
149    delete cmdwork;
150
151    delete bufferwork;
152    pthread_mutex_destroy(&executing_lock);
153    pthread_cond_destroy(&executing_wait);
154
155    pthread_mutex_destroy(&ports_block);
156
157    if (roles) {
158        OMX_U32 i;
159
160        for (i = 0; i < nr_roles; i++)
161            free(roles[i]);
162
163        free(roles);
164    }
165}
166
167/* end of constructor & destructor */
168
169/*
170 * accessor
171 */
172/* name */
173void ComponentBase::SetName(const OMX_STRING name)
174{
175    strncpy(this->name, name, OMX_MAX_STRINGNAME_SIZE);
176    this->name[OMX_MAX_STRINGNAME_SIZE-1] = '\0';
177}
178
179const OMX_STRING ComponentBase::GetName(void)
180{
181    return name;
182}
183
184/* component module */
185void ComponentBase::SetCModule(CModule *cmodule)
186{
187    this->cmodule = cmodule;
188}
189
190CModule *ComponentBase::GetCModule(void)
191{
192    return cmodule;
193}
194
195/* end of accessor */
196
197/*
198 * core methods & helpers
199 */
200/* roles */
201OMX_ERRORTYPE ComponentBase::SetRolesOfComponent(OMX_U32 nr_roles,
202                                                 const OMX_U8 **roles)
203{
204    OMX_U32 i;
205
206    this->roles = (OMX_U8 **)malloc(sizeof(OMX_STRING) * nr_roles);
207    if (!this->roles)
208        return OMX_ErrorInsufficientResources;
209
210    for (i = 0; i < nr_roles; i++) {
211        this->roles[i] = (OMX_U8 *)malloc(OMX_MAX_STRINGNAME_SIZE);
212        if (!this->roles[i]) {
213            int j;
214
215            for (j = (int )i-1; j >= 0; j--)
216                free(this->roles[j]);
217            free(this->roles);
218
219            return OMX_ErrorInsufficientResources;
220        }
221
222        strncpy((OMX_STRING)&this->roles[i][0],
223                (const OMX_STRING)&roles[i][0],
224                OMX_MAX_STRINGNAME_SIZE);
225    }
226
227    this->nr_roles = nr_roles;
228    return OMX_ErrorNone;
229}
230
231OMX_ERRORTYPE ComponentBase::GetRolesOfComponent(OMX_U32 *nr_roles,
232                                                 OMX_U8 **roles)
233{
234    OMX_U32 i;
235    OMX_U32 this_nr_roles = this->nr_roles;
236
237    if (!roles) {
238        *nr_roles = this_nr_roles;
239        return OMX_ErrorNone;
240    }
241
242    if (!nr_roles || (*nr_roles != this_nr_roles))
243        return OMX_ErrorBadParameter;
244
245    for (i = 0; i < this_nr_roles; i++) {
246        if (!roles[i])
247            break;
248
249        if (roles && roles[i])
250            strncpy((OMX_STRING)&roles[i][0],
251                    (const OMX_STRING)&this->roles[i][0],
252                    OMX_MAX_STRINGNAME_SIZE);
253    }
254
255    if (i != this_nr_roles)
256        return OMX_ErrorBadParameter;
257
258    *nr_roles = this_nr_roles;
259    return OMX_ErrorNone;
260}
261
262bool ComponentBase::QueryHavingThisRole(const OMX_STRING role)
263{
264    OMX_U32 i;
265
266    if (!roles || !role)
267        return false;
268
269    for (i = 0; i < nr_roles; i++) {
270        if (!strcmp((OMX_STRING)&roles[i][0], role))
271            return true;
272    }
273
274    return false;
275}
276
277/* GetHandle & FreeHandle */
278OMX_ERRORTYPE ComponentBase::GetHandle(OMX_HANDLETYPE *pHandle,
279                                       OMX_PTR pAppData,
280                                       OMX_CALLBACKTYPE *pCallBacks)
281{
282    OMX_U32 i;
283    OMX_ERRORTYPE ret;
284
285    if (handle)
286        return OMX_ErrorUndefined;
287
288    handle = (OMX_COMPONENTTYPE *)calloc(1, sizeof(*handle));
289    if (!handle)
290        return OMX_ErrorInsufficientResources;
291
292    /* handle initialization */
293    SetTypeHeader(handle, sizeof(*handle));
294    handle->pComponentPrivate = static_cast<OMX_PTR>(this);
295    handle->pApplicationPrivate = pAppData;
296
297    /* virtual - see derived class */
298    ret = InitComponent();
299    if (ret != OMX_ErrorNone) {
300        LOGE("failed to %s::InitComponent(), ret = 0x%08x\n",
301             name, ret);
302        goto free_handle;
303    }
304
305    for (i = 0; i < nr_ports; i++) {
306        ports[i]->SetOwner(handle);
307        ports[i]->SetCallbacks(handle, pCallBacks, pAppData);
308    }
309
310    /* connect handle's functions */
311    handle->GetComponentVersion = GetComponentVersion;
312    handle->SendCommand = SendCommand;
313    handle->GetParameter = GetParameter;
314    handle->SetParameter = SetParameter;
315    handle->GetConfig = GetConfig;
316    handle->SetConfig = SetConfig;
317    handle->GetExtensionIndex = GetExtensionIndex;
318    handle->GetState = GetState;
319    handle->ComponentTunnelRequest = ComponentTunnelRequest;
320    handle->UseBuffer = UseBuffer;
321    handle->AllocateBuffer = AllocateBuffer;
322    handle->FreeBuffer = FreeBuffer;
323    handle->EmptyThisBuffer = EmptyThisBuffer;
324    handle->FillThisBuffer = FillThisBuffer;
325    handle->SetCallbacks = SetCallbacks;
326    handle->ComponentDeInit = ComponentDeInit;
327    handle->UseEGLImage = UseEGLImage;
328    handle->ComponentRoleEnum = ComponentRoleEnum;
329
330    appdata = pAppData;
331    callbacks = pCallBacks;
332    *pHandle = (OMX_HANDLETYPE *)handle;
333
334    state = OMX_StateLoaded;
335    return OMX_ErrorNone;
336
337free_handle:
338    free(this->handle);
339    this->handle = NULL;
340
341    return ret;
342}
343
344OMX_ERRORTYPE ComponentBase::FreeHandle(OMX_HANDLETYPE hComponent)
345{
346    OMX_ERRORTYPE ret;
347
348    if (hComponent != handle)
349        return OMX_ErrorBadParameter;
350
351    /* virtual - see derived class */
352    ret = ExitComponent();
353    if (ret != OMX_ErrorNone)
354        return ret;
355
356    free(handle);
357
358    appdata = NULL;
359    callbacks = NULL;
360
361    state = OMX_StateUnloaded;
362    return OMX_ErrorNone;
363}
364
365/* end of core methods & helpers */
366
367/*
368 * component methods & helpers
369 */
370OMX_ERRORTYPE ComponentBase::GetComponentVersion(
371    OMX_IN  OMX_HANDLETYPE hComponent,
372    OMX_OUT OMX_STRING pComponentName,
373    OMX_OUT OMX_VERSIONTYPE* pComponentVersion,
374    OMX_OUT OMX_VERSIONTYPE* pSpecVersion,
375    OMX_OUT OMX_UUIDTYPE* pComponentUUID)
376{
377    ComponentBase *cbase;
378
379    if (!hComponent)
380        return OMX_ErrorBadParameter;
381
382    cbase = static_cast<ComponentBase *>
383        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
384    if (!cbase)
385        return OMX_ErrorBadParameter;
386
387    return cbase->CBaseGetComponentVersion(hComponent,
388                                           pComponentName,
389                                           pComponentVersion,
390                                           pSpecVersion,
391                                           pComponentUUID);
392}
393
394OMX_ERRORTYPE ComponentBase::CBaseGetComponentVersion(
395    OMX_IN  OMX_HANDLETYPE hComponent,
396    OMX_OUT OMX_STRING pComponentName,
397    OMX_OUT OMX_VERSIONTYPE* pComponentVersion,
398    OMX_OUT OMX_VERSIONTYPE* pSpecVersion,
399    OMX_OUT OMX_UUIDTYPE* pComponentUUID)
400{
401    /*
402     * Todo
403     */
404
405    return OMX_ErrorNotImplemented;
406}
407
408OMX_ERRORTYPE ComponentBase::SendCommand(
409    OMX_IN  OMX_HANDLETYPE hComponent,
410    OMX_IN  OMX_COMMANDTYPE Cmd,
411    OMX_IN  OMX_U32 nParam1,
412    OMX_IN  OMX_PTR pCmdData)
413{
414    ComponentBase *cbase;
415
416    if (!hComponent)
417        return OMX_ErrorBadParameter;
418
419    cbase = static_cast<ComponentBase *>
420        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
421    if (!cbase)
422        return OMX_ErrorBadParameter;
423
424    return cbase->CBaseSendCommand(hComponent, Cmd, nParam1, pCmdData);
425}
426
427OMX_ERRORTYPE ComponentBase::CBaseSendCommand(
428    OMX_IN  OMX_HANDLETYPE hComponent,
429    OMX_IN  OMX_COMMANDTYPE Cmd,
430    OMX_IN  OMX_U32 nParam1,
431    OMX_IN  OMX_PTR pCmdData)
432{
433    struct cmd_s *cmd;
434
435    if (hComponent != handle)
436        return OMX_ErrorInvalidComponent;
437
438    /* basic error check */
439    switch (Cmd) {
440    case OMX_CommandStateSet:
441        /*
442         * Todo
443         */
444        break;
445    case OMX_CommandFlush:
446        /*
447         * Todo
448         */
449        //break;
450    case OMX_CommandPortDisable:
451        /*
452         * Todo
453         */
454        //break;
455    case OMX_CommandPortEnable:
456        /*
457         * Todo
458         */
459        //break;
460    case OMX_CommandMarkBuffer:
461        /*
462         * Todo
463         */
464        //break;
465    default:
466        LOGE("command %d not supported\n", Cmd);
467        return OMX_ErrorUnsupportedIndex;
468    }
469
470    cmd = (struct cmd_s *)malloc(sizeof(*cmd));
471    if (!cmd)
472        return OMX_ErrorInsufficientResources;
473
474    cmd->cmd = Cmd;
475    cmd->param1 = nParam1;
476    cmd->cmddata = pCmdData;
477
478    return cmdwork->PushCmdQueue(cmd);
479}
480
481OMX_ERRORTYPE ComponentBase::GetParameter(
482    OMX_IN  OMX_HANDLETYPE hComponent,
483    OMX_IN  OMX_INDEXTYPE nParamIndex,
484    OMX_INOUT OMX_PTR pComponentParameterStructure)
485{
486    ComponentBase *cbase;
487
488    if (!hComponent)
489        return OMX_ErrorBadParameter;
490
491    cbase = static_cast<ComponentBase *>
492        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
493    if (!cbase)
494        return OMX_ErrorBadParameter;
495
496    return cbase->CBaseGetParameter(hComponent, nParamIndex,
497                                    pComponentParameterStructure);
498}
499
500OMX_ERRORTYPE ComponentBase::CBaseGetParameter(
501    OMX_IN  OMX_HANDLETYPE hComponent,
502    OMX_IN  OMX_INDEXTYPE nParamIndex,
503    OMX_INOUT OMX_PTR pComponentParameterStructure)
504{
505    OMX_ERRORTYPE ret = OMX_ErrorNone;
506
507    if (hComponent != handle)
508        return OMX_ErrorBadParameter;
509
510    switch (nParamIndex) {
511    case OMX_IndexParamAudioInit:
512    case OMX_IndexParamVideoInit:
513    case OMX_IndexParamImageInit:
514    case OMX_IndexParamOtherInit: {
515        OMX_PORT_PARAM_TYPE *p =
516            (OMX_PORT_PARAM_TYPE *)pComponentParameterStructure;
517
518        memcpy(p, &portparam, sizeof(*p));
519        break;
520    }
521    case OMX_IndexParamPortDefinition: {
522        OMX_PARAM_PORTDEFINITIONTYPE *p =
523            (OMX_PARAM_PORTDEFINITIONTYPE *)pComponentParameterStructure;
524        OMX_U32 index = p->nPortIndex;
525        PortBase *port = ports[index];
526
527        memcpy(p, port->GetPortParam(), sizeof(*p));
528        break;
529    }
530    case OMX_IndexParamAudioPortFormat: {
531        OMX_AUDIO_PARAM_PORTFORMATTYPE *p =
532            (OMX_AUDIO_PARAM_PORTFORMATTYPE *)pComponentParameterStructure;
533        OMX_U32 index = p->nPortIndex;
534        PortBase *port = ports[index];
535
536        memcpy(p, port->GetAudioPortParam(), sizeof(*p));
537        break;
538    }
539    case OMX_IndexParamCompBufferSupplier:
540        /*
541         * Todo
542         */
543
544        ret = OMX_ErrorUnsupportedIndex;
545        break;
546    default:
547        ret = ComponentGetParameter(nParamIndex, pComponentParameterStructure);
548    } /* switch */
549
550    return ret;
551}
552
553OMX_ERRORTYPE ComponentBase::SetParameter(
554    OMX_IN  OMX_HANDLETYPE hComponent,
555    OMX_IN  OMX_INDEXTYPE nIndex,
556    OMX_IN  OMX_PTR pComponentParameterStructure)
557{
558    ComponentBase *cbase;
559
560    if (!hComponent)
561        return OMX_ErrorBadParameter;
562
563    cbase = static_cast<ComponentBase *>
564        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
565    if (!cbase)
566        return OMX_ErrorBadParameter;
567
568    return cbase->CBaseSetParameter(hComponent, nIndex,
569                                    pComponentParameterStructure);
570}
571
572OMX_ERRORTYPE ComponentBase::CBaseSetParameter(
573    OMX_IN  OMX_HANDLETYPE hComponent,
574    OMX_IN  OMX_INDEXTYPE nIndex,
575    OMX_IN  OMX_PTR pComponentParameterStructure)
576{
577    OMX_ERRORTYPE ret = OMX_ErrorNone;
578
579    if (hComponent != handle)
580        return OMX_ErrorBadParameter;
581
582    switch (nIndex) {
583    case OMX_IndexParamAudioInit:
584    case OMX_IndexParamVideoInit:
585    case OMX_IndexParamImageInit:
586    case OMX_IndexParamOtherInit: {
587        OMX_PORT_PARAM_TYPE *p = (OMX_PORT_PARAM_TYPE *)
588            pComponentParameterStructure;
589
590        memcpy(&portparam, p, sizeof(*p));
591        break;
592    }
593    case OMX_IndexParamPortDefinition: {
594        OMX_PARAM_PORTDEFINITIONTYPE *p =
595            (OMX_PARAM_PORTDEFINITIONTYPE *)pComponentParameterStructure;
596        OMX_U32 index = p->nPortIndex;
597        PortBase *port = ports[index];
598
599        port->SetPortParam(p);
600        break;
601    }
602    case OMX_IndexParamAudioPortFormat: {
603        OMX_AUDIO_PARAM_PORTFORMATTYPE *p =
604            (OMX_AUDIO_PARAM_PORTFORMATTYPE *)pComponentParameterStructure;
605        OMX_U32 index = p->nPortIndex;
606        PortBase *port = ports[index];
607
608        port->SetAudioPortParam(p);
609        break;
610    }
611    case OMX_IndexParamCompBufferSupplier:
612        /*
613         * Todo
614         */
615
616        ret = OMX_ErrorUnsupportedIndex;
617        break;
618    case OMX_IndexParamStandardComponentRole: {
619        OMX_PARAM_COMPONENTROLETYPE *p =
620            (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure;
621
622        ret = SetWorkingRole((OMX_STRING)p->cRole);
623        if (ret != OMX_ErrorNone)
624            return ret;
625        break;
626    }
627    default:
628        ret = ComponentSetParameter(nIndex, pComponentParameterStructure);
629    } /* switch */
630
631    return ret;
632}
633
634OMX_ERRORTYPE ComponentBase::GetConfig(
635    OMX_IN  OMX_HANDLETYPE hComponent,
636    OMX_IN  OMX_INDEXTYPE nIndex,
637    OMX_INOUT OMX_PTR pComponentConfigStructure)
638{
639    ComponentBase *cbase;
640
641    if (!hComponent)
642        return OMX_ErrorBadParameter;
643
644    cbase = static_cast<ComponentBase *>
645        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
646    if (!cbase)
647        return OMX_ErrorBadParameter;
648
649    return cbase->CBaseGetConfig(hComponent, nIndex,
650                                 pComponentConfigStructure);
651}
652
653OMX_ERRORTYPE ComponentBase::CBaseGetConfig(
654    OMX_IN  OMX_HANDLETYPE hComponent,
655    OMX_IN  OMX_INDEXTYPE nIndex,
656    OMX_INOUT OMX_PTR pComponentConfigStructure)
657{
658    OMX_ERRORTYPE ret;
659
660    if (hComponent != handle)
661        return OMX_ErrorBadParameter;
662
663    switch (nIndex) {
664    default:
665        ret = ComponentGetConfig(nIndex, pComponentConfigStructure);
666    }
667
668    return ret;
669}
670
671OMX_ERRORTYPE ComponentBase::SetConfig(
672    OMX_IN  OMX_HANDLETYPE hComponent,
673    OMX_IN  OMX_INDEXTYPE nIndex,
674    OMX_IN  OMX_PTR pComponentConfigStructure)
675{
676    ComponentBase *cbase;
677
678    if (!hComponent)
679        return OMX_ErrorBadParameter;
680
681    cbase = static_cast<ComponentBase *>
682        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
683    if (!cbase)
684        return OMX_ErrorBadParameter;
685
686    return cbase->CBaseSetConfig(hComponent, nIndex,
687                                 pComponentConfigStructure);
688}
689
690OMX_ERRORTYPE ComponentBase::CBaseSetConfig(
691    OMX_IN  OMX_HANDLETYPE hComponent,
692    OMX_IN  OMX_INDEXTYPE nIndex,
693    OMX_IN  OMX_PTR pComponentConfigStructure)
694{
695    OMX_ERRORTYPE ret;
696
697    if (hComponent != handle)
698        return OMX_ErrorBadParameter;
699
700    switch (nIndex) {
701    default:
702        ret = ComponentSetConfig(nIndex, pComponentConfigStructure);
703    }
704
705    return ret;
706}
707
708OMX_ERRORTYPE ComponentBase::GetExtensionIndex(
709    OMX_IN  OMX_HANDLETYPE hComponent,
710    OMX_IN  OMX_STRING cParameterName,
711    OMX_OUT OMX_INDEXTYPE* pIndexType)
712{
713    ComponentBase *cbase;
714
715    if (!hComponent)
716        return OMX_ErrorBadParameter;
717
718    cbase = static_cast<ComponentBase *>
719        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
720    if (!cbase)
721        return OMX_ErrorBadParameter;
722
723    return cbase->CBaseGetExtensionIndex(hComponent, cParameterName,
724                                         pIndexType);
725}
726
727OMX_ERRORTYPE ComponentBase::CBaseGetExtensionIndex(
728    OMX_IN  OMX_HANDLETYPE hComponent,
729    OMX_IN  OMX_STRING cParameterName,
730    OMX_OUT OMX_INDEXTYPE* pIndexType)
731{
732    /*
733     * Todo
734     */
735
736    return OMX_ErrorNotImplemented;
737}
738
739OMX_ERRORTYPE ComponentBase::GetState(
740    OMX_IN  OMX_HANDLETYPE hComponent,
741    OMX_OUT OMX_STATETYPE* pState)
742{
743    ComponentBase *cbase;
744
745    if (!hComponent)
746        return OMX_ErrorBadParameter;
747
748    cbase = static_cast<ComponentBase *>
749        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
750    if (!cbase)
751        return OMX_ErrorBadParameter;
752
753    return cbase->CBaseGetState(hComponent, pState);
754}
755
756OMX_ERRORTYPE ComponentBase::CBaseGetState(
757    OMX_IN  OMX_HANDLETYPE hComponent,
758    OMX_OUT OMX_STATETYPE* pState)
759{
760    if (hComponent != handle)
761        return OMX_ErrorBadParameter;
762
763    *pState = state;
764    return OMX_ErrorNone;
765}
766
767OMX_ERRORTYPE ComponentBase::ComponentTunnelRequest(
768    OMX_IN  OMX_HANDLETYPE hComponent,
769    OMX_IN  OMX_U32 nPort,
770    OMX_IN  OMX_HANDLETYPE hTunneledComponent,
771    OMX_IN  OMX_U32 nTunneledPort,
772    OMX_INOUT  OMX_TUNNELSETUPTYPE* pTunnelSetup)
773{
774    ComponentBase *cbase;
775
776    if (!hComponent)
777        return OMX_ErrorBadParameter;
778
779    cbase = static_cast<ComponentBase *>
780        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
781    if (!cbase)
782        return OMX_ErrorBadParameter;
783
784    return cbase->CBaseComponentTunnelRequest(hComponent, nPort,
785                                              hTunneledComponent,
786                                              nTunneledPort, pTunnelSetup);
787}
788
789OMX_ERRORTYPE ComponentBase::CBaseComponentTunnelRequest(
790    OMX_IN  OMX_HANDLETYPE hComp,
791    OMX_IN  OMX_U32 nPort,
792    OMX_IN  OMX_HANDLETYPE hTunneledComp,
793    OMX_IN  OMX_U32 nTunneledPort,
794    OMX_INOUT  OMX_TUNNELSETUPTYPE* pTunnelSetup)
795{
796    /*
797     * Todo
798     */
799
800    return OMX_ErrorNotImplemented;
801}
802
803OMX_ERRORTYPE ComponentBase::UseBuffer(
804    OMX_IN OMX_HANDLETYPE hComponent,
805    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr,
806    OMX_IN OMX_U32 nPortIndex,
807    OMX_IN OMX_PTR pAppPrivate,
808    OMX_IN OMX_U32 nSizeBytes,
809    OMX_IN OMX_U8 *pBuffer)
810{
811    ComponentBase *cbase;
812
813    if (!hComponent)
814        return OMX_ErrorBadParameter;
815
816    cbase = static_cast<ComponentBase *>
817        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
818    if (!cbase)
819        return OMX_ErrorBadParameter;
820
821    return cbase->CBaseUseBuffer(hComponent, ppBufferHdr, nPortIndex,
822                                 pAppPrivate, nSizeBytes, pBuffer);
823}
824
825OMX_ERRORTYPE ComponentBase::CBaseUseBuffer(
826    OMX_IN OMX_HANDLETYPE hComponent,
827    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr,
828    OMX_IN OMX_U32 nPortIndex,
829    OMX_IN OMX_PTR pAppPrivate,
830    OMX_IN OMX_U32 nSizeBytes,
831    OMX_IN OMX_U8 *pBuffer)
832{
833    PortBase *port = NULL;
834    OMX_ERRORTYPE ret;
835
836    if (hComponent != handle)
837        return OMX_ErrorBadParameter;
838
839    if (ports)
840        if (nPortIndex < nr_ports)
841            port = ports[nPortIndex];
842
843    if (!port)
844        return OMX_ErrorBadParameter;
845
846    return port->UseBuffer(ppBufferHdr, nPortIndex, pAppPrivate, nSizeBytes,
847                           pBuffer);
848}
849
850OMX_ERRORTYPE ComponentBase::AllocateBuffer(
851    OMX_IN OMX_HANDLETYPE hComponent,
852    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer,
853    OMX_IN OMX_U32 nPortIndex,
854    OMX_IN OMX_PTR pAppPrivate,
855    OMX_IN OMX_U32 nSizeBytes)
856{
857    ComponentBase *cbase;
858
859    if (!hComponent)
860        return OMX_ErrorBadParameter;
861
862    cbase = static_cast<ComponentBase *>
863        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
864    if (!cbase)
865        return OMX_ErrorBadParameter;
866
867    return cbase->CBaseAllocateBuffer(hComponent, ppBuffer, nPortIndex,
868                                      pAppPrivate, nSizeBytes);
869}
870
871OMX_ERRORTYPE ComponentBase::CBaseAllocateBuffer(
872    OMX_IN OMX_HANDLETYPE hComponent,
873    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer,
874    OMX_IN OMX_U32 nPortIndex,
875    OMX_IN OMX_PTR pAppPrivate,
876    OMX_IN OMX_U32 nSizeBytes)
877{
878    PortBase *port = NULL;
879    OMX_ERRORTYPE ret;
880
881    if (hComponent != handle)
882        return OMX_ErrorBadParameter;
883
884    if (ports)
885        if (nPortIndex < nr_ports)
886            port = ports[nPortIndex];
887
888    if (!port)
889        return OMX_ErrorBadParameter;
890
891    return port->AllocateBuffer(ppBuffer, nPortIndex, pAppPrivate, nSizeBytes);
892}
893
894OMX_ERRORTYPE ComponentBase::FreeBuffer(
895    OMX_IN  OMX_HANDLETYPE hComponent,
896    OMX_IN  OMX_U32 nPortIndex,
897    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
898{
899    ComponentBase *cbase;
900
901    if (!hComponent)
902        return OMX_ErrorBadParameter;
903
904    cbase = static_cast<ComponentBase *>
905        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
906    if (!cbase)
907        return OMX_ErrorBadParameter;
908
909    return cbase->CBaseFreeBuffer(hComponent, nPortIndex, pBuffer);
910}
911
912OMX_ERRORTYPE ComponentBase::CBaseFreeBuffer(
913    OMX_IN  OMX_HANDLETYPE hComponent,
914    OMX_IN  OMX_U32 nPortIndex,
915    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
916{
917    PortBase *port = NULL;
918    OMX_ERRORTYPE ret;
919
920    if (hComponent != handle)
921        return OMX_ErrorBadParameter;
922
923    if (ports)
924        if (nPortIndex < nr_ports)
925            port = ports[nPortIndex];
926
927    if (!port)
928        return OMX_ErrorBadParameter;
929
930    return port->FreeBuffer(nPortIndex, pBuffer);
931}
932
933OMX_ERRORTYPE ComponentBase::EmptyThisBuffer(
934    OMX_IN  OMX_HANDLETYPE hComponent,
935    OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer)
936{
937    ComponentBase *cbase;
938
939    if (!hComponent)
940        return OMX_ErrorBadParameter;
941
942    cbase = static_cast<ComponentBase *>
943        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
944    if (!cbase)
945        return OMX_ErrorBadParameter;
946
947    return cbase->CBaseEmptyThisBuffer(hComponent, pBuffer);
948}
949
950OMX_ERRORTYPE ComponentBase::CBaseEmptyThisBuffer(
951    OMX_IN  OMX_HANDLETYPE hComponent,
952    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
953{
954    PortBase *port = NULL;
955    OMX_U32 port_index;
956    OMX_ERRORTYPE ret;
957
958    if ((hComponent != handle) || !pBuffer)
959        return OMX_ErrorBadParameter;
960
961    port_index = pBuffer->nInputPortIndex;
962    if (port_index == (OMX_U32)-1)
963        return OMX_ErrorBadParameter;
964
965    if (ports)
966        if (port_index < nr_ports)
967            port = ports[port_index];
968
969    if (!port)
970        return OMX_ErrorBadParameter;
971
972    ret = port->PushThisBuffer(pBuffer);
973    if (ret == OMX_ErrorNone)
974        bufferwork->ScheduleWork(this);
975
976    return ret;
977}
978
979OMX_ERRORTYPE ComponentBase::FillThisBuffer(
980    OMX_IN  OMX_HANDLETYPE hComponent,
981    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
982{
983    ComponentBase *cbase;
984
985    if (!hComponent)
986        return OMX_ErrorBadParameter;
987
988    cbase = static_cast<ComponentBase *>
989        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
990    if (!cbase)
991        return OMX_ErrorBadParameter;
992
993    return cbase->CBaseFillThisBuffer(hComponent, pBuffer);
994}
995
996OMX_ERRORTYPE ComponentBase::CBaseFillThisBuffer(
997    OMX_IN  OMX_HANDLETYPE hComponent,
998    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
999{
1000    PortBase *port = NULL;
1001    OMX_U32 port_index;
1002    OMX_ERRORTYPE ret;
1003
1004    if ((hComponent != handle) || !pBuffer)
1005        return OMX_ErrorBadParameter;
1006
1007    port_index = pBuffer->nOutputPortIndex;
1008    if (port_index == (OMX_U32)-1)
1009        return OMX_ErrorBadParameter;
1010
1011    if (ports)
1012        if (port_index < nr_ports)
1013            port = ports[port_index];
1014
1015    if (!port)
1016        return OMX_ErrorBadParameter;
1017
1018    ret = port->PushThisBuffer(pBuffer);
1019    if (ret == OMX_ErrorNone)
1020        bufferwork->ScheduleWork(this);
1021
1022    return ret;
1023}
1024
1025OMX_ERRORTYPE ComponentBase::SetCallbacks(
1026    OMX_IN  OMX_HANDLETYPE hComponent,
1027    OMX_IN  OMX_CALLBACKTYPE* pCallbacks,
1028    OMX_IN  OMX_PTR pAppData)
1029{
1030    ComponentBase *cbase;
1031
1032    if (!hComponent)
1033        return OMX_ErrorBadParameter;
1034
1035    cbase = static_cast<ComponentBase *>
1036        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
1037    if (!cbase)
1038        return OMX_ErrorBadParameter;
1039
1040    return cbase->CBaseSetCallbacks(hComponent, pCallbacks, pAppData);
1041}
1042
1043OMX_ERRORTYPE ComponentBase::CBaseSetCallbacks(
1044    OMX_IN  OMX_HANDLETYPE hComponent,
1045    OMX_IN  OMX_CALLBACKTYPE *pCallbacks,
1046    OMX_IN  OMX_PTR pAppData)
1047{
1048    if (hComponent != handle)
1049        return OMX_ErrorBadParameter;
1050
1051    appdata = pAppData;
1052    callbacks = pCallbacks;
1053
1054    return OMX_ErrorNone;
1055}
1056
1057OMX_ERRORTYPE ComponentBase::ComponentDeInit(
1058    OMX_IN  OMX_HANDLETYPE hComponent)
1059{
1060    ComponentBase *cbase;
1061
1062    if (!hComponent)
1063        return OMX_ErrorBadParameter;
1064
1065    cbase = static_cast<ComponentBase *>
1066        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
1067    if (!cbase)
1068        return OMX_ErrorBadParameter;
1069
1070    return cbase->CBaseComponentDeInit(hComponent);
1071}
1072
1073OMX_ERRORTYPE ComponentBase::CBaseComponentDeInit(
1074    OMX_IN  OMX_HANDLETYPE hComponent)
1075{
1076    /*
1077     * Todo
1078     */
1079
1080    return OMX_ErrorNotImplemented;
1081}
1082
1083OMX_ERRORTYPE ComponentBase::UseEGLImage(
1084    OMX_IN OMX_HANDLETYPE hComponent,
1085    OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
1086    OMX_IN OMX_U32 nPortIndex,
1087    OMX_IN OMX_PTR pAppPrivate,
1088    OMX_IN void* eglImage)
1089{
1090    ComponentBase *cbase;
1091
1092    if (!hComponent)
1093        return OMX_ErrorBadParameter;
1094
1095    cbase = static_cast<ComponentBase *>
1096        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
1097    if (!cbase)
1098        return OMX_ErrorBadParameter;
1099
1100    return cbase->CBaseUseEGLImage(hComponent, ppBufferHdr, nPortIndex,
1101                                   pAppPrivate, eglImage);
1102}
1103
1104OMX_ERRORTYPE ComponentBase::CBaseUseEGLImage(
1105    OMX_IN OMX_HANDLETYPE hComponent,
1106    OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
1107    OMX_IN OMX_U32 nPortIndex,
1108    OMX_IN OMX_PTR pAppPrivate,
1109    OMX_IN void* eglImage)
1110{
1111    /*
1112     * Todo
1113     */
1114
1115    return OMX_ErrorNotImplemented;
1116}
1117
1118OMX_ERRORTYPE ComponentBase::ComponentRoleEnum(
1119    OMX_IN OMX_HANDLETYPE hComponent,
1120    OMX_OUT OMX_U8 *cRole,
1121    OMX_IN OMX_U32 nIndex)
1122{
1123    ComponentBase *cbase;
1124
1125    if (!hComponent)
1126        return OMX_ErrorBadParameter;
1127
1128    cbase = static_cast<ComponentBase *>
1129        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
1130    if (!cbase)
1131        return OMX_ErrorBadParameter;
1132
1133    return cbase->CBaseComponentRoleEnum(hComponent, cRole, nIndex);
1134}
1135
1136OMX_ERRORTYPE ComponentBase::CBaseComponentRoleEnum(
1137    OMX_IN OMX_HANDLETYPE hComponent,
1138    OMX_OUT OMX_U8 *cRole,
1139    OMX_IN OMX_U32 nIndex)
1140{
1141    if (hComponent != (OMX_HANDLETYPE *)this->handle)
1142        return OMX_ErrorBadParameter;
1143
1144    if (nIndex > nr_roles)
1145        return OMX_ErrorBadParameter;
1146
1147    strncpy((char *)cRole, (const char *)roles[nIndex],
1148            OMX_MAX_STRINGNAME_SIZE);
1149    return OMX_ErrorNone;
1150}
1151
1152/* implement CmdHandlerInterface */
1153void ComponentBase::CmdHandler(struct cmd_s *cmd)
1154{
1155    switch (cmd->cmd) {
1156    case OMX_CommandStateSet: {
1157        OMX_STATETYPE transition = (OMX_STATETYPE)cmd->param1;
1158
1159        TransState(transition);
1160        break;
1161    }
1162    case OMX_CommandFlush:
1163        /*
1164         * Todo
1165         */
1166        break;
1167    case OMX_CommandPortDisable:
1168        /*
1169         * Todo
1170         */
1171        break;
1172    case OMX_CommandPortEnable:
1173        /*
1174         * Todo
1175         */
1176        break;
1177    case OMX_CommandMarkBuffer:
1178        /*
1179         * Todo
1180         */
1181        break;
1182    } /* switch */
1183}
1184
1185/*
1186 * SendCommand:OMX_CommandStateSet
1187 * called in CmdHandler or called in other parts of component for reporting
1188 * internal error (OMX_StateInvalid).
1189 */
1190/*
1191 * Todo
1192 *   Resource Management (OMX_StateWaitForResources)
1193 *   for now, we never notify OMX_ErrorInsufficientResources,
1194 *   so IL client doesn't try to set component' state OMX_StateWaitForResources
1195 */
1196static const char *state_name[OMX_StateWaitForResources + 1] = {
1197    "OMX_StateInvalid",
1198    "OMX_StateLoaded",
1199    "OMX_StateIdle",
1200    "OMX_StateExecuting",
1201    "OMX_StatePause",
1202    "OMX_StateWaitForResources",
1203};
1204
1205static inline const char *GetStateName(OMX_STATETYPE state)
1206{
1207    if (state > OMX_StateWaitForResources)
1208        return "UnKnown";
1209
1210    return state_name[state];
1211}
1212
1213void ComponentBase::TransState(OMX_STATETYPE transition)
1214{
1215    OMX_STATETYPE current = this->state;
1216    OMX_EVENTTYPE event;
1217    OMX_U32 data1;
1218    OMX_ERRORTYPE ret;
1219
1220    LOGD("current state = %s, transition state = %s\n",
1221         GetStateName(current), GetStateName(transition));
1222
1223    /* same state */
1224    if (current == transition) {
1225        ret = OMX_ErrorSameState;
1226        goto notify_event;
1227    }
1228
1229    /* invalid state */
1230    if (current == OMX_StateInvalid) {
1231        ret = OMX_ErrorInvalidState;
1232        goto notify_event;
1233    }
1234
1235    if (transition == OMX_StateLoaded)
1236        ret = TransStateToLoaded(current);
1237    else if (transition == OMX_StateIdle)
1238        ret = TransStateToIdle(current);
1239    else if (transition == OMX_StateExecuting)
1240        ret = TransStateToExecuting(current);
1241    else if (transition == OMX_StatePause)
1242        ret = TransStateToPause(current);
1243    else if (transition == OMX_StateInvalid)
1244        ret = TransStateToInvalid(current);
1245    else if (transition == OMX_StateWaitForResources)
1246        ret = TransStateToWaitForResources(current);
1247    else
1248        ret = OMX_ErrorIncorrectStateTransition;
1249
1250notify_event:
1251    if (ret == OMX_ErrorNone) {
1252        event = OMX_EventCmdComplete;
1253        data1 = transition;
1254
1255        state = transition;
1256        LOGD("transition from %s to %s completed\n",
1257             GetStateName(current), GetStateName(transition));
1258    }
1259    else {
1260        event = OMX_EventError;
1261        data1 = ret;
1262
1263        if (transition == OMX_StateInvalid) {
1264            state = transition;
1265            LOGD("transition from %s to %s completed\n",
1266                 GetStateName(current), GetStateName(transition));
1267        }
1268    }
1269
1270    callbacks->EventHandler(handle, appdata, event, data1, 0, NULL);
1271
1272    /* WaitForResources workaround */
1273    if (ret == OMX_ErrorNone && transition == OMX_StateWaitForResources)
1274        callbacks->EventHandler(handle, appdata,
1275                                OMX_EventResourcesAcquired, 0, 0, NULL);
1276}
1277
1278inline OMX_ERRORTYPE ComponentBase::TransStateToLoaded(OMX_STATETYPE current)
1279{
1280    OMX_ERRORTYPE ret;
1281
1282    if (current == OMX_StateIdle) {
1283        /*
1284         * Todo
1285         *   1. waits for completion of deallocation on each port
1286         *      wokeup by FreeBuffer()
1287         *   2. deinitialize buffer process work
1288         *   3. deinitialize component's internal processor
1289         *      (ex. deinitialize sw/hw codec)
1290         */
1291        OMX_U32 i;
1292
1293        for (i = 0; i < nr_ports; i++)
1294            ports[i]->WaitPortBufferCompletion();
1295
1296        ret = OMX_ErrorNone;
1297    }
1298    else if (current == OMX_StateWaitForResources) {
1299        LOGE("state transition's requested from WaitForResources to "
1300             "Loaded\n");
1301
1302        /*
1303         * from WaitForResources to Loaded considered from Loaded to Loaded.
1304         * do nothing
1305         */
1306
1307        ret = OMX_ErrorNone;
1308    }
1309    else
1310        ret = OMX_ErrorIncorrectStateOperation;
1311
1312    return ret;
1313}
1314
1315inline OMX_ERRORTYPE ComponentBase::TransStateToIdle(OMX_STATETYPE current)
1316{
1317    OMX_ERRORTYPE ret;
1318
1319    if (current == OMX_StateLoaded) {
1320        /*
1321         * Todo
1322         *   1. waits for completion of allocation on each port.
1323         *      wokeup by Allocate/UseBuffer()
1324         *   2. initialize buffer process work.
1325         *   3. initialize component's internal processor.
1326         *      (ex. initialize sw/hw codec)
1327         */
1328        OMX_U32 i;
1329
1330        for (i = 0; i < nr_ports; i++)
1331            ports[i]->WaitPortBufferCompletion();
1332
1333        ret = OMX_ErrorNone;
1334    }
1335    else if (current == OMX_StateExecuting) {
1336        /*
1337         * Todo
1338         *   1. returns all buffers to thier suppliers.         !
1339         *      call Fill/EmptyBufferDone() for all ports
1340         *   2. stop buffer process work                        !
1341         *   3. stop component's internal processor
1342         */
1343        OMX_U32 i;
1344
1345        pthread_mutex_lock(&ports_block);
1346        for (i = 0; i < nr_ports; i++) {
1347            ports[i]->FlushPort();
1348        }
1349        pthread_mutex_unlock(&ports_block);
1350
1351        bufferwork->StopWork();
1352
1353        ret = OMX_ErrorNone;
1354    }
1355    else if (current == OMX_StatePause) {
1356        /*
1357         * Todo
1358         *   1. returns all buffers to thier suppliers.         !
1359         *      call Fill/EmptyBufferDone() for all ports
1360         *   2. discard queued work, stop buffer process work   !
1361         *   3. stop component's internal processor
1362         */
1363        OMX_U32 i;
1364
1365        pthread_mutex_lock(&ports_block);
1366        for (i = 0; i < nr_ports; i++) {
1367            ports[i]->FlushPort();
1368        }
1369        pthread_mutex_unlock(&ports_block);
1370
1371        bufferwork->CancelScheduledWork(this);
1372        bufferwork->StopWork();
1373
1374        ret = OMX_ErrorNone;
1375    }
1376    else if (current == OMX_StateWaitForResources) {
1377        LOGE("state transition's requested from WaitForResources to Idle\n");
1378
1379        /* same as Loaded to Idle BUT DO NOTHING for now */
1380
1381        ret = OMX_ErrorNone;
1382    }
1383    else
1384        ret = OMX_ErrorIncorrectStateOperation;
1385
1386    return ret;
1387}
1388
1389inline OMX_ERRORTYPE
1390ComponentBase::TransStateToExecuting(OMX_STATETYPE current)
1391{
1392    OMX_ERRORTYPE ret;
1393
1394    if (current == OMX_StateIdle) {
1395        /*
1396         * Todo
1397         *   1. start component's internal processor
1398         *   2. start processing buffers on each port   !
1399         */
1400
1401        pthread_mutex_lock(&executing_lock);
1402        executing = true;
1403        pthread_mutex_unlock(&executing_lock);
1404
1405        bufferwork->StartWork();
1406        ret = OMX_ErrorNone;
1407    }
1408    else if (current == OMX_StatePause) {
1409        /*
1410         * Todo
1411         *   1. resume component's internal processor
1412         *   2. resume buffer process work              !
1413         */
1414
1415        pthread_mutex_lock(&executing_lock);
1416        executing = true;
1417        pthread_cond_signal(&executing_wait);
1418        pthread_mutex_unlock(&executing_lock);
1419
1420        ret = OMX_ErrorNone;
1421    }
1422    else
1423        ret = OMX_ErrorIncorrectStateOperation;
1424
1425    return ret;
1426}
1427
1428inline OMX_ERRORTYPE ComponentBase::TransStateToPause(OMX_STATETYPE current)
1429{
1430    OMX_ERRORTYPE ret;
1431
1432    if (current == OMX_StateIdle) {
1433        /*
1434         * Todo
1435         *   1. start(paused) component's internal processor
1436         *   2. start(paused) processing buffers on each port   !
1437         */
1438
1439        /* turn off executing flag */
1440        pthread_mutex_lock(&executing_lock);
1441        executing = false;
1442        pthread_mutex_unlock(&executing_lock);
1443
1444        bufferwork->StartWork();
1445
1446        ret = OMX_ErrorNone;
1447    }
1448    else if (current == OMX_StateExecuting) {
1449        /*
1450         * Todo
1451         *   1. pause buffer process work               !
1452         *   2. pause component's internal processor
1453         */
1454
1455        pthread_mutex_lock(&executing_lock);
1456        executing = false;
1457        pthread_mutex_unlock(&executing_lock);
1458
1459        ret = OMX_ErrorNone;
1460    }
1461    else
1462        ret = OMX_ErrorIncorrectStateOperation;
1463
1464    return ret;
1465}
1466
1467inline OMX_ERRORTYPE ComponentBase::TransStateToInvalid(OMX_STATETYPE current)
1468{
1469    OMX_ERRORTYPE ret = OMX_ErrorInvalidState;
1470
1471    /*
1472     * Todo
1473     *   graceful escape
1474     */
1475
1476    return ret;
1477}
1478
1479inline OMX_ERRORTYPE
1480ComponentBase::TransStateToWaitForResources(OMX_STATETYPE current)
1481{
1482    OMX_ERRORTYPE ret;
1483
1484    if (current == OMX_StateLoaded) {
1485        LOGE("state transition's requested from Loaded to WaitForResources\n");
1486        ret = OMX_ErrorNone;
1487    }
1488    else
1489        ret = OMX_ErrorIncorrectStateOperation;
1490
1491    return ret;
1492}
1493
1494/* set working role */
1495OMX_ERRORTYPE ComponentBase::SetWorkingRole(const OMX_STRING role)
1496{
1497    OMX_U32 i;
1498
1499    if (!role)
1500        return OMX_ErrorBadParameter;
1501
1502    for (i = 0; i < nr_roles; i++) {
1503        if (!strcmp((char *)&roles[i][0], role)) {
1504            working_role = (OMX_STRING)&roles[i][0];
1505            return OMX_ErrorNone;
1506        }
1507    }
1508
1509    return OMX_ErrorBadParameter;
1510}
1511
1512/* apply a working role for a component having multiple roles */
1513OMX_ERRORTYPE ComponentBase::ApplyWorkingRole(void)
1514{
1515    OMX_ERRORTYPE ret;
1516
1517    if (!working_role)
1518        return OMX_ErrorBadParameter;
1519
1520    ret = AllocatePorts();
1521    if (ret != OMX_ErrorNone) {
1522        LOGE("failed to AllocatePorts() (ret = 0x%08x)\n", ret);
1523        return ret;
1524    }
1525
1526    return OMX_ErrorNone;
1527}
1528
1529OMX_ERRORTYPE ComponentBase::AllocatePorts(void)
1530{
1531    OMX_ERRORTYPE ret;
1532    OMX_U32 i;
1533
1534    if (ports)
1535        return OMX_ErrorBadParameter;
1536
1537    if (!callbacks || !appdata)
1538        return OMX_ErrorBadParameter;
1539
1540    ret = ComponentAllocatePorts();
1541    if (ret != OMX_ErrorNone) {
1542        LOGE("failed to %s::ComponentAllocatePorts(), ret = 0x%08x\n",
1543             name, ret);
1544        return ret;
1545    }
1546
1547    /* now we can access ports */
1548    for (i = 0; i < nr_ports; i++) {
1549        ports[i]->SetOwner(handle);
1550        ports[i]->SetCallbacks(handle, callbacks, appdata);
1551    }
1552
1553    return OMX_ErrorNone;
1554}
1555
1556/* called int FreeHandle() */
1557OMX_ERRORTYPE ComponentBase::FreePorts(void)
1558{
1559    if (ports) {
1560        OMX_U32 i, this_nr_ports = this->nr_ports;
1561
1562        for (i = 0; i < this_nr_ports; i++) {
1563            if (ports[i]) {
1564                delete ports[i];
1565                ports[i] = NULL;
1566            }
1567        }
1568        delete []ports;
1569        ports = NULL;
1570    }
1571
1572    return OMX_ErrorNone;
1573}
1574
1575/* buffer processing */
1576/* implement WorkableInterface */
1577void ComponentBase::Work(void)
1578{
1579    OMX_BUFFERHEADERTYPE **buffers = NULL;
1580    OMX_U32 i;
1581    bool avail = false;
1582
1583    pthread_mutex_lock(&executing_lock);
1584    if (!executing)
1585        pthread_cond_wait(&executing_wait, &executing_lock);
1586    pthread_mutex_unlock(&executing_lock);
1587
1588    pthread_mutex_lock(&ports_block);
1589
1590    avail = IsAllBufferAvailable();
1591    if (avail) {
1592        buffers = (OMX_BUFFERHEADERTYPE **)
1593            calloc(nr_ports, sizeof(OMX_BUFFERHEADERTYPE *));
1594        if (!buffers) {
1595            bufferwork->ScheduleWork(this);
1596            return;
1597        }
1598
1599        for (i = 0; i < nr_ports; i++)
1600            buffers[i] = ports[i]->PopBuffer();
1601    }
1602    ScheduleIfAllBufferAvailable();
1603
1604    pthread_mutex_unlock(&ports_block);
1605
1606    if (buffers) {
1607        ComponentProcessBuffers(buffers, nr_ports);
1608
1609        free(buffers);
1610        buffers = NULL;
1611    }
1612}
1613
1614bool ComponentBase::IsAllBufferAvailable(void)
1615{
1616    OMX_U32 i;
1617    OMX_U32 nr_avail = 0;
1618
1619    for (i = 0; i < nr_ports; i++) {
1620        OMX_U32 length;
1621
1622        length = ports[i]->BufferQueueLength();
1623        if (length)
1624            nr_avail++;
1625    }
1626
1627    if (nr_avail == nr_ports)
1628        return true;
1629    else
1630        return false;
1631}
1632
1633void ComponentBase::ScheduleIfAllBufferAvailable(void)
1634{
1635    bool avail;
1636
1637    avail = IsAllBufferAvailable();
1638    if (avail)
1639        bufferwork->ScheduleWork(this);
1640}
1641
1642/* end of component methods & helpers */
1643
1644/*
1645 * omx header manipuation
1646 */
1647void ComponentBase::SetTypeHeader(OMX_PTR type, OMX_U32 size)
1648{
1649    OMX_U32 *nsize;
1650    OMX_VERSIONTYPE *nversion;
1651
1652    if (!type)
1653        return;
1654
1655    nsize = (OMX_U32 *)type;
1656    nversion = (OMX_VERSIONTYPE *)((OMX_U8 *)type + sizeof(OMX_U32));
1657
1658    *nsize = size;
1659    nversion->nVersion = OMX_SPEC_VERSION;
1660}
1661
1662OMX_ERRORTYPE ComponentBase::CheckTypeHeader(OMX_PTR type, OMX_U32 size)
1663{
1664    OMX_U32 *nsize;
1665    OMX_VERSIONTYPE *nversion;
1666
1667    if (!type)
1668        return OMX_ErrorBadParameter;
1669
1670    nsize = (OMX_U32 *)type;
1671    nversion = (OMX_VERSIONTYPE *)((OMX_U8 *)type + sizeof(OMX_U32));
1672
1673    if (*nsize != size)
1674        return OMX_ErrorBadParameter;
1675
1676    if (nversion->nVersion != OMX_SPEC_VERSION)
1677        return OMX_ErrorVersionMismatch;
1678
1679    return OMX_ErrorNone;
1680}
1681
1682/* end of ComponentBase */
1683