componentbase.cpp revision 69d34dfb7d76cbdd1bd0f0b4b7cb1f2267f5002a
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            this->roles[i+1] = this->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    handle = (OMX_COMPONENTTYPE *)calloc(1, sizeof(*handle));
250    if (!handle)
251        return OMX_ErrorInsufficientResources;
252
253    /* handle initialization */
254    SetTypeHeader(handle, sizeof(*handle));
255    handle->pComponentPrivate = static_cast<OMX_PTR>(this);
256    handle->pApplicationPrivate = pAppData;
257
258    /* connect handle's functions */
259    handle->GetComponentVersion = GetComponentVersion;
260    handle->SendCommand = SendCommand;
261    handle->GetParameter = GetParameter;
262    handle->SetParameter = SetParameter;
263    handle->GetConfig = GetConfig;
264    handle->SetConfig = SetConfig;
265    handle->GetExtensionIndex = GetExtensionIndex;
266    handle->GetState = GetState;
267    handle->ComponentTunnelRequest = ComponentTunnelRequest;
268    handle->UseBuffer = UseBuffer;
269    handle->AllocateBuffer = AllocateBuffer;
270    handle->FreeBuffer = FreeBuffer;
271    handle->EmptyThisBuffer = EmptyThisBuffer;
272    handle->FillThisBuffer = FillThisBuffer;
273    handle->SetCallbacks = SetCallbacks;
274    handle->ComponentDeInit = ComponentDeInit;
275    handle->UseEGLImage = UseEGLImage;
276    handle->ComponentRoleEnum = ComponentRoleEnum;
277
278    appdata = pAppData;
279    callbacks = pCallBacks;
280
281    if (nr_roles == 1) {
282        SetWorkingRole((OMX_STRING)&roles[0][0]);
283        ret = ApplyWorkingRole();
284        if (ret != OMX_ErrorNone) {
285            SetWorkingRole(NULL);
286            goto free_handle;
287        }
288    }
289
290    *pHandle = (OMX_HANDLETYPE *)handle;
291    state = OMX_StateLoaded;
292    return OMX_ErrorNone;
293
294free_handle:
295    free(handle);
296
297    appdata = NULL;
298    callbacks = NULL;
299    *pHandle = NULL;
300
301    return ret;
302}
303
304OMX_ERRORTYPE ComponentBase::FreeHandle(OMX_HANDLETYPE hComponent)
305{
306    OMX_ERRORTYPE ret;
307
308    if (hComponent != handle)
309        return OMX_ErrorBadParameter;
310
311    if (state != OMX_StateLoaded)
312        return OMX_ErrorIncorrectStateOperation;
313
314    FreePorts();
315
316    free(handle);
317
318    appdata = NULL;
319    callbacks = NULL;
320
321    state = OMX_StateUnloaded;
322    return OMX_ErrorNone;
323}
324
325/* end of core methods & helpers */
326
327/*
328 * component methods & helpers
329 */
330OMX_ERRORTYPE ComponentBase::GetComponentVersion(
331    OMX_IN  OMX_HANDLETYPE hComponent,
332    OMX_OUT OMX_STRING pComponentName,
333    OMX_OUT OMX_VERSIONTYPE* pComponentVersion,
334    OMX_OUT OMX_VERSIONTYPE* pSpecVersion,
335    OMX_OUT OMX_UUIDTYPE* pComponentUUID)
336{
337    ComponentBase *cbase;
338
339    if (!hComponent)
340        return OMX_ErrorBadParameter;
341
342    cbase = static_cast<ComponentBase *>
343        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
344    if (!cbase)
345        return OMX_ErrorBadParameter;
346
347    return cbase->CBaseGetComponentVersion(hComponent,
348                                           pComponentName,
349                                           pComponentVersion,
350                                           pSpecVersion,
351                                           pComponentUUID);
352}
353
354OMX_ERRORTYPE ComponentBase::CBaseGetComponentVersion(
355    OMX_IN  OMX_HANDLETYPE hComponent,
356    OMX_OUT OMX_STRING pComponentName,
357    OMX_OUT OMX_VERSIONTYPE* pComponentVersion,
358    OMX_OUT OMX_VERSIONTYPE* pSpecVersion,
359    OMX_OUT OMX_UUIDTYPE* pComponentUUID)
360{
361    /*
362     * Todo
363     */
364
365    return OMX_ErrorNotImplemented;
366}
367
368OMX_ERRORTYPE ComponentBase::SendCommand(
369    OMX_IN  OMX_HANDLETYPE hComponent,
370    OMX_IN  OMX_COMMANDTYPE Cmd,
371    OMX_IN  OMX_U32 nParam1,
372    OMX_IN  OMX_PTR pCmdData)
373{
374    ComponentBase *cbase;
375
376    if (!hComponent)
377        return OMX_ErrorBadParameter;
378
379    cbase = static_cast<ComponentBase *>
380        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
381    if (!cbase)
382        return OMX_ErrorBadParameter;
383
384    return cbase->CBaseSendCommand(hComponent, Cmd, nParam1, pCmdData);
385}
386
387OMX_ERRORTYPE ComponentBase::CBaseSendCommand(
388    OMX_IN  OMX_HANDLETYPE hComponent,
389    OMX_IN  OMX_COMMANDTYPE Cmd,
390    OMX_IN  OMX_U32 nParam1,
391    OMX_IN  OMX_PTR pCmdData)
392{
393    struct cmd_s *cmd;
394
395    if (hComponent != handle)
396        return OMX_ErrorInvalidComponent;
397
398    /* basic error check */
399    switch (Cmd) {
400    case OMX_CommandStateSet:
401        /*
402         * Todo
403         */
404        break;
405    case OMX_CommandFlush: {
406        OMX_U32 port_index = nParam1;
407
408        if ((port_index != OMX_ALL) && (port_index > nr_ports-1))
409            return OMX_ErrorBadPortIndex;
410        break;
411    }
412    case OMX_CommandPortDisable:
413    case OMX_CommandPortEnable: {
414        OMX_U32 port_index = nParam1;
415
416        if ((port_index != OMX_ALL) && (port_index > nr_ports-1))
417            return OMX_ErrorBadPortIndex;
418        break;
419    }
420    case OMX_CommandMarkBuffer: {
421        OMX_MARKTYPE *mark = (OMX_MARKTYPE *)pCmdData;
422        OMX_MARKTYPE *copiedmark;
423        OMX_U32 port_index = nParam1;
424
425        if (port_index > nr_ports-1)
426            return OMX_ErrorBadPortIndex;
427
428        if (!mark || !mark->hMarkTargetComponent)
429            return OMX_ErrorBadParameter;
430
431        copiedmark = (OMX_MARKTYPE *)malloc(sizeof(*copiedmark));
432        if (!copiedmark)
433            return OMX_ErrorInsufficientResources;
434
435        copiedmark->hMarkTargetComponent = mark->hMarkTargetComponent;
436        copiedmark->pMarkData = mark->pMarkData;
437        pCmdData = (OMX_PTR)copiedmark;
438        break;
439    }
440    default:
441        LOGE("command %d not supported\n", Cmd);
442        return OMX_ErrorUnsupportedIndex;
443    }
444
445    cmd = (struct cmd_s *)malloc(sizeof(*cmd));
446    if (!cmd)
447        return OMX_ErrorInsufficientResources;
448
449    cmd->cmd = Cmd;
450    cmd->param1 = nParam1;
451    cmd->cmddata = pCmdData;
452
453    return cmdwork->PushCmdQueue(cmd);
454}
455
456OMX_ERRORTYPE ComponentBase::GetParameter(
457    OMX_IN  OMX_HANDLETYPE hComponent,
458    OMX_IN  OMX_INDEXTYPE nParamIndex,
459    OMX_INOUT OMX_PTR pComponentParameterStructure)
460{
461    ComponentBase *cbase;
462
463    if (!hComponent)
464        return OMX_ErrorBadParameter;
465
466    cbase = static_cast<ComponentBase *>
467        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
468    if (!cbase)
469        return OMX_ErrorBadParameter;
470
471    return cbase->CBaseGetParameter(hComponent, nParamIndex,
472                                    pComponentParameterStructure);
473}
474
475OMX_ERRORTYPE ComponentBase::CBaseGetParameter(
476    OMX_IN  OMX_HANDLETYPE hComponent,
477    OMX_IN  OMX_INDEXTYPE nParamIndex,
478    OMX_INOUT OMX_PTR pComponentParameterStructure)
479{
480    OMX_ERRORTYPE ret = OMX_ErrorNone;
481
482    if (hComponent != handle)
483        return OMX_ErrorBadParameter;
484
485    switch (nParamIndex) {
486    case OMX_IndexParamAudioInit:
487    case OMX_IndexParamVideoInit:
488    case OMX_IndexParamImageInit:
489    case OMX_IndexParamOtherInit: {
490        OMX_PORT_PARAM_TYPE *p =
491            (OMX_PORT_PARAM_TYPE *)pComponentParameterStructure;
492
493        ret = CheckTypeHeader(p, sizeof(*p));
494        if (ret != OMX_ErrorNone)
495            return ret;
496
497        memcpy(p, &portparam, sizeof(*p));
498        break;
499    }
500    case OMX_IndexParamPortDefinition: {
501        OMX_PARAM_PORTDEFINITIONTYPE *p =
502            (OMX_PARAM_PORTDEFINITIONTYPE *)pComponentParameterStructure;
503        OMX_U32 index = p->nPortIndex;
504        PortBase *port = NULL;
505
506        ret = CheckTypeHeader(p, sizeof(*p));
507        if (ret != OMX_ErrorNone)
508            return ret;
509
510        if (index < nr_ports)
511            port = ports[index];
512
513        if (!port)
514            return OMX_ErrorBadPortIndex;
515
516        memcpy(p, port->GetPortDefinition(), sizeof(*p));
517        break;
518    }
519    case OMX_IndexParamCompBufferSupplier:
520        /*
521         * Todo
522         */
523
524        ret = OMX_ErrorUnsupportedIndex;
525        break;
526    default:
527        ret = ComponentGetParameter(nParamIndex, pComponentParameterStructure);
528    } /* switch */
529
530    return ret;
531}
532
533OMX_ERRORTYPE ComponentBase::SetParameter(
534    OMX_IN  OMX_HANDLETYPE hComponent,
535    OMX_IN  OMX_INDEXTYPE nIndex,
536    OMX_IN  OMX_PTR pComponentParameterStructure)
537{
538    ComponentBase *cbase;
539
540    if (!hComponent)
541        return OMX_ErrorBadParameter;
542
543    cbase = static_cast<ComponentBase *>
544        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
545    if (!cbase)
546        return OMX_ErrorBadParameter;
547
548    return cbase->CBaseSetParameter(hComponent, nIndex,
549                                    pComponentParameterStructure);
550}
551
552OMX_ERRORTYPE ComponentBase::CBaseSetParameter(
553    OMX_IN  OMX_HANDLETYPE hComponent,
554    OMX_IN  OMX_INDEXTYPE nIndex,
555    OMX_IN  OMX_PTR pComponentParameterStructure)
556{
557    OMX_ERRORTYPE ret = OMX_ErrorNone;
558
559    if (hComponent != handle)
560        return OMX_ErrorBadParameter;
561
562    switch (nIndex) {
563    case OMX_IndexParamAudioInit:
564    case OMX_IndexParamVideoInit:
565    case OMX_IndexParamImageInit:
566    case OMX_IndexParamOtherInit:
567        /* preventing clients from setting OMX_PORT_PARAM_TYPE */
568        ret = OMX_ErrorUnsupportedIndex;
569        break;
570    case OMX_IndexParamPortDefinition: {
571        OMX_PARAM_PORTDEFINITIONTYPE *p =
572            (OMX_PARAM_PORTDEFINITIONTYPE *)pComponentParameterStructure;
573        OMX_U32 index = p->nPortIndex;
574        PortBase *port = NULL;
575
576        ret = CheckTypeHeader(p, sizeof(*p));
577        if (ret != OMX_ErrorNone)
578            return ret;
579
580        if (index < nr_ports)
581            port = ports[index];
582
583        if (!port)
584            return OMX_ErrorBadPortIndex;
585
586        if (port->IsEnabled()) {
587            if (state != OMX_StateLoaded && state != OMX_StateWaitForResources)
588                return OMX_ErrorIncorrectStateOperation;
589        }
590
591        port->SetPortDefinition(p, false);
592        break;
593    }
594    case OMX_IndexParamCompBufferSupplier:
595        /*
596         * Todo
597         */
598
599        ret = OMX_ErrorUnsupportedIndex;
600        break;
601    case OMX_IndexParamStandardComponentRole: {
602        OMX_PARAM_COMPONENTROLETYPE *p =
603            (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure;
604
605        if (state != OMX_StateLoaded && state != OMX_StateWaitForResources)
606            return OMX_ErrorIncorrectStateOperation;
607
608        ret = CheckTypeHeader(p, sizeof(*p));
609        if (ret != OMX_ErrorNone)
610            return ret;
611
612        ret = SetWorkingRole((OMX_STRING)p->cRole);
613        if (ret != OMX_ErrorNone)
614            return ret;
615
616        if (ports)
617            FreePorts();
618
619        ret = ApplyWorkingRole();
620        if (ret != OMX_ErrorNone) {
621            SetWorkingRole(NULL);
622            return ret;
623        }
624        break;
625    }
626    default:
627        ret = ComponentSetParameter(nIndex, pComponentParameterStructure);
628    } /* switch */
629
630    return ret;
631}
632
633OMX_ERRORTYPE ComponentBase::GetConfig(
634    OMX_IN  OMX_HANDLETYPE hComponent,
635    OMX_IN  OMX_INDEXTYPE nIndex,
636    OMX_INOUT OMX_PTR pComponentConfigStructure)
637{
638    ComponentBase *cbase;
639
640    if (!hComponent)
641        return OMX_ErrorBadParameter;
642
643    cbase = static_cast<ComponentBase *>
644        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
645    if (!cbase)
646        return OMX_ErrorBadParameter;
647
648    return cbase->CBaseGetConfig(hComponent, nIndex,
649                                 pComponentConfigStructure);
650}
651
652OMX_ERRORTYPE ComponentBase::CBaseGetConfig(
653    OMX_IN  OMX_HANDLETYPE hComponent,
654    OMX_IN  OMX_INDEXTYPE nIndex,
655    OMX_INOUT OMX_PTR pComponentConfigStructure)
656{
657    OMX_ERRORTYPE ret;
658
659    if (hComponent != handle)
660        return OMX_ErrorBadParameter;
661
662    switch (nIndex) {
663    default:
664        ret = ComponentGetConfig(nIndex, pComponentConfigStructure);
665    }
666
667    return ret;
668}
669
670OMX_ERRORTYPE ComponentBase::SetConfig(
671    OMX_IN  OMX_HANDLETYPE hComponent,
672    OMX_IN  OMX_INDEXTYPE nIndex,
673    OMX_IN  OMX_PTR pComponentConfigStructure)
674{
675    ComponentBase *cbase;
676
677    if (!hComponent)
678        return OMX_ErrorBadParameter;
679
680    cbase = static_cast<ComponentBase *>
681        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
682    if (!cbase)
683        return OMX_ErrorBadParameter;
684
685    return cbase->CBaseSetConfig(hComponent, nIndex,
686                                 pComponentConfigStructure);
687}
688
689OMX_ERRORTYPE ComponentBase::CBaseSetConfig(
690    OMX_IN  OMX_HANDLETYPE hComponent,
691    OMX_IN  OMX_INDEXTYPE nIndex,
692    OMX_IN  OMX_PTR pComponentConfigStructure)
693{
694    OMX_ERRORTYPE ret;
695
696    if (hComponent != handle)
697        return OMX_ErrorBadParameter;
698
699    switch (nIndex) {
700    default:
701        ret = ComponentSetConfig(nIndex, pComponentConfigStructure);
702    }
703
704    return ret;
705}
706
707OMX_ERRORTYPE ComponentBase::GetExtensionIndex(
708    OMX_IN  OMX_HANDLETYPE hComponent,
709    OMX_IN  OMX_STRING cParameterName,
710    OMX_OUT OMX_INDEXTYPE* pIndexType)
711{
712    ComponentBase *cbase;
713
714    if (!hComponent)
715        return OMX_ErrorBadParameter;
716
717    cbase = static_cast<ComponentBase *>
718        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
719    if (!cbase)
720        return OMX_ErrorBadParameter;
721
722    return cbase->CBaseGetExtensionIndex(hComponent, cParameterName,
723                                         pIndexType);
724}
725
726OMX_ERRORTYPE ComponentBase::CBaseGetExtensionIndex(
727    OMX_IN  OMX_HANDLETYPE hComponent,
728    OMX_IN  OMX_STRING cParameterName,
729    OMX_OUT OMX_INDEXTYPE* pIndexType)
730{
731    /*
732     * Todo
733     */
734
735    return OMX_ErrorNotImplemented;
736}
737
738OMX_ERRORTYPE ComponentBase::GetState(
739    OMX_IN  OMX_HANDLETYPE hComponent,
740    OMX_OUT OMX_STATETYPE* pState)
741{
742    ComponentBase *cbase;
743
744    if (!hComponent)
745        return OMX_ErrorBadParameter;
746
747    cbase = static_cast<ComponentBase *>
748        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
749    if (!cbase)
750        return OMX_ErrorBadParameter;
751
752    return cbase->CBaseGetState(hComponent, pState);
753}
754
755OMX_ERRORTYPE ComponentBase::CBaseGetState(
756    OMX_IN  OMX_HANDLETYPE hComponent,
757    OMX_OUT OMX_STATETYPE* pState)
758{
759    if (hComponent != handle)
760        return OMX_ErrorBadParameter;
761
762    *pState = state;
763    return OMX_ErrorNone;
764}
765
766OMX_ERRORTYPE ComponentBase::ComponentTunnelRequest(
767    OMX_IN  OMX_HANDLETYPE hComponent,
768    OMX_IN  OMX_U32 nPort,
769    OMX_IN  OMX_HANDLETYPE hTunneledComponent,
770    OMX_IN  OMX_U32 nTunneledPort,
771    OMX_INOUT  OMX_TUNNELSETUPTYPE* pTunnelSetup)
772{
773    ComponentBase *cbase;
774
775    if (!hComponent)
776        return OMX_ErrorBadParameter;
777
778    cbase = static_cast<ComponentBase *>
779        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
780    if (!cbase)
781        return OMX_ErrorBadParameter;
782
783    return cbase->CBaseComponentTunnelRequest(hComponent, nPort,
784                                              hTunneledComponent,
785                                              nTunneledPort, pTunnelSetup);
786}
787
788OMX_ERRORTYPE ComponentBase::CBaseComponentTunnelRequest(
789    OMX_IN  OMX_HANDLETYPE hComp,
790    OMX_IN  OMX_U32 nPort,
791    OMX_IN  OMX_HANDLETYPE hTunneledComp,
792    OMX_IN  OMX_U32 nTunneledPort,
793    OMX_INOUT  OMX_TUNNELSETUPTYPE* pTunnelSetup)
794{
795    /*
796     * Todo
797     */
798
799    return OMX_ErrorNotImplemented;
800}
801
802OMX_ERRORTYPE ComponentBase::UseBuffer(
803    OMX_IN OMX_HANDLETYPE hComponent,
804    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr,
805    OMX_IN OMX_U32 nPortIndex,
806    OMX_IN OMX_PTR pAppPrivate,
807    OMX_IN OMX_U32 nSizeBytes,
808    OMX_IN OMX_U8 *pBuffer)
809{
810    ComponentBase *cbase;
811
812    if (!hComponent)
813        return OMX_ErrorBadParameter;
814
815    cbase = static_cast<ComponentBase *>
816        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
817    if (!cbase)
818        return OMX_ErrorBadParameter;
819
820    return cbase->CBaseUseBuffer(hComponent, ppBufferHdr, nPortIndex,
821                                 pAppPrivate, nSizeBytes, pBuffer);
822}
823
824OMX_ERRORTYPE ComponentBase::CBaseUseBuffer(
825    OMX_IN OMX_HANDLETYPE hComponent,
826    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr,
827    OMX_IN OMX_U32 nPortIndex,
828    OMX_IN OMX_PTR pAppPrivate,
829    OMX_IN OMX_U32 nSizeBytes,
830    OMX_IN OMX_U8 *pBuffer)
831{
832    PortBase *port = NULL;
833    OMX_ERRORTYPE ret;
834
835    if (hComponent != handle)
836        return OMX_ErrorBadParameter;
837
838    if (!ppBufferHdr)
839        return OMX_ErrorBadParameter;
840    *ppBufferHdr = NULL;
841
842    if (!pBuffer)
843        return OMX_ErrorBadParameter;
844
845    if (ports)
846        if (nPortIndex < nr_ports)
847            port = ports[nPortIndex];
848
849    if (!port)
850        return OMX_ErrorBadParameter;
851
852    if (port->IsEnabled()) {
853        if (state != OMX_StateLoaded && state != OMX_StateWaitForResources)
854            return OMX_ErrorIncorrectStateOperation;
855    }
856
857    return port->UseBuffer(ppBufferHdr, nPortIndex, pAppPrivate, nSizeBytes,
858                           pBuffer);
859}
860
861OMX_ERRORTYPE ComponentBase::AllocateBuffer(
862    OMX_IN OMX_HANDLETYPE hComponent,
863    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer,
864    OMX_IN OMX_U32 nPortIndex,
865    OMX_IN OMX_PTR pAppPrivate,
866    OMX_IN OMX_U32 nSizeBytes)
867{
868    ComponentBase *cbase;
869
870    if (!hComponent)
871        return OMX_ErrorBadParameter;
872
873    cbase = static_cast<ComponentBase *>
874        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
875    if (!cbase)
876        return OMX_ErrorBadParameter;
877
878    return cbase->CBaseAllocateBuffer(hComponent, ppBuffer, nPortIndex,
879                                      pAppPrivate, nSizeBytes);
880}
881
882OMX_ERRORTYPE ComponentBase::CBaseAllocateBuffer(
883    OMX_IN OMX_HANDLETYPE hComponent,
884    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer,
885    OMX_IN OMX_U32 nPortIndex,
886    OMX_IN OMX_PTR pAppPrivate,
887    OMX_IN OMX_U32 nSizeBytes)
888{
889    PortBase *port = NULL;
890    OMX_ERRORTYPE ret;
891
892    if (hComponent != handle)
893        return OMX_ErrorBadParameter;
894
895    if (!ppBuffer)
896        return OMX_ErrorBadParameter;
897    *ppBuffer = NULL;
898
899    if (ports)
900        if (nPortIndex < nr_ports)
901            port = ports[nPortIndex];
902
903    if (!port)
904        return OMX_ErrorBadParameter;
905
906    if (port->IsEnabled()) {
907        if (state != OMX_StateLoaded && state != OMX_StateWaitForResources)
908            return OMX_ErrorIncorrectStateOperation;
909    }
910
911    return port->AllocateBuffer(ppBuffer, nPortIndex, pAppPrivate, nSizeBytes);
912}
913
914OMX_ERRORTYPE ComponentBase::FreeBuffer(
915    OMX_IN  OMX_HANDLETYPE hComponent,
916    OMX_IN  OMX_U32 nPortIndex,
917    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
918{
919    ComponentBase *cbase;
920
921    if (!hComponent)
922        return OMX_ErrorBadParameter;
923
924    cbase = static_cast<ComponentBase *>
925        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
926    if (!cbase)
927        return OMX_ErrorBadParameter;
928
929    return cbase->CBaseFreeBuffer(hComponent, nPortIndex, pBuffer);
930}
931
932OMX_ERRORTYPE ComponentBase::CBaseFreeBuffer(
933    OMX_IN  OMX_HANDLETYPE hComponent,
934    OMX_IN  OMX_U32 nPortIndex,
935    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
936{
937    PortBase *port = NULL;
938    OMX_ERRORTYPE ret;
939
940    if (hComponent != handle)
941        return OMX_ErrorBadParameter;
942
943    if (!pBuffer)
944        return OMX_ErrorBadParameter;
945
946    if (ports)
947        if (nPortIndex < nr_ports)
948            port = ports[nPortIndex];
949
950    if (!port)
951        return OMX_ErrorBadParameter;
952
953    return port->FreeBuffer(nPortIndex, pBuffer);
954}
955
956OMX_ERRORTYPE ComponentBase::EmptyThisBuffer(
957    OMX_IN  OMX_HANDLETYPE hComponent,
958    OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer)
959{
960    ComponentBase *cbase;
961
962    if (!hComponent)
963        return OMX_ErrorBadParameter;
964
965    cbase = static_cast<ComponentBase *>
966        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
967    if (!cbase)
968        return OMX_ErrorBadParameter;
969
970    return cbase->CBaseEmptyThisBuffer(hComponent, pBuffer);
971}
972
973OMX_ERRORTYPE ComponentBase::CBaseEmptyThisBuffer(
974    OMX_IN  OMX_HANDLETYPE hComponent,
975    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
976{
977    PortBase *port = NULL;
978    OMX_U32 port_index;
979    OMX_ERRORTYPE ret;
980
981    if ((hComponent != handle) || !pBuffer)
982        return OMX_ErrorBadParameter;
983
984    ret = CheckTypeHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE));
985    if (ret != OMX_ErrorNone)
986        return ret;
987
988    port_index = pBuffer->nInputPortIndex;
989    if (port_index == (OMX_U32)-1)
990        return OMX_ErrorBadParameter;
991
992    if (ports)
993        if (port_index < nr_ports)
994            port = ports[port_index];
995
996    if (!port)
997        return OMX_ErrorBadParameter;
998
999    if (pBuffer->pInputPortPrivate != port)
1000        return OMX_ErrorBadParameter;
1001
1002    if (port->IsEnabled()) {
1003        if (state != OMX_StateIdle && state != OMX_StateExecuting &&
1004            state != OMX_StatePause)
1005            return OMX_ErrorIncorrectStateOperation;
1006    }
1007
1008    if (!pBuffer->hMarkTargetComponent) {
1009        OMX_MARKTYPE *mark;
1010
1011        mark = port->PopMark();
1012        if (mark) {
1013            pBuffer->hMarkTargetComponent = mark->hMarkTargetComponent;
1014            pBuffer->pMarkData = mark->pMarkData;
1015            free(mark);
1016        }
1017    }
1018
1019    ret = port->PushThisBuffer(pBuffer);
1020    if (ret == OMX_ErrorNone)
1021        bufferwork->ScheduleWork(this);
1022
1023    return ret;
1024}
1025
1026OMX_ERRORTYPE ComponentBase::FillThisBuffer(
1027    OMX_IN  OMX_HANDLETYPE hComponent,
1028    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
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->CBaseFillThisBuffer(hComponent, pBuffer);
1041}
1042
1043OMX_ERRORTYPE ComponentBase::CBaseFillThisBuffer(
1044    OMX_IN  OMX_HANDLETYPE hComponent,
1045    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
1046{
1047    PortBase *port = NULL;
1048    OMX_U32 port_index;
1049    OMX_ERRORTYPE ret;
1050
1051    if ((hComponent != handle) || !pBuffer)
1052        return OMX_ErrorBadParameter;
1053
1054    ret = CheckTypeHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE));
1055    if (ret != OMX_ErrorNone)
1056        return ret;
1057
1058    port_index = pBuffer->nOutputPortIndex;
1059    if (port_index == (OMX_U32)-1)
1060        return OMX_ErrorBadParameter;
1061
1062    if (ports)
1063        if (port_index < nr_ports)
1064            port = ports[port_index];
1065
1066    if (!port)
1067        return OMX_ErrorBadParameter;
1068
1069    if (pBuffer->pOutputPortPrivate != port)
1070        return OMX_ErrorBadParameter;
1071
1072    if (port->IsEnabled()) {
1073        if (state != OMX_StateIdle && state != OMX_StateExecuting &&
1074            state != OMX_StatePause)
1075            return OMX_ErrorIncorrectStateOperation;
1076    }
1077
1078    ret = port->PushThisBuffer(pBuffer);
1079    if (ret == OMX_ErrorNone)
1080        bufferwork->ScheduleWork(this);
1081
1082    return ret;
1083}
1084
1085OMX_ERRORTYPE ComponentBase::SetCallbacks(
1086    OMX_IN  OMX_HANDLETYPE hComponent,
1087    OMX_IN  OMX_CALLBACKTYPE* pCallbacks,
1088    OMX_IN  OMX_PTR pAppData)
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->CBaseSetCallbacks(hComponent, pCallbacks, pAppData);
1101}
1102
1103OMX_ERRORTYPE ComponentBase::CBaseSetCallbacks(
1104    OMX_IN  OMX_HANDLETYPE hComponent,
1105    OMX_IN  OMX_CALLBACKTYPE *pCallbacks,
1106    OMX_IN  OMX_PTR pAppData)
1107{
1108    if (hComponent != handle)
1109        return OMX_ErrorBadParameter;
1110
1111    appdata = pAppData;
1112    callbacks = pCallbacks;
1113
1114    return OMX_ErrorNone;
1115}
1116
1117OMX_ERRORTYPE ComponentBase::ComponentDeInit(
1118    OMX_IN  OMX_HANDLETYPE hComponent)
1119{
1120    ComponentBase *cbase;
1121
1122    if (!hComponent)
1123        return OMX_ErrorBadParameter;
1124
1125    cbase = static_cast<ComponentBase *>
1126        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
1127    if (!cbase)
1128        return OMX_ErrorBadParameter;
1129
1130    return cbase->CBaseComponentDeInit(hComponent);
1131}
1132
1133OMX_ERRORTYPE ComponentBase::CBaseComponentDeInit(
1134    OMX_IN  OMX_HANDLETYPE hComponent)
1135{
1136    /*
1137     * Todo
1138     */
1139
1140    return OMX_ErrorNotImplemented;
1141}
1142
1143OMX_ERRORTYPE ComponentBase::UseEGLImage(
1144    OMX_IN OMX_HANDLETYPE hComponent,
1145    OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
1146    OMX_IN OMX_U32 nPortIndex,
1147    OMX_IN OMX_PTR pAppPrivate,
1148    OMX_IN void* eglImage)
1149{
1150    ComponentBase *cbase;
1151
1152    if (!hComponent)
1153        return OMX_ErrorBadParameter;
1154
1155    cbase = static_cast<ComponentBase *>
1156        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
1157    if (!cbase)
1158        return OMX_ErrorBadParameter;
1159
1160    return cbase->CBaseUseEGLImage(hComponent, ppBufferHdr, nPortIndex,
1161                                   pAppPrivate, eglImage);
1162}
1163
1164OMX_ERRORTYPE ComponentBase::CBaseUseEGLImage(
1165    OMX_IN OMX_HANDLETYPE hComponent,
1166    OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
1167    OMX_IN OMX_U32 nPortIndex,
1168    OMX_IN OMX_PTR pAppPrivate,
1169    OMX_IN void* eglImage)
1170{
1171    /*
1172     * Todo
1173     */
1174
1175    return OMX_ErrorNotImplemented;
1176}
1177
1178OMX_ERRORTYPE ComponentBase::ComponentRoleEnum(
1179    OMX_IN OMX_HANDLETYPE hComponent,
1180    OMX_OUT OMX_U8 *cRole,
1181    OMX_IN OMX_U32 nIndex)
1182{
1183    ComponentBase *cbase;
1184
1185    if (!hComponent)
1186        return OMX_ErrorBadParameter;
1187
1188    cbase = static_cast<ComponentBase *>
1189        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
1190    if (!cbase)
1191        return OMX_ErrorBadParameter;
1192
1193    return cbase->CBaseComponentRoleEnum(hComponent, cRole, nIndex);
1194}
1195
1196OMX_ERRORTYPE ComponentBase::CBaseComponentRoleEnum(
1197    OMX_IN OMX_HANDLETYPE hComponent,
1198    OMX_OUT OMX_U8 *cRole,
1199    OMX_IN OMX_U32 nIndex)
1200{
1201    if (hComponent != (OMX_HANDLETYPE *)this->handle)
1202        return OMX_ErrorBadParameter;
1203
1204    if (nIndex > nr_roles)
1205        return OMX_ErrorBadParameter;
1206
1207    strncpy((char *)cRole, (const char *)roles[nIndex],
1208            OMX_MAX_STRINGNAME_SIZE);
1209    return OMX_ErrorNone;
1210}
1211
1212/* implement CmdHandlerInterface */
1213void ComponentBase::CmdHandler(struct cmd_s *cmd)
1214{
1215    switch (cmd->cmd) {
1216    case OMX_CommandStateSet: {
1217        OMX_STATETYPE transition = (OMX_STATETYPE)cmd->param1;
1218
1219        TransState(transition);
1220        break;
1221    }
1222    case OMX_CommandFlush: {
1223        OMX_U32 port_index = cmd->param1;
1224
1225        FlushPort(port_index, 1);
1226        break;
1227    }
1228    case OMX_CommandPortDisable: {
1229        OMX_U32 port_index = cmd->param1;
1230
1231        TransStatePort(port_index, PortBase::OMX_PortDisabled);
1232        break;
1233    }
1234    case OMX_CommandPortEnable: {
1235        OMX_U32 port_index = cmd->param1;
1236
1237        TransStatePort(port_index, PortBase::OMX_PortEnabled);
1238        break;
1239    }
1240    case OMX_CommandMarkBuffer:
1241        OMX_U32 port_index = (OMX_U32)cmd->param1;
1242        OMX_MARKTYPE *mark = (OMX_MARKTYPE *)cmd->cmddata;
1243
1244        PushThisMark(port_index, mark);
1245        break;
1246    } /* switch */
1247}
1248
1249/*
1250 * SendCommand:OMX_CommandStateSet
1251 * called in CmdHandler or called in other parts of component for reporting
1252 * internal error (OMX_StateInvalid).
1253 */
1254/*
1255 * Todo
1256 *   Resource Management (OMX_StateWaitForResources)
1257 *   for now, we never notify OMX_ErrorInsufficientResources,
1258 *   so IL client doesn't try to set component' state OMX_StateWaitForResources
1259 */
1260static const char *state_name[OMX_StateWaitForResources + 1] = {
1261    "OMX_StateInvalid",
1262    "OMX_StateLoaded",
1263    "OMX_StateIdle",
1264    "OMX_StateExecuting",
1265    "OMX_StatePause",
1266    "OMX_StateWaitForResources",
1267};
1268
1269static inline const char *GetStateName(OMX_STATETYPE state)
1270{
1271    if (state > OMX_StateWaitForResources)
1272        return "UnKnown";
1273
1274    return state_name[state];
1275}
1276
1277void ComponentBase::TransState(OMX_STATETYPE transition)
1278{
1279    OMX_STATETYPE current = this->state;
1280    OMX_EVENTTYPE event;
1281    OMX_U32 data1, data2;
1282    OMX_ERRORTYPE ret;
1283
1284    LOGD("current state = %s, transition state = %s\n",
1285         GetStateName(current), GetStateName(transition));
1286
1287    /* same state */
1288    if (current == transition) {
1289        ret = OMX_ErrorSameState;
1290        goto notify_event;
1291    }
1292
1293    /* invalid state */
1294    if (current == OMX_StateInvalid) {
1295        ret = OMX_ErrorInvalidState;
1296        goto notify_event;
1297    }
1298
1299    if (transition == OMX_StateLoaded)
1300        ret = TransStateToLoaded(current);
1301    else if (transition == OMX_StateIdle)
1302        ret = TransStateToIdle(current);
1303    else if (transition == OMX_StateExecuting)
1304        ret = TransStateToExecuting(current);
1305    else if (transition == OMX_StatePause)
1306        ret = TransStateToPause(current);
1307    else if (transition == OMX_StateInvalid)
1308        ret = TransStateToInvalid(current);
1309    else if (transition == OMX_StateWaitForResources)
1310        ret = TransStateToWaitForResources(current);
1311    else
1312        ret = OMX_ErrorIncorrectStateTransition;
1313
1314notify_event:
1315    if (ret == OMX_ErrorNone) {
1316        event = OMX_EventCmdComplete;
1317        data1 = OMX_CommandStateSet;
1318        data2 = transition;
1319
1320        state = transition;
1321        LOGD("transition from %s to %s completed\n",
1322             GetStateName(current), GetStateName(transition));
1323    }
1324    else {
1325        event = OMX_EventError;
1326        data1 = ret;
1327        data2 = 0;
1328
1329        if (transition == OMX_StateInvalid || ret == OMX_ErrorInvalidState) {
1330            state = OMX_StateInvalid;
1331            LOGD("failed transition from %s to %s, current state is %s\n",
1332                 GetStateName(current), GetStateName(transition),
1333                 GetStateName(state));
1334        }
1335    }
1336
1337    callbacks->EventHandler(handle, appdata, event, data1, data2, NULL);
1338
1339    /* WaitForResources workaround */
1340    if (ret == OMX_ErrorNone && transition == OMX_StateWaitForResources)
1341        callbacks->EventHandler(handle, appdata,
1342                                OMX_EventResourcesAcquired, 0, 0, NULL);
1343}
1344
1345inline OMX_ERRORTYPE ComponentBase::TransStateToLoaded(OMX_STATETYPE current)
1346{
1347    OMX_ERRORTYPE ret;
1348
1349    if (current == OMX_StateIdle) {
1350        OMX_U32 i;
1351
1352        for (i = 0; i < nr_ports; i++)
1353            ports[i]->WaitPortBufferCompletion();
1354
1355        ret = ProcessorDeinit();
1356        if (ret != OMX_ErrorNone) {
1357            LOGE("failed to ProcessorDeinit() (ret = 0x%08x)\n", ret);
1358            ret = OMX_ErrorInvalidState;
1359            goto out;
1360        }
1361    }
1362    else if (current == OMX_StateWaitForResources) {
1363        LOGE("state transition's requested from WaitForResources to "
1364             "Loaded\n");
1365
1366        /*
1367         * from WaitForResources to Loaded considered from Loaded to Loaded.
1368         * do nothing
1369         */
1370
1371        ret = OMX_ErrorNone;
1372    }
1373    else
1374        ret = OMX_ErrorIncorrectStateTransition;
1375
1376out:
1377    return ret;
1378}
1379
1380inline OMX_ERRORTYPE ComponentBase::TransStateToIdle(OMX_STATETYPE current)
1381{
1382    OMX_ERRORTYPE ret;
1383
1384    if (current == OMX_StateLoaded) {
1385        OMX_U32 i;
1386
1387        ret = ProcessorInit();
1388        if (ret != OMX_ErrorNone) {
1389            LOGE("failed to ProcessorInit() (ret = 0x%08x)\n", ret);
1390            ret = OMX_ErrorInvalidState;
1391            goto out;
1392        }
1393
1394        for (i = 0; i < nr_ports; i++) {
1395            if (ports[i]->IsEnabled())
1396                ports[i]->WaitPortBufferCompletion();
1397        }
1398    }
1399    else if (current == OMX_StateExecuting) {
1400        FlushPort(OMX_ALL, 0);
1401
1402        bufferwork->StopWork();
1403
1404        ret = ProcessorStop();
1405        if (ret != OMX_ErrorNone) {
1406            LOGE("failed to ProcessorStop() (ret = 0x%08x)\n", ret);
1407            ret = OMX_ErrorInvalidState;
1408            goto out;
1409        }
1410    }
1411    else if (current == OMX_StatePause) {
1412        FlushPort(OMX_ALL, 0);
1413
1414        bufferwork->CancelScheduledWork(this);
1415        bufferwork->StopWork();
1416
1417        ret = ProcessorStop();
1418        if (ret != OMX_ErrorNone) {
1419            LOGE("failed to ProcessorStop() (ret = 0x%08x)\n", ret);
1420            ret = OMX_ErrorInvalidState;
1421            goto out;
1422        }
1423    }
1424    else if (current == OMX_StateWaitForResources) {
1425        LOGE("state transition's requested from WaitForResources to Idle\n");
1426
1427        /* same as Loaded to Idle BUT DO NOTHING for now */
1428
1429        ret = OMX_ErrorNone;
1430    }
1431    else
1432        ret = OMX_ErrorIncorrectStateTransition;
1433
1434out:
1435    return ret;
1436}
1437
1438inline OMX_ERRORTYPE
1439ComponentBase::TransStateToExecuting(OMX_STATETYPE current)
1440{
1441    OMX_ERRORTYPE ret;
1442
1443    if (current == OMX_StateIdle) {
1444        pthread_mutex_lock(&executing_lock);
1445        executing = true;
1446        pthread_mutex_unlock(&executing_lock);
1447
1448        bufferwork->StartWork();
1449
1450        ret = ProcessorStart();
1451        if (ret != OMX_ErrorNone) {
1452            LOGE("failed to ProcessorStart() (ret = 0x%08x)\n", ret);
1453            ret = OMX_ErrorInvalidState;
1454            goto out;
1455        }
1456    }
1457    else if (current == OMX_StatePause) {
1458        pthread_mutex_lock(&executing_lock);
1459        executing = true;
1460        pthread_cond_signal(&executing_wait);
1461        pthread_mutex_unlock(&executing_lock);
1462
1463        ret = ProcessorResume();
1464        if (ret != OMX_ErrorNone) {
1465            LOGE("failed to ProcessorStart() (ret = 0x%08x)\n", ret);
1466            ret = OMX_ErrorInvalidState;
1467            goto out;
1468        }
1469    }
1470    else
1471        ret = OMX_ErrorIncorrectStateTransition;
1472
1473out:
1474    return ret;
1475}
1476
1477inline OMX_ERRORTYPE ComponentBase::TransStateToPause(OMX_STATETYPE current)
1478{
1479    OMX_ERRORTYPE ret;
1480
1481    if (current == OMX_StateIdle) {
1482        /* turn off executing flag */
1483        pthread_mutex_lock(&executing_lock);
1484        executing = false;
1485        pthread_mutex_unlock(&executing_lock);
1486
1487        bufferwork->StartWork();
1488
1489        ret = ProcessorStart();
1490        if (ret != OMX_ErrorNone) {
1491            LOGE("failed to ProcessorPause() (ret = 0x%08x)\n", ret);
1492            ret = OMX_ErrorInvalidState;
1493            goto out;
1494        }
1495    }
1496    else if (current == OMX_StateExecuting) {
1497        pthread_mutex_lock(&executing_lock);
1498        executing = false;
1499        pthread_mutex_unlock(&executing_lock);
1500
1501        ret = ProcessorPause();
1502        if (ret != OMX_ErrorNone) {
1503            LOGE("failed to ProcessorPause() (ret = 0x%08x)\n", ret);
1504            ret = OMX_ErrorInvalidState;
1505            goto out;
1506        }
1507    }
1508    else
1509        ret = OMX_ErrorIncorrectStateTransition;
1510
1511out:
1512    return ret;
1513}
1514
1515inline OMX_ERRORTYPE ComponentBase::TransStateToInvalid(OMX_STATETYPE current)
1516{
1517    OMX_ERRORTYPE ret = OMX_ErrorInvalidState;
1518
1519    /*
1520     * Todo
1521     *   graceful escape
1522     */
1523
1524    return ret;
1525}
1526
1527inline OMX_ERRORTYPE
1528ComponentBase::TransStateToWaitForResources(OMX_STATETYPE current)
1529{
1530    OMX_ERRORTYPE ret;
1531
1532    if (current == OMX_StateLoaded) {
1533        LOGE("state transition's requested from Loaded to WaitForResources\n");
1534        ret = OMX_ErrorNone;
1535    }
1536    else
1537        ret = OMX_ErrorIncorrectStateTransition;
1538
1539    return ret;
1540}
1541
1542/* mark buffer */
1543void ComponentBase::PushThisMark(OMX_U32 port_index, OMX_MARKTYPE *mark)
1544{
1545    PortBase *port = NULL;
1546    OMX_EVENTTYPE event;
1547    OMX_U32 data1, data2;
1548    OMX_ERRORTYPE ret;
1549
1550    if (ports)
1551        if (port_index < nr_ports)
1552            port = ports[port_index];
1553
1554    if (!port) {
1555        ret = OMX_ErrorBadPortIndex;
1556        goto notify_event;
1557    }
1558
1559    ret = port->PushMark(mark);
1560    if (ret != OMX_ErrorNone) {
1561        /* don't report OMX_ErrorInsufficientResources */
1562        ret = OMX_ErrorUndefined;
1563        goto notify_event;
1564    }
1565
1566notify_event:
1567    if (ret == OMX_ErrorNone) {
1568        event = OMX_EventCmdComplete;
1569        data1 = OMX_CommandMarkBuffer;
1570        data2 = port_index;
1571    }
1572    else {
1573        event = OMX_EventError;
1574        data1 = ret;
1575        data2 = 0;
1576    }
1577
1578    callbacks->EventHandler(handle, appdata, event, data1, data2, NULL);
1579}
1580
1581void ComponentBase::FlushPort(OMX_U32 port_index, bool notify)
1582{
1583    OMX_U32 i, from_index, to_index;
1584
1585    if ((port_index != OMX_ALL) && (port_index > nr_ports-1))
1586        return;
1587
1588    if (port_index == OMX_ALL) {
1589        from_index = 0;
1590        to_index = nr_ports - 1;
1591    }
1592    else {
1593        from_index = port_index;
1594        to_index = port_index;
1595    }
1596
1597    pthread_mutex_lock(&ports_block);
1598    for (i = from_index; i <= to_index; i++) {
1599        ports[i]->FlushPort();
1600        if (notify)
1601            callbacks->EventHandler(handle, appdata, OMX_EventCmdComplete,
1602                                    OMX_CommandFlush, i, NULL);
1603    }
1604    pthread_mutex_unlock(&ports_block);
1605}
1606
1607void ComponentBase::TransStatePort(OMX_U32 port_index, OMX_U8 state)
1608{
1609    OMX_EVENTTYPE event;
1610    OMX_U32 data1, data2;
1611    OMX_U32 i, from_index, to_index;
1612    OMX_ERRORTYPE ret;
1613
1614    if ((port_index != OMX_ALL) && (port_index > nr_ports-1))
1615        return;
1616
1617    if (port_index == OMX_ALL) {
1618        from_index = 0;
1619        to_index = nr_ports - 1;
1620    }
1621    else {
1622        from_index = port_index;
1623        to_index = port_index;
1624    }
1625
1626    pthread_mutex_lock(&ports_block);
1627    for (i = from_index; i <= to_index; i++) {
1628        ret = ports[i]->TransState(state);
1629        if (ret == OMX_ErrorNone) {
1630            event = OMX_EventCmdComplete;
1631            if (state == PortBase::OMX_PortEnabled)
1632                data1 = OMX_CommandPortEnable;
1633            else
1634                data1 = OMX_CommandPortDisable;
1635            data2 = i;
1636        }
1637        else {
1638            event = OMX_EventError;
1639            data1 = ret;
1640            data2 = 0;
1641        }
1642        callbacks->EventHandler(handle, appdata, OMX_EventCmdComplete,
1643                                OMX_CommandPortDisable, data2, NULL);
1644    }
1645    pthread_mutex_unlock(&ports_block);
1646}
1647
1648/* set working role */
1649OMX_ERRORTYPE ComponentBase::SetWorkingRole(const OMX_STRING role)
1650{
1651    OMX_U32 i;
1652
1653    if (state != OMX_StateUnloaded && state != OMX_StateLoaded)
1654        return OMX_ErrorIncorrectStateOperation;
1655
1656    if (!role) {
1657        working_role = NULL;
1658        return OMX_ErrorNone;
1659    }
1660
1661    for (i = 0; i < nr_roles; i++) {
1662        if (!strcmp((char *)&roles[i][0], role)) {
1663            working_role = (OMX_STRING)&roles[i][0];
1664            return OMX_ErrorNone;
1665        }
1666    }
1667
1668    LOGE("cannot find %s role in %s\n", role, name);
1669    return OMX_ErrorBadParameter;
1670}
1671
1672/* apply a working role for a component having multiple roles */
1673OMX_ERRORTYPE ComponentBase::ApplyWorkingRole(void)
1674{
1675    OMX_U32 i;
1676    OMX_ERRORTYPE ret;
1677
1678    if (state != OMX_StateUnloaded && state != OMX_StateLoaded)
1679        return OMX_ErrorIncorrectStateOperation;
1680
1681    if (!working_role)
1682        return OMX_ErrorBadParameter;
1683
1684    if (!callbacks || !appdata)
1685        return OMX_ErrorBadParameter;
1686
1687    ret = AllocatePorts();
1688    if (ret != OMX_ErrorNone) {
1689        LOGE("failed to AllocatePorts() (ret = 0x%08x)\n", ret);
1690        return ret;
1691    }
1692
1693    /* now we can access ports */
1694    for (i = 0; i < nr_ports; i++) {
1695        ports[i]->SetOwner(handle);
1696        ports[i]->SetCallbacks(handle, callbacks, appdata);
1697    }
1698
1699    return OMX_ErrorNone;
1700}
1701
1702OMX_ERRORTYPE ComponentBase::AllocatePorts(void)
1703{
1704    OMX_ERRORTYPE ret;
1705
1706    if (ports)
1707        return OMX_ErrorBadParameter;
1708
1709    ret = ComponentAllocatePorts();
1710    if (ret != OMX_ErrorNone) {
1711        LOGE("failed to %s::ComponentAllocatePorts(), ret = 0x%08x\n",
1712             name, ret);
1713        return ret;
1714    }
1715
1716    return OMX_ErrorNone;
1717}
1718
1719/* called int FreeHandle() */
1720OMX_ERRORTYPE ComponentBase::FreePorts(void)
1721{
1722    if (ports) {
1723        OMX_U32 i, this_nr_ports = this->nr_ports;
1724
1725        for (i = 0; i < this_nr_ports; i++) {
1726            if (ports[i]) {
1727                OMX_MARKTYPE *mark;
1728                /* it should be empty before this */
1729                while ((mark = ports[i]->PopMark()))
1730                    free(mark);
1731
1732                delete ports[i];
1733                ports[i] = NULL;
1734            }
1735        }
1736        delete []ports;
1737        ports = NULL;
1738    }
1739
1740    return OMX_ErrorNone;
1741}
1742
1743/* buffer processing */
1744/* implement WorkableInterface */
1745void ComponentBase::Work(void)
1746{
1747    OMX_BUFFERHEADERTYPE *buffers[nr_ports];
1748    bool retain[nr_ports];
1749    OMX_U32 i;
1750    bool avail = false;
1751
1752    pthread_mutex_lock(&executing_lock);
1753    if (!executing)
1754        pthread_cond_wait(&executing_wait, &executing_lock);
1755    pthread_mutex_unlock(&executing_lock);
1756
1757    pthread_mutex_lock(&ports_block);
1758
1759    avail = IsAllBufferAvailable();
1760    if (avail) {
1761        for (i = 0; i < nr_ports; i++) {
1762            buffers[i] = ports[i]->PopBuffer();
1763            retain[i] = false;
1764        }
1765
1766        ProcessorProcess(buffers, &retain[0], nr_ports);
1767        PostProcessBuffer(buffers, &retain[0], nr_ports);
1768
1769        for (i = 0; i < nr_ports; i++) {
1770            if (retain[i])
1771                ports[i]->RetainThisBuffer(buffers[i]);
1772            else
1773                ports[i]->ReturnThisBuffer(buffers[i]);
1774        }
1775    }
1776    ScheduleIfAllBufferAvailable();
1777
1778    pthread_mutex_unlock(&ports_block);
1779}
1780
1781bool ComponentBase::IsAllBufferAvailable(void)
1782{
1783    OMX_U32 i;
1784    OMX_U32 nr_avail = 0;
1785
1786    for (i = 0; i < nr_ports; i++) {
1787        OMX_U32 length = 0;
1788
1789        if (ports[i]->IsEnabled())
1790            length = ports[i]->BufferQueueLength();
1791
1792        if (length)
1793            nr_avail++;
1794    }
1795
1796    if (nr_avail == nr_ports)
1797        return true;
1798    else
1799        return false;
1800}
1801
1802void ComponentBase::ScheduleIfAllBufferAvailable(void)
1803{
1804    bool avail;
1805
1806    avail = IsAllBufferAvailable();
1807    if (avail)
1808        bufferwork->ScheduleWork(this);
1809}
1810
1811void ComponentBase::PostProcessBuffer(OMX_BUFFERHEADERTYPE **buffers,
1812                                      bool *retain,
1813                                      OMX_U32 nr_buffers)
1814{
1815    OMX_U32 i;
1816
1817    for (i = 0; i < nr_ports; i++) {
1818        OMX_MARKTYPE *mark;
1819
1820        if (ports[i]->GetPortDirection() == OMX_DirInput) {
1821            bool is_sink_component = true;
1822            OMX_U32 j;
1823
1824            if (buffers[i]->hMarkTargetComponent) {
1825                if (buffers[i]->hMarkTargetComponent == handle) {
1826                    callbacks->EventHandler(handle, appdata, OMX_EventMark,
1827                                            0, 0, buffers[i]->pMarkData);
1828                    buffers[i]->hMarkTargetComponent = NULL;
1829                    buffers[i]->pMarkData = NULL;
1830                }
1831            }
1832
1833            for (j = 0; j < nr_ports; j++) {
1834                if (j == i)
1835                    continue;
1836
1837                if (ports[j]->GetPortDirection() == OMX_DirOutput) {
1838                    if (buffers[i]->nFlags & OMX_BUFFERFLAG_EOS) {
1839                        buffers[j]->nFlags |= OMX_BUFFERFLAG_EOS;
1840                        buffers[i]->nFlags &= ~OMX_BUFFERFLAG_EOS;
1841                        retain[i] = false;
1842                        retain[j] = false;
1843                    }
1844
1845                    if (!buffers[j]->hMarkTargetComponent) {
1846                        mark = ports[j]->PopMark();
1847                        if (mark) {
1848                            buffers[j]->hMarkTargetComponent =
1849                                mark->hMarkTargetComponent;
1850                            buffers[j]->pMarkData = mark->pMarkData;
1851                            free(mark);
1852                            mark = NULL;
1853                        }
1854
1855                        if (buffers[i]->hMarkTargetComponent) {
1856                            if (buffers[j]->hMarkTargetComponent) {
1857                                mark = (OMX_MARKTYPE *)
1858                                    malloc(sizeof(*mark));
1859                                if (mark) {
1860                                    mark->hMarkTargetComponent =
1861                                        buffers[i]->hMarkTargetComponent;
1862                                    mark->pMarkData = buffers[i]->pMarkData;
1863                                    ports[j]->PushMark(mark);
1864                                    mark = NULL;
1865                                    buffers[i]->hMarkTargetComponent = NULL;
1866                                    buffers[i]->pMarkData = NULL;
1867                                }
1868                            }
1869                            else {
1870                                buffers[j]->hMarkTargetComponent =
1871                                    buffers[i]->hMarkTargetComponent;
1872                                buffers[j]->pMarkData = buffers[i]->pMarkData;
1873                                buffers[i]->hMarkTargetComponent = NULL;
1874                                buffers[i]->pMarkData = NULL;
1875                            }
1876                        }
1877                    }
1878                    else {
1879                        if (buffers[i]->hMarkTargetComponent) {
1880                            mark = (OMX_MARKTYPE *)malloc(sizeof(*mark));
1881                            if (mark) {
1882                                mark->hMarkTargetComponent =
1883                                    buffers[i]->hMarkTargetComponent;
1884                                mark->pMarkData = buffers[i]->pMarkData;
1885                                ports[j]->PushMark(mark);
1886                                mark = NULL;
1887                                buffers[i]->hMarkTargetComponent = NULL;
1888                                buffers[i]->pMarkData = NULL;
1889                            }
1890                        }
1891                    }
1892                    is_sink_component = false;
1893                }
1894            }
1895
1896            if (is_sink_component) {
1897                if (buffers[i]->nFlags & OMX_BUFFERFLAG_EOS) {
1898                    callbacks->EventHandler(handle, appdata,
1899                                            OMX_EventBufferFlag,
1900                                            i, buffers[i]->nFlags, NULL);
1901                    retain[i] = false;
1902                }
1903            }
1904        }
1905        else if (ports[i]->GetPortDirection() == OMX_DirOutput) {
1906            bool is_source_component = true;
1907            OMX_U32 j;
1908
1909            if (buffers[i]->nFlags & OMX_BUFFERFLAG_EOS) {
1910                callbacks->EventHandler(handle, appdata,
1911                                        OMX_EventBufferFlag,
1912                                        i, buffers[i]->nFlags, NULL);
1913                retain[i] = false;
1914            }
1915
1916            for (j = 0; j < nr_ports; j++) {
1917                if (j == i)
1918                    continue;
1919
1920                if (ports[j]->GetPortDirection() == OMX_DirInput)
1921                    is_source_component = false;
1922            }
1923
1924            if (is_source_component) {
1925                if (!retain[i]) {
1926                    mark = ports[i]->PopMark();
1927                    if (mark) {
1928                        buffers[i]->hMarkTargetComponent =
1929                            mark->hMarkTargetComponent;
1930                        buffers[i]->pMarkData = mark->pMarkData;
1931                        free(mark);
1932                        mark = NULL;
1933
1934                        if (buffers[i]->hMarkTargetComponent == handle) {
1935                            callbacks->EventHandler(handle, appdata,
1936                                                    OMX_EventMark, 0, 0,
1937                                                    buffers[i]->pMarkData);
1938                            buffers[i]->hMarkTargetComponent = NULL;
1939                            buffers[i]->pMarkData = NULL;
1940                        }
1941                    }
1942                }
1943            }
1944        }
1945        else {
1946            LOGE("%s(): fatal error unknown port direction (0x%08x)\n",
1947                 __func__, ports[i]->GetPortDirection());
1948        }
1949    }
1950}
1951
1952/* processor default callbacks */
1953OMX_ERRORTYPE ComponentBase::ProcessorInit(void)
1954{
1955    return OMX_ErrorNone;
1956}
1957OMX_ERRORTYPE ComponentBase::ProcessorDeinit(void)
1958{
1959    return OMX_ErrorNone;
1960}
1961
1962OMX_ERRORTYPE ComponentBase::ProcessorStart(void)
1963{
1964    return OMX_ErrorNone;
1965}
1966
1967OMX_ERRORTYPE ComponentBase::ProcessorStop(void)
1968{
1969    return OMX_ErrorNone;
1970}
1971
1972OMX_ERRORTYPE ComponentBase::ProcessorPause(void)
1973{
1974    return OMX_ErrorNone;
1975}
1976
1977OMX_ERRORTYPE ComponentBase::ProcessorResume(void)
1978{
1979    return OMX_ErrorNone;
1980}
1981
1982/* end of processor callbacks */
1983
1984/* helper for derived class */
1985const OMX_STRING ComponentBase::GetWorkingRole(void)
1986{
1987    return &working_role[0];
1988}
1989
1990const OMX_COMPONENTTYPE *ComponentBase::GetComponentHandle(void)
1991{
1992    return handle;
1993}
1994
1995/* end of component methods & helpers */
1996
1997/*
1998 * omx header manipuation
1999 */
2000void ComponentBase::SetTypeHeader(OMX_PTR type, OMX_U32 size)
2001{
2002    OMX_U32 *nsize;
2003    OMX_VERSIONTYPE *nversion;
2004
2005    if (!type)
2006        return;
2007
2008    nsize = (OMX_U32 *)type;
2009    nversion = (OMX_VERSIONTYPE *)((OMX_U8 *)type + sizeof(OMX_U32));
2010
2011    *nsize = size;
2012    nversion->nVersion = OMX_SPEC_VERSION;
2013}
2014
2015OMX_ERRORTYPE ComponentBase::CheckTypeHeader(const OMX_PTR type, OMX_U32 size)
2016{
2017    OMX_U32 *nsize;
2018    OMX_VERSIONTYPE *nversion;
2019
2020    if (!type)
2021        return OMX_ErrorBadParameter;
2022
2023    nsize = (OMX_U32 *)type;
2024    nversion = (OMX_VERSIONTYPE *)((OMX_U8 *)type + sizeof(OMX_U32));
2025
2026    if (*nsize != size)
2027        return OMX_ErrorBadParameter;
2028
2029    if (nversion->nVersion != OMX_SPEC_VERSION)
2030        return OMX_ErrorVersionMismatch;
2031
2032    return OMX_ErrorNone;
2033}
2034
2035/*
2036 * query_roles helper
2037 */
2038OMX_ERRORTYPE ComponentBase::QueryRolesHelper(
2039    OMX_U32 nr_comp_roles,
2040    const OMX_U8 **comp_roles,
2041    OMX_U32 *nr_roles, OMX_U8 **roles)
2042{
2043    OMX_U32 i;
2044
2045    if (!roles) {
2046        *nr_roles = nr_comp_roles;
2047        return OMX_ErrorNone;
2048    }
2049
2050    if (!nr_roles || (*nr_roles != nr_comp_roles) || !roles)
2051        return OMX_ErrorBadParameter;
2052
2053    for (i = 0; i < nr_comp_roles; i++) {
2054        if (!roles[i])
2055            break;
2056
2057        strncpy((OMX_STRING)&roles[i][0],
2058                (const OMX_STRING)&comp_roles[i][0], OMX_MAX_STRINGNAME_SIZE);
2059    }
2060
2061    if (i != nr_comp_roles)
2062        return OMX_ErrorBadParameter;
2063
2064    *nr_roles = nr_comp_roles;
2065    return OMX_ErrorNone;
2066}
2067
2068/* end of ComponentBase */
2069