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