Exynos_OMX_Venc.c revision 33d6044e338e2ea5c8580b6a52840808e459d998
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_ERROR, "drop frame after seeking");
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_ERROR, "not set check timestame after seeking");
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                    Exynos_OMX_ExtensionSetup(hComponent);
667                    pVideoEnc->bFirstInput = OMX_FALSE;
668                }
669#endif
670                Exynos_OSAL_MutexUnlock(srcInputUseBuffer->bufferMutex);
671                break;
672            }
673
674            if (CHECK_PORT_BEING_FLUSHED(exynosInputPort)) {
675                Exynos_OSAL_MutexUnlock(srcInputUseBuffer->bufferMutex);
676                break;
677            }
678
679            ret = pVideoEnc->exynos_codec_srcInputProcess(pOMXComponent, pSrcInputData);
680            Exynos_ResetCodecData(pSrcInputData);
681            Exynos_OSAL_MutexUnlock(srcInputUseBuffer->bufferMutex);
682            if (ret == OMX_ErrorCodecInit)
683                pVideoEnc->bExitBufferProcessThread = OMX_TRUE;
684        }
685    }
686
687EXIT:
688
689    FunctionOut();
690
691    return ret;
692}
693
694OMX_ERRORTYPE Exynos_OMX_SrcOutputBufferProcess(OMX_HANDLETYPE hComponent)
695{
696    OMX_ERRORTYPE          ret = OMX_ErrorNone;
697    OMX_COMPONENTTYPE     *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
698    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
699    EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle;
700    EXYNOS_OMX_BASEPORT      *exynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX];
701    EXYNOS_OMX_DATABUFFER    *srcOutputUseBuffer = &exynosInputPort->way.port2WayDataBuffer.outputDataBuffer;
702    EXYNOS_OMX_DATA           srcOutputData;
703
704    FunctionIn();
705
706    while (!pVideoEnc->bExitBufferProcessThread) {
707        Exynos_OSAL_SleepMillisec(0);
708
709        while (!pVideoEnc->bExitBufferProcessThread) {
710            if ((exynosInputPort->bufferProcessType & BUFFER_COPY) == BUFFER_COPY) {
711                if (Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX) == OMX_FALSE)
712                    break;
713            }
714            Exynos_OSAL_SleepMillisec(0);
715
716            if (CHECK_PORT_BEING_FLUSHED(exynosInputPort))
717                break;
718
719            Exynos_OSAL_MutexLock(srcOutputUseBuffer->bufferMutex);
720            ret = pVideoEnc->exynos_codec_srcOutputProcess(pOMXComponent, &srcOutputData);
721
722            if (ret == OMX_ErrorNone) {
723                if ((exynosInputPort->bufferProcessType & BUFFER_COPY) == BUFFER_COPY) {
724                    OMX_PTR codecBuffer;
725                    codecBuffer = srcOutputData.pPrivate;
726                    if (codecBuffer != NULL)
727                        Exynos_CodecBufferEnQueue(pExynosComponent, INPUT_PORT_INDEX, codecBuffer);
728                }
729                if (exynosInputPort->bufferProcessType == BUFFER_SHARE) {
730                    Exynos_Shared_DataToBuffer(&srcOutputData, srcOutputUseBuffer);
731                    Exynos_InputBufferReturn(pOMXComponent);
732                }
733                Exynos_ResetCodecData(&srcOutputData);
734            }
735            Exynos_OSAL_MutexUnlock(srcOutputUseBuffer->bufferMutex);
736        }
737    }
738
739EXIT:
740
741    FunctionOut();
742
743    return ret;
744}
745
746OMX_ERRORTYPE Exynos_OMX_DstInputBufferProcess(OMX_HANDLETYPE hComponent)
747{
748    OMX_ERRORTYPE          ret = OMX_ErrorNone;
749    OMX_COMPONENTTYPE     *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
750    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
751    EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle;
752    EXYNOS_OMX_BASEPORT      *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX];
753    EXYNOS_OMX_DATABUFFER    *dstInputUseBuffer = &exynosOutputPort->way.port2WayDataBuffer.inputDataBuffer;
754    EXYNOS_OMX_DATA           dstInputData;
755
756    FunctionIn();
757
758    while (!pVideoEnc->bExitBufferProcessThread) {
759        Exynos_OSAL_SleepMillisec(0);
760
761        while ((Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) &&
762               (!pVideoEnc->bExitBufferProcessThread)) {
763            Exynos_OSAL_SleepMillisec(0);
764
765            if ((CHECK_PORT_BEING_FLUSHED(exynosOutputPort)) ||
766                (!CHECK_PORT_POPULATED(exynosOutputPort)))
767                break;
768            if (exynosOutputPort->portState != OMX_StateIdle)
769                break;
770
771            Exynos_OSAL_MutexLock(dstInputUseBuffer->bufferMutex);
772            if ((exynosOutputPort->bufferProcessType & BUFFER_COPY) == BUFFER_COPY) {
773                OMX_PTR codecBuffer;
774                ret = Exynos_CodecBufferDeQueue(pExynosComponent, OUTPUT_PORT_INDEX, &codecBuffer);
775                if (ret != OMX_ErrorNone) {
776                    Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex);
777                    break;
778                }
779                Exynos_Output_CodecBufferToData(pExynosComponent, codecBuffer, &dstInputData);
780            }
781
782            if (exynosOutputPort->bufferProcessType == BUFFER_SHARE) {
783                if ((dstInputUseBuffer->dataValid != OMX_TRUE) &&
784                    (!CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) {
785                    ret = Exynos_OutputBufferGetQueue(pExynosComponent);
786                    if (ret != OMX_ErrorNone) {
787                        Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex);
788                        break;
789                    }
790                    Exynos_Shared_BufferToData(dstInputUseBuffer, &dstInputData, ONE_PLANE);
791                    Exynos_ResetDataBuffer(dstInputUseBuffer);
792                }
793            }
794
795            if (CHECK_PORT_BEING_FLUSHED(exynosOutputPort)) {
796                Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex);
797                break;
798            }
799            ret = pVideoEnc->exynos_codec_dstInputProcess(pOMXComponent, &dstInputData);
800
801            Exynos_ResetCodecData(&dstInputData);
802            Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex);
803        }
804    }
805
806EXIT:
807
808    FunctionOut();
809
810    return ret;
811}
812
813OMX_ERRORTYPE Exynos_OMX_DstOutputBufferProcess(OMX_HANDLETYPE hComponent)
814{
815    OMX_ERRORTYPE          ret = OMX_ErrorNone;
816    OMX_COMPONENTTYPE     *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
817    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
818    EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle;
819    EXYNOS_OMX_BASEPORT      *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX];
820    EXYNOS_OMX_DATABUFFER    *dstOutputUseBuffer = &exynosOutputPort->way.port2WayDataBuffer.outputDataBuffer;
821    EXYNOS_OMX_DATA          *pDstOutputData = &exynosOutputPort->processData;
822
823    FunctionIn();
824
825    while (!pVideoEnc->bExitBufferProcessThread) {
826        Exynos_OSAL_SleepMillisec(0);
827        Exynos_Wait_ProcessPause(pExynosComponent, OUTPUT_PORT_INDEX);
828
829        while ((Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) &&
830               (!pVideoEnc->bExitBufferProcessThread)) {
831            Exynos_OSAL_SleepMillisec(0);
832
833            if (CHECK_PORT_BEING_FLUSHED(exynosOutputPort))
834                break;
835
836            Exynos_OSAL_MutexLock(dstOutputUseBuffer->bufferMutex);
837            if ((exynosOutputPort->bufferProcessType & BUFFER_COPY) == BUFFER_COPY) {
838                if ((dstOutputUseBuffer->dataValid != OMX_TRUE) &&
839                    (!CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) {
840                    ret = Exynos_OutputBufferGetQueue(pExynosComponent);
841                    if (ret != OMX_ErrorNone) {
842                        Exynos_OSAL_MutexUnlock(dstOutputUseBuffer->bufferMutex);
843                        break;
844                    }
845                }
846            }
847
848            if ((dstOutputUseBuffer->dataValid == OMX_TRUE) ||
849                (exynosOutputPort->bufferProcessType == BUFFER_SHARE))
850                ret = pVideoEnc->exynos_codec_dstOutputProcess(pOMXComponent, pDstOutputData);
851
852            if (((ret == OMX_ErrorNone) && (dstOutputUseBuffer->dataValid == OMX_TRUE)) ||
853                (exynosOutputPort->bufferProcessType == BUFFER_SHARE)) {
854                Exynos_Postprocess_OutputData(pOMXComponent, pDstOutputData);
855            }
856
857            if ((exynosOutputPort->bufferProcessType & BUFFER_COPY) == BUFFER_COPY) {
858                OMX_PTR codecBuffer;
859                codecBuffer = pDstOutputData->pPrivate;
860                if (codecBuffer != NULL) {
861                    Exynos_CodecBufferEnQueue(pExynosComponent, OUTPUT_PORT_INDEX, codecBuffer);
862                    pDstOutputData->pPrivate = NULL;
863                }
864            }
865
866            /* reset outputData */
867            Exynos_ResetCodecData(pDstOutputData);
868            Exynos_OSAL_MutexUnlock(dstOutputUseBuffer->bufferMutex);
869        }
870    }
871
872EXIT:
873
874    FunctionOut();
875
876    return ret;
877}
878
879static OMX_ERRORTYPE Exynos_OMX_SrcInputProcessThread(OMX_PTR threadData)
880{
881    OMX_ERRORTYPE          ret = OMX_ErrorNone;
882    OMX_COMPONENTTYPE     *pOMXComponent = NULL;
883    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
884    EXYNOS_OMX_MESSAGE       *message = NULL;
885
886    FunctionIn();
887
888    if (threadData == NULL) {
889        ret = OMX_ErrorBadParameter;
890        goto EXIT;
891    }
892    pOMXComponent = (OMX_COMPONENTTYPE *)threadData;
893    ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE));
894    if (ret != OMX_ErrorNone) {
895        goto EXIT;
896    }
897    pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
898    Exynos_OMX_SrcInputBufferProcess(pOMXComponent);
899
900    Exynos_OSAL_ThreadExit(NULL);
901
902EXIT:
903    FunctionOut();
904
905    return ret;
906}
907
908static OMX_ERRORTYPE Exynos_OMX_SrcOutputProcessThread(OMX_PTR threadData)
909{
910    OMX_ERRORTYPE          ret = OMX_ErrorNone;
911    OMX_COMPONENTTYPE     *pOMXComponent = NULL;
912    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
913    EXYNOS_OMX_MESSAGE       *message = NULL;
914
915    FunctionIn();
916
917    if (threadData == NULL) {
918        ret = OMX_ErrorBadParameter;
919        goto EXIT;
920    }
921    pOMXComponent = (OMX_COMPONENTTYPE *)threadData;
922    ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE));
923    if (ret != OMX_ErrorNone) {
924        goto EXIT;
925    }
926    pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
927    Exynos_OMX_SrcOutputBufferProcess(pOMXComponent);
928
929    Exynos_OSAL_ThreadExit(NULL);
930
931EXIT:
932    FunctionOut();
933
934    return ret;
935}
936
937static OMX_ERRORTYPE Exynos_OMX_DstInputProcessThread(OMX_PTR threadData)
938{
939    OMX_ERRORTYPE          ret = OMX_ErrorNone;
940    OMX_COMPONENTTYPE     *pOMXComponent = NULL;
941    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
942    EXYNOS_OMX_MESSAGE       *message = NULL;
943
944    FunctionIn();
945
946    if (threadData == NULL) {
947        ret = OMX_ErrorBadParameter;
948        goto EXIT;
949    }
950    pOMXComponent = (OMX_COMPONENTTYPE *)threadData;
951    ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE));
952    if (ret != OMX_ErrorNone) {
953        goto EXIT;
954    }
955    pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
956    Exynos_OMX_DstInputBufferProcess(pOMXComponent);
957
958    Exynos_OSAL_ThreadExit(NULL);
959
960EXIT:
961    FunctionOut();
962
963    return ret;
964}
965
966static OMX_ERRORTYPE Exynos_OMX_DstOutputProcessThread(OMX_PTR threadData)
967{
968    OMX_ERRORTYPE          ret = OMX_ErrorNone;
969    OMX_COMPONENTTYPE     *pOMXComponent = NULL;
970    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
971    EXYNOS_OMX_MESSAGE       *message = NULL;
972
973    FunctionIn();
974
975    if (threadData == NULL) {
976        ret = OMX_ErrorBadParameter;
977        goto EXIT;
978    }
979    pOMXComponent = (OMX_COMPONENTTYPE *)threadData;
980    ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE));
981    if (ret != OMX_ErrorNone) {
982        goto EXIT;
983    }
984    pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
985    Exynos_OMX_DstOutputBufferProcess(pOMXComponent);
986
987    Exynos_OSAL_ThreadExit(NULL);
988
989EXIT:
990    FunctionOut();
991
992    return ret;
993}
994
995OMX_ERRORTYPE Exynos_OMX_BufferProcess_Create(OMX_HANDLETYPE hComponent)
996{
997    OMX_ERRORTYPE          ret = OMX_ErrorNone;
998    OMX_COMPONENTTYPE     *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
999    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
1000    EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle;
1001
1002    FunctionIn();
1003
1004    pVideoEnc->bExitBufferProcessThread = OMX_FALSE;
1005
1006    ret = Exynos_OSAL_ThreadCreate(&pVideoEnc->hDstOutputThread,
1007                 Exynos_OMX_DstOutputProcessThread,
1008                 pOMXComponent);
1009    if (ret == OMX_ErrorNone)
1010        ret = Exynos_OSAL_ThreadCreate(&pVideoEnc->hSrcOutputThread,
1011                     Exynos_OMX_SrcOutputProcessThread,
1012                     pOMXComponent);
1013    if (ret == OMX_ErrorNone)
1014        ret = Exynos_OSAL_ThreadCreate(&pVideoEnc->hDstInputThread,
1015                     Exynos_OMX_DstInputProcessThread,
1016                     pOMXComponent);
1017    if (ret == OMX_ErrorNone)
1018        ret = Exynos_OSAL_ThreadCreate(&pVideoEnc->hSrcInputThread,
1019                     Exynos_OMX_SrcInputProcessThread,
1020                     pOMXComponent);
1021
1022EXIT:
1023    FunctionOut();
1024
1025    return ret;
1026}
1027
1028OMX_ERRORTYPE Exynos_OMX_BufferProcess_Terminate(OMX_HANDLETYPE hComponent)
1029{
1030    OMX_ERRORTYPE          ret = OMX_ErrorNone;
1031    OMX_COMPONENTTYPE     *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
1032    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
1033    EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle;
1034    OMX_S32                countValue = 0;
1035    unsigned int           i = 0;
1036
1037    FunctionIn();
1038
1039    pVideoEnc->bExitBufferProcessThread = OMX_TRUE;
1040
1041    Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].bufferSemID, &countValue);
1042    if (countValue == 0)
1043        Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].bufferSemID);
1044    Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].codecSemID, &countValue);
1045    if (countValue == 0)
1046        Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].codecSemID);
1047    Exynos_OSAL_SignalSet(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].pauseEvent);
1048    Exynos_OSAL_ThreadTerminate(pVideoEnc->hSrcInputThread);
1049    pVideoEnc->hSrcInputThread = NULL;
1050
1051    Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].bufferSemID, &countValue);
1052    if (countValue == 0)
1053        Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].bufferSemID);
1054    Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].codecSemID, &countValue);
1055    if (countValue == 0)
1056        Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].codecSemID);
1057    Exynos_OSAL_SignalSet(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].pauseEvent);
1058    Exynos_OSAL_ThreadTerminate(pVideoEnc->hDstInputThread);
1059    pVideoEnc->hDstInputThread = NULL;
1060
1061    pVideoEnc->exynos_codec_stop(pOMXComponent, INPUT_PORT_INDEX);
1062    pVideoEnc->exynos_codec_bufferProcessRun(pOMXComponent, INPUT_PORT_INDEX);
1063    Exynos_OSAL_SignalSet(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].pauseEvent);
1064    Exynos_OSAL_ThreadTerminate(pVideoEnc->hSrcOutputThread);
1065    pVideoEnc->hSrcOutputThread = NULL;
1066
1067    pVideoEnc->exynos_codec_stop(pOMXComponent, OUTPUT_PORT_INDEX);
1068    pVideoEnc->exynos_codec_bufferProcessRun(pOMXComponent, INPUT_PORT_INDEX);
1069    Exynos_OSAL_SignalSet(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].pauseEvent);
1070    Exynos_OSAL_ThreadTerminate(pVideoEnc->hDstOutputThread);
1071    pVideoEnc->hDstOutputThread = NULL;
1072
1073EXIT:
1074    FunctionOut();
1075
1076    return ret;
1077}
1078
1079OMX_ERRORTYPE Exynos_OMX_VideoEncodeComponentInit(OMX_IN OMX_HANDLETYPE hComponent)
1080{
1081    OMX_ERRORTYPE                  ret = OMX_ErrorNone;
1082    OMX_COMPONENTTYPE             *pOMXComponent = NULL;
1083    EXYNOS_OMX_BASECOMPONENT      *pExynosComponent = NULL;
1084    EXYNOS_OMX_BASEPORT           *pExynosPort = NULL;
1085    EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL;
1086
1087    FunctionIn();
1088
1089    if (hComponent == NULL) {
1090        ret = OMX_ErrorBadParameter;
1091        goto EXIT;
1092    }
1093    pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
1094    ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE));
1095    if (ret != OMX_ErrorNone) {
1096        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__);
1097        goto EXIT;
1098    }
1099
1100    ret = Exynos_OMX_BaseComponent_Constructor(pOMXComponent);
1101    if (ret != OMX_ErrorNone) {
1102        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__);
1103        goto EXIT;
1104    }
1105
1106    ret = Exynos_OMX_Port_Constructor(pOMXComponent);
1107    if (ret != OMX_ErrorNone) {
1108        Exynos_OMX_BaseComponent_Destructor(pOMXComponent);
1109        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__);
1110        goto EXIT;
1111    }
1112
1113    pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
1114
1115    pVideoEnc = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_VIDEOENC_COMPONENT));
1116    if (pVideoEnc == NULL) {
1117        Exynos_OMX_BaseComponent_Destructor(pOMXComponent);
1118        ret = OMX_ErrorInsufficientResources;
1119        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__);
1120        goto EXIT;
1121    }
1122
1123    Exynos_OSAL_Memset(pVideoEnc, 0, sizeof(EXYNOS_OMX_VIDEOENC_COMPONENT));
1124    pExynosComponent->hComponentHandle = (OMX_HANDLETYPE)pVideoEnc;
1125
1126    pExynosComponent->bSaveFlagEOS = OMX_FALSE;
1127
1128    pVideoEnc->bFirstInput  = OMX_FALSE;
1129    pVideoEnc->bFirstOutput = OMX_FALSE;
1130    pVideoEnc->configChange = OMX_FALSE;
1131    pVideoEnc->quantization.nQpI = 4; // I frame quantization parameter
1132    pVideoEnc->quantization.nQpP = 5; // P frame quantization parameter
1133    pVideoEnc->quantization.nQpB = 5; // B frame quantization parameter
1134
1135    pExynosComponent->bMultiThreadProcess = OMX_TRUE;
1136
1137    /* Input port */
1138    pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX];
1139    pExynosPort->portDefinition.nBufferCountActual = MAX_VIDEO_INPUTBUFFER_NUM;
1140    pExynosPort->portDefinition.nBufferCountMin = MAX_VIDEO_INPUTBUFFER_NUM;
1141    pExynosPort->portDefinition.nBufferSize = 0;
1142    pExynosPort->portDefinition.eDomain = OMX_PortDomainVideo;
1143
1144    pExynosPort->portDefinition.format.video.cMIMEType = Exynos_OSAL_Malloc(MAX_OMX_MIMETYPE_SIZE);
1145    Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video");
1146    pExynosPort->portDefinition.format.video.pNativeRender = 0;
1147    pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE;
1148    pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
1149
1150    pExynosPort->portDefinition.format.video.nFrameWidth = 0;
1151    pExynosPort->portDefinition.format.video.nFrameHeight= 0;
1152    pExynosPort->portDefinition.format.video.nStride = 0;
1153    pExynosPort->portDefinition.format.video.nSliceHeight = 0;
1154    pExynosPort->portDefinition.format.video.nBitrate = 64000;
1155    pExynosPort->portDefinition.format.video.xFramerate = (15 << 16);
1156    pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused;
1157    pExynosPort->portDefinition.format.video.pNativeWindow = NULL;
1158    pVideoEnc->eControlRate[INPUT_PORT_INDEX] = OMX_Video_ControlRateDisable;
1159
1160    pExynosPort->bStoreMetaData = OMX_FALSE;
1161
1162    /* Output port */
1163    pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX];
1164    pExynosPort->portDefinition.nBufferCountActual = MAX_VIDEO_OUTPUTBUFFER_NUM;
1165    pExynosPort->portDefinition.nBufferCountMin = MAX_VIDEO_OUTPUTBUFFER_NUM;
1166    pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE;
1167    pExynosPort->portDefinition.eDomain = OMX_PortDomainVideo;
1168
1169    pExynosPort->portDefinition.format.video.cMIMEType = Exynos_OSAL_Malloc(MAX_OMX_MIMETYPE_SIZE);
1170    Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video");
1171    pExynosPort->portDefinition.format.video.pNativeRender = 0;
1172    pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE;
1173    pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
1174
1175    pExynosPort->portDefinition.format.video.nFrameWidth = 0;
1176    pExynosPort->portDefinition.format.video.nFrameHeight= 0;
1177    pExynosPort->portDefinition.format.video.nStride = 0;
1178    pExynosPort->portDefinition.format.video.nSliceHeight = 0;
1179    pExynosPort->portDefinition.format.video.nBitrate = 64000;
1180    pExynosPort->portDefinition.format.video.xFramerate = (15 << 16);
1181    pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused;
1182    pExynosPort->portDefinition.format.video.pNativeWindow = NULL;
1183    pVideoEnc->eControlRate[OUTPUT_PORT_INDEX] = OMX_Video_ControlRateDisable;
1184
1185    pOMXComponent->UseBuffer              = &Exynos_OMX_UseBuffer;
1186    pOMXComponent->AllocateBuffer         = &Exynos_OMX_AllocateBuffer;
1187    pOMXComponent->FreeBuffer             = &Exynos_OMX_FreeBuffer;
1188    pOMXComponent->ComponentTunnelRequest = &Exynos_OMX_ComponentTunnelRequest;
1189
1190    pExynosComponent->exynos_AllocateTunnelBuffer = &Exynos_OMX_AllocateTunnelBuffer;
1191    pExynosComponent->exynos_FreeTunnelBuffer     = &Exynos_OMX_FreeTunnelBuffer;
1192    pExynosComponent->exynos_BufferProcessCreate    = &Exynos_OMX_BufferProcess_Create;
1193    pExynosComponent->exynos_BufferProcessTerminate = &Exynos_OMX_BufferProcess_Terminate;
1194    pExynosComponent->exynos_BufferFlush          = &Exynos_OMX_BufferFlush;
1195
1196EXIT:
1197    FunctionOut();
1198
1199    return ret;
1200}
1201
1202OMX_ERRORTYPE Exynos_OMX_VideoEncodeComponentDeinit(OMX_IN OMX_HANDLETYPE hComponent)
1203{
1204    OMX_ERRORTYPE                  ret = OMX_ErrorNone;
1205    OMX_COMPONENTTYPE             *pOMXComponent = NULL;
1206    EXYNOS_OMX_BASECOMPONENT      *pExynosComponent = NULL;
1207    EXYNOS_OMX_BASEPORT           *pExynosPort = NULL;
1208    EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL;
1209    int                            i = 0;
1210
1211    FunctionIn();
1212
1213    if (hComponent == NULL) {
1214        ret = OMX_ErrorBadParameter;
1215        goto EXIT;
1216    }
1217    pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
1218    ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE));
1219    if (ret != OMX_ErrorNone) {
1220        goto EXIT;
1221    }
1222
1223    if (pOMXComponent->pComponentPrivate == NULL) {
1224        ret = OMX_ErrorBadParameter;
1225        goto EXIT;
1226    }
1227    pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
1228
1229    pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle;
1230
1231    Exynos_OSAL_Free(pVideoEnc);
1232    pExynosComponent->hComponentHandle = pVideoEnc = NULL;
1233
1234    for(i = 0; i < ALL_PORT_NUM; i++) {
1235        pExynosPort = &pExynosComponent->pExynosPort[i];
1236        Exynos_OSAL_Free(pExynosPort->portDefinition.format.video.cMIMEType);
1237        pExynosPort->portDefinition.format.video.cMIMEType = NULL;
1238    }
1239
1240    ret = Exynos_OMX_Port_Destructor(pOMXComponent);
1241
1242    ret = Exynos_OMX_BaseComponent_Destructor(hComponent);
1243
1244EXIT:
1245    FunctionOut();
1246
1247    return ret;
1248}
1249