Home | History | Annotate | Download | only in src
      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 
     39 static const OMX_U32 kMaxAdaptiveStreamingWidth = 1920;
     40 static const OMX_U32 kMaxAdaptiveStreamingHeight = 1088;
     41 /*
     42  * CmdProcessWork
     43  */
     44 CmdProcessWork::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 
     58 CmdProcessWork::~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 
     73 OMX_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 
     90 struct 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 
    101 void 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  */
    120 void 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 
    146 ComponentBase::ComponentBase()
    147 {
    148     __ComponentBase();
    149 }
    150 
    151 ComponentBase::ComponentBase(const OMX_STRING name)
    152 {
    153     __ComponentBase();
    154     SetName(name);
    155 }
    156 
    157 ComponentBase::~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 */
    175 void 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 
    182 OMX_STRING ComponentBase::GetName(void)
    183 {
    184     return name;
    185 }
    186 
    187 /* component module */
    188 void ComponentBase::SetCModule(CModule *cmodule)
    189 {
    190     this->cmodule = cmodule;
    191 }
    192 
    193 CModule *ComponentBase::GetCModule(void)
    194 {
    195     return cmodule;
    196 }
    197 
    198 /* end of accessor */
    199 
    200 /*
    201  * core methods & helpers
    202  */
    203 /* roles */
    204 OMX_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 */
    242 OMX_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 
    311 free_handle:
    312     free(handle);
    313 
    314     appdata = NULL;
    315     callbacks = NULL;
    316     *pHandle = NULL;
    317 
    318 free_bufferwork:
    319     delete bufferwork;
    320 
    321 free_cmdwork:
    322     delete cmdwork;
    323 
    324     return ret;
    325 }
    326 
    327 OMX_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  */
    354 OMX_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 
    373 OMX_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 
    442 OMX_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 
    461 OMX_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 
    519 OMX_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 
    538 OMX_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 
    684 OMX_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 
    703 OMX_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 
    721 OMX_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 
    740 OMX_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 
    758 OMX_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 
    777 OMX_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      if (!strcmp(cParameterName, "OMX.google.android.index.allocateNativeHandle")) {
    878         *pIndexType = static_cast<OMX_INDEXTYPE>(OMX_IndexExtAllocateNativeHandle);
    879         return OMX_ErrorNone;
    880     }
    881 
    882     return OMX_ErrorUnsupportedIndex;
    883 }
    884 
    885 OMX_ERRORTYPE ComponentBase::GetState(
    886     OMX_IN  OMX_HANDLETYPE hComponent,
    887     OMX_OUT OMX_STATETYPE* pState)
    888 {
    889     ComponentBase *cbase;
    890 
    891     if (!hComponent)
    892         return OMX_ErrorBadParameter;
    893 
    894     cbase = static_cast<ComponentBase *>
    895         (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
    896     if (!cbase)
    897         return OMX_ErrorBadParameter;
    898 
    899     return cbase->CBaseGetState(hComponent, pState);
    900 }
    901 
    902 OMX_ERRORTYPE ComponentBase::CBaseGetState(
    903     OMX_IN  OMX_HANDLETYPE hComponent,
    904     OMX_OUT OMX_STATETYPE* pState)
    905 {
    906     if (hComponent != handle)
    907         return OMX_ErrorBadParameter;
    908 
    909     pthread_mutex_lock(&state_block);
    910     *pState = state;
    911     pthread_mutex_unlock(&state_block);
    912     return OMX_ErrorNone;
    913 }
    914 OMX_ERRORTYPE ComponentBase::UseBuffer(
    915     OMX_IN OMX_HANDLETYPE hComponent,
    916     OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr,
    917     OMX_IN OMX_U32 nPortIndex,
    918     OMX_IN OMX_PTR pAppPrivate,
    919     OMX_IN OMX_U32 nSizeBytes,
    920     OMX_IN OMX_U8 *pBuffer)
    921 {
    922     ComponentBase *cbase;
    923 
    924     if (!hComponent)
    925         return OMX_ErrorBadParameter;
    926 
    927     cbase = static_cast<ComponentBase *>
    928         (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
    929     if (!cbase)
    930         return OMX_ErrorBadParameter;
    931 
    932     return cbase->CBaseUseBuffer(hComponent, ppBufferHdr, nPortIndex,
    933                                  pAppPrivate, nSizeBytes, pBuffer);
    934 }
    935 
    936 OMX_ERRORTYPE ComponentBase::CBaseUseBuffer(
    937     OMX_IN OMX_HANDLETYPE hComponent,
    938     OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr,
    939     OMX_IN OMX_U32 nPortIndex,
    940     OMX_IN OMX_PTR pAppPrivate,
    941     OMX_IN OMX_U32 nSizeBytes,
    942     OMX_IN OMX_U8 *pBuffer)
    943 {
    944     PortBase *port = NULL;
    945 
    946     if (hComponent != handle)
    947         return OMX_ErrorBadParameter;
    948 
    949     if (!ppBufferHdr)
    950         return OMX_ErrorBadParameter;
    951     *ppBufferHdr = NULL;
    952 
    953     if (!pBuffer)
    954         return OMX_ErrorBadParameter;
    955 
    956     if (ports)
    957         if (nPortIndex < nr_ports)
    958             port = ports[nPortIndex];
    959 
    960     if (!port)
    961         return OMX_ErrorBadParameter;
    962 
    963     if (port->IsEnabled()) {
    964         if (state != OMX_StateLoaded && state != OMX_StateWaitForResources)
    965             return OMX_ErrorIncorrectStateOperation;
    966     }
    967 
    968     return port->UseBuffer(ppBufferHdr, nPortIndex, pAppPrivate, nSizeBytes,
    969                            pBuffer);
    970 }
    971 
    972 OMX_ERRORTYPE ComponentBase::AllocateBuffer(
    973     OMX_IN OMX_HANDLETYPE hComponent,
    974     OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer,
    975     OMX_IN OMX_U32 nPortIndex,
    976     OMX_IN OMX_PTR pAppPrivate,
    977     OMX_IN OMX_U32 nSizeBytes)
    978 {
    979     ComponentBase *cbase;
    980 
    981     if (!hComponent)
    982         return OMX_ErrorBadParameter;
    983 
    984     cbase = static_cast<ComponentBase *>
    985         (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
    986     if (!cbase)
    987         return OMX_ErrorBadParameter;
    988 
    989     return cbase->CBaseAllocateBuffer(hComponent, ppBuffer, nPortIndex,
    990                                       pAppPrivate, nSizeBytes);
    991 }
    992 
    993 OMX_ERRORTYPE ComponentBase::CBaseAllocateBuffer(
    994     OMX_IN OMX_HANDLETYPE hComponent,
    995     OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer,
    996     OMX_IN OMX_U32 nPortIndex,
    997     OMX_IN OMX_PTR pAppPrivate,
    998     OMX_IN OMX_U32 nSizeBytes)
    999 {
   1000     PortBase *port = NULL;
   1001 
   1002     if (hComponent != handle)
   1003         return OMX_ErrorBadParameter;
   1004 
   1005     if (!ppBuffer)
   1006         return OMX_ErrorBadParameter;
   1007     *ppBuffer = NULL;
   1008 
   1009     if (ports)
   1010         if (nPortIndex < nr_ports)
   1011             port = ports[nPortIndex];
   1012 
   1013     if (!port)
   1014         return OMX_ErrorBadParameter;
   1015 
   1016     if (port->IsEnabled()) {
   1017         if (state != OMX_StateLoaded && state != OMX_StateWaitForResources)
   1018             return OMX_ErrorIncorrectStateOperation;
   1019     }
   1020 
   1021     return port->AllocateBuffer(ppBuffer, nPortIndex, pAppPrivate, nSizeBytes);
   1022 }
   1023 
   1024 OMX_ERRORTYPE ComponentBase::FreeBuffer(
   1025     OMX_IN  OMX_HANDLETYPE hComponent,
   1026     OMX_IN  OMX_U32 nPortIndex,
   1027     OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
   1028 {
   1029     ComponentBase *cbase;
   1030 
   1031     if (!hComponent)
   1032         return OMX_ErrorBadParameter;
   1033 
   1034     cbase = static_cast<ComponentBase *>
   1035         (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
   1036     if (!cbase)
   1037         return OMX_ErrorBadParameter;
   1038 
   1039     return cbase->CBaseFreeBuffer(hComponent, nPortIndex, pBuffer);
   1040 }
   1041 
   1042 OMX_ERRORTYPE ComponentBase::CBaseFreeBuffer(
   1043     OMX_IN  OMX_HANDLETYPE hComponent,
   1044     OMX_IN  OMX_U32 nPortIndex,
   1045     OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
   1046 {
   1047     PortBase *port = NULL;
   1048 
   1049     if (hComponent != handle)
   1050         return OMX_ErrorBadParameter;
   1051 
   1052     if (!pBuffer)
   1053         return OMX_ErrorBadParameter;
   1054 
   1055     if (ports)
   1056         if (nPortIndex < nr_ports)
   1057             port = ports[nPortIndex];
   1058 
   1059     if (!port)
   1060         return OMX_ErrorBadParameter;
   1061 
   1062     ProcessorPreFreeBuffer(nPortIndex, pBuffer);
   1063 
   1064     return port->FreeBuffer(nPortIndex, pBuffer);
   1065 }
   1066 
   1067 OMX_ERRORTYPE ComponentBase::EmptyThisBuffer(
   1068     OMX_IN  OMX_HANDLETYPE hComponent,
   1069     OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer)
   1070 {
   1071     ComponentBase *cbase;
   1072 
   1073     if (!hComponent)
   1074         return OMX_ErrorBadParameter;
   1075 
   1076     cbase = static_cast<ComponentBase *>
   1077         (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
   1078     if (!cbase)
   1079         return OMX_ErrorBadParameter;
   1080 
   1081     return cbase->CBaseEmptyThisBuffer(hComponent, pBuffer);
   1082 }
   1083 
   1084 OMX_ERRORTYPE ComponentBase::CBaseEmptyThisBuffer(
   1085     OMX_IN  OMX_HANDLETYPE hComponent,
   1086     OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
   1087 {
   1088     PortBase *port = NULL;
   1089     OMX_U32 port_index;
   1090     OMX_ERRORTYPE ret;
   1091 
   1092     if ((hComponent != handle) || !pBuffer)
   1093         return OMX_ErrorBadParameter;
   1094 
   1095     ret = CheckTypeHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE));
   1096     if (ret != OMX_ErrorNone)
   1097         return ret;
   1098 
   1099     port_index = pBuffer->nInputPortIndex;
   1100     if (port_index == (OMX_U32)-1)
   1101         return OMX_ErrorBadParameter;
   1102 
   1103     if (ports)
   1104         if (port_index < nr_ports)
   1105             port = ports[port_index];
   1106 
   1107     if (!port)
   1108         return OMX_ErrorBadParameter;
   1109 
   1110     if (port->IsEnabled()) {
   1111         if (state != OMX_StateIdle && state != OMX_StateExecuting &&
   1112             state != OMX_StatePause)
   1113             return OMX_ErrorIncorrectStateOperation;
   1114     }
   1115 
   1116     if (!pBuffer->hMarkTargetComponent) {
   1117         OMX_MARKTYPE *mark;
   1118 
   1119         mark = port->PopMark();
   1120         if (mark) {
   1121             pBuffer->hMarkTargetComponent = mark->hMarkTargetComponent;
   1122             pBuffer->pMarkData = mark->pMarkData;
   1123             free(mark);
   1124         }
   1125     }
   1126 
   1127     ProcessorPreEmptyBuffer(pBuffer);
   1128 
   1129     ret = port->PushThisBuffer(pBuffer);
   1130     if (ret == OMX_ErrorNone)
   1131         bufferwork->ScheduleWork(this);
   1132 
   1133     return ret;
   1134 }
   1135 
   1136 OMX_ERRORTYPE ComponentBase::FillThisBuffer(
   1137     OMX_IN  OMX_HANDLETYPE hComponent,
   1138     OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
   1139 {
   1140     ComponentBase *cbase;
   1141 
   1142     if (!hComponent)
   1143         return OMX_ErrorBadParameter;
   1144 
   1145     cbase = static_cast<ComponentBase *>
   1146         (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
   1147     if (!cbase)
   1148         return OMX_ErrorBadParameter;
   1149 
   1150     return cbase->CBaseFillThisBuffer(hComponent, pBuffer);
   1151 }
   1152 
   1153 OMX_ERRORTYPE ComponentBase::CBaseFillThisBuffer(
   1154     OMX_IN  OMX_HANDLETYPE hComponent,
   1155     OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
   1156 {
   1157     PortBase *port = NULL;
   1158     OMX_U32 port_index;
   1159     OMX_ERRORTYPE ret;
   1160 
   1161     if ((hComponent != handle) || !pBuffer)
   1162         return OMX_ErrorBadParameter;
   1163 
   1164     ret = CheckTypeHeader(pBuffer, sizeof(OMX_BUFFERHEADERTYPE));
   1165     if (ret != OMX_ErrorNone)
   1166         return ret;
   1167 
   1168     port_index = pBuffer->nOutputPortIndex;
   1169     if (port_index == (OMX_U32)-1)
   1170         return OMX_ErrorBadParameter;
   1171 
   1172     if (ports)
   1173         if (port_index < nr_ports)
   1174             port = ports[port_index];
   1175 
   1176     if (!port)
   1177         return OMX_ErrorBadParameter;
   1178 
   1179     if (port->IsEnabled()) {
   1180         if (state != OMX_StateIdle && state != OMX_StateExecuting &&
   1181             state != OMX_StatePause)
   1182             return OMX_ErrorIncorrectStateOperation;
   1183     }
   1184 
   1185     ProcessorPreFillBuffer(pBuffer);
   1186 
   1187     ret = port->PushThisBuffer(pBuffer);
   1188     if (ret == OMX_ErrorNone)
   1189         bufferwork->ScheduleWork(this);
   1190 
   1191     return ret;
   1192 }
   1193 
   1194 OMX_ERRORTYPE ComponentBase::SetCallbacks(
   1195     OMX_IN  OMX_HANDLETYPE hComponent,
   1196     OMX_IN  OMX_CALLBACKTYPE* pCallbacks,
   1197     OMX_IN  OMX_PTR pAppData)
   1198 {
   1199     ComponentBase *cbase;
   1200 
   1201     if (!hComponent)
   1202         return OMX_ErrorBadParameter;
   1203 
   1204     cbase = static_cast<ComponentBase *>
   1205         (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
   1206     if (!cbase)
   1207         return OMX_ErrorBadParameter;
   1208 
   1209     return cbase->CBaseSetCallbacks(hComponent, pCallbacks, pAppData);
   1210 }
   1211 
   1212 OMX_ERRORTYPE ComponentBase::CBaseSetCallbacks(
   1213     OMX_IN  OMX_HANDLETYPE hComponent,
   1214     OMX_IN  OMX_CALLBACKTYPE *pCallbacks,
   1215     OMX_IN  OMX_PTR pAppData)
   1216 {
   1217     if (hComponent != handle)
   1218         return OMX_ErrorBadParameter;
   1219 
   1220     appdata = pAppData;
   1221     callbacks = pCallbacks;
   1222 
   1223     return OMX_ErrorNone;
   1224 }
   1225 
   1226 OMX_ERRORTYPE ComponentBase::ComponentRoleEnum(
   1227     OMX_IN OMX_HANDLETYPE hComponent,
   1228     OMX_OUT OMX_U8 *cRole,
   1229     OMX_IN OMX_U32 nIndex)
   1230 {
   1231     ComponentBase *cbase;
   1232 
   1233     if (!hComponent)
   1234         return OMX_ErrorBadParameter;
   1235 
   1236     cbase = static_cast<ComponentBase *>
   1237         (((OMX_COMPONENTTYPE *)hComponent)->pComponentPrivate);
   1238     if (!cbase)
   1239         return OMX_ErrorBadParameter;
   1240 
   1241     return cbase->CBaseComponentRoleEnum(hComponent, cRole, nIndex);
   1242 }
   1243 
   1244 OMX_ERRORTYPE ComponentBase::CBaseComponentRoleEnum(
   1245     OMX_IN OMX_HANDLETYPE hComponent,
   1246     OMX_OUT OMX_U8 *cRole,
   1247     OMX_IN OMX_U32 nIndex)
   1248 {
   1249     if (hComponent != (OMX_HANDLETYPE *)this->handle)
   1250         return OMX_ErrorBadParameter;
   1251 
   1252     if (nIndex >= nr_roles)
   1253         return OMX_ErrorBadParameter;
   1254 
   1255     strncpy((char *)cRole, (const char *)roles[nIndex],
   1256             OMX_MAX_STRINGNAME_SIZE);
   1257     return OMX_ErrorNone;
   1258 }
   1259 
   1260 /* implement CmdHandlerInterface */
   1261 static const char *cmd_name[OMX_CommandMarkBuffer+2] = {
   1262     "OMX_CommandStateSet",
   1263     "OMX_CommandFlush",
   1264     "OMX_CommandPortDisable",
   1265     "OMX_CommandPortEnable",
   1266     "OMX_CommandMarkBuffer",
   1267     "Unknown Command",
   1268 };
   1269 
   1270 static inline const char *GetCmdName(OMX_COMMANDTYPE cmd)
   1271 {
   1272     if (cmd > OMX_CommandMarkBuffer)
   1273         cmd = (OMX_COMMANDTYPE)(OMX_CommandMarkBuffer+1);
   1274 
   1275     return cmd_name[cmd];
   1276 }
   1277 
   1278 void ComponentBase::CmdHandler(struct cmd_s *cmd)
   1279 {
   1280     LOGV("%s:%s: handling %s command\n",
   1281          GetName(), GetWorkingRole(), GetCmdName(cmd->cmd));
   1282 
   1283     switch (cmd->cmd) {
   1284     case OMX_CommandStateSet: {
   1285         OMX_STATETYPE transition = (OMX_STATETYPE)cmd->param1;
   1286 
   1287         pthread_mutex_lock(&state_block);
   1288         TransState(transition);
   1289         pthread_mutex_unlock(&state_block);
   1290         break;
   1291     }
   1292     case OMX_CommandFlush: {
   1293         OMX_U32 port_index = cmd->param1;
   1294         pthread_mutex_lock(&ports_block);
   1295         ProcessorFlush(port_index);
   1296         FlushPort(port_index, 1);
   1297         pthread_mutex_unlock(&ports_block);
   1298         break;
   1299     }
   1300     case OMX_CommandPortDisable: {
   1301         OMX_U32 port_index = cmd->param1;
   1302 
   1303         TransStatePort(port_index, PortBase::OMX_PortDisabled);
   1304         break;
   1305     }
   1306     case OMX_CommandPortEnable: {
   1307         OMX_U32 port_index = cmd->param1;
   1308 
   1309         TransStatePort(port_index, PortBase::OMX_PortEnabled);
   1310         break;
   1311     }
   1312     case OMX_CommandMarkBuffer: {
   1313         OMX_U32 port_index = (OMX_U32)cmd->param1;
   1314         OMX_MARKTYPE *mark = (OMX_MARKTYPE *)cmd->cmddata;
   1315 
   1316         PushThisMark(port_index, mark);
   1317         break;
   1318     }
   1319     default:
   1320         LOGE("%s:%s:%s: exit failure, command %d cannot be handled\n",
   1321              GetName(), GetWorkingRole(), GetCmdName(cmd->cmd), cmd->cmd);
   1322         break;
   1323     } /* switch */
   1324 
   1325     LOGV("%s:%s: command %s handling done\n",
   1326          GetName(), GetWorkingRole(), GetCmdName(cmd->cmd));
   1327 }
   1328 
   1329 /*
   1330  * SendCommand:OMX_CommandStateSet
   1331  * called in CmdHandler or called in other parts of component for reporting
   1332  * internal error (OMX_StateInvalid).
   1333  */
   1334 /*
   1335  * Todo
   1336  *   Resource Management (OMX_StateWaitForResources)
   1337  *   for now, we never notify OMX_ErrorInsufficientResources,
   1338  *   so IL client doesn't try to set component' state OMX_StateWaitForResources
   1339  */
   1340 static const char *state_name[OMX_StateWaitForResources+2] = {
   1341     "OMX_StateInvalid",
   1342     "OMX_StateLoaded",
   1343     "OMX_StateIdle",
   1344     "OMX_StateExecuting",
   1345     "OMX_StatePause",
   1346     "OMX_StateWaitForResources",
   1347     "Unknown State",
   1348 };
   1349 
   1350 static inline const char *GetStateName(OMX_STATETYPE state)
   1351 {
   1352     if (state > OMX_StateWaitForResources)
   1353         state = (OMX_STATETYPE)(OMX_StateWaitForResources+1);
   1354 
   1355     return state_name[state];
   1356 }
   1357 
   1358 void ComponentBase::TransState(OMX_STATETYPE transition)
   1359 {
   1360     OMX_STATETYPE current = this->state;
   1361     OMX_EVENTTYPE event;
   1362     OMX_U32 data1, data2;
   1363     OMX_ERRORTYPE ret;
   1364 
   1365     LOGV("%s:%s: try to transit state from %s to %s\n",
   1366          GetName(), GetWorkingRole(), GetStateName(current),
   1367          GetStateName(transition));
   1368 
   1369     /* same state */
   1370     if (current == transition) {
   1371         ret = OMX_ErrorSameState;
   1372         LOGE("%s:%s: exit failure, same state (%s)\n",
   1373              GetName(), GetWorkingRole(), GetStateName(current));
   1374         goto notify_event;
   1375     }
   1376 
   1377     /* invalid state */
   1378     if (current == OMX_StateInvalid) {
   1379         ret = OMX_ErrorInvalidState;
   1380         LOGE("%s:%s: exit failure, current state is OMX_StateInvalid\n",
   1381              GetName(), GetWorkingRole());
   1382         goto notify_event;
   1383     }
   1384 
   1385     if (transition == OMX_StateLoaded)
   1386         ret = TransStateToLoaded(current);
   1387     else if (transition == OMX_StateIdle)
   1388         ret = TransStateToIdle(current);
   1389     else if (transition == OMX_StateExecuting)
   1390         ret = TransStateToExecuting(current);
   1391     else if (transition == OMX_StatePause)
   1392         ret = TransStateToPause(current);
   1393     else if (transition == OMX_StateInvalid)
   1394         ret = TransStateToInvalid(current);
   1395     else if (transition == OMX_StateWaitForResources)
   1396         ret = TransStateToWaitForResources(current);
   1397     else
   1398         ret = OMX_ErrorIncorrectStateTransition;
   1399 
   1400 notify_event:
   1401     if (ret == OMX_ErrorNone) {
   1402         event = OMX_EventCmdComplete;
   1403         data1 = OMX_CommandStateSet;
   1404         data2 = transition;
   1405 
   1406         state = transition;
   1407         LOGD("%s:%s: transition from %s to %s completed",
   1408              GetName(), GetWorkingRole(),
   1409              GetStateName(current), GetStateName(transition));
   1410     }
   1411     else {
   1412         event = OMX_EventError;
   1413         data1 = ret;
   1414         data2 = 0;
   1415 
   1416         if (transition == OMX_StateInvalid || ret == OMX_ErrorInvalidState) {
   1417             state = OMX_StateInvalid;
   1418             LOGE("%s:%s: exit failure, transition from %s to %s, "
   1419                  "current state is %s\n",
   1420                  GetName(), GetWorkingRole(), GetStateName(current),
   1421                  GetStateName(transition), GetStateName(state));
   1422         }
   1423     }
   1424 
   1425     callbacks->EventHandler(handle, appdata, event, data1, data2, NULL);
   1426 
   1427     /* WaitForResources workaround */
   1428     if (ret == OMX_ErrorNone && transition == OMX_StateWaitForResources)
   1429         callbacks->EventHandler(handle, appdata,
   1430                                 OMX_EventResourcesAcquired, 0, 0, NULL);
   1431 }
   1432 
   1433 inline OMX_ERRORTYPE ComponentBase::TransStateToLoaded(OMX_STATETYPE current)
   1434 {
   1435     OMX_ERRORTYPE ret;
   1436 
   1437     if (current == OMX_StateIdle) {
   1438         OMX_U32 i;
   1439 
   1440         for (i = 0; i < nr_ports; i++)
   1441 	{
   1442             if (ports[i]->GetPortBufferCount() > 0) {
   1443                 ports[i]->WaitPortBufferCompletion();
   1444 	    };
   1445 	};
   1446 
   1447         ret = ProcessorDeinit();
   1448         if (ret != OMX_ErrorNone) {
   1449             LOGE("%s:%s: ProcessorDeinit() failed "
   1450                  "(ret : 0x%08x)\n", GetName(), GetWorkingRole(),
   1451                  ret);
   1452             goto out;
   1453         }
   1454     }
   1455     else if (current == OMX_StateWaitForResources) {
   1456         LOGV("%s:%s: "
   1457              "state transition's requested from WaitForResources to Loaded\n",
   1458              GetName(), GetWorkingRole());
   1459 
   1460         /*
   1461          * from WaitForResources to Loaded considered from Loaded to Loaded.
   1462          * do nothing
   1463          */
   1464 
   1465         ret = OMX_ErrorNone;
   1466     }
   1467     else
   1468         ret = OMX_ErrorIncorrectStateTransition;
   1469 
   1470 out:
   1471     return ret;
   1472 }
   1473 
   1474 inline OMX_ERRORTYPE ComponentBase::TransStateToIdle(OMX_STATETYPE current)
   1475 {
   1476     OMX_ERRORTYPE ret = OMX_ErrorNone;
   1477 
   1478     if (current == OMX_StateLoaded) {
   1479         OMX_U32 i;
   1480         for (i = 0; i < nr_ports; i++) {
   1481             if (ports[i]->IsEnabled()) {
   1482                 if (GetWorkingRole() != NULL &&
   1483                         !strncmp (GetWorkingRole(),"video_decoder", 13 )) {
   1484                     ret = ports[i]->WaitPortBufferCompletionTimeout(800);
   1485                 } else {
   1486                     ports[i]->WaitPortBufferCompletion();
   1487                 }
   1488             }
   1489         }
   1490 
   1491         if (ret == OMX_ErrorNone) {
   1492             ret = ProcessorInit();
   1493         }
   1494         if (ret != OMX_ErrorNone) {
   1495             LOGE("%s:%s: ProcessorInit() failed (ret : 0x%08x)\n",
   1496                  GetName(), GetWorkingRole(), ret);
   1497             goto out;
   1498         }
   1499     }
   1500     else if ((current == OMX_StatePause) || (current == OMX_StateExecuting)) {
   1501         pthread_mutex_lock(&ports_block);
   1502         FlushPort(OMX_ALL, 0);
   1503         pthread_mutex_unlock(&ports_block);
   1504         LOGV("%s:%s: flushed all ports\n", GetName(), GetWorkingRole());
   1505 
   1506         bufferwork->CancelScheduledWork(this);
   1507         LOGV("%s:%s: discarded all scheduled buffer process work\n",
   1508              GetName(), GetWorkingRole());
   1509 
   1510         if (current == OMX_StatePause) {
   1511             bufferwork->ResumeWork();
   1512             LOGV("%s:%s: buffer process work resumed\n",
   1513                  GetName(), GetWorkingRole());
   1514         }
   1515 
   1516         bufferwork->StopWork();
   1517         LOGV("%s:%s: buffer process work stopped\n",
   1518              GetName(), GetWorkingRole());
   1519 
   1520         ret = ProcessorStop();
   1521         if (ret != OMX_ErrorNone) {
   1522             LOGE("%s:%s: ProcessorStop() failed (ret : 0x%08x)\n",
   1523                  GetName(), GetWorkingRole(), ret);
   1524             goto out;
   1525         }
   1526     }
   1527     else if (current == OMX_StateWaitForResources) {
   1528         LOGV("%s:%s: "
   1529              "state transition's requested from WaitForResources to Idle\n",
   1530              GetName(), GetWorkingRole());
   1531 
   1532         /* same as Loaded to Idle BUT DO NOTHING for now */
   1533 
   1534         ret = OMX_ErrorNone;
   1535     }
   1536     else
   1537         ret = OMX_ErrorIncorrectStateTransition;
   1538 
   1539 out:
   1540     return ret;
   1541 }
   1542 
   1543 inline OMX_ERRORTYPE
   1544 ComponentBase::TransStateToExecuting(OMX_STATETYPE current)
   1545 {
   1546     OMX_ERRORTYPE ret;
   1547 
   1548     if (current == OMX_StateIdle) {
   1549         bufferwork->StartWork(true);
   1550         LOGV("%s:%s: buffer process work started with executing state\n",
   1551              GetName(), GetWorkingRole());
   1552 
   1553         ret = ProcessorStart();
   1554         if (ret != OMX_ErrorNone) {
   1555             LOGE("%s:%s: ProcessorStart() failed (ret : 0x%08x)\n",
   1556                  GetName(), GetWorkingRole(), ret);
   1557             goto out;
   1558         }
   1559     }
   1560     else if (current == OMX_StatePause) {
   1561         bufferwork->ResumeWork();
   1562         LOGV("%s:%s: buffer process work resumed\n",
   1563              GetName(), GetWorkingRole());
   1564 
   1565         ret = ProcessorResume();
   1566         if (ret != OMX_ErrorNone) {
   1567             LOGE("%s:%s: ProcessorResume() failed (ret : 0x%08x)\n",
   1568                  GetName(), GetWorkingRole(), ret);
   1569             goto out;
   1570         }
   1571     }
   1572     else
   1573         ret = OMX_ErrorIncorrectStateTransition;
   1574 
   1575 out:
   1576     return ret;
   1577 }
   1578 
   1579 inline OMX_ERRORTYPE ComponentBase::TransStateToPause(OMX_STATETYPE current)
   1580 {
   1581     OMX_ERRORTYPE ret;
   1582 
   1583     if (current == OMX_StateIdle) {
   1584         bufferwork->StartWork(false);
   1585         LOGV("%s:%s: buffer process work started with paused state\n",
   1586              GetName(), GetWorkingRole());
   1587 
   1588         ret = ProcessorStart();
   1589         if (ret != OMX_ErrorNone) {
   1590             LOGE("%s:%s: ProcessorSart() failed (ret : 0x%08x)\n",
   1591                  GetName(), GetWorkingRole(), ret);
   1592             goto out;
   1593         }
   1594     }
   1595     else if (current == OMX_StateExecuting) {
   1596         bufferwork->PauseWork();
   1597         LOGV("%s:%s: buffer process work paused\n",
   1598              GetName(), GetWorkingRole());
   1599 
   1600         ret = ProcessorPause();
   1601         if (ret != OMX_ErrorNone) {
   1602             LOGE("%s:%s: ProcessorPause() failed (ret : 0x%08x)\n",
   1603                  GetName(), GetWorkingRole(), ret);
   1604             goto out;
   1605         }
   1606     }
   1607     else
   1608         ret = OMX_ErrorIncorrectStateTransition;
   1609 
   1610 out:
   1611     return ret;
   1612 }
   1613 
   1614 inline OMX_ERRORTYPE ComponentBase::TransStateToInvalid(OMX_STATETYPE current)
   1615 {
   1616     OMX_ERRORTYPE ret = OMX_ErrorInvalidState;
   1617     LOGV("transit to invalid state from %d state",current);
   1618     /*
   1619      * Todo
   1620      *   graceful escape
   1621      */
   1622     return ret;
   1623 }
   1624 
   1625 inline OMX_ERRORTYPE
   1626 ComponentBase::TransStateToWaitForResources(OMX_STATETYPE current)
   1627 {
   1628     OMX_ERRORTYPE ret;
   1629 
   1630     if (current == OMX_StateLoaded) {
   1631         LOGV("%s:%s: "
   1632              "state transition's requested from Loaded to WaitForResources\n",
   1633              GetName(), GetWorkingRole());
   1634         ret = OMX_ErrorNone;
   1635     }
   1636     else
   1637         ret = OMX_ErrorIncorrectStateTransition;
   1638 
   1639     return ret;
   1640 }
   1641 
   1642 /* mark buffer */
   1643 void ComponentBase::PushThisMark(OMX_U32 port_index, OMX_MARKTYPE *mark)
   1644 {
   1645     PortBase *port = NULL;
   1646     OMX_EVENTTYPE event;
   1647     OMX_U32 data1, data2;
   1648     OMX_ERRORTYPE ret;
   1649 
   1650     if (ports)
   1651         if (port_index < nr_ports)
   1652             port = ports[port_index];
   1653 
   1654     if (!port) {
   1655         ret = OMX_ErrorBadPortIndex;
   1656         goto notify_event;
   1657     }
   1658 
   1659     ret = port->PushMark(mark);
   1660     if (ret != OMX_ErrorNone) {
   1661         /* don't report OMX_ErrorInsufficientResources */
   1662         ret = OMX_ErrorUndefined;
   1663         goto notify_event;
   1664     }
   1665 
   1666 notify_event:
   1667     if (ret == OMX_ErrorNone) {
   1668         event = OMX_EventCmdComplete;
   1669         data1 = OMX_CommandMarkBuffer;
   1670         data2 = port_index;
   1671     }
   1672     else {
   1673         event = OMX_EventError;
   1674         data1 = ret;
   1675         data2 = 0;
   1676     }
   1677 
   1678     callbacks->EventHandler(handle, appdata, event, data1, data2, NULL);
   1679 }
   1680 
   1681 void ComponentBase::FlushPort(OMX_U32 port_index, bool notify)
   1682 {
   1683     OMX_U32 i, from_index, to_index;
   1684 
   1685     if ((port_index != OMX_ALL) && (port_index > nr_ports-1))
   1686         return;
   1687 
   1688     if (port_index == OMX_ALL) {
   1689         from_index = 0;
   1690         to_index = nr_ports - 1;
   1691     }
   1692     else {
   1693         from_index = port_index;
   1694         to_index = port_index;
   1695     }
   1696 
   1697     LOGV("%s:%s: flush ports (from index %u to %u)\n",
   1698          GetName(), GetWorkingRole(), from_index, to_index);
   1699 
   1700     for (i = from_index; i <= to_index; i++) {
   1701         ports[i]->FlushPort();
   1702         if (notify)
   1703             callbacks->EventHandler(handle, appdata, OMX_EventCmdComplete,
   1704                                     OMX_CommandFlush, i, NULL);
   1705     }
   1706 
   1707     LOGV("%s:%s: flush ports done\n", GetName(), GetWorkingRole());
   1708 }
   1709 
   1710 extern const char *GetPortStateName(OMX_U8 state); //portbase.cpp
   1711 
   1712 void ComponentBase::TransStatePort(OMX_U32 port_index, OMX_U8 state)
   1713 {
   1714     OMX_EVENTTYPE event;
   1715     OMX_U32 data1, data2;
   1716     OMX_U32 i, from_index, to_index;
   1717     OMX_ERRORTYPE ret;
   1718 
   1719     if ((port_index != OMX_ALL) && (port_index > nr_ports-1))
   1720         return;
   1721 
   1722     if (port_index == OMX_ALL) {
   1723         from_index = 0;
   1724         to_index = nr_ports - 1;
   1725     }
   1726     else {
   1727         from_index = port_index;
   1728         to_index = port_index;
   1729     }
   1730 
   1731     LOGV("%s:%s: transit ports state to %s (from index %u to %u)\n",
   1732          GetName(), GetWorkingRole(), GetPortStateName(state),
   1733          from_index, to_index);
   1734 
   1735     pthread_mutex_lock(&ports_block);
   1736     for (i = from_index; i <= to_index; i++) {
   1737         ret = ports[i]->TransState(state);
   1738         if (ret == OMX_ErrorNone) {
   1739             event = OMX_EventCmdComplete;
   1740             if (state == PortBase::OMX_PortEnabled) {
   1741                 data1 = OMX_CommandPortEnable;
   1742                 ProcessorReset();
   1743             } else {
   1744                 data1 = OMX_CommandPortDisable;
   1745             }
   1746             data2 = i;
   1747         } else {
   1748             event = OMX_EventError;
   1749             data1 = ret;
   1750             data2 = 0;
   1751         }
   1752         callbacks->EventHandler(handle, appdata, event,
   1753                                 data1, data2, NULL);
   1754     }
   1755     pthread_mutex_unlock(&ports_block);
   1756 
   1757     LOGV("%s:%s: transit ports state to %s completed\n",
   1758          GetName(), GetWorkingRole(), GetPortStateName(state));
   1759 }
   1760 
   1761 /* set working role */
   1762 OMX_ERRORTYPE ComponentBase::SetWorkingRole(const OMX_STRING role)
   1763 {
   1764     OMX_U32 i;
   1765 
   1766     if (state != OMX_StateUnloaded && state != OMX_StateLoaded)
   1767         return OMX_ErrorIncorrectStateOperation;
   1768 
   1769     if (!role) {
   1770         working_role = NULL;
   1771         return OMX_ErrorNone;
   1772     }
   1773 
   1774     for (i = 0; i < nr_roles; i++) {
   1775         if (!strcmp((char *)&roles[i][0], role)) {
   1776             working_role = (OMX_STRING)&roles[i][0];
   1777             return OMX_ErrorNone;
   1778         }
   1779     }
   1780 
   1781     LOGE("%s: cannot find %s role\n", GetName(), role);
   1782     return OMX_ErrorBadParameter;
   1783 }
   1784 
   1785 /* apply a working role for a component having multiple roles */
   1786 OMX_ERRORTYPE ComponentBase::ApplyWorkingRole(void)
   1787 {
   1788     OMX_U32 i;
   1789     OMX_ERRORTYPE ret;
   1790 
   1791     if (state != OMX_StateUnloaded && state != OMX_StateLoaded)
   1792         return OMX_ErrorIncorrectStateOperation;
   1793 
   1794     if (!working_role)
   1795         return OMX_ErrorBadParameter;
   1796 
   1797     if (!callbacks || !appdata)
   1798         return OMX_ErrorBadParameter;
   1799 
   1800     ret = AllocatePorts();
   1801     if (ret != OMX_ErrorNone) {
   1802         LOGE("failed to AllocatePorts() (ret = 0x%08x)\n", ret);
   1803         return ret;
   1804     }
   1805 
   1806     /* now we can access ports */
   1807     for (i = 0; i < nr_ports; i++) {
   1808         ports[i]->SetOwner(handle);
   1809         ports[i]->SetCallbacks(handle, callbacks, appdata);
   1810     }
   1811 
   1812     LOGI("%s: set working role %s:", GetName(), GetWorkingRole());
   1813     return OMX_ErrorNone;
   1814 }
   1815 
   1816 OMX_ERRORTYPE ComponentBase::AllocatePorts(void)
   1817 {
   1818     OMX_DIRTYPE dir;
   1819     bool has_input, has_output;
   1820     OMX_U32 i;
   1821     OMX_ERRORTYPE ret;
   1822 
   1823     if (ports)
   1824         return OMX_ErrorBadParameter;
   1825 
   1826     ret = ComponentAllocatePorts();
   1827     if (ret != OMX_ErrorNone) {
   1828         LOGE("failed to %s::ComponentAllocatePorts(), ret = 0x%08x\n",
   1829              name, ret);
   1830         return ret;
   1831     }
   1832 
   1833     has_input = false;
   1834     has_output = false;
   1835     ret = OMX_ErrorNone;
   1836     for (i = 0; i < nr_ports; i++) {
   1837         dir = ports[i]->GetPortDirection();
   1838         if (dir == OMX_DirInput)
   1839             has_input = true;
   1840         else if (dir == OMX_DirOutput)
   1841             has_output = true;
   1842         else {
   1843             ret = OMX_ErrorUndefined;
   1844             break;
   1845         }
   1846     }
   1847     if (ret != OMX_ErrorNone)
   1848         goto free_ports;
   1849 
   1850     if ((has_input == false) && (has_output == true))
   1851         cvariant = CVARIANT_SOURCE;
   1852     else if ((has_input == true) && (has_output == true))
   1853         cvariant = CVARIANT_FILTER;
   1854     else if ((has_input == true) && (has_output == false))
   1855         cvariant = CVARIANT_SINK;
   1856     else
   1857         goto free_ports;
   1858 
   1859     return OMX_ErrorNone;
   1860 
   1861 free_ports:
   1862     LOGE("%s(): exit, unknown component variant\n", __func__);
   1863     FreePorts();
   1864     return OMX_ErrorUndefined;
   1865 }
   1866 
   1867 /* called int FreeHandle() */
   1868 OMX_ERRORTYPE ComponentBase::FreePorts(void)
   1869 {
   1870     if (ports) {
   1871         OMX_U32 i, this_nr_ports = this->nr_ports;
   1872 
   1873         for (i = 0; i < this_nr_ports; i++) {
   1874             if (ports[i]) {
   1875                 OMX_MARKTYPE *mark;
   1876                 /* it should be empty before this */
   1877                 while ((mark = ports[i]->PopMark()))
   1878                     free(mark);
   1879 
   1880                 delete ports[i];
   1881                 ports[i] = NULL;
   1882             }
   1883         }
   1884         delete []ports;
   1885         ports = NULL;
   1886     }
   1887 
   1888     return OMX_ErrorNone;
   1889 }
   1890 
   1891 /* buffer processing */
   1892 /* implement WorkableInterface */
   1893 void ComponentBase::Work(void)
   1894 {
   1895     OMX_BUFFERHEADERTYPE **buffers[nr_ports];
   1896     OMX_BUFFERHEADERTYPE *buffers_hdr[nr_ports];
   1897     OMX_BUFFERHEADERTYPE *buffers_org[nr_ports];
   1898     buffer_retain_t retain[nr_ports];
   1899     OMX_U32 i;
   1900     OMX_ERRORTYPE ret;
   1901 
   1902     if (nr_ports == 0) {
   1903         return;
   1904     }
   1905 
   1906     memset(buffers, 0, sizeof(OMX_BUFFERHEADERTYPE *) * nr_ports);
   1907     memset(buffers_hdr, 0, sizeof(OMX_BUFFERHEADERTYPE *) * nr_ports);
   1908     memset(buffers_org, 0, sizeof(OMX_BUFFERHEADERTYPE *) * nr_ports);
   1909 
   1910     pthread_mutex_lock(&ports_block);
   1911 
   1912     while(IsAllBufferAvailable())
   1913     {
   1914         for (i = 0; i < nr_ports; i++) {
   1915             buffers_hdr[i] = ports[i]->PopBuffer();
   1916             buffers[i] = &buffers_hdr[i];
   1917             buffers_org[i] = buffers_hdr[i];
   1918             retain[i] = BUFFER_RETAIN_NOT_RETAIN;
   1919         }
   1920 
   1921         if (working_role != NULL && !strncmp((char*)working_role, "video_decoder", 13)){
   1922             ret = ProcessorProcess(buffers, &retain[0], nr_ports);
   1923         }else{
   1924             ret = ProcessorProcess(buffers_hdr, &retain[0], nr_ports);
   1925         }
   1926 
   1927         if (ret == OMX_ErrorNone) {
   1928             if (!working_role || (strncmp((char*)working_role, "video_encoder", 13) != 0))
   1929                 PostProcessBuffers(buffers, &retain[0]);
   1930 
   1931             for (i = 0; i < nr_ports; i++) {
   1932                 if (buffers_hdr[i] == NULL)
   1933                     continue;
   1934 
   1935                 if(retain[i] == BUFFER_RETAIN_GETAGAIN) {
   1936                     ports[i]->RetainThisBuffer(*buffers[i], false);
   1937                 }
   1938                 else if (retain[i] == BUFFER_RETAIN_ACCUMULATE) {
   1939                     ports[i]->RetainThisBuffer(*buffers[i], true);
   1940                 }
   1941                 else if (retain[i] == BUFFER_RETAIN_OVERRIDDEN) {
   1942                     ports[i]->RetainAndReturnBuffer(buffers_org[i], *buffers[i]);
   1943                 }
   1944                 else if (retain[i] == BUFFER_RETAIN_CACHE) {
   1945                     //nothing to do
   1946                 } else {
   1947                     ports[i]->ReturnThisBuffer(*buffers[i]);
   1948                 }
   1949             }
   1950         }
   1951         else {
   1952 
   1953             for (i = 0; i < nr_ports; i++) {
   1954                 if (buffers_hdr[i] == NULL)
   1955                     continue;
   1956 
   1957                 /* return buffers by hands, these buffers're not in queue */
   1958                 ports[i]->ReturnThisBuffer(*buffers[i]);
   1959                 /* flush ports */
   1960                 ports[i]->FlushPort();
   1961             }
   1962 
   1963             callbacks->EventHandler(handle, appdata, OMX_EventError, ret,
   1964                                     0, NULL);
   1965         }
   1966     }
   1967 
   1968     pthread_mutex_unlock(&ports_block);
   1969 }
   1970 
   1971 bool ComponentBase::IsAllBufferAvailable(void)
   1972 {
   1973     OMX_U32 i;
   1974     OMX_U32 nr_avail = 0;
   1975 
   1976     for (i = 0; i < nr_ports; i++) {
   1977         OMX_U32 length = 0;
   1978 
   1979         if (ports[i]->IsEnabled()) {
   1980             length += ports[i]->BufferQueueLength();
   1981             length += ports[i]->RetainedBufferQueueLength();
   1982         }
   1983 
   1984         if (length)
   1985             nr_avail++;
   1986     }
   1987 
   1988     if (nr_avail == nr_ports)
   1989         return true;
   1990     else
   1991         return false;
   1992 }
   1993 
   1994 inline void ComponentBase::SourcePostProcessBuffers(
   1995     OMX_BUFFERHEADERTYPE ***buffers)
   1996 {
   1997     OMX_U32 i;
   1998 
   1999     for (i = 0; i < nr_ports; i++) {
   2000         /*
   2001          * in case of source component, buffers're marked when they come
   2002          * from the ouput ports
   2003          */
   2004         if (!(*buffers[i])->hMarkTargetComponent) {
   2005             OMX_MARKTYPE *mark;
   2006 
   2007             mark = ports[i]->PopMark();
   2008             if (mark) {
   2009                 (*buffers[i])->hMarkTargetComponent = mark->hMarkTargetComponent;
   2010                 (*buffers[i])->pMarkData = mark->pMarkData;
   2011                 free(mark);
   2012             }
   2013         }
   2014     }
   2015 }
   2016 
   2017 inline void ComponentBase::FilterPostProcessBuffers(
   2018     OMX_BUFFERHEADERTYPE ***buffers,
   2019     const buffer_retain_t *retain)
   2020 {
   2021     OMX_MARKTYPE *mark;
   2022     OMX_U32 i, j;
   2023 
   2024     for (i = 0; i < nr_ports; i++) {
   2025         if (ports[i]->GetPortDirection() == OMX_DirInput) {
   2026             for (j = 0; j < nr_ports; j++) {
   2027                 if (ports[j]->GetPortDirection() != OMX_DirOutput)
   2028                     continue;
   2029 
   2030                 /* propagates EOS flag */
   2031                 /* clear input EOS at the end of this loop */
   2032                 if (retain[i] != BUFFER_RETAIN_GETAGAIN) {
   2033                     if ((*buffers[i])->nFlags & OMX_BUFFERFLAG_EOS)
   2034                         (*buffers[j])->nFlags |= OMX_BUFFERFLAG_EOS;
   2035                 }
   2036 
   2037                 /* propagates marks */
   2038                 /*
   2039                  * if hMarkTargetComponent == handle then the mark's not
   2040                  * propagated
   2041                  */
   2042                 if ((*buffers[i])->hMarkTargetComponent &&
   2043                     ((*buffers[i])->hMarkTargetComponent != handle)) {
   2044                     if ((*buffers[j])->hMarkTargetComponent) {
   2045                         mark = (OMX_MARKTYPE *)malloc(sizeof(*mark));
   2046                         if (mark) {
   2047                             mark->hMarkTargetComponent =
   2048                                 (*buffers[i])->hMarkTargetComponent;
   2049                             mark->pMarkData = (*buffers[i])->pMarkData;
   2050                             ports[j]->PushMark(mark);
   2051                             mark = NULL;
   2052                             (*buffers[i])->hMarkTargetComponent = NULL;
   2053                             (*buffers[i])->pMarkData = NULL;
   2054                         }
   2055                     }
   2056                     else {
   2057                         mark = ports[j]->PopMark();
   2058                         if (mark) {
   2059                             (*buffers[j])->hMarkTargetComponent =
   2060                                 mark->hMarkTargetComponent;
   2061                             (*buffers[j])->pMarkData = mark->pMarkData;
   2062                             free(mark);
   2063 
   2064                             mark = (OMX_MARKTYPE *)malloc(sizeof(*mark));
   2065                             if (mark) {
   2066                                 mark->hMarkTargetComponent =
   2067                                     (*buffers[i])->hMarkTargetComponent;
   2068                                 mark->pMarkData = (*buffers[i])->pMarkData;
   2069                                 ports[j]->PushMark(mark);
   2070                                 mark = NULL;
   2071                                 (*buffers[i])->hMarkTargetComponent = NULL;
   2072                                 (*buffers[i])->pMarkData = NULL;
   2073                             }
   2074                         }
   2075                         else {
   2076                             (*buffers[j])->hMarkTargetComponent =
   2077                                 (*buffers[i])->hMarkTargetComponent;
   2078                             (*buffers[j])->pMarkData = (*buffers[i])->pMarkData;
   2079                             (*buffers[i])->hMarkTargetComponent = NULL;
   2080                             (*buffers[i])->pMarkData = NULL;
   2081                         }
   2082                     }
   2083                 }
   2084             }
   2085             /* clear input buffer's EOS */
   2086             if (retain[i] != BUFFER_RETAIN_GETAGAIN)
   2087                 (*buffers[i])->nFlags &= ~OMX_BUFFERFLAG_EOS;
   2088         }
   2089     }
   2090 }
   2091 
   2092 inline void ComponentBase::SinkPostProcessBuffers()
   2093 {
   2094     return;
   2095 }
   2096 
   2097 void ComponentBase::PostProcessBuffers(OMX_BUFFERHEADERTYPE ***buffers,
   2098                                        const buffer_retain_t *retain)
   2099 {
   2100 
   2101     if (cvariant == CVARIANT_SOURCE)
   2102         SourcePostProcessBuffers(buffers);
   2103     else if (cvariant == CVARIANT_FILTER)
   2104         FilterPostProcessBuffers(buffers, retain);
   2105     else if (cvariant == CVARIANT_SINK) {
   2106         SinkPostProcessBuffers();
   2107     }
   2108     else {
   2109         LOGE("%s(): fatal error unknown component variant (%d)\n",
   2110              __func__, cvariant);
   2111     }
   2112 }
   2113 
   2114 /* processor default callbacks */
   2115 OMX_ERRORTYPE ComponentBase::ProcessorInit(void)
   2116 {
   2117     return OMX_ErrorNone;
   2118 }
   2119 OMX_ERRORTYPE ComponentBase::ProcessorDeinit(void)
   2120 {
   2121     return OMX_ErrorNone;
   2122 }
   2123 
   2124 OMX_ERRORTYPE ComponentBase::ProcessorStart(void)
   2125 {
   2126     return OMX_ErrorNone;
   2127 }
   2128 
   2129 OMX_ERRORTYPE ComponentBase::ProcessorReset(void)
   2130 {
   2131     return OMX_ErrorNone;
   2132 }
   2133 
   2134 
   2135 OMX_ERRORTYPE ComponentBase::ProcessorStop(void)
   2136 {
   2137     return OMX_ErrorNone;
   2138 }
   2139 
   2140 OMX_ERRORTYPE ComponentBase::ProcessorPause(void)
   2141 {
   2142     return OMX_ErrorNone;
   2143 }
   2144 
   2145 OMX_ERRORTYPE ComponentBase::ProcessorResume(void)
   2146 {
   2147     return OMX_ErrorNone;
   2148 }
   2149 
   2150 OMX_ERRORTYPE ComponentBase::ProcessorFlush(OMX_U32)
   2151 {
   2152     return OMX_ErrorNone;
   2153 }
   2154 OMX_ERRORTYPE ComponentBase::ProcessorPreFillBuffer(OMX_BUFFERHEADERTYPE*)
   2155 {
   2156     return OMX_ErrorNone;
   2157 }
   2158 
   2159 OMX_ERRORTYPE ComponentBase::ProcessorPreEmptyBuffer(OMX_BUFFERHEADERTYPE*)
   2160 {
   2161     return OMX_ErrorNone;
   2162 }
   2163 OMX_ERRORTYPE ComponentBase::ProcessorProcess(OMX_BUFFERHEADERTYPE **,
   2164                                            buffer_retain_t *,
   2165                                            OMX_U32)
   2166 {
   2167     LOGE("ProcessorProcess not be implemented");
   2168     return OMX_ErrorNotImplemented;
   2169 }
   2170 OMX_ERRORTYPE ComponentBase::ProcessorProcess(OMX_BUFFERHEADERTYPE ***,
   2171                                            buffer_retain_t *,
   2172                                            OMX_U32)
   2173 {
   2174     LOGE("ProcessorProcess not be implemented");
   2175     return OMX_ErrorNotImplemented;
   2176 }
   2177 
   2178 OMX_ERRORTYPE ComponentBase::ProcessorPreFreeBuffer(OMX_U32, OMX_BUFFERHEADERTYPE*)
   2179 {
   2180     return OMX_ErrorNone;
   2181 
   2182 }
   2183 /* end of processor callbacks */
   2184 
   2185 /* helper for derived class */
   2186 OMX_STRING ComponentBase::GetWorkingRole(void)
   2187 {
   2188     return &working_role[0];
   2189 }
   2190 
   2191 const OMX_COMPONENTTYPE *ComponentBase::GetComponentHandle(void)
   2192 {
   2193     return handle;
   2194 }
   2195 #if 0
   2196 void ComponentBase::DumpBuffer(const OMX_BUFFERHEADERTYPE *bufferheader,
   2197                                bool dumpdata)
   2198 {
   2199     OMX_U8 *pbuffer = bufferheader->pBuffer, *p;
   2200     OMX_U32 offset = bufferheader->nOffset;
   2201     OMX_U32 alloc_len = bufferheader->nAllocLen;
   2202     OMX_U32 filled_len =  bufferheader->nFilledLen;
   2203     OMX_U32 left = filled_len, oneline;
   2204     OMX_U32 index = 0, i;
   2205     /* 0x%04lx:  %02x %02x .. (n = 16)\n\0 */
   2206     char prbuffer[8 + 3 * 0x10 + 2], *pp;
   2207     OMX_U32 prbuffer_len;
   2208 
   2209     LOGD("Component %s DumpBuffer\n", name);
   2210     LOGD("%s port index = %lu",
   2211          (bufferheader->nInputPortIndex != 0x7fffffff) ? "input" : "output",
   2212          (bufferheader->nInputPortIndex != 0x7fffffff) ?
   2213          bufferheader->nInputPortIndex : bufferheader->nOutputPortIndex);
   2214     LOGD("nAllocLen = %lu, nOffset = %lu, nFilledLen = %lu\n",
   2215          alloc_len, offset, filled_len);
   2216     LOGD("nTimeStamp = %lld, nTickCount = %lu",
   2217          bufferheader->nTimeStamp,
   2218          bufferheader->nTickCount);
   2219     LOGD("nFlags = 0x%08lx\n", bufferheader->nFlags);
   2220     LOGD("hMarkTargetComponent = %p, pMarkData = %p\n",
   2221          bufferheader->hMarkTargetComponent, bufferheader->pMarkData);
   2222 
   2223     if (!pbuffer || !alloc_len || !filled_len)
   2224         return;
   2225 
   2226     if (offset + filled_len > alloc_len)
   2227         return;
   2228 
   2229     if (!dumpdata)
   2230         return;
   2231 
   2232     p = pbuffer + offset;
   2233     while (left) {
   2234         oneline = left > 0x10 ? 0x10 : left; /* 16 items per 1 line */
   2235         pp += sprintf(pp, "0x%04lx: ", index);
   2236         for (i = 0; i < oneline; i++)
   2237             pp += sprintf(pp, " %02x", *(p + i));
   2238         pp += sprintf(pp, "\n");
   2239         *pp = '\0';
   2240 
   2241         index += 0x10;
   2242         p += oneline;
   2243         left -= oneline;
   2244 
   2245         pp = &prbuffer[0];
   2246         LOGD("%s", pp);
   2247     }
   2248 }
   2249 #endif
   2250 /* end of component methods & helpers */
   2251 
   2252 /*
   2253  * omx header manipuation
   2254  */
   2255 void ComponentBase::SetTypeHeader(OMX_PTR type, OMX_U32 size)
   2256 {
   2257     OMX_U32 *nsize;
   2258     OMX_VERSIONTYPE *nversion;
   2259 
   2260     if (!type)
   2261         return;
   2262 
   2263     nsize = (OMX_U32 *)type;
   2264     nversion = (OMX_VERSIONTYPE *)((OMX_U8 *)type + sizeof(OMX_U32));
   2265 
   2266     *nsize = size;
   2267     nversion->nVersion = OMX_SPEC_VERSION;
   2268 }
   2269 
   2270 OMX_ERRORTYPE ComponentBase::CheckTypeHeader(const OMX_PTR type, OMX_U32 size)
   2271 {
   2272     OMX_U32 *nsize;
   2273     OMX_VERSIONTYPE *nversion;
   2274 
   2275     if (!type)
   2276         return OMX_ErrorBadParameter;
   2277 
   2278     nsize = (OMX_U32 *)type;
   2279     nversion = (OMX_VERSIONTYPE *)((OMX_U8 *)type + sizeof(OMX_U32));
   2280 
   2281     if (*nsize != size)
   2282         return OMX_ErrorBadParameter;
   2283 
   2284     if (nversion->nVersion != OMX_SPEC_VERSION)
   2285         return OMX_ErrorVersionMismatch;
   2286 
   2287     return OMX_ErrorNone;
   2288 }
   2289 
   2290 /* end of ComponentBase */
   2291