componentbase.cpp revision e58385f99580a21a25641e3012aa4bfd1b5ddd0c
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_IndexParamCompBufferSupplier:
520        /*
521         * Todo
522         */
523
524        ret = OMX_ErrorUnsupportedIndex;
525        break;
526    default:
527        ret = ComponentGetParameter(nParamIndex, pComponentParameterStructure);
528    } /* switch */
529
530    return ret;
531}
532
533OMX_ERRORTYPE ComponentBase::SetParameter(
534    OMX_IN  OMX_HANDLETYPE hComponent,
535    OMX_IN  OMX_INDEXTYPE nIndex,
536    OMX_IN  OMX_PTR pComponentParameterStructure)
537{
538    ComponentBase *cbase;
539
540    if (!hComponent)
541        return OMX_ErrorBadParameter;
542
543    cbase = static_cast<ComponentBase *>
544        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
545    if (!cbase)
546        return OMX_ErrorBadParameter;
547
548    return cbase->CBaseSetParameter(hComponent, nIndex,
549                                    pComponentParameterStructure);
550}
551
552OMX_ERRORTYPE ComponentBase::CBaseSetParameter(
553    OMX_IN  OMX_HANDLETYPE hComponent,
554    OMX_IN  OMX_INDEXTYPE nIndex,
555    OMX_IN  OMX_PTR pComponentParameterStructure)
556{
557    OMX_ERRORTYPE ret = OMX_ErrorNone;
558
559    if (hComponent != handle)
560        return OMX_ErrorBadParameter;
561
562    switch (nIndex) {
563    case OMX_IndexParamAudioInit:
564    case OMX_IndexParamVideoInit:
565    case OMX_IndexParamImageInit:
566    case OMX_IndexParamOtherInit:
567        /* preventing clients from setting OMX_PORT_PARAM_TYPE */
568        ret = OMX_ErrorUnsupportedIndex;
569        break;
570    case OMX_IndexParamPortDefinition: {
571        OMX_PARAM_PORTDEFINITIONTYPE *p =
572            (OMX_PARAM_PORTDEFINITIONTYPE *)pComponentParameterStructure;
573        OMX_U32 index = p->nPortIndex;
574        PortBase *port = NULL;
575
576        ret = CheckTypeHeader(p, sizeof(*p));
577        if (ret != OMX_ErrorNone)
578            return ret;
579
580        if (index < nr_ports)
581            port = ports[index];
582
583        if (!port)
584            return OMX_ErrorBadPortIndex;
585
586        if (port->IsEnabled()) {
587            if (state != OMX_StateLoaded && state != OMX_StateWaitForResources)
588                return OMX_ErrorIncorrectStateOperation;
589        }
590
591        port->SetPortDefinition(p, false);
592        break;
593    }
594    case OMX_IndexParamCompBufferSupplier:
595        /*
596         * Todo
597         */
598
599        ret = OMX_ErrorUnsupportedIndex;
600        break;
601    case OMX_IndexParamStandardComponentRole: {
602        OMX_PARAM_COMPONENTROLETYPE *p =
603            (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure;
604
605        if (state != OMX_StateLoaded && state != OMX_StateWaitForResources)
606            return OMX_ErrorIncorrectStateOperation;
607
608        ret = CheckTypeHeader(p, sizeof(*p));
609        if (ret != OMX_ErrorNone)
610            return ret;
611
612        ret = SetWorkingRole((OMX_STRING)p->cRole);
613        if (ret != OMX_ErrorNone)
614            return ret;
615
616        if (ports)
617            FreePorts();
618
619        ret = ApplyWorkingRole();
620        if (ret != OMX_ErrorNone) {
621            SetWorkingRole(NULL);
622            return ret;
623        }
624        break;
625    }
626    default:
627        ret = ComponentSetParameter(nIndex, pComponentParameterStructure);
628    } /* switch */
629
630    if (ret == OMX_ErrorNone)
631        ProcessorSetParameter(nIndex);
632
633    return ret;
634}
635
636OMX_ERRORTYPE ComponentBase::GetConfig(
637    OMX_IN  OMX_HANDLETYPE hComponent,
638    OMX_IN  OMX_INDEXTYPE nIndex,
639    OMX_INOUT OMX_PTR pComponentConfigStructure)
640{
641    ComponentBase *cbase;
642
643    if (!hComponent)
644        return OMX_ErrorBadParameter;
645
646    cbase = static_cast<ComponentBase *>
647        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
648    if (!cbase)
649        return OMX_ErrorBadParameter;
650
651    return cbase->CBaseGetConfig(hComponent, nIndex,
652                                 pComponentConfigStructure);
653}
654
655OMX_ERRORTYPE ComponentBase::CBaseGetConfig(
656    OMX_IN  OMX_HANDLETYPE hComponent,
657    OMX_IN  OMX_INDEXTYPE nIndex,
658    OMX_INOUT OMX_PTR pComponentConfigStructure)
659{
660    OMX_ERRORTYPE ret;
661
662    if (hComponent != handle)
663        return OMX_ErrorBadParameter;
664
665    switch (nIndex) {
666    default:
667        ret = ComponentGetConfig(nIndex, pComponentConfigStructure);
668    }
669
670    return ret;
671}
672
673OMX_ERRORTYPE ComponentBase::SetConfig(
674    OMX_IN  OMX_HANDLETYPE hComponent,
675    OMX_IN  OMX_INDEXTYPE nIndex,
676    OMX_IN  OMX_PTR pComponentConfigStructure)
677{
678    ComponentBase *cbase;
679
680    if (!hComponent)
681        return OMX_ErrorBadParameter;
682
683    cbase = static_cast<ComponentBase *>
684        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
685    if (!cbase)
686        return OMX_ErrorBadParameter;
687
688    return cbase->CBaseSetConfig(hComponent, nIndex,
689                                 pComponentConfigStructure);
690}
691
692OMX_ERRORTYPE ComponentBase::CBaseSetConfig(
693    OMX_IN  OMX_HANDLETYPE hComponent,
694    OMX_IN  OMX_INDEXTYPE nIndex,
695    OMX_IN  OMX_PTR pComponentConfigStructure)
696{
697    OMX_ERRORTYPE ret;
698
699    if (hComponent != handle)
700        return OMX_ErrorBadParameter;
701
702    switch (nIndex) {
703    default:
704        ret = ComponentSetConfig(nIndex, pComponentConfigStructure);
705    }
706
707    if (ret == OMX_ErrorNone)
708        ProcessorSetConfig(nIndex);
709
710    return ret;
711}
712
713OMX_ERRORTYPE ComponentBase::GetExtensionIndex(
714    OMX_IN  OMX_HANDLETYPE hComponent,
715    OMX_IN  OMX_STRING cParameterName,
716    OMX_OUT OMX_INDEXTYPE* pIndexType)
717{
718    ComponentBase *cbase;
719
720    if (!hComponent)
721        return OMX_ErrorBadParameter;
722
723    cbase = static_cast<ComponentBase *>
724        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
725    if (!cbase)
726        return OMX_ErrorBadParameter;
727
728    return cbase->CBaseGetExtensionIndex(hComponent, cParameterName,
729                                         pIndexType);
730}
731
732OMX_ERRORTYPE ComponentBase::CBaseGetExtensionIndex(
733    OMX_IN  OMX_HANDLETYPE hComponent,
734    OMX_IN  OMX_STRING cParameterName,
735    OMX_OUT OMX_INDEXTYPE* pIndexType)
736{
737    /*
738     * Todo
739     */
740
741    return OMX_ErrorNotImplemented;
742}
743
744OMX_ERRORTYPE ComponentBase::GetState(
745    OMX_IN  OMX_HANDLETYPE hComponent,
746    OMX_OUT OMX_STATETYPE* pState)
747{
748    ComponentBase *cbase;
749
750    if (!hComponent)
751        return OMX_ErrorBadParameter;
752
753    cbase = static_cast<ComponentBase *>
754        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
755    if (!cbase)
756        return OMX_ErrorBadParameter;
757
758    return cbase->CBaseGetState(hComponent, pState);
759}
760
761OMX_ERRORTYPE ComponentBase::CBaseGetState(
762    OMX_IN  OMX_HANDLETYPE hComponent,
763    OMX_OUT OMX_STATETYPE* pState)
764{
765    if (hComponent != handle)
766        return OMX_ErrorBadParameter;
767
768    *pState = state;
769    return OMX_ErrorNone;
770}
771
772OMX_ERRORTYPE ComponentBase::ComponentTunnelRequest(
773    OMX_IN  OMX_HANDLETYPE hComponent,
774    OMX_IN  OMX_U32 nPort,
775    OMX_IN  OMX_HANDLETYPE hTunneledComponent,
776    OMX_IN  OMX_U32 nTunneledPort,
777    OMX_INOUT  OMX_TUNNELSETUPTYPE* pTunnelSetup)
778{
779    ComponentBase *cbase;
780
781    if (!hComponent)
782        return OMX_ErrorBadParameter;
783
784    cbase = static_cast<ComponentBase *>
785        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
786    if (!cbase)
787        return OMX_ErrorBadParameter;
788
789    return cbase->CBaseComponentTunnelRequest(hComponent, nPort,
790                                              hTunneledComponent,
791                                              nTunneledPort, pTunnelSetup);
792}
793
794OMX_ERRORTYPE ComponentBase::CBaseComponentTunnelRequest(
795    OMX_IN  OMX_HANDLETYPE hComp,
796    OMX_IN  OMX_U32 nPort,
797    OMX_IN  OMX_HANDLETYPE hTunneledComp,
798    OMX_IN  OMX_U32 nTunneledPort,
799    OMX_INOUT  OMX_TUNNELSETUPTYPE* pTunnelSetup)
800{
801    /*
802     * Todo
803     */
804
805    return OMX_ErrorNotImplemented;
806}
807
808OMX_ERRORTYPE ComponentBase::UseBuffer(
809    OMX_IN OMX_HANDLETYPE hComponent,
810    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr,
811    OMX_IN OMX_U32 nPortIndex,
812    OMX_IN OMX_PTR pAppPrivate,
813    OMX_IN OMX_U32 nSizeBytes,
814    OMX_IN OMX_U8 *pBuffer)
815{
816    ComponentBase *cbase;
817
818    if (!hComponent)
819        return OMX_ErrorBadParameter;
820
821    cbase = static_cast<ComponentBase *>
822        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
823    if (!cbase)
824        return OMX_ErrorBadParameter;
825
826    return cbase->CBaseUseBuffer(hComponent, ppBufferHdr, nPortIndex,
827                                 pAppPrivate, nSizeBytes, pBuffer);
828}
829
830OMX_ERRORTYPE ComponentBase::CBaseUseBuffer(
831    OMX_IN OMX_HANDLETYPE hComponent,
832    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr,
833    OMX_IN OMX_U32 nPortIndex,
834    OMX_IN OMX_PTR pAppPrivate,
835    OMX_IN OMX_U32 nSizeBytes,
836    OMX_IN OMX_U8 *pBuffer)
837{
838    PortBase *port = NULL;
839    OMX_ERRORTYPE ret;
840
841    if (hComponent != handle)
842        return OMX_ErrorBadParameter;
843
844    if (!ppBufferHdr)
845        return OMX_ErrorBadParameter;
846    *ppBufferHdr = NULL;
847
848    if (!pBuffer)
849        return OMX_ErrorBadParameter;
850
851    if (ports)
852        if (nPortIndex < nr_ports)
853            port = ports[nPortIndex];
854
855    if (!port)
856        return OMX_ErrorBadParameter;
857
858    if (port->IsEnabled()) {
859        if (state != OMX_StateLoaded && state != OMX_StateWaitForResources)
860            return OMX_ErrorIncorrectStateOperation;
861    }
862
863    return port->UseBuffer(ppBufferHdr, nPortIndex, pAppPrivate, nSizeBytes,
864                           pBuffer);
865}
866
867OMX_ERRORTYPE ComponentBase::AllocateBuffer(
868    OMX_IN OMX_HANDLETYPE hComponent,
869    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer,
870    OMX_IN OMX_U32 nPortIndex,
871    OMX_IN OMX_PTR pAppPrivate,
872    OMX_IN OMX_U32 nSizeBytes)
873{
874    ComponentBase *cbase;
875
876    if (!hComponent)
877        return OMX_ErrorBadParameter;
878
879    cbase = static_cast<ComponentBase *>
880        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
881    if (!cbase)
882        return OMX_ErrorBadParameter;
883
884    return cbase->CBaseAllocateBuffer(hComponent, ppBuffer, nPortIndex,
885                                      pAppPrivate, nSizeBytes);
886}
887
888OMX_ERRORTYPE ComponentBase::CBaseAllocateBuffer(
889    OMX_IN OMX_HANDLETYPE hComponent,
890    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer,
891    OMX_IN OMX_U32 nPortIndex,
892    OMX_IN OMX_PTR pAppPrivate,
893    OMX_IN OMX_U32 nSizeBytes)
894{
895    PortBase *port = NULL;
896    OMX_ERRORTYPE ret;
897
898    if (hComponent != handle)
899        return OMX_ErrorBadParameter;
900
901    if (!ppBuffer)
902        return OMX_ErrorBadParameter;
903    *ppBuffer = NULL;
904
905    if (ports)
906        if (nPortIndex < nr_ports)
907            port = ports[nPortIndex];
908
909    if (!port)
910        return OMX_ErrorBadParameter;
911
912    if (port->IsEnabled()) {
913        if (state != OMX_StateLoaded && state != OMX_StateWaitForResources)
914            return OMX_ErrorIncorrectStateOperation;
915    }
916
917    return port->AllocateBuffer(ppBuffer, nPortIndex, pAppPrivate, nSizeBytes);
918}
919
920OMX_ERRORTYPE ComponentBase::FreeBuffer(
921    OMX_IN  OMX_HANDLETYPE hComponent,
922    OMX_IN  OMX_U32 nPortIndex,
923    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
924{
925    ComponentBase *cbase;
926
927    if (!hComponent)
928        return OMX_ErrorBadParameter;
929
930    cbase = static_cast<ComponentBase *>
931        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
932    if (!cbase)
933        return OMX_ErrorBadParameter;
934
935    return cbase->CBaseFreeBuffer(hComponent, nPortIndex, pBuffer);
936}
937
938OMX_ERRORTYPE ComponentBase::CBaseFreeBuffer(
939    OMX_IN  OMX_HANDLETYPE hComponent,
940    OMX_IN  OMX_U32 nPortIndex,
941    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
942{
943    PortBase *port = NULL;
944    OMX_ERRORTYPE ret;
945
946    if (hComponent != handle)
947        return OMX_ErrorBadParameter;
948
949    if (!pBuffer)
950        return OMX_ErrorBadParameter;
951
952    if (ports)
953        if (nPortIndex < nr_ports)
954            port = ports[nPortIndex];
955
956    if (!port)
957        return OMX_ErrorBadParameter;
958
959    return port->FreeBuffer(nPortIndex, pBuffer);
960}
961
962OMX_ERRORTYPE ComponentBase::EmptyThisBuffer(
963    OMX_IN  OMX_HANDLETYPE hComponent,
964    OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer)
965{
966    ComponentBase *cbase;
967
968    if (!hComponent)
969        return OMX_ErrorBadParameter;
970
971    cbase = static_cast<ComponentBase *>
972        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
973    if (!cbase)
974        return OMX_ErrorBadParameter;
975
976    return cbase->CBaseEmptyThisBuffer(hComponent, pBuffer);
977}
978
979OMX_ERRORTYPE ComponentBase::CBaseEmptyThisBuffer(
980    OMX_IN  OMX_HANDLETYPE hComponent,
981    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
982{
983    PortBase *port = NULL;
984    OMX_U32 port_index;
985    OMX_ERRORTYPE ret;
986
987    if ((hComponent != handle) || !pBuffer)
988        return OMX_ErrorBadParameter;
989
990    ret = CheckTypeHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE));
991    if (ret != OMX_ErrorNone)
992        return ret;
993
994    port_index = pBuffer->nInputPortIndex;
995    if (port_index == (OMX_U32)-1)
996        return OMX_ErrorBadParameter;
997
998    if (ports)
999        if (port_index < nr_ports)
1000            port = ports[port_index];
1001
1002    if (!port)
1003        return OMX_ErrorBadParameter;
1004
1005    if (pBuffer->pInputPortPrivate != port)
1006        return OMX_ErrorBadParameter;
1007
1008    if (port->IsEnabled()) {
1009        if (state != OMX_StateIdle && state != OMX_StateExecuting &&
1010            state != OMX_StatePause)
1011            return OMX_ErrorIncorrectStateOperation;
1012    }
1013
1014    if (!pBuffer->hMarkTargetComponent) {
1015        OMX_MARKTYPE *mark;
1016
1017        mark = port->PopMark();
1018        if (mark) {
1019            pBuffer->hMarkTargetComponent = mark->hMarkTargetComponent;
1020            pBuffer->pMarkData = mark->pMarkData;
1021            free(mark);
1022        }
1023    }
1024
1025    ret = port->PushThisBuffer(pBuffer);
1026    if (ret == OMX_ErrorNone)
1027        bufferwork->ScheduleWork(this);
1028
1029    return ret;
1030}
1031
1032OMX_ERRORTYPE ComponentBase::FillThisBuffer(
1033    OMX_IN  OMX_HANDLETYPE hComponent,
1034    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
1035{
1036    ComponentBase *cbase;
1037
1038    if (!hComponent)
1039        return OMX_ErrorBadParameter;
1040
1041    cbase = static_cast<ComponentBase *>
1042        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
1043    if (!cbase)
1044        return OMX_ErrorBadParameter;
1045
1046    return cbase->CBaseFillThisBuffer(hComponent, pBuffer);
1047}
1048
1049OMX_ERRORTYPE ComponentBase::CBaseFillThisBuffer(
1050    OMX_IN  OMX_HANDLETYPE hComponent,
1051    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
1052{
1053    PortBase *port = NULL;
1054    OMX_U32 port_index;
1055    OMX_ERRORTYPE ret;
1056
1057    if ((hComponent != handle) || !pBuffer)
1058        return OMX_ErrorBadParameter;
1059
1060    ret = CheckTypeHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE));
1061    if (ret != OMX_ErrorNone)
1062        return ret;
1063
1064    port_index = pBuffer->nOutputPortIndex;
1065    if (port_index == (OMX_U32)-1)
1066        return OMX_ErrorBadParameter;
1067
1068    if (ports)
1069        if (port_index < nr_ports)
1070            port = ports[port_index];
1071
1072    if (!port)
1073        return OMX_ErrorBadParameter;
1074
1075    if (pBuffer->pOutputPortPrivate != port)
1076        return OMX_ErrorBadParameter;
1077
1078    if (port->IsEnabled()) {
1079        if (state != OMX_StateIdle && state != OMX_StateExecuting &&
1080            state != OMX_StatePause)
1081            return OMX_ErrorIncorrectStateOperation;
1082    }
1083
1084    ret = port->PushThisBuffer(pBuffer);
1085    if (ret == OMX_ErrorNone)
1086        bufferwork->ScheduleWork(this);
1087
1088    return ret;
1089}
1090
1091OMX_ERRORTYPE ComponentBase::SetCallbacks(
1092    OMX_IN  OMX_HANDLETYPE hComponent,
1093    OMX_IN  OMX_CALLBACKTYPE* pCallbacks,
1094    OMX_IN  OMX_PTR pAppData)
1095{
1096    ComponentBase *cbase;
1097
1098    if (!hComponent)
1099        return OMX_ErrorBadParameter;
1100
1101    cbase = static_cast<ComponentBase *>
1102        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
1103    if (!cbase)
1104        return OMX_ErrorBadParameter;
1105
1106    return cbase->CBaseSetCallbacks(hComponent, pCallbacks, pAppData);
1107}
1108
1109OMX_ERRORTYPE ComponentBase::CBaseSetCallbacks(
1110    OMX_IN  OMX_HANDLETYPE hComponent,
1111    OMX_IN  OMX_CALLBACKTYPE *pCallbacks,
1112    OMX_IN  OMX_PTR pAppData)
1113{
1114    if (hComponent != handle)
1115        return OMX_ErrorBadParameter;
1116
1117    appdata = pAppData;
1118    callbacks = pCallbacks;
1119
1120    return OMX_ErrorNone;
1121}
1122
1123OMX_ERRORTYPE ComponentBase::ComponentDeInit(
1124    OMX_IN  OMX_HANDLETYPE hComponent)
1125{
1126    ComponentBase *cbase;
1127
1128    if (!hComponent)
1129        return OMX_ErrorBadParameter;
1130
1131    cbase = static_cast<ComponentBase *>
1132        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
1133    if (!cbase)
1134        return OMX_ErrorBadParameter;
1135
1136    return cbase->CBaseComponentDeInit(hComponent);
1137}
1138
1139OMX_ERRORTYPE ComponentBase::CBaseComponentDeInit(
1140    OMX_IN  OMX_HANDLETYPE hComponent)
1141{
1142    /*
1143     * Todo
1144     */
1145
1146    return OMX_ErrorNotImplemented;
1147}
1148
1149OMX_ERRORTYPE ComponentBase::UseEGLImage(
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    ComponentBase *cbase;
1157
1158    if (!hComponent)
1159        return OMX_ErrorBadParameter;
1160
1161    cbase = static_cast<ComponentBase *>
1162        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
1163    if (!cbase)
1164        return OMX_ErrorBadParameter;
1165
1166    return cbase->CBaseUseEGLImage(hComponent, ppBufferHdr, nPortIndex,
1167                                   pAppPrivate, eglImage);
1168}
1169
1170OMX_ERRORTYPE ComponentBase::CBaseUseEGLImage(
1171    OMX_IN OMX_HANDLETYPE hComponent,
1172    OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
1173    OMX_IN OMX_U32 nPortIndex,
1174    OMX_IN OMX_PTR pAppPrivate,
1175    OMX_IN void* eglImage)
1176{
1177    /*
1178     * Todo
1179     */
1180
1181    return OMX_ErrorNotImplemented;
1182}
1183
1184OMX_ERRORTYPE ComponentBase::ComponentRoleEnum(
1185    OMX_IN OMX_HANDLETYPE hComponent,
1186    OMX_OUT OMX_U8 *cRole,
1187    OMX_IN OMX_U32 nIndex)
1188{
1189    ComponentBase *cbase;
1190
1191    if (!hComponent)
1192        return OMX_ErrorBadParameter;
1193
1194    cbase = static_cast<ComponentBase *>
1195        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
1196    if (!cbase)
1197        return OMX_ErrorBadParameter;
1198
1199    return cbase->CBaseComponentRoleEnum(hComponent, cRole, nIndex);
1200}
1201
1202OMX_ERRORTYPE ComponentBase::CBaseComponentRoleEnum(
1203    OMX_IN OMX_HANDLETYPE hComponent,
1204    OMX_OUT OMX_U8 *cRole,
1205    OMX_IN OMX_U32 nIndex)
1206{
1207    if (hComponent != (OMX_HANDLETYPE *)this->handle)
1208        return OMX_ErrorBadParameter;
1209
1210    if (nIndex > nr_roles)
1211        return OMX_ErrorBadParameter;
1212
1213    strncpy((char *)cRole, (const char *)roles[nIndex],
1214            OMX_MAX_STRINGNAME_SIZE);
1215    return OMX_ErrorNone;
1216}
1217
1218/* implement CmdHandlerInterface */
1219void ComponentBase::CmdHandler(struct cmd_s *cmd)
1220{
1221    switch (cmd->cmd) {
1222    case OMX_CommandStateSet: {
1223        OMX_STATETYPE transition = (OMX_STATETYPE)cmd->param1;
1224
1225        TransState(transition);
1226        break;
1227    }
1228    case OMX_CommandFlush: {
1229        OMX_U32 port_index = cmd->param1;
1230
1231        FlushPort(port_index, 1);
1232        break;
1233    }
1234    case OMX_CommandPortDisable: {
1235        OMX_U32 port_index = cmd->param1;
1236
1237        TransStatePort(port_index, PortBase::OMX_PortDisabled);
1238        break;
1239    }
1240    case OMX_CommandPortEnable: {
1241        OMX_U32 port_index = cmd->param1;
1242
1243        TransStatePort(port_index, PortBase::OMX_PortEnabled);
1244        break;
1245    }
1246    case OMX_CommandMarkBuffer:
1247        OMX_U32 port_index = (OMX_U32)cmd->param1;
1248        OMX_MARKTYPE *mark = (OMX_MARKTYPE *)cmd->cmddata;
1249
1250        PushThisMark(port_index, mark);
1251        break;
1252    } /* switch */
1253}
1254
1255/*
1256 * SendCommand:OMX_CommandStateSet
1257 * called in CmdHandler or called in other parts of component for reporting
1258 * internal error (OMX_StateInvalid).
1259 */
1260/*
1261 * Todo
1262 *   Resource Management (OMX_StateWaitForResources)
1263 *   for now, we never notify OMX_ErrorInsufficientResources,
1264 *   so IL client doesn't try to set component' state OMX_StateWaitForResources
1265 */
1266static const char *state_name[OMX_StateWaitForResources + 1] = {
1267    "OMX_StateInvalid",
1268    "OMX_StateLoaded",
1269    "OMX_StateIdle",
1270    "OMX_StateExecuting",
1271    "OMX_StatePause",
1272    "OMX_StateWaitForResources",
1273};
1274
1275static inline const char *GetStateName(OMX_STATETYPE state)
1276{
1277    if (state > OMX_StateWaitForResources)
1278        return "UnKnown";
1279
1280    return state_name[state];
1281}
1282
1283void ComponentBase::TransState(OMX_STATETYPE transition)
1284{
1285    OMX_STATETYPE current = this->state;
1286    OMX_EVENTTYPE event;
1287    OMX_U32 data1, data2;
1288    OMX_ERRORTYPE ret;
1289
1290    LOGD("current state = %s, transition state = %s\n",
1291         GetStateName(current), GetStateName(transition));
1292
1293    /* same state */
1294    if (current == transition) {
1295        ret = OMX_ErrorSameState;
1296        goto notify_event;
1297    }
1298
1299    /* invalid state */
1300    if (current == OMX_StateInvalid) {
1301        ret = OMX_ErrorInvalidState;
1302        goto notify_event;
1303    }
1304
1305    if (transition == OMX_StateLoaded)
1306        ret = TransStateToLoaded(current);
1307    else if (transition == OMX_StateIdle)
1308        ret = TransStateToIdle(current);
1309    else if (transition == OMX_StateExecuting)
1310        ret = TransStateToExecuting(current);
1311    else if (transition == OMX_StatePause)
1312        ret = TransStateToPause(current);
1313    else if (transition == OMX_StateInvalid)
1314        ret = TransStateToInvalid(current);
1315    else if (transition == OMX_StateWaitForResources)
1316        ret = TransStateToWaitForResources(current);
1317    else
1318        ret = OMX_ErrorIncorrectStateTransition;
1319
1320notify_event:
1321    if (ret == OMX_ErrorNone) {
1322        event = OMX_EventCmdComplete;
1323        data1 = OMX_CommandStateSet;
1324        data2 = transition;
1325
1326        state = transition;
1327        LOGD("transition from %s to %s completed\n",
1328             GetStateName(current), GetStateName(transition));
1329    }
1330    else {
1331        event = OMX_EventError;
1332        data1 = ret;
1333        data2 = 0;
1334
1335        if (transition == OMX_StateInvalid || ret == OMX_ErrorInvalidState) {
1336            state = OMX_StateInvalid;
1337            LOGD("failed transition from %s to %s, current state is %s\n",
1338                 GetStateName(current), GetStateName(transition),
1339                 GetStateName(state));
1340        }
1341    }
1342
1343    callbacks->EventHandler(handle, appdata, event, data1, data2, NULL);
1344
1345    /* WaitForResources workaround */
1346    if (ret == OMX_ErrorNone && transition == OMX_StateWaitForResources)
1347        callbacks->EventHandler(handle, appdata,
1348                                OMX_EventResourcesAcquired, 0, 0, NULL);
1349}
1350
1351inline OMX_ERRORTYPE ComponentBase::TransStateToLoaded(OMX_STATETYPE current)
1352{
1353    OMX_ERRORTYPE ret;
1354
1355    if (current == OMX_StateIdle) {
1356        OMX_U32 i;
1357
1358        for (i = 0; i < nr_ports; i++)
1359            ports[i]->WaitPortBufferCompletion();
1360
1361        ret = ProcessorDeinit();
1362        if (ret != OMX_ErrorNone) {
1363            LOGE("failed to ProcessorDeinit() (ret = 0x%08x)\n", ret);
1364            ret = OMX_ErrorInvalidState;
1365            goto out;
1366        }
1367    }
1368    else if (current == OMX_StateWaitForResources) {
1369        LOGE("state transition's requested from WaitForResources to "
1370             "Loaded\n");
1371
1372        /*
1373         * from WaitForResources to Loaded considered from Loaded to Loaded.
1374         * do nothing
1375         */
1376
1377        ret = OMX_ErrorNone;
1378    }
1379    else
1380        ret = OMX_ErrorIncorrectStateTransition;
1381
1382out:
1383    return ret;
1384}
1385
1386inline OMX_ERRORTYPE ComponentBase::TransStateToIdle(OMX_STATETYPE current)
1387{
1388    OMX_ERRORTYPE ret;
1389
1390    if (current == OMX_StateLoaded) {
1391        OMX_U32 i;
1392
1393        ret = ProcessorInit();
1394        if (ret != OMX_ErrorNone) {
1395            LOGE("failed to ProcessorInit() (ret = 0x%08x)\n", ret);
1396            ret = OMX_ErrorInvalidState;
1397            goto out;
1398        }
1399
1400        for (i = 0; i < nr_ports; i++) {
1401            if (ports[i]->IsEnabled())
1402                ports[i]->WaitPortBufferCompletion();
1403        }
1404    }
1405    else if (current == OMX_StateExecuting) {
1406        FlushPort(OMX_ALL, 0);
1407
1408        bufferwork->StopWork();
1409
1410        ret = ProcessorStop();
1411        if (ret != OMX_ErrorNone) {
1412            LOGE("failed to ProcessorStop() (ret = 0x%08x)\n", ret);
1413            ret = OMX_ErrorInvalidState;
1414            goto out;
1415        }
1416    }
1417    else if (current == OMX_StatePause) {
1418        FlushPort(OMX_ALL, 0);
1419
1420        bufferwork->CancelScheduledWork(this);
1421        bufferwork->StopWork();
1422
1423        ret = ProcessorStop();
1424        if (ret != OMX_ErrorNone) {
1425            LOGE("failed to ProcessorStop() (ret = 0x%08x)\n", ret);
1426            ret = OMX_ErrorInvalidState;
1427            goto out;
1428        }
1429    }
1430    else if (current == OMX_StateWaitForResources) {
1431        LOGE("state transition's requested from WaitForResources to Idle\n");
1432
1433        /* same as Loaded to Idle BUT DO NOTHING for now */
1434
1435        ret = OMX_ErrorNone;
1436    }
1437    else
1438        ret = OMX_ErrorIncorrectStateTransition;
1439
1440out:
1441    return ret;
1442}
1443
1444inline OMX_ERRORTYPE
1445ComponentBase::TransStateToExecuting(OMX_STATETYPE current)
1446{
1447    OMX_ERRORTYPE ret;
1448
1449    if (current == OMX_StateIdle) {
1450        pthread_mutex_lock(&executing_lock);
1451        executing = true;
1452        pthread_mutex_unlock(&executing_lock);
1453
1454        bufferwork->StartWork();
1455
1456        ret = ProcessorStart();
1457        if (ret != OMX_ErrorNone) {
1458            LOGE("failed to ProcessorStart() (ret = 0x%08x)\n", ret);
1459            ret = OMX_ErrorInvalidState;
1460            goto out;
1461        }
1462    }
1463    else if (current == OMX_StatePause) {
1464        pthread_mutex_lock(&executing_lock);
1465        executing = true;
1466        pthread_cond_signal(&executing_wait);
1467        pthread_mutex_unlock(&executing_lock);
1468
1469        ret = ProcessorResume();
1470        if (ret != OMX_ErrorNone) {
1471            LOGE("failed to ProcessorStart() (ret = 0x%08x)\n", ret);
1472            ret = OMX_ErrorInvalidState;
1473            goto out;
1474        }
1475    }
1476    else
1477        ret = OMX_ErrorIncorrectStateTransition;
1478
1479out:
1480    return ret;
1481}
1482
1483inline OMX_ERRORTYPE ComponentBase::TransStateToPause(OMX_STATETYPE current)
1484{
1485    OMX_ERRORTYPE ret;
1486
1487    if (current == OMX_StateIdle) {
1488        /* turn off executing flag */
1489        pthread_mutex_lock(&executing_lock);
1490        executing = false;
1491        pthread_mutex_unlock(&executing_lock);
1492
1493        bufferwork->StartWork();
1494
1495        ret = ProcessorStart();
1496        if (ret != OMX_ErrorNone) {
1497            LOGE("failed to ProcessorPause() (ret = 0x%08x)\n", ret);
1498            ret = OMX_ErrorInvalidState;
1499            goto out;
1500        }
1501    }
1502    else if (current == OMX_StateExecuting) {
1503        pthread_mutex_lock(&executing_lock);
1504        executing = false;
1505        pthread_mutex_unlock(&executing_lock);
1506
1507        ret = ProcessorPause();
1508        if (ret != OMX_ErrorNone) {
1509            LOGE("failed to ProcessorPause() (ret = 0x%08x)\n", ret);
1510            ret = OMX_ErrorInvalidState;
1511            goto out;
1512        }
1513    }
1514    else
1515        ret = OMX_ErrorIncorrectStateTransition;
1516
1517out:
1518    return ret;
1519}
1520
1521inline OMX_ERRORTYPE ComponentBase::TransStateToInvalid(OMX_STATETYPE current)
1522{
1523    OMX_ERRORTYPE ret = OMX_ErrorInvalidState;
1524
1525    /*
1526     * Todo
1527     *   graceful escape
1528     */
1529
1530    return ret;
1531}
1532
1533inline OMX_ERRORTYPE
1534ComponentBase::TransStateToWaitForResources(OMX_STATETYPE current)
1535{
1536    OMX_ERRORTYPE ret;
1537
1538    if (current == OMX_StateLoaded) {
1539        LOGE("state transition's requested from Loaded to WaitForResources\n");
1540        ret = OMX_ErrorNone;
1541    }
1542    else
1543        ret = OMX_ErrorIncorrectStateTransition;
1544
1545    return ret;
1546}
1547
1548/* mark buffer */
1549void ComponentBase::PushThisMark(OMX_U32 port_index, OMX_MARKTYPE *mark)
1550{
1551    PortBase *port = NULL;
1552    OMX_EVENTTYPE event;
1553    OMX_U32 data1, data2;
1554    OMX_ERRORTYPE ret;
1555
1556    if (ports)
1557        if (port_index < nr_ports)
1558            port = ports[port_index];
1559
1560    if (!port) {
1561        ret = OMX_ErrorBadPortIndex;
1562        goto notify_event;
1563    }
1564
1565    ret = port->PushMark(mark);
1566    if (ret != OMX_ErrorNone) {
1567        /* don't report OMX_ErrorInsufficientResources */
1568        ret = OMX_ErrorUndefined;
1569        goto notify_event;
1570    }
1571
1572notify_event:
1573    if (ret == OMX_ErrorNone) {
1574        event = OMX_EventCmdComplete;
1575        data1 = OMX_CommandMarkBuffer;
1576        data2 = port_index;
1577    }
1578    else {
1579        event = OMX_EventError;
1580        data1 = ret;
1581        data2 = 0;
1582    }
1583
1584    callbacks->EventHandler(handle, appdata, event, data1, data2, NULL);
1585}
1586
1587void ComponentBase::FlushPort(OMX_U32 port_index, bool notify)
1588{
1589    OMX_U32 i, from_index, to_index;
1590
1591    if ((port_index != OMX_ALL) && (port_index > nr_ports-1))
1592        return;
1593
1594    if (port_index == OMX_ALL) {
1595        from_index = 0;
1596        to_index = nr_ports - 1;
1597    }
1598    else {
1599        from_index = port_index;
1600        to_index = port_index;
1601    }
1602
1603    pthread_mutex_lock(&ports_block);
1604    for (i = from_index; i <= to_index; i++) {
1605        ports[i]->FlushPort();
1606        if (notify)
1607            callbacks->EventHandler(handle, appdata, OMX_EventCmdComplete,
1608                                    OMX_CommandFlush, i, NULL);
1609    }
1610    pthread_mutex_unlock(&ports_block);
1611}
1612
1613void ComponentBase::TransStatePort(OMX_U32 port_index, OMX_U8 state)
1614{
1615    OMX_EVENTTYPE event;
1616    OMX_U32 data1, data2;
1617    OMX_U32 i, from_index, to_index;
1618    OMX_ERRORTYPE ret;
1619
1620    if ((port_index != OMX_ALL) && (port_index > nr_ports-1))
1621        return;
1622
1623    if (port_index == OMX_ALL) {
1624        from_index = 0;
1625        to_index = nr_ports - 1;
1626    }
1627    else {
1628        from_index = port_index;
1629        to_index = port_index;
1630    }
1631
1632    pthread_mutex_lock(&ports_block);
1633    for (i = from_index; i <= to_index; i++) {
1634        ret = ports[i]->TransState(state);
1635        if (ret == OMX_ErrorNone) {
1636            event = OMX_EventCmdComplete;
1637            if (state == PortBase::OMX_PortEnabled)
1638                data1 = OMX_CommandPortEnable;
1639            else
1640                data1 = OMX_CommandPortDisable;
1641            data2 = i;
1642        }
1643        else {
1644            event = OMX_EventError;
1645            data1 = ret;
1646            data2 = 0;
1647        }
1648        callbacks->EventHandler(handle, appdata, OMX_EventCmdComplete,
1649                                OMX_CommandPortDisable, data2, NULL);
1650    }
1651    pthread_mutex_unlock(&ports_block);
1652}
1653
1654/* set working role */
1655OMX_ERRORTYPE ComponentBase::SetWorkingRole(const OMX_STRING role)
1656{
1657    OMX_U32 i;
1658
1659    if (state != OMX_StateUnloaded && state != OMX_StateLoaded)
1660        return OMX_ErrorIncorrectStateOperation;
1661
1662    if (!role) {
1663        working_role = NULL;
1664        return OMX_ErrorNone;
1665    }
1666
1667    for (i = 0; i < nr_roles; i++) {
1668        if (!strcmp((char *)&roles[i][0], role)) {
1669            working_role = (OMX_STRING)&roles[i][0];
1670            return OMX_ErrorNone;
1671        }
1672    }
1673
1674    LOGE("cannot find %s role in %s\n", role, name);
1675    return OMX_ErrorBadParameter;
1676}
1677
1678/* apply a working role for a component having multiple roles */
1679OMX_ERRORTYPE ComponentBase::ApplyWorkingRole(void)
1680{
1681    OMX_U32 i;
1682    OMX_ERRORTYPE ret;
1683
1684    if (state != OMX_StateUnloaded && state != OMX_StateLoaded)
1685        return OMX_ErrorIncorrectStateOperation;
1686
1687    if (!working_role)
1688        return OMX_ErrorBadParameter;
1689
1690    if (!callbacks || !appdata)
1691        return OMX_ErrorBadParameter;
1692
1693    ret = AllocatePorts();
1694    if (ret != OMX_ErrorNone) {
1695        LOGE("failed to AllocatePorts() (ret = 0x%08x)\n", ret);
1696        return ret;
1697    }
1698
1699    /* now we can access ports */
1700    for (i = 0; i < nr_ports; i++) {
1701        ports[i]->SetOwner(handle);
1702        ports[i]->SetCallbacks(handle, callbacks, appdata);
1703    }
1704
1705    return OMX_ErrorNone;
1706}
1707
1708OMX_ERRORTYPE ComponentBase::AllocatePorts(void)
1709{
1710    OMX_ERRORTYPE ret;
1711
1712    if (ports)
1713        return OMX_ErrorBadParameter;
1714
1715    ret = ComponentAllocatePorts();
1716    if (ret != OMX_ErrorNone) {
1717        LOGE("failed to %s::ComponentAllocatePorts(), ret = 0x%08x\n",
1718             name, ret);
1719        return ret;
1720    }
1721
1722    return OMX_ErrorNone;
1723}
1724
1725/* called int FreeHandle() */
1726OMX_ERRORTYPE ComponentBase::FreePorts(void)
1727{
1728    if (ports) {
1729        OMX_U32 i, this_nr_ports = this->nr_ports;
1730
1731        for (i = 0; i < this_nr_ports; i++) {
1732            if (ports[i]) {
1733                OMX_MARKTYPE *mark;
1734                /* it should be empty before this */
1735                while ((mark = ports[i]->PopMark()))
1736                    free(mark);
1737
1738                delete ports[i];
1739                ports[i] = NULL;
1740            }
1741        }
1742        delete []ports;
1743        ports = NULL;
1744    }
1745
1746    return OMX_ErrorNone;
1747}
1748
1749/* buffer processing */
1750/* implement WorkableInterface */
1751void ComponentBase::Work(void)
1752{
1753    OMX_BUFFERHEADERTYPE *buffers[nr_ports];
1754    bool retain[nr_ports];
1755    OMX_U32 i;
1756    bool avail = false;
1757
1758    pthread_mutex_lock(&executing_lock);
1759    if (!executing)
1760        pthread_cond_wait(&executing_wait, &executing_lock);
1761    pthread_mutex_unlock(&executing_lock);
1762
1763    pthread_mutex_lock(&ports_block);
1764
1765    avail = IsAllBufferAvailable();
1766    if (avail) {
1767        for (i = 0; i < nr_ports; i++) {
1768            buffers[i] = ports[i]->PopBuffer();
1769            retain[i] = false;
1770        }
1771
1772        ProcessorProcess(buffers, &retain[0], nr_ports);
1773        PostProcessBuffer(buffers, &retain[0], nr_ports);
1774
1775        for (i = 0; i < nr_ports; i++) {
1776            if (retain[i])
1777                ports[i]->RetainThisBuffer(buffers[i]);
1778            else
1779                ports[i]->ReturnThisBuffer(buffers[i]);
1780        }
1781    }
1782    ScheduleIfAllBufferAvailable();
1783
1784    pthread_mutex_unlock(&ports_block);
1785}
1786
1787bool ComponentBase::IsAllBufferAvailable(void)
1788{
1789    OMX_U32 i;
1790    OMX_U32 nr_avail = 0;
1791
1792    for (i = 0; i < nr_ports; i++) {
1793        OMX_U32 length = 0;
1794
1795        if (ports[i]->IsEnabled())
1796            length = ports[i]->BufferQueueLength();
1797
1798        if (length)
1799            nr_avail++;
1800    }
1801
1802    if (nr_avail == nr_ports)
1803        return true;
1804    else
1805        return false;
1806}
1807
1808void ComponentBase::ScheduleIfAllBufferAvailable(void)
1809{
1810    bool avail;
1811
1812    avail = IsAllBufferAvailable();
1813    if (avail)
1814        bufferwork->ScheduleWork(this);
1815}
1816
1817void ComponentBase::PostProcessBuffer(OMX_BUFFERHEADERTYPE **buffers,
1818                                      bool *retain,
1819                                      OMX_U32 nr_buffers)
1820{
1821    OMX_U32 i;
1822
1823    for (i = 0; i < nr_ports; i++) {
1824        OMX_MARKTYPE *mark;
1825
1826        if (ports[i]->GetPortDirection() == OMX_DirInput) {
1827            bool is_sink_component = true;
1828            OMX_U32 j;
1829
1830            if (buffers[i]->hMarkTargetComponent) {
1831                if (buffers[i]->hMarkTargetComponent == handle) {
1832                    callbacks->EventHandler(handle, appdata, OMX_EventMark,
1833                                            0, 0, buffers[i]->pMarkData);
1834                    buffers[i]->hMarkTargetComponent = NULL;
1835                    buffers[i]->pMarkData = NULL;
1836                }
1837            }
1838
1839            for (j = 0; j < nr_ports; j++) {
1840                if (j == i)
1841                    continue;
1842
1843                if (ports[j]->GetPortDirection() == OMX_DirOutput) {
1844                    if (buffers[i]->nFlags & OMX_BUFFERFLAG_EOS) {
1845                        buffers[j]->nFlags |= OMX_BUFFERFLAG_EOS;
1846                        buffers[i]->nFlags &= ~OMX_BUFFERFLAG_EOS;
1847                        retain[i] = false;
1848                        retain[j] = false;
1849                    }
1850
1851                    if (!buffers[j]->hMarkTargetComponent) {
1852                        mark = ports[j]->PopMark();
1853                        if (mark) {
1854                            buffers[j]->hMarkTargetComponent =
1855                                mark->hMarkTargetComponent;
1856                            buffers[j]->pMarkData = mark->pMarkData;
1857                            free(mark);
1858                            mark = NULL;
1859                        }
1860
1861                        if (buffers[i]->hMarkTargetComponent) {
1862                            if (buffers[j]->hMarkTargetComponent) {
1863                                mark = (OMX_MARKTYPE *)
1864                                    malloc(sizeof(*mark));
1865                                if (mark) {
1866                                    mark->hMarkTargetComponent =
1867                                        buffers[i]->hMarkTargetComponent;
1868                                    mark->pMarkData = buffers[i]->pMarkData;
1869                                    ports[j]->PushMark(mark);
1870                                    mark = NULL;
1871                                    buffers[i]->hMarkTargetComponent = NULL;
1872                                    buffers[i]->pMarkData = NULL;
1873                                }
1874                            }
1875                            else {
1876                                buffers[j]->hMarkTargetComponent =
1877                                    buffers[i]->hMarkTargetComponent;
1878                                buffers[j]->pMarkData = buffers[i]->pMarkData;
1879                                buffers[i]->hMarkTargetComponent = NULL;
1880                                buffers[i]->pMarkData = NULL;
1881                            }
1882                        }
1883                    }
1884                    else {
1885                        if (buffers[i]->hMarkTargetComponent) {
1886                            mark = (OMX_MARKTYPE *)malloc(sizeof(*mark));
1887                            if (mark) {
1888                                mark->hMarkTargetComponent =
1889                                    buffers[i]->hMarkTargetComponent;
1890                                mark->pMarkData = buffers[i]->pMarkData;
1891                                ports[j]->PushMark(mark);
1892                                mark = NULL;
1893                                buffers[i]->hMarkTargetComponent = NULL;
1894                                buffers[i]->pMarkData = NULL;
1895                            }
1896                        }
1897                    }
1898                    is_sink_component = false;
1899                }
1900            }
1901
1902            if (is_sink_component) {
1903                if (buffers[i]->nFlags & OMX_BUFFERFLAG_EOS) {
1904                    callbacks->EventHandler(handle, appdata,
1905                                            OMX_EventBufferFlag,
1906                                            i, buffers[i]->nFlags, NULL);
1907                    retain[i] = false;
1908                }
1909            }
1910        }
1911        else if (ports[i]->GetPortDirection() == OMX_DirOutput) {
1912            bool is_source_component = true;
1913            OMX_U32 j;
1914
1915            if (buffers[i]->nFlags & OMX_BUFFERFLAG_EOS) {
1916                callbacks->EventHandler(handle, appdata,
1917                                        OMX_EventBufferFlag,
1918                                        i, buffers[i]->nFlags, NULL);
1919                retain[i] = false;
1920            }
1921
1922            for (j = 0; j < nr_ports; j++) {
1923                if (j == i)
1924                    continue;
1925
1926                if (ports[j]->GetPortDirection() == OMX_DirInput)
1927                    is_source_component = false;
1928            }
1929
1930            if (is_source_component) {
1931                if (!retain[i]) {
1932                    mark = ports[i]->PopMark();
1933                    if (mark) {
1934                        buffers[i]->hMarkTargetComponent =
1935                            mark->hMarkTargetComponent;
1936                        buffers[i]->pMarkData = mark->pMarkData;
1937                        free(mark);
1938                        mark = NULL;
1939
1940                        if (buffers[i]->hMarkTargetComponent == handle) {
1941                            callbacks->EventHandler(handle, appdata,
1942                                                    OMX_EventMark, 0, 0,
1943                                                    buffers[i]->pMarkData);
1944                            buffers[i]->hMarkTargetComponent = NULL;
1945                            buffers[i]->pMarkData = NULL;
1946                        }
1947                    }
1948                }
1949            }
1950        }
1951        else {
1952            LOGE("%s(): fatal error unknown port direction (0x%08x)\n",
1953                 __func__, ports[i]->GetPortDirection());
1954        }
1955    }
1956}
1957
1958/* processor default callbacks */
1959OMX_ERRORTYPE ComponentBase::ProcessorInit(void)
1960{
1961    return OMX_ErrorNone;
1962}
1963OMX_ERRORTYPE ComponentBase::ProcessorDeinit(void)
1964{
1965    return OMX_ErrorNone;
1966}
1967
1968OMX_ERRORTYPE ComponentBase::ProcessorStart(void)
1969{
1970    return OMX_ErrorNone;
1971}
1972
1973OMX_ERRORTYPE ComponentBase::ProcessorStop(void)
1974{
1975    return OMX_ErrorNone;
1976}
1977
1978OMX_ERRORTYPE ComponentBase::ProcessorPause(void)
1979{
1980    return OMX_ErrorNone;
1981}
1982
1983OMX_ERRORTYPE ComponentBase::ProcessorResume(void)
1984{
1985    return OMX_ErrorNone;
1986}
1987
1988OMX_ERRORTYPE ComponentBase::ProcessorSetConfig(OMX_INDEXTYPE nParamIndex)
1989{
1990    return OMX_ErrorNone;
1991}
1992
1993OMX_ERRORTYPE ComponentBase::ProcessorSetParameter(OMX_INDEXTYPE nParamIndex)
1994{
1995    return OMX_ErrorNone;
1996}
1997
1998/* end of processor callbacks */
1999
2000/* end of component methods & helpers */
2001
2002/*
2003 * omx header manipuation
2004 */
2005void ComponentBase::SetTypeHeader(OMX_PTR type, OMX_U32 size)
2006{
2007    OMX_U32 *nsize;
2008    OMX_VERSIONTYPE *nversion;
2009
2010    if (!type)
2011        return;
2012
2013    nsize = (OMX_U32 *)type;
2014    nversion = (OMX_VERSIONTYPE *)((OMX_U8 *)type + sizeof(OMX_U32));
2015
2016    *nsize = size;
2017    nversion->nVersion = OMX_SPEC_VERSION;
2018}
2019
2020OMX_ERRORTYPE ComponentBase::CheckTypeHeader(const OMX_PTR type, OMX_U32 size)
2021{
2022    OMX_U32 *nsize;
2023    OMX_VERSIONTYPE *nversion;
2024
2025    if (!type)
2026        return OMX_ErrorBadParameter;
2027
2028    nsize = (OMX_U32 *)type;
2029    nversion = (OMX_VERSIONTYPE *)((OMX_U8 *)type + sizeof(OMX_U32));
2030
2031    if (*nsize != size)
2032        return OMX_ErrorBadParameter;
2033
2034    if (nversion->nVersion != OMX_SPEC_VERSION)
2035        return OMX_ErrorVersionMismatch;
2036
2037    return OMX_ErrorNone;
2038}
2039
2040/*
2041 * query_roles helper
2042 */
2043OMX_ERRORTYPE ComponentBase::QueryRolesHelper(
2044    OMX_U32 nr_comp_roles,
2045    const OMX_U8 **comp_roles,
2046    OMX_U32 *nr_roles, OMX_U8 **roles)
2047{
2048    OMX_U32 i;
2049
2050    if (!roles) {
2051        *nr_roles = nr_comp_roles;
2052        return OMX_ErrorNone;
2053    }
2054
2055    if (!nr_roles || (*nr_roles != nr_comp_roles) || !roles)
2056        return OMX_ErrorBadParameter;
2057
2058    for (i = 0; i < nr_comp_roles; i++) {
2059        if (!roles[i])
2060            break;
2061
2062        strncpy((OMX_STRING)&roles[i][0],
2063                (const OMX_STRING)&comp_roles[i][0], OMX_MAX_STRINGNAME_SIZE);
2064    }
2065
2066    if (i != nr_comp_roles)
2067        return OMX_ErrorBadParameter;
2068
2069    *nr_roles = nr_comp_roles;
2070    return OMX_ErrorNone;
2071}
2072
2073/* end of ComponentBase */
2074