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