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