1/*
2 * Copyright 2012 Samsung Electronics S.LSI Co. LTD
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 * @file        Exynos_OSAL_Android.cpp
19 * @brief
20 * @author      Seungbeom Kim (sbcrux.kim@samsung.com)
21 * @author      Hyeyeon Chung (hyeon.chung@samsung.com)
22 * @author      Yunji Kim (yunji.kim@samsung.com)
23 * @author      Jinsung Yang (jsgood.yang@samsung.com)
24 * @version     2.0.0
25 * @history
26 *   2012.02.20 : Create
27 */
28
29#include <stdio.h>
30#include <stdlib.h>
31
32#include <system/window.h>
33#include <ui/GraphicBuffer.h>
34#include <ui/GraphicBufferMapper.h>
35#include <ui/Rect.h>
36#include <media/hardware/HardwareAPI.h>
37#include <hardware/hardware.h>
38#include <media/hardware/OMXPluginBase.h>
39#include <media/hardware/MetadataBufferType.h>
40#include <gralloc_priv.h>
41
42#include "Exynos_OSAL_Mutex.h"
43#include "Exynos_OSAL_Semaphore.h"
44#include "Exynos_OMX_Baseport.h"
45#include "Exynos_OMX_Basecomponent.h"
46#include "Exynos_OMX_Macros.h"
47#include "Exynos_OMX_Vdec.h"
48#include "Exynos_OMX_Venc.h"
49#include "Exynos_OSAL_Android.h"
50#include "exynos_format.h"
51#include "ion.h"
52
53#undef  EXYNOS_LOG_TAG
54#define EXYNOS_LOG_TAG    "Exynos_OSAL_Android"
55#define EXYNOS_LOG_OFF
56#include "Exynos_OSAL_Log.h"
57
58using namespace android;
59
60#ifdef __cplusplus
61extern "C" {
62#endif
63
64int getIonFd(gralloc_module_t const *module)
65{
66    private_module_t* m = const_cast<private_module_t*>(reinterpret_cast<const private_module_t*>(module));
67    return m->ionfd;
68}
69
70OMX_ERRORTYPE Exynos_OSAL_LockANBHandle(
71    OMX_IN OMX_U32 handle,
72    OMX_IN OMX_U32 width,
73    OMX_IN OMX_U32 height,
74    OMX_IN OMX_COLOR_FORMATTYPE format,
75    OMX_OUT OMX_PTR planes)
76{
77    FunctionIn();
78
79    OMX_ERRORTYPE ret = OMX_ErrorNone;
80    GraphicBufferMapper &mapper = GraphicBufferMapper::get();
81    buffer_handle_t bufferHandle = (buffer_handle_t) handle;
82    private_handle_t *priv_hnd = (private_handle_t *) bufferHandle;
83    Rect bounds(width, height);
84    ExynosVideoPlane *vplanes = (ExynosVideoPlane *) planes;
85    void *vaddr[MAX_BUFFER_PLANE];
86
87    Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s: handle: 0x%x", __func__, handle);
88
89    int usage = 0;
90
91    switch (format) {
92    case OMX_COLOR_FormatYUV420Planar:
93    case OMX_COLOR_FormatYUV420SemiPlanar:
94    case OMX_SEC_COLOR_FormatNV12Tiled:
95        usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
96        break;
97    default:
98        usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
99        break;
100    }
101
102    if (mapper.lock(bufferHandle, usage, bounds, vaddr) != 0) {
103        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: mapper.lock() fail", __func__);
104        ret = OMX_ErrorUndefined;
105        goto EXIT;
106    }
107
108    vplanes[0].fd = priv_hnd->fd;
109    vplanes[0].offset = 0;
110    vplanes[0].addr = vaddr[0];
111    vplanes[1].fd = priv_hnd->fd1;
112    vplanes[1].offset = 0;
113    vplanes[1].addr = vaddr[1];
114    vplanes[2].fd = priv_hnd->fd2;
115    vplanes[2].offset = 0;
116    vplanes[2].addr = vaddr[2];
117
118    Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s: buffer locked: 0x%x", __func__, *vaddr);
119
120EXIT:
121    FunctionOut();
122
123    return ret;
124}
125
126OMX_ERRORTYPE Exynos_OSAL_UnlockANBHandle(OMX_IN OMX_U32 handle)
127{
128    FunctionIn();
129
130    OMX_ERRORTYPE ret = OMX_ErrorNone;
131    GraphicBufferMapper &mapper = GraphicBufferMapper::get();
132    buffer_handle_t bufferHandle = (buffer_handle_t) handle;
133
134    Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s: handle: 0x%x", __func__, handle);
135
136    if (mapper.unlock(bufferHandle) != 0) {
137        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: mapper.unlock() fail", __func__);
138        ret = OMX_ErrorUndefined;
139        goto EXIT;
140    }
141
142    Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s: buffer unlocked: 0x%x", __func__, handle);
143
144EXIT:
145    FunctionOut();
146
147    return ret;
148}
149
150OMX_COLOR_FORMATTYPE Exynos_OSAL_GetANBColorFormat(OMX_IN OMX_U32 handle)
151{
152    FunctionIn();
153
154    OMX_COLOR_FORMATTYPE ret = OMX_COLOR_FormatUnused;
155    private_handle_t *priv_hnd = (private_handle_t *) handle;
156
157    ret = Exynos_OSAL_Hal2OMXPixelFormat(priv_hnd->format);
158    Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "ColorFormat: 0x%x", ret);
159
160EXIT:
161    FunctionOut();
162
163    return ret;
164}
165
166OMX_U32 Exynos_OSAL_GetANBStride(OMX_IN OMX_U32 handle)
167{
168    FunctionIn();
169
170    OMX_U32 nStride = 0;
171    private_handle_t *priv_hnd = (private_handle_t *) handle;
172
173    nStride = priv_hnd->stride;
174
175EXIT:
176    FunctionOut();
177
178    return nStride;
179}
180
181OMX_ERRORTYPE Exynos_OSAL_LockANB(
182    OMX_IN OMX_PTR pBuffer,
183    OMX_IN OMX_U32 width,
184    OMX_IN OMX_U32 height,
185    OMX_IN OMX_COLOR_FORMATTYPE format,
186    OMX_OUT OMX_U32 *pStride,
187    OMX_OUT OMX_PTR planes)
188{
189    FunctionIn();
190
191    OMX_ERRORTYPE ret = OMX_ErrorNone;
192    android_native_buffer_t *pANB = (android_native_buffer_t *) pBuffer;
193
194    ret = Exynos_OSAL_LockANBHandle((OMX_U32)pANB->handle, width, height, format, planes);
195    *pStride = pANB->stride;
196
197EXIT:
198    FunctionOut();
199
200    return ret;
201}
202
203OMX_ERRORTYPE Exynos_OSAL_UnlockANB(OMX_IN OMX_PTR pBuffer)
204{
205    FunctionIn();
206
207    OMX_ERRORTYPE ret = OMX_ErrorNone;
208    android_native_buffer_t *pANB = (android_native_buffer_t *) pBuffer;
209
210    ret = Exynos_OSAL_UnlockANBHandle((OMX_U32)pANB->handle);
211
212EXIT:
213    FunctionOut();
214
215    return ret;
216}
217
218OMX_ERRORTYPE Exynos_OSAL_LockMetaData(
219    OMX_IN OMX_PTR pBuffer,
220    OMX_IN OMX_U32 width,
221    OMX_IN OMX_U32 height,
222    OMX_IN OMX_COLOR_FORMATTYPE format,
223    OMX_OUT OMX_U32 *pStride,
224    OMX_OUT OMX_PTR planes)
225{
226    FunctionIn();
227
228    OMX_ERRORTYPE ret = OMX_ErrorNone;
229    OMX_PTR pBuf;
230
231    ret = Exynos_OSAL_GetInfoFromMetaData((OMX_BYTE)pBuffer, &pBuf);
232    if (ret == OMX_ErrorNone) {
233        ret = Exynos_OSAL_LockANBHandle((OMX_U32)pBuf, width, height, format, planes);
234        *pStride = Exynos_OSAL_GetANBStride((OMX_U32)pBuf);
235    }
236
237EXIT:
238    FunctionOut();
239
240    return ret;
241}
242
243OMX_ERRORTYPE Exynos_OSAL_UnlockMetaData(OMX_IN OMX_PTR pBuffer)
244{
245    FunctionIn();
246
247    OMX_ERRORTYPE ret = OMX_ErrorNone;
248    OMX_PTR pBuf;
249
250    ret = Exynos_OSAL_GetInfoFromMetaData((OMX_BYTE)pBuffer, &pBuf);
251    if (ret == OMX_ErrorNone)
252        ret = Exynos_OSAL_UnlockANBHandle((OMX_U32)pBuf);
253
254EXIT:
255    FunctionOut();
256
257    return ret;
258}
259
260OMX_HANDLETYPE Exynos_OSAL_RefANB_Create()
261{
262    int i = 0;
263    EXYNOS_OMX_REF_HANDLE *phREF = NULL;
264    OMX_ERRORTYPE err = OMX_ErrorNone;
265
266    FunctionIn();
267
268    phREF = (EXYNOS_OMX_REF_HANDLE *) Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_REF_HANDLE));
269    if (phREF == NULL)
270        goto EXIT;
271
272    Exynos_OSAL_Memset(phREF, 0, sizeof(EXYNOS_OMX_REF_HANDLE));
273    for (i = 0; i < MAX_BUFFER_REF; i++) {
274        phREF->SharedBuffer[i].BufferFd  = -1;
275        phREF->SharedBuffer[i].BufferFd1 = -1;
276        phREF->SharedBuffer[i].BufferFd2 = -1;
277    }
278
279    err = Exynos_OSAL_MutexCreate(&phREF->hMutex);
280    if (err != OMX_ErrorNone) {
281        Exynos_OSAL_Free(phREF);
282        phREF = NULL;
283    }
284
285EXIT:
286    FunctionOut();
287
288    return ((OMX_HANDLETYPE)phREF);
289}
290
291OMX_ERRORTYPE Exynos_OSAL_RefANB_Reset(OMX_HANDLETYPE hREF)
292{
293    int i = 0;
294    OMX_ERRORTYPE ret = OMX_ErrorNone;
295    EXYNOS_OMX_REF_HANDLE *phREF = (EXYNOS_OMX_REF_HANDLE *)hREF;
296    gralloc_module_t* module = NULL;
297
298    FunctionIn();
299
300    if (phREF == NULL) {
301        ret = OMX_ErrorBadParameter;
302        goto EXIT;
303    }
304
305    hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&module);
306
307    Exynos_OSAL_MutexLock(phREF->hMutex);
308    for (i = 0; i < MAX_BUFFER_REF; i++) {
309        if (phREF->SharedBuffer[i].BufferFd > -1) {
310            while(phREF->SharedBuffer[i].cnt > 0) {
311                if (phREF->SharedBuffer[i].BufferFd > -1)
312                    ion_decRef(getIonFd(module), phREF->SharedBuffer[i].pIonHandle);
313                if (phREF->SharedBuffer[i].BufferFd1 > -1)
314                    ion_decRef(getIonFd(module), phREF->SharedBuffer[i].pIonHandle1);
315                if (phREF->SharedBuffer[i].BufferFd2 > -1)
316                    ion_decRef(getIonFd(module), phREF->SharedBuffer[i].pIonHandle2);
317                phREF->SharedBuffer[i].cnt--;
318            }
319            phREF->SharedBuffer[i].BufferFd    = -1;
320            phREF->SharedBuffer[i].BufferFd1   = -1;
321            phREF->SharedBuffer[i].BufferFd2   = -1;
322            phREF->SharedBuffer[i].pIonHandle  = NULL;
323            phREF->SharedBuffer[i].pIonHandle1 = NULL;
324            phREF->SharedBuffer[i].pIonHandle2 = NULL;
325        }
326    }
327    Exynos_OSAL_MutexUnlock(phREF->hMutex);
328
329EXIT:
330    FunctionOut();
331
332    return ret;
333}
334
335OMX_ERRORTYPE Exynos_OSAL_RefANB_Terminate(OMX_HANDLETYPE hREF)
336{
337    OMX_ERRORTYPE ret = OMX_ErrorNone;
338    EXYNOS_OMX_REF_HANDLE *phREF = (EXYNOS_OMX_REF_HANDLE *)hREF;
339    FunctionIn();
340
341    if (phREF == NULL) {
342        ret = OMX_ErrorBadParameter;
343        goto EXIT;
344    }
345
346    Exynos_OSAL_RefANB_Reset(phREF);
347
348    ret = Exynos_OSAL_MutexTerminate(phREF->hMutex);
349    if (ret != OMX_ErrorNone)
350        goto EXIT;
351
352    Exynos_OSAL_Free(phREF);
353    phREF = NULL;
354
355EXIT:
356    FunctionOut();
357
358    return ret;
359}
360
361OMX_ERRORTYPE Exynos_OSAL_RefANB_Increase(OMX_HANDLETYPE hREF, OMX_PTR pBuffer)
362{
363    int i;
364    OMX_ERRORTYPE ret = OMX_ErrorNone;
365    buffer_handle_t bufferHandle = (buffer_handle_t) pBuffer;//pANB->handle;
366    private_handle_t *priv_hnd = (private_handle_t *) bufferHandle;
367    EXYNOS_OMX_REF_HANDLE *phREF = (EXYNOS_OMX_REF_HANDLE *)hREF;
368    gralloc_module_t* module = NULL;
369
370    unsigned long *pIonHandle;
371    unsigned long *pIonHandle1;
372    unsigned long *pIonHandle2;
373
374    FunctionIn();
375
376    if (phREF == NULL) {
377        ret = OMX_ErrorBadParameter;
378        goto EXIT;
379    }
380
381    hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&module);
382
383    Exynos_OSAL_MutexLock(phREF->hMutex);
384
385    if (priv_hnd->fd >= 0) {
386        ion_incRef(getIonFd(module), priv_hnd->fd, &pIonHandle);
387    }
388    if (priv_hnd->fd1 >= 0) {
389        ion_incRef(getIonFd(module), priv_hnd->fd1, &pIonHandle1);
390    }
391    if (priv_hnd->fd2 >= 0) {
392        ion_incRef(getIonFd(module), priv_hnd->fd2, &pIonHandle2);
393    }
394
395    for (i = 0; i < MAX_BUFFER_REF; i++) {
396        if (phREF->SharedBuffer[i].BufferFd == priv_hnd->fd) {
397            phREF->SharedBuffer[i].cnt++;
398            break;
399        }
400    }
401
402    if (i >=  MAX_BUFFER_REF) {
403        for (i = 0; i < MAX_BUFFER_REF; i++) {
404            if (phREF->SharedBuffer[i].BufferFd == -1) {
405                phREF->SharedBuffer[i].BufferFd    = priv_hnd->fd;
406                phREF->SharedBuffer[i].BufferFd1   = priv_hnd->fd1;
407                phREF->SharedBuffer[i].BufferFd2   = priv_hnd->fd2;
408                phREF->SharedBuffer[i].pIonHandle  = pIonHandle;
409                phREF->SharedBuffer[i].pIonHandle1 = pIonHandle1;
410                phREF->SharedBuffer[i].pIonHandle2 = pIonHandle2;
411                phREF->SharedBuffer[i].cnt++;
412                break;
413            }
414        }
415    }
416
417    Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "inc fd:%d cnt:%d", phREF->SharedBuffer[i].BufferFd, phREF->SharedBuffer[i].cnt);
418
419    Exynos_OSAL_MutexUnlock(phREF->hMutex);
420
421    if (i >=  MAX_BUFFER_REF) {
422        ret = OMX_ErrorUndefined;
423    }
424
425EXIT:
426    FunctionOut();
427
428    return ret;
429}
430
431OMX_ERRORTYPE Exynos_OSAL_RefANB_Decrease(OMX_HANDLETYPE hREF, OMX_U32 BufferFd)
432{
433    int i;
434    OMX_ERRORTYPE ret = OMX_ErrorNone;
435    EXYNOS_OMX_REF_HANDLE *phREF = (EXYNOS_OMX_REF_HANDLE *)hREF;
436    gralloc_module_t* module = NULL;
437
438    FunctionIn();
439
440    if ((phREF == NULL) || (BufferFd < 0)) {
441        ret = OMX_ErrorBadParameter;
442        goto EXIT;
443    }
444
445    Exynos_OSAL_MutexLock(phREF->hMutex);
446    hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&module);
447    for (i = 0; i < MAX_BUFFER_REF; i++) {
448        if (phREF->SharedBuffer[i].BufferFd == BufferFd) {
449            ion_decRef(getIonFd(module), phREF->SharedBuffer[i].pIonHandle);
450            ion_decRef(getIonFd(module), phREF->SharedBuffer[i].pIonHandle1);
451            ion_decRef(getIonFd(module), phREF->SharedBuffer[i].pIonHandle2);
452            phREF->SharedBuffer[i].cnt--;
453            if (phREF->SharedBuffer[i].cnt == 0) {
454                phREF->SharedBuffer[i].BufferFd    = -1;
455                phREF->SharedBuffer[i].BufferFd1   = -1;
456                phREF->SharedBuffer[i].BufferFd2   = -1;
457                phREF->SharedBuffer[i].pIonHandle  = NULL;
458                phREF->SharedBuffer[i].pIonHandle1 = NULL;
459                phREF->SharedBuffer[i].pIonHandle2 = NULL;
460            }
461            break;
462        }
463    }
464    Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "dec fd:%d cnt:%d", phREF->SharedBuffer[i].BufferFd, phREF->SharedBuffer[i].cnt);
465
466    Exynos_OSAL_MutexUnlock(phREF->hMutex);
467
468    if (i >=  MAX_BUFFER_REF) {
469        ret = OMX_ErrorUndefined;
470        goto EXIT;
471    }
472
473EXIT:
474    FunctionOut();
475
476    return ret;
477}
478
479OMX_ERRORTYPE useAndroidNativeBuffer(
480    EXYNOS_OMX_BASEPORT      *pExynosPort,
481    OMX_BUFFERHEADERTYPE **ppBufferHdr,
482    OMX_U32                nPortIndex,
483    OMX_PTR                pAppPrivate,
484    OMX_U32                nSizeBytes,
485    OMX_U8                *pBuffer)
486{
487    OMX_ERRORTYPE         ret = OMX_ErrorNone;
488    OMX_BUFFERHEADERTYPE *temp_bufferHeader = NULL;
489    unsigned int          i = 0;
490    OMX_U32               width, height;
491    OMX_U32               stride;
492    ExynosVideoPlane      planes[MAX_BUFFER_PLANE];
493
494    FunctionIn();
495
496    if (pExynosPort == NULL) {
497        ret = OMX_ErrorBadParameter;
498        goto EXIT;
499    }
500    if (pExynosPort->portState != OMX_StateIdle) {
501        ret = OMX_ErrorIncorrectStateOperation;
502        goto EXIT;
503    }
504    if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) {
505        ret = OMX_ErrorBadPortIndex;
506        goto EXIT;
507    }
508
509    temp_bufferHeader = (OMX_BUFFERHEADERTYPE *)Exynos_OSAL_Malloc(sizeof(OMX_BUFFERHEADERTYPE));
510    if (temp_bufferHeader == NULL) {
511        ret = OMX_ErrorInsufficientResources;
512        goto EXIT;
513    }
514    Exynos_OSAL_Memset(temp_bufferHeader, 0, sizeof(OMX_BUFFERHEADERTYPE));
515
516    for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) {
517        if (pExynosPort->bufferStateAllocate[i] == BUFFER_STATE_FREE) {
518            pExynosPort->extendBufferHeader[i].OMXBufferHeader = temp_bufferHeader;
519            pExynosPort->bufferStateAllocate[i] = (BUFFER_STATE_ASSIGNED | HEADER_STATE_ALLOCATED);
520            INIT_SET_SIZE_VERSION(temp_bufferHeader, OMX_BUFFERHEADERTYPE);
521            temp_bufferHeader->pBuffer        = pBuffer;
522            temp_bufferHeader->nAllocLen      = nSizeBytes;
523            temp_bufferHeader->pAppPrivate    = pAppPrivate;
524            if (nPortIndex == INPUT_PORT_INDEX)
525                temp_bufferHeader->nInputPortIndex = INPUT_PORT_INDEX;
526            else
527                temp_bufferHeader->nOutputPortIndex = OUTPUT_PORT_INDEX;
528
529            width = pExynosPort->portDefinition.format.video.nFrameWidth;
530            height = pExynosPort->portDefinition.format.video.nFrameHeight;
531            Exynos_OSAL_LockANB(temp_bufferHeader->pBuffer, width, height,
532                                pExynosPort->portDefinition.format.video.eColorFormat,
533                                &stride, planes);
534            pExynosPort->extendBufferHeader[i].buf_fd[0] = planes[0].fd;
535            pExynosPort->extendBufferHeader[i].pYUVBuf[0] = planes[0].addr;
536            pExynosPort->extendBufferHeader[i].buf_fd[1] = planes[1].fd;
537            pExynosPort->extendBufferHeader[i].pYUVBuf[1] = planes[1].addr;
538            pExynosPort->extendBufferHeader[i].buf_fd[2] = planes[2].fd;
539            pExynosPort->extendBufferHeader[i].pYUVBuf[2] = planes[2].addr;
540            Exynos_OSAL_UnlockANB(temp_bufferHeader->pBuffer);
541            Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "useAndroidNativeBuffer: buf %d pYUVBuf[0]:0x%x (fd:%d), pYUVBuf[1]:0x%x (fd:%d)",
542                            i, pExynosPort->extendBufferHeader[i].pYUVBuf[0], planes[0].fd,
543                            pExynosPort->extendBufferHeader[i].pYUVBuf[1], planes[1].fd);
544
545            pExynosPort->assignedBufferNum++;
546            if (pExynosPort->assignedBufferNum == pExynosPort->portDefinition.nBufferCountActual) {
547                pExynosPort->portDefinition.bPopulated = OMX_TRUE;
548                /* Exynos_OSAL_MutexLock(pExynosComponent->compMutex); */
549                Exynos_OSAL_SemaphorePost(pExynosPort->loadedResource);
550                /* Exynos_OSAL_MutexUnlock(pExynosComponent->compMutex); */
551            }
552            *ppBufferHdr = temp_bufferHeader;
553            ret = OMX_ErrorNone;
554
555            goto EXIT;
556        }
557    }
558
559    Exynos_OSAL_Free(temp_bufferHeader);
560    ret = OMX_ErrorInsufficientResources;
561
562EXIT:
563    FunctionOut();
564
565    return ret;
566}
567
568OMX_ERRORTYPE Exynos_OSAL_GetANBParameter(
569    OMX_IN OMX_HANDLETYPE hComponent,
570    OMX_IN OMX_INDEXTYPE  nIndex,
571    OMX_INOUT OMX_PTR     ComponentParameterStructure)
572{
573    OMX_ERRORTYPE          ret = OMX_ErrorNone;
574    OMX_COMPONENTTYPE     *pOMXComponent = NULL;
575    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
576
577    FunctionIn();
578
579    if (hComponent == NULL) {
580        ret = OMX_ErrorBadParameter;
581        goto EXIT;
582    }
583
584    pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
585    ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE));
586    if (ret != OMX_ErrorNone) {
587        goto EXIT;
588    }
589
590    if (pOMXComponent->pComponentPrivate == NULL) {
591        ret = OMX_ErrorBadParameter;
592        goto EXIT;
593    }
594
595    pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
596    if (pExynosComponent->currentState == OMX_StateInvalid ) {
597        ret = OMX_ErrorInvalidState;
598        goto EXIT;
599    }
600
601    if (ComponentParameterStructure == NULL) {
602        ret = OMX_ErrorBadParameter;
603        goto EXIT;
604    }
605
606    switch (nIndex) {
607    case OMX_IndexParamGetAndroidNativeBuffer:
608    {
609        GetAndroidNativeBufferUsageParams *pANBParams = (GetAndroidNativeBufferUsageParams *) ComponentParameterStructure;
610        OMX_U32 portIndex = pANBParams->nPortIndex;
611
612        Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s: OMX_IndexParamGetAndroidNativeBuffer", __func__);
613
614        ret = Exynos_OMX_Check_SizeVersion(pANBParams, sizeof(GetAndroidNativeBufferUsageParams));
615        if (ret != OMX_ErrorNone) {
616            Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Exynos_OMX_Check_SizeVersion(GetAndroidNativeBufferUsageParams) is failed", __func__);
617            goto EXIT;
618        }
619
620        if (portIndex >= pExynosComponent->portParam.nPorts) {
621            ret = OMX_ErrorBadPortIndex;
622            goto EXIT;
623        }
624
625        /* NOTE: OMX_IndexParamGetAndroidNativeBuffer returns original 'nUsage' without any
626         * modifications since currently not defined what the 'nUsage' is for.
627         */
628        pANBParams->nUsage |= (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
629    }
630        break;
631
632    default:
633    {
634        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Unsupported index (%d)", __func__, nIndex);
635        ret = OMX_ErrorUnsupportedIndex;
636        goto EXIT;
637    }
638        break;
639    }
640
641EXIT:
642    FunctionOut();
643
644    return ret;
645}
646
647OMX_ERRORTYPE Exynos_OSAL_SetANBParameter(
648    OMX_IN OMX_HANDLETYPE hComponent,
649    OMX_IN OMX_INDEXTYPE  nIndex,
650    OMX_IN OMX_PTR        ComponentParameterStructure)
651{
652    OMX_ERRORTYPE          ret = OMX_ErrorNone;
653    OMX_COMPONENTTYPE     *pOMXComponent = NULL;
654    EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
655
656    FunctionIn();
657
658    if (hComponent == NULL) {
659        ret = OMX_ErrorBadParameter;
660        goto EXIT;
661    }
662
663    pOMXComponent = (OMX_COMPONENTTYPE *)hComponent;
664    ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE));
665    if (ret != OMX_ErrorNone) {
666        goto EXIT;
667    }
668
669    if (pOMXComponent->pComponentPrivate == NULL) {
670        ret = OMX_ErrorBadParameter;
671        goto EXIT;
672    }
673
674    pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
675    if (pExynosComponent->currentState == OMX_StateInvalid ) {
676        ret = OMX_ErrorInvalidState;
677        goto EXIT;
678    }
679
680    if (ComponentParameterStructure == NULL) {
681        ret = OMX_ErrorBadParameter;
682        goto EXIT;
683    }
684
685    switch (nIndex) {
686    case OMX_IndexParamEnableAndroidBuffers:
687    {
688        EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
689        EnableAndroidNativeBuffersParams *pANBParams = (EnableAndroidNativeBuffersParams *) ComponentParameterStructure;
690        OMX_U32 portIndex = pANBParams->nPortIndex;
691        EXYNOS_OMX_BASEPORT *pExynosPort = NULL;
692
693        Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s: OMX_IndexParamEnableAndroidNativeBuffers", __func__);
694
695        ret = Exynos_OMX_Check_SizeVersion(pANBParams, sizeof(EnableAndroidNativeBuffersParams));
696        if (ret != OMX_ErrorNone) {
697            Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Exynos_OMX_Check_SizeVersion(EnableAndroidNativeBuffersParams) is failed", __func__);
698            goto EXIT;
699        }
700
701        if (portIndex >= pExynosComponent->portParam.nPorts) {
702            ret = OMX_ErrorBadPortIndex;
703            goto EXIT;
704        }
705
706        pExynosPort = &pExynosComponent->pExynosPort[portIndex];
707        if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) {
708            ret = OMX_ErrorBadPortIndex;
709            goto EXIT;
710        }
711
712        /* ANB and DPB Buffer Sharing */
713        if (pExynosPort->bStoreMetaData != OMX_TRUE)
714            pExynosPort->bIsANBEnabled = pANBParams->enable;
715        if ((portIndex == OUTPUT_PORT_INDEX) &&
716            (pExynosPort->bIsANBEnabled == OMX_TRUE) &&
717            ((pExynosPort->bufferProcessType & BUFFER_ANBSHARE) == BUFFER_ANBSHARE)) {
718            pExynosPort->bufferProcessType = BUFFER_SHARE;
719            pExynosPort->portDefinition.format.video.eColorFormat = (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled;
720            Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "OMX_IndexParamEnableAndroidBuffers & bufferProcessType change to BUFFER_SHARE");
721        }
722    }
723        break;
724
725    case OMX_IndexParamUseAndroidNativeBuffer:
726    {
727        EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;
728        UseAndroidNativeBufferParams *pANBParams = (UseAndroidNativeBufferParams *) ComponentParameterStructure;
729        OMX_U32 portIndex = pANBParams->nPortIndex;
730        EXYNOS_OMX_BASEPORT *pExynosPort = NULL;
731        android_native_buffer_t *pANB;
732        OMX_U32 nSizeBytes;
733
734        Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s: OMX_IndexParamUseAndroidNativeBuffer, portIndex: %d", __func__, portIndex);
735
736        ret = Exynos_OMX_Check_SizeVersion(pANBParams, sizeof(UseAndroidNativeBufferParams));
737        if (ret != OMX_ErrorNone) {
738            Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Exynos_OMX_Check_SizeVersion(UseAndroidNativeBufferParams) is failed", __func__);
739            goto EXIT;
740        }
741
742        if (portIndex >= pExynosComponent->portParam.nPorts) {
743            ret = OMX_ErrorBadPortIndex;
744            goto EXIT;
745        }
746
747        pExynosPort = &pExynosComponent->pExynosPort[portIndex];
748        if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) {
749            ret = OMX_ErrorBadPortIndex;
750            goto EXIT;
751        }
752
753        if (pExynosPort->portState != OMX_StateIdle) {
754            Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Port state should be IDLE", __func__);
755            ret = OMX_ErrorIncorrectStateOperation;
756            goto EXIT;
757        }
758
759        pANB = pANBParams->nativeBuffer.get();
760
761        /* MALI alignment restriction */
762        nSizeBytes = ALIGN(pANB->width, 16) * ALIGN(pANB->height, 16);
763        nSizeBytes += ALIGN(pANB->width / 2, 16) * ALIGN(pANB->height / 2, 16) * 2;
764
765        ret = useAndroidNativeBuffer(pExynosPort,
766                                     pANBParams->bufferHeader,
767                                     pANBParams->nPortIndex,
768                                     pANBParams->pAppPrivate,
769                                     nSizeBytes,
770                                     (OMX_U8 *) pANB);
771        if (ret != OMX_ErrorNone) {
772            Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: useAndroidNativeBuffer is failed: err=0x%x", __func__,ret);
773            goto EXIT;
774        }
775    }
776        break;
777
778    case OMX_IndexParamStoreMetaDataBuffer:
779    {
780        StoreMetaDataInBuffersParams *pANBParams = (StoreMetaDataInBuffersParams *) ComponentParameterStructure;
781        OMX_U32 portIndex = pANBParams->nPortIndex;
782        EXYNOS_OMX_BASEPORT *pExynosPort = NULL;
783
784        Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s: OMX_IndexParamStoreMetaDataBuffer", __func__);
785
786        ret = Exynos_OMX_Check_SizeVersion(pANBParams, sizeof(StoreMetaDataInBuffersParams));
787        if (ret != OMX_ErrorNone) {
788            Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Exynos_OMX_Check_SizeVersion(StoreMetaDataInBuffersParams) is failed", __func__);
789            goto EXIT;
790        }
791
792        if (portIndex >= pExynosComponent->portParam.nPorts) {
793            ret = OMX_ErrorBadPortIndex;
794            goto EXIT;
795        }
796
797        pExynosPort = &pExynosComponent->pExynosPort[portIndex];
798        if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) {
799            ret = OMX_ErrorBadPortIndex;
800            goto EXIT;
801        }
802
803        // WORKAROUND: do not advertise metadata mode support for VP8 decoder until it can handle dynamic resolution change
804        // TRICKY: check VP8 decode feature on input port, but matching feature in on output port
805        bool isVP8Decoder = pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.eCompressionFormat == OMX_VIDEO_CodingVPX;
806        if (isVP8Decoder && portIndex == OUTPUT_PORT_INDEX) {
807            ret = OMX_ErrorNotImplemented;
808            goto EXIT;
809        }
810
811        pExynosPort->bStoreMetaData = pANBParams->bStoreMetaData;
812        if (pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) {
813            EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle;;
814            pVideoEnc->bFirstInput = OMX_TRUE;
815        } else if (pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) {
816            EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle;;
817            if ((portIndex == OUTPUT_PORT_INDEX) &&
818                (pExynosPort->bStoreMetaData == OMX_TRUE) &&
819                ((pExynosPort->bufferProcessType & BUFFER_ANBSHARE) == BUFFER_ANBSHARE)) {
820                pExynosPort->bufferProcessType = BUFFER_SHARE;
821                pExynosPort->portDefinition.format.video.eColorFormat = (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled;
822                Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "OMX_IndexParamStoreMetaDataBuffer & bufferProcessType change to BUFFER_SHARE");
823            }
824
825        }
826    }
827        break;
828
829    default:
830    {
831        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Unsupported index (%d)", __func__, nIndex);
832        ret = OMX_ErrorUnsupportedIndex;
833        goto EXIT;
834    }
835        break;
836    }
837
838EXIT:
839    FunctionOut();
840
841    return ret;
842}
843
844OMX_ERRORTYPE Exynos_OSAL_GetInfoFromMetaData(OMX_IN OMX_BYTE pBuffer,
845                                           OMX_OUT OMX_PTR *ppBuf)
846{
847    OMX_ERRORTYPE      ret = OMX_ErrorNone;
848    MetadataBufferType type;
849
850    FunctionIn();
851
852/*
853 * meta data contains the following data format.
854 * payload depends on the MetadataBufferType
855 * --------------------------------------------------------------
856 * | MetadataBufferType                         |          payload                           |
857 * --------------------------------------------------------------
858 *
859 * If MetadataBufferType is kMetadataBufferTypeCameraSource, then
860 * --------------------------------------------------------------
861 * | kMetadataBufferTypeCameraSource  | physical addr. of Y |physical addr. of CbCr |
862 * --------------------------------------------------------------
863 *
864 * If MetadataBufferType is kMetadataBufferTypeGrallocSource, then
865 * --------------------------------------------------------------
866 * | kMetadataBufferTypeGrallocSource    | buffer_handle_t |
867 * --------------------------------------------------------------
868 */
869
870    /* MetadataBufferType */
871    Exynos_OSAL_Memcpy(&type, (MetadataBufferType *)pBuffer, sizeof(MetadataBufferType));
872
873    if (type == kMetadataBufferTypeCameraSource) {
874        void *pAddress = NULL;
875
876        /* Address. of Y */
877        Exynos_OSAL_Memcpy(&pAddress, pBuffer + sizeof(MetadataBufferType), sizeof(void *));
878        ppBuf[0] = (void *)pAddress;
879
880        /* Address. of CbCr */
881        Exynos_OSAL_Memcpy(&pAddress, pBuffer + sizeof(MetadataBufferType) + sizeof(void *), sizeof(void *));
882        ppBuf[1] = (void *)pAddress;
883
884    } else if (type == kMetadataBufferTypeGrallocSource) {
885        buffer_handle_t    pBufHandle;
886
887        /* buffer_handle_t */
888        Exynos_OSAL_Memcpy(&pBufHandle, pBuffer + sizeof(MetadataBufferType), sizeof(buffer_handle_t));
889        ppBuf[0] = (OMX_PTR)pBufHandle;
890    }
891
892EXIT:
893    FunctionOut();
894
895    return ret;
896}
897
898OMX_ERRORTYPE Exynos_OSAL_SetPrependSPSPPSToIDR(
899    OMX_PTR pComponentParameterStructure,
900    OMX_PTR pbPrependSpsPpsToIdr)
901{
902    OMX_ERRORTYPE                    ret        = OMX_ErrorNone;
903    PrependSPSPPSToIDRFramesParams  *pANBParams = (PrependSPSPPSToIDRFramesParams *)pComponentParameterStructure;
904
905    ret = Exynos_OMX_Check_SizeVersion(pANBParams, sizeof(PrependSPSPPSToIDRFramesParams));
906    if (ret != OMX_ErrorNone) {
907        Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Exynos_OMX_Check_SizeVersion(PrependSPSPPSToIDRFrames) is failed", __func__);
908        goto EXIT;
909    }
910
911    (*((OMX_BOOL *)pbPrependSpsPpsToIdr)) = pANBParams->bEnable;
912
913EXIT:
914    return ret;
915}
916
917OMX_COLOR_FORMATTYPE Exynos_OSAL_Hal2OMXPixelFormat(
918    unsigned int hal_format)
919{
920    OMX_COLOR_FORMATTYPE omx_format;
921    switch (hal_format) {
922    case HAL_PIXEL_FORMAT_YCbCr_422_I:
923        omx_format = OMX_COLOR_FormatYCbYCr;
924        break;
925    case HAL_PIXEL_FORMAT_YCbCr_420_P:
926        omx_format = OMX_COLOR_FormatYUV420Planar;
927        break;
928    case HAL_PIXEL_FORMAT_YCbCr_420_SP:
929        omx_format = OMX_COLOR_FormatYUV420SemiPlanar;
930        break;
931    case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED:
932        omx_format = (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12TPhysicalAddress;
933        break;
934    case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
935        omx_format = (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled;
936        break;
937    case HAL_PIXEL_FORMAT_BGRA_8888:
938    case HAL_PIXEL_FORMAT_CUSTOM_ARGB_8888:
939        omx_format = OMX_COLOR_Format32bitARGB8888;
940        break;
941    default:
942        omx_format = OMX_COLOR_FormatYUV420Planar;
943        break;
944    }
945    return omx_format;
946}
947
948unsigned int Exynos_OSAL_OMX2HalPixelFormat(
949    OMX_COLOR_FORMATTYPE omx_format)
950{
951    unsigned int hal_format;
952    switch (omx_format) {
953    case OMX_COLOR_FormatYCbYCr:
954        hal_format = HAL_PIXEL_FORMAT_YCbCr_422_I;
955        break;
956    case OMX_COLOR_FormatYUV420Planar:
957        hal_format = HAL_PIXEL_FORMAT_YCbCr_420_P;
958        break;
959    case OMX_COLOR_FormatYUV420SemiPlanar:
960        hal_format = HAL_PIXEL_FORMAT_YCbCr_420_SP;
961        break;
962    case OMX_SEC_COLOR_FormatNV12TPhysicalAddress:
963        hal_format = HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED;
964        break;
965    case OMX_SEC_COLOR_FormatNV12Tiled:
966        hal_format = HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED;
967        break;
968    case OMX_COLOR_Format32bitARGB8888:
969        hal_format = HAL_PIXEL_FORMAT_CUSTOM_ARGB_8888;
970        break;
971    default:
972        hal_format = HAL_PIXEL_FORMAT_YCbCr_420_P;
973        break;
974    }
975    return hal_format;
976}
977
978
979#ifdef __cplusplus
980}
981#endif
982