componentbase.cpp revision ec2f29d0c23a6c7ea3a36e03a9635b63ac23ae35
1/*
2 * componentbase.cpp, component base class
3 *
4 * Copyright (c) 2009-2010 Wind River Systems, Inc.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#include <stdlib.h>
20#include <string.h>
21
22#include <pthread.h>
23
24#include <OMX_Core.h>
25#include <OMX_Component.h>
26
27#include <componentbase.h>
28
29#include <queue.h>
30#include <workqueue.h>
31#include <OMX_IndexExt.h>
32
33//#define LOG_NDEBUG 0
34
35#define LOG_TAG "componentbase"
36#include <log.h>
37
38/*
39 * CmdProcessWork
40 */
41CmdProcessWork::CmdProcessWork(CmdHandlerInterface *ci)
42{
43    this->ci = ci;
44
45    workq = new WorkQueue;
46
47    __queue_init(&q);
48    pthread_mutex_init(&lock, NULL);
49
50    workq->StartWork(true);
51
52    LOGV("command process workqueue started\n");
53}
54
55CmdProcessWork::~CmdProcessWork()
56{
57    struct cmd_s *temp;
58
59    workq->StopWork();
60    delete workq;
61
62    while ((temp = PopCmdQueue()))
63        free(temp);
64
65    pthread_mutex_destroy(&lock);
66
67    LOGV("command process workqueue stopped\n");
68}
69
70OMX_ERRORTYPE CmdProcessWork::PushCmdQueue(struct cmd_s *cmd)
71{
72    int ret;
73
74    pthread_mutex_lock(&lock);
75    ret = queue_push_tail(&q, cmd);
76    if (ret) {
77        pthread_mutex_unlock(&lock);
78        return OMX_ErrorInsufficientResources;
79    }
80
81    workq->ScheduleWork(this);
82    pthread_mutex_unlock(&lock);
83
84    return OMX_ErrorNone;
85}
86
87struct cmd_s *CmdProcessWork::PopCmdQueue(void)
88{
89    struct cmd_s *cmd;
90
91    pthread_mutex_lock(&lock);
92    cmd = (struct cmd_s *)queue_pop_head(&q);
93    pthread_mutex_unlock(&lock);
94
95    return cmd;
96}
97
98void CmdProcessWork::Work(void)
99{
100    struct cmd_s *cmd;
101
102    cmd = PopCmdQueue();
103    if (cmd) {
104        ci->CmdHandler(cmd);
105        free(cmd);
106    }
107}
108
109/* end of CmdProcessWork */
110
111/*
112 * ComponentBase
113 */
114/*
115 * constructor & destructor
116 */
117void ComponentBase::__ComponentBase(void)
118{
119    memset(name, 0, OMX_MAX_STRINGNAME_SIZE);
120    cmodule = NULL;
121    handle = NULL;
122
123    roles = NULL;
124    nr_roles = 0;
125
126    working_role = NULL;
127
128    ports = NULL;
129    nr_ports = 0;
130    memset(&portparam, 0, sizeof(portparam));
131
132    state = OMX_StateUnloaded;
133
134    cmdwork = NULL;
135
136    bufferwork = NULL;
137
138    pthread_mutex_init(&ports_block, NULL);
139}
140
141ComponentBase::ComponentBase()
142{
143    __ComponentBase();
144}
145
146ComponentBase::ComponentBase(const OMX_STRING name)
147{
148    __ComponentBase();
149    SetName(name);
150}
151
152ComponentBase::~ComponentBase()
153{
154    pthread_mutex_destroy(&ports_block);
155
156    if (roles) {
157        if (roles[0])
158            free(roles[0]);
159        free(roles);
160    }
161}
162
163/* end of constructor & destructor */
164
165/*
166 * accessor
167 */
168/* name */
169void ComponentBase::SetName(const OMX_STRING name)
170{
171    strncpy(this->name, name, (strlen(name) < OMX_MAX_STRINGNAME_SIZE) ? strlen(name) : (OMX_MAX_STRINGNAME_SIZE-1));
172   // strncpy(this->name, name, OMX_MAX_STRINGNAME_SIZE);
173    this->name[OMX_MAX_STRINGNAME_SIZE-1] = '\0';
174}
175
176const OMX_STRING ComponentBase::GetName(void)
177{
178    return name;
179}
180
181/* component module */
182void ComponentBase::SetCModule(CModule *cmodule)
183{
184    this->cmodule = cmodule;
185}
186
187CModule *ComponentBase::GetCModule(void)
188{
189    return cmodule;
190}
191
192/* end of accessor */
193
194/*
195 * core methods & helpers
196 */
197/* roles */
198OMX_ERRORTYPE ComponentBase::SetRolesOfComponent(OMX_U32 nr_roles,
199                                                 const OMX_U8 **roles)
200{
201    OMX_U32 i;
202
203    if (!roles || !nr_roles)
204        return OMX_ErrorBadParameter;
205
206    if (this->roles) {
207        free(this->roles[0]);
208        free(this->roles);
209        this->roles = NULL;
210    }
211
212    this->roles = (OMX_U8 **)malloc(sizeof(OMX_STRING) * nr_roles);
213    if (!this->roles)
214        return OMX_ErrorInsufficientResources;
215
216    this->roles[0] = (OMX_U8 *)malloc(OMX_MAX_STRINGNAME_SIZE * nr_roles);
217    if (!this->roles[0]) {
218        free(this->roles);
219        this->roles = NULL;
220        return OMX_ErrorInsufficientResources;
221    }
222
223    for (i = 0; i < nr_roles; i++) {
224        if (i < nr_roles-1)
225            this->roles[i+1] = this->roles[i] + OMX_MAX_STRINGNAME_SIZE;
226
227        strncpy((OMX_STRING)&this->roles[i][0],
228                (const OMX_STRING)&roles[i][0], OMX_MAX_STRINGNAME_SIZE);
229    }
230
231    this->nr_roles = nr_roles;
232    return OMX_ErrorNone;
233}
234
235/* GetHandle & FreeHandle */
236OMX_ERRORTYPE ComponentBase::GetHandle(OMX_HANDLETYPE *pHandle,
237                                       OMX_PTR pAppData,
238                                       OMX_CALLBACKTYPE *pCallBacks)
239{
240    OMX_U32 i;
241    OMX_ERRORTYPE ret;
242
243    if (!pHandle)
244        return OMX_ErrorBadParameter;
245
246    if (handle)
247        return OMX_ErrorUndefined;
248
249    cmdwork = new CmdProcessWork(this);
250    if (!cmdwork)
251        return OMX_ErrorInsufficientResources;
252
253    bufferwork = new WorkQueue();
254    if (!bufferwork) {
255        ret = OMX_ErrorInsufficientResources;
256        goto free_cmdwork;
257    }
258
259    handle = (OMX_COMPONENTTYPE *)calloc(1, sizeof(*handle));
260    if (!handle) {
261        ret = OMX_ErrorInsufficientResources;
262        goto free_bufferwork;
263    }
264
265    /* handle initialization */
266    SetTypeHeader(handle, sizeof(*handle));
267    handle->pComponentPrivate = static_cast<OMX_PTR>(this);
268    handle->pApplicationPrivate = pAppData;
269
270    /* connect handle's functions */
271    handle->GetComponentVersion = NULL;
272    handle->SendCommand = SendCommand;
273    handle->GetParameter = GetParameter;
274    handle->SetParameter = SetParameter;
275    handle->GetConfig = GetConfig;
276    handle->SetConfig = SetConfig;
277    handle->GetExtensionIndex = GetExtensionIndex;
278    handle->GetState = GetState;
279    handle->ComponentTunnelRequest = NULL;
280    handle->UseBuffer = UseBuffer;
281    handle->AllocateBuffer = AllocateBuffer;
282    handle->FreeBuffer = FreeBuffer;
283    handle->EmptyThisBuffer = EmptyThisBuffer;
284    handle->FillThisBuffer = FillThisBuffer;
285    handle->SetCallbacks = SetCallbacks;
286    handle->ComponentDeInit = NULL;
287    handle->UseEGLImage = NULL;
288    handle->ComponentRoleEnum = ComponentRoleEnum;
289
290    appdata = pAppData;
291    callbacks = pCallBacks;
292
293    if (nr_roles == 1) {
294        SetWorkingRole((OMX_STRING)&roles[0][0]);
295        ret = ApplyWorkingRole();
296        if (ret != OMX_ErrorNone) {
297            SetWorkingRole(NULL);
298            goto free_handle;
299        }
300    }
301
302    *pHandle = (OMX_HANDLETYPE *)handle;
303    state = OMX_StateLoaded;
304    return OMX_ErrorNone;
305
306free_handle:
307    free(handle);
308
309    appdata = NULL;
310    callbacks = NULL;
311    *pHandle = NULL;
312
313free_bufferwork:
314    delete bufferwork;
315
316free_cmdwork:
317    delete cmdwork;
318
319    return ret;
320}
321
322OMX_ERRORTYPE ComponentBase::FreeHandle(OMX_HANDLETYPE hComponent)
323{
324    OMX_ERRORTYPE ret;
325
326    if (hComponent != handle)
327        return OMX_ErrorBadParameter;
328
329    if (state != OMX_StateLoaded)
330        return OMX_ErrorIncorrectStateOperation;
331
332    FreePorts();
333
334    free(handle);
335
336    appdata = NULL;
337    callbacks = NULL;
338
339    delete cmdwork;
340    delete bufferwork;
341
342    state = OMX_StateUnloaded;
343    return OMX_ErrorNone;
344}
345
346/* end of core methods & helpers */
347
348/*
349 * component methods & helpers
350 */
351OMX_ERRORTYPE ComponentBase::SendCommand(
352    OMX_IN  OMX_HANDLETYPE hComponent,
353    OMX_IN  OMX_COMMANDTYPE Cmd,
354    OMX_IN  OMX_U32 nParam1,
355    OMX_IN  OMX_PTR pCmdData)
356{
357    ComponentBase *cbase;
358
359    if (!hComponent)
360        return OMX_ErrorBadParameter;
361
362    cbase = static_cast<ComponentBase *>
363        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
364    if (!cbase)
365        return OMX_ErrorBadParameter;
366
367    return cbase->CBaseSendCommand(hComponent, Cmd, nParam1, pCmdData);
368}
369
370OMX_ERRORTYPE ComponentBase::CBaseSendCommand(
371    OMX_IN  OMX_HANDLETYPE hComponent,
372    OMX_IN  OMX_COMMANDTYPE Cmd,
373    OMX_IN  OMX_U32 nParam1,
374    OMX_IN  OMX_PTR pCmdData)
375{
376    struct cmd_s *cmd;
377
378    if (hComponent != handle)
379        return OMX_ErrorInvalidComponent;
380
381    /* basic error check */
382    switch (Cmd) {
383    case OMX_CommandStateSet:
384        /*
385         * Todo
386         */
387        break;
388    case OMX_CommandFlush: {
389        OMX_U32 port_index = nParam1;
390
391        if ((port_index != OMX_ALL) && (port_index > nr_ports-1))
392            return OMX_ErrorBadPortIndex;
393        break;
394    }
395    case OMX_CommandPortDisable:
396    case OMX_CommandPortEnable: {
397        OMX_U32 port_index = nParam1;
398
399        if ((port_index != OMX_ALL) && (port_index > nr_ports-1))
400            return OMX_ErrorBadPortIndex;
401        break;
402    }
403    case OMX_CommandMarkBuffer: {
404        OMX_MARKTYPE *mark = (OMX_MARKTYPE *)pCmdData;
405        OMX_MARKTYPE *copiedmark;
406        OMX_U32 port_index = nParam1;
407
408        if (port_index > nr_ports-1)
409            return OMX_ErrorBadPortIndex;
410
411        if (!mark || !mark->hMarkTargetComponent)
412            return OMX_ErrorBadParameter;
413
414        copiedmark = (OMX_MARKTYPE *)malloc(sizeof(*copiedmark));
415        if (!copiedmark)
416            return OMX_ErrorInsufficientResources;
417
418        copiedmark->hMarkTargetComponent = mark->hMarkTargetComponent;
419        copiedmark->pMarkData = mark->pMarkData;
420        pCmdData = (OMX_PTR)copiedmark;
421        break;
422    }
423    default:
424        LOGE("command %d not supported\n", Cmd);
425        return OMX_ErrorUnsupportedIndex;
426    }
427
428    cmd = (struct cmd_s *)malloc(sizeof(*cmd));
429    if (!cmd)
430        return OMX_ErrorInsufficientResources;
431
432    cmd->cmd = Cmd;
433    cmd->param1 = nParam1;
434    cmd->cmddata = pCmdData;
435
436    return cmdwork->PushCmdQueue(cmd);
437}
438
439OMX_ERRORTYPE ComponentBase::GetParameter(
440    OMX_IN  OMX_HANDLETYPE hComponent,
441    OMX_IN  OMX_INDEXTYPE nParamIndex,
442    OMX_INOUT OMX_PTR pComponentParameterStructure)
443{
444    ComponentBase *cbase;
445
446    if (!hComponent)
447        return OMX_ErrorBadParameter;
448
449    cbase = static_cast<ComponentBase *>
450        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
451    if (!cbase)
452        return OMX_ErrorBadParameter;
453
454    return cbase->CBaseGetParameter(hComponent, nParamIndex,
455                                    pComponentParameterStructure);
456}
457
458OMX_ERRORTYPE ComponentBase::CBaseGetParameter(
459    OMX_IN  OMX_HANDLETYPE hComponent,
460    OMX_IN  OMX_INDEXTYPE nParamIndex,
461    OMX_INOUT OMX_PTR pComponentParameterStructure)
462{
463    OMX_ERRORTYPE ret = OMX_ErrorNone;
464
465    if (hComponent != handle)
466        return OMX_ErrorBadParameter;
467
468    switch (nParamIndex) {
469    case OMX_IndexParamAudioInit:
470    case OMX_IndexParamVideoInit:
471    case OMX_IndexParamImageInit:
472    case OMX_IndexParamOtherInit: {
473        OMX_PORT_PARAM_TYPE *p =
474            (OMX_PORT_PARAM_TYPE *)pComponentParameterStructure;
475
476        ret = CheckTypeHeader(p, sizeof(*p));
477        if (ret != OMX_ErrorNone)
478            return ret;
479
480        memcpy(p, &portparam, sizeof(*p));
481        break;
482    }
483    case OMX_IndexParamPortDefinition: {
484        OMX_PARAM_PORTDEFINITIONTYPE *p =
485            (OMX_PARAM_PORTDEFINITIONTYPE *)pComponentParameterStructure;
486        OMX_U32 index = p->nPortIndex;
487        PortBase *port = NULL;
488
489        ret = CheckTypeHeader(p, sizeof(*p));
490        if (ret != OMX_ErrorNone)
491            return ret;
492
493        if (index < nr_ports)
494            port = ports[index];
495
496        if (!port)
497            return OMX_ErrorBadPortIndex;
498
499        memcpy(p, port->GetPortDefinition(), sizeof(*p));
500        break;
501    }
502    case OMX_IndexParamCompBufferSupplier:
503        /*
504         * Todo
505         */
506
507        ret = OMX_ErrorUnsupportedIndex;
508        break;
509
510    default:
511        ret = ComponentGetParameter(nParamIndex, pComponentParameterStructure);
512    } /* switch */
513
514    return ret;
515}
516
517OMX_ERRORTYPE ComponentBase::SetParameter(
518    OMX_IN  OMX_HANDLETYPE hComponent,
519    OMX_IN  OMX_INDEXTYPE nIndex,
520    OMX_IN  OMX_PTR pComponentParameterStructure)
521{
522    ComponentBase *cbase;
523
524    if (!hComponent)
525        return OMX_ErrorBadParameter;
526
527    cbase = static_cast<ComponentBase *>
528        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
529    if (!cbase)
530        return OMX_ErrorBadParameter;
531
532    return cbase->CBaseSetParameter(hComponent, nIndex,
533                                    pComponentParameterStructure);
534}
535
536OMX_ERRORTYPE ComponentBase::CBaseSetParameter(
537    OMX_IN  OMX_HANDLETYPE hComponent,
538    OMX_IN  OMX_INDEXTYPE nIndex,
539    OMX_IN  OMX_PTR pComponentParameterStructure)
540{
541    OMX_ERRORTYPE ret = OMX_ErrorNone;
542
543    if (hComponent != handle)
544        return OMX_ErrorBadParameter;
545
546    switch (nIndex) {
547    case OMX_IndexParamAudioInit:
548    case OMX_IndexParamVideoInit:
549    case OMX_IndexParamImageInit:
550    case OMX_IndexParamOtherInit:
551        /* preventing clients from setting OMX_PORT_PARAM_TYPE */
552        ret = OMX_ErrorUnsupportedIndex;
553        break;
554    case OMX_IndexParamPortDefinition: {
555        OMX_PARAM_PORTDEFINITIONTYPE *p =
556            (OMX_PARAM_PORTDEFINITIONTYPE *)pComponentParameterStructure;
557        OMX_U32 index = p->nPortIndex;
558        PortBase *port = NULL;
559
560        ret = CheckTypeHeader(p, sizeof(*p));
561        if (ret != OMX_ErrorNone)
562            return ret;
563
564        if (index < nr_ports)
565            port = ports[index];
566
567        if (!port)
568            return OMX_ErrorBadPortIndex;
569
570        if (port->IsEnabled()) {
571            if (state != OMX_StateLoaded && state != OMX_StateWaitForResources)
572                return OMX_ErrorIncorrectStateOperation;
573        }
574
575        port->SetPortDefinition(p, false);
576        break;
577    }
578    case OMX_IndexParamCompBufferSupplier:
579        /*
580         * Todo
581         */
582
583        ret = OMX_ErrorUnsupportedIndex;
584        break;
585    case OMX_IndexParamStandardComponentRole: {
586        OMX_PARAM_COMPONENTROLETYPE *p =
587            (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure;
588
589        if (state != OMX_StateLoaded && state != OMX_StateWaitForResources)
590            return OMX_ErrorIncorrectStateOperation;
591
592        ret = CheckTypeHeader(p, sizeof(*p));
593        if (ret != OMX_ErrorNone)
594            return ret;
595
596        ret = SetWorkingRole((OMX_STRING)p->cRole);
597        if (ret != OMX_ErrorNone)
598            return ret;
599
600        if (ports)
601            FreePorts();
602
603        ret = ApplyWorkingRole();
604        if (ret != OMX_ErrorNone) {
605            SetWorkingRole(NULL);
606            return ret;
607        }
608        break;
609    }
610
611    default:
612        ret = ComponentSetParameter(nIndex, pComponentParameterStructure);
613    } /* switch */
614
615    return ret;
616}
617
618OMX_ERRORTYPE ComponentBase::GetConfig(
619    OMX_IN  OMX_HANDLETYPE hComponent,
620    OMX_IN  OMX_INDEXTYPE nIndex,
621    OMX_INOUT OMX_PTR pComponentConfigStructure)
622{
623    ComponentBase *cbase;
624
625    if (!hComponent)
626        return OMX_ErrorBadParameter;
627
628    cbase = static_cast<ComponentBase *>
629        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
630    if (!cbase)
631        return OMX_ErrorBadParameter;
632
633    return cbase->CBaseGetConfig(hComponent, nIndex,
634                                 pComponentConfigStructure);
635}
636
637OMX_ERRORTYPE ComponentBase::CBaseGetConfig(
638    OMX_IN  OMX_HANDLETYPE hComponent,
639    OMX_IN  OMX_INDEXTYPE nIndex,
640    OMX_INOUT OMX_PTR pComponentConfigStructure)
641{
642    OMX_ERRORTYPE ret;
643
644    if (hComponent != handle)
645        return OMX_ErrorBadParameter;
646
647    switch (nIndex) {
648    default:
649        ret = ComponentGetConfig(nIndex, pComponentConfigStructure);
650    }
651
652    return ret;
653}
654
655OMX_ERRORTYPE ComponentBase::SetConfig(
656    OMX_IN  OMX_HANDLETYPE hComponent,
657    OMX_IN  OMX_INDEXTYPE nIndex,
658    OMX_IN  OMX_PTR pComponentConfigStructure)
659{
660    ComponentBase *cbase;
661
662    if (!hComponent)
663        return OMX_ErrorBadParameter;
664
665    cbase = static_cast<ComponentBase *>
666        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
667    if (!cbase)
668        return OMX_ErrorBadParameter;
669
670    return cbase->CBaseSetConfig(hComponent, nIndex,
671                                 pComponentConfigStructure);
672}
673
674OMX_ERRORTYPE ComponentBase::CBaseSetConfig(
675    OMX_IN  OMX_HANDLETYPE hComponent,
676    OMX_IN  OMX_INDEXTYPE nIndex,
677    OMX_IN  OMX_PTR pComponentConfigStructure)
678{
679    OMX_ERRORTYPE ret;
680
681    if (hComponent != handle)
682        return OMX_ErrorBadParameter;
683
684    switch (nIndex) {
685    default:
686        ret = ComponentSetConfig(nIndex, pComponentConfigStructure);
687    }
688
689    return ret;
690}
691
692OMX_ERRORTYPE ComponentBase::GetExtensionIndex(
693    OMX_IN  OMX_HANDLETYPE hComponent,
694    OMX_IN  OMX_STRING cParameterName,
695    OMX_OUT OMX_INDEXTYPE* pIndexType)
696{
697    ComponentBase *cbase;
698
699    if (!hComponent)
700        return OMX_ErrorBadParameter;
701
702    cbase = static_cast<ComponentBase *>
703        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
704    if (!cbase)
705        return OMX_ErrorBadParameter;
706
707    return cbase->CBaseGetExtensionIndex(hComponent, cParameterName,
708                                         pIndexType);
709}
710
711OMX_ERRORTYPE ComponentBase::CBaseGetExtensionIndex(
712    OMX_IN  OMX_HANDLETYPE hComponent,
713    OMX_IN  OMX_STRING cParameterName,
714    OMX_OUT OMX_INDEXTYPE* pIndexType)
715{
716    /*
717     * Todo
718     */
719    if (hComponent != handle) {
720
721        return OMX_ErrorBadParameter;
722    }
723
724    if (!strcmp(cParameterName, "OMX.google.android.index.storeMetaDataInBuffers")) {
725        *pIndexType = static_cast<OMX_INDEXTYPE>(OMX_IndexStoreMetaDataInBuffers);
726        return OMX_ErrorNone;
727    }
728
729    if (!strcmp(cParameterName, "OMX.google.android.index.enableAndroidNativeBuffers")) {
730        *pIndexType = static_cast<OMX_INDEXTYPE>(OMX_IndexExtEnableNativeBuffer);
731        return OMX_ErrorNone;
732    }
733
734    if (!strcmp(cParameterName, "OMX.google.android.index.getAndroidNativeBufferUsage")) {
735        *pIndexType = static_cast<OMX_INDEXTYPE>(OMX_IndexExtGetNativeBufferUsage);
736        return OMX_ErrorNone;
737    }
738
739    if (!strcmp(cParameterName, "OMX.google.android.index.useAndroidNativeBuffer")) {
740        *pIndexType = static_cast<OMX_INDEXTYPE>(OMX_IndexExtUseNativeBuffer);
741        return OMX_ErrorNone;
742    }
743    if (!strcmp(cParameterName, "OMX.Intel.index.rotation")) {
744        *pIndexType = static_cast<OMX_INDEXTYPE>(OMX_IndexExtRotationDegrees);
745        return OMX_ErrorNone;
746    }
747
748    return OMX_ErrorUnsupportedIndex;
749}
750
751OMX_ERRORTYPE ComponentBase::GetState(
752    OMX_IN  OMX_HANDLETYPE hComponent,
753    OMX_OUT OMX_STATETYPE* pState)
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->CBaseGetState(hComponent, pState);
766}
767
768OMX_ERRORTYPE ComponentBase::CBaseGetState(
769    OMX_IN  OMX_HANDLETYPE hComponent,
770    OMX_OUT OMX_STATETYPE* pState)
771{
772    if (hComponent != handle)
773        return OMX_ErrorBadParameter;
774
775    *pState = state;
776    return OMX_ErrorNone;
777}
778OMX_ERRORTYPE ComponentBase::UseBuffer(
779    OMX_IN OMX_HANDLETYPE hComponent,
780    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr,
781    OMX_IN OMX_U32 nPortIndex,
782    OMX_IN OMX_PTR pAppPrivate,
783    OMX_IN OMX_U32 nSizeBytes,
784    OMX_IN OMX_U8 *pBuffer)
785{
786    ComponentBase *cbase;
787
788    if (!hComponent)
789        return OMX_ErrorBadParameter;
790
791    cbase = static_cast<ComponentBase *>
792        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
793    if (!cbase)
794        return OMX_ErrorBadParameter;
795
796    return cbase->CBaseUseBuffer(hComponent, ppBufferHdr, nPortIndex,
797                                 pAppPrivate, nSizeBytes, pBuffer);
798}
799
800OMX_ERRORTYPE ComponentBase::CBaseUseBuffer(
801    OMX_IN OMX_HANDLETYPE hComponent,
802    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr,
803    OMX_IN OMX_U32 nPortIndex,
804    OMX_IN OMX_PTR pAppPrivate,
805    OMX_IN OMX_U32 nSizeBytes,
806    OMX_IN OMX_U8 *pBuffer)
807{
808    PortBase *port = NULL;
809    OMX_ERRORTYPE ret;
810
811    if (hComponent != handle)
812        return OMX_ErrorBadParameter;
813
814    if (!ppBufferHdr)
815        return OMX_ErrorBadParameter;
816    *ppBufferHdr = NULL;
817
818    if (!pBuffer)
819        return OMX_ErrorBadParameter;
820
821    if (ports)
822        if (nPortIndex < nr_ports)
823            port = ports[nPortIndex];
824
825    if (!port)
826        return OMX_ErrorBadParameter;
827
828    if (port->IsEnabled()) {
829        if (state != OMX_StateLoaded && state != OMX_StateWaitForResources)
830            return OMX_ErrorIncorrectStateOperation;
831    }
832
833    return port->UseBuffer(ppBufferHdr, nPortIndex, pAppPrivate, nSizeBytes,
834                           pBuffer);
835}
836
837OMX_ERRORTYPE ComponentBase::AllocateBuffer(
838    OMX_IN OMX_HANDLETYPE hComponent,
839    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer,
840    OMX_IN OMX_U32 nPortIndex,
841    OMX_IN OMX_PTR pAppPrivate,
842    OMX_IN OMX_U32 nSizeBytes)
843{
844    ComponentBase *cbase;
845
846    if (!hComponent)
847        return OMX_ErrorBadParameter;
848
849    cbase = static_cast<ComponentBase *>
850        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
851    if (!cbase)
852        return OMX_ErrorBadParameter;
853
854    return cbase->CBaseAllocateBuffer(hComponent, ppBuffer, nPortIndex,
855                                      pAppPrivate, nSizeBytes);
856}
857
858OMX_ERRORTYPE ComponentBase::CBaseAllocateBuffer(
859    OMX_IN OMX_HANDLETYPE hComponent,
860    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer,
861    OMX_IN OMX_U32 nPortIndex,
862    OMX_IN OMX_PTR pAppPrivate,
863    OMX_IN OMX_U32 nSizeBytes)
864{
865    PortBase *port = NULL;
866    OMX_ERRORTYPE ret;
867
868    if (hComponent != handle)
869        return OMX_ErrorBadParameter;
870
871    if (!ppBuffer)
872        return OMX_ErrorBadParameter;
873    *ppBuffer = NULL;
874
875    if (ports)
876        if (nPortIndex < nr_ports)
877            port = ports[nPortIndex];
878
879    if (!port)
880        return OMX_ErrorBadParameter;
881
882    if (port->IsEnabled()) {
883        if (state != OMX_StateLoaded && state != OMX_StateWaitForResources)
884            return OMX_ErrorIncorrectStateOperation;
885    }
886
887    return port->AllocateBuffer(ppBuffer, nPortIndex, pAppPrivate, nSizeBytes);
888}
889
890OMX_ERRORTYPE ComponentBase::FreeBuffer(
891    OMX_IN  OMX_HANDLETYPE hComponent,
892    OMX_IN  OMX_U32 nPortIndex,
893    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
894{
895    ComponentBase *cbase;
896
897    if (!hComponent)
898        return OMX_ErrorBadParameter;
899
900    cbase = static_cast<ComponentBase *>
901        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
902    if (!cbase)
903        return OMX_ErrorBadParameter;
904
905    return cbase->CBaseFreeBuffer(hComponent, nPortIndex, pBuffer);
906}
907
908OMX_ERRORTYPE ComponentBase::CBaseFreeBuffer(
909    OMX_IN  OMX_HANDLETYPE hComponent,
910    OMX_IN  OMX_U32 nPortIndex,
911    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
912{
913    PortBase *port = NULL;
914    OMX_ERRORTYPE ret;
915
916    if (hComponent != handle)
917        return OMX_ErrorBadParameter;
918
919    if (!pBuffer)
920        return OMX_ErrorBadParameter;
921
922    if (ports)
923        if (nPortIndex < nr_ports)
924            port = ports[nPortIndex];
925
926    if (!port)
927        return OMX_ErrorBadParameter;
928
929    ProcessorPreFreeBuffer(nPortIndex, pBuffer);
930
931    return port->FreeBuffer(nPortIndex, pBuffer);
932}
933
934OMX_ERRORTYPE ComponentBase::EmptyThisBuffer(
935    OMX_IN  OMX_HANDLETYPE hComponent,
936    OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer)
937{
938    ComponentBase *cbase;
939
940    if (!hComponent)
941        return OMX_ErrorBadParameter;
942
943    cbase = static_cast<ComponentBase *>
944        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
945    if (!cbase)
946        return OMX_ErrorBadParameter;
947
948    return cbase->CBaseEmptyThisBuffer(hComponent, pBuffer);
949}
950
951OMX_ERRORTYPE ComponentBase::CBaseEmptyThisBuffer(
952    OMX_IN  OMX_HANDLETYPE hComponent,
953    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
954{
955    PortBase *port = NULL;
956    OMX_U32 port_index;
957    OMX_ERRORTYPE ret;
958
959    if ((hComponent != handle) || !pBuffer)
960        return OMX_ErrorBadParameter;
961
962    ret = CheckTypeHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE));
963    if (ret != OMX_ErrorNone)
964        return ret;
965
966    port_index = pBuffer->nInputPortIndex;
967    if (port_index == (OMX_U32)-1)
968        return OMX_ErrorBadParameter;
969
970    if (ports)
971        if (port_index < nr_ports)
972            port = ports[port_index];
973
974    if (!port)
975        return OMX_ErrorBadParameter;
976
977    if (pBuffer->pInputPortPrivate != port)
978        return OMX_ErrorBadParameter;
979
980    if (port->IsEnabled()) {
981        if (state != OMX_StateIdle && state != OMX_StateExecuting &&
982            state != OMX_StatePause)
983            return OMX_ErrorIncorrectStateOperation;
984    }
985
986    if (!pBuffer->hMarkTargetComponent) {
987        OMX_MARKTYPE *mark;
988
989        mark = port->PopMark();
990        if (mark) {
991            pBuffer->hMarkTargetComponent = mark->hMarkTargetComponent;
992            pBuffer->pMarkData = mark->pMarkData;
993            free(mark);
994        }
995    }
996
997    ret = port->PushThisBuffer(pBuffer);
998    if (ret == OMX_ErrorNone)
999        bufferwork->ScheduleWork(this);
1000
1001    return ret;
1002}
1003
1004OMX_ERRORTYPE ComponentBase::FillThisBuffer(
1005    OMX_IN  OMX_HANDLETYPE hComponent,
1006    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
1007{
1008    ComponentBase *cbase;
1009
1010    if (!hComponent)
1011        return OMX_ErrorBadParameter;
1012
1013    cbase = static_cast<ComponentBase *>
1014        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
1015    if (!cbase)
1016        return OMX_ErrorBadParameter;
1017
1018    return cbase->CBaseFillThisBuffer(hComponent, pBuffer);
1019}
1020
1021OMX_ERRORTYPE ComponentBase::CBaseFillThisBuffer(
1022    OMX_IN  OMX_HANDLETYPE hComponent,
1023    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
1024{
1025    PortBase *port = NULL;
1026    OMX_U32 port_index;
1027    OMX_ERRORTYPE ret;
1028
1029    if ((hComponent != handle) || !pBuffer)
1030        return OMX_ErrorBadParameter;
1031
1032    ret = CheckTypeHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE));
1033    if (ret != OMX_ErrorNone)
1034        return ret;
1035
1036    port_index = pBuffer->nOutputPortIndex;
1037    if (port_index == (OMX_U32)-1)
1038        return OMX_ErrorBadParameter;
1039
1040    if (ports)
1041        if (port_index < nr_ports)
1042            port = ports[port_index];
1043
1044    if (!port)
1045        return OMX_ErrorBadParameter;
1046
1047    if (pBuffer->pOutputPortPrivate != port)
1048        return OMX_ErrorBadParameter;
1049
1050    if (port->IsEnabled()) {
1051        if (state != OMX_StateIdle && state != OMX_StateExecuting &&
1052            state != OMX_StatePause)
1053            return OMX_ErrorIncorrectStateOperation;
1054    }
1055
1056    ProcessorPreFillBuffer(pBuffer);
1057
1058    ret = port->PushThisBuffer(pBuffer);
1059    if (ret == OMX_ErrorNone)
1060        bufferwork->ScheduleWork(this);
1061
1062    return ret;
1063}
1064
1065OMX_ERRORTYPE ComponentBase::SetCallbacks(
1066    OMX_IN  OMX_HANDLETYPE hComponent,
1067    OMX_IN  OMX_CALLBACKTYPE* pCallbacks,
1068    OMX_IN  OMX_PTR pAppData)
1069{
1070    ComponentBase *cbase;
1071
1072    if (!hComponent)
1073        return OMX_ErrorBadParameter;
1074
1075    cbase = static_cast<ComponentBase *>
1076        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
1077    if (!cbase)
1078        return OMX_ErrorBadParameter;
1079
1080    return cbase->CBaseSetCallbacks(hComponent, pCallbacks, pAppData);
1081}
1082
1083OMX_ERRORTYPE ComponentBase::CBaseSetCallbacks(
1084    OMX_IN  OMX_HANDLETYPE hComponent,
1085    OMX_IN  OMX_CALLBACKTYPE *pCallbacks,
1086    OMX_IN  OMX_PTR pAppData)
1087{
1088    if (hComponent != handle)
1089        return OMX_ErrorBadParameter;
1090
1091    appdata = pAppData;
1092    callbacks = pCallbacks;
1093
1094    return OMX_ErrorNone;
1095}
1096
1097OMX_ERRORTYPE ComponentBase::ComponentRoleEnum(
1098    OMX_IN OMX_HANDLETYPE hComponent,
1099    OMX_OUT OMX_U8 *cRole,
1100    OMX_IN OMX_U32 nIndex)
1101{
1102    ComponentBase *cbase;
1103
1104    if (!hComponent)
1105        return OMX_ErrorBadParameter;
1106
1107    cbase = static_cast<ComponentBase *>
1108        (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
1109    if (!cbase)
1110        return OMX_ErrorBadParameter;
1111
1112    return cbase->CBaseComponentRoleEnum(hComponent, cRole, nIndex);
1113}
1114
1115OMX_ERRORTYPE ComponentBase::CBaseComponentRoleEnum(
1116    OMX_IN OMX_HANDLETYPE hComponent,
1117    OMX_OUT OMX_U8 *cRole,
1118    OMX_IN OMX_U32 nIndex)
1119{
1120    if (hComponent != (OMX_HANDLETYPE *)this->handle)
1121        return OMX_ErrorBadParameter;
1122
1123    if (nIndex >= nr_roles)
1124        return OMX_ErrorBadParameter;
1125
1126    strncpy((char *)cRole, (const char *)roles[nIndex],
1127            OMX_MAX_STRINGNAME_SIZE);
1128    return OMX_ErrorNone;
1129}
1130
1131/* implement CmdHandlerInterface */
1132static const char *cmd_name[OMX_CommandMarkBuffer+2] = {
1133    "OMX_CommandStateSet",
1134    "OMX_CommandFlush",
1135    "OMX_CommandPortDisable",
1136    "OMX_CommandPortEnable",
1137    "OMX_CommandMarkBuffer",
1138    "Unknown Command",
1139};
1140
1141static inline const char *GetCmdName(OMX_COMMANDTYPE cmd)
1142{
1143    if (cmd > OMX_CommandMarkBuffer)
1144        cmd = (OMX_COMMANDTYPE)(OMX_CommandMarkBuffer+1);
1145
1146    return cmd_name[cmd];
1147}
1148
1149void ComponentBase::CmdHandler(struct cmd_s *cmd)
1150{
1151    LOGV("%s:%s: handling %s command\n",
1152         GetName(), GetWorkingRole(), GetCmdName(cmd->cmd));
1153
1154    switch (cmd->cmd) {
1155    case OMX_CommandStateSet: {
1156        OMX_STATETYPE transition = (OMX_STATETYPE)cmd->param1;
1157
1158        TransState(transition);
1159        break;
1160    }
1161    case OMX_CommandFlush: {
1162        OMX_U32 port_index = cmd->param1;
1163        pthread_mutex_lock(&ports_block);
1164        ProcessorFlush(port_index);
1165        FlushPort(port_index, 1);
1166        pthread_mutex_unlock(&ports_block);
1167        break;
1168    }
1169    case OMX_CommandPortDisable: {
1170        OMX_U32 port_index = cmd->param1;
1171
1172        TransStatePort(port_index, PortBase::OMX_PortDisabled);
1173        break;
1174    }
1175    case OMX_CommandPortEnable: {
1176        OMX_U32 port_index = cmd->param1;
1177
1178        TransStatePort(port_index, PortBase::OMX_PortEnabled);
1179        break;
1180    }
1181    case OMX_CommandMarkBuffer: {
1182        OMX_U32 port_index = (OMX_U32)cmd->param1;
1183        OMX_MARKTYPE *mark = (OMX_MARKTYPE *)cmd->cmddata;
1184
1185        PushThisMark(port_index, mark);
1186        break;
1187    }
1188    default:
1189        LOGE("%s:%s:%s: exit failure, command %d cannot be handled\n",
1190             GetName(), GetWorkingRole(), GetCmdName(cmd->cmd), cmd->cmd);
1191        break;
1192    } /* switch */
1193
1194    LOGV("%s:%s: command %s handling done\n",
1195         GetName(), GetWorkingRole(), GetCmdName(cmd->cmd));
1196}
1197
1198/*
1199 * SendCommand:OMX_CommandStateSet
1200 * called in CmdHandler or called in other parts of component for reporting
1201 * internal error (OMX_StateInvalid).
1202 */
1203/*
1204 * Todo
1205 *   Resource Management (OMX_StateWaitForResources)
1206 *   for now, we never notify OMX_ErrorInsufficientResources,
1207 *   so IL client doesn't try to set component' state OMX_StateWaitForResources
1208 */
1209static const char *state_name[OMX_StateWaitForResources+2] = {
1210    "OMX_StateInvalid",
1211    "OMX_StateLoaded",
1212    "OMX_StateIdle",
1213    "OMX_StateExecuting",
1214    "OMX_StatePause",
1215    "OMX_StateWaitForResources",
1216    "Unknown State",
1217};
1218
1219static inline const char *GetStateName(OMX_STATETYPE state)
1220{
1221    if (state > OMX_StateWaitForResources)
1222        state = (OMX_STATETYPE)(OMX_StateWaitForResources+1);
1223
1224    return state_name[state];
1225}
1226
1227void ComponentBase::TransState(OMX_STATETYPE transition)
1228{
1229    OMX_STATETYPE current = this->state;
1230    OMX_EVENTTYPE event;
1231    OMX_U32 data1, data2;
1232    OMX_ERRORTYPE ret;
1233
1234    LOGV("%s:%s: try to transit state from %s to %s\n",
1235         GetName(), GetWorkingRole(), GetStateName(current),
1236         GetStateName(transition));
1237
1238    /* same state */
1239    if (current == transition) {
1240        ret = OMX_ErrorSameState;
1241        LOGE("%s:%s: exit failure, same state (%s)\n",
1242             GetName(), GetWorkingRole(), GetStateName(current));
1243        goto notify_event;
1244    }
1245
1246    /* invalid state */
1247    if (current == OMX_StateInvalid) {
1248        ret = OMX_ErrorInvalidState;
1249        LOGE("%s:%s: exit failure, current state is OMX_StateInvalid\n",
1250             GetName(), GetWorkingRole());
1251        goto notify_event;
1252    }
1253
1254    if (transition == OMX_StateLoaded)
1255        ret = TransStateToLoaded(current);
1256    else if (transition == OMX_StateIdle)
1257        ret = TransStateToIdle(current);
1258    else if (transition == OMX_StateExecuting)
1259        ret = TransStateToExecuting(current);
1260    else if (transition == OMX_StatePause)
1261        ret = TransStateToPause(current);
1262    else if (transition == OMX_StateInvalid)
1263        ret = TransStateToInvalid(current);
1264    else if (transition == OMX_StateWaitForResources)
1265        ret = TransStateToWaitForResources(current);
1266    else
1267        ret = OMX_ErrorIncorrectStateTransition;
1268
1269notify_event:
1270    if (ret == OMX_ErrorNone) {
1271        event = OMX_EventCmdComplete;
1272        data1 = OMX_CommandStateSet;
1273        data2 = transition;
1274
1275        state = transition;
1276        LOGD("%s:%s: transition from %s to %s completed",
1277             GetName(), GetWorkingRole(),
1278             GetStateName(current), GetStateName(transition));
1279    }
1280    else {
1281        event = OMX_EventError;
1282        data1 = ret;
1283        data2 = 0;
1284
1285        if (transition == OMX_StateInvalid || ret == OMX_ErrorInvalidState) {
1286            state = OMX_StateInvalid;
1287            LOGE("%s:%s: exit failure, transition from %s to %s, "
1288                 "current state is %s\n",
1289                 GetName(), GetWorkingRole(), GetStateName(current),
1290                 GetStateName(transition), GetStateName(state));
1291        }
1292    }
1293
1294    callbacks->EventHandler(handle, appdata, event, data1, data2, NULL);
1295
1296    /* WaitForResources workaround */
1297    if (ret == OMX_ErrorNone && transition == OMX_StateWaitForResources)
1298        callbacks->EventHandler(handle, appdata,
1299                                OMX_EventResourcesAcquired, 0, 0, NULL);
1300}
1301
1302inline OMX_ERRORTYPE ComponentBase::TransStateToLoaded(OMX_STATETYPE current)
1303{
1304    OMX_ERRORTYPE ret;
1305
1306    if (current == OMX_StateIdle) {
1307        OMX_U32 i;
1308
1309        for (i = 0; i < nr_ports; i++)
1310	{
1311            if (ports[i]->GetPortBufferCount() > 0) {
1312                ports[i]->WaitPortBufferCompletion();
1313	    };
1314	};
1315
1316        ret = ProcessorDeinit();
1317        if (ret != OMX_ErrorNone) {
1318            LOGE("%s:%s: ProcessorDeinit() failed "
1319                 "(ret : 0x%08x)\n", GetName(), GetWorkingRole(),
1320                 ret);
1321            goto out;
1322        }
1323    }
1324    else if (current == OMX_StateWaitForResources) {
1325        LOGV("%s:%s: "
1326             "state transition's requested from WaitForResources to Loaded\n",
1327             GetName(), GetWorkingRole());
1328
1329        /*
1330         * from WaitForResources to Loaded considered from Loaded to Loaded.
1331         * do nothing
1332         */
1333
1334        ret = OMX_ErrorNone;
1335    }
1336    else
1337        ret = OMX_ErrorIncorrectStateTransition;
1338
1339out:
1340    return ret;
1341}
1342
1343inline OMX_ERRORTYPE ComponentBase::TransStateToIdle(OMX_STATETYPE current)
1344{
1345    OMX_ERRORTYPE ret;
1346
1347    if (current == OMX_StateLoaded) {
1348        OMX_U32 i;
1349
1350        ret = ProcessorInit();
1351        if (ret != OMX_ErrorNone) {
1352            LOGE("%s:%s: ProcessorInit() failed (ret : 0x%08x)\n",
1353                 GetName(), GetWorkingRole(), ret);
1354            goto out;
1355        }
1356
1357        for (i = 0; i < nr_ports; i++) {
1358            if (ports[i]->IsEnabled())
1359                ports[i]->WaitPortBufferCompletion();
1360        }
1361    }
1362    else if ((current == OMX_StatePause) || (current == OMX_StateExecuting)) {
1363        pthread_mutex_lock(&ports_block);
1364        FlushPort(OMX_ALL, 0);
1365        pthread_mutex_unlock(&ports_block);
1366        LOGV("%s:%s: flushed all ports\n", GetName(), GetWorkingRole());
1367
1368        bufferwork->CancelScheduledWork(this);
1369        LOGV("%s:%s: discarded all scheduled buffer process work\n",
1370             GetName(), GetWorkingRole());
1371
1372        if (current == OMX_StatePause) {
1373            bufferwork->ResumeWork();
1374            LOGV("%s:%s: buffer process work resumed\n",
1375                 GetName(), GetWorkingRole());
1376        }
1377
1378        bufferwork->StopWork();
1379        LOGV("%s:%s: buffer process work stopped\n",
1380             GetName(), GetWorkingRole());
1381
1382        ret = ProcessorStop();
1383        if (ret != OMX_ErrorNone) {
1384            LOGE("%s:%s: ProcessorStop() failed (ret : 0x%08x)\n",
1385                 GetName(), GetWorkingRole(), ret);
1386            goto out;
1387        }
1388    }
1389    else if (current == OMX_StateWaitForResources) {
1390        LOGV("%s:%s: "
1391             "state transition's requested from WaitForResources to Idle\n",
1392             GetName(), GetWorkingRole());
1393
1394        /* same as Loaded to Idle BUT DO NOTHING for now */
1395
1396        ret = OMX_ErrorNone;
1397    }
1398    else
1399        ret = OMX_ErrorIncorrectStateTransition;
1400
1401out:
1402    return ret;
1403}
1404
1405inline OMX_ERRORTYPE
1406ComponentBase::TransStateToExecuting(OMX_STATETYPE current)
1407{
1408    OMX_ERRORTYPE ret;
1409
1410    if (current == OMX_StateIdle) {
1411        bufferwork->StartWork(true);
1412        LOGV("%s:%s: buffer process work started with executing state\n",
1413             GetName(), GetWorkingRole());
1414
1415        ret = ProcessorStart();
1416        if (ret != OMX_ErrorNone) {
1417            LOGE("%s:%s: ProcessorStart() failed (ret : 0x%08x)\n",
1418                 GetName(), GetWorkingRole(), ret);
1419            goto out;
1420        }
1421    }
1422    else if (current == OMX_StatePause) {
1423        bufferwork->ResumeWork();
1424        LOGV("%s:%s: buffer process work resumed\n",
1425             GetName(), GetWorkingRole());
1426
1427        ret = ProcessorResume();
1428        if (ret != OMX_ErrorNone) {
1429            LOGE("%s:%s: ProcessorResume() failed (ret : 0x%08x)\n",
1430                 GetName(), GetWorkingRole(), ret);
1431            goto out;
1432        }
1433    }
1434    else
1435        ret = OMX_ErrorIncorrectStateTransition;
1436
1437out:
1438    return ret;
1439}
1440
1441inline OMX_ERRORTYPE ComponentBase::TransStateToPause(OMX_STATETYPE current)
1442{
1443    OMX_ERRORTYPE ret;
1444
1445    if (current == OMX_StateIdle) {
1446        bufferwork->StartWork(false);
1447        LOGV("%s:%s: buffer process work started with paused state\n",
1448             GetName(), GetWorkingRole());
1449
1450        ret = ProcessorStart();
1451        if (ret != OMX_ErrorNone) {
1452            LOGE("%s:%s: ProcessorSart() failed (ret : 0x%08x)\n",
1453                 GetName(), GetWorkingRole(), ret);
1454            goto out;
1455        }
1456    }
1457    else if (current == OMX_StateExecuting) {
1458        bufferwork->PauseWork();
1459        LOGV("%s:%s: buffer process work paused\n",
1460             GetName(), GetWorkingRole());
1461
1462        ret = ProcessorPause();
1463        if (ret != OMX_ErrorNone) {
1464            LOGE("%s:%s: ProcessorPause() failed (ret : 0x%08x)\n",
1465                 GetName(), GetWorkingRole(), ret);
1466            goto out;
1467        }
1468    }
1469    else
1470        ret = OMX_ErrorIncorrectStateTransition;
1471
1472out:
1473    return ret;
1474}
1475
1476inline OMX_ERRORTYPE ComponentBase::TransStateToInvalid(OMX_STATETYPE current)
1477{
1478    OMX_ERRORTYPE ret = OMX_ErrorInvalidState;
1479
1480    /*
1481     * Todo
1482     *   graceful escape
1483     */
1484
1485    return ret;
1486}
1487
1488inline OMX_ERRORTYPE
1489ComponentBase::TransStateToWaitForResources(OMX_STATETYPE current)
1490{
1491    OMX_ERRORTYPE ret;
1492
1493    if (current == OMX_StateLoaded) {
1494        LOGV("%s:%s: "
1495             "state transition's requested from Loaded to WaitForResources\n",
1496             GetName(), GetWorkingRole());
1497        ret = OMX_ErrorNone;
1498    }
1499    else
1500        ret = OMX_ErrorIncorrectStateTransition;
1501
1502    return ret;
1503}
1504
1505/* mark buffer */
1506void ComponentBase::PushThisMark(OMX_U32 port_index, OMX_MARKTYPE *mark)
1507{
1508    PortBase *port = NULL;
1509    OMX_EVENTTYPE event;
1510    OMX_U32 data1, data2;
1511    OMX_ERRORTYPE ret;
1512
1513    if (ports)
1514        if (port_index < nr_ports)
1515            port = ports[port_index];
1516
1517    if (!port) {
1518        ret = OMX_ErrorBadPortIndex;
1519        goto notify_event;
1520    }
1521
1522    ret = port->PushMark(mark);
1523    if (ret != OMX_ErrorNone) {
1524        /* don't report OMX_ErrorInsufficientResources */
1525        ret = OMX_ErrorUndefined;
1526        goto notify_event;
1527    }
1528
1529notify_event:
1530    if (ret == OMX_ErrorNone) {
1531        event = OMX_EventCmdComplete;
1532        data1 = OMX_CommandMarkBuffer;
1533        data2 = port_index;
1534    }
1535    else {
1536        event = OMX_EventError;
1537        data1 = ret;
1538        data2 = 0;
1539    }
1540
1541    callbacks->EventHandler(handle, appdata, event, data1, data2, NULL);
1542}
1543
1544void ComponentBase::FlushPort(OMX_U32 port_index, bool notify)
1545{
1546    OMX_U32 i, from_index, to_index;
1547
1548    if ((port_index != OMX_ALL) && (port_index > nr_ports-1))
1549        return;
1550
1551    if (port_index == OMX_ALL) {
1552        from_index = 0;
1553        to_index = nr_ports - 1;
1554    }
1555    else {
1556        from_index = port_index;
1557        to_index = port_index;
1558    }
1559
1560    LOGV("%s:%s: flush ports (from index %lu to %lu)\n",
1561         GetName(), GetWorkingRole(), from_index, to_index);
1562
1563    for (i = from_index; i <= to_index; i++) {
1564        ports[i]->FlushPort();
1565        if (notify)
1566            callbacks->EventHandler(handle, appdata, OMX_EventCmdComplete,
1567                                    OMX_CommandFlush, i, NULL);
1568    }
1569
1570    LOGV("%s:%s: flush ports done\n", GetName(), GetWorkingRole());
1571}
1572
1573extern const char *GetPortStateName(OMX_U8 state); //portbase.cpp
1574
1575void ComponentBase::TransStatePort(OMX_U32 port_index, OMX_U8 state)
1576{
1577    OMX_EVENTTYPE event;
1578    OMX_U32 data1, data2;
1579    OMX_U32 i, from_index, to_index;
1580    OMX_ERRORTYPE ret;
1581
1582    if ((port_index != OMX_ALL) && (port_index > nr_ports-1))
1583        return;
1584
1585    if (port_index == OMX_ALL) {
1586        from_index = 0;
1587        to_index = nr_ports - 1;
1588    }
1589    else {
1590        from_index = port_index;
1591        to_index = port_index;
1592    }
1593
1594    LOGV("%s:%s: transit ports state to %s (from index %lu to %lu)\n",
1595         GetName(), GetWorkingRole(), GetPortStateName(state),
1596         from_index, to_index);
1597
1598    pthread_mutex_lock(&ports_block);
1599    for (i = from_index; i <= to_index; i++) {
1600        ret = ports[i]->TransState(state);
1601        if (ret == OMX_ErrorNone) {
1602            event = OMX_EventCmdComplete;
1603            if (state == PortBase::OMX_PortEnabled) {
1604                data1 = OMX_CommandPortEnable;
1605                ProcessorReset();
1606            }
1607            else
1608                data1 = OMX_CommandPortDisable;
1609            data2 = i;
1610        }
1611        else {
1612            event = OMX_EventError;
1613            data1 = ret;
1614            data2 = 0;
1615        }
1616        callbacks->EventHandler(handle, appdata, OMX_EventCmdComplete,
1617                                data1, data2, NULL);
1618    }
1619    pthread_mutex_unlock(&ports_block);
1620
1621    LOGV("%s:%s: transit ports state to %s completed\n",
1622         GetName(), GetWorkingRole(), GetPortStateName(state));
1623}
1624
1625/* set working role */
1626OMX_ERRORTYPE ComponentBase::SetWorkingRole(const OMX_STRING role)
1627{
1628    OMX_U32 i;
1629
1630    if (state != OMX_StateUnloaded && state != OMX_StateLoaded)
1631        return OMX_ErrorIncorrectStateOperation;
1632
1633    if (!role) {
1634        working_role = NULL;
1635        return OMX_ErrorNone;
1636    }
1637
1638    for (i = 0; i < nr_roles; i++) {
1639        if (!strcmp((char *)&roles[i][0], role)) {
1640            working_role = (OMX_STRING)&roles[i][0];
1641            return OMX_ErrorNone;
1642        }
1643    }
1644
1645    LOGE("%s: cannot find %s role\n", GetName(), role);
1646    return OMX_ErrorBadParameter;
1647}
1648
1649/* apply a working role for a component having multiple roles */
1650OMX_ERRORTYPE ComponentBase::ApplyWorkingRole(void)
1651{
1652    OMX_U32 i;
1653    OMX_ERRORTYPE ret;
1654
1655    if (state != OMX_StateUnloaded && state != OMX_StateLoaded)
1656        return OMX_ErrorIncorrectStateOperation;
1657
1658    if (!working_role)
1659        return OMX_ErrorBadParameter;
1660
1661    if (!callbacks || !appdata)
1662        return OMX_ErrorBadParameter;
1663
1664    ret = AllocatePorts();
1665    if (ret != OMX_ErrorNone) {
1666        LOGE("failed to AllocatePorts() (ret = 0x%08x)\n", ret);
1667        return ret;
1668    }
1669
1670    /* now we can access ports */
1671    for (i = 0; i < nr_ports; i++) {
1672        ports[i]->SetOwner(handle);
1673        ports[i]->SetCallbacks(handle, callbacks, appdata);
1674    }
1675
1676    LOGI("%s: set working role %s:", GetName(), GetWorkingRole());
1677    return OMX_ErrorNone;
1678}
1679
1680OMX_ERRORTYPE ComponentBase::AllocatePorts(void)
1681{
1682    OMX_DIRTYPE dir;
1683    bool has_input, has_output;
1684    OMX_U32 i;
1685    OMX_ERRORTYPE ret;
1686
1687    if (ports)
1688        return OMX_ErrorBadParameter;
1689
1690    ret = ComponentAllocatePorts();
1691    if (ret != OMX_ErrorNone) {
1692        LOGE("failed to %s::ComponentAllocatePorts(), ret = 0x%08x\n",
1693             name, ret);
1694        return ret;
1695    }
1696
1697    has_input = false;
1698    has_output = false;
1699    ret = OMX_ErrorNone;
1700    for (i = 0; i < nr_ports; i++) {
1701        dir = ports[i]->GetPortDirection();
1702        if (dir == OMX_DirInput)
1703            has_input = true;
1704        else if (dir == OMX_DirOutput)
1705            has_output = true;
1706        else {
1707            ret = OMX_ErrorUndefined;
1708            break;
1709        }
1710    }
1711    if (ret != OMX_ErrorNone)
1712        goto free_ports;
1713
1714    if ((has_input == false) && (has_output == true))
1715        cvariant = CVARIANT_SOURCE;
1716    else if ((has_input == true) && (has_output == true))
1717        cvariant = CVARIANT_FILTER;
1718    else if ((has_input == true) && (has_output == false))
1719        cvariant = CVARIANT_SINK;
1720    else
1721        goto free_ports;
1722
1723    return OMX_ErrorNone;
1724
1725free_ports:
1726    LOGE("%s(): exit, unknown component variant\n", __func__);
1727    FreePorts();
1728    return ret;
1729}
1730
1731/* called int FreeHandle() */
1732OMX_ERRORTYPE ComponentBase::FreePorts(void)
1733{
1734    if (ports) {
1735        OMX_U32 i, this_nr_ports = this->nr_ports;
1736
1737        for (i = 0; i < this_nr_ports; i++) {
1738            if (ports[i]) {
1739                OMX_MARKTYPE *mark;
1740                /* it should be empty before this */
1741                while ((mark = ports[i]->PopMark()))
1742                    free(mark);
1743
1744                delete ports[i];
1745                ports[i] = NULL;
1746            }
1747        }
1748        delete []ports;
1749        ports = NULL;
1750    }
1751
1752    return OMX_ErrorNone;
1753}
1754
1755/* buffer processing */
1756/* implement WorkableInterface */
1757void ComponentBase::Work(void)
1758{
1759    OMX_BUFFERHEADERTYPE **buffers[nr_ports];
1760    OMX_BUFFERHEADERTYPE *buffers_hdr[nr_ports];
1761    OMX_BUFFERHEADERTYPE *buffers_org[nr_ports];
1762    buffer_retain_t retain[nr_ports];
1763    OMX_U32 i;
1764    OMX_ERRORTYPE ret;
1765
1766    pthread_mutex_lock(&ports_block);
1767
1768    while(IsAllBufferAvailable())
1769    {
1770        for (i = 0; i < nr_ports; i++) {
1771            buffers_hdr[i] = ports[i]->PopBuffer();
1772            buffers[i] = &buffers_hdr[i];
1773            buffers_org[i] = buffers_hdr[i];
1774            retain[i] = BUFFER_RETAIN_NOT_RETAIN;
1775        }
1776
1777        if (working_role != NULL && !strncmp((char*)working_role, "video_decoder", 13)){
1778            ret = ProcessorProcess(buffers, &retain[0], nr_ports);
1779        }else{
1780            ret = ProcessorProcess(buffers_hdr, &retain[0], nr_ports);
1781        }
1782
1783        if (ret == OMX_ErrorNone) {
1784            PostProcessBuffers(buffers, &retain[0]);
1785
1786            for (i = 0; i < nr_ports; i++) {
1787                if(retain[i] == BUFFER_RETAIN_GETAGAIN) {
1788                    ports[i]->RetainThisBuffer(*buffers[i], false);
1789                }
1790                else if (retain[i] == BUFFER_RETAIN_ACCUMULATE) {
1791                    ports[i]->RetainThisBuffer(*buffers[i], true);
1792                }
1793                else if (retain[i] == BUFFER_RETAIN_OVERRIDDEN) {
1794                    ports[i]->RetainAndReturnBuffer(buffers_org[i], *buffers[i]);
1795                } else {
1796                    ports[i]->ReturnThisBuffer(*buffers[i]);
1797                }
1798            }
1799        }
1800        else {
1801
1802            for (i = 0; i < nr_ports; i++) {
1803                /* return buffers by hands, these buffers're not in queue */
1804                ports[i]->ReturnThisBuffer(*buffers[i]);
1805                /* flush ports */
1806                ports[i]->FlushPort();
1807            }
1808
1809            callbacks->EventHandler(handle, appdata, OMX_EventError, ret,
1810                                    0, NULL);
1811        }
1812    }
1813
1814    pthread_mutex_unlock(&ports_block);
1815}
1816
1817bool ComponentBase::IsAllBufferAvailable(void)
1818{
1819    OMX_U32 i;
1820    OMX_U32 nr_avail = 0;
1821
1822    for (i = 0; i < nr_ports; i++) {
1823        OMX_U32 length = 0;
1824
1825        if (ports[i]->IsEnabled())
1826            length = ports[i]->BufferQueueLength();
1827
1828        if (length)
1829            nr_avail++;
1830    }
1831
1832    if (nr_avail == nr_ports)
1833        return true;
1834    else
1835        return false;
1836}
1837
1838inline void ComponentBase::SourcePostProcessBuffers(
1839    OMX_BUFFERHEADERTYPE ***buffers,
1840    const buffer_retain_t *retain)
1841{
1842    OMX_U32 i;
1843
1844    for (i = 0; i < nr_ports; i++) {
1845        /*
1846         * in case of source component, buffers're marked when they come
1847         * from the ouput ports
1848         */
1849        if (!(*buffers[i])->hMarkTargetComponent) {
1850            OMX_MARKTYPE *mark;
1851
1852            mark = ports[i]->PopMark();
1853            if (mark) {
1854                (*buffers[i])->hMarkTargetComponent = mark->hMarkTargetComponent;
1855                (*buffers[i])->pMarkData = mark->pMarkData;
1856                free(mark);
1857            }
1858        }
1859    }
1860}
1861
1862inline void ComponentBase::FilterPostProcessBuffers(
1863    OMX_BUFFERHEADERTYPE ***buffers,
1864    const buffer_retain_t *retain)
1865{
1866    OMX_MARKTYPE *mark;
1867    OMX_U32 i, j;
1868
1869    for (i = 0; i < nr_ports; i++) {
1870        if (ports[i]->GetPortDirection() == OMX_DirInput) {
1871            for (j = 0; j < nr_ports; j++) {
1872                if (ports[j]->GetPortDirection() != OMX_DirOutput)
1873                    continue;
1874
1875                /* propagates EOS flag */
1876                /* clear input EOS at the end of this loop */
1877                if (retain[i] != BUFFER_RETAIN_GETAGAIN) {
1878                    if ((*buffers[i])->nFlags & OMX_BUFFERFLAG_EOS)
1879                        (*buffers[j])->nFlags |= OMX_BUFFERFLAG_EOS;
1880                }
1881
1882                /* propagates marks */
1883                /*
1884                 * if hMarkTargetComponent == handle then the mark's not
1885                 * propagated
1886                 */
1887                if ((*buffers[i])->hMarkTargetComponent &&
1888                    ((*buffers[i])->hMarkTargetComponent != handle)) {
1889                    if ((*buffers[j])->hMarkTargetComponent) {
1890                        mark = (OMX_MARKTYPE *)malloc(sizeof(*mark));
1891                        if (mark) {
1892                            mark->hMarkTargetComponent =
1893                                (*buffers[i])->hMarkTargetComponent;
1894                            mark->pMarkData = (*buffers[i])->pMarkData;
1895                            ports[j]->PushMark(mark);
1896                            mark = NULL;
1897                            (*buffers[i])->hMarkTargetComponent = NULL;
1898                            (*buffers[i])->pMarkData = NULL;
1899                        }
1900                    }
1901                    else {
1902                        mark = ports[j]->PopMark();
1903                        if (mark) {
1904                            (*buffers[j])->hMarkTargetComponent =
1905                                mark->hMarkTargetComponent;
1906                            (*buffers[j])->pMarkData = mark->pMarkData;
1907                            free(mark);
1908
1909                            mark = (OMX_MARKTYPE *)malloc(sizeof(*mark));
1910                            if (mark) {
1911                                mark->hMarkTargetComponent =
1912                                    (*buffers[i])->hMarkTargetComponent;
1913                                mark->pMarkData = (*buffers[i])->pMarkData;
1914                                ports[j]->PushMark(mark);
1915                                mark = NULL;
1916                                (*buffers[i])->hMarkTargetComponent = NULL;
1917                                (*buffers[i])->pMarkData = NULL;
1918                            }
1919                        }
1920                        else {
1921                            (*buffers[j])->hMarkTargetComponent =
1922                                (*buffers[i])->hMarkTargetComponent;
1923                            (*buffers[j])->pMarkData = (*buffers[i])->pMarkData;
1924                            (*buffers[i])->hMarkTargetComponent = NULL;
1925                            (*buffers[i])->pMarkData = NULL;
1926                        }
1927                    }
1928                }
1929            }
1930            /* clear input buffer's EOS */
1931            if (retain[i] != BUFFER_RETAIN_GETAGAIN)
1932                (*buffers[i])->nFlags &= ~OMX_BUFFERFLAG_EOS;
1933        }
1934    }
1935}
1936
1937inline void ComponentBase::SinkPostProcessBuffers(
1938    OMX_BUFFERHEADERTYPE ***buffers,
1939    const buffer_retain_t *retain)
1940{
1941    return;
1942}
1943
1944void ComponentBase::PostProcessBuffers(OMX_BUFFERHEADERTYPE ***buffers,
1945                                       const buffer_retain_t *retain)
1946{
1947
1948    if (cvariant == CVARIANT_SOURCE)
1949        SourcePostProcessBuffers(buffers, retain);
1950    else if (cvariant == CVARIANT_FILTER)
1951        FilterPostProcessBuffers(buffers, retain);
1952    else if (cvariant == CVARIANT_SINK) {
1953        SinkPostProcessBuffers(buffers, retain);
1954    }
1955    else {
1956        LOGE("%s(): fatal error unknown component variant (%d)\n",
1957             __func__, cvariant);
1958    }
1959}
1960
1961/* processor default callbacks */
1962OMX_ERRORTYPE ComponentBase::ProcessorInit(void)
1963{
1964    return OMX_ErrorNone;
1965}
1966OMX_ERRORTYPE ComponentBase::ProcessorDeinit(void)
1967{
1968    return OMX_ErrorNone;
1969}
1970
1971OMX_ERRORTYPE ComponentBase::ProcessorStart(void)
1972{
1973    return OMX_ErrorNone;
1974}
1975
1976OMX_ERRORTYPE ComponentBase::ProcessorReset(void)
1977{
1978    return OMX_ErrorNone;
1979}
1980
1981
1982OMX_ERRORTYPE ComponentBase::ProcessorStop(void)
1983{
1984    return OMX_ErrorNone;
1985}
1986
1987OMX_ERRORTYPE ComponentBase::ProcessorPause(void)
1988{
1989    return OMX_ErrorNone;
1990}
1991
1992OMX_ERRORTYPE ComponentBase::ProcessorResume(void)
1993{
1994    return OMX_ErrorNone;
1995}
1996
1997OMX_ERRORTYPE ComponentBase::ProcessorFlush(OMX_U32 port_index)
1998{
1999    return OMX_ErrorNone;
2000}
2001
2002OMX_ERRORTYPE ComponentBase::ProcessorPreFillBuffer(OMX_BUFFERHEADERTYPE* buffer)
2003{
2004    return OMX_ErrorNone;
2005}
2006
2007OMX_ERRORTYPE ComponentBase::ProcessorProcess(OMX_BUFFERHEADERTYPE **pBuffers,
2008                                           buffer_retain_t *retain,
2009                                           OMX_U32 nr_buffers)
2010{
2011    LOGE("ProcessorProcess not be implemented");
2012    return OMX_ErrorNotImplemented;
2013}
2014OMX_ERRORTYPE ComponentBase::ProcessorProcess(OMX_BUFFERHEADERTYPE ***pBuffers,
2015                                           buffer_retain_t *retain,
2016                                           OMX_U32 nr_buffers)
2017{
2018    LOGE("ProcessorProcess not be implemented");
2019    return OMX_ErrorNotImplemented;
2020}
2021
2022OMX_ERRORTYPE ComponentBase::ProcessorPreFreeBuffer(OMX_U32 nPortIndex, OMX_BUFFERHEADERTYPE* pBuffer)
2023{
2024    return OMX_ErrorNone;
2025
2026}
2027/* end of processor callbacks */
2028
2029/* helper for derived class */
2030const OMX_STRING ComponentBase::GetWorkingRole(void)
2031{
2032    return &working_role[0];
2033}
2034
2035const OMX_COMPONENTTYPE *ComponentBase::GetComponentHandle(void)
2036{
2037    return handle;
2038}
2039#if 0
2040void ComponentBase::DumpBuffer(const OMX_BUFFERHEADERTYPE *bufferheader,
2041                               bool dumpdata)
2042{
2043    OMX_U8 *pbuffer = bufferheader->pBuffer, *p;
2044    OMX_U32 offset = bufferheader->nOffset;
2045    OMX_U32 alloc_len = bufferheader->nAllocLen;
2046    OMX_U32 filled_len =  bufferheader->nFilledLen;
2047    OMX_U32 left = filled_len, oneline;
2048    OMX_U32 index = 0, i;
2049    /* 0x%04lx:  %02x %02x .. (n = 16)\n\0 */
2050    char prbuffer[8 + 3 * 0x10 + 2], *pp;
2051    OMX_U32 prbuffer_len;
2052
2053    LOGD("Component %s DumpBuffer\n", name);
2054    LOGD("%s port index = %lu",
2055         (bufferheader->nInputPortIndex != 0x7fffffff) ? "input" : "output",
2056         (bufferheader->nInputPortIndex != 0x7fffffff) ?
2057         bufferheader->nInputPortIndex : bufferheader->nOutputPortIndex);
2058    LOGD("nAllocLen = %lu, nOffset = %lu, nFilledLen = %lu\n",
2059         alloc_len, offset, filled_len);
2060    LOGD("nTimeStamp = %lld, nTickCount = %lu",
2061         bufferheader->nTimeStamp,
2062         bufferheader->nTickCount);
2063    LOGD("nFlags = 0x%08lx\n", bufferheader->nFlags);
2064    LOGD("hMarkTargetComponent = %p, pMarkData = %p\n",
2065         bufferheader->hMarkTargetComponent, bufferheader->pMarkData);
2066
2067    if (!pbuffer || !alloc_len || !filled_len)
2068        return;
2069
2070    if (offset + filled_len > alloc_len)
2071        return;
2072
2073    if (!dumpdata)
2074        return;
2075
2076    p = pbuffer + offset;
2077    while (left) {
2078        oneline = left > 0x10 ? 0x10 : left; /* 16 items per 1 line */
2079        pp += sprintf(pp, "0x%04lx: ", index);
2080        for (i = 0; i < oneline; i++)
2081            pp += sprintf(pp, " %02x", *(p + i));
2082        pp += sprintf(pp, "\n");
2083        *pp = '\0';
2084
2085        index += 0x10;
2086        p += oneline;
2087        left -= oneline;
2088
2089        pp = &prbuffer[0];
2090        LOGD("%s", pp);
2091    }
2092}
2093#endif
2094/* end of component methods & helpers */
2095
2096/*
2097 * omx header manipuation
2098 */
2099void ComponentBase::SetTypeHeader(OMX_PTR type, OMX_U32 size)
2100{
2101    OMX_U32 *nsize;
2102    OMX_VERSIONTYPE *nversion;
2103
2104    if (!type)
2105        return;
2106
2107    nsize = (OMX_U32 *)type;
2108    nversion = (OMX_VERSIONTYPE *)((OMX_U8 *)type + sizeof(OMX_U32));
2109
2110    *nsize = size;
2111    nversion->nVersion = OMX_SPEC_VERSION;
2112}
2113
2114OMX_ERRORTYPE ComponentBase::CheckTypeHeader(const OMX_PTR type, OMX_U32 size)
2115{
2116    OMX_U32 *nsize;
2117    OMX_VERSIONTYPE *nversion;
2118
2119    if (!type)
2120        return OMX_ErrorBadParameter;
2121
2122    nsize = (OMX_U32 *)type;
2123    nversion = (OMX_VERSIONTYPE *)((OMX_U8 *)type + sizeof(OMX_U32));
2124
2125    if (*nsize != size)
2126        return OMX_ErrorBadParameter;
2127
2128    if (nversion->nVersion != OMX_SPEC_VERSION)
2129        return OMX_ErrorVersionMismatch;
2130
2131    return OMX_ErrorNone;
2132}
2133
2134/* end of ComponentBase */
2135