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