Exynos_OMX_Vp8dec.c revision 20d3e6e3118a6e19627296e9247e948d54ec0fb8
1/*
2 *
3 * Copyright 2011 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_Vp8dec.c
20 * @brief
21 * @author      Satish Kumar Reddy (palli.satish@samsung.com)
22 * @version     1.1.0
23 * @history
24 *   2011.11.15 : Create
25 */
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30
31#include "Exynos_OMX_Macros.h"
32#include "Exynos_OMX_Basecomponent.h"
33#include "Exynos_OMX_Baseport.h"
34#include "Exynos_OMX_Vdec.h"
35#include "Exynos_OSAL_ETC.h"
36#include "Exynos_OSAL_Semaphore.h"
37#include "Exynos_OSAL_Thread.h"
38#include "library_register.h"
39#include "Exynos_OMX_Vp8dec.h"
40#include "ExynosVideoApi.h"
41
42#ifdef USE_ANB
43#include "Exynos_OSAL_Android.h"
44#endif
45
46/* To use CSC_METHOD_PREFER_HW or CSC_METHOD_HW in EXYNOS OMX, gralloc should allocate physical memory using FIMC */
47/* It means GRALLOC_USAGE_HW_FIMC1 should be set on Native Window usage */
48#include "csc.h"
49
50#undef  EXYNOS_LOG_TAG
51#define EXYNOS_LOG_TAG    "EXYNOS_VP8_DEC"
52#define EXYNOS_LOG_OFF
53#include "Exynos_OSAL_Log.h"
54
55#define VP8_DEC_NUM_OF_EXTRA_BUFFERS 7
56
57//#define FULL_FRAME_SEARCH /* Full frame search not support*/
58
59static int Check_VP8_Frame(
60    OMX_U8   *pInputStream,
61    int       buffSize,
62    OMX_U32   flag,
63    OMX_BOOL  bPreviousFrameEOF,
64    OMX_BOOL *pbEndOfFrame)
65{
66    /* Uncompressed data Chunk comprises a common
67    (for key frames and interframes) 3-byte frame tag that
68    contains four fields
69    - 1-bit frame type (0 - key frame, 1 - inter frame)
70    - 3-bit version number (0 - 3 are defined as four different
71                                      profiles with different decoding complexity)
72    - 1-bit show_frame flag ( 0 - current frame not for display,
73                                          1 - current frame is for dispaly)
74    - 19-bit field - size of the first data partition in bytes
75
76    Key Frames : frame tag followed by 7 bytes of uncompressed
77    data
78    3-bytes : Start code (byte 0: 0x9d,byte 1: 0x01,byte 2: 0x2a)
79    Next 4-bytes: Width & height, Horizontal and vertical scale information
80    16 bits      :     (2 bits Horizontal Scale << 14) | Width (14 bits)
81    16 bits      :     (2 bits Vertical Scale << 14) | Height (14 bits)
82    */
83    int width, height;
84    int horizSscale, vertScale;
85
86    FunctionIn();
87
88    *pbEndOfFrame = OMX_TRUE;
89
90    /*Check for Key frame*/
91    if (!(pInputStream[0] & 0x01)){
92        /* Key Frame  Start code*/
93        if (pInputStream[3] != 0x9d || pInputStream[4] != 0x01 || pInputStream[5]!=0x2a) {
94            Exynos_OSAL_Log(EXYNOS_LOG_ERROR, " VP8 Key Frame Start Code not Found");
95            *pbEndOfFrame = OMX_FALSE;
96        }
97        Exynos_OSAL_Log(EXYNOS_LOG_TRACE, " VP8 Found Key Frame Start Code");
98        width = (pInputStream[6] | (pInputStream[7] << 8)) & 0x3fff;
99        horizSscale = pInputStream[7] >> 6;
100        height = (pInputStream[8] | (pInputStream[9] << 8)) & 0x3fff;
101        vertScale = pInputStream[9] >> 6;
102        Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "width = %d, height = %d, horizSscale = %d, vertScale = %d", width, height, horizSscale, vertScale);
103    }
104
105    FunctionOut();
106    return buffSize;
107}
108
109OMX_BOOL Check_VP8_StartCode(
110    OMX_U8     *pInputStream,
111    OMX_U32     streamSize)
112{
113    Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "streamSize: %d",streamSize);
114    if (streamSize < 3) {
115        return OMX_FALSE;
116    }
117
118    if (!(pInputStream[0] & 0x01)){
119        /* Key Frame  Start code*/
120        if (pInputStream[3] != 0x9d || pInputStream[4] != 0x01 || pInputStream[5]!=0x2a) {
121            Exynos_OSAL_Log(EXYNOS_LOG_ERROR, " VP8 Key Frame Start Code not Found");
122            return OMX_FALSE;
123        }
124        Exynos_OSAL_Log(EXYNOS_LOG_TRACE, " VP8 Found Key Frame Start Code");
125    }
126
127    return OMX_TRUE;
128}
129
130OMX_ERRORTYPE Exynos_MFC_VP8Dec_GetParameter(
131    OMX_IN OMX_HANDLETYPE hComponent,
132    OMX_IN OMX_INDEXTYPE  nParamIndex,
133    OMX_INOUT OMX_PTR     pComponentParameterStructure)
134{
135    OMX_ERRORTYPE             ret              = OMX_ErrorNone;
136    OMX_COMPONENTTYPE        *pOMXComponent    = NULL;
137    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
138
139    FunctionIn();
140
141    if (hComponent == NULL || pComponentParameterStructure == NULL) {
142        ret = OMX_ErrorBadParameter;
143        goto EXIT;
144    }
145    pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
146    ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE));
147    if (ret != OMX_ErrorNone) {
148        goto EXIT;
149    }
150    if (pOMXComponent->pComponentPrivate == NULL) {
151        ret = OMX_ErrorBadParameter;
152        goto EXIT;
153    }
154
155    pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
156    if (pExynosComponent->currentState == OMX_StateInvalid ) {
157        ret = OMX_ErrorInvalidState;
158        goto EXIT;
159    }
160
161    switch (nParamIndex) {
162    case OMX_IndexParamStandardComponentRole:
163    {
164        OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure;
165        ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE));
166        if (ret != OMX_ErrorNone) {
167            goto EXIT;
168        }
169
170        Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_VP8_DEC_ROLE);
171    }
172        break;
173    case OMX_IndexParamVideoErrorCorrection:
174    {
175        OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure;
176        OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = NULL;
177        EXYNOS_VP8DEC_HANDLE                *pVp8Dec                 = NULL;
178
179        ret = Exynos_OMX_Check_SizeVersion(pDstErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE));
180        if (ret != OMX_ErrorNone) {
181            goto EXIT;
182        }
183
184        if (pDstErrorCorrectionType->nPortIndex != INPUT_PORT_INDEX) {
185            ret = OMX_ErrorBadPortIndex;
186            goto EXIT;
187        }
188
189        pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle;
190        pSrcErrorCorrectionType = &pVp8Dec->errorCorrectionType[INPUT_PORT_INDEX];
191
192        pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC;
193        pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync;
194        pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing;
195        pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning;
196        pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC;
197    }
198        break;
199    default:
200        ret = Exynos_OMX_VideoDecodeGetParameter(hComponent, nParamIndex, pComponentParameterStructure);
201        break;
202    }
203EXIT:
204    FunctionOut();
205
206    return ret;
207}
208
209OMX_ERRORTYPE Exynos_MFC_VP8Dec_SetParameter(
210    OMX_IN OMX_HANDLETYPE hComponent,
211    OMX_IN OMX_INDEXTYPE  nIndex,
212    OMX_IN OMX_PTR        pComponentParameterStructure)
213{
214    OMX_ERRORTYPE             ret              = OMX_ErrorNone;
215    OMX_COMPONENTTYPE        *pOMXComponent    = NULL;
216    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
217
218    FunctionIn();
219
220    if (hComponent == NULL || pComponentParameterStructure == NULL) {
221        ret = OMX_ErrorBadParameter;
222        goto EXIT;
223    }
224    pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
225    ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE));
226    if (ret != OMX_ErrorNone) {
227        goto EXIT;
228    }
229    if (pOMXComponent->pComponentPrivate == NULL) {
230        ret = OMX_ErrorBadParameter;
231        goto EXIT;
232    }
233
234    pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
235    if (pExynosComponent->currentState == OMX_StateInvalid ) {
236        ret = OMX_ErrorInvalidState;
237        goto EXIT;
238    }
239
240    switch (nIndex) {
241    case OMX_IndexParamStandardComponentRole:
242    {
243        OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)pComponentParameterStructure;
244
245        ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE));
246        if (ret != OMX_ErrorNone) {
247            goto EXIT;
248        }
249
250        if ((pExynosComponent->currentState != OMX_StateLoaded) && (pExynosComponent->currentState != OMX_StateWaitForResources)) {
251            ret = OMX_ErrorIncorrectStateOperation;
252            goto EXIT;
253        }
254
255        if (!Exynos_OSAL_Strcmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_VP8_DEC_ROLE)) {
256            pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingVPX;
257        } else {
258            ret = OMX_ErrorBadParameter;
259            goto EXIT;
260        }
261    }
262        break;
263    case OMX_IndexParamPortDefinition:
264    {
265        OMX_PARAM_PORTDEFINITIONTYPE *pPortDefinition = (OMX_PARAM_PORTDEFINITIONTYPE *)pComponentParameterStructure;
266        OMX_U32                       portIndex       = pPortDefinition->nPortIndex;
267        EXYNOS_OMX_BASEPORT          *pExynosPort;
268        OMX_U32                       width, height, size;
269        OMX_U32                       realWidth, realHeight;
270
271        if (portIndex >= pExynosComponent->portParam.nPorts) {
272            ret = OMX_ErrorBadPortIndex;
273            goto EXIT;
274        }
275        ret = Exynos_OMX_Check_SizeVersion(pPortDefinition, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
276        if (ret != OMX_ErrorNone) {
277            goto EXIT;
278        }
279
280        pExynosPort = &pExynosComponent->pExynosPort[portIndex];
281
282        if ((pExynosComponent->currentState != OMX_StateLoaded) && (pExynosComponent->currentState != OMX_StateWaitForResources)) {
283            if (pExynosPort->portDefinition.bEnabled == OMX_TRUE) {
284                ret = OMX_ErrorIncorrectStateOperation;
285                goto EXIT;
286            }
287        }
288        if (pPortDefinition->nBufferCountActual < pExynosPort->portDefinition.nBufferCountMin) {
289            ret = OMX_ErrorBadParameter;
290            goto EXIT;
291        }
292
293        Exynos_OSAL_Memcpy(&pExynosPort->portDefinition, pPortDefinition, pPortDefinition->nSize);
294
295        realWidth = pExynosPort->portDefinition.format.video.nFrameWidth;
296        realHeight = pExynosPort->portDefinition.format.video.nFrameHeight;
297        width = ((realWidth + 15) & (~15));
298        height = ((realHeight + 15) & (~15));
299        size = (width * height * 3) / 2;
300        pExynosPort->portDefinition.format.video.nStride = width;
301        pExynosPort->portDefinition.format.video.nSliceHeight = height;
302        pExynosPort->portDefinition.nBufferSize = (size > pExynosPort->portDefinition.nBufferSize) ? size : pExynosPort->portDefinition.nBufferSize;
303
304        if (portIndex == INPUT_PORT_INDEX) {
305            EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX];
306            pExynosOutputPort->portDefinition.format.video.nFrameWidth = pExynosPort->portDefinition.format.video.nFrameWidth;
307            pExynosOutputPort->portDefinition.format.video.nFrameHeight = pExynosPort->portDefinition.format.video.nFrameHeight;
308            pExynosOutputPort->portDefinition.format.video.nStride = width;
309            pExynosOutputPort->portDefinition.format.video.nSliceHeight = height;
310
311            switch (pExynosOutputPort->portDefinition.format.video.eColorFormat) {
312            case OMX_COLOR_FormatYUV420Planar:
313            case OMX_COLOR_FormatYUV420SemiPlanar:
314            case OMX_SEC_COLOR_FormatNV12TPhysicalAddress:
315            case OMX_SEC_COLOR_FormatANBYUV420SemiPlanar:
316                pExynosOutputPort->portDefinition.nBufferSize = (width * height * 3) / 2;
317                break;
318            case OMX_SEC_COLOR_FormatNV12Tiled:
319                pExynosOutputPort->portDefinition.nBufferSize =
320                    ALIGN_TO_8KB(ALIGN_TO_128B(realWidth) * ALIGN_TO_32B(realHeight)) \
321                  + ALIGN_TO_8KB(ALIGN_TO_128B(realWidth) * ALIGN_TO_32B(realHeight/2));
322                break;
323            default:
324                Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Color format is not support!! use default YUV size!!");
325                ret = OMX_ErrorUnsupportedSetting;
326                break;
327            }
328        }
329    }
330        break;
331    case OMX_IndexParamVideoErrorCorrection:
332    {
333        OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure;
334        OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = NULL;
335        EXYNOS_VP8DEC_HANDLE                *pVp8Dec                 = NULL;
336
337        ret = Exynos_OMX_Check_SizeVersion(pSrcErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE));
338        if (ret != OMX_ErrorNone) {
339            goto EXIT;
340        }
341
342        if (pSrcErrorCorrectionType->nPortIndex != INPUT_PORT_INDEX) {
343            ret = OMX_ErrorBadPortIndex;
344            goto EXIT;
345        }
346
347        pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle;
348        pDstErrorCorrectionType = &pVp8Dec->errorCorrectionType[INPUT_PORT_INDEX];
349
350        pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC;
351        pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync;
352        pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing;
353        pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning;
354        pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC;
355    }
356        break;
357    default:
358        ret = Exynos_OMX_VideoDecodeSetParameter(hComponent, nIndex, pComponentParameterStructure);
359        break;
360    }
361EXIT:
362    FunctionOut();
363
364    return ret;
365}
366
367OMX_ERRORTYPE Exynos_MFC_VP8Dec_GetConfig(
368    OMX_HANDLETYPE hComponent,
369    OMX_INDEXTYPE  nIndex,
370    OMX_PTR        pComponentConfigStructure)
371{
372    OMX_ERRORTYPE             ret              = OMX_ErrorNone;
373    OMX_COMPONENTTYPE        *pOMXComponent    = NULL;
374    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
375
376    FunctionIn();
377
378    if (hComponent == NULL) {
379        ret = OMX_ErrorBadParameter;
380        goto EXIT;
381    }
382    pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
383    ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE));
384    if (ret != OMX_ErrorNone) {
385        goto EXIT;
386    }
387
388    if (pOMXComponent->pComponentPrivate == NULL) {
389        ret = OMX_ErrorBadParameter;
390        goto EXIT;
391    }
392    pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
393
394    if (pComponentConfigStructure == NULL) {
395        ret = OMX_ErrorBadParameter;
396        goto EXIT;
397    }
398    if (pExynosComponent->currentState == OMX_StateInvalid) {
399        ret = OMX_ErrorInvalidState;
400        goto EXIT;
401    }
402
403    switch (nIndex) {
404    default:
405        ret = Exynos_OMX_VideoDecodeGetConfig(hComponent, nIndex, pComponentConfigStructure);
406        break;
407    }
408
409EXIT:
410    FunctionOut();
411
412    return ret;
413}
414
415OMX_ERRORTYPE Exynos_MFC_VP8Dec_SetConfig(
416    OMX_HANDLETYPE hComponent,
417    OMX_INDEXTYPE  nIndex,
418    OMX_PTR        pComponentConfigStructure)
419{
420    OMX_ERRORTYPE             ret              = OMX_ErrorNone;
421    OMX_COMPONENTTYPE        *pOMXComponent    = NULL;
422    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
423
424    FunctionIn();
425
426    if (hComponent == NULL) {
427        ret = OMX_ErrorBadParameter;
428        goto EXIT;
429    }
430    pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
431    ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE));
432    if (ret != OMX_ErrorNone) {
433        goto EXIT;
434    }
435
436    if (pOMXComponent->pComponentPrivate == NULL) {
437        ret = OMX_ErrorBadParameter;
438        goto EXIT;
439    }
440    pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
441
442    if (pComponentConfigStructure == NULL) {
443        ret = OMX_ErrorBadParameter;
444        goto EXIT;
445    }
446    if (pExynosComponent->currentState == OMX_StateInvalid) {
447        ret = OMX_ErrorInvalidState;
448        goto EXIT;
449    }
450
451    switch (nIndex) {
452    default:
453        ret = Exynos_OMX_VideoDecodeSetConfig(hComponent, nIndex, pComponentConfigStructure);
454        break;
455    }
456
457EXIT:
458    FunctionOut();
459
460    return ret;
461}
462
463OMX_ERRORTYPE Exynos_MFC_VP8Dec_GetExtensionIndex(
464    OMX_IN  OMX_HANDLETYPE  hComponent,
465    OMX_IN  OMX_STRING      cParameterName,
466    OMX_OUT OMX_INDEXTYPE   *pIndexType)
467{
468    OMX_ERRORTYPE             ret              = OMX_ErrorNone;
469    OMX_COMPONENTTYPE        *pOMXComponent    = NULL;
470    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
471
472    FunctionIn();
473
474    if (hComponent == NULL) {
475        ret = OMX_ErrorBadParameter;
476        goto EXIT;
477    }
478    pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
479    ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE));
480    if (ret != OMX_ErrorNone) {
481        goto EXIT;
482    }
483
484    if (pOMXComponent->pComponentPrivate == NULL) {
485        ret = OMX_ErrorBadParameter;
486        goto EXIT;
487    }
488    pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
489
490    if ((cParameterName == NULL) || (pIndexType == NULL)) {
491        ret = OMX_ErrorBadParameter;
492        goto EXIT;
493    }
494    if (pExynosComponent->currentState == OMX_StateInvalid) {
495        ret = OMX_ErrorInvalidState;
496        goto EXIT;
497    }
498
499    if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_ENABLE_THUMBNAIL) == 0) {
500        EXYNOS_VP8DEC_HANDLE *pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle;
501
502        *pIndexType = OMX_IndexVendorThumbnailMode;
503
504        ret = OMX_ErrorNone;
505    } else {
506        ret = Exynos_OMX_VideoDecodeGetExtensionIndex(hComponent, cParameterName, pIndexType);
507    }
508
509EXIT:
510    FunctionOut();
511
512    return ret;
513}
514
515OMX_ERRORTYPE Exynos_MFC_VP8Dec_ComponentRoleEnum(
516    OMX_HANDLETYPE hComponent,
517    OMX_U8        *cRole,
518    OMX_U32        nIndex)
519{
520    OMX_ERRORTYPE             ret              = OMX_ErrorNone;
521    OMX_COMPONENTTYPE        *pOMXComponent    = NULL;
522    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
523
524    FunctionIn();
525
526    if ((hComponent == NULL) || (cRole == NULL)) {
527        ret = OMX_ErrorBadParameter;
528        goto EXIT;
529    }
530    if (nIndex == (MAX_COMPONENT_ROLE_NUM-1)) {
531        Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_VP8_DEC_ROLE);
532        ret = OMX_ErrorNone;
533    } else {
534        ret = OMX_ErrorNoMore;
535    }
536
537EXIT:
538    FunctionOut();
539
540    return ret;
541}
542
543OMX_ERRORTYPE Exynos_MFC_DecodeThread(
544    OMX_HANDLETYPE hComponent)
545{
546    OMX_ERRORTYPE                  ret              = OMX_ErrorNone;
547    OMX_COMPONENTTYPE             *pOMXComponent    = (OMX_COMPONENTTYPE *)hComponent;
548    EXYNOS_OMX_BASECOMPONENT      *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
549    EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec        = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
550    EXYNOS_VP8DEC_HANDLE          *pVp8Dec          = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle;
551    ExynosVideoDecOps             *pDecOps          = pVideoDec->pDecOps;
552    ExynosVideoDecBufferOps       *pInbufOps        = pVideoDec->pInbufOps;
553    ExynosVideoDecBufferOps       *pOutbufOps       = pVideoDec->pOutbufOps;
554
555    FunctionIn();
556
557    if (hComponent == NULL) {
558        ret = OMX_ErrorBadParameter;
559        goto EXIT;
560    }
561
562    while (pVideoDec->NBDecThread.bExitDecodeThread == OMX_FALSE) {
563        Exynos_OSAL_SemaphoreWait(pVideoDec->NBDecThread.hDecFrameStart);
564
565        if (pVideoDec->NBDecThread.bExitDecodeThread == OMX_FALSE) {
566#ifdef CONFIG_MFC_FPS
567            Exynos_OSAL_PerfStart(PERF_ID_DEC);
568#endif
569            if (pVideoDec->NBDecThread.oneFrameSize > 0) {
570                /* queue work for input buffer */
571                pInbufOps->Enqueue(pVp8Dec->hMFCVp8Handle.hMFCHandle,
572                                  (unsigned char **)&pVp8Dec->hMFCVp8Handle.pMFCStreamBuffer,
573                                  (unsigned int *)&pVideoDec->NBDecThread.oneFrameSize,
574                                   1, NULL);
575
576                pVideoDec->indexInputBuffer++;
577                pVideoDec->indexInputBuffer %= MFC_INPUT_BUFFER_NUM_MAX;
578                pVp8Dec->hMFCVp8Handle.pMFCStreamBuffer    = pVideoDec->MFCDecInputBuffer[pVideoDec->indexInputBuffer].VirAddr;
579                pVp8Dec->hMFCVp8Handle.pMFCStreamPhyBuffer = pVideoDec->MFCDecInputBuffer[pVideoDec->indexInputBuffer].PhyAddr;
580                pExynosComponent->processData[INPUT_PORT_INDEX].dataBuffer = pVideoDec->MFCDecInputBuffer[pVideoDec->indexInputBuffer].VirAddr;
581                pExynosComponent->processData[INPUT_PORT_INDEX].allocSize = pVideoDec->MFCDecInputBuffer[pVideoDec->indexInputBuffer].bufferSize;
582
583                pInbufOps->Dequeue(pVp8Dec->hMFCVp8Handle.hMFCHandle);
584                pVideoDec->pOutbuf = pOutbufOps->Dequeue(pVp8Dec->hMFCVp8Handle.hMFCHandle);
585            }
586
587            pVp8Dec->hMFCVp8Handle.returnCodec = VIDEO_TRUE;
588#ifdef CONFIG_MFC_FPS
589            Exynos_OSAL_PerfStop(PERF_ID_DEC);
590#endif
591            Exynos_OSAL_SemaphorePost(pVideoDec->NBDecThread.hDecFrameEnd);
592        }
593    }
594
595EXIT:
596    Exynos_OSAL_ThreadExit(NULL);
597    FunctionOut();
598
599    return ret;
600}
601
602/* MFC Init */
603OMX_ERRORTYPE Exynos_MFC_VP8Dec_Init(
604    OMX_COMPONENTTYPE *pOMXComponent)
605{
606    OMX_ERRORTYPE                  ret               = OMX_ErrorNone;
607    EXYNOS_OMX_BASECOMPONENT      *pExynosComponent  = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
608    EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec         = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
609    EXYNOS_OMX_BASEPORT           *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX];
610    EXYNOS_VP8DEC_HANDLE          *pVp8Dec           = NULL;
611    OMX_PTR                        hMFCHandle        = NULL;
612    OMX_PTR                        pStreamBuffer     = NULL;
613    OMX_PTR                        pStreamPhyBuffer  = NULL;
614    ExynosVideoDecOps             *pDecOps           = NULL;
615    ExynosVideoDecBufferOps       *pInbufOps         = NULL;
616    ExynosVideoDecBufferOps       *pOutbufOps        = NULL;
617    ExynosVideoBuffer              bufferInfo;
618    ExynosVideoGeometry            bufferConf;
619
620    CSC_METHOD csc_method = CSC_METHOD_SW;
621    int i = 0;
622
623    FunctionIn();
624
625#ifdef CONFIG_MFC_FPS
626    Exynos_OSAL_PerfInit(PERF_ID_DEC);
627    Exynos_OSAL_PerfInit(PERF_ID_CSC);
628#endif
629
630    pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle;
631    pVp8Dec->hMFCVp8Handle.bConfiguredMFC = OMX_FALSE;
632    pExynosComponent->bUseFlagEOF = OMX_FALSE;
633    pExynosComponent->bSaveFlagEOS = OMX_FALSE;
634
635    /* alloc ops structure */
636    pDecOps = (ExynosVideoDecOps *)malloc(sizeof(*pDecOps));
637    pInbufOps = (ExynosVideoDecBufferOps *)malloc(sizeof(*pInbufOps));
638    pOutbufOps = (ExynosVideoDecBufferOps *)malloc(sizeof(*pOutbufOps));
639
640    if ((pDecOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) {
641        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to allocate decoder ops buffer");
642        ret = OMX_ErrorInsufficientResources;
643        goto EXIT;
644    }
645
646    pVideoDec->pDecOps = pDecOps;
647    pVideoDec->pInbufOps = pInbufOps;
648    pVideoDec->pOutbufOps = pOutbufOps;
649
650    /* function pointer mapping */
651    pDecOps->nSize = sizeof(*pDecOps);
652    pInbufOps->nSize = sizeof(*pInbufOps);
653    pOutbufOps->nSize = sizeof(*pOutbufOps);
654
655    Exynos_Video_Register_Decoder(pDecOps, pInbufOps, pOutbufOps);
656
657    /* check mandatory functions for decoder ops */
658    if ((pDecOps->Init == NULL) || (pDecOps->Finalize == NULL) ||
659        (pDecOps->Get_ActualBufferCount == NULL) || (pDecOps->Set_FrameTag == NULL) ||
660        (pDecOps->Get_FrameTag == NULL)) {
661        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Mandatory functions must be supplied");
662        ret = OMX_ErrorInsufficientResources;
663        goto EXIT;
664    }
665
666    /* check mandatory functions for buffer ops */
667    if ((pInbufOps->Setup == NULL) || (pOutbufOps->Setup == NULL) ||
668        (pInbufOps->Run == NULL) || (pOutbufOps->Run == NULL) ||
669        (pInbufOps->Stop == NULL) || (pOutbufOps->Stop == NULL) ||
670        (pInbufOps->Enqueue == NULL) || (pOutbufOps->Enqueue == NULL) ||
671        (pInbufOps->Dequeue == NULL) || (pOutbufOps->Dequeue == NULL)) {
672        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Mandatory functions must be supplied");
673        ret = OMX_ErrorInsufficientResources;
674        goto EXIT;
675    }
676
677    /* alloc context, open, querycap */
678    pVp8Dec->hMFCVp8Handle.hMFCHandle = pVideoDec->pDecOps->Init();
679    if (pVp8Dec->hMFCVp8Handle.hMFCHandle == NULL) {
680        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to allocate context buffer");
681        ret = OMX_ErrorInsufficientResources;
682        goto EXIT;
683    }
684
685    Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf));
686
687    /* input buffer info: only 2 config values needed */
688    bufferConf.nSizeImage = DEFAULT_MFC_INPUT_BUFFER_SIZE / 2;
689    bufferConf.eCompressionFormat = VIDEO_CODING_VP8;
690
691    /* set input buffer geometry */
692    if (pInbufOps->Set_Geometry) {
693        if (pInbufOps->Set_Geometry(pVp8Dec->hMFCVp8Handle.hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) {
694            Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to set geometry for input buffer");
695            ret = OMX_ErrorInsufficientResources;
696            goto EXIT;
697        }
698    }
699
700    /* setup input buffer */
701    if (pInbufOps->Setup(pVp8Dec->hMFCVp8Handle.hMFCHandle, MFC_INPUT_BUFFER_NUM_MAX) != VIDEO_ERROR_NONE) {
702        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup input buffer");
703        ret = OMX_ErrorInsufficientResources;
704        goto EXIT;
705    }
706
707    /* get input buffer info */
708    for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) {
709        Exynos_OSAL_Memset(&bufferInfo, 0, sizeof(bufferInfo));
710
711        if (pInbufOps->Get_BufferInfo) {
712           if (pInbufOps->Get_BufferInfo(pVp8Dec->hMFCVp8Handle.hMFCHandle, i, &bufferInfo) != VIDEO_ERROR_NONE) {
713               Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to get input buffer info");
714               ret = OMX_ErrorInsufficientResources;
715               goto EXIT;
716           }
717        }
718
719        pVideoDec->MFCDecInputBuffer[i].VirAddr = (void *)bufferInfo.planes[0].addr;
720        pVideoDec->MFCDecInputBuffer[i].PhyAddr = NULL;
721        pVideoDec->MFCDecInputBuffer[i].bufferSize = bufferInfo.planes[0].allocSize;
722        pVideoDec->MFCDecInputBuffer[i].dataSize = 0;
723    }
724
725    pVideoDec->indexInputBuffer = 0;
726    pVideoDec->bFirstFrame = OMX_TRUE;
727
728    pVideoDec->NBDecThread.bExitDecodeThread = OMX_FALSE;
729    pVideoDec->NBDecThread.bDecoderRun = OMX_FALSE;
730    pVideoDec->NBDecThread.oneFrameSize = 0;
731    Exynos_OSAL_SemaphoreCreate(&(pVideoDec->NBDecThread.hDecFrameStart));
732    Exynos_OSAL_SemaphoreCreate(&(pVideoDec->NBDecThread.hDecFrameEnd));
733    if (OMX_ErrorNone == Exynos_OSAL_ThreadCreate(&pVideoDec->NBDecThread.hNBDecodeThread,
734                                                Exynos_MFC_DecodeThread,
735                                                pOMXComponent)) {
736        pVp8Dec->hMFCVp8Handle.returnCodec = VIDEO_TRUE;
737    }
738
739    pVp8Dec->hMFCVp8Handle.pMFCStreamBuffer    = pVideoDec->MFCDecInputBuffer[0].VirAddr;
740    pVp8Dec->hMFCVp8Handle.pMFCStreamPhyBuffer = pVideoDec->MFCDecInputBuffer[0].PhyAddr;
741    pExynosComponent->processData[INPUT_PORT_INDEX].dataBuffer = pVideoDec->MFCDecInputBuffer[0].VirAddr;
742    pExynosComponent->processData[INPUT_PORT_INDEX].allocSize = pVideoDec->MFCDecInputBuffer[0].bufferSize;
743
744    Exynos_OSAL_Memset(pExynosComponent->timeStamp, -19771003, sizeof(OMX_TICKS) * MAX_TIMESTAMP);
745    Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS);
746    pVp8Dec->hMFCVp8Handle.indexTimestamp = 0;
747    pVp8Dec->hMFCVp8Handle.outputIndexTimestamp = 0;
748
749    pExynosComponent->getAllDelayBuffer = OMX_FALSE;
750
751#ifdef USE_ANB
752#if defined(USE_CSC_FIMC) || defined(USE_CSC_GSCALER)
753    if (pExynosOutputPort->bIsANBEnabled == OMX_TRUE) {
754        csc_method = CSC_METHOD_PREFER_HW;
755    }
756#endif
757#endif
758    pVideoDec->csc_handle = csc_init(&csc_method);
759    pVideoDec->csc_set_format = OMX_FALSE;
760
761EXIT:
762    FunctionOut();
763
764    return ret;
765}
766
767/* MFC Terminate */
768OMX_ERRORTYPE Exynos_MFC_VP8Dec_Terminate(
769    OMX_COMPONENTTYPE *pOMXComponent)
770{
771    OMX_ERRORTYPE                  ret              = OMX_ErrorNone;
772    EXYNOS_OMX_BASECOMPONENT      *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
773    EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec        = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
774    EXYNOS_VP8DEC_HANDLE          *pVp8Dec          = NULL;
775    OMX_PTR                        hMFCHandle       = NULL;
776    ExynosVideoDecOps             *pDecOps          = pVideoDec->pDecOps;
777    ExynosVideoDecBufferOps       *pInbufOps        = pVideoDec->pInbufOps;
778    ExynosVideoDecBufferOps       *pOutbufOps       = pVideoDec->pOutbufOps;
779
780    FunctionIn();
781
782#ifdef CONFIG_MFC_FPS
783    Exynos_OSAL_PerfPrint("[DEC]",  PERF_ID_DEC);
784    Exynos_OSAL_PerfPrint("[CSC]",  PERF_ID_CSC);
785#endif
786
787    pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle;
788    hMFCHandle = pVp8Dec->hMFCVp8Handle.hMFCHandle;
789
790    pVp8Dec->hMFCVp8Handle.pMFCStreamBuffer    = NULL;
791    pVp8Dec->hMFCVp8Handle.pMFCStreamPhyBuffer = NULL;
792    pExynosComponent->processData[INPUT_PORT_INDEX].dataBuffer = NULL;
793    pExynosComponent->processData[INPUT_PORT_INDEX].allocSize = 0;
794
795    if (pVideoDec->NBDecThread.hNBDecodeThread != NULL) {
796        pVideoDec->NBDecThread.bExitDecodeThread = OMX_TRUE;
797        Exynos_OSAL_SemaphorePost(pVideoDec->NBDecThread.hDecFrameStart);
798        Exynos_OSAL_ThreadTerminate(pVideoDec->NBDecThread.hNBDecodeThread);
799        pVideoDec->NBDecThread.hNBDecodeThread = NULL;
800    }
801
802    if(pVideoDec->NBDecThread.hDecFrameEnd != NULL) {
803        Exynos_OSAL_SemaphoreTerminate(pVideoDec->NBDecThread.hDecFrameEnd);
804        pVideoDec->NBDecThread.hDecFrameEnd = NULL;
805    }
806
807    if(pVideoDec->NBDecThread.hDecFrameStart != NULL) {
808        Exynos_OSAL_SemaphoreTerminate(pVideoDec->NBDecThread.hDecFrameStart);
809        pVideoDec->NBDecThread.hDecFrameStart = NULL;
810    }
811
812    if (hMFCHandle != NULL) {
813        pInbufOps->Stop(hMFCHandle);
814        pOutbufOps->Stop(hMFCHandle);
815        pDecOps->Finalize(hMFCHandle);
816
817        free(pInbufOps);
818        free(pOutbufOps);
819        free(pDecOps);
820
821        pVp8Dec->hMFCVp8Handle.hMFCHandle = NULL;
822    }
823
824    if (pVideoDec->csc_handle != NULL) {
825        csc_deinit(pVideoDec->csc_handle);
826        pVideoDec->csc_handle = NULL;
827    }
828
829EXIT:
830    FunctionOut();
831
832    return ret;
833}
834
835OMX_ERRORTYPE Exynos_MFC_VP8_Decode_Configure(
836    OMX_COMPONENTTYPE   *pOMXComponent,
837    EXYNOS_OMX_DATA     *pInputData,
838    EXYNOS_OMX_DATA     *pOutputData)
839{
840    OMX_ERRORTYPE                  ret               = OMX_ErrorNone;
841    EXYNOS_OMX_BASECOMPONENT      *pExynosComponent  = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
842    EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec         = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
843    EXYNOS_VP8DEC_HANDLE          *pVp8Dec           = (EXYNOS_VP8DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle;
844    OMX_HANDLETYPE                 hMFCHandle        = pVp8Dec->hMFCVp8Handle.hMFCHandle;
845    EXYNOS_OMX_BASEPORT           *pExynosInputPort  = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX];
846    EXYNOS_OMX_BASEPORT           *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX];
847    OMX_U32                        oneFrameSize      = pInputData->dataLen;
848    OMX_S32                        setConfVal        = 0;
849    ExynosVideoDecOps             *pDecOps           = pVideoDec->pDecOps;
850    ExynosVideoDecBufferOps       *pInbufOps         = pVideoDec->pInbufOps;
851    ExynosVideoDecBufferOps       *pOutbufOps        = pVideoDec->pOutbufOps;
852    ExynosVideoGeometry            bufferConf;
853
854    int i, nOutbufs;
855
856    FunctionIn();
857
858    if ((oneFrameSize <= 0) && (pInputData->nFlags & OMX_BUFFERFLAG_EOS)) {
859        pOutputData->timeStamp = pInputData->timeStamp;
860        pOutputData->nFlags = pInputData->nFlags;
861        ret = OMX_ErrorNone;
862        goto EXIT;
863    }
864
865    if (pDecOps->Set_DisplayDelay && (pVideoDec->bThumbnailMode == OMX_TRUE)) {
866        setConfVal = 0;
867        pDecOps->Set_DisplayDelay(hMFCHandle, setConfVal);
868    }
869
870    Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf));
871
872    /* set geometry for dest */
873    if (pOutbufOps->Set_Geometry) {
874        /* only output color format is needed to set */
875        bufferConf.eColorFormat = VIDEO_COLORFORMAT_NV12_TILED;
876        if (pOutbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) {
877            Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to set geometry for output buffer");
878            ret = OMX_ErrorInsufficientResources;
879            goto EXIT;
880        }
881    }
882
883    /* input buffer enqueue for header parsing */
884    if (pInbufOps->Enqueue(hMFCHandle,
885                          (unsigned char **)&pVp8Dec->hMFCVp8Handle.pMFCStreamBuffer,
886                          (unsigned int *)&oneFrameSize, 1, NULL) != VIDEO_ERROR_NONE) {
887        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to enqueue input buffer for header parsing");
888        ret = OMX_ErrorInsufficientResources;
889        goto EXIT;
890    }
891
892    /* start header parsing */
893    if (pInbufOps->Run(hMFCHandle) != VIDEO_ERROR_NONE) {
894        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to run input buffer for header parsing");
895        ret = OMX_ErrorInsufficientResources;
896        goto EXIT;
897    }
898
899    Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf));
900
901    /* get geometry for output */
902    if (pOutbufOps->Get_Geometry) {
903        if (pOutbufOps->Get_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) {
904            Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to get geometry for parsed header info");
905            ret = OMX_ErrorInsufficientResources;
906            goto EXIT;
907        }
908    }
909
910    if ((pExynosInputPort->portDefinition.format.video.nFrameWidth != bufferConf.nFrameWidth) ||
911        (pExynosInputPort->portDefinition.format.video.nFrameHeight != bufferConf.nFrameHeight)) {
912        pExynosInputPort->portDefinition.format.video.nFrameWidth = bufferConf.nFrameWidth;
913        pExynosInputPort->portDefinition.format.video.nFrameHeight = bufferConf.nFrameHeight;
914        pExynosInputPort->portDefinition.format.video.nStride = ((bufferConf.nFrameWidth + 15) & (~15));
915        pExynosInputPort->portDefinition.format.video.nSliceHeight = ((bufferConf.nFrameHeight + 15) & (~15));
916
917        Exynos_UpdateFrameSize(pOMXComponent);
918
919        /** Send Port Settings changed call back **/
920        (*(pExynosComponent->pCallbacks->EventHandler))
921            (pOMXComponent,
922             pExynosComponent->callbackData,
923             OMX_EventPortSettingsChanged, /* The command was completed */
924             OMX_DirOutput, /* This is the port index */
925             0,
926             NULL);
927    }
928
929    /* should be done before prepare output buffer */
930    if (pExynosOutputPort->portDefinition.format.video.eColorFormat != OMX_SEC_COLOR_FormatNV12TPhysicalAddress) {
931        if (pVideoDec->pDecOps->Enable_Cacheable) {
932            if (pVideoDec->pDecOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) {
933                ret = OMX_ErrorInsufficientResources;
934                goto EXIT;
935            }
936        }
937    }
938
939    /* get dpb count */
940    nOutbufs = pDecOps->Get_ActualBufferCount(hMFCHandle);
941    if (nOutbufs < 0) {
942        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Invalid DPB count");
943        ret = OMX_ErrorInsufficientResources;
944        goto EXIT;
945    }
946
947    if (pVideoDec->bThumbnailMode == OMX_FALSE)
948        nOutbufs += VP8_DEC_NUM_OF_EXTRA_BUFFERS;
949
950    if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) {
951        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer");
952        ret = OMX_ErrorInsufficientResources;
953        goto EXIT;
954    }
955
956    if (pOutbufOps->Enqueue_All) {
957        if (pOutbufOps->Enqueue_All(hMFCHandle) != VIDEO_ERROR_NONE) {
958            Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to flush all output buffer");
959            ret = OMX_ErrorInsufficientResources;
960            goto EXIT;
961        }
962    }
963
964    if (pOutbufOps->Run(hMFCHandle) != VIDEO_ERROR_NONE) {
965        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to run output buffer");
966        ret = OMX_ErrorInsufficientResources;
967        goto EXIT;
968    }
969
970    if (pInbufOps->Dequeue(hMFCHandle) == NULL) {
971        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to wait input buffer");
972        ret = OMX_ErrorInsufficientResources;
973        goto EXIT;
974    }
975
976    pVp8Dec->hMFCVp8Handle.bConfiguredMFC = OMX_TRUE;
977    pVp8Dec->hMFCVp8Handle.returnCodec = VIDEO_TRUE;
978    pOutputData->timeStamp = pInputData->timeStamp;
979    pOutputData->nFlags = pInputData->nFlags;
980
981    ret = OMX_ErrorInputDataDecodeYet;
982
983EXIT:
984    FunctionOut();
985    return ret;
986}
987OMX_ERRORTYPE Exynos_MFC_VP8_Decode_Nonblock(
988    OMX_COMPONENTTYPE   *pOMXComponent,
989    EXYNOS_OMX_DATA     *pInputData,
990    EXYNOS_OMX_DATA     *pOutputData)
991{
992    OMX_ERRORTYPE                  ret               = OMX_ErrorNone;
993    EXYNOS_OMX_BASECOMPONENT      *pExynosComponent  = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
994    EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec         = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
995    EXYNOS_VP8DEC_HANDLE          *pVp8Dec           = (EXYNOS_VP8DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle;
996    EXYNOS_OMX_BASEPORT           *pExynosInputPort  = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX];
997    EXYNOS_OMX_BASEPORT           *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX];
998    OMX_HANDLETYPE                 hMFCHandle        = pVp8Dec->hMFCVp8Handle.hMFCHandle;
999    OMX_U32                        oneFrameSize      = pInputData->dataLen;
1000    OMX_S32                        setConfVal        = 0;
1001    OMX_U32                        FrameBufferYSize  = 0;
1002    OMX_U32                        FrameBufferUVSize = 0;
1003    OMX_BOOL                       outputDataValid   = OMX_FALSE;
1004    ExynosVideoDecOps             *pDecOps           = pVideoDec->pDecOps;
1005    ExynosVideoDecBufferOps       *pInbufOps         = pVideoDec->pInbufOps;
1006    ExynosVideoDecBufferOps       *pOutbufOps        = pVideoDec->pOutbufOps;
1007
1008    OMX_PTR outputYPhyAddr, outputCPhyAddr, outputYVirAddr, outputCVirAddr;
1009    int bufWidth, bufHeight, outputImgWidth, outputImgHeight;
1010
1011    FunctionIn();
1012
1013    if (pVp8Dec->hMFCVp8Handle.bConfiguredMFC == OMX_FALSE) {
1014        ret = Exynos_MFC_VP8_Decode_Configure(pOMXComponent, pInputData, pOutputData);
1015        goto EXIT;
1016    }
1017
1018#ifndef FULL_FRAME_SEARCH
1019    if ((pInputData->nFlags & OMX_BUFFERFLAG_ENDOFFRAME) &&
1020        (pExynosComponent->bUseFlagEOF == OMX_FALSE))
1021        pExynosComponent->bUseFlagEOF = OMX_TRUE;
1022#endif
1023
1024    pExynosComponent->timeStamp[pVp8Dec->hMFCVp8Handle.indexTimestamp] = pInputData->timeStamp;
1025    pExynosComponent->nFlags[pVp8Dec->hMFCVp8Handle.indexTimestamp] = pInputData->nFlags;
1026
1027    if (pVideoDec->bFirstFrame == OMX_FALSE) {
1028        ExynosVideoFrameStatusType status = VIDEO_FRAME_STATUS_UNKNOWN;
1029        OMX_S32 indexTimestamp = 0;
1030
1031        /* wait for mfc decode done */
1032        if (pVideoDec->NBDecThread.bDecoderRun == OMX_TRUE) {
1033            Exynos_OSAL_SemaphoreWait(pVideoDec->NBDecThread.hDecFrameEnd);
1034            pVideoDec->NBDecThread.bDecoderRun = OMX_FALSE;
1035        }
1036
1037        Exynos_OSAL_SleepMillisec(0);
1038
1039        if (pVideoDec->pOutbuf != NULL) {
1040            status = pVideoDec->pOutbuf->displayStatus;
1041            outputYVirAddr = pVideoDec->pOutbuf->planes[0].addr;
1042            outputCVirAddr = pVideoDec->pOutbuf->planes[1].addr;
1043        }
1044
1045        outputImgWidth = pExynosInputPort->portDefinition.format.video.nFrameWidth;
1046        outputImgHeight = pExynosInputPort->portDefinition.format.video.nFrameHeight;
1047
1048        bufWidth = (outputImgWidth + 15) & (~15);
1049        bufHeight = (outputImgHeight + 15) & (~15);
1050        FrameBufferYSize = ALIGN_TO_8KB(ALIGN_TO_128B(outputImgWidth) * ALIGN_TO_32B(outputImgHeight));
1051        FrameBufferUVSize = ALIGN_TO_8KB(ALIGN_TO_128B(outputImgWidth) * ALIGN_TO_32B(outputImgHeight/2));
1052
1053        indexTimestamp = pDecOps->Get_FrameTag(hMFCHandle);
1054        if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) {
1055            pOutputData->timeStamp = pInputData->timeStamp;
1056            pOutputData->nFlags = pInputData->nFlags;
1057        } else {
1058            /* For timestamp correction. if mfc support frametype detect */
1059            Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "disp_pic_frame_type: %d", pVideoDec->pOutbuf->frameType);
1060#ifdef NEED_TIMESTAMP_REORDER
1061            if (pVideoDec->pOutbuf->frameType == VIDEO_FRAME_I) {
1062                pOutputData->timeStamp = pExynosComponent->timeStamp[indexTimestamp];
1063                pOutputData->nFlags = pExynosComponent->nFlags[indexTimestamp];
1064                pVp8Dec->hMFCVp8Handle.outputIndexTimestamp = indexTimestamp;
1065            } else {
1066                pOutputData->timeStamp = pExynosComponent->timeStamp[pVp8Dec->hMFCVp8Handle.outputIndexTimestamp];
1067                pOutputData->nFlags = pExynosComponent->nFlags[pVp8Dec->hMFCVp8Handle.outputIndexTimestamp];
1068            }
1069#else
1070            pOutputData->timeStamp = pExynosComponent->timeStamp[indexTimestamp];
1071            pOutputData->nFlags = pExynosComponent->nFlags[indexTimestamp];
1072#endif
1073            Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "timestamp %lld us (%.2f secs)", pOutputData->timeStamp, pOutputData->timeStamp / 1E6);
1074        }
1075
1076        if ((status == VIDEO_FRAME_STATUS_DISPLAY_DECODING) ||
1077            (status == VIDEO_FRAME_STATUS_DISPLAY_ONLY)) {
1078            outputDataValid = OMX_TRUE;
1079            pVp8Dec->hMFCVp8Handle.outputIndexTimestamp++;
1080            pVp8Dec->hMFCVp8Handle.outputIndexTimestamp %= MAX_TIMESTAMP;
1081        }
1082        if (pOutputData->nFlags & OMX_BUFFERFLAG_EOS)
1083            outputDataValid = OMX_FALSE;
1084
1085        if ((status == VIDEO_FRAME_STATUS_DISPLAY_ONLY) ||
1086            (pExynosComponent->getAllDelayBuffer == OMX_TRUE))
1087            ret = OMX_ErrorInputDataDecodeYet;
1088
1089        if (status == VIDEO_FRAME_STATUS_DECODING_ONLY) {
1090            if (((pInputData->nFlags & OMX_BUFFERFLAG_EOS) != OMX_BUFFERFLAG_EOS) &&
1091                ((pExynosComponent->bSaveFlagEOS == OMX_TRUE) || (pExynosComponent->getAllDelayBuffer == OMX_TRUE))) {
1092                pInputData->nFlags |= OMX_BUFFERFLAG_EOS;
1093                pExynosComponent->getAllDelayBuffer = OMX_TRUE;
1094                ret = OMX_ErrorInputDataDecodeYet;
1095            } else {
1096                ret = OMX_ErrorNone;
1097            }
1098            outputDataValid = OMX_FALSE;
1099        }
1100
1101#ifdef FULL_FRAME_SEARCH
1102        if (((pInputData->nFlags & OMX_BUFFERFLAG_EOS) != OMX_BUFFERFLAG_EOS) &&
1103            (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) {
1104            pInputData->nFlags |= OMX_BUFFERFLAG_EOS;
1105            pExynosComponent->getAllDelayBuffer = OMX_TRUE;
1106            ret = OMX_ErrorInputDataDecodeYet;
1107        } else
1108#endif
1109        if ((pInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) {
1110            pInputData->nFlags = (pOutputData->nFlags & (~OMX_BUFFERFLAG_EOS));
1111            pExynosComponent->getAllDelayBuffer = OMX_TRUE;
1112            ret = OMX_ErrorInputDataDecodeYet;
1113        } else if ((pOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) {
1114            pExynosComponent->getAllDelayBuffer = OMX_FALSE;
1115            ret = OMX_ErrorNone;
1116        }
1117    } else {
1118        pOutputData->timeStamp = pInputData->timeStamp;
1119        pOutputData->nFlags = pInputData->nFlags;
1120
1121        if ((pExynosComponent->bSaveFlagEOS == OMX_TRUE) ||
1122            (pExynosComponent->getAllDelayBuffer == OMX_TRUE) ||
1123            (pInputData->nFlags & OMX_BUFFERFLAG_EOS)) {
1124            pOutputData->nFlags |= OMX_BUFFERFLAG_EOS;
1125            pExynosComponent->getAllDelayBuffer = OMX_FALSE;
1126        }
1127
1128        if ((pVideoDec->bFirstFrame == OMX_TRUE) &&
1129            ((pOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) &&
1130            ((pInputData->nFlags & OMX_BUFFERFLAG_CODECCONFIG) != OMX_BUFFERFLAG_CODECCONFIG)) {
1131            pOutputData->nFlags = (pOutputData->nFlags & (~OMX_BUFFERFLAG_EOS));
1132        }
1133
1134        outputDataValid = OMX_FALSE;
1135
1136        /* ret = OMX_ErrorUndefined; */
1137        ret = OMX_ErrorNone;
1138    }
1139
1140    if (ret == OMX_ErrorInputDataDecodeYet) {
1141        pVideoDec->MFCDecInputBuffer[pVideoDec->indexInputBuffer].dataSize = oneFrameSize;
1142        pVideoDec->indexInputBuffer++;
1143        pVideoDec->indexInputBuffer %= MFC_INPUT_BUFFER_NUM_MAX;
1144        pVp8Dec->hMFCVp8Handle.pMFCStreamBuffer    = pVideoDec->MFCDecInputBuffer[pVideoDec->indexInputBuffer].VirAddr;
1145        pVp8Dec->hMFCVp8Handle.pMFCStreamPhyBuffer = pVideoDec->MFCDecInputBuffer[pVideoDec->indexInputBuffer].PhyAddr;
1146        pExynosComponent->processData[INPUT_PORT_INDEX].dataBuffer = pVideoDec->MFCDecInputBuffer[pVideoDec->indexInputBuffer].VirAddr;
1147        pExynosComponent->processData[INPUT_PORT_INDEX].allocSize = pVideoDec->MFCDecInputBuffer[pVideoDec->indexInputBuffer].bufferSize;
1148        oneFrameSize = pVideoDec->MFCDecInputBuffer[pVideoDec->indexInputBuffer].dataSize;
1149    }
1150
1151    if ((Check_VP8_StartCode(pInputData->dataBuffer, oneFrameSize) == OMX_TRUE) &&
1152        ((pOutputData->nFlags & OMX_BUFFERFLAG_EOS) != OMX_BUFFERFLAG_EOS)) {
1153        if ((ret != OMX_ErrorInputDataDecodeYet) || (pExynosComponent->getAllDelayBuffer == OMX_TRUE)) {
1154            pDecOps->Set_FrameTag(hMFCHandle, pVp8Dec->hMFCVp8Handle.indexTimestamp);
1155            pVp8Dec->hMFCVp8Handle.indexTimestamp++;
1156            pVp8Dec->hMFCVp8Handle.indexTimestamp %= MAX_TIMESTAMP;
1157        }
1158
1159        pVideoDec->MFCDecInputBuffer[pVideoDec->indexInputBuffer].dataSize = oneFrameSize;
1160        pVideoDec->NBDecThread.oneFrameSize = oneFrameSize;
1161
1162        /* mfc decode start */
1163        Exynos_OSAL_SemaphorePost(pVideoDec->NBDecThread.hDecFrameStart);
1164        pVideoDec->NBDecThread.bDecoderRun = OMX_TRUE;
1165        pVp8Dec->hMFCVp8Handle.returnCodec = VIDEO_TRUE;
1166
1167        Exynos_OSAL_SleepMillisec(0);
1168
1169        if ((pVideoDec->bFirstFrame == OMX_TRUE) &&
1170            (pExynosComponent->bSaveFlagEOS == OMX_TRUE) &&
1171            (outputDataValid == OMX_FALSE)) {
1172            ret = OMX_ErrorInputDataDecodeYet;
1173        }
1174
1175        pVideoDec->bFirstFrame = OMX_FALSE;
1176    } else {
1177        if (pExynosComponent->checkTimeStamp.needCheckStartTimeStamp == OMX_TRUE)
1178            pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_TRUE;
1179    }
1180
1181    /** Fill Output Buffer **/
1182    if (outputDataValid == OMX_TRUE) {
1183        void        *pOutputBuf = (void *)pOutputData->dataBuffer;
1184        void        *pSrcBuf[3] = {NULL, };
1185        void        *pYUVBuf[3] = {NULL, };
1186        unsigned int csc_src_color_format, csc_dst_color_format;
1187        CSC_METHOD   csc_method = CSC_METHOD_SW;
1188        unsigned int cacheable  = 1;
1189        int          frameSize  = bufWidth * bufHeight;
1190        int          width      = outputImgWidth;
1191        int          height     = outputImgHeight;
1192        int          imageSize  = outputImgWidth * outputImgHeight;
1193
1194        pSrcBuf[0] = outputYVirAddr;
1195        pSrcBuf[1] = outputCVirAddr;
1196
1197        pYUVBuf[0]  = (unsigned char *)pOutputBuf;
1198        pYUVBuf[1]  = (unsigned char *)pOutputBuf + imageSize;
1199        pYUVBuf[2]  = (unsigned char *)pOutputBuf + imageSize + imageSize / 4;
1200        pOutputData->dataLen = (imageSize * 3) / 2;
1201
1202#ifdef USE_ANB
1203        if (pExynosOutputPort->bIsANBEnabled == OMX_TRUE) {
1204            unsigned int stride;
1205            Exynos_OSAL_LockANB(pOutputData->dataBuffer, width, height, pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].portDefinition.format.video.eColorFormat, &stride, pYUVBuf);
1206            width = stride;
1207            pOutputData->dataLen = sizeof(void *);
1208         }
1209#endif
1210        if ((pVideoDec->bThumbnailMode == OMX_FALSE) &&
1211            (pExynosOutputPort->portDefinition.format.video.eColorFormat == OMX_SEC_COLOR_FormatNV12TPhysicalAddress)) {
1212            /* if use Post copy address structure */
1213            Exynos_OSAL_Memcpy(pYUVBuf[0], &(outputYPhyAddr), sizeof(outputYPhyAddr));
1214            Exynos_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 1), &(outputCPhyAddr), sizeof(outputCPhyAddr));
1215            Exynos_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 2), &(outputYVirAddr), sizeof(outputYVirAddr));
1216            Exynos_OSAL_Memcpy((unsigned char *)pYUVBuf[0] + (sizeof(void *) * 3), &(outputCVirAddr), sizeof(outputCVirAddr));
1217            pOutputData->dataLen = (width * height * 3) / 2;
1218        } else {
1219            Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "YUV420 SP/P Output mode");
1220#ifdef CONFIG_MFC_FPS
1221            Exynos_OSAL_PerfStart(PERF_ID_CSC);
1222#endif
1223            switch (pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].portDefinition.format.video.eColorFormat) {
1224            case OMX_SEC_COLOR_FormatNV12Tiled:
1225                Exynos_OSAL_Memcpy(pOutputBuf, outputYVirAddr, FrameBufferYSize);
1226                Exynos_OSAL_Memcpy((unsigned char *)pOutputBuf + FrameBufferYSize, outputCVirAddr, FrameBufferUVSize);
1227                pOutputData->dataLen = FrameBufferYSize + FrameBufferUVSize;
1228                break;
1229            case OMX_COLOR_FormatYUV420SemiPlanar:
1230            case OMX_SEC_COLOR_FormatANBYUV420SemiPlanar:
1231                csc_src_color_format = omx_2_hal_pixel_format((unsigned int)OMX_SEC_COLOR_FormatNV12Tiled);
1232                csc_dst_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420SemiPlanar);
1233                break;
1234            case OMX_COLOR_FormatYUV420Planar:
1235            default:
1236                csc_src_color_format = omx_2_hal_pixel_format((unsigned int)OMX_SEC_COLOR_FormatNV12Tiled);
1237                csc_dst_color_format = omx_2_hal_pixel_format((unsigned int)OMX_COLOR_FormatYUV420Planar);
1238                break;
1239            }
1240
1241            csc_get_method(pVideoDec->csc_handle, &csc_method);
1242#ifdef ENABLE_PHYSICAL_ADDRESS
1243            if ((pExynosOutputPort->bIsANBEnabled == OMX_TRUE) && (csc_method == CSC_METHOD_HW)) {
1244                Exynos_OSAL_GetPhysANB(pOutputData->dataBuffer, pYUVBuf);
1245                pSrcBuf[0] = outputYPhyAddr;
1246                pSrcBuf[1] = outputCPhyAddr;
1247            }
1248#endif
1249            if (pVideoDec->csc_set_format == OMX_FALSE) {
1250                csc_set_src_format(
1251                    pVideoDec->csc_handle,  /* handle */
1252                    width,                  /* width */
1253                    height,                 /* height */
1254                    0,                      /* crop_left */
1255                    0,                      /* crop_right */
1256                    width,                  /* crop_width */
1257                    height,                 /* crop_height */
1258                    csc_src_color_format,   /* color_format */
1259                    cacheable);             /* cacheable */
1260                csc_set_dst_format(
1261                    pVideoDec->csc_handle,  /* handle */
1262                    width,                  /* width */
1263                    height,                 /* height */
1264                    0,                      /* crop_left */
1265                    0,                      /* crop_right */
1266                    width,                  /* crop_width */
1267                    height,                 /* crop_height */
1268                    csc_dst_color_format,   /* color_format */
1269                    cacheable);             /* cacheable */
1270                pVideoDec->csc_set_format = OMX_TRUE;
1271            }
1272            csc_set_src_buffer(
1273                pVideoDec->csc_handle,  /* handle */
1274                pSrcBuf[0],             /* y addr */
1275                pSrcBuf[1],             /* u addr or uv addr */
1276                pSrcBuf[2],             /* v addr or none */
1277                0);                     /* ion fd */
1278            csc_set_dst_buffer(
1279                pVideoDec->csc_handle,
1280                pYUVBuf[0],             /* y addr */
1281                pYUVBuf[1],             /* u addr or uv addr */
1282                pYUVBuf[2],             /* v addr or none */
1283                0);                     /* ion fd */
1284            csc_convert(pVideoDec->csc_handle);
1285
1286#ifdef CONFIG_MFC_FPS
1287            Exynos_OSAL_PerfStop(PERF_ID_CSC);
1288#endif
1289        }
1290#ifdef USE_ANB
1291        if (pExynosOutputPort->bIsANBEnabled == OMX_TRUE) {
1292            Exynos_OSAL_UnlockANB(pOutputData->dataBuffer);
1293        }
1294#endif
1295        /* enqueue all available output buffers */
1296        pOutbufOps->Enqueue_All(hMFCHandle);
1297    } else {
1298        pOutputData->dataLen = 0;
1299    }
1300
1301EXIT:
1302    FunctionOut();
1303
1304    return ret;
1305}
1306
1307/* MFC Decode */
1308OMX_ERRORTYPE Exynos_MFC_VP8Dec_bufferProcess(
1309    OMX_COMPONENTTYPE   *pOMXComponent,
1310    EXYNOS_OMX_DATA     *pInputData,
1311    EXYNOS_OMX_DATA     *pOutputData)
1312{
1313    OMX_ERRORTYPE                ret                = OMX_ErrorNone;
1314    EXYNOS_OMX_BASECOMPONENT    *pExynosComponent   = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
1315    EXYNOS_VP8DEC_HANDLE        *pVp8Dec            = (EXYNOS_VP8DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle;
1316    EXYNOS_OMX_BASEPORT         *pExynosInputPort   = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX];
1317    EXYNOS_OMX_BASEPORT         *pExynosOutputPort  = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX];
1318    OMX_BOOL                     endOfFrame         = OMX_FALSE;
1319
1320    FunctionIn();
1321
1322    if ((!CHECK_PORT_ENABLED(pExynosInputPort)) || (!CHECK_PORT_ENABLED(pExynosOutputPort)) ||
1323        (!CHECK_PORT_POPULATED(pExynosInputPort)) || (!CHECK_PORT_POPULATED(pExynosOutputPort))) {
1324        ret = OMX_ErrorNone;
1325        goto EXIT;
1326    }
1327    if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent)) {
1328        ret = OMX_ErrorNone;
1329        goto EXIT;
1330    }
1331
1332    ret = Exynos_MFC_VP8_Decode_Nonblock(pOMXComponent, pInputData, pOutputData);
1333    if (ret != OMX_ErrorNone) {
1334        if (ret == OMX_ErrorInputDataDecodeYet) {
1335            pOutputData->usedDataLen = 0;
1336            pOutputData->remainDataLen = pOutputData->dataLen;
1337        } else {
1338            pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent,
1339                                                    pExynosComponent->callbackData,
1340                                                    OMX_EventError, ret, 0, NULL);
1341        }
1342    } else {
1343        pInputData->previousDataLen = pInputData->dataLen;
1344        pInputData->usedDataLen += pInputData->dataLen;
1345        pInputData->remainDataLen = pInputData->dataLen - pInputData->usedDataLen;
1346        pInputData->dataLen -= pInputData->usedDataLen;
1347        pInputData->usedDataLen = 0;
1348
1349        pOutputData->usedDataLen = 0;
1350        pOutputData->remainDataLen = pOutputData->dataLen;
1351    }
1352
1353EXIT:
1354    FunctionOut();
1355
1356    return ret;
1357}
1358
1359OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit(
1360    OMX_HANDLETYPE  hComponent,
1361    OMX_STRING      componentName)
1362{
1363    OMX_ERRORTYPE                    ret                = OMX_ErrorNone;
1364    OMX_COMPONENTTYPE               *pOMXComponent      = NULL;
1365    EXYNOS_OMX_BASECOMPONENT        *pExynosComponent   = NULL;
1366    EXYNOS_OMX_BASEPORT             *pExynosPort        = NULL;
1367    EXYNOS_OMX_VIDEODEC_COMPONENT   *pVideoDec          = NULL;
1368    EXYNOS_VP8DEC_HANDLE            *pVp8Dec            = NULL;
1369
1370    int i = 0;
1371
1372    FunctionIn();
1373
1374    if ((hComponent == NULL) || (componentName == NULL)) {
1375        ret = OMX_ErrorBadParameter;
1376        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, Line:%d", __LINE__);
1377        goto EXIT;
1378    }
1379    if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_VP8_DEC, componentName) != 0) {
1380        ret = OMX_ErrorBadParameter;
1381        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, componentName:%s, Line:%d", componentName, __LINE__);
1382        goto EXIT;
1383    }
1384
1385    pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
1386    ret = Exynos_OMX_VideoDecodeComponentInit(pOMXComponent);
1387    if (ret != OMX_ErrorNone) {
1388        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__);
1389        goto EXIT;
1390    }
1391    pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
1392    pExynosComponent->codecType = HW_VIDEO_DEC_CODEC;
1393
1394    pExynosComponent->componentName = (OMX_STRING)Exynos_OSAL_Malloc(MAX_OMX_COMPONENT_NAME_SIZE);
1395    if (pExynosComponent->componentName == NULL) {
1396        Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent);
1397        ret = OMX_ErrorInsufficientResources;
1398        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__);
1399        goto EXIT;
1400    }
1401    Exynos_OSAL_Memset(pExynosComponent->componentName, 0, MAX_OMX_COMPONENT_NAME_SIZE);
1402
1403    pVp8Dec = Exynos_OSAL_Malloc(sizeof(EXYNOS_VP8DEC_HANDLE));
1404    if (pVp8Dec == NULL) {
1405        Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent);
1406        ret = OMX_ErrorInsufficientResources;
1407        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__);
1408        goto EXIT;
1409    }
1410    Exynos_OSAL_Memset(pVp8Dec, 0, sizeof(EXYNOS_VP8DEC_HANDLE));
1411    pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
1412    pVideoDec->hCodecHandle = (OMX_HANDLETYPE)pVp8Dec;
1413
1414    Exynos_OSAL_Strcpy(pExynosComponent->componentName, EXYNOS_OMX_COMPONENT_VP8_DEC);
1415
1416    /* Set componentVersion */
1417    pExynosComponent->componentVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER;
1418    pExynosComponent->componentVersion.s.nVersionMinor = VERSIONMINOR_NUMBER;
1419    pExynosComponent->componentVersion.s.nRevision     = REVISION_NUMBER;
1420    pExynosComponent->componentVersion.s.nStep         = STEP_NUMBER;
1421    /* Set specVersion */
1422    pExynosComponent->specVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER;
1423    pExynosComponent->specVersion.s.nVersionMinor = VERSIONMINOR_NUMBER;
1424    pExynosComponent->specVersion.s.nRevision     = REVISION_NUMBER;
1425    pExynosComponent->specVersion.s.nStep         = STEP_NUMBER;
1426
1427    /* Android CapabilityFlags */
1428    pExynosComponent->capabilityFlags.iIsOMXComponentMultiThreaded                   = OMX_TRUE;
1429    pExynosComponent->capabilityFlags.iOMXComponentSupportsExternalInputBufferAlloc  = OMX_TRUE;
1430    pExynosComponent->capabilityFlags.iOMXComponentSupportsExternalOutputBufferAlloc = OMX_TRUE;
1431    pExynosComponent->capabilityFlags.iOMXComponentSupportsMovableInputBuffers       = OMX_FALSE;
1432    pExynosComponent->capabilityFlags.iOMXComponentSupportsPartialFrames             = OMX_FALSE;
1433    pExynosComponent->capabilityFlags.iOMXComponentUsesNALStartCodes                 = OMX_TRUE;
1434    pExynosComponent->capabilityFlags.iOMXComponentCanHandleIncompleteFrames         = OMX_TRUE;
1435    pExynosComponent->capabilityFlags.iOMXComponentUsesFullAVCFrames                 = OMX_TRUE;
1436
1437    /* Input port */
1438    pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX];
1439    pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH;
1440    pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT;
1441    pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/
1442    pExynosPort->portDefinition.format.video.nSliceHeight = 0;
1443    pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_INPUT_BUFFER_SIZE;
1444    pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingVPX;
1445    Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE);
1446    Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "video/x-vnd.on2.vp8");
1447    pExynosPort->portDefinition.format.video.pNativeRender = 0;
1448    pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE;
1449    pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused;
1450    pExynosPort->portDefinition.bEnabled = OMX_TRUE;
1451
1452    /* Output port */
1453    pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX];
1454    pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH;
1455    pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT;
1456    pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/
1457    pExynosPort->portDefinition.format.video.nSliceHeight = 0;
1458    pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE;
1459    pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
1460    Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE);
1461    Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video");
1462    pExynosPort->portDefinition.format.video.pNativeRender = 0;
1463    pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE;
1464    pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
1465    pExynosPort->portDefinition.bEnabled = OMX_TRUE;
1466
1467    pOMXComponent->GetParameter      = &Exynos_MFC_VP8Dec_GetParameter;
1468    pOMXComponent->SetParameter      = &Exynos_MFC_VP8Dec_SetParameter;
1469    pOMXComponent->GetConfig         = &Exynos_MFC_VP8Dec_GetConfig;
1470    pOMXComponent->SetConfig         = &Exynos_MFC_VP8Dec_SetConfig;
1471    pOMXComponent->GetExtensionIndex = &Exynos_MFC_VP8Dec_GetExtensionIndex;
1472    pOMXComponent->ComponentRoleEnum = &Exynos_MFC_VP8Dec_ComponentRoleEnum;
1473    pOMXComponent->ComponentDeInit   = &Exynos_OMX_ComponentDeinit;
1474
1475    pExynosComponent->exynos_mfc_componentInit      = &Exynos_MFC_VP8Dec_Init;
1476    pExynosComponent->exynos_mfc_componentTerminate = &Exynos_MFC_VP8Dec_Terminate;
1477    pExynosComponent->exynos_mfc_bufferProcess      = &Exynos_MFC_VP8Dec_bufferProcess;
1478    pExynosComponent->exynos_checkInputFrame        = &Check_VP8_Frame;
1479
1480    pExynosComponent->currentState = OMX_StateLoaded;
1481
1482    ret = OMX_ErrorNone;
1483
1484EXIT:
1485    FunctionOut();
1486
1487    return ret;
1488}
1489
1490OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(
1491    OMX_HANDLETYPE hComponent)
1492{
1493    OMX_ERRORTYPE                ret                = OMX_ErrorNone;
1494    OMX_COMPONENTTYPE           *pOMXComponent      = NULL;
1495    EXYNOS_OMX_BASECOMPONENT    *pExynosComponent   = NULL;
1496    EXYNOS_VP8DEC_HANDLE        *pVp8Dec            = NULL;
1497
1498    FunctionIn();
1499
1500    if (hComponent == NULL) {
1501        ret = OMX_ErrorBadParameter;
1502        goto EXIT;
1503    }
1504    pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
1505    pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
1506
1507    Exynos_OSAL_Free(pExynosComponent->componentName);
1508    pExynosComponent->componentName = NULL;
1509
1510    pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle;
1511    if (pVp8Dec != NULL) {
1512        Exynos_OSAL_Free(pVp8Dec);
1513        pVp8Dec = ((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle = NULL;
1514    }
1515
1516    ret = Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent);
1517    if (ret != OMX_ErrorNone) {
1518        goto EXIT;
1519    }
1520
1521    ret = OMX_ErrorNone;
1522
1523EXIT:
1524    FunctionOut();
1525
1526    return ret;
1527}
1528