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