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