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