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     return OMX_ErrorUnsupportedIndex;
    878 }
    879 
    880 OMX_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 
    897 OMX_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 }
    909 OMX_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 
    931 OMX_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 
    967 OMX_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 
    988 OMX_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 
   1019 OMX_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 
   1037 OMX_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 
   1062 OMX_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 
   1079 OMX_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 
   1131 OMX_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 
   1148 OMX_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 
   1189 OMX_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 
   1207 OMX_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 
   1221 OMX_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 
   1239 OMX_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 */
   1256 static 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 
   1265 static 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 
   1273 void 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  */
   1335 static 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 
   1345 static 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 
   1353 void 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 
   1395 notify_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 
   1428 inline 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 
   1465 out:
   1466     return ret;
   1467 }
   1468 
   1469 inline 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 
   1534 out:
   1535     return ret;
   1536 }
   1537 
   1538 inline OMX_ERRORTYPE
   1539 ComponentBase::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 
   1570 out:
   1571     return ret;
   1572 }
   1573 
   1574 inline 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 
   1605 out:
   1606     return ret;
   1607 }
   1608 
   1609 inline 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 
   1620 inline OMX_ERRORTYPE
   1621 ComponentBase::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 */
   1638 void 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 
   1661 notify_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 
   1676 void 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 
   1705 extern const char *GetPortStateName(OMX_U8 state); //portbase.cpp
   1706 
   1707 void 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 */
   1757 OMX_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 */
   1781 OMX_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 
   1811 OMX_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 
   1856 free_ports:
   1857     LOGE("%s(): exit, unknown component variant\n", __func__);
   1858     FreePorts();
   1859     return OMX_ErrorUndefined;
   1860 }
   1861 
   1862 /* called int FreeHandle() */
   1863 OMX_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 */
   1888 void 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 
   1966 bool 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 
   1989 inline 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 
   2012 inline 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 
   2087 inline void ComponentBase::SinkPostProcessBuffers()
   2088 {
   2089     return;
   2090 }
   2091 
   2092 void 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 */
   2110 OMX_ERRORTYPE ComponentBase::ProcessorInit(void)
   2111 {
   2112     return OMX_ErrorNone;
   2113 }
   2114 OMX_ERRORTYPE ComponentBase::ProcessorDeinit(void)
   2115 {
   2116     return OMX_ErrorNone;
   2117 }
   2118 
   2119 OMX_ERRORTYPE ComponentBase::ProcessorStart(void)
   2120 {
   2121     return OMX_ErrorNone;
   2122 }
   2123 
   2124 OMX_ERRORTYPE ComponentBase::ProcessorReset(void)
   2125 {
   2126     return OMX_ErrorNone;
   2127 }
   2128 
   2129 
   2130 OMX_ERRORTYPE ComponentBase::ProcessorStop(void)
   2131 {
   2132     return OMX_ErrorNone;
   2133 }
   2134 
   2135 OMX_ERRORTYPE ComponentBase::ProcessorPause(void)
   2136 {
   2137     return OMX_ErrorNone;
   2138 }
   2139 
   2140 OMX_ERRORTYPE ComponentBase::ProcessorResume(void)
   2141 {
   2142     return OMX_ErrorNone;
   2143 }
   2144 
   2145 OMX_ERRORTYPE ComponentBase::ProcessorFlush(OMX_U32)
   2146 {
   2147     return OMX_ErrorNone;
   2148 }
   2149 OMX_ERRORTYPE ComponentBase::ProcessorPreFillBuffer(OMX_BUFFERHEADERTYPE*)
   2150 {
   2151     return OMX_ErrorNone;
   2152 }
   2153 
   2154 OMX_ERRORTYPE ComponentBase::ProcessorPreEmptyBuffer(OMX_BUFFERHEADERTYPE*)
   2155 {
   2156     return OMX_ErrorNone;
   2157 }
   2158 OMX_ERRORTYPE ComponentBase::ProcessorProcess(OMX_BUFFERHEADERTYPE **,
   2159                                            buffer_retain_t *,
   2160                                            OMX_U32)
   2161 {
   2162     LOGE("ProcessorProcess not be implemented");
   2163     return OMX_ErrorNotImplemented;
   2164 }
   2165 OMX_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 
   2173 OMX_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 */
   2181 OMX_STRING ComponentBase::GetWorkingRole(void)
   2182 {
   2183     return &working_role[0];
   2184 }
   2185 
   2186 const OMX_COMPONENTTYPE *ComponentBase::GetComponentHandle(void)
   2187 {
   2188     return handle;
   2189 }
   2190 #if 0
   2191 void 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  */
   2250 void 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 
   2265 OMX_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