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