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