componentbase.cpp revision 3e70358f4893dffa18a9edf60e02fe4c017328de
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    case OMX_CommandMarkBuffer:
421        /*
422         * Todo
423         */
424        //break;
425    default:
426        LOGE("command %d not supported\n", Cmd);
427        return OMX_ErrorUnsupportedIndex;
428    }
429
430    cmd = (struct cmd_s *)malloc(sizeof(*cmd));
431    if (!cmd)
432        return OMX_ErrorInsufficientResources;
433
434    cmd->cmd = Cmd;
435    cmd->param1 = nParam1;
436    cmd->cmddata = pCmdData;
437
438    return cmdwork->PushCmdQueue(cmd);
439}
440
441OMX_ERRORTYPE ComponentBase::GetParameter(
442    OMX_IN  OMX_HANDLETYPE hComponent,
443    OMX_IN  OMX_INDEXTYPE nParamIndex,
444    OMX_INOUT OMX_PTR pComponentParameterStructure)
445{
446    ComponentBase *cbase;
447
448    if (!hComponent)
449        return OMX_ErrorBadParameter;
450
451    cbase = static_cast<ComponentBase *>
452        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
453    if (!cbase)
454        return OMX_ErrorBadParameter;
455
456    return cbase->CBaseGetParameter(hComponent, nParamIndex,
457                                    pComponentParameterStructure);
458}
459
460OMX_ERRORTYPE ComponentBase::CBaseGetParameter(
461    OMX_IN  OMX_HANDLETYPE hComponent,
462    OMX_IN  OMX_INDEXTYPE nParamIndex,
463    OMX_INOUT OMX_PTR pComponentParameterStructure)
464{
465    OMX_ERRORTYPE ret = OMX_ErrorNone;
466
467    if (hComponent != handle)
468        return OMX_ErrorBadParameter;
469
470    switch (nParamIndex) {
471    case OMX_IndexParamAudioInit:
472    case OMX_IndexParamVideoInit:
473    case OMX_IndexParamImageInit:
474    case OMX_IndexParamOtherInit: {
475        OMX_PORT_PARAM_TYPE *p =
476            (OMX_PORT_PARAM_TYPE *)pComponentParameterStructure;
477
478        ret = CheckTypeHeader(p, sizeof(*p));
479        if (ret != OMX_ErrorNone)
480            return ret;
481
482        memcpy(p, &portparam, sizeof(*p));
483        break;
484    }
485    case OMX_IndexParamPortDefinition: {
486        OMX_PARAM_PORTDEFINITIONTYPE *p =
487            (OMX_PARAM_PORTDEFINITIONTYPE *)pComponentParameterStructure;
488        OMX_U32 index = p->nPortIndex;
489        PortBase *port = NULL;
490
491        ret = CheckTypeHeader(p, sizeof(*p));
492        if (ret != OMX_ErrorNone)
493            return ret;
494
495        if (index < nr_ports)
496            port = ports[index];
497
498        if (!port)
499            return OMX_ErrorBadParameter;
500
501        memcpy(p, port->GetPortParam(), sizeof(*p));
502        break;
503    }
504    case OMX_IndexParamAudioPortFormat: {
505        OMX_AUDIO_PARAM_PORTFORMATTYPE *p =
506            (OMX_AUDIO_PARAM_PORTFORMATTYPE *)pComponentParameterStructure;
507        OMX_U32 index = p->nPortIndex;
508        PortBase *port = NULL;
509
510        ret = CheckTypeHeader(p, sizeof(*p));
511        if (ret != OMX_ErrorNone)
512            return ret;
513
514        if (index < nr_ports)
515            port = ports[index];
516
517        if (!port)
518            return OMX_ErrorBadParameter;
519
520        memcpy(p, port->GetAudioPortParam(), sizeof(*p));
521        break;
522    }
523    case OMX_IndexParamCompBufferSupplier:
524        /*
525         * Todo
526         */
527
528        ret = OMX_ErrorUnsupportedIndex;
529        break;
530    default:
531        ret = ComponentGetParameter(nParamIndex, pComponentParameterStructure);
532    } /* switch */
533
534    return ret;
535}
536
537OMX_ERRORTYPE ComponentBase::SetParameter(
538    OMX_IN  OMX_HANDLETYPE hComponent,
539    OMX_IN  OMX_INDEXTYPE nIndex,
540    OMX_IN  OMX_PTR pComponentParameterStructure)
541{
542    ComponentBase *cbase;
543
544    if (!hComponent)
545        return OMX_ErrorBadParameter;
546
547    cbase = static_cast<ComponentBase *>
548        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
549    if (!cbase)
550        return OMX_ErrorBadParameter;
551
552    return cbase->CBaseSetParameter(hComponent, nIndex,
553                                    pComponentParameterStructure);
554}
555
556OMX_ERRORTYPE ComponentBase::CBaseSetParameter(
557    OMX_IN  OMX_HANDLETYPE hComponent,
558    OMX_IN  OMX_INDEXTYPE nIndex,
559    OMX_IN  OMX_PTR pComponentParameterStructure)
560{
561    OMX_ERRORTYPE ret = OMX_ErrorNone;
562
563    if (hComponent != handle)
564        return OMX_ErrorBadParameter;
565
566    switch (nIndex) {
567    case OMX_IndexParamAudioInit:
568    case OMX_IndexParamVideoInit:
569    case OMX_IndexParamImageInit:
570    case OMX_IndexParamOtherInit: {
571        OMX_PORT_PARAM_TYPE *p = (OMX_PORT_PARAM_TYPE *)
572            pComponentParameterStructure;
573
574        ret = CheckTypeHeader(p, sizeof(*p));
575        if (ret != OMX_ErrorNone)
576            return ret;
577
578        memcpy(&portparam, p, sizeof(*p));
579        break;
580    }
581    case OMX_IndexParamPortDefinition: {
582        OMX_PARAM_PORTDEFINITIONTYPE *p =
583            (OMX_PARAM_PORTDEFINITIONTYPE *)pComponentParameterStructure;
584        OMX_U32 index = p->nPortIndex;
585        PortBase *port = NULL;
586
587        ret = CheckTypeHeader(p, sizeof(*p));
588        if (ret != OMX_ErrorNone)
589            return ret;
590
591        if (index < nr_ports)
592            port = ports[index];
593
594        if (!port)
595            return OMX_ErrorBadParameter;
596
597        port->SetPortParam(p);
598        break;
599    }
600    case OMX_IndexParamAudioPortFormat: {
601        OMX_AUDIO_PARAM_PORTFORMATTYPE *p =
602            (OMX_AUDIO_PARAM_PORTFORMATTYPE *)pComponentParameterStructure;
603        OMX_U32 index = p->nPortIndex;
604        PortBase *port = NULL;
605
606        ret = CheckTypeHeader(p, sizeof(*p));
607        if (ret != OMX_ErrorNone)
608            return ret;
609
610        if (index < nr_ports)
611            port = ports[index];
612
613        if (!port)
614            return OMX_ErrorBadParameter;
615
616        port->SetAudioPortParam(p);
617        break;
618    }
619    case OMX_IndexParamCompBufferSupplier:
620        /*
621         * Todo
622         */
623
624        ret = OMX_ErrorUnsupportedIndex;
625        break;
626    case OMX_IndexParamStandardComponentRole: {
627        OMX_PARAM_COMPONENTROLETYPE *p =
628            (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure;
629
630        ret = CheckTypeHeader(p, sizeof(*p));
631        if (ret != OMX_ErrorNone)
632            return ret;
633
634        ret = SetWorkingRole((OMX_STRING)p->cRole);
635        if (ret != OMX_ErrorNone)
636            return ret;
637
638        if (ports)
639            FreePorts();
640
641        ret = ApplyWorkingRole();
642        if (ret != OMX_ErrorNone) {
643            SetWorkingRole(NULL);
644            return ret;
645        }
646        break;
647    }
648    default:
649        ret = ComponentSetParameter(nIndex, pComponentParameterStructure);
650    } /* switch */
651
652    return ret;
653}
654
655OMX_ERRORTYPE ComponentBase::GetConfig(
656    OMX_IN  OMX_HANDLETYPE hComponent,
657    OMX_IN  OMX_INDEXTYPE nIndex,
658    OMX_INOUT OMX_PTR pComponentConfigStructure)
659{
660    ComponentBase *cbase;
661
662    if (!hComponent)
663        return OMX_ErrorBadParameter;
664
665    cbase = static_cast<ComponentBase *>
666        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
667    if (!cbase)
668        return OMX_ErrorBadParameter;
669
670    return cbase->CBaseGetConfig(hComponent, nIndex,
671                                 pComponentConfigStructure);
672}
673
674OMX_ERRORTYPE ComponentBase::CBaseGetConfig(
675    OMX_IN  OMX_HANDLETYPE hComponent,
676    OMX_IN  OMX_INDEXTYPE nIndex,
677    OMX_INOUT OMX_PTR pComponentConfigStructure)
678{
679    OMX_ERRORTYPE ret;
680
681    if (hComponent != handle)
682        return OMX_ErrorBadParameter;
683
684    switch (nIndex) {
685    default:
686        ret = ComponentGetConfig(nIndex, pComponentConfigStructure);
687    }
688
689    return ret;
690}
691
692OMX_ERRORTYPE ComponentBase::SetConfig(
693    OMX_IN  OMX_HANDLETYPE hComponent,
694    OMX_IN  OMX_INDEXTYPE nIndex,
695    OMX_IN  OMX_PTR pComponentConfigStructure)
696{
697    ComponentBase *cbase;
698
699    if (!hComponent)
700        return OMX_ErrorBadParameter;
701
702    cbase = static_cast<ComponentBase *>
703        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
704    if (!cbase)
705        return OMX_ErrorBadParameter;
706
707    return cbase->CBaseSetConfig(hComponent, nIndex,
708                                 pComponentConfigStructure);
709}
710
711OMX_ERRORTYPE ComponentBase::CBaseSetConfig(
712    OMX_IN  OMX_HANDLETYPE hComponent,
713    OMX_IN  OMX_INDEXTYPE nIndex,
714    OMX_IN  OMX_PTR pComponentConfigStructure)
715{
716    OMX_ERRORTYPE ret;
717
718    if (hComponent != handle)
719        return OMX_ErrorBadParameter;
720
721    switch (nIndex) {
722    default:
723        ret = ComponentSetConfig(nIndex, pComponentConfigStructure);
724    }
725
726    return ret;
727}
728
729OMX_ERRORTYPE ComponentBase::GetExtensionIndex(
730    OMX_IN  OMX_HANDLETYPE hComponent,
731    OMX_IN  OMX_STRING cParameterName,
732    OMX_OUT OMX_INDEXTYPE* pIndexType)
733{
734    ComponentBase *cbase;
735
736    if (!hComponent)
737        return OMX_ErrorBadParameter;
738
739    cbase = static_cast<ComponentBase *>
740        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
741    if (!cbase)
742        return OMX_ErrorBadParameter;
743
744    return cbase->CBaseGetExtensionIndex(hComponent, cParameterName,
745                                         pIndexType);
746}
747
748OMX_ERRORTYPE ComponentBase::CBaseGetExtensionIndex(
749    OMX_IN  OMX_HANDLETYPE hComponent,
750    OMX_IN  OMX_STRING cParameterName,
751    OMX_OUT OMX_INDEXTYPE* pIndexType)
752{
753    /*
754     * Todo
755     */
756
757    return OMX_ErrorNotImplemented;
758}
759
760OMX_ERRORTYPE ComponentBase::GetState(
761    OMX_IN  OMX_HANDLETYPE hComponent,
762    OMX_OUT OMX_STATETYPE* pState)
763{
764    ComponentBase *cbase;
765
766    if (!hComponent)
767        return OMX_ErrorBadParameter;
768
769    cbase = static_cast<ComponentBase *>
770        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
771    if (!cbase)
772        return OMX_ErrorBadParameter;
773
774    return cbase->CBaseGetState(hComponent, pState);
775}
776
777OMX_ERRORTYPE ComponentBase::CBaseGetState(
778    OMX_IN  OMX_HANDLETYPE hComponent,
779    OMX_OUT OMX_STATETYPE* pState)
780{
781    if (hComponent != handle)
782        return OMX_ErrorBadParameter;
783
784    *pState = state;
785    return OMX_ErrorNone;
786}
787
788OMX_ERRORTYPE ComponentBase::ComponentTunnelRequest(
789    OMX_IN  OMX_HANDLETYPE hComponent,
790    OMX_IN  OMX_U32 nPort,
791    OMX_IN  OMX_HANDLETYPE hTunneledComponent,
792    OMX_IN  OMX_U32 nTunneledPort,
793    OMX_INOUT  OMX_TUNNELSETUPTYPE* pTunnelSetup)
794{
795    ComponentBase *cbase;
796
797    if (!hComponent)
798        return OMX_ErrorBadParameter;
799
800    cbase = static_cast<ComponentBase *>
801        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
802    if (!cbase)
803        return OMX_ErrorBadParameter;
804
805    return cbase->CBaseComponentTunnelRequest(hComponent, nPort,
806                                              hTunneledComponent,
807                                              nTunneledPort, pTunnelSetup);
808}
809
810OMX_ERRORTYPE ComponentBase::CBaseComponentTunnelRequest(
811    OMX_IN  OMX_HANDLETYPE hComp,
812    OMX_IN  OMX_U32 nPort,
813    OMX_IN  OMX_HANDLETYPE hTunneledComp,
814    OMX_IN  OMX_U32 nTunneledPort,
815    OMX_INOUT  OMX_TUNNELSETUPTYPE* pTunnelSetup)
816{
817    /*
818     * Todo
819     */
820
821    return OMX_ErrorNotImplemented;
822}
823
824OMX_ERRORTYPE ComponentBase::UseBuffer(
825    OMX_IN OMX_HANDLETYPE hComponent,
826    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr,
827    OMX_IN OMX_U32 nPortIndex,
828    OMX_IN OMX_PTR pAppPrivate,
829    OMX_IN OMX_U32 nSizeBytes,
830    OMX_IN OMX_U8 *pBuffer)
831{
832    ComponentBase *cbase;
833
834    if (!hComponent)
835        return OMX_ErrorBadParameter;
836
837    cbase = static_cast<ComponentBase *>
838        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
839    if (!cbase)
840        return OMX_ErrorBadParameter;
841
842    return cbase->CBaseUseBuffer(hComponent, ppBufferHdr, nPortIndex,
843                                 pAppPrivate, nSizeBytes, pBuffer);
844}
845
846OMX_ERRORTYPE ComponentBase::CBaseUseBuffer(
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    PortBase *port = NULL;
855    OMX_ERRORTYPE ret;
856
857    if (hComponent != handle)
858        return OMX_ErrorBadParameter;
859
860    if (!ppBufferHdr)
861        return OMX_ErrorBadParameter;
862    *ppBufferHdr = NULL;
863
864    if (!pBuffer)
865        return OMX_ErrorBadParameter;
866
867    if (ports)
868        if (nPortIndex < nr_ports)
869            port = ports[nPortIndex];
870
871    if (!port)
872        return OMX_ErrorBadParameter;
873
874    if (port->IsEnabled()) {
875        if (state != OMX_StateLoaded && state != OMX_StateWaitForResources)
876            return OMX_ErrorIncorrectStateOperation;
877    }
878
879    return port->UseBuffer(ppBufferHdr, nPortIndex, pAppPrivate, nSizeBytes,
880                           pBuffer);
881}
882
883OMX_ERRORTYPE ComponentBase::AllocateBuffer(
884    OMX_IN OMX_HANDLETYPE hComponent,
885    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer,
886    OMX_IN OMX_U32 nPortIndex,
887    OMX_IN OMX_PTR pAppPrivate,
888    OMX_IN OMX_U32 nSizeBytes)
889{
890    ComponentBase *cbase;
891
892    if (!hComponent)
893        return OMX_ErrorBadParameter;
894
895    cbase = static_cast<ComponentBase *>
896        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
897    if (!cbase)
898        return OMX_ErrorBadParameter;
899
900    return cbase->CBaseAllocateBuffer(hComponent, ppBuffer, nPortIndex,
901                                      pAppPrivate, nSizeBytes);
902}
903
904OMX_ERRORTYPE ComponentBase::CBaseAllocateBuffer(
905    OMX_IN OMX_HANDLETYPE hComponent,
906    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer,
907    OMX_IN OMX_U32 nPortIndex,
908    OMX_IN OMX_PTR pAppPrivate,
909    OMX_IN OMX_U32 nSizeBytes)
910{
911    PortBase *port = NULL;
912    OMX_ERRORTYPE ret;
913
914    if (hComponent != handle)
915        return OMX_ErrorBadParameter;
916
917    if (!ppBuffer)
918        return OMX_ErrorBadParameter;
919    *ppBuffer = NULL;
920
921    if (ports)
922        if (nPortIndex < nr_ports)
923            port = ports[nPortIndex];
924
925    if (!port)
926        return OMX_ErrorBadParameter;
927
928    if (port->IsEnabled()) {
929        if (state != OMX_StateLoaded && state != OMX_StateWaitForResources)
930            return OMX_ErrorIncorrectStateOperation;
931    }
932
933    return port->AllocateBuffer(ppBuffer, nPortIndex, pAppPrivate, nSizeBytes);
934}
935
936OMX_ERRORTYPE ComponentBase::FreeBuffer(
937    OMX_IN  OMX_HANDLETYPE hComponent,
938    OMX_IN  OMX_U32 nPortIndex,
939    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
940{
941    ComponentBase *cbase;
942
943    if (!hComponent)
944        return OMX_ErrorBadParameter;
945
946    cbase = static_cast<ComponentBase *>
947        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
948    if (!cbase)
949        return OMX_ErrorBadParameter;
950
951    return cbase->CBaseFreeBuffer(hComponent, nPortIndex, pBuffer);
952}
953
954OMX_ERRORTYPE ComponentBase::CBaseFreeBuffer(
955    OMX_IN  OMX_HANDLETYPE hComponent,
956    OMX_IN  OMX_U32 nPortIndex,
957    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
958{
959    PortBase *port = NULL;
960    OMX_ERRORTYPE ret;
961
962    if (hComponent != handle)
963        return OMX_ErrorBadParameter;
964
965    if (!pBuffer)
966        return OMX_ErrorBadParameter;
967
968    if (ports)
969        if (nPortIndex < nr_ports)
970            port = ports[nPortIndex];
971
972    if (!port)
973        return OMX_ErrorBadParameter;
974
975    return port->FreeBuffer(nPortIndex, pBuffer);
976}
977
978OMX_ERRORTYPE ComponentBase::EmptyThisBuffer(
979    OMX_IN  OMX_HANDLETYPE hComponent,
980    OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer)
981{
982    ComponentBase *cbase;
983
984    if (!hComponent)
985        return OMX_ErrorBadParameter;
986
987    cbase = static_cast<ComponentBase *>
988        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
989    if (!cbase)
990        return OMX_ErrorBadParameter;
991
992    return cbase->CBaseEmptyThisBuffer(hComponent, pBuffer);
993}
994
995OMX_ERRORTYPE ComponentBase::CBaseEmptyThisBuffer(
996    OMX_IN  OMX_HANDLETYPE hComponent,
997    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
998{
999    PortBase *port = NULL;
1000    OMX_U32 port_index;
1001    OMX_ERRORTYPE ret;
1002
1003    if ((hComponent != handle) || !pBuffer)
1004        return OMX_ErrorBadParameter;
1005
1006    port_index = pBuffer->nInputPortIndex;
1007    if (port_index == (OMX_U32)-1)
1008        return OMX_ErrorBadParameter;
1009
1010    if (ports)
1011        if (port_index < nr_ports)
1012            port = ports[port_index];
1013
1014    if (!port)
1015        return OMX_ErrorBadParameter;
1016
1017    ret = port->PushThisBuffer(pBuffer);
1018    if (ret == OMX_ErrorNone)
1019        bufferwork->ScheduleWork(this);
1020
1021    return ret;
1022}
1023
1024OMX_ERRORTYPE ComponentBase::FillThisBuffer(
1025    OMX_IN  OMX_HANDLETYPE hComponent,
1026    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
1027{
1028    ComponentBase *cbase;
1029
1030    if (!hComponent)
1031        return OMX_ErrorBadParameter;
1032
1033    cbase = static_cast<ComponentBase *>
1034        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
1035    if (!cbase)
1036        return OMX_ErrorBadParameter;
1037
1038    return cbase->CBaseFillThisBuffer(hComponent, pBuffer);
1039}
1040
1041OMX_ERRORTYPE ComponentBase::CBaseFillThisBuffer(
1042    OMX_IN  OMX_HANDLETYPE hComponent,
1043    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
1044{
1045    PortBase *port = NULL;
1046    OMX_U32 port_index;
1047    OMX_ERRORTYPE ret;
1048
1049    if ((hComponent != handle) || !pBuffer)
1050        return OMX_ErrorBadParameter;
1051
1052    port_index = pBuffer->nOutputPortIndex;
1053    if (port_index == (OMX_U32)-1)
1054        return OMX_ErrorBadParameter;
1055
1056    if (ports)
1057        if (port_index < nr_ports)
1058            port = ports[port_index];
1059
1060    if (!port)
1061        return OMX_ErrorBadParameter;
1062
1063    ret = port->PushThisBuffer(pBuffer);
1064    if (ret == OMX_ErrorNone)
1065        bufferwork->ScheduleWork(this);
1066
1067    return ret;
1068}
1069
1070OMX_ERRORTYPE ComponentBase::SetCallbacks(
1071    OMX_IN  OMX_HANDLETYPE hComponent,
1072    OMX_IN  OMX_CALLBACKTYPE* pCallbacks,
1073    OMX_IN  OMX_PTR pAppData)
1074{
1075    ComponentBase *cbase;
1076
1077    if (!hComponent)
1078        return OMX_ErrorBadParameter;
1079
1080    cbase = static_cast<ComponentBase *>
1081        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
1082    if (!cbase)
1083        return OMX_ErrorBadParameter;
1084
1085    return cbase->CBaseSetCallbacks(hComponent, pCallbacks, pAppData);
1086}
1087
1088OMX_ERRORTYPE ComponentBase::CBaseSetCallbacks(
1089    OMX_IN  OMX_HANDLETYPE hComponent,
1090    OMX_IN  OMX_CALLBACKTYPE *pCallbacks,
1091    OMX_IN  OMX_PTR pAppData)
1092{
1093    if (hComponent != handle)
1094        return OMX_ErrorBadParameter;
1095
1096    appdata = pAppData;
1097    callbacks = pCallbacks;
1098
1099    return OMX_ErrorNone;
1100}
1101
1102OMX_ERRORTYPE ComponentBase::ComponentDeInit(
1103    OMX_IN  OMX_HANDLETYPE hComponent)
1104{
1105    ComponentBase *cbase;
1106
1107    if (!hComponent)
1108        return OMX_ErrorBadParameter;
1109
1110    cbase = static_cast<ComponentBase *>
1111        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
1112    if (!cbase)
1113        return OMX_ErrorBadParameter;
1114
1115    return cbase->CBaseComponentDeInit(hComponent);
1116}
1117
1118OMX_ERRORTYPE ComponentBase::CBaseComponentDeInit(
1119    OMX_IN  OMX_HANDLETYPE hComponent)
1120{
1121    /*
1122     * Todo
1123     */
1124
1125    return OMX_ErrorNotImplemented;
1126}
1127
1128OMX_ERRORTYPE ComponentBase::UseEGLImage(
1129    OMX_IN OMX_HANDLETYPE hComponent,
1130    OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
1131    OMX_IN OMX_U32 nPortIndex,
1132    OMX_IN OMX_PTR pAppPrivate,
1133    OMX_IN void* eglImage)
1134{
1135    ComponentBase *cbase;
1136
1137    if (!hComponent)
1138        return OMX_ErrorBadParameter;
1139
1140    cbase = static_cast<ComponentBase *>
1141        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
1142    if (!cbase)
1143        return OMX_ErrorBadParameter;
1144
1145    return cbase->CBaseUseEGLImage(hComponent, ppBufferHdr, nPortIndex,
1146                                   pAppPrivate, eglImage);
1147}
1148
1149OMX_ERRORTYPE ComponentBase::CBaseUseEGLImage(
1150    OMX_IN OMX_HANDLETYPE hComponent,
1151    OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
1152    OMX_IN OMX_U32 nPortIndex,
1153    OMX_IN OMX_PTR pAppPrivate,
1154    OMX_IN void* eglImage)
1155{
1156    /*
1157     * Todo
1158     */
1159
1160    return OMX_ErrorNotImplemented;
1161}
1162
1163OMX_ERRORTYPE ComponentBase::ComponentRoleEnum(
1164    OMX_IN OMX_HANDLETYPE hComponent,
1165    OMX_OUT OMX_U8 *cRole,
1166    OMX_IN OMX_U32 nIndex)
1167{
1168    ComponentBase *cbase;
1169
1170    if (!hComponent)
1171        return OMX_ErrorBadParameter;
1172
1173    cbase = static_cast<ComponentBase *>
1174        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
1175    if (!cbase)
1176        return OMX_ErrorBadParameter;
1177
1178    return cbase->CBaseComponentRoleEnum(hComponent, cRole, nIndex);
1179}
1180
1181OMX_ERRORTYPE ComponentBase::CBaseComponentRoleEnum(
1182    OMX_IN OMX_HANDLETYPE hComponent,
1183    OMX_OUT OMX_U8 *cRole,
1184    OMX_IN OMX_U32 nIndex)
1185{
1186    if (hComponent != (OMX_HANDLETYPE *)this->handle)
1187        return OMX_ErrorBadParameter;
1188
1189    if (nIndex > nr_roles)
1190        return OMX_ErrorBadParameter;
1191
1192    strncpy((char *)cRole, (const char *)roles[nIndex],
1193            OMX_MAX_STRINGNAME_SIZE);
1194    return OMX_ErrorNone;
1195}
1196
1197/* implement CmdHandlerInterface */
1198void ComponentBase::CmdHandler(struct cmd_s *cmd)
1199{
1200    switch (cmd->cmd) {
1201    case OMX_CommandStateSet: {
1202        OMX_STATETYPE transition = (OMX_STATETYPE)cmd->param1;
1203
1204        TransState(transition);
1205        break;
1206    }
1207    case OMX_CommandFlush:
1208        /*
1209         * Todo
1210         */
1211        break;
1212    case OMX_CommandPortDisable:
1213        /*
1214         * Todo
1215         */
1216        break;
1217    case OMX_CommandPortEnable:
1218        /*
1219         * Todo
1220         */
1221        break;
1222    case OMX_CommandMarkBuffer:
1223        /*
1224         * Todo
1225         */
1226        break;
1227    } /* switch */
1228}
1229
1230/*
1231 * SendCommand:OMX_CommandStateSet
1232 * called in CmdHandler or called in other parts of component for reporting
1233 * internal error (OMX_StateInvalid).
1234 */
1235/*
1236 * Todo
1237 *   Resource Management (OMX_StateWaitForResources)
1238 *   for now, we never notify OMX_ErrorInsufficientResources,
1239 *   so IL client doesn't try to set component' state OMX_StateWaitForResources
1240 */
1241static const char *state_name[OMX_StateWaitForResources + 1] = {
1242    "OMX_StateInvalid",
1243    "OMX_StateLoaded",
1244    "OMX_StateIdle",
1245    "OMX_StateExecuting",
1246    "OMX_StatePause",
1247    "OMX_StateWaitForResources",
1248};
1249
1250static inline const char *GetStateName(OMX_STATETYPE state)
1251{
1252    if (state > OMX_StateWaitForResources)
1253        return "UnKnown";
1254
1255    return state_name[state];
1256}
1257
1258void ComponentBase::TransState(OMX_STATETYPE transition)
1259{
1260    OMX_STATETYPE current = this->state;
1261    OMX_EVENTTYPE event;
1262    OMX_U32 data1, data2;
1263    OMX_ERRORTYPE ret;
1264
1265    LOGD("current state = %s, transition state = %s\n",
1266         GetStateName(current), GetStateName(transition));
1267
1268    /* same state */
1269    if (current == transition) {
1270        ret = OMX_ErrorSameState;
1271        goto notify_event;
1272    }
1273
1274    /* invalid state */
1275    if (current == OMX_StateInvalid) {
1276        ret = OMX_ErrorInvalidState;
1277        goto notify_event;
1278    }
1279
1280    if (transition == OMX_StateLoaded)
1281        ret = TransStateToLoaded(current);
1282    else if (transition == OMX_StateIdle)
1283        ret = TransStateToIdle(current);
1284    else if (transition == OMX_StateExecuting)
1285        ret = TransStateToExecuting(current);
1286    else if (transition == OMX_StatePause)
1287        ret = TransStateToPause(current);
1288    else if (transition == OMX_StateInvalid)
1289        ret = TransStateToInvalid(current);
1290    else if (transition == OMX_StateWaitForResources)
1291        ret = TransStateToWaitForResources(current);
1292    else
1293        ret = OMX_ErrorIncorrectStateTransition;
1294
1295notify_event:
1296    if (ret == OMX_ErrorNone) {
1297        event = OMX_EventCmdComplete;
1298        data1 = OMX_CommandStateSet;
1299        data2 = transition;
1300
1301        state = transition;
1302        LOGD("transition from %s to %s completed\n",
1303             GetStateName(current), GetStateName(transition));
1304    }
1305    else {
1306        event = OMX_EventError;
1307        data1 = ret;
1308        data2 = 0;
1309
1310        if (transition == OMX_StateInvalid) {
1311            state = transition;
1312            LOGD("transition from %s to %s completed\n",
1313                 GetStateName(current), GetStateName(transition));
1314        }
1315    }
1316
1317    callbacks->EventHandler(handle, appdata, event, data1, data2, NULL);
1318
1319    /* WaitForResources workaround */
1320    if (ret == OMX_ErrorNone && transition == OMX_StateWaitForResources)
1321        callbacks->EventHandler(handle, appdata,
1322                                OMX_EventResourcesAcquired, 0, 0, NULL);
1323}
1324
1325inline OMX_ERRORTYPE ComponentBase::TransStateToLoaded(OMX_STATETYPE current)
1326{
1327    OMX_ERRORTYPE ret;
1328
1329    if (current == OMX_StateIdle) {
1330        /*
1331         * Todo
1332         *   1. waits for completion of deallocation on each port
1333         *      wokeup by FreeBuffer()
1334         *   2. deinitialize buffer process work
1335         *   3. deinitialize component's internal processor
1336         *      (ex. deinitialize sw/hw codec)
1337         */
1338        OMX_U32 i;
1339
1340        for (i = 0; i < nr_ports; i++)
1341            ports[i]->WaitPortBufferCompletion();
1342
1343        ret = OMX_ErrorNone;
1344    }
1345    else if (current == OMX_StateWaitForResources) {
1346        LOGE("state transition's requested from WaitForResources to "
1347             "Loaded\n");
1348
1349        /*
1350         * from WaitForResources to Loaded considered from Loaded to Loaded.
1351         * do nothing
1352         */
1353
1354        ret = OMX_ErrorNone;
1355    }
1356    else
1357        ret = OMX_ErrorIncorrectStateOperation;
1358
1359    return ret;
1360}
1361
1362inline OMX_ERRORTYPE ComponentBase::TransStateToIdle(OMX_STATETYPE current)
1363{
1364    OMX_ERRORTYPE ret;
1365
1366    if (current == OMX_StateLoaded) {
1367        /*
1368         * Todo
1369         *   1. waits for completion of allocation on each port.
1370         *      wokeup by Allocate/UseBuffer()
1371         *   2. initialize buffer process work.
1372         *   3. initialize component's internal processor.
1373         *      (ex. initialize sw/hw codec)
1374         */
1375        OMX_U32 i;
1376
1377        for (i = 0; i < nr_ports; i++)
1378            ports[i]->WaitPortBufferCompletion();
1379
1380        ret = OMX_ErrorNone;
1381    }
1382    else if (current == OMX_StateExecuting) {
1383        /*
1384         * Todo
1385         *   1. returns all buffers to thier suppliers.         !
1386         *      call Fill/EmptyBufferDone() for all ports
1387         *   2. stop buffer process work                        !
1388         *   3. stop component's internal processor
1389         */
1390        OMX_U32 i;
1391
1392        pthread_mutex_lock(&ports_block);
1393        for (i = 0; i < nr_ports; i++) {
1394            ports[i]->FlushPort();
1395        }
1396        pthread_mutex_unlock(&ports_block);
1397
1398        bufferwork->StopWork();
1399
1400        ret = OMX_ErrorNone;
1401    }
1402    else if (current == OMX_StatePause) {
1403        /*
1404         * Todo
1405         *   1. returns all buffers to thier suppliers.         !
1406         *      call Fill/EmptyBufferDone() for all ports
1407         *   2. discard queued work, stop buffer process work   !
1408         *   3. stop component's internal processor
1409         */
1410        OMX_U32 i;
1411
1412        pthread_mutex_lock(&ports_block);
1413        for (i = 0; i < nr_ports; i++) {
1414            ports[i]->FlushPort();
1415        }
1416        pthread_mutex_unlock(&ports_block);
1417
1418        bufferwork->CancelScheduledWork(this);
1419        bufferwork->StopWork();
1420
1421        ret = OMX_ErrorNone;
1422    }
1423    else if (current == OMX_StateWaitForResources) {
1424        LOGE("state transition's requested from WaitForResources to Idle\n");
1425
1426        /* same as Loaded to Idle BUT DO NOTHING for now */
1427
1428        ret = OMX_ErrorNone;
1429    }
1430    else
1431        ret = OMX_ErrorIncorrectStateOperation;
1432
1433    return ret;
1434}
1435
1436inline OMX_ERRORTYPE
1437ComponentBase::TransStateToExecuting(OMX_STATETYPE current)
1438{
1439    OMX_ERRORTYPE ret;
1440
1441    if (current == OMX_StateIdle) {
1442        /*
1443         * Todo
1444         *   1. start component's internal processor
1445         *   2. start processing buffers on each port   !
1446         */
1447
1448        pthread_mutex_lock(&executing_lock);
1449        executing = true;
1450        pthread_mutex_unlock(&executing_lock);
1451
1452        bufferwork->StartWork();
1453        ret = OMX_ErrorNone;
1454    }
1455    else if (current == OMX_StatePause) {
1456        /*
1457         * Todo
1458         *   1. resume component's internal processor
1459         *   2. resume buffer process work              !
1460         */
1461
1462        pthread_mutex_lock(&executing_lock);
1463        executing = true;
1464        pthread_cond_signal(&executing_wait);
1465        pthread_mutex_unlock(&executing_lock);
1466
1467        ret = OMX_ErrorNone;
1468    }
1469    else
1470        ret = OMX_ErrorIncorrectStateOperation;
1471
1472    return ret;
1473}
1474
1475inline OMX_ERRORTYPE ComponentBase::TransStateToPause(OMX_STATETYPE current)
1476{
1477    OMX_ERRORTYPE ret;
1478
1479    if (current == OMX_StateIdle) {
1480        /*
1481         * Todo
1482         *   1. start(paused) component's internal processor
1483         *   2. start(paused) processing buffers on each port   !
1484         */
1485
1486        /* turn off executing flag */
1487        pthread_mutex_lock(&executing_lock);
1488        executing = false;
1489        pthread_mutex_unlock(&executing_lock);
1490
1491        bufferwork->StartWork();
1492
1493        ret = OMX_ErrorNone;
1494    }
1495    else if (current == OMX_StateExecuting) {
1496        /*
1497         * Todo
1498         *   1. pause buffer process work               !
1499         *   2. pause component's internal processor
1500         */
1501
1502        pthread_mutex_lock(&executing_lock);
1503        executing = false;
1504        pthread_mutex_unlock(&executing_lock);
1505
1506        ret = OMX_ErrorNone;
1507    }
1508    else
1509        ret = OMX_ErrorIncorrectStateOperation;
1510
1511    return ret;
1512}
1513
1514inline OMX_ERRORTYPE ComponentBase::TransStateToInvalid(OMX_STATETYPE current)
1515{
1516    OMX_ERRORTYPE ret = OMX_ErrorInvalidState;
1517
1518    /*
1519     * Todo
1520     *   graceful escape
1521     */
1522
1523    return ret;
1524}
1525
1526inline OMX_ERRORTYPE
1527ComponentBase::TransStateToWaitForResources(OMX_STATETYPE current)
1528{
1529    OMX_ERRORTYPE ret;
1530
1531    if (current == OMX_StateLoaded) {
1532        LOGE("state transition's requested from Loaded to WaitForResources\n");
1533        ret = OMX_ErrorNone;
1534    }
1535    else
1536        ret = OMX_ErrorIncorrectStateOperation;
1537
1538    return ret;
1539}
1540
1541/* set working role */
1542OMX_ERRORTYPE ComponentBase::SetWorkingRole(const OMX_STRING role)
1543{
1544    OMX_U32 i;
1545
1546    if (state != OMX_StateUnloaded && state != OMX_StateLoaded)
1547        return OMX_ErrorIncorrectStateOperation;
1548
1549    if (!role) {
1550        working_role = NULL;
1551        return OMX_ErrorNone;
1552    }
1553
1554    for (i = 0; i < nr_roles; i++) {
1555        if (!strcmp((char *)&roles[i][0], role)) {
1556            working_role = (OMX_STRING)&roles[i][0];
1557            return OMX_ErrorNone;
1558        }
1559    }
1560
1561    LOGE("cannot find %s role in %s\n", role, name);
1562    return OMX_ErrorBadParameter;
1563}
1564
1565/* apply a working role for a component having multiple roles */
1566OMX_ERRORTYPE ComponentBase::ApplyWorkingRole(void)
1567{
1568    OMX_U32 i;
1569    OMX_ERRORTYPE ret;
1570
1571    if (state != OMX_StateUnloaded && state != OMX_StateLoaded)
1572        return OMX_ErrorIncorrectStateOperation;
1573
1574    if (!working_role)
1575        return OMX_ErrorBadParameter;
1576
1577    if (!callbacks || !appdata)
1578        return OMX_ErrorBadParameter;
1579
1580    ret = AllocatePorts();
1581    if (ret != OMX_ErrorNone) {
1582        LOGE("failed to AllocatePorts() (ret = 0x%08x)\n", ret);
1583        return ret;
1584    }
1585
1586    /* now we can access ports */
1587    for (i = 0; i < nr_ports; i++) {
1588        ports[i]->SetOwner(handle);
1589        ports[i]->SetCallbacks(handle, callbacks, appdata);
1590    }
1591
1592    return OMX_ErrorNone;
1593}
1594
1595OMX_ERRORTYPE ComponentBase::AllocatePorts(void)
1596{
1597    OMX_ERRORTYPE ret;
1598
1599    if (ports)
1600        return OMX_ErrorBadParameter;
1601
1602    ret = ComponentAllocatePorts();
1603    if (ret != OMX_ErrorNone) {
1604        LOGE("failed to %s::ComponentAllocatePorts(), ret = 0x%08x\n",
1605             name, ret);
1606        return ret;
1607    }
1608
1609    return OMX_ErrorNone;
1610}
1611
1612/* called int FreeHandle() */
1613OMX_ERRORTYPE ComponentBase::FreePorts(void)
1614{
1615    if (ports) {
1616        OMX_U32 i, this_nr_ports = this->nr_ports;
1617
1618        for (i = 0; i < this_nr_ports; i++) {
1619            if (ports[i]) {
1620                delete ports[i];
1621                ports[i] = NULL;
1622            }
1623        }
1624        delete []ports;
1625        ports = NULL;
1626    }
1627
1628    return OMX_ErrorNone;
1629}
1630
1631/* buffer processing */
1632/* implement WorkableInterface */
1633void ComponentBase::Work(void)
1634{
1635    OMX_BUFFERHEADERTYPE **buffers = NULL;
1636    OMX_U32 i;
1637    bool avail = false;
1638
1639    pthread_mutex_lock(&executing_lock);
1640    if (!executing)
1641        pthread_cond_wait(&executing_wait, &executing_lock);
1642    pthread_mutex_unlock(&executing_lock);
1643
1644    pthread_mutex_lock(&ports_block);
1645
1646    avail = IsAllBufferAvailable();
1647    if (avail) {
1648        buffers = (OMX_BUFFERHEADERTYPE **)
1649            calloc(nr_ports, sizeof(OMX_BUFFERHEADERTYPE *));
1650        if (!buffers) {
1651            bufferwork->ScheduleWork(this);
1652            return;
1653        }
1654
1655        for (i = 0; i < nr_ports; i++)
1656            buffers[i] = ports[i]->PopBuffer();
1657    }
1658    ScheduleIfAllBufferAvailable();
1659
1660    pthread_mutex_unlock(&ports_block);
1661
1662    if (buffers) {
1663        ComponentProcessBuffers(buffers, nr_ports);
1664
1665        free(buffers);
1666        buffers = NULL;
1667    }
1668}
1669
1670bool ComponentBase::IsAllBufferAvailable(void)
1671{
1672    OMX_U32 i;
1673    OMX_U32 nr_avail = 0;
1674
1675    for (i = 0; i < nr_ports; i++) {
1676        OMX_U32 length;
1677
1678        length = ports[i]->BufferQueueLength();
1679        if (length)
1680            nr_avail++;
1681    }
1682
1683    if (nr_avail == nr_ports)
1684        return true;
1685    else
1686        return false;
1687}
1688
1689void ComponentBase::ScheduleIfAllBufferAvailable(void)
1690{
1691    bool avail;
1692
1693    avail = IsAllBufferAvailable();
1694    if (avail)
1695        bufferwork->ScheduleWork(this);
1696}
1697
1698/* end of component methods & helpers */
1699
1700/*
1701 * omx header manipuation
1702 */
1703void ComponentBase::SetTypeHeader(OMX_PTR type, OMX_U32 size)
1704{
1705    OMX_U32 *nsize;
1706    OMX_VERSIONTYPE *nversion;
1707
1708    if (!type)
1709        return;
1710
1711    nsize = (OMX_U32 *)type;
1712    nversion = (OMX_VERSIONTYPE *)((OMX_U8 *)type + sizeof(OMX_U32));
1713
1714    *nsize = size;
1715    nversion->nVersion = OMX_SPEC_VERSION;
1716}
1717
1718OMX_ERRORTYPE ComponentBase::CheckTypeHeader(OMX_PTR type, OMX_U32 size)
1719{
1720    OMX_U32 *nsize;
1721    OMX_VERSIONTYPE *nversion;
1722
1723    if (!type)
1724        return OMX_ErrorBadParameter;
1725
1726    nsize = (OMX_U32 *)type;
1727    nversion = (OMX_VERSIONTYPE *)((OMX_U8 *)type + sizeof(OMX_U32));
1728
1729    if (*nsize != size)
1730        return OMX_ErrorBadParameter;
1731
1732    if (nversion->nVersion != OMX_SPEC_VERSION)
1733        return OMX_ErrorVersionMismatch;
1734
1735    return OMX_ErrorNone;
1736}
1737
1738/*
1739 * query_roles helper
1740 */
1741OMX_ERRORTYPE ComponentBase::QueryRolesHelper(
1742    OMX_U32 nr_comp_roles,
1743    const OMX_U8 **comp_roles,
1744    OMX_U32 *nr_roles, OMX_U8 **roles)
1745{
1746    OMX_U32 i;
1747
1748    if (!roles) {
1749        *nr_roles = nr_comp_roles;
1750        return OMX_ErrorNone;
1751    }
1752
1753    if (!nr_roles || (*nr_roles != nr_comp_roles) || !roles)
1754        return OMX_ErrorBadParameter;
1755
1756    for (i = 0; i < nr_comp_roles; i++) {
1757        if (!roles[i])
1758            break;
1759
1760        strncpy((OMX_STRING)&roles[i][0],
1761                (const OMX_STRING)&comp_roles[i][0], OMX_MAX_STRINGNAME_SIZE);
1762    }
1763
1764    if (i != nr_comp_roles)
1765        return OMX_ErrorBadParameter;
1766
1767    *nr_roles = nr_comp_roles;
1768    return OMX_ErrorNone;
1769}
1770
1771/* end of ComponentBase */
1772