componentbase.cpp revision fb74fc90d40dadb1a607b3e81a2f271845fcd659
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
1406        if (current == OMX_StatePause) {
1407            pthread_mutex_lock(&executing_lock);
1408            executing = true;
1409            pthread_cond_signal(&executing_wait);
1410            pthread_mutex_unlock(&executing_lock);
1411        }
1412
1413        bufferwork->StopWork();
1414
1415        ret = ProcessorStop();
1416        if (ret != OMX_ErrorNone) {
1417            LOGE("failed to ProcessorStop() (ret = 0x%08x)\n", ret);
1418            ret = OMX_ErrorInvalidState;
1419            goto out;
1420        }
1421    }
1422    else if (current == OMX_StateWaitForResources) {
1423        LOGE("state transition's requested from WaitForResources to Idle\n");
1424
1425        /* same as Loaded to Idle BUT DO NOTHING for now */
1426
1427        ret = OMX_ErrorNone;
1428    }
1429    else
1430        ret = OMX_ErrorIncorrectStateTransition;
1431
1432out:
1433    return ret;
1434}
1435
1436inline OMX_ERRORTYPE
1437ComponentBase::TransStateToExecuting(OMX_STATETYPE current)
1438{
1439    OMX_ERRORTYPE ret;
1440
1441    if (current == OMX_StateIdle) {
1442        pthread_mutex_lock(&executing_lock);
1443        executing = true;
1444        pthread_mutex_unlock(&executing_lock);
1445
1446        bufferwork->StartWork();
1447
1448        ret = ProcessorStart();
1449        if (ret != OMX_ErrorNone) {
1450            LOGE("failed to ProcessorStart() (ret = 0x%08x)\n", ret);
1451            ret = OMX_ErrorInvalidState;
1452            goto out;
1453        }
1454    }
1455    else if (current == OMX_StatePause) {
1456        pthread_mutex_lock(&executing_lock);
1457        executing = true;
1458        pthread_cond_signal(&executing_wait);
1459        pthread_mutex_unlock(&executing_lock);
1460
1461        ret = ProcessorResume();
1462        if (ret != OMX_ErrorNone) {
1463            LOGE("failed to ProcessorStart() (ret = 0x%08x)\n", ret);
1464            ret = OMX_ErrorInvalidState;
1465            goto out;
1466        }
1467    }
1468    else
1469        ret = OMX_ErrorIncorrectStateTransition;
1470
1471out:
1472    return ret;
1473}
1474
1475inline OMX_ERRORTYPE ComponentBase::TransStateToPause(OMX_STATETYPE current)
1476{
1477    OMX_ERRORTYPE ret;
1478
1479    if (current == OMX_StateIdle) {
1480        /* turn off executing flag */
1481        pthread_mutex_lock(&executing_lock);
1482        executing = false;
1483        pthread_mutex_unlock(&executing_lock);
1484
1485        bufferwork->StartWork();
1486
1487        ret = ProcessorStart();
1488        if (ret != OMX_ErrorNone) {
1489            LOGE("failed to ProcessorPause() (ret = 0x%08x)\n", ret);
1490            ret = OMX_ErrorInvalidState;
1491            goto out;
1492        }
1493    }
1494    else if (current == OMX_StateExecuting) {
1495        pthread_mutex_lock(&executing_lock);
1496        executing = false;
1497        pthread_mutex_unlock(&executing_lock);
1498
1499        ret = ProcessorPause();
1500        if (ret != OMX_ErrorNone) {
1501            LOGE("failed to ProcessorPause() (ret = 0x%08x)\n", ret);
1502            ret = OMX_ErrorInvalidState;
1503            goto out;
1504        }
1505    }
1506    else
1507        ret = OMX_ErrorIncorrectStateTransition;
1508
1509out:
1510    return ret;
1511}
1512
1513inline OMX_ERRORTYPE ComponentBase::TransStateToInvalid(OMX_STATETYPE current)
1514{
1515    OMX_ERRORTYPE ret = OMX_ErrorInvalidState;
1516
1517    /*
1518     * Todo
1519     *   graceful escape
1520     */
1521
1522    return ret;
1523}
1524
1525inline OMX_ERRORTYPE
1526ComponentBase::TransStateToWaitForResources(OMX_STATETYPE current)
1527{
1528    OMX_ERRORTYPE ret;
1529
1530    if (current == OMX_StateLoaded) {
1531        LOGE("state transition's requested from Loaded to WaitForResources\n");
1532        ret = OMX_ErrorNone;
1533    }
1534    else
1535        ret = OMX_ErrorIncorrectStateTransition;
1536
1537    return ret;
1538}
1539
1540/* mark buffer */
1541void ComponentBase::PushThisMark(OMX_U32 port_index, OMX_MARKTYPE *mark)
1542{
1543    PortBase *port = NULL;
1544    OMX_EVENTTYPE event;
1545    OMX_U32 data1, data2;
1546    OMX_ERRORTYPE ret;
1547
1548    if (ports)
1549        if (port_index < nr_ports)
1550            port = ports[port_index];
1551
1552    if (!port) {
1553        ret = OMX_ErrorBadPortIndex;
1554        goto notify_event;
1555    }
1556
1557    ret = port->PushMark(mark);
1558    if (ret != OMX_ErrorNone) {
1559        /* don't report OMX_ErrorInsufficientResources */
1560        ret = OMX_ErrorUndefined;
1561        goto notify_event;
1562    }
1563
1564notify_event:
1565    if (ret == OMX_ErrorNone) {
1566        event = OMX_EventCmdComplete;
1567        data1 = OMX_CommandMarkBuffer;
1568        data2 = port_index;
1569    }
1570    else {
1571        event = OMX_EventError;
1572        data1 = ret;
1573        data2 = 0;
1574    }
1575
1576    callbacks->EventHandler(handle, appdata, event, data1, data2, NULL);
1577}
1578
1579void ComponentBase::FlushPort(OMX_U32 port_index, bool notify)
1580{
1581    OMX_U32 i, from_index, to_index;
1582
1583    if ((port_index != OMX_ALL) && (port_index > nr_ports-1))
1584        return;
1585
1586    if (port_index == OMX_ALL) {
1587        from_index = 0;
1588        to_index = nr_ports - 1;
1589    }
1590    else {
1591        from_index = port_index;
1592        to_index = port_index;
1593    }
1594
1595    pthread_mutex_lock(&ports_block);
1596    for (i = from_index; i <= to_index; i++) {
1597        ports[i]->FlushPort();
1598        if (notify)
1599            callbacks->EventHandler(handle, appdata, OMX_EventCmdComplete,
1600                                    OMX_CommandFlush, i, NULL);
1601    }
1602    pthread_mutex_unlock(&ports_block);
1603}
1604
1605void ComponentBase::TransStatePort(OMX_U32 port_index, OMX_U8 state)
1606{
1607    OMX_EVENTTYPE event;
1608    OMX_U32 data1, data2;
1609    OMX_U32 i, from_index, to_index;
1610    OMX_ERRORTYPE ret;
1611
1612    if ((port_index != OMX_ALL) && (port_index > nr_ports-1))
1613        return;
1614
1615    if (port_index == OMX_ALL) {
1616        from_index = 0;
1617        to_index = nr_ports - 1;
1618    }
1619    else {
1620        from_index = port_index;
1621        to_index = port_index;
1622    }
1623
1624    pthread_mutex_lock(&ports_block);
1625    for (i = from_index; i <= to_index; i++) {
1626        ret = ports[i]->TransState(state);
1627        if (ret == OMX_ErrorNone) {
1628            event = OMX_EventCmdComplete;
1629            if (state == PortBase::OMX_PortEnabled)
1630                data1 = OMX_CommandPortEnable;
1631            else
1632                data1 = OMX_CommandPortDisable;
1633            data2 = i;
1634        }
1635        else {
1636            event = OMX_EventError;
1637            data1 = ret;
1638            data2 = 0;
1639        }
1640        callbacks->EventHandler(handle, appdata, OMX_EventCmdComplete,
1641                                OMX_CommandPortDisable, data2, NULL);
1642    }
1643    pthread_mutex_unlock(&ports_block);
1644}
1645
1646/* set working role */
1647OMX_ERRORTYPE ComponentBase::SetWorkingRole(const OMX_STRING role)
1648{
1649    OMX_U32 i;
1650
1651    if (state != OMX_StateUnloaded && state != OMX_StateLoaded)
1652        return OMX_ErrorIncorrectStateOperation;
1653
1654    if (!role) {
1655        working_role = NULL;
1656        return OMX_ErrorNone;
1657    }
1658
1659    for (i = 0; i < nr_roles; i++) {
1660        if (!strcmp((char *)&roles[i][0], role)) {
1661            working_role = (OMX_STRING)&roles[i][0];
1662            return OMX_ErrorNone;
1663        }
1664    }
1665
1666    LOGE("cannot find %s role in %s\n", role, name);
1667    return OMX_ErrorBadParameter;
1668}
1669
1670/* apply a working role for a component having multiple roles */
1671OMX_ERRORTYPE ComponentBase::ApplyWorkingRole(void)
1672{
1673    OMX_U32 i;
1674    OMX_ERRORTYPE ret;
1675
1676    if (state != OMX_StateUnloaded && state != OMX_StateLoaded)
1677        return OMX_ErrorIncorrectStateOperation;
1678
1679    if (!working_role)
1680        return OMX_ErrorBadParameter;
1681
1682    if (!callbacks || !appdata)
1683        return OMX_ErrorBadParameter;
1684
1685    ret = AllocatePorts();
1686    if (ret != OMX_ErrorNone) {
1687        LOGE("failed to AllocatePorts() (ret = 0x%08x)\n", ret);
1688        return ret;
1689    }
1690
1691    /* now we can access ports */
1692    for (i = 0; i < nr_ports; i++) {
1693        ports[i]->SetOwner(handle);
1694        ports[i]->SetCallbacks(handle, callbacks, appdata);
1695    }
1696
1697    return OMX_ErrorNone;
1698}
1699
1700OMX_ERRORTYPE ComponentBase::AllocatePorts(void)
1701{
1702    OMX_ERRORTYPE ret;
1703
1704    if (ports)
1705        return OMX_ErrorBadParameter;
1706
1707    ret = ComponentAllocatePorts();
1708    if (ret != OMX_ErrorNone) {
1709        LOGE("failed to %s::ComponentAllocatePorts(), ret = 0x%08x\n",
1710             name, ret);
1711        return ret;
1712    }
1713
1714    return OMX_ErrorNone;
1715}
1716
1717/* called int FreeHandle() */
1718OMX_ERRORTYPE ComponentBase::FreePorts(void)
1719{
1720    if (ports) {
1721        OMX_U32 i, this_nr_ports = this->nr_ports;
1722
1723        for (i = 0; i < this_nr_ports; i++) {
1724            if (ports[i]) {
1725                OMX_MARKTYPE *mark;
1726                /* it should be empty before this */
1727                while ((mark = ports[i]->PopMark()))
1728                    free(mark);
1729
1730                delete ports[i];
1731                ports[i] = NULL;
1732            }
1733        }
1734        delete []ports;
1735        ports = NULL;
1736    }
1737
1738    return OMX_ErrorNone;
1739}
1740
1741/* buffer processing */
1742/* implement WorkableInterface */
1743void ComponentBase::Work(void)
1744{
1745    OMX_BUFFERHEADERTYPE *buffers[nr_ports];
1746    bool retain[nr_ports];
1747    OMX_U32 i;
1748    bool avail = false;
1749
1750    pthread_mutex_lock(&executing_lock);
1751    if (!executing)
1752        pthread_cond_wait(&executing_wait, &executing_lock);
1753    pthread_mutex_unlock(&executing_lock);
1754
1755    pthread_mutex_lock(&ports_block);
1756
1757    avail = IsAllBufferAvailable();
1758    if (avail) {
1759        for (i = 0; i < nr_ports; i++) {
1760            buffers[i] = ports[i]->PopBuffer();
1761            retain[i] = false;
1762        }
1763
1764        ProcessorProcess(buffers, &retain[0], nr_ports);
1765        PostProcessBuffer(buffers, &retain[0], nr_ports);
1766
1767        for (i = 0; i < nr_ports; i++) {
1768            if (retain[i])
1769                ports[i]->RetainThisBuffer(buffers[i]);
1770            else
1771                ports[i]->ReturnThisBuffer(buffers[i]);
1772        }
1773    }
1774    ScheduleIfAllBufferAvailable();
1775    pthread_mutex_unlock(&ports_block);
1776}
1777
1778bool ComponentBase::IsAllBufferAvailable(void)
1779{
1780    OMX_U32 i;
1781    OMX_U32 nr_avail = 0;
1782
1783    for (i = 0; i < nr_ports; i++) {
1784        OMX_U32 length = 0;
1785
1786        if (ports[i]->IsEnabled())
1787            length = ports[i]->BufferQueueLength();
1788
1789        if (length)
1790            nr_avail++;
1791    }
1792
1793    if (nr_avail == nr_ports)
1794        return true;
1795    else
1796        return false;
1797}
1798
1799void ComponentBase::ScheduleIfAllBufferAvailable(void)
1800{
1801    bool avail;
1802
1803    avail = IsAllBufferAvailable();
1804    if (avail)
1805        bufferwork->ScheduleWork(this);
1806}
1807
1808void ComponentBase::PostProcessBuffer(OMX_BUFFERHEADERTYPE **buffers,
1809                                      bool *retain,
1810                                      OMX_U32 nr_buffers)
1811{
1812    OMX_U32 i;
1813
1814    for (i = 0; i < nr_ports; i++) {
1815        OMX_MARKTYPE *mark;
1816
1817        if (ports[i]->GetPortDirection() == OMX_DirInput) {
1818            bool is_sink_component = true;
1819            OMX_U32 j;
1820
1821            if (buffers[i]->hMarkTargetComponent) {
1822                if (buffers[i]->hMarkTargetComponent == handle) {
1823                    callbacks->EventHandler(handle, appdata, OMX_EventMark,
1824                                            0, 0, buffers[i]->pMarkData);
1825                    buffers[i]->hMarkTargetComponent = NULL;
1826                    buffers[i]->pMarkData = NULL;
1827                }
1828            }
1829
1830            for (j = 0; j < nr_ports; j++) {
1831                if (j == i)
1832                    continue;
1833
1834                if (ports[j]->GetPortDirection() == OMX_DirOutput) {
1835                    if (buffers[i]->nFlags & OMX_BUFFERFLAG_EOS) {
1836                        buffers[j]->nFlags |= OMX_BUFFERFLAG_EOS;
1837                        buffers[i]->nFlags &= ~OMX_BUFFERFLAG_EOS;
1838                        retain[i] = false;
1839                        retain[j] = false;
1840                    }
1841
1842                    if (!buffers[j]->hMarkTargetComponent) {
1843                        mark = ports[j]->PopMark();
1844                        if (mark) {
1845                            buffers[j]->hMarkTargetComponent =
1846                                mark->hMarkTargetComponent;
1847                            buffers[j]->pMarkData = mark->pMarkData;
1848                            free(mark);
1849                            mark = NULL;
1850                        }
1851
1852                        if (buffers[i]->hMarkTargetComponent) {
1853                            if (buffers[j]->hMarkTargetComponent) {
1854                                mark = (OMX_MARKTYPE *)
1855                                    malloc(sizeof(*mark));
1856                                if (mark) {
1857                                    mark->hMarkTargetComponent =
1858                                        buffers[i]->hMarkTargetComponent;
1859                                    mark->pMarkData = buffers[i]->pMarkData;
1860                                    ports[j]->PushMark(mark);
1861                                    mark = NULL;
1862                                    buffers[i]->hMarkTargetComponent = NULL;
1863                                    buffers[i]->pMarkData = NULL;
1864                                }
1865                            }
1866                            else {
1867                                buffers[j]->hMarkTargetComponent =
1868                                    buffers[i]->hMarkTargetComponent;
1869                                buffers[j]->pMarkData = buffers[i]->pMarkData;
1870                                buffers[i]->hMarkTargetComponent = NULL;
1871                                buffers[i]->pMarkData = NULL;
1872                            }
1873                        }
1874                    }
1875                    else {
1876                        if (buffers[i]->hMarkTargetComponent) {
1877                            mark = (OMX_MARKTYPE *)malloc(sizeof(*mark));
1878                            if (mark) {
1879                                mark->hMarkTargetComponent =
1880                                    buffers[i]->hMarkTargetComponent;
1881                                mark->pMarkData = buffers[i]->pMarkData;
1882                                ports[j]->PushMark(mark);
1883                                mark = NULL;
1884                                buffers[i]->hMarkTargetComponent = NULL;
1885                                buffers[i]->pMarkData = NULL;
1886                            }
1887                        }
1888                    }
1889                    is_sink_component = false;
1890                }
1891            }
1892
1893            if (is_sink_component) {
1894                if (buffers[i]->nFlags & OMX_BUFFERFLAG_EOS) {
1895                    callbacks->EventHandler(handle, appdata,
1896                                            OMX_EventBufferFlag,
1897                                            i, buffers[i]->nFlags, NULL);
1898                    retain[i] = false;
1899                }
1900            }
1901        }
1902        else if (ports[i]->GetPortDirection() == OMX_DirOutput) {
1903            bool is_source_component = true;
1904            OMX_U32 j;
1905
1906            if (buffers[i]->nFlags & OMX_BUFFERFLAG_EOS) {
1907                callbacks->EventHandler(handle, appdata,
1908                                        OMX_EventBufferFlag,
1909                                        i, buffers[i]->nFlags, NULL);
1910                retain[i] = false;
1911            }
1912
1913            for (j = 0; j < nr_ports; j++) {
1914                if (j == i)
1915                    continue;
1916
1917                if (ports[j]->GetPortDirection() == OMX_DirInput)
1918                    is_source_component = false;
1919            }
1920
1921            if (is_source_component) {
1922                if (!retain[i]) {
1923                    mark = ports[i]->PopMark();
1924                    if (mark) {
1925                        buffers[i]->hMarkTargetComponent =
1926                            mark->hMarkTargetComponent;
1927                        buffers[i]->pMarkData = mark->pMarkData;
1928                        free(mark);
1929                        mark = NULL;
1930
1931                        if (buffers[i]->hMarkTargetComponent == handle) {
1932                            callbacks->EventHandler(handle, appdata,
1933                                                    OMX_EventMark, 0, 0,
1934                                                    buffers[i]->pMarkData);
1935                            buffers[i]->hMarkTargetComponent = NULL;
1936                            buffers[i]->pMarkData = NULL;
1937                        }
1938                    }
1939                }
1940            }
1941        }
1942        else {
1943            LOGE("%s(): fatal error unknown port direction (0x%08x)\n",
1944                 __func__, ports[i]->GetPortDirection());
1945        }
1946    }
1947}
1948
1949/* processor default callbacks */
1950OMX_ERRORTYPE ComponentBase::ProcessorInit(void)
1951{
1952    return OMX_ErrorNone;
1953}
1954OMX_ERRORTYPE ComponentBase::ProcessorDeinit(void)
1955{
1956    return OMX_ErrorNone;
1957}
1958
1959OMX_ERRORTYPE ComponentBase::ProcessorStart(void)
1960{
1961    return OMX_ErrorNone;
1962}
1963
1964OMX_ERRORTYPE ComponentBase::ProcessorStop(void)
1965{
1966    return OMX_ErrorNone;
1967}
1968
1969OMX_ERRORTYPE ComponentBase::ProcessorPause(void)
1970{
1971    return OMX_ErrorNone;
1972}
1973
1974OMX_ERRORTYPE ComponentBase::ProcessorResume(void)
1975{
1976    return OMX_ErrorNone;
1977}
1978
1979/* end of processor callbacks */
1980
1981/* helper for derived class */
1982const OMX_STRING ComponentBase::GetWorkingRole(void)
1983{
1984    return &working_role[0];
1985}
1986
1987const OMX_COMPONENTTYPE *ComponentBase::GetComponentHandle(void)
1988{
1989    return handle;
1990}
1991
1992void ComponentBase::DumpBuffer(const OMX_BUFFERHEADERTYPE *bufferheader)
1993{
1994    OMX_U8 *pbuffer = bufferheader->pBuffer, *p;
1995    OMX_U32 offset = bufferheader->nOffset;
1996    OMX_U32 alloc_len = bufferheader->nAllocLen;
1997    OMX_U32 filled_len =  bufferheader->nFilledLen;
1998    OMX_U32 left = filled_len, oneline;
1999    OMX_U32 index = 0, i;
2000    /* 0x%04lx:  %02x %02x .. (n = 16)\n\0 */
2001    char prbuffer[8 + 3 * 0x10 + 2], *pp;
2002    OMX_U32 prbuffer_len;
2003
2004    LOGD("Componant %s DumpBuffer\n", name);
2005    LOGD("%s port index = %lu",
2006         (bufferheader->nInputPortIndex != 0x7fffffff) ? "input" : "output",
2007         (bufferheader->nInputPortIndex != 0x7fffffff) ?
2008         bufferheader->nInputPortIndex : bufferheader->nOutputPortIndex);
2009    LOGD("nAllocLen = %lu, nOffset = %lu, nFilledLen = %lu\n",
2010         alloc_len, offset, filled_len);
2011    LOGD("nTimeStamp = %lld, nTickCount = %lu",
2012         bufferheader->nTimeStamp,
2013         bufferheader->nTickCount);
2014    LOGD("nFlags = 0x%08lx\n", bufferheader->nFlags);
2015
2016    if (!pbuffer || !alloc_len || !filled_len)
2017        return;
2018
2019    if (offset + filled_len > alloc_len)
2020        return;
2021
2022    p = pbuffer + offset;
2023    while (left) {
2024        oneline = left > 0x10 ? 0x10 : left; /* 16 items per 1 line */
2025        pp += sprintf(pp, "0x%04lx: ", index);
2026        for (i = 0; i < oneline; i++)
2027            pp += sprintf(pp, " %02x", *(p + i));
2028        pp += sprintf(pp, "\n");
2029        *pp = '\0';
2030
2031        index += 0x10;
2032        p += oneline;
2033        left -= oneline;
2034
2035        pp = &prbuffer[0];
2036        LOGD("%s", pp);
2037    }
2038}
2039
2040/* end of component methods & helpers */
2041
2042/*
2043 * omx header manipuation
2044 */
2045void ComponentBase::SetTypeHeader(OMX_PTR type, OMX_U32 size)
2046{
2047    OMX_U32 *nsize;
2048    OMX_VERSIONTYPE *nversion;
2049
2050    if (!type)
2051        return;
2052
2053    nsize = (OMX_U32 *)type;
2054    nversion = (OMX_VERSIONTYPE *)((OMX_U8 *)type + sizeof(OMX_U32));
2055
2056    *nsize = size;
2057    nversion->nVersion = OMX_SPEC_VERSION;
2058}
2059
2060OMX_ERRORTYPE ComponentBase::CheckTypeHeader(const OMX_PTR type, OMX_U32 size)
2061{
2062    OMX_U32 *nsize;
2063    OMX_VERSIONTYPE *nversion;
2064
2065    if (!type)
2066        return OMX_ErrorBadParameter;
2067
2068    nsize = (OMX_U32 *)type;
2069    nversion = (OMX_VERSIONTYPE *)((OMX_U8 *)type + sizeof(OMX_U32));
2070
2071    if (*nsize != size)
2072        return OMX_ErrorBadParameter;
2073
2074    if (nversion->nVersion != OMX_SPEC_VERSION)
2075        return OMX_ErrorVersionMismatch;
2076
2077    return OMX_ErrorNone;
2078}
2079
2080/*
2081 * query_roles helper
2082 */
2083OMX_ERRORTYPE ComponentBase::QueryRolesHelper(
2084    OMX_U32 nr_comp_roles,
2085    const OMX_U8 **comp_roles,
2086    OMX_U32 *nr_roles, OMX_U8 **roles)
2087{
2088    OMX_U32 i;
2089
2090    if (!roles) {
2091        *nr_roles = nr_comp_roles;
2092        return OMX_ErrorNone;
2093    }
2094
2095    if (!nr_roles || (*nr_roles != nr_comp_roles) || !roles)
2096        return OMX_ErrorBadParameter;
2097
2098    for (i = 0; i < nr_comp_roles; i++) {
2099        if (!roles[i])
2100            break;
2101
2102        strncpy((OMX_STRING)&roles[i][0],
2103                (const OMX_STRING)&comp_roles[i][0], OMX_MAX_STRINGNAME_SIZE);
2104    }
2105
2106    if (i != nr_comp_roles)
2107        return OMX_ErrorBadParameter;
2108
2109    *nr_roles = nr_comp_roles;
2110    return OMX_ErrorNone;
2111}
2112
2113/* end of ComponentBase */
2114