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