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