1/*
2 *
3 * Copyright 2012 Samsung Electronics S.LSI Co. LTD
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * @file        Exynos_OMX_Vdec.c
20 * @brief
21 * @author      SeungBeom Kim (sbcrux.kim@samsung.com)
22 *              HyeYeon Chung (hyeon.chung@samsung.com)
23 *              Yunji Kim (yunji.kim@samsung.com)
24 * @version     2.0.0
25 * @history
26 *   2012.02.20 : Create
27 */
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include "Exynos_OMX_Macros.h"
33#include "Exynos_OSAL_Event.h"
34#include "Exynos_OMX_Vdec.h"
35#include "Exynos_OMX_VdecControl.h"
36#include "Exynos_OMX_Basecomponent.h"
37#include "Exynos_OSAL_SharedMemory.h"
38#include "Exynos_OSAL_Thread.h"
39#include "Exynos_OSAL_Semaphore.h"
40#include "Exynos_OSAL_Mutex.h"
41#include "Exynos_OSAL_ETC.h"
42#include "csc.h"
43
44#ifdef USE_ANB
45#include "Exynos_OSAL_Android.h"
46#endif
47
48#undef  EXYNOS_LOG_TAG
49#define EXYNOS_LOG_TAG    "EXYNOS_VIDEO_DEC"
50#define EXYNOS_LOG_OFF
51//#define EXYNOS_TRACE_ON
52#include "Exynos_OSAL_Log.h"
53
54
55int calc_plane(int width, int height)
56{
57    int mbX, mbY;
58
59    mbX = (width + 15)/16;
60    mbY = (height + 15)/16;
61
62    /* Alignment for interlaced processing */
63    mbY = (mbY + 1) / 2 * 2;
64
65    return (mbX * 16) * (mbY * 16);
66}
67
68inline void Exynos_UpdateFrameSize(OMX_COMPONENTTYPE *pOMXComponent)
69{
70    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
71    EXYNOS_OMX_BASEPORT      *exynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX];
72    EXYNOS_OMX_BASEPORT      *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX];
73
74    if ((exynosOutputPort->portDefinition.format.video.nFrameWidth !=
75            exynosInputPort->portDefinition.format.video.nFrameWidth) ||
76        (exynosOutputPort->portDefinition.format.video.nFrameHeight !=
77            exynosInputPort->portDefinition.format.video.nFrameHeight)) {
78        OMX_U32 width = 0, height = 0;
79
80        exynosOutputPort->portDefinition.format.video.nFrameWidth =
81            exynosInputPort->portDefinition.format.video.nFrameWidth;
82        exynosOutputPort->portDefinition.format.video.nFrameHeight =
83            exynosInputPort->portDefinition.format.video.nFrameHeight;
84        width = exynosOutputPort->portDefinition.format.video.nStride =
85            exynosInputPort->portDefinition.format.video.nStride;
86        height = exynosOutputPort->portDefinition.format.video.nSliceHeight =
87            exynosInputPort->portDefinition.format.video.nSliceHeight;
88
89        switch(exynosOutputPort->portDefinition.format.video.eColorFormat) {
90        case OMX_COLOR_FormatYUV420Planar:
91        case OMX_COLOR_FormatYUV420SemiPlanar:
92        case OMX_SEC_COLOR_FormatNV12TPhysicalAddress:
93            if (width && height)
94                exynosOutputPort->portDefinition.nBufferSize = (width * height * 3) / 2;
95            break;
96        case OMX_SEC_COLOR_FormatNV12Tiled:
97            width = exynosOutputPort->portDefinition.format.video.nFrameWidth;
98            height = exynosOutputPort->portDefinition.format.video.nFrameHeight;
99            if (width && height) {
100                int YBufferSize = calc_plane(width, height);
101                int CBufferSize = calc_plane(width, height >> 1);
102                exynosOutputPort->portDefinition.nBufferSize = YBufferSize + CBufferSize;
103            }
104            break;
105        default:
106            if (width && height)
107                exynosOutputPort->portDefinition.nBufferSize = width * height * 2;
108            break;
109        }
110    }
111
112    return;
113}
114
115void Exynos_Free_CodecBuffers(
116    OMX_COMPONENTTYPE   *pOMXComponent,
117    OMX_U32              nPortIndex)
118{
119    OMX_ERRORTYPE                    ret                = OMX_ErrorNone;
120    EXYNOS_OMX_BASECOMPONENT        *pExynosComponent   = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
121    EXYNOS_OMX_VIDEODEC_COMPONENT   *pVideoDec          = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
122    CODEC_DEC_BUFFER               **ppCodecBuffer      = NULL;
123
124    OMX_U32 nPlaneCnt = 0;
125    int i, j;
126
127    FunctionIn();
128
129    if (nPortIndex == INPUT_PORT_INDEX) {
130        ppCodecBuffer = &(pVideoDec->pMFCDecInputBuffer[0]);
131        nPlaneCnt = MFC_INPUT_BUFFER_PLANE;
132    } else {
133        ppCodecBuffer = &(pVideoDec->pMFCDecOutputBuffer[0]);
134        nPlaneCnt = MFC_OUTPUT_BUFFER_PLANE;
135    }
136
137    for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) {
138        if (ppCodecBuffer[i] != NULL) {
139            for (j = 0; j < nPlaneCnt; j++) {
140                if (ppCodecBuffer[i]->pVirAddr[j] != NULL)
141                    Exynos_OSAL_SharedMemory_Free(pVideoDec->hSharedMemory, ppCodecBuffer[i]->pVirAddr[j]);
142            }
143
144            Exynos_OSAL_Free(ppCodecBuffer[i]);
145            ppCodecBuffer[i] = NULL;
146        }
147    }
148
149    FunctionOut();
150}
151
152OMX_ERRORTYPE Exynos_Allocate_CodecBuffers(
153    OMX_COMPONENTTYPE   *pOMXComponent,
154    OMX_U32              nPortIndex,
155    OMX_U32              nBufferCnt,
156    OMX_U32              nPlaneSize[MFC_OUTPUT_BUFFER_PLANE])
157{
158    OMX_ERRORTYPE                    ret                = OMX_ErrorNone;
159    EXYNOS_OMX_BASECOMPONENT        *pExynosComponent   = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
160    EXYNOS_OMX_VIDEODEC_COMPONENT   *pVideoDec          = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
161    MEMORY_TYPE                      eMemoryType        = NORMAL_MEMORY;
162    CODEC_DEC_BUFFER               **ppCodecBuffer      = NULL;
163
164    OMX_U32 nPlaneCnt = 0;
165    int i, j;
166
167    FunctionIn();
168
169    if (pVideoDec->bDRMPlayerMode == OMX_TRUE)
170        eMemoryType = SECURE_MEMORY;
171
172    if (nPortIndex == INPUT_PORT_INDEX) {
173        ppCodecBuffer = &(pVideoDec->pMFCDecInputBuffer[0]);
174        nPlaneCnt = MFC_INPUT_BUFFER_PLANE;
175    } else {
176        ppCodecBuffer = &(pVideoDec->pMFCDecOutputBuffer[0]);
177        nPlaneCnt = MFC_OUTPUT_BUFFER_PLANE;
178    }
179
180    for (i = 0; i < nBufferCnt; i++) {
181        ppCodecBuffer[i] = (CODEC_DEC_BUFFER *)Exynos_OSAL_Malloc(sizeof(CODEC_DEC_BUFFER));
182        if (ppCodecBuffer[i] == NULL) {
183            Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to Alloc codec buffer");
184            ret = OMX_ErrorInsufficientResources;
185            goto EXIT;
186        }
187        Exynos_OSAL_Memset(ppCodecBuffer[i], 0, sizeof(CODEC_DEC_BUFFER));
188
189        for (j = 0; j < nPlaneCnt; j++) {
190            ppCodecBuffer[i]->pVirAddr[j] =
191                (void *)Exynos_OSAL_SharedMemory_Alloc(pVideoDec->hSharedMemory, nPlaneSize[j], eMemoryType);
192            if (ppCodecBuffer[i]->pVirAddr[j] == NULL) {
193                Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to Alloc plane");
194                ret = OMX_ErrorInsufficientResources;
195                goto EXIT;
196            }
197
198            ppCodecBuffer[i]->fd[j] =
199                Exynos_OSAL_SharedMemory_VirtToION(pVideoDec->hSharedMemory, ppCodecBuffer[i]->pVirAddr[j]);
200            ppCodecBuffer[i]->bufferSize[j] = nPlaneSize[j];
201            Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "PORT[%d]: pMFCCodecBuffer[%d]->pVirAddr[%d]: 0x%x", nPortIndex, i, j, ppCodecBuffer[i]->pVirAddr[j]);
202        }
203
204        ppCodecBuffer[i]->dataSize = 0;
205    }
206
207    return OMX_ErrorNone;
208
209EXIT:
210    Exynos_Free_CodecBuffers(pOMXComponent, nPortIndex);
211
212    FunctionOut();
213
214    return ret;
215}
216
217OMX_BOOL Exynos_Check_BufferProcess_State(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nPortIndex)
218{
219    OMX_BOOL ret = OMX_FALSE;
220
221    if ((pExynosComponent->currentState == OMX_StateExecuting) &&
222        (pExynosComponent->pExynosPort[nPortIndex].portState == OMX_StateIdle) &&
223        (pExynosComponent->transientState != EXYNOS_OMX_TransStateExecutingToIdle) &&
224        (pExynosComponent->transientState != EXYNOS_OMX_TransStateIdleToExecuting)) {
225        ret = OMX_TRUE;
226    } else {
227        ret = OMX_FALSE;
228    }
229
230    return ret;
231}
232
233OMX_ERRORTYPE Exynos_ResetAllPortConfig(OMX_COMPONENTTYPE *pOMXComponent)
234{
235    OMX_ERRORTYPE                  ret               = OMX_ErrorNone;
236    EXYNOS_OMX_BASECOMPONENT      *pExynosComponent  = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
237    EXYNOS_OMX_BASEPORT           *pExynosInputPort  = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX];
238    EXYNOS_OMX_BASEPORT           *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX];
239
240    /* Input port */
241    pExynosInputPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH;
242    pExynosInputPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT;
243    pExynosInputPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/
244    pExynosInputPort->portDefinition.format.video.nSliceHeight = 0;
245    pExynosInputPort->portDefinition.nBufferSize = DEFAULT_VIDEO_INPUT_BUFFER_SIZE;
246    pExynosInputPort->portDefinition.format.video.pNativeRender = 0;
247    pExynosInputPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE;
248    pExynosInputPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused;
249    pExynosInputPort->portDefinition.bEnabled = OMX_TRUE;
250    pExynosInputPort->bufferProcessType = BUFFER_SHARE;
251    pExynosInputPort->portWayType = WAY2_PORT;
252
253    /* Output port */
254    pExynosOutputPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH;
255    pExynosOutputPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT;
256    pExynosOutputPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/
257    pExynosOutputPort->portDefinition.format.video.nSliceHeight = 0;
258    pExynosOutputPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE;
259    pExynosOutputPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
260    Exynos_OSAL_Memset(pExynosOutputPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE);
261    Exynos_OSAL_Strcpy(pExynosOutputPort->portDefinition.format.video.cMIMEType, "raw/video");
262    pExynosOutputPort->portDefinition.format.video.pNativeRender = 0;
263    pExynosOutputPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE;
264    pExynosOutputPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
265    pExynosOutputPort->portDefinition.nBufferCountActual = MAX_VIDEO_OUTPUTBUFFER_NUM;
266    pExynosOutputPort->portDefinition.nBufferCountMin = MAX_VIDEO_OUTPUTBUFFER_NUM;
267    pExynosOutputPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE;
268    pExynosOutputPort->portDefinition.bEnabled = OMX_TRUE;
269    pExynosOutputPort->bufferProcessType = BUFFER_COPY | BUFFER_ANBSHARE;
270    pExynosOutputPort->bIsANBEnabled = OMX_FALSE;
271    pExynosOutputPort->portWayType = WAY2_PORT;
272
273    return ret;
274}
275
276OMX_ERRORTYPE Exynos_Input_CodecBufferToData(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_PTR codecBuffer, EXYNOS_OMX_DATA *pData)
277{
278    OMX_ERRORTYPE                  ret = OMX_ErrorNone;
279    EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
280    CODEC_DEC_BUFFER *pInputCodecBuffer = (CODEC_DEC_BUFFER *)codecBuffer;
281
282    pData->buffer.singlePlaneBuffer.dataBuffer = pInputCodecBuffer->pVirAddr[0];
283    pData->buffer.singlePlaneBuffer.fd = pInputCodecBuffer->fd[0];
284    pData->allocSize     = pInputCodecBuffer->bufferSize[0];
285    pData->dataLen       = pInputCodecBuffer->dataSize;
286    pData->usedDataLen   = 0;
287    pData->remainDataLen = pInputCodecBuffer->dataSize;
288
289    pData->nFlags        = 0;
290    pData->timeStamp     = 0;
291    pData->pPrivate      = codecBuffer;
292    pData->bufferHeader  = NULL;
293
294    return ret;
295}
296
297OMX_ERRORTYPE Exynos_Output_CodecBufferToData(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_PTR codecBuffer, EXYNOS_OMX_DATA *pData)
298{
299    OMX_ERRORTYPE                  ret = OMX_ErrorNone;
300    EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
301    CODEC_DEC_BUFFER *pCodecBuffer = (CODEC_DEC_BUFFER *)codecBuffer;
302    int i = 0;
303
304    pData->allocSize     = 0;
305    pData->dataLen       = 0;
306    pData->usedDataLen   = 0;
307    pData->remainDataLen = 0;
308
309    pData->nFlags        = 0;
310    pData->timeStamp     = 0;
311    pData->pPrivate      = codecBuffer;
312    pData->bufferHeader  = NULL;
313
314    for (i = 0; i < MAX_BUFFER_PLANE; i++) {
315        pData->buffer.multiPlaneBuffer.dataBuffer[i] = pCodecBuffer->pVirAddr[i];
316        pData->buffer.multiPlaneBuffer.fd[i] = pCodecBuffer->fd[i];
317        pData->allocSize += pCodecBuffer->bufferSize[i];
318    }
319
320    return ret;
321}
322
323void Exynos_Wait_ProcessPause(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nPortIndex)
324{
325    EXYNOS_OMX_BASEPORT *exynosOMXInputPort  = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX];
326    EXYNOS_OMX_BASEPORT *exynosOMXOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX];
327    EXYNOS_OMX_BASEPORT *exynosOMXPort = NULL;
328
329    FunctionIn();
330
331    exynosOMXPort = &pExynosComponent->pExynosPort[nPortIndex];
332
333    if (((pExynosComponent->currentState == OMX_StatePause) ||
334        (pExynosComponent->currentState == OMX_StateIdle) ||
335        (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle) ||
336        (pExynosComponent->transientState == EXYNOS_OMX_TransStateExecutingToIdle)) &&
337        (pExynosComponent->transientState != EXYNOS_OMX_TransStateIdleToLoaded) &&
338        (!CHECK_PORT_BEING_FLUSHED(exynosOMXPort))) {
339        Exynos_OSAL_SignalWait(pExynosComponent->pExynosPort[nPortIndex].pauseEvent, DEF_MAX_WAIT_TIME);
340        Exynos_OSAL_SignalReset(pExynosComponent->pExynosPort[nPortIndex].pauseEvent);
341    }
342
343    FunctionOut();
344
345    return;
346}
347
348OMX_BOOL Exynos_CSC_OutputData(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *dstOutputData)
349{
350    OMX_BOOL                   ret = OMX_FALSE;
351    EXYNOS_OMX_BASECOMPONENT  *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
352    EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
353    EXYNOS_OMX_BASEPORT       *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX];
354    EXYNOS_OMX_DATABUFFER     *outputUseBuffer = &exynosOutputPort->way.port2WayDataBuffer.outputDataBuffer;
355    OMX_U32                    copySize = 0;
356    DECODE_CODEC_EXTRA_BUFFERINFO *pBufferInfo = NULL;
357
358    FunctionIn();
359
360    OMX_U32 width = 0, height = 0;
361    int imageSize = 0;
362    OMX_COLOR_FORMATTYPE colorFormat;
363
364    void *pOutputBuf = (void *)outputUseBuffer->bufferHeader->pBuffer;
365    void *pSrcBuf[MAX_BUFFER_PLANE] = {NULL, };
366    void *pYUVBuf[MAX_BUFFER_PLANE] = {NULL, };
367
368    CSC_ERRORCODE cscRet = CSC_ErrorNone;
369    CSC_METHOD csc_method = CSC_METHOD_SW;
370    unsigned int cacheable = 1;
371
372    pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)dstOutputData->extInfo;
373
374    width = pBufferInfo->imageWidth;
375    height = pBufferInfo->imageHeight;
376    imageSize = width * height;
377    colorFormat = pBufferInfo->ColorFormat;
378
379    pSrcBuf[0] = dstOutputData->buffer.multiPlaneBuffer.dataBuffer[0];
380    pSrcBuf[1] = dstOutputData->buffer.multiPlaneBuffer.dataBuffer[1];
381    pSrcBuf[2] = dstOutputData->buffer.multiPlaneBuffer.dataBuffer[2];
382
383    pYUVBuf[0]  = (unsigned char *)pOutputBuf;
384    pYUVBuf[1]  = (unsigned char *)pOutputBuf + imageSize;
385    pYUVBuf[2]  = (unsigned char *)pOutputBuf + imageSize + imageSize / 4;
386
387    csc_get_method(pVideoDec->csc_handle, &csc_method);
388    if (csc_method == CSC_METHOD_HW) {
389        pSrcBuf[0] = dstOutputData->buffer.multiPlaneBuffer.fd[0];
390        pSrcBuf[1] = dstOutputData->buffer.multiPlaneBuffer.fd[1];
391        pSrcBuf[2] = dstOutputData->buffer.multiPlaneBuffer.fd[2];
392    }
393
394#ifdef USE_ANB
395    if ((exynosOutputPort->bIsANBEnabled == OMX_TRUE) ||
396        (exynosOutputPort->bStoreMetaData == OMX_TRUE)) {
397        ExynosVideoPlane planes[MAX_BUFFER_PLANE];
398        OMX_U32 stride;
399        if (exynosOutputPort->bIsANBEnabled == OMX_TRUE) {
400            Exynos_OSAL_LockANB(pOutputBuf, width, height, exynosOutputPort->portDefinition.format.video.eColorFormat, &stride, planes);
401        } else if (exynosOutputPort->bStoreMetaData == OMX_TRUE) {
402            Exynos_OSAL_LockMetaData(pOutputBuf, width, height, exynosOutputPort->portDefinition.format.video.eColorFormat, &stride, planes);
403        }
404        width = stride;
405        outputUseBuffer->dataLen = sizeof(void *);
406
407        if (csc_method == CSC_METHOD_SW) {
408            pYUVBuf[0]  = (unsigned char *)planes[0].addr;
409            pYUVBuf[1]  = (unsigned char *)planes[1].addr;
410            pYUVBuf[2]  = (unsigned char *)planes[2].addr;
411        } else {
412            pYUVBuf[0]  = (unsigned char *)planes[0].fd;
413            pYUVBuf[1]  = (unsigned char *)planes[1].fd;
414            pYUVBuf[2]  = (unsigned char *)planes[2].fd;
415        }
416    }
417#endif
418    if ((exynosOutputPort->bIsANBEnabled == OMX_FALSE) &&
419        (exynosOutputPort->bStoreMetaData == OMX_FALSE) &&
420        (csc_method == CSC_METHOD_HW)) {
421        pYUVBuf[0] = Exynos_OSAL_SharedMemory_VirtToION(pVideoDec->hSharedMemory, pOutputBuf);
422        pYUVBuf[1] = NULL;
423        pYUVBuf[2] = NULL;
424    }
425
426    if (pVideoDec->csc_set_format == OMX_FALSE) {
427        csc_set_src_format(
428            pVideoDec->csc_handle,  /* handle */
429            width,            /* width */
430            height,           /* height */
431            0,                /* crop_left */
432            0,                /* crop_right */
433            width,            /* crop_width */
434            height,           /* crop_height */
435            omx_2_hal_pixel_format(colorFormat), /* color_format */
436            cacheable);             /* cacheable */
437        csc_set_dst_format(
438            pVideoDec->csc_handle,  /* handle */
439            width,           /* width */
440            height,           /* height */
441            0,                /* crop_left */
442            0,                /* crop_right */
443            width,           /* crop_width */
444            height,           /* crop_height */
445            omx_2_hal_pixel_format(exynosOutputPort->portDefinition.format.video.eColorFormat), /* color_format */
446            cacheable);             /* cacheable */
447        pVideoDec->csc_set_format = OMX_TRUE;
448    }
449    csc_set_src_buffer(
450        pVideoDec->csc_handle,  /* handle */
451        pSrcBuf);            /* YUV Addr or FD */
452    csc_set_dst_buffer(
453        pVideoDec->csc_handle,  /* handle */
454        pYUVBuf);            /* YUV Addr or FD */
455    cscRet = csc_convert(pVideoDec->csc_handle);
456    if (cscRet != CSC_ErrorNone)
457        ret = OMX_FALSE;
458    else
459        ret = OMX_TRUE;
460
461#ifdef USE_ANB
462    if (exynosOutputPort->bIsANBEnabled == OMX_TRUE) {
463        Exynos_OSAL_UnlockANB(pOutputBuf);
464    } else if (exynosOutputPort->bStoreMetaData == OMX_TRUE) {
465        Exynos_OSAL_UnlockMetaData(pOutputBuf);
466    }
467#endif
468
469EXIT:
470    FunctionOut();
471
472    return ret;
473}
474
475OMX_BOOL Exynos_Preprocessor_InputData(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *srcInputData)
476{
477    OMX_BOOL               ret = OMX_FALSE;
478    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
479    EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
480    EXYNOS_OMX_BASEPORT      *exynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX];
481    EXYNOS_OMX_DATABUFFER    *inputUseBuffer = &exynosInputPort->way.port2WayDataBuffer.inputDataBuffer;
482    OMX_U32                copySize = 0;
483    OMX_BYTE               checkInputStream = NULL;
484    OMX_U32                checkInputStreamLen = 0;
485
486    FunctionIn();
487
488    if ((exynosInputPort->bufferProcessType & BUFFER_COPY) == BUFFER_COPY) {
489        if ((srcInputData->buffer.singlePlaneBuffer.dataBuffer == NULL) ||
490            (srcInputData->pPrivate == NULL)) {
491            ret = OMX_FALSE;
492            goto EXIT;
493        }
494    }
495
496    if (inputUseBuffer->dataValid == OMX_TRUE) {
497        if (exynosInputPort->bufferProcessType == BUFFER_SHARE) {
498            Exynos_Shared_BufferToData(inputUseBuffer, srcInputData, ONE_PLANE);
499
500            if (pVideoDec->bDRMPlayerMode == OMX_TRUE) {
501                OMX_PTR dataBuffer = NULL;
502
503                dataBuffer = Exynos_OSAL_SharedMemory_IONToVirt(pVideoDec->hSharedMemory,
504                                                            srcInputData->buffer.singlePlaneBuffer.dataBuffer);
505                if (dataBuffer == NULL) {
506                    ret = OMX_FALSE;
507                    goto EXIT;
508                }
509
510                srcInputData->buffer.singlePlaneBuffer.dataBuffer = dataBuffer;
511            }
512
513            /* reset dataBuffer */
514            Exynos_ResetDataBuffer(inputUseBuffer);
515        } else if ((exynosInputPort->bufferProcessType & BUFFER_COPY) == BUFFER_COPY) {
516            checkInputStream = inputUseBuffer->bufferHeader->pBuffer + inputUseBuffer->usedDataLen;
517            checkInputStreamLen = inputUseBuffer->remainDataLen;
518
519            pExynosComponent->bUseFlagEOF = OMX_TRUE;
520
521            copySize = checkInputStreamLen;
522            Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "exynos_checkInputFrame : OMX_TRUE");
523
524            if (((srcInputData->allocSize) - (srcInputData->dataLen)) >= copySize) {
525                if (copySize > 0) {
526                    Exynos_OSAL_Memcpy(srcInputData->buffer.singlePlaneBuffer.dataBuffer + srcInputData->dataLen,
527                                       checkInputStream, copySize);
528                }
529
530                inputUseBuffer->dataLen -= copySize;
531                inputUseBuffer->remainDataLen -= copySize;
532                inputUseBuffer->usedDataLen += copySize;
533
534                srcInputData->dataLen += copySize;
535                srcInputData->remainDataLen += copySize;
536
537                srcInputData->timeStamp = inputUseBuffer->timeStamp;
538                srcInputData->nFlags = inputUseBuffer->nFlags;
539                srcInputData->bufferHeader = inputUseBuffer->bufferHeader;
540            } else {
541                Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "input codec buffer is smaller than decoded input data size Out Length");
542                pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent,
543                                                        pExynosComponent->callbackData,
544                                                        OMX_EventError, OMX_ErrorUndefined, 0, NULL);
545                ret = OMX_FALSE;
546            }
547
548            Exynos_InputBufferReturn(pOMXComponent, inputUseBuffer);
549        }
550
551        if ((srcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) {
552            Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "bSaveFlagEOS : OMX_TRUE");
553            pExynosComponent->bSaveFlagEOS = OMX_TRUE;
554            if (srcInputData->dataLen != 0)
555                pExynosComponent->bBehaviorEOS = OMX_TRUE;
556        }
557
558        if (pExynosComponent->checkTimeStamp.needSetStartTimeStamp == OMX_TRUE) {
559            pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_TRUE;
560            pExynosComponent->checkTimeStamp.startTimeStamp = srcInputData->timeStamp;
561            pExynosComponent->checkTimeStamp.nStartFlags = srcInputData->nFlags;
562            pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_FALSE;
563            Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "first frame timestamp after seeking %lld us (%.2f secs)",
564                            srcInputData->timeStamp, srcInputData->timeStamp / 1E6);
565        }
566
567        ret = OMX_TRUE;
568    }
569
570EXIT:
571
572    FunctionOut();
573
574    return ret;
575}
576
577OMX_BOOL Exynos_Postprocess_OutputData(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *dstOutputData)
578{
579    OMX_BOOL                   ret = OMX_FALSE;
580    EXYNOS_OMX_BASECOMPONENT  *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
581    EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
582    EXYNOS_OMX_BASEPORT       *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX];
583    EXYNOS_OMX_DATABUFFER     *outputUseBuffer = &exynosOutputPort->way.port2WayDataBuffer.outputDataBuffer;
584    OMX_U32                    copySize = 0;
585    DECODE_CODEC_EXTRA_BUFFERINFO *pBufferInfo = NULL;
586
587    FunctionIn();
588
589    if (exynosOutputPort->bufferProcessType == BUFFER_SHARE) {
590        if ((exynosOutputPort->bIsANBEnabled == OMX_FALSE) &&
591            (exynosOutputPort->bStoreMetaData == OMX_FALSE)) {
592            if (Exynos_Shared_DataToBuffer(dstOutputData, outputUseBuffer) == OMX_ErrorNone)
593                outputUseBuffer->dataValid = OMX_TRUE;
594        } else {
595            if (Exynos_Shared_DataToANBBuffer(dstOutputData, outputUseBuffer, exynosOutputPort) == OMX_ErrorNone) {
596                outputUseBuffer->dataValid = OMX_TRUE;
597            } else {
598                ret = OMX_FALSE;
599                goto EXIT;
600            }
601        }
602    }
603
604    if (outputUseBuffer->dataValid == OMX_TRUE) {
605        Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "out timestamp after seeking %lld us (%.2f secs)",
606            dstOutputData->timeStamp, dstOutputData->timeStamp / 1E6);
607        if ((pExynosComponent->checkTimeStamp.needCheckStartTimeStamp == OMX_TRUE) &&
608            ((dstOutputData->nFlags & OMX_BUFFERFLAG_EOS) != OMX_BUFFERFLAG_EOS)) {
609            if ((pExynosComponent->checkTimeStamp.startTimeStamp == dstOutputData->timeStamp) &&
610                (pExynosComponent->checkTimeStamp.nStartFlags == dstOutputData->nFlags)){
611                pExynosComponent->checkTimeStamp.startTimeStamp = -19761123;
612                pExynosComponent->checkTimeStamp.nStartFlags = 0x0;
613                pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_FALSE;
614                pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_FALSE;
615            } else {
616                Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "drop frame after seeking", pExynosComponent);
617                if (exynosOutputPort->bufferProcessType == BUFFER_SHARE)
618                    Exynos_OMX_FillThisBuffer(pOMXComponent, outputUseBuffer->bufferHeader);
619                ret = OMX_TRUE;
620                goto EXIT;
621            }
622        } else if ((pExynosComponent->checkTimeStamp.needSetStartTimeStamp == OMX_TRUE)) {
623            ret = OMX_TRUE;
624            Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "not set check timestame after seeking");
625            goto EXIT;
626        }
627
628        if ((exynosOutputPort->bufferProcessType & BUFFER_COPY) == BUFFER_COPY) {
629            OMX_U32 width = 0, height = 0;
630            int imageSize = 0;
631            void *pOutputBuf = (void *)outputUseBuffer->bufferHeader->pBuffer;
632
633            pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)dstOutputData->extInfo;
634
635            width = pBufferInfo->imageWidth;
636            height = pBufferInfo->imageHeight;
637            imageSize = width * height;
638
639            if ((dstOutputData->remainDataLen <= (outputUseBuffer->allocSize - outputUseBuffer->dataLen)) &&
640                (!CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) {
641                copySize = dstOutputData->remainDataLen;
642                Exynos_OSAL_Log(EXYNOS_LOG_TRACE,"copySize: %d", copySize);
643
644                outputUseBuffer->dataLen += copySize;
645                outputUseBuffer->remainDataLen += copySize;
646                outputUseBuffer->nFlags = dstOutputData->nFlags;
647                outputUseBuffer->timeStamp = dstOutputData->timeStamp;
648
649                if (outputUseBuffer->remainDataLen > 0) {
650                    ret = Exynos_CSC_OutputData(pOMXComponent, dstOutputData);
651                } else {
652                    ret = OMX_TRUE;
653                }
654
655                if (ret == OMX_TRUE) {
656                    if ((outputUseBuffer->remainDataLen > 0) ||
657                        ((outputUseBuffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) ||
658                        (CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) {
659                        Exynos_OutputBufferReturn(pOMXComponent, outputUseBuffer);
660                    }
661                } else {
662                    Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "csc_convert Error");
663                    pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent,
664                                                            pExynosComponent->callbackData,
665                                                            OMX_EventError, OMX_ErrorUndefined, 0, NULL);
666                    ret = OMX_FALSE;
667                }
668            } else if (CHECK_PORT_BEING_FLUSHED(exynosOutputPort)) {
669                outputUseBuffer->dataLen = 0;
670                outputUseBuffer->remainDataLen = 0;
671                outputUseBuffer->nFlags = dstOutputData->nFlags;
672                outputUseBuffer->timeStamp = dstOutputData->timeStamp;
673                Exynos_OutputBufferReturn(pOMXComponent, outputUseBuffer);
674            } else {
675                Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "output buffer is smaller than decoded data size Out Length");
676                pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent,
677                                                        pExynosComponent->callbackData,
678                                                        OMX_EventError, OMX_ErrorUndefined, 0, NULL);
679                ret = OMX_FALSE;
680            }
681        } else if (exynosOutputPort->bufferProcessType == BUFFER_SHARE) {
682            if ((outputUseBuffer->remainDataLen > 0) ||
683                ((outputUseBuffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) ||
684                (CHECK_PORT_BEING_FLUSHED(exynosOutputPort)))
685                Exynos_OutputBufferReturn(pOMXComponent, outputUseBuffer);
686        }
687    } else {
688        ret = OMX_FALSE;
689    }
690
691EXIT:
692    FunctionOut();
693
694    return ret;
695}
696
697OMX_ERRORTYPE Exynos_OMX_SrcInputBufferProcess(OMX_HANDLETYPE hComponent)
698{
699    OMX_ERRORTYPE          ret = OMX_ErrorNone;
700    OMX_COMPONENTTYPE     *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
701    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
702    EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
703    EXYNOS_OMX_BASEPORT      *exynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX];
704    EXYNOS_OMX_BASEPORT      *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX];
705    EXYNOS_OMX_DATABUFFER    *srcInputUseBuffer = &exynosInputPort->way.port2WayDataBuffer.inputDataBuffer;
706    EXYNOS_OMX_DATA          *pSrcInputData = &exynosInputPort->processData;
707    OMX_BOOL               bCheckInputData = OMX_FALSE;
708    OMX_BOOL               bValidCodecData = OMX_FALSE;
709
710    FunctionIn();
711
712    while (!pVideoDec->bExitBufferProcessThread) {
713        Exynos_OSAL_SleepMillisec(0);
714        Exynos_Wait_ProcessPause(pExynosComponent, INPUT_PORT_INDEX);
715
716        while ((Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) &&
717               (!pVideoDec->bExitBufferProcessThread)) {
718            Exynos_OSAL_SleepMillisec(0);
719
720            if ((CHECK_PORT_BEING_FLUSHED(exynosInputPort)) ||
721                ((exynosOutputPort->exceptionFlag != GENERAL_STATE) && (ret == OMX_ErrorInputDataDecodeYet)))
722                break;
723            if (exynosInputPort->portState != OMX_StateIdle)
724                break;
725
726            Exynos_OSAL_MutexLock(srcInputUseBuffer->bufferMutex);
727            if (ret != OMX_ErrorInputDataDecodeYet) {
728                if ((exynosInputPort->bufferProcessType & BUFFER_COPY) == BUFFER_COPY) {
729                    OMX_PTR codecBuffer;
730                    if ((pSrcInputData->buffer.singlePlaneBuffer.dataBuffer == NULL) || (pSrcInputData->pPrivate == NULL)) {
731                        Exynos_CodecBufferDeQueue(pExynosComponent, INPUT_PORT_INDEX, &codecBuffer);
732                        if (codecBuffer != NULL) {
733                            Exynos_Input_CodecBufferToData(pExynosComponent, codecBuffer, pSrcInputData);
734                        }
735                        Exynos_OSAL_MutexUnlock(srcInputUseBuffer->bufferMutex);
736                        break;
737                    }
738                }
739
740                if (srcInputUseBuffer->dataValid == OMX_TRUE) {
741                    bCheckInputData = Exynos_Preprocessor_InputData(pOMXComponent, pSrcInputData);
742                } else {
743                    bCheckInputData = OMX_FALSE;
744                }
745
746                if ((bCheckInputData == OMX_FALSE) &&
747                    (!CHECK_PORT_BEING_FLUSHED(exynosInputPort))) {
748                    ret = Exynos_InputBufferGetQueue(pExynosComponent);
749                    Exynos_OSAL_MutexUnlock(srcInputUseBuffer->bufferMutex);
750                    break;
751                }
752
753                if (CHECK_PORT_BEING_FLUSHED(exynosInputPort)) {
754                    Exynos_OSAL_MutexUnlock(srcInputUseBuffer->bufferMutex);
755                    break;
756                }
757            }
758
759            ret = pVideoDec->exynos_codec_srcInputProcess(pOMXComponent, pSrcInputData);
760            if (ret != OMX_ErrorInputDataDecodeYet) {
761                Exynos_ResetCodecData(pSrcInputData);
762            }
763            Exynos_OSAL_MutexUnlock(srcInputUseBuffer->bufferMutex);
764            if (ret == OMX_ErrorCodecInit)
765                pVideoDec->bExitBufferProcessThread = OMX_TRUE;
766        }
767    }
768
769EXIT:
770
771    FunctionOut();
772
773    return ret;
774}
775
776OMX_ERRORTYPE Exynos_OMX_SrcOutputBufferProcess(OMX_HANDLETYPE hComponent)
777{
778    OMX_ERRORTYPE          ret = OMX_ErrorNone;
779    OMX_COMPONENTTYPE     *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
780    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
781    EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
782    EXYNOS_OMX_BASEPORT      *exynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX];
783    EXYNOS_OMX_DATABUFFER    *srcOutputUseBuffer = &exynosInputPort->way.port2WayDataBuffer.outputDataBuffer;
784    EXYNOS_OMX_DATA           srcOutputData;
785
786    FunctionIn();
787
788    while (!pVideoDec->bExitBufferProcessThread) {
789        Exynos_OSAL_SleepMillisec(0);
790
791        while (!pVideoDec->bExitBufferProcessThread) {
792            if ((exynosInputPort->bufferProcessType & BUFFER_COPY) == BUFFER_COPY) {
793                if (Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX) == OMX_FALSE)
794                    break;
795            }
796            Exynos_OSAL_SleepMillisec(0);
797
798            if (CHECK_PORT_BEING_FLUSHED(exynosInputPort))
799                break;
800
801            Exynos_OSAL_MutexLock(srcOutputUseBuffer->bufferMutex);
802            ret = pVideoDec->exynos_codec_srcOutputProcess(pOMXComponent, &srcOutputData);
803
804            if (ret == OMX_ErrorNone) {
805                if ((exynosInputPort->bufferProcessType & BUFFER_COPY) == BUFFER_COPY) {
806                    OMX_PTR codecBuffer;
807                    codecBuffer = srcOutputData.pPrivate;
808                    if (codecBuffer != NULL)
809                        Exynos_CodecBufferEnQueue(pExynosComponent, INPUT_PORT_INDEX, codecBuffer);
810                }
811                if (exynosInputPort->bufferProcessType == BUFFER_SHARE) {
812                    Exynos_Shared_DataToBuffer(&srcOutputData, srcOutputUseBuffer);
813                    Exynos_InputBufferReturn(pOMXComponent, srcOutputUseBuffer);
814                }
815                Exynos_ResetCodecData(&srcOutputData);
816            }
817            Exynos_OSAL_MutexUnlock(srcOutputUseBuffer->bufferMutex);
818        }
819    }
820
821EXIT:
822
823    FunctionOut();
824
825    return ret;
826}
827
828OMX_ERRORTYPE Exynos_OMX_DstInputBufferProcess(OMX_HANDLETYPE hComponent)
829{
830    OMX_ERRORTYPE          ret = OMX_ErrorNone;
831    OMX_COMPONENTTYPE     *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
832    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
833    EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
834    EXYNOS_OMX_BASEPORT      *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX];
835    EXYNOS_OMX_DATABUFFER    *dstInputUseBuffer = &exynosOutputPort->way.port2WayDataBuffer.inputDataBuffer;
836    EXYNOS_OMX_DATA           dstInputData;
837
838    FunctionIn();
839
840    while (!pVideoDec->bExitBufferProcessThread) {
841        Exynos_OSAL_SleepMillisec(0);
842
843        while ((Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) &&
844               (!pVideoDec->bExitBufferProcessThread)) {
845            Exynos_OSAL_SleepMillisec(0);
846
847            if ((CHECK_PORT_BEING_FLUSHED(exynosOutputPort)) ||
848                (!CHECK_PORT_POPULATED(exynosOutputPort)) ||
849                (exynosOutputPort->exceptionFlag != GENERAL_STATE))
850                break;
851            if (exynosOutputPort->portState != OMX_StateIdle)
852                break;
853
854            Exynos_OSAL_MutexLock(dstInputUseBuffer->bufferMutex);
855            if (ret != OMX_ErrorOutputBufferUseYet) {
856                if ((exynosOutputPort->bufferProcessType & BUFFER_COPY) == BUFFER_COPY) {
857                    OMX_PTR codecBuffer;
858                    ret = Exynos_CodecBufferDeQueue(pExynosComponent, OUTPUT_PORT_INDEX, &codecBuffer);
859                    if (ret != OMX_ErrorNone) {
860                        Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex);
861                        break;
862                    }
863                    Exynos_Output_CodecBufferToData(pExynosComponent, codecBuffer, &dstInputData);
864                }
865
866                if (exynosOutputPort->bufferProcessType == BUFFER_SHARE) {
867                    if ((dstInputUseBuffer->dataValid != OMX_TRUE) &&
868                        (!CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) {
869                        ret = Exynos_OutputBufferGetQueue(pExynosComponent);
870                        if (ret != OMX_ErrorNone) {
871                            Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex);
872                            break;
873                        }
874                        if ((exynosOutputPort->bIsANBEnabled == OMX_FALSE) &&
875                            (exynosOutputPort->bStoreMetaData == OMX_FALSE)) {
876                            Exynos_Shared_BufferToData(dstInputUseBuffer, &dstInputData, TWO_PLANE);
877                        } else {
878                            ret = Exynos_Shared_ANBBufferToData(dstInputUseBuffer, &dstInputData, exynosOutputPort, TWO_PLANE);
879                            if (ret != OMX_ErrorNone) {
880                                dstInputUseBuffer->dataValid = OMX_FALSE;
881                                Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex);
882                                break;
883                            }
884                        }
885                        Exynos_OSAL_RefANB_Increase(pVideoDec->hRefHandle, dstInputData.bufferHeader->pBuffer);
886                        Exynos_ResetDataBuffer(dstInputUseBuffer);
887                    }
888                }
889
890                if (CHECK_PORT_BEING_FLUSHED(exynosOutputPort)) {
891                    Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex);
892                    break;
893                }
894            }
895
896            ret = pVideoDec->exynos_codec_dstInputProcess(pOMXComponent, &dstInputData);
897            if (ret != OMX_ErrorOutputBufferUseYet) {
898                Exynos_ResetCodecData(&dstInputData);
899            }
900            Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex);
901        }
902    }
903
904EXIT:
905
906    FunctionOut();
907
908    return ret;
909}
910
911OMX_ERRORTYPE Exynos_OMX_DstOutputBufferProcess(OMX_HANDLETYPE hComponent)
912{
913    OMX_ERRORTYPE          ret = OMX_ErrorNone;
914    OMX_COMPONENTTYPE     *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
915    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
916    EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
917    EXYNOS_OMX_BASEPORT      *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX];
918    EXYNOS_OMX_DATABUFFER    *dstOutputUseBuffer = &exynosOutputPort->way.port2WayDataBuffer.outputDataBuffer;
919    EXYNOS_OMX_DATA          *pDstOutputData = &exynosOutputPort->processData;
920
921    FunctionIn();
922
923    while (!pVideoDec->bExitBufferProcessThread) {
924        Exynos_OSAL_SleepMillisec(0);
925        Exynos_Wait_ProcessPause(pExynosComponent, OUTPUT_PORT_INDEX);
926
927        while ((Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) &&
928               (!pVideoDec->bExitBufferProcessThread)) {
929            Exynos_OSAL_SleepMillisec(0);
930
931            if (CHECK_PORT_BEING_FLUSHED(exynosOutputPort))
932                break;
933
934            Exynos_OSAL_MutexLock(dstOutputUseBuffer->bufferMutex);
935            if ((exynosOutputPort->bufferProcessType & BUFFER_COPY) == BUFFER_COPY) {
936                if ((dstOutputUseBuffer->dataValid != OMX_TRUE) &&
937                    (!CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) {
938                    ret = Exynos_OutputBufferGetQueue(pExynosComponent);
939                    if (ret != OMX_ErrorNone) {
940                        Exynos_OSAL_MutexUnlock(dstOutputUseBuffer->bufferMutex);
941                        break;
942                    }
943                }
944            }
945
946            if ((dstOutputUseBuffer->dataValid == OMX_TRUE) ||
947                (exynosOutputPort->bufferProcessType == BUFFER_SHARE))
948                ret = pVideoDec->exynos_codec_dstOutputProcess(pOMXComponent, pDstOutputData);
949
950            if (((ret == OMX_ErrorNone) && (dstOutputUseBuffer->dataValid == OMX_TRUE)) ||
951                (exynosOutputPort->bufferProcessType == BUFFER_SHARE)) {
952                if (exynosOutputPort->bufferProcessType == BUFFER_SHARE) {
953                    DECODE_CODEC_EXTRA_BUFFERINFO *pBufferInfo = NULL;
954                    int i;
955                    pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)pDstOutputData->extInfo;
956                    for (i = 0; i < VIDEO_BUFFER_MAX_NUM; i++) {
957                        if (pBufferInfo->PDSB.dpbFD[i].fd > -1) {
958                            Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "decRefCnt-FD:%d", pBufferInfo->PDSB.dpbFD[i].fd);
959                            Exynos_OSAL_RefANB_Decrease(pVideoDec->hRefHandle, pBufferInfo->PDSB.dpbFD[i].fd);
960                        } else {
961                            break;
962                        }
963                    }
964                }
965                Exynos_Postprocess_OutputData(pOMXComponent, pDstOutputData);
966            }
967
968            if ((exynosOutputPort->bufferProcessType & BUFFER_COPY) == BUFFER_COPY) {
969                OMX_PTR codecBuffer = pDstOutputData->pPrivate;
970                if (codecBuffer != NULL) {
971                    Exynos_CodecBufferEnQueue(pExynosComponent, OUTPUT_PORT_INDEX, codecBuffer);
972                    pDstOutputData->pPrivate = NULL;
973                }
974            }
975
976            /* reset outputData */
977            Exynos_ResetCodecData(pDstOutputData);
978            Exynos_OSAL_MutexUnlock(dstOutputUseBuffer->bufferMutex);
979        }
980    }
981
982EXIT:
983
984    FunctionOut();
985
986    return ret;
987}
988
989static OMX_ERRORTYPE Exynos_OMX_SrcInputProcessThread(OMX_PTR threadData)
990{
991    OMX_ERRORTYPE          ret = OMX_ErrorNone;
992    OMX_COMPONENTTYPE     *pOMXComponent = NULL;
993    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
994    EXYNOS_OMX_MESSAGE       *message = NULL;
995
996    FunctionIn();
997
998    if (threadData == NULL) {
999        ret = OMX_ErrorBadParameter;
1000        goto EXIT;
1001    }
1002    pOMXComponent = (OMX_COMPONENTTYPE *)threadData;
1003    ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE));
1004    if (ret != OMX_ErrorNone) {
1005        goto EXIT;
1006    }
1007    pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
1008    Exynos_OMX_SrcInputBufferProcess(pOMXComponent);
1009
1010    Exynos_OSAL_ThreadExit(NULL);
1011
1012EXIT:
1013    FunctionOut();
1014
1015    return ret;
1016}
1017
1018static OMX_ERRORTYPE Exynos_OMX_SrcOutputProcessThread(OMX_PTR threadData)
1019{
1020    OMX_ERRORTYPE          ret = OMX_ErrorNone;
1021    OMX_COMPONENTTYPE     *pOMXComponent = NULL;
1022    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
1023    EXYNOS_OMX_MESSAGE       *message = NULL;
1024
1025    FunctionIn();
1026
1027    if (threadData == NULL) {
1028        ret = OMX_ErrorBadParameter;
1029        goto EXIT;
1030    }
1031    pOMXComponent = (OMX_COMPONENTTYPE *)threadData;
1032    ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE));
1033    if (ret != OMX_ErrorNone) {
1034        goto EXIT;
1035    }
1036    pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
1037    Exynos_OMX_SrcOutputBufferProcess(pOMXComponent);
1038
1039    Exynos_OSAL_ThreadExit(NULL);
1040
1041EXIT:
1042    FunctionOut();
1043
1044    return ret;
1045}
1046
1047static OMX_ERRORTYPE Exynos_OMX_DstInputProcessThread(OMX_PTR threadData)
1048{
1049    OMX_ERRORTYPE          ret = OMX_ErrorNone;
1050    OMX_COMPONENTTYPE     *pOMXComponent = NULL;
1051    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
1052    EXYNOS_OMX_MESSAGE       *message = NULL;
1053
1054    FunctionIn();
1055
1056    if (threadData == NULL) {
1057        ret = OMX_ErrorBadParameter;
1058        goto EXIT;
1059    }
1060    pOMXComponent = (OMX_COMPONENTTYPE *)threadData;
1061    ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE));
1062    if (ret != OMX_ErrorNone) {
1063        goto EXIT;
1064    }
1065    pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
1066    Exynos_OMX_DstInputBufferProcess(pOMXComponent);
1067
1068    Exynos_OSAL_ThreadExit(NULL);
1069
1070EXIT:
1071    FunctionOut();
1072
1073    return ret;
1074}
1075
1076static OMX_ERRORTYPE Exynos_OMX_DstOutputProcessThread(OMX_PTR threadData)
1077{
1078    OMX_ERRORTYPE          ret = OMX_ErrorNone;
1079    OMX_COMPONENTTYPE     *pOMXComponent = NULL;
1080    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
1081    EXYNOS_OMX_MESSAGE       *message = NULL;
1082
1083    FunctionIn();
1084
1085    if (threadData == NULL) {
1086        ret = OMX_ErrorBadParameter;
1087        goto EXIT;
1088    }
1089    pOMXComponent = (OMX_COMPONENTTYPE *)threadData;
1090    ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE));
1091    if (ret != OMX_ErrorNone) {
1092        goto EXIT;
1093    }
1094    pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
1095    Exynos_OMX_DstOutputBufferProcess(pOMXComponent);
1096
1097    Exynos_OSAL_ThreadExit(NULL);
1098
1099EXIT:
1100    FunctionOut();
1101
1102    return ret;
1103}
1104
1105OMX_ERRORTYPE Exynos_OMX_BufferProcess_Create(OMX_HANDLETYPE hComponent)
1106{
1107    OMX_ERRORTYPE          ret = OMX_ErrorNone;
1108    OMX_COMPONENTTYPE     *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
1109    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
1110    EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
1111
1112    FunctionIn();
1113
1114    pVideoDec->bExitBufferProcessThread = OMX_FALSE;
1115
1116    ret = Exynos_OSAL_ThreadCreate(&pVideoDec->hDstOutputThread,
1117                 Exynos_OMX_DstOutputProcessThread,
1118                 pOMXComponent);
1119    if (ret == OMX_ErrorNone)
1120        ret = Exynos_OSAL_ThreadCreate(&pVideoDec->hSrcOutputThread,
1121                     Exynos_OMX_SrcOutputProcessThread,
1122                     pOMXComponent);
1123    if (ret == OMX_ErrorNone)
1124        ret = Exynos_OSAL_ThreadCreate(&pVideoDec->hDstInputThread,
1125                     Exynos_OMX_DstInputProcessThread,
1126                     pOMXComponent);
1127    if (ret == OMX_ErrorNone)
1128        ret = Exynos_OSAL_ThreadCreate(&pVideoDec->hSrcInputThread,
1129                     Exynos_OMX_SrcInputProcessThread,
1130                     pOMXComponent);
1131
1132EXIT:
1133    FunctionOut();
1134
1135    return ret;
1136}
1137
1138OMX_ERRORTYPE Exynos_OMX_BufferProcess_Terminate(OMX_HANDLETYPE hComponent)
1139{
1140    OMX_ERRORTYPE          ret = OMX_ErrorNone;
1141    OMX_COMPONENTTYPE     *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
1142    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
1143    EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
1144    OMX_S32                countValue = 0;
1145    unsigned int           i = 0;
1146
1147    FunctionIn();
1148
1149    pVideoDec->bExitBufferProcessThread = OMX_TRUE;
1150
1151    Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].bufferSemID, &countValue);
1152    if (countValue == 0)
1153        Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].bufferSemID);
1154    Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].codecSemID, &countValue);
1155    if (countValue == 0)
1156        Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].codecSemID);
1157    Exynos_OSAL_SignalSet(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].pauseEvent);
1158    Exynos_OSAL_ThreadTerminate(pVideoDec->hSrcInputThread);
1159    pVideoDec->hSrcInputThread = NULL;
1160
1161    Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].bufferSemID, &countValue);
1162    if (countValue == 0)
1163        Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].bufferSemID);
1164    Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].codecSemID, &countValue);
1165    if (countValue == 0)
1166        Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].codecSemID);
1167    Exynos_OSAL_SignalSet(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].pauseEvent);
1168    Exynos_OSAL_ThreadTerminate(pVideoDec->hDstInputThread);
1169    pVideoDec->hDstInputThread = NULL;
1170
1171    pVideoDec->exynos_codec_stop(pOMXComponent, INPUT_PORT_INDEX);
1172    pVideoDec->exynos_codec_bufferProcessRun(pOMXComponent, INPUT_PORT_INDEX);
1173    Exynos_OSAL_SignalSet(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].pauseEvent);
1174    Exynos_OSAL_ThreadTerminate(pVideoDec->hSrcOutputThread);
1175    pVideoDec->hSrcOutputThread = NULL;
1176
1177    pVideoDec->exynos_codec_stop(pOMXComponent, OUTPUT_PORT_INDEX);
1178    pVideoDec->exynos_codec_bufferProcessRun(pOMXComponent, INPUT_PORT_INDEX);
1179    Exynos_OSAL_SignalSet(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].pauseEvent);
1180    Exynos_OSAL_ThreadTerminate(pVideoDec->hDstOutputThread);
1181    pVideoDec->hDstOutputThread = NULL;
1182
1183    pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_FALSE;
1184    pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_FALSE;
1185
1186EXIT:
1187    FunctionOut();
1188
1189    return ret;
1190}
1191
1192OMX_ERRORTYPE Exynos_OMX_VideoDecodeComponentInit(OMX_IN OMX_HANDLETYPE hComponent)
1193{
1194    OMX_ERRORTYPE          ret = OMX_ErrorNone;
1195    OMX_COMPONENTTYPE     *pOMXComponent = NULL;
1196    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
1197    EXYNOS_OMX_BASEPORT      *pExynosPort = NULL;
1198    EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL;
1199
1200    FunctionIn();
1201
1202    if (hComponent == NULL) {
1203        ret = OMX_ErrorBadParameter;
1204        goto EXIT;
1205    }
1206    pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
1207    ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE));
1208    if (ret != OMX_ErrorNone) {
1209        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__);
1210        goto EXIT;
1211    }
1212
1213    ret = Exynos_OMX_BaseComponent_Constructor(pOMXComponent);
1214    if (ret != OMX_ErrorNone) {
1215        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__);
1216        goto EXIT;
1217    }
1218
1219    ret = Exynos_OMX_Port_Constructor(pOMXComponent);
1220    if (ret != OMX_ErrorNone) {
1221        Exynos_OMX_BaseComponent_Destructor(pOMXComponent);
1222        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__);
1223        goto EXIT;
1224    }
1225
1226    pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
1227
1228    pVideoDec = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_VIDEODEC_COMPONENT));
1229    if (pVideoDec == NULL) {
1230        Exynos_OMX_BaseComponent_Destructor(pOMXComponent);
1231        ret = OMX_ErrorInsufficientResources;
1232        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__);
1233        goto EXIT;
1234    }
1235
1236    Exynos_OSAL_Memset(pVideoDec, 0, sizeof(EXYNOS_OMX_VIDEODEC_COMPONENT));
1237    pVideoDec->bReconfigDPB = OMX_FALSE;
1238    pExynosComponent->hComponentHandle = (OMX_HANDLETYPE)pVideoDec;
1239
1240    pExynosComponent->bSaveFlagEOS = OMX_FALSE;
1241    pExynosComponent->bBehaviorEOS = OMX_FALSE;
1242    pExynosComponent->bMultiThreadProcess = OMX_TRUE;
1243
1244    /* Input port */
1245    pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX];
1246    pExynosPort->portDefinition.nBufferCountActual = MAX_VIDEO_INPUTBUFFER_NUM;
1247    pExynosPort->portDefinition.nBufferCountMin = MAX_VIDEO_INPUTBUFFER_NUM;
1248    pExynosPort->portDefinition.nBufferSize = 0;
1249    pExynosPort->portDefinition.eDomain = OMX_PortDomainVideo;
1250
1251    pExynosPort->portDefinition.format.video.cMIMEType = Exynos_OSAL_Malloc(MAX_OMX_MIMETYPE_SIZE);
1252    Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video");
1253    pExynosPort->portDefinition.format.video.pNativeRender = 0;
1254    pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE;
1255    pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
1256
1257    pExynosPort->portDefinition.format.video.nFrameWidth = 0;
1258    pExynosPort->portDefinition.format.video.nFrameHeight= 0;
1259    pExynosPort->portDefinition.format.video.nStride = 0;
1260    pExynosPort->portDefinition.format.video.nSliceHeight = 0;
1261    pExynosPort->portDefinition.format.video.nBitrate = 64000;
1262    pExynosPort->portDefinition.format.video.xFramerate = (15 << 16);
1263    pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused;
1264    pExynosPort->portDefinition.format.video.pNativeWindow = NULL;
1265
1266    /* Output port */
1267    pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX];
1268    pExynosPort->portDefinition.nBufferCountActual = MAX_VIDEO_OUTPUTBUFFER_NUM;
1269    pExynosPort->portDefinition.nBufferCountMin = MAX_VIDEO_OUTPUTBUFFER_NUM;
1270    pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE;
1271    pExynosPort->portDefinition.eDomain = OMX_PortDomainVideo;
1272
1273    pExynosPort->portDefinition.format.video.cMIMEType = Exynos_OSAL_Malloc(MAX_OMX_MIMETYPE_SIZE);
1274    Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video");
1275    pExynosPort->portDefinition.format.video.pNativeRender = 0;
1276    pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE;
1277    pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
1278
1279    pExynosPort->portDefinition.format.video.nFrameWidth = 0;
1280    pExynosPort->portDefinition.format.video.nFrameHeight= 0;
1281    pExynosPort->portDefinition.format.video.nStride = 0;
1282    pExynosPort->portDefinition.format.video.nSliceHeight = 0;
1283    pExynosPort->portDefinition.format.video.nBitrate = 64000;
1284    pExynosPort->portDefinition.format.video.xFramerate = (15 << 16);
1285    pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused;
1286    pExynosPort->portDefinition.format.video.pNativeWindow = NULL;
1287
1288    pExynosPort->processData.extInfo = (OMX_PTR)Exynos_OSAL_Malloc(sizeof(DECODE_CODEC_EXTRA_BUFFERINFO));
1289    Exynos_OSAL_Memset(((char *)pExynosPort->processData.extInfo), 0, sizeof(DECODE_CODEC_EXTRA_BUFFERINFO));
1290{
1291    int i = 0;
1292    DECODE_CODEC_EXTRA_BUFFERINFO *pBufferInfo = NULL;
1293    pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)(pExynosPort->processData.extInfo);
1294    for (i = 0; i < VIDEO_BUFFER_MAX_NUM; i++) {
1295        pBufferInfo->PDSB.dpbFD[i].fd  = -1;
1296        pBufferInfo->PDSB.dpbFD[i].fd1 = -1;
1297        pBufferInfo->PDSB.dpbFD[i].fd2 = -1;
1298    }
1299}
1300    pOMXComponent->UseBuffer              = &Exynos_OMX_UseBuffer;
1301    pOMXComponent->AllocateBuffer         = &Exynos_OMX_AllocateBuffer;
1302    pOMXComponent->FreeBuffer             = &Exynos_OMX_FreeBuffer;
1303    pOMXComponent->ComponentTunnelRequest = &Exynos_OMX_ComponentTunnelRequest;
1304
1305    pExynosComponent->exynos_AllocateTunnelBuffer = &Exynos_OMX_AllocateTunnelBuffer;
1306    pExynosComponent->exynos_FreeTunnelBuffer     = &Exynos_OMX_FreeTunnelBuffer;
1307    pExynosComponent->exynos_BufferProcessCreate    = &Exynos_OMX_BufferProcess_Create;
1308    pExynosComponent->exynos_BufferProcessTerminate = &Exynos_OMX_BufferProcess_Terminate;
1309    pExynosComponent->exynos_BufferFlush          = &Exynos_OMX_BufferFlush;
1310
1311    pVideoDec->hRefHandle = Exynos_OSAL_RefANB_Create();
1312
1313EXIT:
1314    FunctionOut();
1315
1316    return ret;
1317}
1318
1319OMX_ERRORTYPE Exynos_OMX_VideoDecodeComponentDeinit(OMX_IN OMX_HANDLETYPE hComponent)
1320{
1321    OMX_ERRORTYPE          ret = OMX_ErrorNone;
1322    OMX_COMPONENTTYPE     *pOMXComponent = NULL;
1323    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
1324    EXYNOS_OMX_BASEPORT      *pExynosPort = NULL;
1325    EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL;
1326    int                    i = 0;
1327
1328    FunctionIn();
1329
1330    if (hComponent == NULL) {
1331        ret = OMX_ErrorBadParameter;
1332        goto EXIT;
1333    }
1334    pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
1335    ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE));
1336    if (ret != OMX_ErrorNone) {
1337        goto EXIT;
1338    }
1339
1340    if (pOMXComponent->pComponentPrivate == NULL) {
1341        ret = OMX_ErrorBadParameter;
1342        goto EXIT;
1343    }
1344    pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
1345
1346    pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
1347
1348    Exynos_OSAL_RefANB_Terminate(pVideoDec->hRefHandle);
1349
1350    Exynos_OSAL_Free(pVideoDec);
1351    pExynosComponent->hComponentHandle = pVideoDec = NULL;
1352
1353    pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX];
1354    if (pExynosPort->processData.extInfo != NULL) {
1355        Exynos_OSAL_Free(pExynosPort->processData.extInfo);
1356        pExynosPort->processData.extInfo = NULL;
1357    }
1358
1359    for(i = 0; i < ALL_PORT_NUM; i++) {
1360        pExynosPort = &pExynosComponent->pExynosPort[i];
1361        Exynos_OSAL_Free(pExynosPort->portDefinition.format.video.cMIMEType);
1362        pExynosPort->portDefinition.format.video.cMIMEType = NULL;
1363    }
1364
1365    ret = Exynos_OMX_Port_Destructor(pOMXComponent);
1366
1367    ret = Exynos_OMX_BaseComponent_Destructor(hComponent);
1368
1369EXIT:
1370    FunctionOut();
1371
1372    return ret;
1373}
1374