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