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