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(¶mPortDefinitionOutput,ports[p->nPortIndex]->GetPortDefinition(),
673 sizeof(paramPortDefinitionOutput));
674 paramPortDefinitionOutput.format.video.nFrameWidth = mMaxFrameWidth;
675 paramPortDefinitionOutput.format.video.nFrameHeight = mMaxFrameHeight;
676 ports[p->nPortIndex]->SetPortDefinition(¶mPortDefinitionOutput, 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