blob: 2e8a758c4d6fd7008ba4e670cdd58478c6632d60 [file] [log] [blame]
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001/*
Jiho Chang20d3e6e2012-03-24 03:43:08 +09002 *
Jiho Chang38ef2572012-06-01 20:58:55 +00003 * Copyright 2012 Samsung Electronics S.LSI Co. LTD
Jiho Chang20d3e6e2012-03-24 03:43:08 +09004 *
Jiho Chang38ef2572012-06-01 20:58:55 +00005 * Licensed under the Apache License, Version 2.0 (the "License");
Jiho Chang20d3e6e2012-03-24 03:43:08 +09006 * 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 ExynosVideoDecoder.c
20 * @brief
21 * @author Jinsung Yang (jsgood.yang@samsung.com)
22 * @version 1.0.0
23 * @history
24 * 2012.01.15: Initial Version
25 */
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <unistd.h>
30#include <string.h>
31#include <fcntl.h>
32
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <sys/ioctl.h>
36#include <sys/mman.h>
Jiho Chang38ef2572012-06-01 20:58:55 +000037#include <pthread.h>
Jiho Chang20d3e6e2012-03-24 03:43:08 +090038
39#include <sys/poll.h>
40
41#include "ExynosVideoApi.h"
42#include "ExynosVideoDec.h"
Jiho Chang20d3e6e2012-03-24 03:43:08 +090043
44/* #define LOG_NDEBUG 0 */
45#define LOG_TAG "ExynosVideoDecoder"
46#include <utils/Log.h>
47
48/*
49 * [Common] __CodingType_To_V4L2PixelFormat
50 */
51static unsigned int __CodingType_To_V4L2PixelFormat(ExynosVideoCodingType codingType)
52{
53 unsigned int pixelformat = V4L2_PIX_FMT_H264;
54
55 switch (codingType) {
56 case VIDEO_CODING_AVC:
57 pixelformat = V4L2_PIX_FMT_H264;
58 break;
59 case VIDEO_CODING_MPEG4:
60 pixelformat = V4L2_PIX_FMT_MPEG4;
61 break;
62 case VIDEO_CODING_VP8:
63 pixelformat = V4L2_PIX_FMT_VP8;
64 break;
65 case VIDEO_CODING_H263:
66 pixelformat = V4L2_PIX_FMT_H263;
67 break;
68 case VIDEO_CODING_VC1:
69 pixelformat = V4L2_PIX_FMT_VC1_ANNEX_G;
70 break;
71 case VIDEO_CODING_VC1_RCV:
72 pixelformat = V4L2_PIX_FMT_VC1_ANNEX_L;
73 break;
74 case VIDEO_CODING_MPEG2:
Jiho Chang800a8d72012-04-26 13:25:31 -070075 pixelformat = V4L2_PIX_FMT_MPEG2;
Jiho Chang20d3e6e2012-03-24 03:43:08 +090076 break;
77 default:
78 pixelformat = V4L2_PIX_FMT_H264;
79 break;
80 }
81
82 return pixelformat;
83}
84
85/*
86 * [Common] __ColorFormatType_To_V4L2PixelFormat
87 */
88static unsigned int __ColorFormatType_To_V4L2PixelFormat(ExynosVideoColorFormatType colorFormatType)
89{
90 unsigned int pixelformat = V4L2_PIX_FMT_NV12M;
91
92 switch (colorFormatType) {
93 case VIDEO_COLORFORMAT_NV12_TILED:
94 pixelformat = V4L2_PIX_FMT_NV12MT_16X16;
95 break;
96 case VIDEO_COLORFORMAT_NV21:
97 pixelformat = V4L2_PIX_FMT_NV21M;
98 break;
99 case VIDEO_COLORFORMAT_NV12:
100 default:
101 pixelformat = V4L2_PIX_FMT_NV12M;
102 break;
103 }
104
105 return pixelformat;
106}
107
108/*
109 * [Decoder OPS] Init
110 */
SeungBeom Kimc94beae2012-07-05 14:59:40 +0900111static void *MFC_Decoder_Init(int nMemoryType)
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900112{
113 ExynosVideoDecContext *pCtx = NULL;
Jiho Chang38ef2572012-06-01 20:58:55 +0000114 pthread_mutex_t *pMutex = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900115 int needCaps = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING);
116
117 pCtx = (ExynosVideoDecContext *)malloc(sizeof(*pCtx));
118 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700119 ALOGE("%s: Failed to allocate decoder context buffer", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900120 goto EXIT_ALLOC_FAIL;
121 }
122
123 memset(pCtx, 0, sizeof(*pCtx));
124
Jiho Chang38ef2572012-06-01 20:58:55 +0000125 pCtx->hDec = exynos_v4l2_open_devname(VIDEO_DECODER_NAME, O_RDWR, 0);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900126 if (pCtx->hDec < 0) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700127 ALOGE("%s: Failed to open decoder device", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900128 goto EXIT_OPEN_FAIL;
129 }
130
131 if (!exynos_v4l2_querycap(pCtx->hDec, needCaps)) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700132 ALOGE("%s: Failed to querycap", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900133 goto EXIT_QUERYCAP_FAIL;
134 }
135
136 pCtx->bStreamonInbuf = VIDEO_FALSE;
137 pCtx->bStreamonOutbuf = VIDEO_FALSE;
138
SeungBeom Kimc94beae2012-07-05 14:59:40 +0900139 pCtx->nMemoryType = nMemoryType;
SeungBeom Kim1f0d5e32012-07-03 15:45:57 +0900140
Jiho Chang38ef2572012-06-01 20:58:55 +0000141 pMutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
142 if (pMutex == NULL) {
143 ALOGE("%s: Failed to allocate mutex about input buffer", __func__);
144 goto EXIT_QUERYCAP_FAIL;
145 }
Jiho Chang38ef2572012-06-01 20:58:55 +0000146 if (pthread_mutex_init(pMutex, NULL) != 0) {
147 free(pMutex);
148 goto EXIT_QUERYCAP_FAIL;
149 }
150 pCtx->pInMutex = (void*)pMutex;
151
152 pMutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
153 if (pMutex == NULL) {
154 ALOGE("%s: Failed to allocate mutex about output buffer", __func__);
155 goto EXIT_QUERYCAP_FAIL;
156 }
Jiho Chang38ef2572012-06-01 20:58:55 +0000157 if (pthread_mutex_init(pMutex, NULL) != 0) {
158 free(pMutex);
159 goto EXIT_QUERYCAP_FAIL;
160 }
161 pCtx->pOutMutex = (void*)pMutex;
162
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900163 return (void *)pCtx;
164
165EXIT_QUERYCAP_FAIL:
Jiho Chang38ef2572012-06-01 20:58:55 +0000166 if (pCtx->pInMutex != NULL) {
167 pthread_mutex_destroy(pCtx->pInMutex);
168 free(pCtx->pInMutex);
169 }
170
171 if (pCtx->pOutMutex != NULL) {
172 pthread_mutex_destroy(pCtx->pOutMutex);
173 free(pCtx->pOutMutex);
174 }
175
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900176 close(pCtx->hDec);
177
178EXIT_OPEN_FAIL:
179 free(pCtx);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900180
181EXIT_ALLOC_FAIL:
182 return NULL;
183}
184
185/*
186 * [Decoder OPS] Finalize
187 */
188static ExynosVideoErrorType MFC_Decoder_Finalize(void *pHandle)
189{
Jiho Chang38ef2572012-06-01 20:58:55 +0000190 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
191 ExynosVideoPlane *pVideoPlane = NULL;
192 pthread_mutex_t *pMutex = NULL;
193 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900194 int i, j;
195
196 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700197 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900198 ret = VIDEO_ERROR_BADPARAM;
199 goto EXIT;
200 }
201
Jiho Chang38ef2572012-06-01 20:58:55 +0000202 if (pCtx->pOutMutex != NULL) {
203 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
204 pthread_mutex_destroy(pMutex);
205 free(pMutex);
206 pCtx->pOutMutex = NULL;
207 }
208
209 if (pCtx->pInMutex != NULL) {
210 pMutex = (pthread_mutex_t*)pCtx->pInMutex;
211 pthread_mutex_destroy(pMutex);
212 free(pMutex);
213 pCtx->pInMutex = NULL;
214 }
215
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900216 if (pCtx->bShareInbuf == VIDEO_FALSE) {
217 for (i = 0; i < pCtx->nInbufs; i++) {
218 for (j = 0; j < VIDEO_DECODER_INBUF_PLANES; j++) {
219 pVideoPlane = &pCtx->pInbuf[i].planes[j];
220 if (pVideoPlane->addr != NULL) {
221 munmap(pVideoPlane->addr, pVideoPlane->allocSize);
222 pVideoPlane->addr = NULL;
223 pVideoPlane->allocSize = 0;
224 pVideoPlane->dataSize = 0;
225 }
226
227 pCtx->pInbuf[i].pGeometry = NULL;
228 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
Jiho Chang38ef2572012-06-01 20:58:55 +0000229 pCtx->pInbuf[i].bRegistered = VIDEO_FALSE;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900230 }
231 }
232 }
233
234 if (pCtx->bShareOutbuf == VIDEO_FALSE) {
235 for (i = 0; i < pCtx->nOutbufs; i++) {
236 for (j = 0; j < VIDEO_DECODER_OUTBUF_PLANES; j++) {
237 pVideoPlane = &pCtx->pOutbuf[i].planes[j];
238 if (pVideoPlane->addr != NULL) {
239 munmap(pVideoPlane->addr, pVideoPlane->allocSize);
240 pVideoPlane->addr = NULL;
241 pVideoPlane->allocSize = 0;
242 pVideoPlane->dataSize = 0;
243 }
244
245 pCtx->pOutbuf[i].pGeometry = NULL;
246 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
Jiho Chang38ef2572012-06-01 20:58:55 +0000247 pCtx->pOutbuf[i].bRegistered = VIDEO_FALSE;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900248 }
249 }
250 }
251
252 if (pCtx->pInbuf != NULL)
253 free(pCtx->pInbuf);
254
255 if (pCtx->pOutbuf != NULL)
256 free(pCtx->pOutbuf);
257
258 if (pCtx->hDec > 0)
259 close(pCtx->hDec);
260
261 free(pCtx);
262
263EXIT:
264 return ret;
265}
266
267/*
268 * [Decoder OPS] Set Frame Tag
269 */
270static ExynosVideoErrorType MFC_Decoder_Set_FrameTag(
271 void *pHandle,
272 int frameTag)
273{
274 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
275 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
276
277 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700278 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900279 ret = VIDEO_ERROR_BADPARAM;
280 goto EXIT;
281 }
282
Jiho Chang38ef2572012-06-01 20:58:55 +0000283 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, frameTag) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900284 ret = VIDEO_ERROR_APIFAIL;
285 goto EXIT;
286 }
287
288EXIT:
289 return ret;
290}
291
292/*
293 * [Decoder OPS] Get Frame Tag
294 */
295static int MFC_Decoder_Get_FrameTag(void *pHandle)
296{
297 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
298 int frameTag = -1;
299
300 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700301 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900302 goto EXIT;
303 }
304
305 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, &frameTag);
306
307EXIT:
308 return frameTag;
309}
310
311/*
312 * [Decoder OPS] Get Buffer Count
313 */
314static int MFC_Decoder_Get_ActualBufferCount(void *pHandle)
315{
316 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
317 int bufferCount = -1;
318
319 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700320 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900321 goto EXIT;
322 }
323
324 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, &bufferCount);
325
326EXIT:
327 return bufferCount;
328}
329
330/*
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900331 * [Decoder OPS] Set Display Delay
332 */
333static ExynosVideoErrorType MFC_Decoder_Set_DisplayDelay(
334 void *pHandle,
335 int delay)
336{
337 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
338 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
339
340 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700341 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900342 ret = VIDEO_ERROR_BADPARAM;
343 goto EXIT;
344 }
345
Jiho Chang38ef2572012-06-01 20:58:55 +0000346 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY, delay) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900347 ret = VIDEO_ERROR_APIFAIL;
348 goto EXIT;
349 }
350
351EXIT:
352 return ret;
353}
354
355/*
356 * [Decoder OPS] Enable Packed PB
357 */
358static ExynosVideoErrorType MFC_Decoder_Enable_PackedPB(void *pHandle)
359{
360 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
361 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
362
363 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700364 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900365 ret = VIDEO_ERROR_BADPARAM;
366 goto EXIT;
367 }
368
Jiho Chang38ef2572012-06-01 20:58:55 +0000369 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_PACKED_PB, 1) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900370 ret = VIDEO_ERROR_APIFAIL;
371 goto EXIT;
372 }
373
374EXIT:
375 return ret;
376}
377
378/*
379 * [Decoder OPS] Enable Loop Filter
380 */
381static ExynosVideoErrorType MFC_Decoder_Enable_LoopFilter(void *pHandle)
382{
383 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
384 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
385
386 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700387 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900388 ret = VIDEO_ERROR_BADPARAM;
389 goto EXIT;
390 }
391
Jiho Chang38ef2572012-06-01 20:58:55 +0000392 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER, 1) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900393 ret = VIDEO_ERROR_APIFAIL;
394 goto EXIT;
395 }
396
397EXIT:
398 return ret;
399}
400
401/*
402 * [Decoder OPS] Enable Slice Mode
403 */
404static ExynosVideoErrorType MFC_Decoder_Enable_SliceMode(void *pHandle)
405{
406 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
407 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
408
409 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700410 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900411 ret = VIDEO_ERROR_BADPARAM;
412 goto EXIT;
413 }
414
Jiho Chang38ef2572012-06-01 20:58:55 +0000415 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE, 1) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900416 ret = VIDEO_ERROR_APIFAIL;
417 goto EXIT;
418 }
419
420EXIT:
421 return ret;
422}
423
424/*
Jiho Chang800a8d72012-04-26 13:25:31 -0700425 * [Decoder OPS] Enable SEI Parsing
426 */
427static ExynosVideoErrorType MFC_Decoder_Enable_SEIParsing(void *pHandle)
428{
429 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
430 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
431
432 if (pCtx == NULL) {
433 ALOGE("%s: Video context info must be supplied", __func__);
434 ret = VIDEO_ERROR_BADPARAM;
435 goto EXIT;
436 }
437
Jiho Chang38ef2572012-06-01 20:58:55 +0000438 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING, 1) != 0) {
Jiho Chang800a8d72012-04-26 13:25:31 -0700439 ret = VIDEO_ERROR_APIFAIL;
440 goto EXIT;
441 }
442
443EXIT:
444 return ret;
445}
446
447/*
448 * [Decoder OPS] Get Frame Packing information
449 */
450static ExynosVideoErrorType MFC_Decoder_Get_FramePackingInfo(
451 void *pHandle,
452 ExynosVideoFramePacking *pFramePacking)
453{
454 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
455 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
456
457 struct v4l2_ext_control ext_ctrl[FRAME_PACK_SEI_INFO_NUM];
458 struct v4l2_ext_controls ext_ctrls;
459
460 int seiAvailable, seiInfo, seiGridPos, i;
461 unsigned int seiArgmtId;
462
463
Jiho Chang38ef2572012-06-01 20:58:55 +0000464 if ((pCtx == NULL) || (pFramePacking == NULL)) {
465 ALOGE("%s: Video context info or FramePacking pointer must be supplied", __func__);
Jiho Chang800a8d72012-04-26 13:25:31 -0700466 ret = VIDEO_ERROR_BADPARAM;
467 goto EXIT;
468 }
469
470 memset(pFramePacking, 0, sizeof(*pFramePacking));
471 memset(ext_ctrl, 0, (sizeof(struct v4l2_ext_control) * FRAME_PACK_SEI_INFO_NUM));
472
473 ext_ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
474 ext_ctrls.count = FRAME_PACK_SEI_INFO_NUM;
475 ext_ctrls.controls = ext_ctrl;
476 ext_ctrl[0].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_AVAIL;
477 ext_ctrl[1].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRGMENT_ID;
478 ext_ctrl[2].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_INFO;
479 ext_ctrl[3].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_GRID_POS;
480
Jiho Chang38ef2572012-06-01 20:58:55 +0000481 if (exynos_v4l2_g_ext_ctrl(pCtx->hDec, &ext_ctrls) != 0) {
Jiho Chang800a8d72012-04-26 13:25:31 -0700482 ret = VIDEO_ERROR_APIFAIL;
483 goto EXIT;
484 }
485
486 seiAvailable = ext_ctrl[0].value;
487 seiArgmtId = ext_ctrl[1].value;
488 seiInfo = ext_ctrl[2].value;
489 seiGridPos = ext_ctrl[3].value;
490
491 pFramePacking->available = seiAvailable;
492 pFramePacking->arrangement_id = seiArgmtId;
493
494 pFramePacking->arrangement_cancel_flag = OPERATE_BIT(seiInfo, 0x1, 0);
495 pFramePacking->arrangement_type = OPERATE_BIT(seiInfo, 0x3f, 1);
496 pFramePacking->quincunx_sampling_flag = OPERATE_BIT(seiInfo, 0x1, 8);
497 pFramePacking->content_interpretation_type = OPERATE_BIT(seiInfo, 0x3f, 9);
498 pFramePacking->spatial_flipping_flag = OPERATE_BIT(seiInfo, 0x1, 15);
499 pFramePacking->frame0_flipped_flag = OPERATE_BIT(seiInfo, 0x1, 16);
500 pFramePacking->field_views_flag = OPERATE_BIT(seiInfo, 0x1, 17);
501 pFramePacking->current_frame_is_frame0_flag = OPERATE_BIT(seiInfo, 0x1, 18);
502
503 pFramePacking->frame0_grid_pos_x = OPERATE_BIT(seiGridPos, 0xf, 0);
504 pFramePacking->frame0_grid_pos_y = OPERATE_BIT(seiGridPos, 0xf, 4);
505 pFramePacking->frame1_grid_pos_x = OPERATE_BIT(seiGridPos, 0xf, 8);
506 pFramePacking->frame1_grid_pos_y = OPERATE_BIT(seiGridPos, 0xf, 12);
507
508EXIT:
509 return ret;
510}
511
512/*
513 * [Decoder Buffer OPS] Enable Cacheable (Input)
514 */
515static ExynosVideoErrorType MFC_Decoder_Enable_Cacheable_Inbuf(void *pHandle)
516{
517 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
518 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
519
520 if (pCtx == NULL) {
521 ALOGE("%s: Video context info must be supplied", __func__);
522 ret = VIDEO_ERROR_BADPARAM;
523 goto EXIT;
524 }
525
Jiho Chang38ef2572012-06-01 20:58:55 +0000526 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_CACHEABLE, 2) != 0) {
Jiho Chang800a8d72012-04-26 13:25:31 -0700527 ret = VIDEO_ERROR_APIFAIL;
528 goto EXIT;
529 }
530
531EXIT:
532 return ret;
533}
534
535/*
536 * [Decoder Buffer OPS] Enable Cacheable (Output)
537 */
538static ExynosVideoErrorType MFC_Decoder_Enable_Cacheable_Outbuf(void *pHandle)
539{
540 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
541 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
542
543 if (pCtx == NULL) {
544 ALOGE("%s: Video context info must be supplied", __func__);
545 ret = VIDEO_ERROR_BADPARAM;
546 goto EXIT;
547 }
548
Jiho Chang38ef2572012-06-01 20:58:55 +0000549 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_CACHEABLE, 1) != 0) {
Jiho Chang800a8d72012-04-26 13:25:31 -0700550 ret = VIDEO_ERROR_APIFAIL;
551 goto EXIT;
552 }
553
554EXIT:
555 return ret;
556}
557
558/*
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900559 * [Decoder Buffer OPS] Set Shareable Buffer (Input)
560 */
561static ExynosVideoErrorType MFC_Decoder_Set_Shareable_Inbuf(void *pHandle)
562{
563 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
564 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
565
566 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700567 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900568 ret = VIDEO_ERROR_BADPARAM;
569 goto EXIT;
570 }
571
572 pCtx->bShareInbuf = VIDEO_TRUE;
573
574EXIT:
575 return ret;
576}
577
578/*
579 * [Decoder Buffer OPS] Set Shareable Buffer (Output)
580 */
581static ExynosVideoErrorType MFC_Decoder_Set_Shareable_Outbuf(void *pHandle)
582{
583 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
584 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
585
586 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700587 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900588 ret = VIDEO_ERROR_BADPARAM;
589 goto EXIT;
590 }
591
592 pCtx->bShareOutbuf = VIDEO_TRUE;
593
594EXIT:
595 return ret;
596}
597
598/*
Jiho Chang38ef2572012-06-01 20:58:55 +0000599 * [Decoder Buffer OPS] Get Buffer (Input)
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900600 */
Jiho Chang38ef2572012-06-01 20:58:55 +0000601static ExynosVideoErrorType MFC_Decoder_Get_Buffer_Inbuf(
602 void *pHandle,
603 int nIndex,
604 ExynosVideoBuffer **pBuffer)
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900605{
606 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
607 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
608
609 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700610 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang38ef2572012-06-01 20:58:55 +0000611 *pBuffer = NULL;
612 ret = VIDEO_ERROR_BADPARAM;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900613 goto EXIT;
614 }
615
Jiho Chang38ef2572012-06-01 20:58:55 +0000616 if (pCtx->nInbufs <= nIndex) {
617 *pBuffer = NULL;
618 ret = VIDEO_ERROR_BADPARAM;
619 goto EXIT;
620 }
621
622 *pBuffer = (ExynosVideoBuffer *)&pCtx->pInbuf[nIndex];
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900623
624EXIT:
625 return ret;
626}
627
628/*
Jiho Chang38ef2572012-06-01 20:58:55 +0000629 * [Decoder Buffer OPS] Get Buffer (Output)
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900630 */
Jiho Chang38ef2572012-06-01 20:58:55 +0000631static ExynosVideoErrorType MFC_Decoder_Get_Buffer_Outbuf(
632 void *pHandle,
633 int nIndex,
634 ExynosVideoBuffer **pBuffer)
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900635{
636 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
637 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
638
639 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700640 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang38ef2572012-06-01 20:58:55 +0000641 *pBuffer = NULL;
642 ret = VIDEO_ERROR_BADPARAM;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900643 goto EXIT;
644 }
645
Jiho Chang38ef2572012-06-01 20:58:55 +0000646 if (pCtx->nOutbufs <= nIndex) {
647 *pBuffer = NULL;
648 ret = VIDEO_ERROR_BADPARAM;
649 goto EXIT;
650 }
651
652 *pBuffer = (ExynosVideoBuffer *)&pCtx->pOutbuf[nIndex];
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900653
654EXIT:
655 return ret;
656}
657
658/*
659 * [Decoder Buffer OPS] Set Geometry (Input)
660 */
661static ExynosVideoErrorType MFC_Decoder_Set_Geometry_Inbuf(
662 void *pHandle,
663 ExynosVideoGeometry *bufferConf)
664{
665 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
666 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
667
668 struct v4l2_format fmt;
669
670 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700671 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900672 ret = VIDEO_ERROR_BADPARAM;
673 goto EXIT;
674 }
675
676 if (bufferConf == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700677 ALOGE("%s: Buffer geometry must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900678 ret = VIDEO_ERROR_BADPARAM;
679 goto EXIT;
680 }
681
682 memset(&fmt, 0, sizeof(fmt));
683
684 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
685 fmt.fmt.pix_mp.pixelformat = __CodingType_To_V4L2PixelFormat(bufferConf->eCompressionFormat);
686 fmt.fmt.pix_mp.plane_fmt[0].sizeimage = bufferConf->nSizeImage;
687
Jiho Chang38ef2572012-06-01 20:58:55 +0000688 if (exynos_v4l2_s_fmt(pCtx->hDec, &fmt) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900689 ret = VIDEO_ERROR_APIFAIL;
690 goto EXIT;
691 }
692
693 memcpy(&pCtx->inbufGeometry, bufferConf, sizeof(pCtx->inbufGeometry));
694
695EXIT:
696 return ret;
697}
698
699/*
700 * [Decoder Buffer OPS] Set Geometry (Output)
701 */
702static ExynosVideoErrorType MFC_Decoder_Set_Geometry_Outbuf(
703 void *pHandle,
704 ExynosVideoGeometry *bufferConf)
705{
706 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
707 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
708
709 struct v4l2_format fmt;
710
711 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700712 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900713 ret = VIDEO_ERROR_BADPARAM;
714 goto EXIT;
715 }
716
717 if (bufferConf == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700718 ALOGE("%s: Buffer geometry must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900719 ret = VIDEO_ERROR_BADPARAM;
720 goto EXIT;
721 }
722
723 memset(&fmt, 0, sizeof(fmt));
724
725 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
726 fmt.fmt.pix_mp.pixelformat = __ColorFormatType_To_V4L2PixelFormat(bufferConf->eColorFormat);
727
Jiho Chang38ef2572012-06-01 20:58:55 +0000728 if (exynos_v4l2_s_fmt(pCtx->hDec, &fmt) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900729 ret = VIDEO_ERROR_APIFAIL;
730 goto EXIT;
731 }
732
733 memcpy(&pCtx->outbufGeometry, bufferConf, sizeof(pCtx->outbufGeometry));
734
735EXIT:
736 return ret;
737}
738
739/*
740 * [Decoder Buffer OPS] Get Geometry (Output)
741 */
742static ExynosVideoErrorType MFC_Decoder_Get_Geometry_Outbuf(
743 void *pHandle,
744 ExynosVideoGeometry *bufferConf)
745{
746 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
747 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
748
749 struct v4l2_format fmt;
750 struct v4l2_crop crop;
751
752 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700753 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900754 ret = VIDEO_ERROR_BADPARAM;
755 goto EXIT;
756 }
757
758 if (bufferConf == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700759 ALOGE("%s: Buffer geometry must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900760 ret = VIDEO_ERROR_BADPARAM;
761 goto EXIT;
762 }
763
764 memset(&fmt, 0, sizeof(fmt));
765 memset(&crop, 0, sizeof(crop));
766
767 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
Jiho Chang38ef2572012-06-01 20:58:55 +0000768 if (exynos_v4l2_g_fmt(pCtx->hDec, &fmt) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900769 ret = VIDEO_ERROR_APIFAIL;
770 goto EXIT;
771 }
772
773 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
Jiho Chang38ef2572012-06-01 20:58:55 +0000774 if (exynos_v4l2_g_crop(pCtx->hDec, &crop) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900775 ret = VIDEO_ERROR_APIFAIL;
776 goto EXIT;
777 }
778
779 bufferConf->nFrameWidth = fmt.fmt.pix_mp.width;
780 bufferConf->nFrameHeight = fmt.fmt.pix_mp.height;
781
782 bufferConf->cropRect.nTop = crop.c.top;
783 bufferConf->cropRect.nLeft = crop.c.left;
784 bufferConf->cropRect.nWidth = crop.c.width;
785 bufferConf->cropRect.nHeight = crop.c.height;
786
787EXIT:
788 return ret;
789}
790
791/*
792 * [Decoder Buffer OPS] Setup (Input)
793 */
794static ExynosVideoErrorType MFC_Decoder_Setup_Inbuf(
795 void *pHandle,
796 unsigned int nBufferCount)
797{
Jiho Chang38ef2572012-06-01 20:58:55 +0000798 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
799 ExynosVideoPlane *pVideoPlane = NULL;
800 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900801
802 struct v4l2_requestbuffers req;
803 struct v4l2_buffer buf;
804 struct v4l2_plane planes[VIDEO_DECODER_INBUF_PLANES];
805 int i;
806
807 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700808 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900809 ret = VIDEO_ERROR_BADPARAM;
810 goto EXIT;
811 }
812
813 if (nBufferCount == 0) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700814 ALOGE("%s: Buffer count must be greater than 0", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900815 ret = VIDEO_ERROR_BADPARAM;
816 goto EXIT;
817 }
818
Dima Zavin01fa64f2012-06-13 16:42:27 -0700819 ALOGV("%s: setting up inbufs (%d) shared=%s\n", __func__, nBufferCount,
820 pCtx->bShareInbuf ? "true" : "false");
821
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900822 memset(&req, 0, sizeof(req));
823
824 req.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
825 req.count = nBufferCount;
826
827 if (pCtx->bShareInbuf == VIDEO_TRUE)
SeungBeom Kim1f0d5e32012-07-03 15:45:57 +0900828 req.memory = pCtx->nMemoryType;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900829 else
830 req.memory = V4L2_MEMORY_MMAP;
831
Jiho Chang38ef2572012-06-01 20:58:55 +0000832 if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900833 ret = VIDEO_ERROR_APIFAIL;
834 goto EXIT;
835 }
836
Dima Zavin01fa64f2012-06-13 16:42:27 -0700837 if (req.count != nBufferCount)
838 ALOGW("%s: asked for %d, got %d\n", __func__, nBufferCount, req.count);
839
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900840 pCtx->nInbufs = (int)req.count;
841
842 pCtx->pInbuf = malloc(sizeof(*pCtx->pInbuf) * pCtx->nInbufs);
843 if (pCtx->pInbuf == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700844 ALOGE("Failed to allocate input buffer context");
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900845 ret = VIDEO_ERROR_NOMEM;
846 goto EXIT;
847 }
848 memset(pCtx->pInbuf, 0, sizeof(*pCtx->pInbuf) * pCtx->nInbufs);
849
850 memset(&buf, 0, sizeof(buf));
851
852 if (pCtx->bShareInbuf == VIDEO_FALSE) {
853 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
854 buf.memory = V4L2_MEMORY_MMAP;
855 buf.m.planes = planes;
856 buf.length = VIDEO_DECODER_INBUF_PLANES;
857
858 for (i = 0; i < pCtx->nInbufs; i++) {
859 buf.index = i;
Jiho Chang38ef2572012-06-01 20:58:55 +0000860 if (exynos_v4l2_querybuf(pCtx->hDec, &buf) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900861 ret = VIDEO_ERROR_APIFAIL;
862 goto EXIT;
863 }
864
865 pVideoPlane = &pCtx->pInbuf[i].planes[0];
866
867 pVideoPlane->addr = mmap(NULL,
868 buf.m.planes[0].length, PROT_READ | PROT_WRITE,
869 MAP_SHARED, pCtx->hDec, buf.m.planes[0].m.mem_offset);
870
871 if (pVideoPlane->addr == MAP_FAILED) {
872 ret = VIDEO_ERROR_MAPFAIL;
873 goto EXIT;
874 }
875
876 pVideoPlane->allocSize = buf.m.planes[0].length;
877 pVideoPlane->dataSize = 0;
878
879 pCtx->pInbuf[i].pGeometry = &pCtx->inbufGeometry;
Jiho Chang38ef2572012-06-01 20:58:55 +0000880 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
881 pCtx->pInbuf[i].bRegistered = VIDEO_TRUE;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900882 }
883 }
884
885 return ret;
886
887EXIT:
Jiho Chang800a8d72012-04-26 13:25:31 -0700888 if ((pCtx != NULL) && (pCtx->pInbuf != NULL)) {
889 if (pCtx->bShareInbuf == VIDEO_FALSE) {
890 for (i = 0; i < pCtx->nInbufs; i++) {
891 pVideoPlane = &pCtx->pInbuf[i].planes[0];
892 if (pVideoPlane->addr == MAP_FAILED) {
893 pVideoPlane->addr = NULL;
894 break;
895 }
896
897 munmap(pVideoPlane->addr, pVideoPlane->allocSize);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900898 }
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900899 }
Jiho Chang800a8d72012-04-26 13:25:31 -0700900
901 free(pCtx->pInbuf);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900902 }
903
904 return ret;
905}
906
907/*
908 * [Decoder Buffer OPS] Setup (Output)
909 */
910static ExynosVideoErrorType MFC_Decoder_Setup_Outbuf(
911 void *pHandle,
912 unsigned int nBufferCount)
913{
Jiho Chang38ef2572012-06-01 20:58:55 +0000914 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
915 ExynosVideoPlane *pVideoPlane = NULL;
916 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900917
918 struct v4l2_requestbuffers req;
919 struct v4l2_buffer buf;
920 struct v4l2_plane planes[VIDEO_DECODER_OUTBUF_PLANES];
921 int i, j;
922
923 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700924 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900925 ret = VIDEO_ERROR_BADPARAM;
926 goto EXIT;
927 }
928
929 if (nBufferCount == 0) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700930 ALOGE("%s: Buffer count must be greater than 0", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900931 ret = VIDEO_ERROR_BADPARAM;
932 goto EXIT;
933 }
934
Dima Zavin01fa64f2012-06-13 16:42:27 -0700935 ALOGV("%s: setting up outbufs (%d) shared=%s\n", __func__, nBufferCount,
936 pCtx->bShareOutbuf ? "true" : "false");
937
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900938 memset(&req, 0, sizeof(req));
939
940 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
941 req.count = nBufferCount;
942
943 if (pCtx->bShareOutbuf == VIDEO_TRUE)
SeungBeom Kim1f0d5e32012-07-03 15:45:57 +0900944 req.memory = pCtx->nMemoryType;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900945 else
946 req.memory = V4L2_MEMORY_MMAP;
947
Jiho Chang38ef2572012-06-01 20:58:55 +0000948 if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900949 ret = VIDEO_ERROR_APIFAIL;
950 goto EXIT;
951 }
952
953 pCtx->nOutbufs = req.count;
954
955 pCtx->pOutbuf = malloc(sizeof(*pCtx->pOutbuf) * pCtx->nOutbufs);
956 if (pCtx->pOutbuf == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700957 ALOGE("Failed to allocate output buffer context");
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900958 ret = VIDEO_ERROR_NOMEM;
959 goto EXIT;
960 }
961 memset(pCtx->pOutbuf, 0, sizeof(*pCtx->pOutbuf) * pCtx->nOutbufs);
962
963 memset(&buf, 0, sizeof(buf));
964
965 if (pCtx->bShareOutbuf == VIDEO_FALSE) {
966 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
967 buf.memory = V4L2_MEMORY_MMAP;
968 buf.m.planes = planes;
969 buf.length = VIDEO_DECODER_OUTBUF_PLANES;
970
971 for (i = 0; i < pCtx->nOutbufs; i++) {
972 buf.index = i;
Jiho Chang38ef2572012-06-01 20:58:55 +0000973 if (exynos_v4l2_querybuf(pCtx->hDec, &buf) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900974 ret = VIDEO_ERROR_APIFAIL;
975 goto EXIT;
976 }
977
978 for (j = 0; j < VIDEO_DECODER_OUTBUF_PLANES; j++) {
979 pVideoPlane = &pCtx->pOutbuf[i].planes[j];
980 pVideoPlane->addr = mmap(NULL,
981 buf.m.planes[j].length, PROT_READ | PROT_WRITE,
982 MAP_SHARED, pCtx->hDec, buf.m.planes[j].m.mem_offset);
983
984 if (pVideoPlane->addr == MAP_FAILED) {
985 ret = VIDEO_ERROR_MAPFAIL;
986 goto EXIT;
987 }
988
989 pVideoPlane->allocSize = buf.m.planes[j].length;
990 pVideoPlane->dataSize = 0;
991 }
992
993 pCtx->pOutbuf[i].pGeometry = &pCtx->outbufGeometry;
994 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
Jiho Chang38ef2572012-06-01 20:58:55 +0000995 pCtx->pOutbuf[i].bRegistered = VIDEO_TRUE;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900996 }
997 }
998
999 return ret;
1000
1001EXIT:
Jiho Chang800a8d72012-04-26 13:25:31 -07001002 if ((pCtx != NULL) && (pCtx->pOutbuf != NULL)) {
1003 if (pCtx->bShareOutbuf == VIDEO_FALSE) {
1004 for (i = 0; i < pCtx->nOutbufs; i++) {
1005 for (j = 0; j < VIDEO_DECODER_OUTBUF_PLANES; j++) {
1006 pVideoPlane = &pCtx->pOutbuf[i].planes[j];
1007 if (pVideoPlane->addr == MAP_FAILED) {
1008 pVideoPlane->addr = NULL;
1009 break;
1010 }
1011
1012 munmap(pVideoPlane->addr, pVideoPlane->allocSize);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001013 }
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001014 }
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001015 }
Jiho Chang800a8d72012-04-26 13:25:31 -07001016
1017 free(pCtx->pOutbuf);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001018 }
1019
1020 return ret;
1021}
1022
1023/*
1024 * [Decoder Buffer OPS] Run (Input)
1025 */
1026static ExynosVideoErrorType MFC_Decoder_Run_Inbuf(void *pHandle)
1027{
1028 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1029 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1030
1031 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001032 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001033 ret = VIDEO_ERROR_BADPARAM;
1034 goto EXIT;
1035 }
1036
1037 if (pCtx->bStreamonInbuf == VIDEO_FALSE) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001038 if (exynos_v4l2_streamon(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001039 ALOGE("%s: Failed to streamon for input buffer", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001040 ret = VIDEO_ERROR_APIFAIL;
1041 goto EXIT;
1042 }
1043 pCtx->bStreamonInbuf = VIDEO_TRUE;
1044 }
1045
1046EXIT:
1047 return ret;
1048}
1049
1050/*
1051 * [Decoder Buffer OPS] Run (Output)
1052 */
1053static ExynosVideoErrorType MFC_Decoder_Run_Outbuf(void *pHandle)
1054{
1055 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1056 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1057
1058 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001059 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001060 ret = VIDEO_ERROR_BADPARAM;
1061 goto EXIT;
1062 }
1063
1064 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001065 if (exynos_v4l2_streamon(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001066 ALOGE("%s: Failed to streamon for output buffer", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001067 ret = VIDEO_ERROR_APIFAIL;
1068 goto EXIT;
1069 }
1070 pCtx->bStreamonOutbuf = VIDEO_TRUE;
1071 }
1072
1073EXIT:
1074 return ret;
1075}
1076
1077/*
1078 * [Decoder Buffer OPS] Stop (Input)
1079 */
1080static ExynosVideoErrorType MFC_Decoder_Stop_Inbuf(void *pHandle)
1081{
1082 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1083 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
Jiho Chang38ef2572012-06-01 20:58:55 +00001084 int i = 0;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001085
1086 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001087 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001088 ret = VIDEO_ERROR_BADPARAM;
1089 goto EXIT;
1090 }
1091
1092 if (pCtx->bStreamonInbuf == VIDEO_TRUE) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001093 if (exynos_v4l2_streamoff(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001094 ALOGE("%s: Failed to streamoff for input buffer", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001095 ret = VIDEO_ERROR_APIFAIL;
1096 goto EXIT;
1097 }
1098 pCtx->bStreamonInbuf = VIDEO_FALSE;
1099 }
1100
Jiho Chang38ef2572012-06-01 20:58:55 +00001101 for (i = 0; i < pCtx->nInbufs; i++) {
1102 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
1103 }
1104
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001105EXIT:
1106 return ret;
1107}
1108
1109/*
1110 * [Decoder Buffer OPS] Stop (Output)
1111 */
1112static ExynosVideoErrorType MFC_Decoder_Stop_Outbuf(void *pHandle)
1113{
1114 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1115 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
Jiho Chang38ef2572012-06-01 20:58:55 +00001116 int i = 0;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001117
1118 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001119 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001120 ret = VIDEO_ERROR_BADPARAM;
1121 goto EXIT;
1122 }
1123
1124 if (pCtx->bStreamonOutbuf == VIDEO_TRUE) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001125 if (exynos_v4l2_streamoff(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001126 ALOGE("%s: Failed to streamoff for output buffer", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001127 ret = VIDEO_ERROR_APIFAIL;
1128 goto EXIT;
1129 }
1130 pCtx->bStreamonOutbuf = VIDEO_FALSE;
1131 }
1132
Jiho Chang38ef2572012-06-01 20:58:55 +00001133 for (i = 0; i < pCtx->nOutbufs; i++) {
1134 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
1135 }
1136
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001137EXIT:
1138 return ret;
1139}
1140
1141/*
1142 * [Decoder Buffer OPS] Wait (Input)
1143 */
1144static ExynosVideoErrorType MFC_Decoder_Wait_Inbuf(void *pHandle)
1145{
1146 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1147 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1148
1149 struct pollfd poll_events;
1150 int poll_state;
1151
1152 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001153 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001154 ret = VIDEO_ERROR_BADPARAM;
1155 goto EXIT;
1156 }
1157
1158 poll_events.fd = pCtx->hDec;
1159 poll_events.events = POLLOUT | POLLERR;
1160 poll_events.revents = 0;
1161
1162 do {
1163 poll_state = poll((struct pollfd*)&poll_events, 1, VIDEO_DECODER_POLL_TIMEOUT);
1164 if (poll_state > 0) {
1165 if (poll_events.revents & POLLOUT) {
1166 break;
1167 } else {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001168 ALOGE("%s: Poll return error", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001169 ret = VIDEO_ERROR_POLL;
1170 break;
1171 }
1172 } else if (poll_state < 0) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001173 ALOGE("%s: Poll state error", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001174 ret = VIDEO_ERROR_POLL;
1175 break;
1176 }
1177 } while (poll_state == 0);
1178
1179EXIT:
1180 return ret;
1181}
1182
Jiho Chang38ef2572012-06-01 20:58:55 +00001183static ExynosVideoErrorType MFC_Decoder_Register_Inbuf(
Dima Zavin01fa64f2012-06-13 16:42:27 -07001184 void *pHandle,
1185 ExynosVideoPlane *planes,
1186 int nPlanes)
Jiho Chang38ef2572012-06-01 20:58:55 +00001187{
1188 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1189 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1190 int nIndex;
1191
Dima Zavin01fa64f2012-06-13 16:42:27 -07001192 if ((pCtx == NULL) || (planes == NULL) || (nPlanes != 1)) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001193 ALOGE("%s: params must be supplied", __func__);
1194 ret = VIDEO_ERROR_BADPARAM;
1195 goto EXIT;
1196 }
1197
1198 for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
1199 if (pCtx->pInbuf[nIndex].bRegistered == VIDEO_FALSE) {
Dima Zavin01fa64f2012-06-13 16:42:27 -07001200 pCtx->pInbuf[nIndex].planes[0].addr = planes[0].addr;
1201 pCtx->pInbuf[nIndex].planes[0].allocSize = planes[0].allocSize;
1202 pCtx->pInbuf[nIndex].planes[0].fd = planes[0].fd;
Jiho Chang38ef2572012-06-01 20:58:55 +00001203 pCtx->pInbuf[nIndex].bRegistered = VIDEO_TRUE;
Dima Zavin01fa64f2012-06-13 16:42:27 -07001204 ALOGV("%s: registered buf %d (addr=%p alloc_sz=%ld fd=%d)\n", __func__, nIndex,
1205 planes[0].addr, planes[0].allocSize, planes[0].fd);
Jiho Chang38ef2572012-06-01 20:58:55 +00001206 break;
1207 }
1208 }
1209
1210 if (nIndex == pCtx->nInbufs) {
1211 ALOGE("%s: can not find non-registered input buffer", __func__);
1212 ret = VIDEO_ERROR_NOBUFFERS;
1213 }
1214
1215EXIT:
1216 return ret;
1217}
1218
1219static ExynosVideoErrorType MFC_Decoder_Register_Outbuf(
Dima Zavin01fa64f2012-06-13 16:42:27 -07001220 void *pHandle,
1221 ExynosVideoPlane *planes,
1222 int nPlanes)
Jiho Chang38ef2572012-06-01 20:58:55 +00001223{
1224 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1225 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1226 int nIndex;
1227
Dima Zavin01fa64f2012-06-13 16:42:27 -07001228 if ((pCtx == NULL) || (planes == NULL) || (nPlanes != 2)) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001229 ALOGE("%s: params must be supplied", __func__);
1230 ret = VIDEO_ERROR_BADPARAM;
1231 goto EXIT;
1232 }
1233
1234 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
1235 if (pCtx->pOutbuf[nIndex].bRegistered == VIDEO_FALSE) {
Dima Zavin01fa64f2012-06-13 16:42:27 -07001236 int plane;
1237 for (plane = 0; plane < 2; plane++) {
1238 pCtx->pOutbuf[nIndex].planes[plane].addr = planes[plane].addr;
1239 pCtx->pOutbuf[nIndex].planes[plane].allocSize = planes[plane].allocSize;
1240 pCtx->pOutbuf[nIndex].planes[plane].fd = planes[plane].fd;
1241 }
Jiho Chang38ef2572012-06-01 20:58:55 +00001242 pCtx->pOutbuf[nIndex].bRegistered = VIDEO_TRUE;
Dima Zavin01fa64f2012-06-13 16:42:27 -07001243 ALOGV("%s: registered buf %d 0:(addr=%p alloc_sz=%d fd=%d) 1:(addr=%p alloc_sz=%d fd=%d)\n",
1244 __func__, nIndex, planes[0].addr, planes[0].allocSize, planes[0].fd,
1245 planes[1].addr, planes[1].allocSize, planes[1].fd);
Jiho Chang38ef2572012-06-01 20:58:55 +00001246 break;
1247 }
1248 }
1249
1250 if (nIndex == pCtx->nOutbufs) {
1251 ALOGE("%s: can not find non-registered output buffer", __func__);
1252 ret = VIDEO_ERROR_NOBUFFERS;
1253 }
1254
1255EXIT:
1256 return ret;
1257}
1258
1259static ExynosVideoErrorType MFC_Decoder_Clear_RegisteredBuffer_Inbuf(void *pHandle)
1260{
1261 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1262 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1263 int nIndex;
1264
1265 if (pCtx == NULL) {
1266 ALOGE("%s: Video context info must be supplied", __func__);
1267 ret = VIDEO_ERROR_BADPARAM;
1268 goto EXIT;
1269 }
1270
1271 for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
1272 pCtx->pInbuf[nIndex].planes[0].addr = NULL;
1273 pCtx->pInbuf[nIndex].bRegistered = VIDEO_FALSE;
1274 }
1275
1276EXIT:
1277 return ret;
1278}
1279
1280static ExynosVideoErrorType MFC_Decoder_Clear_RegisteredBuffer_Outbuf(void *pHandle)
1281{
1282 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1283 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1284 int nIndex;
1285
1286 if (pCtx == NULL) {
1287 ALOGE("%s: Video context info must be supplied", __func__);
1288 ret = VIDEO_ERROR_BADPARAM;
1289 goto EXIT;
1290 }
1291
1292 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
1293 pCtx->pOutbuf[nIndex].planes[0].addr = NULL;
1294 pCtx->pOutbuf[nIndex].bRegistered = VIDEO_FALSE;
1295 }
1296
1297EXIT:
1298 return ret;
1299}
1300
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001301/*
1302 * [Decoder Buffer OPS] Find (Input)
1303 */
1304static int MFC_Decoder_Find_Inbuf(
1305 void *pHandle,
1306 unsigned char *pBuffer)
1307{
1308 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1309 int nIndex = -1;
1310
1311 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001312 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001313 goto EXIT;
1314 }
1315
1316 if (pBuffer == NULL) {
1317 for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
1318 if (pCtx->pInbuf[nIndex].bQueued == VIDEO_FALSE)
1319 break;
1320 }
1321 } else {
1322 for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
1323 if (pCtx->pInbuf[nIndex].planes[0].addr == pBuffer)
1324 break;
1325 }
1326 }
1327
1328 if (nIndex == pCtx->nInbufs) {
1329 nIndex = -1;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001330 }
1331
1332EXIT:
1333 return nIndex;
1334}
1335
1336/*
1337 * [Decoder Buffer OPS] Find (Outnput)
1338 */
1339static int MFC_Decoder_Find_Outbuf(
1340 void *pHandle,
1341 unsigned char *pBuffer)
1342{
1343 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1344 int nIndex = -1;
1345
1346 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001347 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001348 goto EXIT;
1349 }
1350
1351 if (pBuffer == NULL) {
1352 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
1353 if (pCtx->pOutbuf[nIndex].bQueued == VIDEO_FALSE)
1354 break;
1355 }
1356 } else {
1357 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
1358 if (pCtx->pOutbuf[nIndex].planes[0].addr == pBuffer)
1359 break;
1360 }
1361 }
1362
1363 if (nIndex == pCtx->nOutbufs) {
1364 nIndex = -1;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001365 }
1366
1367EXIT:
1368 return nIndex;
1369}
1370
1371/*
1372 * [Decoder Buffer OPS] Enqueue (Input)
1373 */
1374static ExynosVideoErrorType MFC_Decoder_Enqueue_Inbuf(
1375 void *pHandle,
1376 unsigned char *pBuffer[],
1377 unsigned int dataSize[],
1378 int nPlanes,
1379 void *pPrivate)
1380{
1381 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1382 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
Jiho Chang38ef2572012-06-01 20:58:55 +00001383 pthread_mutex_t *pMutex = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001384
1385 struct v4l2_plane planes[VIDEO_DECODER_INBUF_PLANES];
1386 struct v4l2_buffer buf;
1387 int index, i;
1388
1389 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001390 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001391 ret = VIDEO_ERROR_BADPARAM;
1392 goto EXIT;
1393 }
1394
Jiho Chang800a8d72012-04-26 13:25:31 -07001395 if (VIDEO_DECODER_INBUF_PLANES < nPlanes) {
1396 ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__,
1397 VIDEO_DECODER_INBUF_PLANES, nPlanes);
1398 ret = VIDEO_ERROR_BADPARAM;
1399 goto EXIT;
1400 }
1401
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001402 memset(&buf, 0, sizeof(buf));
1403
1404 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1405 buf.m.planes = planes;
1406 buf.length = VIDEO_DECODER_INBUF_PLANES;
1407
Jiho Chang38ef2572012-06-01 20:58:55 +00001408 index = MFC_Decoder_Find_Inbuf(pCtx, pBuffer[0]);
1409 if ((index == -1) &&
1410 (pCtx->bShareInbuf == VIDEO_TRUE) &&
1411 (pBuffer[0] != NULL))
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001412 index = MFC_Decoder_Find_Inbuf(pCtx, NULL);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001413 if (index == -1) {
1414 ret = VIDEO_ERROR_NOBUFFERS;
1415 goto EXIT;
1416 }
1417
1418 buf.index = index;
1419
1420 if (pCtx->bShareInbuf == VIDEO_TRUE) {
SeungBeom Kim1f0d5e32012-07-03 15:45:57 +09001421 buf.memory = pCtx->nMemoryType;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001422 for (i = 0; i < nPlanes; i++) {
Dima Zavin01fa64f2012-06-13 16:42:27 -07001423 buf.m.planes[i].m.fd = pCtx->pInbuf[index].planes[i].fd;
Jiho Chang38ef2572012-06-01 20:58:55 +00001424 buf.m.planes[i].length = pCtx->pInbuf[index].planes[i].allocSize;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001425 buf.m.planes[i].bytesused = dataSize[i];
1426 pCtx->pInbuf[buf.index].planes[i].addr = pBuffer[i];
Dima Zavin01fa64f2012-06-13 16:42:27 -07001427 ALOGV("%s: shared inbuf(%d) plane(%d) fd=%d len=%d used=%d\n", __func__,
1428 index, i,
1429 buf.m.planes[i].m.fd,
1430 buf.m.planes[i].length,
1431 buf.m.planes[i].bytesused);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001432 }
1433 } else {
1434 buf.memory = V4L2_MEMORY_MMAP;
1435 for (i = 0; i < nPlanes; i++)
1436 buf.m.planes[i].bytesused = dataSize[i];
1437 }
1438
Jiho Chang38ef2572012-06-01 20:58:55 +00001439 pMutex = (pthread_mutex_t*)pCtx->pInMutex;
1440 pthread_mutex_lock(pMutex);
1441 if (pCtx->pInbuf[buf.index].bQueued == VIDEO_FALSE) {
1442 if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) {
1443 ALOGE("%s: Failed to enqueue input buffer", __func__);
1444 ret = VIDEO_ERROR_APIFAIL;
1445 goto EXIT;
1446 }
1447
1448 pCtx->pInbuf[buf.index].pPrivate = pPrivate;
1449 pCtx->pInbuf[buf.index].bQueued = VIDEO_TRUE;
1450 } else {
1451 ALOGE("Lost Input Buffer");
1452 pthread_mutex_unlock(pMutex);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001453 ret = VIDEO_ERROR_APIFAIL;
1454 goto EXIT;
1455 }
Jiho Chang38ef2572012-06-01 20:58:55 +00001456 pthread_mutex_unlock(pMutex);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001457
1458EXIT:
1459 return ret;
1460}
1461
1462/*
1463 * [Decoder Buffer OPS] Enqueue (Output)
1464 */
1465static ExynosVideoErrorType MFC_Decoder_Enqueue_Outbuf(
1466 void *pHandle,
1467 unsigned char *pBuffer[],
1468 unsigned int dataSize[],
1469 int nPlanes,
1470 void *pPrivate)
1471{
1472 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1473 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
Jiho Chang38ef2572012-06-01 20:58:55 +00001474 pthread_mutex_t *pMutex = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001475
1476 struct v4l2_plane planes[VIDEO_DECODER_OUTBUF_PLANES];
1477 struct v4l2_buffer buf;
1478 int i, index;
1479
1480 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001481 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001482 ret = VIDEO_ERROR_BADPARAM;
1483 goto EXIT;
1484 }
1485
Jiho Chang38ef2572012-06-01 20:58:55 +00001486 if (VIDEO_DECODER_OUTBUF_PLANES < nPlanes) {
1487 ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__,
1488 VIDEO_DECODER_OUTBUF_PLANES, nPlanes);
1489 ret = VIDEO_ERROR_BADPARAM;
1490 goto EXIT;
1491 }
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001492
Jiho Chang38ef2572012-06-01 20:58:55 +00001493 memset(&buf, 0, sizeof(buf));
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001494 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1495 buf.m.planes = planes;
Dima Zavin01fa64f2012-06-13 16:42:27 -07001496 buf.length = nPlanes;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001497
Jiho Chang38ef2572012-06-01 20:58:55 +00001498 index = MFC_Decoder_Find_Outbuf(pCtx, pBuffer[0]);
1499 if ((index == -1) &&
1500 (pCtx->bShareOutbuf == VIDEO_TRUE) &&
1501 (pBuffer[0] != NULL))
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001502 index = MFC_Decoder_Find_Outbuf(pCtx, NULL);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001503 if (index == -1) {
1504 ret = VIDEO_ERROR_NOBUFFERS;
Jiho Chang38ef2572012-06-01 20:58:55 +00001505 ALOGE("Can not Find Buffer Index");
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001506 goto EXIT;
1507 }
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001508 buf.index = index;
1509
1510 if (pCtx->bShareOutbuf == VIDEO_TRUE) {
SeungBeom Kim1f0d5e32012-07-03 15:45:57 +09001511 buf.memory = pCtx->nMemoryType;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001512 for (i = 0; i < nPlanes; i++) {
Dima Zavin01fa64f2012-06-13 16:42:27 -07001513 buf.m.planes[i].m.fd = pCtx->pOutbuf[index].planes[i].fd;
Jiho Chang38ef2572012-06-01 20:58:55 +00001514 buf.m.planes[i].length = pCtx->pOutbuf[index].planes[i].allocSize;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001515 buf.m.planes[i].bytesused = dataSize[i];
Dima Zavin01fa64f2012-06-13 16:42:27 -07001516
1517 ALOGV("%s: shared outbuf(%d) plane=%d addr=%p fd=%d len=%d used=%d\n", __func__,
1518 index, i,
1519 pCtx->pOutbuf[index].planes[i].addr,
1520 buf.m.planes[i].m.fd,
1521 buf.m.planes[i].length,
1522 buf.m.planes[i].bytesused);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001523 }
1524 } else {
Dima Zavin01fa64f2012-06-13 16:42:27 -07001525 ALOGV("%s: non-shared outbuf(%d)\n", __func__, index);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001526 buf.memory = V4L2_MEMORY_MMAP;
1527 }
1528
Jiho Chang38ef2572012-06-01 20:58:55 +00001529 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
1530 pthread_mutex_lock(pMutex);
1531 if (pCtx->pOutbuf[buf.index].bQueued == VIDEO_FALSE) {
1532 if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) {
1533 ALOGE("%s: Failed to enqueue output buffer", __func__);
1534 ret = VIDEO_ERROR_APIFAIL;
1535 goto EXIT;
1536 }
1537
1538 pCtx->pOutbuf[buf.index].pPrivate = pPrivate;
1539 pCtx->pOutbuf[buf.index].bQueued = VIDEO_TRUE;
1540 } else {
1541 ALOGE("Lost Output Buffer");
1542 pthread_mutex_unlock(pMutex);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001543 ret = VIDEO_ERROR_APIFAIL;
1544 goto EXIT;
1545 }
Jiho Chang38ef2572012-06-01 20:58:55 +00001546 pthread_mutex_unlock(pMutex);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001547
1548EXIT:
1549 return ret;
1550}
1551
1552/*
1553 * [Decoder Buffer OPS] Dequeue (Input)
1554 */
1555static ExynosVideoBuffer *MFC_Decoder_Dequeue_Inbuf(void *pHandle)
1556{
Jiho Chang38ef2572012-06-01 20:58:55 +00001557 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1558 ExynosVideoBuffer *pInbuf = NULL;
1559 pthread_mutex_t *pMutex = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001560
1561 struct v4l2_buffer buf;
1562
1563 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001564 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001565 goto EXIT;
1566 }
1567
1568 if (pCtx->bStreamonInbuf == VIDEO_FALSE) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001569 pInbuf = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001570 goto EXIT;
1571 }
1572
1573 memset(&buf, 0, sizeof(buf));
1574
1575 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1576
1577 if (pCtx->bShareInbuf == VIDEO_TRUE)
SeungBeom Kim1f0d5e32012-07-03 15:45:57 +09001578 buf.memory = pCtx->nMemoryType;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001579 else
1580 buf.memory = V4L2_MEMORY_MMAP;
1581
Jiho Chang38ef2572012-06-01 20:58:55 +00001582 if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) {
1583 pInbuf = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001584 goto EXIT;
1585 }
1586
Jiho Chang38ef2572012-06-01 20:58:55 +00001587 pMutex = (pthread_mutex_t*)pCtx->pInMutex;
1588 pthread_mutex_lock(pMutex);
1589 pCtx->pInbuf[buf.index].bQueued = VIDEO_FALSE;
1590 pthread_mutex_unlock(pMutex);
1591 pInbuf = &pCtx->pInbuf[buf.index];
1592
1593 if (pCtx->bStreamonInbuf == VIDEO_FALSE)
1594 pInbuf = NULL;
1595
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001596EXIT:
Jiho Chang38ef2572012-06-01 20:58:55 +00001597 return pInbuf;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001598}
1599
1600/*
1601 * [Decoder Buffer OPS] Enqueue All (Output)
1602 */
1603static ExynosVideoErrorType MFC_Decoder_Enqueue_All_Outbuf(void *pHandle)
1604{
1605 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1606 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1607
Jiho Chang38ef2572012-06-01 20:58:55 +00001608 unsigned char *pBuffer[VIDEO_BUFFER_MAX_PLANES] = {NULL, };
1609 unsigned int dataSize[VIDEO_BUFFER_MAX_PLANES] = {0, };
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001610 int i;
1611
1612 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001613 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001614 ret = VIDEO_ERROR_BADPARAM;
1615 goto EXIT;
1616 }
1617
Jiho Chang38ef2572012-06-01 20:58:55 +00001618 for (i = 0; i < pCtx->nOutbufs; i++) {
1619 ret = MFC_Decoder_Enqueue_Outbuf(pCtx, pBuffer, dataSize, 0, NULL);
1620 if (ret != VIDEO_ERROR_NONE)
1621 goto EXIT;
1622 }
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001623
1624EXIT:
1625 return ret;
1626}
1627
1628/*
1629 * [Decoder Buffer OPS] Dequeue (Output)
1630 */
1631static ExynosVideoBuffer *MFC_Decoder_Dequeue_Outbuf(void *pHandle)
1632{
1633 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1634 ExynosVideoBuffer *pOutbuf = NULL;
Jiho Chang38ef2572012-06-01 20:58:55 +00001635 pthread_mutex_t *pMutex = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001636
1637 struct v4l2_buffer buf;
1638 int value;
1639
1640 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001641 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001642 goto EXIT;
1643 }
1644
1645 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001646 pOutbuf = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001647 goto EXIT;
1648 }
1649
1650 memset(&buf, 0, sizeof(buf));
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001651 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1652
1653 if (pCtx->bShareOutbuf == VIDEO_TRUE)
SeungBeom Kim1f0d5e32012-07-03 15:45:57 +09001654 buf.memory = pCtx->nMemoryType;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001655 else
1656 buf.memory = V4L2_MEMORY_MMAP;
1657
1658 /* HACK: pOutbuf return -1 means DECODING_ONLY for almost cases */
Jiho Chang38ef2572012-06-01 20:58:55 +00001659 if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) {
1660 pOutbuf = NULL;
1661 goto EXIT;
1662 }
1663
1664 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001665 pOutbuf = NULL;
1666 goto EXIT;
1667 }
1668
1669 pOutbuf = &pCtx->pOutbuf[buf.index];
1670
1671 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS, &value);
1672
1673 switch (value) {
1674 case 0:
1675 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_ONLY;
1676 break;
1677 case 1:
1678 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_DECODING;
1679 break;
1680 case 2:
1681 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_ONLY;
1682 break;
1683 case 3:
1684 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_CHANGE_RESOL;
1685 break;
1686 default:
1687 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_UNKNOWN;
1688 break;
1689 }
1690
1691 switch (buf.flags & (0x7 << 3)) {
1692 case V4L2_BUF_FLAG_KEYFRAME:
1693 pOutbuf->frameType = VIDEO_FRAME_I;
1694 break;
1695 case V4L2_BUF_FLAG_PFRAME:
1696 pOutbuf->frameType = VIDEO_FRAME_P;
1697 break;
1698 case V4L2_BUF_FLAG_BFRAME:
1699 pOutbuf->frameType = VIDEO_FRAME_B;
1700 break;
1701 default:
1702 pOutbuf->frameType = VIDEO_FRAME_OTHERS;
1703 break;
1704 };
1705
Jiho Chang38ef2572012-06-01 20:58:55 +00001706 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
1707 pthread_mutex_lock(pMutex);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001708 pOutbuf->bQueued = VIDEO_FALSE;
Jiho Chang38ef2572012-06-01 20:58:55 +00001709 pthread_mutex_unlock(pMutex);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001710
1711EXIT:
1712 return pOutbuf;
1713}
1714
Jiho Chang38ef2572012-06-01 20:58:55 +00001715static ExynosVideoErrorType MFC_Decoder_Clear_Queued_Inbuf(void *pHandle)
1716{
1717 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1718 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1719 int i;
1720
1721 if (pCtx == NULL) {
1722 ALOGE("%s: Video context info must be supplied", __func__);
1723 ret = VIDEO_ERROR_BADPARAM;
1724 goto EXIT;
1725 }
1726
1727 for (i = 0; i < pCtx->nInbufs; i++) {
1728 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
1729 }
1730
1731EXIT:
1732 return ret;
1733}
1734
1735static ExynosVideoErrorType MFC_Decoder_Clear_Queued_Outbuf(void *pHandle)
1736{
1737 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1738 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1739 int i;
1740
1741 if (pCtx == NULL) {
1742 ALOGE("%s: Video context info must be supplied", __func__);
1743 ret = VIDEO_ERROR_BADPARAM;
1744 goto EXIT;
1745 }
1746
1747 for (i = 0; i < pCtx->nOutbufs; i++) {
1748 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
1749 }
1750
1751EXIT:
1752 return ret;
1753}
1754
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001755/*
1756 * [Decoder OPS] Common
1757 */
1758static ExynosVideoDecOps defDecOps = {
Jiho Chang38ef2572012-06-01 20:58:55 +00001759 .nSize = 0,
1760 .Init = MFC_Decoder_Init,
1761 .Finalize = MFC_Decoder_Finalize,
1762 .Set_DisplayDelay = MFC_Decoder_Set_DisplayDelay,
1763 .Enable_PackedPB = MFC_Decoder_Enable_PackedPB,
1764 .Enable_LoopFilter = MFC_Decoder_Enable_LoopFilter,
1765 .Enable_SliceMode = MFC_Decoder_Enable_SliceMode,
1766 .Get_ActualBufferCount = MFC_Decoder_Get_ActualBufferCount,
1767 .Set_FrameTag = MFC_Decoder_Set_FrameTag,
1768 .Get_FrameTag = MFC_Decoder_Get_FrameTag,
1769 .Enable_SEIParsing = MFC_Decoder_Enable_SEIParsing,
1770 .Get_FramePackingInfo = MFC_Decoder_Get_FramePackingInfo,
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001771};
1772
1773/*
1774 * [Decoder Buffer OPS] Input
1775 */
1776static ExynosVideoDecBufferOps defInbufOps = {
Jiho Chang38ef2572012-06-01 20:58:55 +00001777 .nSize = 0,
1778 .Enable_Cacheable = MFC_Decoder_Enable_Cacheable_Inbuf,
1779 .Set_Shareable = MFC_Decoder_Set_Shareable_Inbuf,
1780 .Get_Buffer = NULL,
1781 .Set_Geometry = MFC_Decoder_Set_Geometry_Inbuf,
1782 .Get_Geometry = NULL,
1783 .Setup = MFC_Decoder_Setup_Inbuf,
1784 .Run = MFC_Decoder_Run_Inbuf,
1785 .Stop = MFC_Decoder_Stop_Inbuf,
1786 .Enqueue = MFC_Decoder_Enqueue_Inbuf,
1787 .Enqueue_All = NULL,
1788 .Dequeue = MFC_Decoder_Dequeue_Inbuf,
1789 .Register = MFC_Decoder_Register_Inbuf,
1790 .Clear_RegisteredBuffer = MFC_Decoder_Clear_RegisteredBuffer_Inbuf,
1791 .Clear_Queue = MFC_Decoder_Clear_Queued_Inbuf,
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001792};
1793
1794/*
1795 * [Decoder Buffer OPS] Output
1796 */
1797static ExynosVideoDecBufferOps defOutbufOps = {
Jiho Chang38ef2572012-06-01 20:58:55 +00001798 .nSize = 0,
1799 .Enable_Cacheable = MFC_Decoder_Enable_Cacheable_Outbuf,
1800 .Set_Shareable = MFC_Decoder_Set_Shareable_Outbuf,
1801 .Get_Buffer = MFC_Decoder_Get_Buffer_Outbuf,
1802 .Set_Geometry = MFC_Decoder_Set_Geometry_Outbuf,
1803 .Get_Geometry = MFC_Decoder_Get_Geometry_Outbuf,
1804 .Setup = MFC_Decoder_Setup_Outbuf,
1805 .Run = MFC_Decoder_Run_Outbuf,
1806 .Stop = MFC_Decoder_Stop_Outbuf,
1807 .Enqueue = MFC_Decoder_Enqueue_Outbuf,
1808 .Enqueue_All = MFC_Decoder_Enqueue_All_Outbuf,
1809 .Dequeue = MFC_Decoder_Dequeue_Outbuf,
1810 .Register = MFC_Decoder_Register_Outbuf,
1811 .Clear_RegisteredBuffer = MFC_Decoder_Clear_RegisteredBuffer_Outbuf,
1812 .Clear_Queue = MFC_Decoder_Clear_Queued_Outbuf,
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001813};
1814
1815int Exynos_Video_Register_Decoder(
1816 ExynosVideoDecOps *pDecOps,
1817 ExynosVideoDecBufferOps *pInbufOps,
1818 ExynosVideoDecBufferOps *pOutbufOps)
1819{
1820 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1821
1822 if ((pDecOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) {
1823 ret = VIDEO_ERROR_BADPARAM;
1824 goto EXIT;
1825 }
1826
1827 defDecOps.nSize = sizeof(defDecOps);
1828 defInbufOps.nSize = sizeof(defInbufOps);
1829 defOutbufOps.nSize = sizeof(defOutbufOps);
1830
1831 memcpy((char *)pDecOps + sizeof(pDecOps->nSize), (char *)&defDecOps + sizeof(defDecOps.nSize),
1832 pDecOps->nSize - sizeof(pDecOps->nSize));
1833
1834 memcpy((char *)pInbufOps + sizeof(pInbufOps->nSize), (char *)&defInbufOps + sizeof(defInbufOps.nSize),
1835 pInbufOps->nSize - sizeof(pInbufOps->nSize));
1836
1837 memcpy((char *)pOutbufOps + sizeof(pOutbufOps->nSize), (char *)&defOutbufOps + sizeof(defOutbufOps.nSize),
1838 pOutbufOps->nSize - sizeof(pOutbufOps->nSize));
1839
1840EXIT:
1841 return ret;
1842}