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