exynos_omx: multi_thread: Add crop info update code.
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos5.git] / exynos_omx / openmax / exynos_omx / component / video / dec / Exynos_OMX_Vdec.c
index 4f696aadda011a69e7df7c35796c2cb4db4f2ac6..8d0e6d5bd8fb9f4390afe1f0a483195250385f25 100644 (file)
@@ -34,6 +34,7 @@
 #include "Exynos_OMX_Vdec.h"
 #include "Exynos_OMX_VdecControl.h"
 #include "Exynos_OMX_Basecomponent.h"
+#include "Exynos_OSAL_SharedMemory.h"
 #include "Exynos_OSAL_Thread.h"
 #include "Exynos_OSAL_Semaphore.h"
 #include "Exynos_OSAL_Mutex.h"
@@ -111,6 +112,108 @@ inline void Exynos_UpdateFrameSize(OMX_COMPONENTTYPE *pOMXComponent)
     return;
 }
 
+void Exynos_Free_CodecBuffers(
+    OMX_COMPONENTTYPE   *pOMXComponent,
+    OMX_U32              nPortIndex)
+{
+    OMX_ERRORTYPE                    ret                = OMX_ErrorNone;
+    EXYNOS_OMX_BASECOMPONENT        *pExynosComponent   = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
+    EXYNOS_OMX_VIDEODEC_COMPONENT   *pVideoDec          = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
+    CODEC_DEC_BUFFER               **ppCodecBuffer      = NULL;
+
+    OMX_U32 nPlaneCnt = 0;
+    int i, j;
+
+    FunctionIn();
+
+    if (nPortIndex == INPUT_PORT_INDEX) {
+        ppCodecBuffer = &(pVideoDec->pMFCDecInputBuffer[0]);
+        nPlaneCnt = MFC_INPUT_BUFFER_PLANE;
+    } else {
+        ppCodecBuffer = &(pVideoDec->pMFCDecOutputBuffer[0]);
+        nPlaneCnt = MFC_OUTPUT_BUFFER_PLANE;
+    }
+
+    for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) {
+        if (ppCodecBuffer[i] != NULL) {
+            for (j = 0; j < nPlaneCnt; j++) {
+                if (ppCodecBuffer[i]->pVirAddr[j] != NULL)
+                    Exynos_OSAL_SharedMemory_Free(pVideoDec->hSharedMemory, ppCodecBuffer[i]->pVirAddr[j]);
+            }
+
+            Exynos_OSAL_Free(ppCodecBuffer[i]);
+            ppCodecBuffer[i] = NULL;
+        }
+    }
+
+    FunctionOut();
+}
+
+OMX_ERRORTYPE Exynos_Allocate_CodecBuffers(
+    OMX_COMPONENTTYPE   *pOMXComponent,
+    OMX_U32              nPortIndex,
+    OMX_U32              nBufferCnt,
+    OMX_U32              nPlaneSize[MFC_OUTPUT_BUFFER_PLANE])
+{
+    OMX_ERRORTYPE                    ret                = OMX_ErrorNone;
+    EXYNOS_OMX_BASECOMPONENT        *pExynosComponent   = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
+    EXYNOS_OMX_VIDEODEC_COMPONENT   *pVideoDec          = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
+    MEMORY_TYPE                      eMemoryType        = NORMAL_MEMORY;
+    CODEC_DEC_BUFFER               **ppCodecBuffer      = NULL;
+
+    OMX_U32 nPlaneCnt = 0;
+    int i, j;
+
+    FunctionIn();
+
+    if (pVideoDec->bDRMPlayerMode == OMX_TRUE)
+        eMemoryType = SECURE_MEMORY;
+
+    if (nPortIndex == INPUT_PORT_INDEX) {
+        ppCodecBuffer = &(pVideoDec->pMFCDecInputBuffer[0]);
+        nPlaneCnt = MFC_INPUT_BUFFER_PLANE;
+    } else {
+        ppCodecBuffer = &(pVideoDec->pMFCDecOutputBuffer[0]);
+        nPlaneCnt = MFC_OUTPUT_BUFFER_PLANE;
+    }
+
+    for (i = 0; i < nBufferCnt; i++) {
+        ppCodecBuffer[i] = (CODEC_DEC_BUFFER *)Exynos_OSAL_Malloc(sizeof(CODEC_DEC_BUFFER));
+        if (ppCodecBuffer[i] == NULL) {
+            Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to Alloc codec buffer");
+            ret = OMX_ErrorInsufficientResources;
+            goto EXIT;
+        }
+        Exynos_OSAL_Memset(ppCodecBuffer[i], 0, sizeof(CODEC_DEC_BUFFER));
+
+        for (j = 0; j < nPlaneCnt; j++) {
+            ppCodecBuffer[i]->pVirAddr[j] =
+                (void *)Exynos_OSAL_SharedMemory_Alloc(pVideoDec->hSharedMemory, nPlaneSize[j], eMemoryType);
+            if (ppCodecBuffer[i]->pVirAddr[j] == NULL) {
+                Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to Alloc plane");
+                ret = OMX_ErrorInsufficientResources;
+                goto EXIT;
+            }
+
+            ppCodecBuffer[i]->fd[j] =
+                Exynos_OSAL_SharedMemory_VirtToION(pVideoDec->hSharedMemory, ppCodecBuffer[i]->pVirAddr[j]);
+            ppCodecBuffer[i]->bufferSize[j] = nPlaneSize[j];
+            Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "PORT[%d]: pMFCCodecBuffer[%d]->pVirAddr[%d]: 0x%x", nPortIndex, i, j, ppCodecBuffer[i]->pVirAddr[j]);
+        }
+
+        ppCodecBuffer[i]->dataSize = 0;
+    }
+
+    return OMX_ErrorNone;
+
+EXIT:
+    Exynos_Free_CodecBuffers(pOMXComponent, nPortIndex);
+
+    FunctionOut();
+
+    return ret;
+}
+
 OMX_BOOL Exynos_Check_BufferProcess_State(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nPortIndex)
 {
     OMX_BOOL ret = OMX_FALSE;
@@ -127,17 +230,58 @@ OMX_BOOL Exynos_Check_BufferProcess_State(EXYNOS_OMX_BASECOMPONENT *pExynosCompo
     return ret;
 }
 
+OMX_ERRORTYPE Exynos_ResetAllPortConfig(OMX_COMPONENTTYPE *pOMXComponent)
+{
+    OMX_ERRORTYPE                  ret               = OMX_ErrorNone;
+    EXYNOS_OMX_BASECOMPONENT      *pExynosComponent  = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
+    EXYNOS_OMX_BASEPORT           *pExynosInputPort  = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX];
+    EXYNOS_OMX_BASEPORT           *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX];
+
+    /* Input port */
+    pExynosInputPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH;
+    pExynosInputPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT;
+    pExynosInputPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/
+    pExynosInputPort->portDefinition.format.video.nSliceHeight = 0;
+    pExynosInputPort->portDefinition.nBufferSize = DEFAULT_VIDEO_INPUT_BUFFER_SIZE;
+    pExynosInputPort->portDefinition.format.video.pNativeRender = 0;
+    pExynosInputPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE;
+    pExynosInputPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused;
+    pExynosInputPort->portDefinition.bEnabled = OMX_TRUE;
+    pExynosInputPort->bufferProcessType = BUFFER_SHARE;
+    pExynosInputPort->portWayType = WAY2_PORT;
+
+    /* Output port */
+    pExynosOutputPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH;
+    pExynosOutputPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT;
+    pExynosOutputPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/
+    pExynosOutputPort->portDefinition.format.video.nSliceHeight = 0;
+    pExynosOutputPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE;
+    pExynosOutputPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
+    Exynos_OSAL_Memset(pExynosOutputPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE);
+    Exynos_OSAL_Strcpy(pExynosOutputPort->portDefinition.format.video.cMIMEType, "raw/video");
+    pExynosOutputPort->portDefinition.format.video.pNativeRender = 0;
+    pExynosOutputPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE;
+    pExynosOutputPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
+    pExynosOutputPort->portDefinition.nBufferCountActual = MAX_VIDEO_OUTPUTBUFFER_NUM;
+    pExynosOutputPort->portDefinition.nBufferCountMin = MAX_VIDEO_OUTPUTBUFFER_NUM;
+    pExynosOutputPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE;
+    pExynosOutputPort->portDefinition.bEnabled = OMX_TRUE;
+    pExynosOutputPort->bufferProcessType = BUFFER_COPY | BUFFER_ANBSHARE;
+    pExynosOutputPort->bIsANBEnabled = OMX_FALSE;
+    pExynosOutputPort->portWayType = WAY2_PORT;
+
+    return ret;
+}
+
 OMX_ERRORTYPE Exynos_Input_CodecBufferToData(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_PTR codecBuffer, EXYNOS_OMX_DATA *pData)
 {
     OMX_ERRORTYPE                  ret = OMX_ErrorNone;
     EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
-    CODEC_DEC_INPUT_BUFFER *pInputCodecBuffer = (CODEC_DEC_INPUT_BUFFER*)codecBuffer;
-
-    Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s: buffer=%p\n", __func__, codecBuffer);
+    CODEC_DEC_BUFFER *pInputCodecBuffer = (CODEC_DEC_BUFFER *)codecBuffer;
 
-    pData->buffer.singlePlaneBuffer.dataBuffer = pInputCodecBuffer->VirAddr;
-    pData->buffer.singlePlaneBuffer.fd = pInputCodecBuffer->fd;
-    pData->allocSize     = pInputCodecBuffer->bufferSize;
+    pData->buffer.singlePlaneBuffer.dataBuffer = pInputCodecBuffer->pVirAddr[0];
+    pData->buffer.singlePlaneBuffer.fd = pInputCodecBuffer->fd[0];
+    pData->allocSize     = pInputCodecBuffer->bufferSize[0];
     pData->dataLen       = pInputCodecBuffer->dataSize;
     pData->usedDataLen   = 0;
     pData->remainDataLen = pInputCodecBuffer->dataSize;
@@ -154,14 +298,10 @@ OMX_ERRORTYPE Exynos_Output_CodecBufferToData(EXYNOS_OMX_BASECOMPONENT *pExynosC
 {
     OMX_ERRORTYPE                  ret = OMX_ErrorNone;
     EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
-    OMX_PTR pSrcBuf[MAX_BUFFER_PLANE];
-    OMX_U32 allocSize[MAX_BUFFER_PLANE];
-
-    pVideoDec->exynos_codec_getCodecOutputPrivateData(codecBuffer, pSrcBuf, allocSize);
-    pData->buffer.multiPlaneBuffer.dataBuffer[0] = pSrcBuf[0];
-    pData->buffer.multiPlaneBuffer.dataBuffer[1] = pSrcBuf[1];
-    pData->buffer.multiPlaneBuffer.dataBuffer[2] = pSrcBuf[2];
-    pData->allocSize     = allocSize[0] + allocSize[1] + allocSize[2];
+    CODEC_DEC_BUFFER *pCodecBuffer = (CODEC_DEC_BUFFER *)codecBuffer;
+    int i = 0;
+
+    pData->allocSize     = 0;
     pData->dataLen       = 0;
     pData->usedDataLen   = 0;
     pData->remainDataLen = 0;
@@ -171,6 +311,12 @@ OMX_ERRORTYPE Exynos_Output_CodecBufferToData(EXYNOS_OMX_BASECOMPONENT *pExynosC
     pData->pPrivate      = codecBuffer;
     pData->bufferHeader  = NULL;
 
+    for (i = 0; i < MAX_BUFFER_PLANE; i++) {
+        pData->buffer.multiPlaneBuffer.dataBuffer[i] = pCodecBuffer->pVirAddr[i];
+        pData->buffer.multiPlaneBuffer.fd[i] = pCodecBuffer->fd[i];
+        pData->allocSize += pCodecBuffer->bufferSize[i];
+    }
+
     return ret;
 }
 
@@ -199,6 +345,133 @@ void Exynos_Wait_ProcessPause(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U3
     return;
 }
 
+OMX_BOOL Exynos_CSC_OutputData(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *dstOutputData)
+{
+    OMX_BOOL                   ret = OMX_FALSE;
+    EXYNOS_OMX_BASECOMPONENT  *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
+    EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
+    EXYNOS_OMX_BASEPORT       *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX];
+    EXYNOS_OMX_DATABUFFER     *outputUseBuffer = &exynosOutputPort->way.port2WayDataBuffer.outputDataBuffer;
+    OMX_U32                    copySize = 0;
+    DECODE_CODEC_EXTRA_BUFFERINFO *pBufferInfo = NULL;
+
+    FunctionIn();
+
+    OMX_U32 width = 0, height = 0;
+    int imageSize = 0;
+    OMX_COLOR_FORMATTYPE colorFormat;
+
+    void *pOutputBuf = (void *)outputUseBuffer->bufferHeader->pBuffer;
+    void *pSrcBuf[MAX_BUFFER_PLANE] = {NULL, };
+    void *pYUVBuf[MAX_BUFFER_PLANE] = {NULL, };
+
+    CSC_ERRORCODE cscRet = CSC_ErrorNone;
+    CSC_METHOD csc_method = CSC_METHOD_SW;
+    unsigned int cacheable = 1;
+
+    pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)dstOutputData->extInfo;
+
+    width = pBufferInfo->imageWidth;
+    height = pBufferInfo->imageHeight;
+    imageSize = width * height;
+    colorFormat = pBufferInfo->ColorFormat;
+
+    pSrcBuf[0] = dstOutputData->buffer.multiPlaneBuffer.dataBuffer[0];
+    pSrcBuf[1] = dstOutputData->buffer.multiPlaneBuffer.dataBuffer[1];
+    pSrcBuf[2] = dstOutputData->buffer.multiPlaneBuffer.dataBuffer[2];
+
+    pYUVBuf[0]  = (unsigned char *)pOutputBuf;
+    pYUVBuf[1]  = (unsigned char *)pOutputBuf + imageSize;
+    pYUVBuf[2]  = (unsigned char *)pOutputBuf + imageSize + imageSize / 4;
+
+    csc_get_method(pVideoDec->csc_handle, &csc_method);
+    if (csc_method == CSC_METHOD_HW) {
+        pSrcBuf[0] = dstOutputData->buffer.multiPlaneBuffer.fd[0];
+        pSrcBuf[1] = dstOutputData->buffer.multiPlaneBuffer.fd[1];
+        pSrcBuf[2] = dstOutputData->buffer.multiPlaneBuffer.fd[2];
+    }
+
+#ifdef USE_ANB
+    if ((exynosOutputPort->bIsANBEnabled == OMX_TRUE) ||
+        (exynosOutputPort->bStoreMetaData == OMX_TRUE)) {
+        ExynosVideoPlane planes[MAX_BUFFER_PLANE];
+        OMX_U32 stride;
+        if (exynosOutputPort->bIsANBEnabled == OMX_TRUE) {
+            Exynos_OSAL_LockANBHandle(pOutputBuf, width, height, exynosOutputPort->portDefinition.format.video.eColorFormat, &stride, planes);
+        } else if (exynosOutputPort->bStoreMetaData == OMX_TRUE) {
+            Exynos_OSAL_LockMetaData(pOutputBuf, width, height, exynosOutputPort->portDefinition.format.video.eColorFormat, &stride, planes);
+        }
+        width = stride;
+        outputUseBuffer->dataLen = sizeof(void *);
+
+        if (csc_method == CSC_METHOD_SW) {
+            pYUVBuf[0]  = (unsigned char *)planes[0].addr;
+            pYUVBuf[1]  = (unsigned char *)planes[1].addr;
+            pYUVBuf[2]  = (unsigned char *)planes[2].addr;
+        } else {
+            pYUVBuf[0]  = (unsigned char *)planes[0].fd;
+            pYUVBuf[1]  = (unsigned char *)planes[1].fd;
+            pYUVBuf[2]  = (unsigned char *)planes[2].fd;
+        }
+    }
+#endif
+    if ((exynosOutputPort->bIsANBEnabled == OMX_FALSE) &&
+        (exynosOutputPort->bStoreMetaData == OMX_FALSE) &&
+        (csc_method == CSC_METHOD_HW)) {
+        pYUVBuf[0] = Exynos_OSAL_SharedMemory_VirtToION(pVideoDec->hSharedMemory, pOutputBuf);
+        pYUVBuf[1] = NULL;
+        pYUVBuf[2] = NULL;
+    }
+
+    if (pVideoDec->csc_set_format == OMX_FALSE) {
+        csc_set_src_format(
+            pVideoDec->csc_handle,  /* handle */
+            width,            /* width */
+            height,           /* height */
+            0,                /* crop_left */
+            0,                /* crop_right */
+            width,            /* crop_width */
+            height,           /* crop_height */
+            omx_2_hal_pixel_format(colorFormat), /* color_format */
+            cacheable);             /* cacheable */
+        csc_set_dst_format(
+            pVideoDec->csc_handle,  /* handle */
+            width,           /* width */
+            height,           /* height */
+            0,                /* crop_left */
+            0,                /* crop_right */
+            width,           /* crop_width */
+            height,           /* crop_height */
+            omx_2_hal_pixel_format(exynosOutputPort->portDefinition.format.video.eColorFormat), /* color_format */
+            cacheable);             /* cacheable */
+        pVideoDec->csc_set_format = OMX_TRUE;
+    }
+    csc_set_src_buffer(
+        pVideoDec->csc_handle,  /* handle */
+        pSrcBuf);            /* YUV Addr or FD */
+    csc_set_dst_buffer(
+        pVideoDec->csc_handle,  /* handle */
+        pYUVBuf);            /* YUV Addr or FD */
+    cscRet = csc_convert(pVideoDec->csc_handle);
+    if (cscRet != CSC_ErrorNone)
+        ret = OMX_FALSE;
+    else
+        ret = OMX_TRUE;
+
+#ifdef USE_ANB
+    if (exynosOutputPort->bIsANBEnabled == OMX_TRUE) {
+        Exynos_OSAL_UnlockANBHandle(pOutputBuf);
+    } else if (exynosOutputPort->bStoreMetaData == OMX_TRUE) {
+        Exynos_OSAL_UnlockMetaData(pOutputBuf);
+    }
+#endif
+
+EXIT:
+    FunctionOut();
+
+    return ret;
+}
+
 OMX_BOOL Exynos_Preprocessor_InputData(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *srcInputData)
 {
     OMX_BOOL               ret = OMX_FALSE;
@@ -209,9 +482,6 @@ OMX_BOOL Exynos_Preprocessor_InputData(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_
     OMX_U32                copySize = 0;
     OMX_BYTE               checkInputStream = NULL;
     OMX_U32                checkInputStreamLen = 0;
-    OMX_U32                checkedSize = 0;
-    OMX_BOOL               flagEOF = OMX_FALSE;
-    OMX_BOOL               previousFrameEOF = OMX_FALSE;
 
     FunctionIn();
 
@@ -227,32 +497,29 @@ OMX_BOOL Exynos_Preprocessor_InputData(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_
         if (exynosInputPort->bufferProcessType == BUFFER_SHARE) {
             Exynos_Shared_BufferToData(inputUseBuffer, srcInputData, ONE_PLANE);
 
+            if (pVideoDec->bDRMPlayerMode == OMX_TRUE) {
+                OMX_PTR dataBuffer = NULL;
+
+                dataBuffer = Exynos_OSAL_SharedMemory_IONToVirt(pVideoDec->hSharedMemory,
+                                                            srcInputData->buffer.singlePlaneBuffer.dataBuffer);
+                if (dataBuffer == NULL) {
+                    ret = OMX_FALSE;
+                    goto EXIT;
+                }
+
+                srcInputData->buffer.singlePlaneBuffer.dataBuffer = dataBuffer;
+            }
+
             /* reset dataBuffer */
             Exynos_ResetDataBuffer(inputUseBuffer);
-
-            flagEOF = OMX_TRUE;
         } else if ((exynosInputPort->bufferProcessType & BUFFER_COPY) == BUFFER_COPY) {
             checkInputStream = inputUseBuffer->bufferHeader->pBuffer + inputUseBuffer->usedDataLen;
             checkInputStreamLen = inputUseBuffer->remainDataLen;
 
-            if (srcInputData->dataLen == 0) {
-                previousFrameEOF = OMX_TRUE;
-            } else {
-                previousFrameEOF = OMX_FALSE;
-            }
-
-            flagEOF = OMX_TRUE;
             pExynosComponent->bUseFlagEOF = OMX_TRUE;
 
-            checkedSize = checkInputStreamLen;
-
-            if (flagEOF == OMX_TRUE) {
-                copySize = checkedSize;
-                Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "exynos_checkInputFrame : OMX_TRUE");
-            } else {
-                copySize = checkInputStreamLen;
-                Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "exynos_checkInputFrame : OMX_FALSE");
-            }
+            copySize = checkInputStreamLen;
+            Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "exynos_checkInputFrame : OMX_TRUE");
 
             if (((srcInputData->allocSize) - (srcInputData->dataLen)) >= copySize) {
                 if (copySize > 0) {
@@ -275,33 +542,29 @@ OMX_BOOL Exynos_Preprocessor_InputData(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_
                 pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent,
                                                         pExynosComponent->callbackData,
                                                         OMX_EventError, OMX_ErrorUndefined, 0, NULL);
-                flagEOF = OMX_FALSE;
+                ret = OMX_FALSE;
             }
 
-            Exynos_InputBufferReturn(pOMXComponent);
+            Exynos_InputBufferReturn(pOMXComponent, inputUseBuffer);
         }
 
         if ((srcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) {
             Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "bSaveFlagEOS : OMX_TRUE");
-            srcInputData->dataLen = 0;
-            srcInputData->remainDataLen = 0;
             pExynosComponent->bSaveFlagEOS = OMX_TRUE;
+            if (srcInputData->dataLen != 0)
+                pExynosComponent->bBehaviorEOS = OMX_TRUE;
         }
 
-        if (flagEOF == OMX_TRUE) {
-            if (pExynosComponent->checkTimeStamp.needSetStartTimeStamp == OMX_TRUE) {
-                pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_TRUE;
-                pExynosComponent->checkTimeStamp.startTimeStamp = srcInputData->timeStamp;
-                pExynosComponent->checkTimeStamp.nStartFlags = srcInputData->nFlags;
-                pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_FALSE;
-                Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "first frame timestamp after seeking %lld us (%.2f secs)",
-                    srcInputData->timeStamp, srcInputData->timeStamp / 1E6);
-            }
-
-            ret = OMX_TRUE;
-        } else {
-            ret = OMX_FALSE;
+        if (pExynosComponent->checkTimeStamp.needSetStartTimeStamp == OMX_TRUE) {
+            pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_TRUE;
+            pExynosComponent->checkTimeStamp.startTimeStamp = srcInputData->timeStamp;
+            pExynosComponent->checkTimeStamp.nStartFlags = srcInputData->nFlags;
+            pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_FALSE;
+            Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "first frame timestamp after seeking %lld us (%.2f secs)",
+                            srcInputData->timeStamp, srcInputData->timeStamp / 1E6);
         }
+
+        ret = OMX_TRUE;
     }
 
 EXIT:
@@ -324,7 +587,8 @@ OMX_BOOL Exynos_Postprocess_OutputData(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_
     FunctionIn();
 
     if (exynosOutputPort->bufferProcessType == BUFFER_SHARE) {
-        if (exynosOutputPort->bIsANBEnabled == OMX_FALSE) {
+        if ((exynosOutputPort->bIsANBEnabled == OMX_FALSE) &&
+            (exynosOutputPort->bStoreMetaData == OMX_FALSE)) {
             if (Exynos_Shared_DataToBuffer(dstOutputData, outputUseBuffer) == OMX_ErrorNone)
                 outputUseBuffer->dataValid = OMX_TRUE;
         } else {
@@ -364,33 +628,13 @@ OMX_BOOL Exynos_Postprocess_OutputData(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_
         if ((exynosOutputPort->bufferProcessType & BUFFER_COPY) == BUFFER_COPY) {
             OMX_U32 width = 0, height = 0;
             int imageSize = 0;
-            OMX_COLOR_FORMATTYPE colorFormat;
-
             void *pOutputBuf = (void *)outputUseBuffer->bufferHeader->pBuffer;
-            void *pSrcBuf[MAX_BUFFER_PLANE] = {NULL, };
-            void *pYUVBuf[MAX_BUFFER_PLANE] = {NULL, };
-            int fds[MAX_BUFFER_PLANE];
-
-            CSC_ERRORCODE cscRet = CSC_ErrorNone;
-            CSC_METHOD csc_method = CSC_METHOD_SW;
-            unsigned int cacheable = 1;
 
             pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)dstOutputData->extInfo;
-#if 0
-            pVideoDec->exynos_codec_getCodecOutputPrivateData(dstOutputData->pPrivate, pSrcBuf, NULL);
-#else
-            pSrcBuf[0] = dstOutputData->buffer.multiPlaneBuffer.dataBuffer[0];
-            pSrcBuf[1] = dstOutputData->buffer.multiPlaneBuffer.dataBuffer[1];
-            pSrcBuf[2] = dstOutputData->buffer.multiPlaneBuffer.dataBuffer[2];
-#endif
+
             width = pBufferInfo->imageWidth;
             height = pBufferInfo->imageHeight;
             imageSize = width * height;
-            colorFormat = pBufferInfo->ColorFormat;
-
-            pYUVBuf[0]  = (unsigned char *)pOutputBuf;
-            pYUVBuf[1]  = (unsigned char *)pOutputBuf + imageSize;
-            pYUVBuf[2]  = (unsigned char *)pOutputBuf + imageSize + imageSize / 4;
 
             if ((dstOutputData->remainDataLen <= (outputUseBuffer->allocSize - outputUseBuffer->dataLen)) &&
                 (!CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) {
@@ -403,85 +647,16 @@ OMX_BOOL Exynos_Postprocess_OutputData(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_
                 outputUseBuffer->timeStamp = dstOutputData->timeStamp;
 
                 if (outputUseBuffer->remainDataLen > 0) {
-#ifdef USE_ANB
-                    void *pPhys[MAX_BUFFER_PLANE];
-                    
-                    if (exynosOutputPort->bIsANBEnabled == OMX_TRUE) {
-                        OMX_U32 stride;
-                        ExynosVideoPlane planes[MAX_BUFFER_PLANE];
-                        Exynos_OSAL_LockANB(outputUseBuffer->bufferHeader->pBuffer, width, height, exynosOutputPort->portDefinition.format.video.eColorFormat, &stride, planes);
-                        width = stride;
-                        fds[0] = planes[0].fd;
-                        fds[1] = planes[1].fd;
-                        fds[2] = planes[2].fd;
-                        pYUVBuf[0] = planes[0].addr;
-                        pYUVBuf[1] = planes[1].addr;
-                        pYUVBuf[2] = planes[2].addr;
-                        outputUseBuffer->dataLen = sizeof(void *);
-                    }
-#endif
-                    if (exynosOutputPort->portDefinition.format.video.eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12TPhysicalAddress) {
-                        /* if use Post copy address structure */
-                        Exynos_OSAL_Memcpy(pYUVBuf[0], &(pSrcBuf[0]), sizeof(void *));
-                        Exynos_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 1), &(pSrcBuf[1]), sizeof(void *));
-                        Exynos_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 2), &(pSrcBuf[0]), sizeof(void *));
-                        Exynos_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 3), &(pSrcBuf[1]), sizeof(void *));
-                        outputUseBuffer->dataLen = sizeof(void *) * 4;
-                    } else {
-                        csc_get_method(pVideoDec->csc_handle, &csc_method);
-                        if (pVideoDec->csc_set_format == OMX_FALSE) {
-                            csc_set_src_format(
-                                pVideoDec->csc_handle,  /* handle */
-                                width,            /* width */
-                                height,           /* height */
-                                0,                /* crop_left */
-                                0,                /* crop_right */
-                                width,            /* crop_width */
-                                height,           /* crop_height */
-                                omx_2_hal_pixel_format(colorFormat), /* color_format */
-                                cacheable);             /* cacheable */
-                            csc_set_dst_format(
-                                pVideoDec->csc_handle,  /* handle */
-                                width,           /* width */
-                                height,           /* height */
-                                0,                /* crop_left */
-                                0,                /* crop_right */
-                                width,           /* crop_width */
-                                height,           /* crop_height */
-                                omx_2_hal_pixel_format(exynosOutputPort->portDefinition.format.video.eColorFormat),       /* color_format */
-                                cacheable);             /* cacheable */
-                            pVideoDec->csc_set_format = OMX_TRUE;
-                        }
-                        csc_set_src_buffer(
-                            pVideoDec->csc_handle,  /* handle */
-                            pSrcBuf[0],             /* y addr */
-                            pSrcBuf[1],             /* u addr or uv addr */
-                            pSrcBuf[2],             /* v addr or none */
-                            0);                     /* ion fd */
-                        csc_set_dst_buffer(
-                            pVideoDec->csc_handle,  /* handle */
-                            pYUVBuf[0],             /* y addr */
-                            pYUVBuf[1],             /* u addr or uv addr */
-                            pYUVBuf[2],             /* v addr or none */
-                            0);                     /* ion fd */
-                        cscRet = csc_convert(pVideoDec->csc_handle);
-                    }
-#ifdef USE_ANB
-                    if (exynosOutputPort->bIsANBEnabled == OMX_TRUE) {
-                        Exynos_OSAL_UnlockANB(outputUseBuffer->bufferHeader->pBuffer/*dstOutputData->dataBuffer*/);
-                    }
-#endif
+                    ret = Exynos_CSC_OutputData(pOMXComponent, dstOutputData);
                 } else {
-                    cscRet = CSC_ErrorNone;
-                }
-
-                if (cscRet == CSC_ErrorNone) {
                     ret = OMX_TRUE;
+                }
 
+                if (ret == OMX_TRUE) {
                     if ((outputUseBuffer->remainDataLen > 0) ||
                         ((outputUseBuffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) ||
                         (CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) {
-                        Exynos_OutputBufferReturn(pOMXComponent);
+                        Exynos_OutputBufferReturn(pOMXComponent, outputUseBuffer);
                     }
                 } else {
                     Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "csc_convert Error");
@@ -495,7 +670,7 @@ OMX_BOOL Exynos_Postprocess_OutputData(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_
                 outputUseBuffer->remainDataLen = 0;
                 outputUseBuffer->nFlags = dstOutputData->nFlags;
                 outputUseBuffer->timeStamp = dstOutputData->timeStamp;
-                Exynos_OutputBufferReturn(pOMXComponent);
+                Exynos_OutputBufferReturn(pOMXComponent, outputUseBuffer);
             } else {
                 Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "output buffer is smaller than decoded data size Out Length");
                 pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent,
@@ -507,7 +682,7 @@ OMX_BOOL Exynos_Postprocess_OutputData(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_
             if ((outputUseBuffer->remainDataLen > 0) ||
                 ((outputUseBuffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) ||
                 (CHECK_PORT_BEING_FLUSHED(exynosOutputPort)))
-                Exynos_OutputBufferReturn(pOMXComponent);
+                Exynos_OutputBufferReturn(pOMXComponent, outputUseBuffer);
         }
     } else {
         ret = OMX_FALSE;
@@ -543,7 +718,7 @@ OMX_ERRORTYPE Exynos_OMX_SrcInputBufferProcess(OMX_HANDLETYPE hComponent)
             Exynos_OSAL_SleepMillisec(0);
 
             if ((CHECK_PORT_BEING_FLUSHED(exynosInputPort)) ||
-                ((exynosOutputPort->exceptionFlag == NEED_PORT_DISABLE) && (ret == OMX_ErrorInputDataDecodeYet)))
+                ((exynosOutputPort->exceptionFlag != GENERAL_STATE) && (ret == OMX_ErrorInputDataDecodeYet)))
                 break;
             if (exynosInputPort->portState != OMX_StateIdle)
                 break;
@@ -635,7 +810,7 @@ OMX_ERRORTYPE Exynos_OMX_SrcOutputBufferProcess(OMX_HANDLETYPE hComponent)
                 }
                 if (exynosInputPort->bufferProcessType == BUFFER_SHARE) {
                     Exynos_Shared_DataToBuffer(&srcOutputData, srcOutputUseBuffer);
-                    Exynos_InputBufferReturn(pOMXComponent);
+                    Exynos_InputBufferReturn(pOMXComponent, srcOutputUseBuffer);
                 }
                 Exynos_ResetCodecData(&srcOutputData);
             }
@@ -659,7 +834,7 @@ OMX_ERRORTYPE Exynos_OMX_DstInputBufferProcess(OMX_HANDLETYPE hComponent)
     EXYNOS_OMX_BASEPORT      *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX];
     EXYNOS_OMX_DATABUFFER    *dstInputUseBuffer = &exynosOutputPort->way.port2WayDataBuffer.inputDataBuffer;
     EXYNOS_OMX_DATA           dstInputData;
-    
+
     FunctionIn();
 
     while (!pVideoDec->bExitBufferProcessThread) {
@@ -670,7 +845,8 @@ OMX_ERRORTYPE Exynos_OMX_DstInputBufferProcess(OMX_HANDLETYPE hComponent)
             Exynos_OSAL_SleepMillisec(0);
 
             if ((CHECK_PORT_BEING_FLUSHED(exynosOutputPort)) ||
-                (!CHECK_PORT_POPULATED(exynosOutputPort)))
+                (!CHECK_PORT_POPULATED(exynosOutputPort)) ||
+                (exynosOutputPort->exceptionFlag != GENERAL_STATE))
                 break;
             if (exynosOutputPort->portState != OMX_StateIdle)
                 break;
@@ -695,7 +871,8 @@ OMX_ERRORTYPE Exynos_OMX_DstInputBufferProcess(OMX_HANDLETYPE hComponent)
                             Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex);
                             break;
                         }
-                        if (exynosOutputPort->bIsANBEnabled == OMX_FALSE) {
+                        if ((exynosOutputPort->bIsANBEnabled == OMX_FALSE) &&
+                            (exynosOutputPort->bStoreMetaData == OMX_FALSE)) {
                             Exynos_Shared_BufferToData(dstInputUseBuffer, &dstInputData, TWO_PLANE);
                         } else {
                             ret = Exynos_Shared_ANBBufferToData(dstInputUseBuffer, &dstInputData, exynosOutputPort, TWO_PLANE);
@@ -705,6 +882,11 @@ OMX_ERRORTYPE Exynos_OMX_DstInputBufferProcess(OMX_HANDLETYPE hComponent)
                                 break;
                             }
                         }
+
+                        OMX_PTR pBufferHandle = dstInputData.bufferHeader->pBuffer;
+                        if (exynosOutputPort->bStoreMetaData == OMX_TRUE)
+                            Exynos_OSAL_GetInfoFromMetaData(dstInputData.bufferHeader->pBuffer, &pBufferHandle);
+                        Exynos_OSAL_RefANB_Increase(pVideoDec->hRefHandle, pBufferHandle);
                         Exynos_ResetDataBuffer(dstInputUseBuffer);
                     }
                 }
@@ -739,7 +921,7 @@ OMX_ERRORTYPE Exynos_OMX_DstOutputBufferProcess(OMX_HANDLETYPE hComponent)
     EXYNOS_OMX_BASEPORT      *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX];
     EXYNOS_OMX_DATABUFFER    *dstOutputUseBuffer = &exynosOutputPort->way.port2WayDataBuffer.outputDataBuffer;
     EXYNOS_OMX_DATA          *pDstOutputData = &exynosOutputPort->processData;
-    
+
     FunctionIn();
 
     while (!pVideoDec->bExitBufferProcessThread) {
@@ -771,13 +953,24 @@ OMX_ERRORTYPE Exynos_OMX_DstOutputBufferProcess(OMX_HANDLETYPE hComponent)
 
             if (((ret == OMX_ErrorNone) && (dstOutputUseBuffer->dataValid == OMX_TRUE)) ||
                 (exynosOutputPort->bufferProcessType == BUFFER_SHARE)) {
+                if (exynosOutputPort->bufferProcessType == BUFFER_SHARE) {
+                    DECODE_CODEC_EXTRA_BUFFERINFO *pBufferInfo = NULL;
+                    int i;
+                    pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)pDstOutputData->extInfo;
+                    for (i = 0; i < VIDEO_BUFFER_MAX_NUM; i++) {
+                        if (pBufferInfo->PDSB.dpbFD[i].fd > -1) {
+                            Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "decRefCnt-FD:%d", pBufferInfo->PDSB.dpbFD[i].fd);
+                            Exynos_OSAL_RefANB_Decrease(pVideoDec->hRefHandle, pBufferInfo->PDSB.dpbFD[i].fd);
+                        } else {
+                            break;
+                        }
+                    }
+                }
                 Exynos_Postprocess_OutputData(pOMXComponent, pDstOutputData);
             }
 
             if ((exynosOutputPort->bufferProcessType & BUFFER_COPY) == BUFFER_COPY) {
-                OMX_PTR codecBuffer;
-                DECODE_CODEC_EXTRA_BUFFERINFO *pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)pDstOutputData->extInfo;
-                codecBuffer = pDstOutputData->pPrivate;
+                OMX_PTR codecBuffer = pDstOutputData->pPrivate;
                 if (codecBuffer != NULL) {
                     Exynos_CodecBufferEnQueue(pExynosComponent, OUTPUT_PORT_INDEX, codecBuffer);
                     pDstOutputData->pPrivate = NULL;
@@ -991,6 +1184,9 @@ OMX_ERRORTYPE Exynos_OMX_BufferProcess_Terminate(OMX_HANDLETYPE hComponent)
     Exynos_OSAL_ThreadTerminate(pVideoDec->hDstOutputThread);
     pVideoDec->hDstOutputThread = NULL;
 
+    pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_FALSE;
+    pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_FALSE;
+
 EXIT:
     FunctionOut();
 
@@ -1042,9 +1238,11 @@ OMX_ERRORTYPE Exynos_OMX_VideoDecodeComponentInit(OMX_IN OMX_HANDLETYPE hCompone
     }
 
     Exynos_OSAL_Memset(pVideoDec, 0, sizeof(EXYNOS_OMX_VIDEODEC_COMPONENT));
+    pVideoDec->bReconfigDPB = OMX_FALSE;
     pExynosComponent->hComponentHandle = (OMX_HANDLETYPE)pVideoDec;
 
     pExynosComponent->bSaveFlagEOS = OMX_FALSE;
+    pExynosComponent->bBehaviorEOS = OMX_FALSE;
     pExynosComponent->bMultiThreadProcess = OMX_TRUE;
 
     /* Input port */
@@ -1092,7 +1290,17 @@ OMX_ERRORTYPE Exynos_OMX_VideoDecodeComponentInit(OMX_IN OMX_HANDLETYPE hCompone
     pExynosPort->portDefinition.format.video.pNativeWindow = NULL;
 
     pExynosPort->processData.extInfo = (OMX_PTR)Exynos_OSAL_Malloc(sizeof(DECODE_CODEC_EXTRA_BUFFERINFO));
-
+    Exynos_OSAL_Memset(((char *)pExynosPort->processData.extInfo), 0, sizeof(DECODE_CODEC_EXTRA_BUFFERINFO));
+{
+    int i = 0;
+    DECODE_CODEC_EXTRA_BUFFERINFO *pBufferInfo = NULL;
+    pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)(pExynosPort->processData.extInfo);
+    for (i = 0; i < VIDEO_BUFFER_MAX_NUM; i++) {
+        pBufferInfo->PDSB.dpbFD[i].fd  = -1;
+        pBufferInfo->PDSB.dpbFD[i].fd1 = -1;
+        pBufferInfo->PDSB.dpbFD[i].fd2 = -1;
+    }
+}
     pOMXComponent->UseBuffer              = &Exynos_OMX_UseBuffer;
     pOMXComponent->AllocateBuffer         = &Exynos_OMX_AllocateBuffer;
     pOMXComponent->FreeBuffer             = &Exynos_OMX_FreeBuffer;
@@ -1104,6 +1312,8 @@ OMX_ERRORTYPE Exynos_OMX_VideoDecodeComponentInit(OMX_IN OMX_HANDLETYPE hCompone
     pExynosComponent->exynos_BufferProcessTerminate = &Exynos_OMX_BufferProcess_Terminate;
     pExynosComponent->exynos_BufferFlush          = &Exynos_OMX_BufferFlush;
 
+    pVideoDec->hRefHandle = Exynos_OSAL_RefANB_Create();
+
 EXIT:
     FunctionOut();
 
@@ -1139,6 +1349,8 @@ OMX_ERRORTYPE Exynos_OMX_VideoDecodeComponentDeinit(OMX_IN OMX_HANDLETYPE hCompo
 
     pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
 
+    Exynos_OSAL_RefANB_Terminate(pVideoDec->hRefHandle);
+
     Exynos_OSAL_Free(pVideoDec);
     pExynosComponent->hComponentHandle = pVideoDec = NULL;