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