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