• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
CmdProcessWork(CmdHandlerInterface * ci)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 
~CmdProcessWork()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 
PushCmdQueue(struct cmd_s * cmd)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 
PopCmdQueue(void)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 
Work(void)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  */
__ComponentBase(void)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 
ComponentBase()146 ComponentBase::ComponentBase()
147 {
148     __ComponentBase();
149 }
150 
ComponentBase(const OMX_STRING name)151 ComponentBase::ComponentBase(const OMX_STRING name)
152 {
153     __ComponentBase();
154     SetName(name);
155 }
156 
~ComponentBase()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 */
SetName(const OMX_STRING 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 
GetName(void)182 OMX_STRING ComponentBase::GetName(void)
183 {
184     return name;
185 }
186 
187 /* component module */
SetCModule(CModule * cmodule)188 void ComponentBase::SetCModule(CModule *cmodule)
189 {
190     this->cmodule = cmodule;
191 }
192 
GetCModule(void)193 CModule *ComponentBase::GetCModule(void)
194 {
195     return cmodule;
196 }
197 
198 /* end of accessor */
199 
200 /*
201  * core methods & helpers
202  */
203 /* roles */
SetRolesOfComponent(OMX_U32 nr_roles,const OMX_U8 ** 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 */
GetHandle(OMX_HANDLETYPE * pHandle,OMX_PTR pAppData,OMX_CALLBACKTYPE * pCallBacks)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 
FreeHandle(OMX_HANDLETYPE hComponent)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  */
SendCommand(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_COMMANDTYPE Cmd,OMX_IN OMX_U32 nParam1,OMX_IN OMX_PTR pCmdData)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 
CBaseSendCommand(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_COMMANDTYPE Cmd,OMX_IN OMX_U32 nParam1,OMX_IN OMX_PTR pCmdData)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 
GetParameter(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_INDEXTYPE nParamIndex,OMX_INOUT OMX_PTR pComponentParameterStructure)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 
CBaseGetParameter(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_INDEXTYPE nParamIndex,OMX_INOUT OMX_PTR pComponentParameterStructure)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 
SetParameter(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_INDEXTYPE nIndex,OMX_IN OMX_PTR pComponentParameterStructure)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 
CBaseSetParameter(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_INDEXTYPE nIndex,OMX_IN OMX_PTR pComponentParameterStructure)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 
GetConfig(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_INDEXTYPE nIndex,OMX_INOUT OMX_PTR pComponentConfigStructure)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 
CBaseGetConfig(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_INDEXTYPE nIndex,OMX_INOUT OMX_PTR pComponentConfigStructure)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 
SetConfig(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_INDEXTYPE nIndex,OMX_IN OMX_PTR pComponentConfigStructure)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 
CBaseSetConfig(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_INDEXTYPE nIndex,OMX_IN OMX_PTR pComponentConfigStructure)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 
GetExtensionIndex(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_STRING cParameterName,OMX_OUT OMX_INDEXTYPE * pIndexType)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 
CBaseGetExtensionIndex(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_STRING cParameterName,OMX_OUT OMX_INDEXTYPE * pIndexType)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 
GetState(OMX_IN OMX_HANDLETYPE hComponent,OMX_OUT OMX_STATETYPE * pState)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 
CBaseGetState(OMX_IN OMX_HANDLETYPE hComponent,OMX_OUT OMX_STATETYPE * pState)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 }
UseBuffer(OMX_IN OMX_HANDLETYPE hComponent,OMX_INOUT OMX_BUFFERHEADERTYPE ** ppBufferHdr,OMX_IN OMX_U32 nPortIndex,OMX_IN OMX_PTR pAppPrivate,OMX_IN OMX_U32 nSizeBytes,OMX_IN OMX_U8 * pBuffer)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 
CBaseUseBuffer(OMX_IN OMX_HANDLETYPE hComponent,OMX_INOUT OMX_BUFFERHEADERTYPE ** ppBufferHdr,OMX_IN OMX_U32 nPortIndex,OMX_IN OMX_PTR pAppPrivate,OMX_IN OMX_U32 nSizeBytes,OMX_IN OMX_U8 * pBuffer)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 
AllocateBuffer(OMX_IN OMX_HANDLETYPE hComponent,OMX_INOUT OMX_BUFFERHEADERTYPE ** ppBuffer,OMX_IN OMX_U32 nPortIndex,OMX_IN OMX_PTR pAppPrivate,OMX_IN OMX_U32 nSizeBytes)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 
CBaseAllocateBuffer(OMX_IN OMX_HANDLETYPE hComponent,OMX_INOUT OMX_BUFFERHEADERTYPE ** ppBuffer,OMX_IN OMX_U32 nPortIndex,OMX_IN OMX_PTR pAppPrivate,OMX_IN OMX_U32 nSizeBytes)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 
FreeBuffer(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_U32 nPortIndex,OMX_IN OMX_BUFFERHEADERTYPE * pBuffer)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 
CBaseFreeBuffer(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_U32 nPortIndex,OMX_IN OMX_BUFFERHEADERTYPE * pBuffer)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 
EmptyThisBuffer(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_BUFFERHEADERTYPE * pBuffer)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 
CBaseEmptyThisBuffer(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_BUFFERHEADERTYPE * pBuffer)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 
FillThisBuffer(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_BUFFERHEADERTYPE * pBuffer)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 
CBaseFillThisBuffer(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_BUFFERHEADERTYPE * pBuffer)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 
SetCallbacks(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_CALLBACKTYPE * pCallbacks,OMX_IN OMX_PTR pAppData)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 
CBaseSetCallbacks(OMX_IN OMX_HANDLETYPE hComponent,OMX_IN OMX_CALLBACKTYPE * pCallbacks,OMX_IN OMX_PTR pAppData)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 
ComponentRoleEnum(OMX_IN OMX_HANDLETYPE hComponent,OMX_OUT OMX_U8 * cRole,OMX_IN OMX_U32 nIndex)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 
CBaseComponentRoleEnum(OMX_IN OMX_HANDLETYPE hComponent,OMX_OUT OMX_U8 * cRole,OMX_IN OMX_U32 nIndex)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 
GetCmdName(OMX_COMMANDTYPE cmd)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 
CmdHandler(struct cmd_s * cmd)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 
GetStateName(OMX_STATETYPE state)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 
TransState(OMX_STATETYPE transition)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 
TransStateToLoaded(OMX_STATETYPE current)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 
TransStateToIdle(OMX_STATETYPE current)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
TransStateToExecuting(OMX_STATETYPE current)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 
TransStateToPause(OMX_STATETYPE current)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 
TransStateToInvalid(OMX_STATETYPE current)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
TransStateToWaitForResources(OMX_STATETYPE current)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 */
PushThisMark(OMX_U32 port_index,OMX_MARKTYPE * mark)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 
FlushPort(OMX_U32 port_index,bool notify)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 
TransStatePort(OMX_U32 port_index,OMX_U8 state)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 */
SetWorkingRole(const OMX_STRING 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 */
ApplyWorkingRole(void)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 
AllocatePorts(void)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() */
FreePorts(void)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 */
Work(void)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 
IsAllBufferAvailable(void)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 
SourcePostProcessBuffers(OMX_BUFFERHEADERTYPE *** buffers)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 
FilterPostProcessBuffers(OMX_BUFFERHEADERTYPE *** buffers,const buffer_retain_t * retain)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 
SinkPostProcessBuffers()2087 inline void ComponentBase::SinkPostProcessBuffers()
2088 {
2089     return;
2090 }
2091 
PostProcessBuffers(OMX_BUFFERHEADERTYPE *** buffers,const buffer_retain_t * retain)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 */
ProcessorInit(void)2110 OMX_ERRORTYPE ComponentBase::ProcessorInit(void)
2111 {
2112     return OMX_ErrorNone;
2113 }
ProcessorDeinit(void)2114 OMX_ERRORTYPE ComponentBase::ProcessorDeinit(void)
2115 {
2116     return OMX_ErrorNone;
2117 }
2118 
ProcessorStart(void)2119 OMX_ERRORTYPE ComponentBase::ProcessorStart(void)
2120 {
2121     return OMX_ErrorNone;
2122 }
2123 
ProcessorReset(void)2124 OMX_ERRORTYPE ComponentBase::ProcessorReset(void)
2125 {
2126     return OMX_ErrorNone;
2127 }
2128 
2129 
ProcessorStop(void)2130 OMX_ERRORTYPE ComponentBase::ProcessorStop(void)
2131 {
2132     return OMX_ErrorNone;
2133 }
2134 
ProcessorPause(void)2135 OMX_ERRORTYPE ComponentBase::ProcessorPause(void)
2136 {
2137     return OMX_ErrorNone;
2138 }
2139 
ProcessorResume(void)2140 OMX_ERRORTYPE ComponentBase::ProcessorResume(void)
2141 {
2142     return OMX_ErrorNone;
2143 }
2144 
ProcessorFlush(OMX_U32)2145 OMX_ERRORTYPE ComponentBase::ProcessorFlush(OMX_U32)
2146 {
2147     return OMX_ErrorNone;
2148 }
ProcessorPreFillBuffer(OMX_BUFFERHEADERTYPE *)2149 OMX_ERRORTYPE ComponentBase::ProcessorPreFillBuffer(OMX_BUFFERHEADERTYPE*)
2150 {
2151     return OMX_ErrorNone;
2152 }
2153 
ProcessorPreEmptyBuffer(OMX_BUFFERHEADERTYPE *)2154 OMX_ERRORTYPE ComponentBase::ProcessorPreEmptyBuffer(OMX_BUFFERHEADERTYPE*)
2155 {
2156     return OMX_ErrorNone;
2157 }
ProcessorProcess(OMX_BUFFERHEADERTYPE **,buffer_retain_t *,OMX_U32)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 }
ProcessorProcess(OMX_BUFFERHEADERTYPE ***,buffer_retain_t *,OMX_U32)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 
ProcessorPreFreeBuffer(OMX_U32,OMX_BUFFERHEADERTYPE *)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 */
GetWorkingRole(void)2181 OMX_STRING ComponentBase::GetWorkingRole(void)
2182 {
2183     return &working_role[0];
2184 }
2185 
GetComponentHandle(void)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  */
SetTypeHeader(OMX_PTR type,OMX_U32 size)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 
CheckTypeHeader(const OMX_PTR type,OMX_U32 size)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