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