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