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