componentbase.cpp revision dd0f8243514bd9380e5172ba883e488bcf65dcc9
1/*
2 * Copyright (c) 2009 Wind River Systems, Inc.
3 *
4 * The right to copy, distribute, modify, or otherwise make use
5 * of this software may be licensed only pursuant to the terms
6 * of an applicable Wind River license agreement.
7 */
8
9#include <stdlib.h>
10#include <string.h>
11
12#include <pthread.h>
13
14#include <OMX_Core.h>
15#include <OMX_Component.h>
16
17#include <componentbase.h>
18
19#include <queue.h>
20#include <workqueue.h>
21
22#define LOG_TAG "componentbase"
23#include <log.h>
24
25/*
26 * CmdProcessWork
27 */
28CmdProcessWork::CmdProcessWork(CmdHandlerInterface *ci)
29{
30    this->ci = ci;
31
32    workq = new WorkQueue;
33
34    __queue_init(&q);
35    pthread_mutex_init(&lock, NULL);
36
37    workq->StartWork(true);
38}
39
40CmdProcessWork::~CmdProcessWork()
41{
42    workq->StopWork();
43    delete workq;
44
45    pthread_mutex_lock(&lock);
46    queue_free_all(&q);
47    pthread_mutex_unlock(&lock);
48
49    pthread_mutex_destroy(&lock);
50}
51
52OMX_ERRORTYPE CmdProcessWork::PushCmdQueue(struct cmd_s *cmd)
53{
54    int ret;
55
56    pthread_mutex_lock(&lock);
57    ret = queue_push_tail(&q, cmd);
58    if (ret) {
59        pthread_mutex_unlock(&lock);
60        return OMX_ErrorInsufficientResources;
61    }
62
63    workq->ScheduleWork(this);
64    pthread_mutex_unlock(&lock);
65
66    return OMX_ErrorNone;
67}
68
69struct cmd_s *CmdProcessWork::PopCmdQueue(void)
70{
71    struct cmd_s *cmd;
72
73    pthread_mutex_lock(&lock);
74    cmd = (struct cmd_s *)queue_pop_head(&q);
75    pthread_mutex_unlock(&lock);
76
77    return cmd;
78}
79
80void CmdProcessWork::ScheduleIfAvailable(void)
81{
82    bool avail;
83
84    pthread_mutex_lock(&lock);
85    avail = queue_length(&q) ? true : false;
86    pthread_mutex_unlock(&lock);
87
88    if (avail)
89        workq->ScheduleWork(this);
90}
91
92void CmdProcessWork::Work(void)
93{
94    struct cmd_s *cmd;
95
96    cmd = PopCmdQueue();
97    if (cmd) {
98        ci->CmdHandler(cmd);
99        free(cmd);
100    }
101    ScheduleIfAvailable();
102}
103
104/* end of CmdProcessWork */
105
106/*
107 * ComponentBase
108 */
109/*
110 * constructor & destructor
111 */
112void ComponentBase::__ComponentBase(void)
113{
114    memset(name, 0, OMX_MAX_STRINGNAME_SIZE);
115    cmodule = NULL;
116    handle = NULL;
117
118    roles = NULL;
119    nr_roles = 0;
120
121    working_role = NULL;
122
123    ports = NULL;
124    nr_ports = 0;
125    memset(&portparam, 0, sizeof(portparam));
126
127    state = OMX_StateUnloaded;
128
129    cmdwork = new CmdProcessWork(this);
130
131    bufferwork = new WorkQueue();
132
133    pthread_mutex_init(&ports_block, NULL);
134}
135
136ComponentBase::ComponentBase()
137{
138    __ComponentBase();
139}
140
141ComponentBase::ComponentBase(const OMX_STRING name)
142{
143    __ComponentBase();
144    SetName(name);
145}
146
147ComponentBase::~ComponentBase()
148{
149    delete cmdwork;
150
151    delete bufferwork;
152
153    pthread_mutex_destroy(&ports_block);
154
155    if (roles) {
156        if (roles[0])
157            free(roles[0]);
158        free(roles);
159    }
160}
161
162/* end of constructor & destructor */
163
164/*
165 * accessor
166 */
167/* name */
168void ComponentBase::SetName(const OMX_STRING name)
169{
170    strncpy(this->name, name, OMX_MAX_STRINGNAME_SIZE);
171    this->name[OMX_MAX_STRINGNAME_SIZE-1] = '\0';
172}
173
174const OMX_STRING ComponentBase::GetName(void)
175{
176    return name;
177}
178
179/* component module */
180void ComponentBase::SetCModule(CModule *cmodule)
181{
182    this->cmodule = cmodule;
183}
184
185CModule *ComponentBase::GetCModule(void)
186{
187    return cmodule;
188}
189
190/* end of accessor */
191
192/*
193 * core methods & helpers
194 */
195/* roles */
196OMX_ERRORTYPE ComponentBase::SetRolesOfComponent(OMX_U32 nr_roles,
197                                                 const OMX_U8 **roles)
198{
199    OMX_U32 i;
200
201    if (!roles || !nr_roles)
202        return OMX_ErrorBadParameter;
203
204    if (this->roles) {
205        free(this->roles[0]);
206        free(this->roles);
207        this->roles = NULL;
208    }
209
210    this->roles = (OMX_U8 **)malloc(sizeof(OMX_STRING) * nr_roles);
211    if (!this->roles)
212        return OMX_ErrorInsufficientResources;
213
214    this->roles[0] = (OMX_U8 *)malloc(OMX_MAX_STRINGNAME_SIZE * nr_roles);
215    if (!this->roles[0]) {
216        free(this->roles);
217        this->roles = NULL;
218        return OMX_ErrorInsufficientResources;
219    }
220
221    for (i = 0; i < nr_roles; i++) {
222        if (i < nr_roles-1)
223            this->roles[i+1] = this->roles[i] + OMX_MAX_STRINGNAME_SIZE;
224
225        strncpy((OMX_STRING)&this->roles[i][0],
226                (const OMX_STRING)&roles[i][0], OMX_MAX_STRINGNAME_SIZE);
227    }
228
229    this->nr_roles = nr_roles;
230    return OMX_ErrorNone;
231}
232
233/* GetHandle & FreeHandle */
234OMX_ERRORTYPE ComponentBase::GetHandle(OMX_HANDLETYPE *pHandle,
235                                       OMX_PTR pAppData,
236                                       OMX_CALLBACKTYPE *pCallBacks)
237{
238    OMX_U32 i;
239    OMX_ERRORTYPE ret;
240
241    if (!pHandle)
242        return OMX_ErrorBadParameter;
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            bufferwork->ResumeWork();
1408
1409        bufferwork->StopWork();
1410
1411        ret = ProcessorStop();
1412        if (ret != OMX_ErrorNone) {
1413            LOGE("failed to ProcessorStop() (ret = 0x%08x)\n", ret);
1414            ret = OMX_ErrorInvalidState;
1415            goto out;
1416        }
1417    }
1418    else if (current == OMX_StateWaitForResources) {
1419        LOGE("state transition's requested from WaitForResources to Idle\n");
1420
1421        /* same as Loaded to Idle BUT DO NOTHING for now */
1422
1423        ret = OMX_ErrorNone;
1424    }
1425    else
1426        ret = OMX_ErrorIncorrectStateTransition;
1427
1428out:
1429    return ret;
1430}
1431
1432inline OMX_ERRORTYPE
1433ComponentBase::TransStateToExecuting(OMX_STATETYPE current)
1434{
1435    OMX_ERRORTYPE ret;
1436
1437    if (current == OMX_StateIdle) {
1438        bufferwork->StartWork(true);
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        bufferwork->ResumeWork();
1449
1450        ret = ProcessorResume();
1451        if (ret != OMX_ErrorNone) {
1452            LOGE("failed to ProcessorStart() (ret = 0x%08x)\n", ret);
1453            ret = OMX_ErrorInvalidState;
1454            goto out;
1455        }
1456    }
1457    else
1458        ret = OMX_ErrorIncorrectStateTransition;
1459
1460out:
1461    return ret;
1462}
1463
1464inline OMX_ERRORTYPE ComponentBase::TransStateToPause(OMX_STATETYPE current)
1465{
1466    OMX_ERRORTYPE ret;
1467
1468    if (current == OMX_StateIdle) {
1469        bufferwork->StartWork(false);
1470
1471        ret = ProcessorStart();
1472        if (ret != OMX_ErrorNone) {
1473            LOGE("failed to ProcessorPause() (ret = 0x%08x)\n", ret);
1474            ret = OMX_ErrorInvalidState;
1475            goto out;
1476        }
1477    }
1478    else if (current == OMX_StateExecuting) {
1479        bufferwork->PauseWork();
1480
1481        ret = ProcessorPause();
1482        if (ret != OMX_ErrorNone) {
1483            LOGE("failed to ProcessorPause() (ret = 0x%08x)\n", ret);
1484            ret = OMX_ErrorInvalidState;
1485            goto out;
1486        }
1487    }
1488    else
1489        ret = OMX_ErrorIncorrectStateTransition;
1490
1491out:
1492    return ret;
1493}
1494
1495inline OMX_ERRORTYPE ComponentBase::TransStateToInvalid(OMX_STATETYPE current)
1496{
1497    OMX_ERRORTYPE ret = OMX_ErrorInvalidState;
1498
1499    /*
1500     * Todo
1501     *   graceful escape
1502     */
1503
1504    return ret;
1505}
1506
1507inline OMX_ERRORTYPE
1508ComponentBase::TransStateToWaitForResources(OMX_STATETYPE current)
1509{
1510    OMX_ERRORTYPE ret;
1511
1512    if (current == OMX_StateLoaded) {
1513        LOGE("state transition's requested from Loaded to WaitForResources\n");
1514        ret = OMX_ErrorNone;
1515    }
1516    else
1517        ret = OMX_ErrorIncorrectStateTransition;
1518
1519    return ret;
1520}
1521
1522/* mark buffer */
1523void ComponentBase::PushThisMark(OMX_U32 port_index, OMX_MARKTYPE *mark)
1524{
1525    PortBase *port = NULL;
1526    OMX_EVENTTYPE event;
1527    OMX_U32 data1, data2;
1528    OMX_ERRORTYPE ret;
1529
1530    if (ports)
1531        if (port_index < nr_ports)
1532            port = ports[port_index];
1533
1534    if (!port) {
1535        ret = OMX_ErrorBadPortIndex;
1536        goto notify_event;
1537    }
1538
1539    ret = port->PushMark(mark);
1540    if (ret != OMX_ErrorNone) {
1541        /* don't report OMX_ErrorInsufficientResources */
1542        ret = OMX_ErrorUndefined;
1543        goto notify_event;
1544    }
1545
1546notify_event:
1547    if (ret == OMX_ErrorNone) {
1548        event = OMX_EventCmdComplete;
1549        data1 = OMX_CommandMarkBuffer;
1550        data2 = port_index;
1551    }
1552    else {
1553        event = OMX_EventError;
1554        data1 = ret;
1555        data2 = 0;
1556    }
1557
1558    callbacks->EventHandler(handle, appdata, event, data1, data2, NULL);
1559}
1560
1561void ComponentBase::FlushPort(OMX_U32 port_index, bool notify)
1562{
1563    OMX_U32 i, from_index, to_index;
1564
1565    if ((port_index != OMX_ALL) && (port_index > nr_ports-1))
1566        return;
1567
1568    if (port_index == OMX_ALL) {
1569        from_index = 0;
1570        to_index = nr_ports - 1;
1571    }
1572    else {
1573        from_index = port_index;
1574        to_index = port_index;
1575    }
1576
1577    pthread_mutex_lock(&ports_block);
1578    for (i = from_index; i <= to_index; i++) {
1579        ports[i]->FlushPort();
1580        if (notify)
1581            callbacks->EventHandler(handle, appdata, OMX_EventCmdComplete,
1582                                    OMX_CommandFlush, i, NULL);
1583    }
1584    pthread_mutex_unlock(&ports_block);
1585}
1586
1587void ComponentBase::TransStatePort(OMX_U32 port_index, OMX_U8 state)
1588{
1589    OMX_EVENTTYPE event;
1590    OMX_U32 data1, data2;
1591    OMX_U32 i, from_index, to_index;
1592    OMX_ERRORTYPE ret;
1593
1594    if ((port_index != OMX_ALL) && (port_index > nr_ports-1))
1595        return;
1596
1597    if (port_index == OMX_ALL) {
1598        from_index = 0;
1599        to_index = nr_ports - 1;
1600    }
1601    else {
1602        from_index = port_index;
1603        to_index = port_index;
1604    }
1605
1606    pthread_mutex_lock(&ports_block);
1607    for (i = from_index; i <= to_index; i++) {
1608        ret = ports[i]->TransState(state);
1609        if (ret == OMX_ErrorNone) {
1610            event = OMX_EventCmdComplete;
1611            if (state == PortBase::OMX_PortEnabled)
1612                data1 = OMX_CommandPortEnable;
1613            else
1614                data1 = OMX_CommandPortDisable;
1615            data2 = i;
1616        }
1617        else {
1618            event = OMX_EventError;
1619            data1 = ret;
1620            data2 = 0;
1621        }
1622        callbacks->EventHandler(handle, appdata, OMX_EventCmdComplete,
1623                                OMX_CommandPortDisable, data2, NULL);
1624    }
1625    pthread_mutex_unlock(&ports_block);
1626}
1627
1628/* set working role */
1629OMX_ERRORTYPE ComponentBase::SetWorkingRole(const OMX_STRING role)
1630{
1631    OMX_U32 i;
1632
1633    if (state != OMX_StateUnloaded && state != OMX_StateLoaded)
1634        return OMX_ErrorIncorrectStateOperation;
1635
1636    if (!role) {
1637        working_role = NULL;
1638        return OMX_ErrorNone;
1639    }
1640
1641    for (i = 0; i < nr_roles; i++) {
1642        if (!strcmp((char *)&roles[i][0], role)) {
1643            working_role = (OMX_STRING)&roles[i][0];
1644            return OMX_ErrorNone;
1645        }
1646    }
1647
1648    LOGE("cannot find %s role in %s\n", role, name);
1649    return OMX_ErrorBadParameter;
1650}
1651
1652/* apply a working role for a component having multiple roles */
1653OMX_ERRORTYPE ComponentBase::ApplyWorkingRole(void)
1654{
1655    OMX_U32 i;
1656    OMX_ERRORTYPE ret;
1657
1658    if (state != OMX_StateUnloaded && state != OMX_StateLoaded)
1659        return OMX_ErrorIncorrectStateOperation;
1660
1661    if (!working_role)
1662        return OMX_ErrorBadParameter;
1663
1664    if (!callbacks || !appdata)
1665        return OMX_ErrorBadParameter;
1666
1667    ret = AllocatePorts();
1668    if (ret != OMX_ErrorNone) {
1669        LOGE("failed to AllocatePorts() (ret = 0x%08x)\n", ret);
1670        return ret;
1671    }
1672
1673    /* now we can access ports */
1674    for (i = 0; i < nr_ports; i++) {
1675        ports[i]->SetOwner(handle);
1676        ports[i]->SetCallbacks(handle, callbacks, appdata);
1677    }
1678
1679    return OMX_ErrorNone;
1680}
1681
1682OMX_ERRORTYPE ComponentBase::AllocatePorts(void)
1683{
1684    OMX_ERRORTYPE ret;
1685
1686    if (ports)
1687        return OMX_ErrorBadParameter;
1688
1689    ret = ComponentAllocatePorts();
1690    if (ret != OMX_ErrorNone) {
1691        LOGE("failed to %s::ComponentAllocatePorts(), ret = 0x%08x\n",
1692             name, ret);
1693        return ret;
1694    }
1695
1696    return OMX_ErrorNone;
1697}
1698
1699/* called int FreeHandle() */
1700OMX_ERRORTYPE ComponentBase::FreePorts(void)
1701{
1702    if (ports) {
1703        OMX_U32 i, this_nr_ports = this->nr_ports;
1704
1705        for (i = 0; i < this_nr_ports; i++) {
1706            if (ports[i]) {
1707                OMX_MARKTYPE *mark;
1708                /* it should be empty before this */
1709                while ((mark = ports[i]->PopMark()))
1710                    free(mark);
1711
1712                delete ports[i];
1713                ports[i] = NULL;
1714            }
1715        }
1716        delete []ports;
1717        ports = NULL;
1718    }
1719
1720    return OMX_ErrorNone;
1721}
1722
1723/* buffer processing */
1724/* implement WorkableInterface */
1725void ComponentBase::Work(void)
1726{
1727    OMX_BUFFERHEADERTYPE *buffers[nr_ports];
1728    bool retain[nr_ports];
1729    OMX_U32 i;
1730    bool avail = false;
1731
1732    pthread_mutex_lock(&ports_block);
1733
1734    avail = IsAllBufferAvailable();
1735    if (avail) {
1736        for (i = 0; i < nr_ports; i++) {
1737            buffers[i] = ports[i]->PopBuffer();
1738            retain[i] = false;
1739        }
1740
1741        ProcessorProcess(buffers, &retain[0], nr_ports);
1742        PostProcessBuffer(buffers, &retain[0], nr_ports);
1743
1744        for (i = 0; i < nr_ports; i++) {
1745            if (retain[i])
1746                ports[i]->RetainThisBuffer(buffers[i]);
1747            else
1748                ports[i]->ReturnThisBuffer(buffers[i]);
1749        }
1750    }
1751    ScheduleIfAllBufferAvailable();
1752    pthread_mutex_unlock(&ports_block);
1753}
1754
1755bool ComponentBase::IsAllBufferAvailable(void)
1756{
1757    OMX_U32 i;
1758    OMX_U32 nr_avail = 0;
1759
1760    for (i = 0; i < nr_ports; i++) {
1761        OMX_U32 length = 0;
1762
1763        if (ports[i]->IsEnabled())
1764            length = ports[i]->BufferQueueLength();
1765
1766        if (length)
1767            nr_avail++;
1768    }
1769
1770    if (nr_avail == nr_ports)
1771        return true;
1772    else
1773        return false;
1774}
1775
1776void ComponentBase::ScheduleIfAllBufferAvailable(void)
1777{
1778    bool avail;
1779
1780    avail = IsAllBufferAvailable();
1781    if (avail)
1782        bufferwork->ScheduleWork(this);
1783}
1784
1785void ComponentBase::PostProcessBuffer(OMX_BUFFERHEADERTYPE **buffers,
1786                                      bool *retain,
1787                                      OMX_U32 nr_buffers)
1788{
1789    OMX_U32 i;
1790
1791    for (i = 0; i < nr_ports; i++) {
1792        OMX_MARKTYPE *mark;
1793
1794        if (ports[i]->GetPortDirection() == OMX_DirInput) {
1795            bool is_sink_component = true;
1796            OMX_U32 j;
1797
1798            if (buffers[i]->hMarkTargetComponent) {
1799                if (buffers[i]->hMarkTargetComponent == handle) {
1800                    callbacks->EventHandler(handle, appdata, OMX_EventMark,
1801                                            0, 0, buffers[i]->pMarkData);
1802                    buffers[i]->hMarkTargetComponent = NULL;
1803                    buffers[i]->pMarkData = NULL;
1804                }
1805            }
1806
1807            for (j = 0; j < nr_ports; j++) {
1808                if (j == i)
1809                    continue;
1810
1811                if (ports[j]->GetPortDirection() == OMX_DirOutput) {
1812                    if (buffers[i]->nFlags & OMX_BUFFERFLAG_EOS) {
1813                        buffers[j]->nFlags |= OMX_BUFFERFLAG_EOS;
1814                        buffers[i]->nFlags &= ~OMX_BUFFERFLAG_EOS;
1815                        retain[i] = false;
1816                        retain[j] = false;
1817                    }
1818
1819                    if (!buffers[j]->hMarkTargetComponent) {
1820                        mark = ports[j]->PopMark();
1821                        if (mark) {
1822                            buffers[j]->hMarkTargetComponent =
1823                                mark->hMarkTargetComponent;
1824                            buffers[j]->pMarkData = mark->pMarkData;
1825                            free(mark);
1826                            mark = NULL;
1827                        }
1828
1829                        if (buffers[i]->hMarkTargetComponent) {
1830                            if (buffers[j]->hMarkTargetComponent) {
1831                                mark = (OMX_MARKTYPE *)
1832                                    malloc(sizeof(*mark));
1833                                if (mark) {
1834                                    mark->hMarkTargetComponent =
1835                                        buffers[i]->hMarkTargetComponent;
1836                                    mark->pMarkData = buffers[i]->pMarkData;
1837                                    ports[j]->PushMark(mark);
1838                                    mark = NULL;
1839                                    buffers[i]->hMarkTargetComponent = NULL;
1840                                    buffers[i]->pMarkData = NULL;
1841                                }
1842                            }
1843                            else {
1844                                buffers[j]->hMarkTargetComponent =
1845                                    buffers[i]->hMarkTargetComponent;
1846                                buffers[j]->pMarkData = buffers[i]->pMarkData;
1847                                buffers[i]->hMarkTargetComponent = NULL;
1848                                buffers[i]->pMarkData = NULL;
1849                            }
1850                        }
1851                    }
1852                    else {
1853                        if (buffers[i]->hMarkTargetComponent) {
1854                            mark = (OMX_MARKTYPE *)malloc(sizeof(*mark));
1855                            if (mark) {
1856                                mark->hMarkTargetComponent =
1857                                    buffers[i]->hMarkTargetComponent;
1858                                mark->pMarkData = buffers[i]->pMarkData;
1859                                ports[j]->PushMark(mark);
1860                                mark = NULL;
1861                                buffers[i]->hMarkTargetComponent = NULL;
1862                                buffers[i]->pMarkData = NULL;
1863                            }
1864                        }
1865                    }
1866                    is_sink_component = false;
1867                }
1868            }
1869
1870            if (is_sink_component) {
1871                if (buffers[i]->nFlags & OMX_BUFFERFLAG_EOS) {
1872                    callbacks->EventHandler(handle, appdata,
1873                                            OMX_EventBufferFlag,
1874                                            i, buffers[i]->nFlags, NULL);
1875                    retain[i] = false;
1876                }
1877            }
1878        }
1879        else if (ports[i]->GetPortDirection() == OMX_DirOutput) {
1880            bool is_source_component = true;
1881            OMX_U32 j;
1882
1883            if (buffers[i]->nFlags & OMX_BUFFERFLAG_EOS) {
1884                callbacks->EventHandler(handle, appdata,
1885                                        OMX_EventBufferFlag,
1886                                        i, buffers[i]->nFlags, NULL);
1887                retain[i] = false;
1888            }
1889
1890            for (j = 0; j < nr_ports; j++) {
1891                if (j == i)
1892                    continue;
1893
1894                if (ports[j]->GetPortDirection() == OMX_DirInput)
1895                    is_source_component = false;
1896            }
1897
1898            if (is_source_component) {
1899                if (!retain[i]) {
1900                    mark = ports[i]->PopMark();
1901                    if (mark) {
1902                        buffers[i]->hMarkTargetComponent =
1903                            mark->hMarkTargetComponent;
1904                        buffers[i]->pMarkData = mark->pMarkData;
1905                        free(mark);
1906                        mark = NULL;
1907
1908                        if (buffers[i]->hMarkTargetComponent == handle) {
1909                            callbacks->EventHandler(handle, appdata,
1910                                                    OMX_EventMark, 0, 0,
1911                                                    buffers[i]->pMarkData);
1912                            buffers[i]->hMarkTargetComponent = NULL;
1913                            buffers[i]->pMarkData = NULL;
1914                        }
1915                    }
1916                }
1917            }
1918        }
1919        else {
1920            LOGE("%s(): fatal error unknown port direction (0x%08x)\n",
1921                 __func__, ports[i]->GetPortDirection());
1922        }
1923    }
1924}
1925
1926/* processor default callbacks */
1927OMX_ERRORTYPE ComponentBase::ProcessorInit(void)
1928{
1929    return OMX_ErrorNone;
1930}
1931OMX_ERRORTYPE ComponentBase::ProcessorDeinit(void)
1932{
1933    return OMX_ErrorNone;
1934}
1935
1936OMX_ERRORTYPE ComponentBase::ProcessorStart(void)
1937{
1938    return OMX_ErrorNone;
1939}
1940
1941OMX_ERRORTYPE ComponentBase::ProcessorStop(void)
1942{
1943    return OMX_ErrorNone;
1944}
1945
1946OMX_ERRORTYPE ComponentBase::ProcessorPause(void)
1947{
1948    return OMX_ErrorNone;
1949}
1950
1951OMX_ERRORTYPE ComponentBase::ProcessorResume(void)
1952{
1953    return OMX_ErrorNone;
1954}
1955
1956/* end of processor callbacks */
1957
1958/* helper for derived class */
1959const OMX_STRING ComponentBase::GetWorkingRole(void)
1960{
1961    return &working_role[0];
1962}
1963
1964const OMX_COMPONENTTYPE *ComponentBase::GetComponentHandle(void)
1965{
1966    return handle;
1967}
1968
1969void ComponentBase::DumpBuffer(const OMX_BUFFERHEADERTYPE *bufferheader,
1970                               bool dumpdata)
1971{
1972    OMX_U8 *pbuffer = bufferheader->pBuffer, *p;
1973    OMX_U32 offset = bufferheader->nOffset;
1974    OMX_U32 alloc_len = bufferheader->nAllocLen;
1975    OMX_U32 filled_len =  bufferheader->nFilledLen;
1976    OMX_U32 left = filled_len, oneline;
1977    OMX_U32 index = 0, i;
1978    /* 0x%04lx:  %02x %02x .. (n = 16)\n\0 */
1979    char prbuffer[8 + 3 * 0x10 + 2], *pp;
1980    OMX_U32 prbuffer_len;
1981
1982    LOGD("Componant %s DumpBuffer\n", name);
1983    LOGD("%s port index = %lu",
1984         (bufferheader->nInputPortIndex != 0x7fffffff) ? "input" : "output",
1985         (bufferheader->nInputPortIndex != 0x7fffffff) ?
1986         bufferheader->nInputPortIndex : bufferheader->nOutputPortIndex);
1987    LOGD("nAllocLen = %lu, nOffset = %lu, nFilledLen = %lu\n",
1988         alloc_len, offset, filled_len);
1989    LOGD("nTimeStamp = %lld, nTickCount = %lu",
1990         bufferheader->nTimeStamp,
1991         bufferheader->nTickCount);
1992    LOGD("nFlags = 0x%08lx\n", bufferheader->nFlags);
1993
1994    if (!pbuffer || !alloc_len || !filled_len)
1995        return;
1996
1997    if (offset + filled_len > alloc_len)
1998        return;
1999
2000    if (!dumpdata)
2001        return;
2002
2003    p = pbuffer + offset;
2004    while (left) {
2005        oneline = left > 0x10 ? 0x10 : left; /* 16 items per 1 line */
2006        pp += sprintf(pp, "0x%04lx: ", index);
2007        for (i = 0; i < oneline; i++)
2008            pp += sprintf(pp, " %02x", *(p + i));
2009        pp += sprintf(pp, "\n");
2010        *pp = '\0';
2011
2012        index += 0x10;
2013        p += oneline;
2014        left -= oneline;
2015
2016        pp = &prbuffer[0];
2017        LOGD("%s", pp);
2018    }
2019}
2020
2021/* end of component methods & helpers */
2022
2023/*
2024 * omx header manipuation
2025 */
2026void ComponentBase::SetTypeHeader(OMX_PTR type, OMX_U32 size)
2027{
2028    OMX_U32 *nsize;
2029    OMX_VERSIONTYPE *nversion;
2030
2031    if (!type)
2032        return;
2033
2034    nsize = (OMX_U32 *)type;
2035    nversion = (OMX_VERSIONTYPE *)((OMX_U8 *)type + sizeof(OMX_U32));
2036
2037    *nsize = size;
2038    nversion->nVersion = OMX_SPEC_VERSION;
2039}
2040
2041OMX_ERRORTYPE ComponentBase::CheckTypeHeader(const OMX_PTR type, OMX_U32 size)
2042{
2043    OMX_U32 *nsize;
2044    OMX_VERSIONTYPE *nversion;
2045
2046    if (!type)
2047        return OMX_ErrorBadParameter;
2048
2049    nsize = (OMX_U32 *)type;
2050    nversion = (OMX_VERSIONTYPE *)((OMX_U8 *)type + sizeof(OMX_U32));
2051
2052    if (*nsize != size)
2053        return OMX_ErrorBadParameter;
2054
2055    if (nversion->nVersion != OMX_SPEC_VERSION)
2056        return OMX_ErrorVersionMismatch;
2057
2058    return OMX_ErrorNone;
2059}
2060
2061/* end of ComponentBase */
2062