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