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