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