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