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