blob: c48e43dcca0955aed5d76ae0194ac358a6f4356b [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"
43#include "exynos_v4l2.h"
44
45/* #define LOG_NDEBUG 0 */
46#define LOG_TAG "ExynosVideoDecoder"
47#include <utils/Log.h>
48
49/*
50 * [Common] __CodingType_To_V4L2PixelFormat
51 */
52static unsigned int __CodingType_To_V4L2PixelFormat(ExynosVideoCodingType codingType)
53{
54 unsigned int pixelformat = V4L2_PIX_FMT_H264;
55
56 switch (codingType) {
57 case VIDEO_CODING_AVC:
58 pixelformat = V4L2_PIX_FMT_H264;
59 break;
60 case VIDEO_CODING_MPEG4:
61 pixelformat = V4L2_PIX_FMT_MPEG4;
62 break;
63 case VIDEO_CODING_VP8:
64 pixelformat = V4L2_PIX_FMT_VP8;
65 break;
66 case VIDEO_CODING_H263:
67 pixelformat = V4L2_PIX_FMT_H263;
68 break;
69 case VIDEO_CODING_VC1:
70 pixelformat = V4L2_PIX_FMT_VC1_ANNEX_G;
71 break;
72 case VIDEO_CODING_VC1_RCV:
73 pixelformat = V4L2_PIX_FMT_VC1_ANNEX_L;
74 break;
75 case VIDEO_CODING_MPEG2:
Jiho Chang800a8d72012-04-26 13:25:31 -070076 pixelformat = V4L2_PIX_FMT_MPEG2;
Jiho Chang20d3e6e2012-03-24 03:43:08 +090077 break;
78 default:
79 pixelformat = V4L2_PIX_FMT_H264;
80 break;
81 }
82
83 return pixelformat;
84}
85
86/*
87 * [Common] __ColorFormatType_To_V4L2PixelFormat
88 */
89static unsigned int __ColorFormatType_To_V4L2PixelFormat(ExynosVideoColorFormatType colorFormatType)
90{
91 unsigned int pixelformat = V4L2_PIX_FMT_NV12M;
92
93 switch (colorFormatType) {
94 case VIDEO_COLORFORMAT_NV12_TILED:
95 pixelformat = V4L2_PIX_FMT_NV12MT_16X16;
96 break;
97 case VIDEO_COLORFORMAT_NV21:
98 pixelformat = V4L2_PIX_FMT_NV21M;
99 break;
100 case VIDEO_COLORFORMAT_NV12:
101 default:
102 pixelformat = V4L2_PIX_FMT_NV12M;
103 break;
104 }
105
106 return pixelformat;
107}
108
109/*
110 * [Decoder OPS] Init
111 */
112static void *MFC_Decoder_Init(void)
113{
114 ExynosVideoDecContext *pCtx = NULL;
Jiho Chang38ef2572012-06-01 20:58:55 +0000115 pthread_mutex_t *pMutex = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900116 int needCaps = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING);
117
118 pCtx = (ExynosVideoDecContext *)malloc(sizeof(*pCtx));
119 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700120 ALOGE("%s: Failed to allocate decoder context buffer", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900121 goto EXIT_ALLOC_FAIL;
122 }
123
124 memset(pCtx, 0, sizeof(*pCtx));
125
Jiho Chang38ef2572012-06-01 20:58:55 +0000126 pCtx->hDec = exynos_v4l2_open_devname(VIDEO_DECODER_NAME, O_RDWR, 0);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900127 if (pCtx->hDec < 0) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700128 ALOGE("%s: Failed to open decoder device", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900129 goto EXIT_OPEN_FAIL;
130 }
131
132 if (!exynos_v4l2_querycap(pCtx->hDec, needCaps)) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700133 ALOGE("%s: Failed to querycap", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900134 goto EXIT_QUERYCAP_FAIL;
135 }
136
137 pCtx->bStreamonInbuf = VIDEO_FALSE;
138 pCtx->bStreamonOutbuf = VIDEO_FALSE;
139
SeungBeom Kim1f0d5e32012-07-03 15:45:57 +0900140 pCtx->nMemoryType = V4L2_MEMORY_DMABUF;
141
Jiho Chang38ef2572012-06-01 20:58:55 +0000142 pMutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
143 if (pMutex == NULL) {
144 ALOGE("%s: Failed to allocate mutex about input buffer", __func__);
145 goto EXIT_QUERYCAP_FAIL;
146 }
Jiho Chang38ef2572012-06-01 20:58:55 +0000147 if (pthread_mutex_init(pMutex, NULL) != 0) {
148 free(pMutex);
149 goto EXIT_QUERYCAP_FAIL;
150 }
151 pCtx->pInMutex = (void*)pMutex;
152
153 pMutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
154 if (pMutex == NULL) {
155 ALOGE("%s: Failed to allocate mutex about output buffer", __func__);
156 goto EXIT_QUERYCAP_FAIL;
157 }
Jiho Chang38ef2572012-06-01 20:58:55 +0000158 if (pthread_mutex_init(pMutex, NULL) != 0) {
159 free(pMutex);
160 goto EXIT_QUERYCAP_FAIL;
161 }
162 pCtx->pOutMutex = (void*)pMutex;
163
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900164 return (void *)pCtx;
165
166EXIT_QUERYCAP_FAIL:
Jiho Chang38ef2572012-06-01 20:58:55 +0000167 if (pCtx->pInMutex != NULL) {
168 pthread_mutex_destroy(pCtx->pInMutex);
169 free(pCtx->pInMutex);
170 }
171
172 if (pCtx->pOutMutex != NULL) {
173 pthread_mutex_destroy(pCtx->pOutMutex);
174 free(pCtx->pOutMutex);
175 }
176
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900177 close(pCtx->hDec);
178
179EXIT_OPEN_FAIL:
180 free(pCtx);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900181
182EXIT_ALLOC_FAIL:
183 return NULL;
184}
185
186/*
187 * [Decoder OPS] Finalize
188 */
189static ExynosVideoErrorType MFC_Decoder_Finalize(void *pHandle)
190{
Jiho Chang38ef2572012-06-01 20:58:55 +0000191 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
192 ExynosVideoPlane *pVideoPlane = NULL;
193 pthread_mutex_t *pMutex = NULL;
194 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900195 int i, j;
196
197 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700198 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900199 ret = VIDEO_ERROR_BADPARAM;
200 goto EXIT;
201 }
202
Jiho Chang38ef2572012-06-01 20:58:55 +0000203 if (pCtx->pOutMutex != NULL) {
204 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
205 pthread_mutex_destroy(pMutex);
206 free(pMutex);
207 pCtx->pOutMutex = NULL;
208 }
209
210 if (pCtx->pInMutex != NULL) {
211 pMutex = (pthread_mutex_t*)pCtx->pInMutex;
212 pthread_mutex_destroy(pMutex);
213 free(pMutex);
214 pCtx->pInMutex = NULL;
215 }
216
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900217 if (pCtx->bShareInbuf == VIDEO_FALSE) {
218 for (i = 0; i < pCtx->nInbufs; i++) {
219 for (j = 0; j < VIDEO_DECODER_INBUF_PLANES; j++) {
220 pVideoPlane = &pCtx->pInbuf[i].planes[j];
221 if (pVideoPlane->addr != NULL) {
222 munmap(pVideoPlane->addr, pVideoPlane->allocSize);
223 pVideoPlane->addr = NULL;
224 pVideoPlane->allocSize = 0;
225 pVideoPlane->dataSize = 0;
226 }
227
228 pCtx->pInbuf[i].pGeometry = NULL;
229 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
Jiho Chang38ef2572012-06-01 20:58:55 +0000230 pCtx->pInbuf[i].bRegistered = VIDEO_FALSE;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900231 }
232 }
233 }
234
235 if (pCtx->bShareOutbuf == VIDEO_FALSE) {
236 for (i = 0; i < pCtx->nOutbufs; i++) {
237 for (j = 0; j < VIDEO_DECODER_OUTBUF_PLANES; j++) {
238 pVideoPlane = &pCtx->pOutbuf[i].planes[j];
239 if (pVideoPlane->addr != NULL) {
240 munmap(pVideoPlane->addr, pVideoPlane->allocSize);
241 pVideoPlane->addr = NULL;
242 pVideoPlane->allocSize = 0;
243 pVideoPlane->dataSize = 0;
244 }
245
246 pCtx->pOutbuf[i].pGeometry = NULL;
247 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
Jiho Chang38ef2572012-06-01 20:58:55 +0000248 pCtx->pOutbuf[i].bRegistered = VIDEO_FALSE;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900249 }
250 }
251 }
252
253 if (pCtx->pInbuf != NULL)
254 free(pCtx->pInbuf);
255
256 if (pCtx->pOutbuf != NULL)
257 free(pCtx->pOutbuf);
258
259 if (pCtx->hDec > 0)
260 close(pCtx->hDec);
261
262 free(pCtx);
263
264EXIT:
265 return ret;
266}
267
268/*
269 * [Decoder OPS] Set Frame Tag
270 */
271static ExynosVideoErrorType MFC_Decoder_Set_FrameTag(
272 void *pHandle,
273 int frameTag)
274{
275 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
276 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
277
278 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700279 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900280 ret = VIDEO_ERROR_BADPARAM;
281 goto EXIT;
282 }
283
Jiho Chang38ef2572012-06-01 20:58:55 +0000284 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, frameTag) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900285 ret = VIDEO_ERROR_APIFAIL;
286 goto EXIT;
287 }
288
289EXIT:
290 return ret;
291}
292
293/*
294 * [Decoder OPS] Get Frame Tag
295 */
296static int MFC_Decoder_Get_FrameTag(void *pHandle)
297{
298 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
299 int frameTag = -1;
300
301 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700302 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900303 goto EXIT;
304 }
305
306 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, &frameTag);
307
308EXIT:
309 return frameTag;
310}
311
312/*
313 * [Decoder OPS] Get Buffer Count
314 */
315static int MFC_Decoder_Get_ActualBufferCount(void *pHandle)
316{
317 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
318 int bufferCount = -1;
319
320 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700321 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900322 goto EXIT;
323 }
324
325 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, &bufferCount);
326
327EXIT:
328 return bufferCount;
329}
330
331/*
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900332 * [Decoder OPS] Set Display Delay
333 */
334static ExynosVideoErrorType MFC_Decoder_Set_DisplayDelay(
335 void *pHandle,
336 int delay)
337{
338 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
339 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
340
341 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700342 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900343 ret = VIDEO_ERROR_BADPARAM;
344 goto EXIT;
345 }
346
Jiho Chang38ef2572012-06-01 20:58:55 +0000347 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 +0900348 ret = VIDEO_ERROR_APIFAIL;
349 goto EXIT;
350 }
351
352EXIT:
353 return ret;
354}
355
356/*
357 * [Decoder OPS] Enable Packed PB
358 */
359static ExynosVideoErrorType MFC_Decoder_Enable_PackedPB(void *pHandle)
360{
361 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
362 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
363
364 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700365 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900366 ret = VIDEO_ERROR_BADPARAM;
367 goto EXIT;
368 }
369
Jiho Chang38ef2572012-06-01 20:58:55 +0000370 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_PACKED_PB, 1) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900371 ret = VIDEO_ERROR_APIFAIL;
372 goto EXIT;
373 }
374
375EXIT:
376 return ret;
377}
378
379/*
380 * [Decoder OPS] Enable Loop Filter
381 */
382static ExynosVideoErrorType MFC_Decoder_Enable_LoopFilter(void *pHandle)
383{
384 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
385 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
386
387 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700388 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900389 ret = VIDEO_ERROR_BADPARAM;
390 goto EXIT;
391 }
392
Jiho Chang38ef2572012-06-01 20:58:55 +0000393 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER, 1) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900394 ret = VIDEO_ERROR_APIFAIL;
395 goto EXIT;
396 }
397
398EXIT:
399 return ret;
400}
401
402/*
403 * [Decoder OPS] Enable Slice Mode
404 */
405static ExynosVideoErrorType MFC_Decoder_Enable_SliceMode(void *pHandle)
406{
407 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
408 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
409
410 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700411 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900412 ret = VIDEO_ERROR_BADPARAM;
413 goto EXIT;
414 }
415
Jiho Chang38ef2572012-06-01 20:58:55 +0000416 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE, 1) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900417 ret = VIDEO_ERROR_APIFAIL;
418 goto EXIT;
419 }
420
421EXIT:
422 return ret;
423}
424
425/*
Jiho Chang800a8d72012-04-26 13:25:31 -0700426 * [Decoder OPS] Enable SEI Parsing
427 */
428static ExynosVideoErrorType MFC_Decoder_Enable_SEIParsing(void *pHandle)
429{
430 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
431 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
432
433 if (pCtx == NULL) {
434 ALOGE("%s: Video context info must be supplied", __func__);
435 ret = VIDEO_ERROR_BADPARAM;
436 goto EXIT;
437 }
438
Jiho Chang38ef2572012-06-01 20:58:55 +0000439 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING, 1) != 0) {
Jiho Chang800a8d72012-04-26 13:25:31 -0700440 ret = VIDEO_ERROR_APIFAIL;
441 goto EXIT;
442 }
443
444EXIT:
445 return ret;
446}
447
448/*
449 * [Decoder OPS] Get Frame Packing information
450 */
451static ExynosVideoErrorType MFC_Decoder_Get_FramePackingInfo(
452 void *pHandle,
453 ExynosVideoFramePacking *pFramePacking)
454{
455 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
456 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
457
458 struct v4l2_ext_control ext_ctrl[FRAME_PACK_SEI_INFO_NUM];
459 struct v4l2_ext_controls ext_ctrls;
460
461 int seiAvailable, seiInfo, seiGridPos, i;
462 unsigned int seiArgmtId;
463
464
Jiho Chang38ef2572012-06-01 20:58:55 +0000465 if ((pCtx == NULL) || (pFramePacking == NULL)) {
466 ALOGE("%s: Video context info or FramePacking pointer must be supplied", __func__);
Jiho Chang800a8d72012-04-26 13:25:31 -0700467 ret = VIDEO_ERROR_BADPARAM;
468 goto EXIT;
469 }
470
471 memset(pFramePacking, 0, sizeof(*pFramePacking));
472 memset(ext_ctrl, 0, (sizeof(struct v4l2_ext_control) * FRAME_PACK_SEI_INFO_NUM));
473
474 ext_ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
475 ext_ctrls.count = FRAME_PACK_SEI_INFO_NUM;
476 ext_ctrls.controls = ext_ctrl;
477 ext_ctrl[0].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_AVAIL;
478 ext_ctrl[1].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRGMENT_ID;
479 ext_ctrl[2].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_INFO;
480 ext_ctrl[3].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_GRID_POS;
481
Jiho Chang38ef2572012-06-01 20:58:55 +0000482 if (exynos_v4l2_g_ext_ctrl(pCtx->hDec, &ext_ctrls) != 0) {
Jiho Chang800a8d72012-04-26 13:25:31 -0700483 ret = VIDEO_ERROR_APIFAIL;
484 goto EXIT;
485 }
486
487 seiAvailable = ext_ctrl[0].value;
488 seiArgmtId = ext_ctrl[1].value;
489 seiInfo = ext_ctrl[2].value;
490 seiGridPos = ext_ctrl[3].value;
491
492 pFramePacking->available = seiAvailable;
493 pFramePacking->arrangement_id = seiArgmtId;
494
495 pFramePacking->arrangement_cancel_flag = OPERATE_BIT(seiInfo, 0x1, 0);
496 pFramePacking->arrangement_type = OPERATE_BIT(seiInfo, 0x3f, 1);
497 pFramePacking->quincunx_sampling_flag = OPERATE_BIT(seiInfo, 0x1, 8);
498 pFramePacking->content_interpretation_type = OPERATE_BIT(seiInfo, 0x3f, 9);
499 pFramePacking->spatial_flipping_flag = OPERATE_BIT(seiInfo, 0x1, 15);
500 pFramePacking->frame0_flipped_flag = OPERATE_BIT(seiInfo, 0x1, 16);
501 pFramePacking->field_views_flag = OPERATE_BIT(seiInfo, 0x1, 17);
502 pFramePacking->current_frame_is_frame0_flag = OPERATE_BIT(seiInfo, 0x1, 18);
503
504 pFramePacking->frame0_grid_pos_x = OPERATE_BIT(seiGridPos, 0xf, 0);
505 pFramePacking->frame0_grid_pos_y = OPERATE_BIT(seiGridPos, 0xf, 4);
506 pFramePacking->frame1_grid_pos_x = OPERATE_BIT(seiGridPos, 0xf, 8);
507 pFramePacking->frame1_grid_pos_y = OPERATE_BIT(seiGridPos, 0xf, 12);
508
509EXIT:
510 return ret;
511}
512
513/*
514 * [Decoder Buffer OPS] Enable Cacheable (Input)
515 */
516static ExynosVideoErrorType MFC_Decoder_Enable_Cacheable_Inbuf(void *pHandle)
517{
518 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
519 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
520
521 if (pCtx == NULL) {
522 ALOGE("%s: Video context info must be supplied", __func__);
523 ret = VIDEO_ERROR_BADPARAM;
524 goto EXIT;
525 }
526
Jiho Chang38ef2572012-06-01 20:58:55 +0000527 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_CACHEABLE, 2) != 0) {
Jiho Chang800a8d72012-04-26 13:25:31 -0700528 ret = VIDEO_ERROR_APIFAIL;
529 goto EXIT;
530 }
531
532EXIT:
533 return ret;
534}
535
536/*
537 * [Decoder Buffer OPS] Enable Cacheable (Output)
538 */
539static ExynosVideoErrorType MFC_Decoder_Enable_Cacheable_Outbuf(void *pHandle)
540{
541 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
542 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
543
544 if (pCtx == NULL) {
545 ALOGE("%s: Video context info must be supplied", __func__);
546 ret = VIDEO_ERROR_BADPARAM;
547 goto EXIT;
548 }
549
Jiho Chang38ef2572012-06-01 20:58:55 +0000550 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_CACHEABLE, 1) != 0) {
Jiho Chang800a8d72012-04-26 13:25:31 -0700551 ret = VIDEO_ERROR_APIFAIL;
552 goto EXIT;
553 }
554
555EXIT:
556 return ret;
557}
558
559/*
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900560 * [Decoder Buffer OPS] Set Shareable Buffer (Input)
561 */
562static ExynosVideoErrorType MFC_Decoder_Set_Shareable_Inbuf(void *pHandle)
563{
564 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
565 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
566
567 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700568 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900569 ret = VIDEO_ERROR_BADPARAM;
570 goto EXIT;
571 }
572
573 pCtx->bShareInbuf = VIDEO_TRUE;
574
575EXIT:
576 return ret;
577}
578
579/*
580 * [Decoder Buffer OPS] Set Shareable Buffer (Output)
581 */
582static ExynosVideoErrorType MFC_Decoder_Set_Shareable_Outbuf(void *pHandle)
583{
584 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
585 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
586
587 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700588 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900589 ret = VIDEO_ERROR_BADPARAM;
590 goto EXIT;
591 }
592
593 pCtx->bShareOutbuf = VIDEO_TRUE;
594
595EXIT:
596 return ret;
597}
598
599/*
Jiho Chang38ef2572012-06-01 20:58:55 +0000600 * [Decoder Buffer OPS] Get Buffer (Input)
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900601 */
Jiho Chang38ef2572012-06-01 20:58:55 +0000602static ExynosVideoErrorType MFC_Decoder_Get_Buffer_Inbuf(
603 void *pHandle,
604 int nIndex,
605 ExynosVideoBuffer **pBuffer)
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900606{
607 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
608 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
609
610 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700611 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang38ef2572012-06-01 20:58:55 +0000612 *pBuffer = NULL;
613 ret = VIDEO_ERROR_BADPARAM;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900614 goto EXIT;
615 }
616
Jiho Chang38ef2572012-06-01 20:58:55 +0000617 if (pCtx->nInbufs <= nIndex) {
618 *pBuffer = NULL;
619 ret = VIDEO_ERROR_BADPARAM;
620 goto EXIT;
621 }
622
623 *pBuffer = (ExynosVideoBuffer *)&pCtx->pInbuf[nIndex];
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900624
625EXIT:
626 return ret;
627}
628
629/*
Jiho Chang38ef2572012-06-01 20:58:55 +0000630 * [Decoder Buffer OPS] Get Buffer (Output)
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900631 */
Jiho Chang38ef2572012-06-01 20:58:55 +0000632static ExynosVideoErrorType MFC_Decoder_Get_Buffer_Outbuf(
633 void *pHandle,
634 int nIndex,
635 ExynosVideoBuffer **pBuffer)
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900636{
637 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
638 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
639
640 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700641 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang38ef2572012-06-01 20:58:55 +0000642 *pBuffer = NULL;
643 ret = VIDEO_ERROR_BADPARAM;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900644 goto EXIT;
645 }
646
Jiho Chang38ef2572012-06-01 20:58:55 +0000647 if (pCtx->nOutbufs <= nIndex) {
648 *pBuffer = NULL;
649 ret = VIDEO_ERROR_BADPARAM;
650 goto EXIT;
651 }
652
653 *pBuffer = (ExynosVideoBuffer *)&pCtx->pOutbuf[nIndex];
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900654
655EXIT:
656 return ret;
657}
658
659/*
660 * [Decoder Buffer OPS] Set Geometry (Input)
661 */
662static ExynosVideoErrorType MFC_Decoder_Set_Geometry_Inbuf(
663 void *pHandle,
664 ExynosVideoGeometry *bufferConf)
665{
666 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
667 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
668
669 struct v4l2_format fmt;
670
671 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700672 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900673 ret = VIDEO_ERROR_BADPARAM;
674 goto EXIT;
675 }
676
677 if (bufferConf == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700678 ALOGE("%s: Buffer geometry must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900679 ret = VIDEO_ERROR_BADPARAM;
680 goto EXIT;
681 }
682
683 memset(&fmt, 0, sizeof(fmt));
684
685 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
686 fmt.fmt.pix_mp.pixelformat = __CodingType_To_V4L2PixelFormat(bufferConf->eCompressionFormat);
687 fmt.fmt.pix_mp.plane_fmt[0].sizeimage = bufferConf->nSizeImage;
688
Jiho Chang38ef2572012-06-01 20:58:55 +0000689 if (exynos_v4l2_s_fmt(pCtx->hDec, &fmt) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900690 ret = VIDEO_ERROR_APIFAIL;
691 goto EXIT;
692 }
693
694 memcpy(&pCtx->inbufGeometry, bufferConf, sizeof(pCtx->inbufGeometry));
695
696EXIT:
697 return ret;
698}
699
700/*
701 * [Decoder Buffer OPS] Set Geometry (Output)
702 */
703static ExynosVideoErrorType MFC_Decoder_Set_Geometry_Outbuf(
704 void *pHandle,
705 ExynosVideoGeometry *bufferConf)
706{
707 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
708 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
709
710 struct v4l2_format fmt;
711
712 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700713 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900714 ret = VIDEO_ERROR_BADPARAM;
715 goto EXIT;
716 }
717
718 if (bufferConf == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700719 ALOGE("%s: Buffer geometry must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900720 ret = VIDEO_ERROR_BADPARAM;
721 goto EXIT;
722 }
723
724 memset(&fmt, 0, sizeof(fmt));
725
726 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
727 fmt.fmt.pix_mp.pixelformat = __ColorFormatType_To_V4L2PixelFormat(bufferConf->eColorFormat);
728
Jiho Chang38ef2572012-06-01 20:58:55 +0000729 if (exynos_v4l2_s_fmt(pCtx->hDec, &fmt) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900730 ret = VIDEO_ERROR_APIFAIL;
731 goto EXIT;
732 }
733
734 memcpy(&pCtx->outbufGeometry, bufferConf, sizeof(pCtx->outbufGeometry));
735
736EXIT:
737 return ret;
738}
739
740/*
741 * [Decoder Buffer OPS] Get Geometry (Output)
742 */
743static ExynosVideoErrorType MFC_Decoder_Get_Geometry_Outbuf(
744 void *pHandle,
745 ExynosVideoGeometry *bufferConf)
746{
747 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
748 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
749
750 struct v4l2_format fmt;
751 struct v4l2_crop crop;
752
753 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700754 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900755 ret = VIDEO_ERROR_BADPARAM;
756 goto EXIT;
757 }
758
759 if (bufferConf == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700760 ALOGE("%s: Buffer geometry must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900761 ret = VIDEO_ERROR_BADPARAM;
762 goto EXIT;
763 }
764
765 memset(&fmt, 0, sizeof(fmt));
766 memset(&crop, 0, sizeof(crop));
767
768 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
Jiho Chang38ef2572012-06-01 20:58:55 +0000769 if (exynos_v4l2_g_fmt(pCtx->hDec, &fmt) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900770 ret = VIDEO_ERROR_APIFAIL;
771 goto EXIT;
772 }
773
774 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
Jiho Chang38ef2572012-06-01 20:58:55 +0000775 if (exynos_v4l2_g_crop(pCtx->hDec, &crop) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900776 ret = VIDEO_ERROR_APIFAIL;
777 goto EXIT;
778 }
779
780 bufferConf->nFrameWidth = fmt.fmt.pix_mp.width;
781 bufferConf->nFrameHeight = fmt.fmt.pix_mp.height;
782
783 bufferConf->cropRect.nTop = crop.c.top;
784 bufferConf->cropRect.nLeft = crop.c.left;
785 bufferConf->cropRect.nWidth = crop.c.width;
786 bufferConf->cropRect.nHeight = crop.c.height;
787
788EXIT:
789 return ret;
790}
791
792/*
793 * [Decoder Buffer OPS] Setup (Input)
794 */
795static ExynosVideoErrorType MFC_Decoder_Setup_Inbuf(
796 void *pHandle,
797 unsigned int nBufferCount)
798{
Jiho Chang38ef2572012-06-01 20:58:55 +0000799 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
800 ExynosVideoPlane *pVideoPlane = NULL;
801 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900802
803 struct v4l2_requestbuffers req;
804 struct v4l2_buffer buf;
805 struct v4l2_plane planes[VIDEO_DECODER_INBUF_PLANES];
806 int i;
807
808 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700809 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900810 ret = VIDEO_ERROR_BADPARAM;
811 goto EXIT;
812 }
813
814 if (nBufferCount == 0) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700815 ALOGE("%s: Buffer count must be greater than 0", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900816 ret = VIDEO_ERROR_BADPARAM;
817 goto EXIT;
818 }
819
Dima Zavin01fa64f2012-06-13 16:42:27 -0700820 ALOGV("%s: setting up inbufs (%d) shared=%s\n", __func__, nBufferCount,
821 pCtx->bShareInbuf ? "true" : "false");
822
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900823 memset(&req, 0, sizeof(req));
824
825 req.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
826 req.count = nBufferCount;
827
828 if (pCtx->bShareInbuf == VIDEO_TRUE)
SeungBeom Kim1f0d5e32012-07-03 15:45:57 +0900829 req.memory = pCtx->nMemoryType;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900830 else
831 req.memory = V4L2_MEMORY_MMAP;
832
Jiho Chang38ef2572012-06-01 20:58:55 +0000833 if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900834 ret = VIDEO_ERROR_APIFAIL;
835 goto EXIT;
836 }
837
Dima Zavin01fa64f2012-06-13 16:42:27 -0700838 if (req.count != nBufferCount)
839 ALOGW("%s: asked for %d, got %d\n", __func__, nBufferCount, req.count);
840
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900841 pCtx->nInbufs = (int)req.count;
842
843 pCtx->pInbuf = malloc(sizeof(*pCtx->pInbuf) * pCtx->nInbufs);
844 if (pCtx->pInbuf == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700845 ALOGE("Failed to allocate input buffer context");
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900846 ret = VIDEO_ERROR_NOMEM;
847 goto EXIT;
848 }
849 memset(pCtx->pInbuf, 0, sizeof(*pCtx->pInbuf) * pCtx->nInbufs);
850
851 memset(&buf, 0, sizeof(buf));
852
853 if (pCtx->bShareInbuf == VIDEO_FALSE) {
854 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
855 buf.memory = V4L2_MEMORY_MMAP;
856 buf.m.planes = planes;
857 buf.length = VIDEO_DECODER_INBUF_PLANES;
858
859 for (i = 0; i < pCtx->nInbufs; i++) {
860 buf.index = i;
Jiho Chang38ef2572012-06-01 20:58:55 +0000861 if (exynos_v4l2_querybuf(pCtx->hDec, &buf) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900862 ret = VIDEO_ERROR_APIFAIL;
863 goto EXIT;
864 }
865
866 pVideoPlane = &pCtx->pInbuf[i].planes[0];
867
868 pVideoPlane->addr = mmap(NULL,
869 buf.m.planes[0].length, PROT_READ | PROT_WRITE,
870 MAP_SHARED, pCtx->hDec, buf.m.planes[0].m.mem_offset);
871
872 if (pVideoPlane->addr == MAP_FAILED) {
873 ret = VIDEO_ERROR_MAPFAIL;
874 goto EXIT;
875 }
876
877 pVideoPlane->allocSize = buf.m.planes[0].length;
878 pVideoPlane->dataSize = 0;
879
880 pCtx->pInbuf[i].pGeometry = &pCtx->inbufGeometry;
Jiho Chang38ef2572012-06-01 20:58:55 +0000881 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
882 pCtx->pInbuf[i].bRegistered = VIDEO_TRUE;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900883 }
884 }
885
886 return ret;
887
888EXIT:
Jiho Chang800a8d72012-04-26 13:25:31 -0700889 if ((pCtx != NULL) && (pCtx->pInbuf != NULL)) {
890 if (pCtx->bShareInbuf == VIDEO_FALSE) {
891 for (i = 0; i < pCtx->nInbufs; i++) {
892 pVideoPlane = &pCtx->pInbuf[i].planes[0];
893 if (pVideoPlane->addr == MAP_FAILED) {
894 pVideoPlane->addr = NULL;
895 break;
896 }
897
898 munmap(pVideoPlane->addr, pVideoPlane->allocSize);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900899 }
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900900 }
Jiho Chang800a8d72012-04-26 13:25:31 -0700901
902 free(pCtx->pInbuf);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900903 }
904
905 return ret;
906}
907
908/*
909 * [Decoder Buffer OPS] Setup (Output)
910 */
911static ExynosVideoErrorType MFC_Decoder_Setup_Outbuf(
912 void *pHandle,
913 unsigned int nBufferCount)
914{
Jiho Chang38ef2572012-06-01 20:58:55 +0000915 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
916 ExynosVideoPlane *pVideoPlane = NULL;
917 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900918
919 struct v4l2_requestbuffers req;
920 struct v4l2_buffer buf;
921 struct v4l2_plane planes[VIDEO_DECODER_OUTBUF_PLANES];
922 int i, j;
923
924 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700925 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900926 ret = VIDEO_ERROR_BADPARAM;
927 goto EXIT;
928 }
929
930 if (nBufferCount == 0) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700931 ALOGE("%s: Buffer count must be greater than 0", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900932 ret = VIDEO_ERROR_BADPARAM;
933 goto EXIT;
934 }
935
Dima Zavin01fa64f2012-06-13 16:42:27 -0700936 ALOGV("%s: setting up outbufs (%d) shared=%s\n", __func__, nBufferCount,
937 pCtx->bShareOutbuf ? "true" : "false");
938
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900939 memset(&req, 0, sizeof(req));
940
941 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
942 req.count = nBufferCount;
943
944 if (pCtx->bShareOutbuf == VIDEO_TRUE)
SeungBeom Kim1f0d5e32012-07-03 15:45:57 +0900945 req.memory = pCtx->nMemoryType;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900946 else
947 req.memory = V4L2_MEMORY_MMAP;
948
Jiho Chang38ef2572012-06-01 20:58:55 +0000949 if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900950 ret = VIDEO_ERROR_APIFAIL;
951 goto EXIT;
952 }
953
954 pCtx->nOutbufs = req.count;
955
956 pCtx->pOutbuf = malloc(sizeof(*pCtx->pOutbuf) * pCtx->nOutbufs);
957 if (pCtx->pOutbuf == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700958 ALOGE("Failed to allocate output buffer context");
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900959 ret = VIDEO_ERROR_NOMEM;
960 goto EXIT;
961 }
962 memset(pCtx->pOutbuf, 0, sizeof(*pCtx->pOutbuf) * pCtx->nOutbufs);
963
964 memset(&buf, 0, sizeof(buf));
965
966 if (pCtx->bShareOutbuf == VIDEO_FALSE) {
967 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
968 buf.memory = V4L2_MEMORY_MMAP;
969 buf.m.planes = planes;
970 buf.length = VIDEO_DECODER_OUTBUF_PLANES;
971
972 for (i = 0; i < pCtx->nOutbufs; i++) {
973 buf.index = i;
Jiho Chang38ef2572012-06-01 20:58:55 +0000974 if (exynos_v4l2_querybuf(pCtx->hDec, &buf) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900975 ret = VIDEO_ERROR_APIFAIL;
976 goto EXIT;
977 }
978
979 for (j = 0; j < VIDEO_DECODER_OUTBUF_PLANES; j++) {
980 pVideoPlane = &pCtx->pOutbuf[i].planes[j];
981 pVideoPlane->addr = mmap(NULL,
982 buf.m.planes[j].length, PROT_READ | PROT_WRITE,
983 MAP_SHARED, pCtx->hDec, buf.m.planes[j].m.mem_offset);
984
985 if (pVideoPlane->addr == MAP_FAILED) {
986 ret = VIDEO_ERROR_MAPFAIL;
987 goto EXIT;
988 }
989
990 pVideoPlane->allocSize = buf.m.planes[j].length;
991 pVideoPlane->dataSize = 0;
992 }
993
994 pCtx->pOutbuf[i].pGeometry = &pCtx->outbufGeometry;
995 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
Jiho Chang38ef2572012-06-01 20:58:55 +0000996 pCtx->pOutbuf[i].bRegistered = VIDEO_TRUE;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900997 }
998 }
999
1000 return ret;
1001
1002EXIT:
Jiho Chang800a8d72012-04-26 13:25:31 -07001003 if ((pCtx != NULL) && (pCtx->pOutbuf != NULL)) {
1004 if (pCtx->bShareOutbuf == VIDEO_FALSE) {
1005 for (i = 0; i < pCtx->nOutbufs; i++) {
1006 for (j = 0; j < VIDEO_DECODER_OUTBUF_PLANES; j++) {
1007 pVideoPlane = &pCtx->pOutbuf[i].planes[j];
1008 if (pVideoPlane->addr == MAP_FAILED) {
1009 pVideoPlane->addr = NULL;
1010 break;
1011 }
1012
1013 munmap(pVideoPlane->addr, pVideoPlane->allocSize);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001014 }
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001015 }
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001016 }
Jiho Chang800a8d72012-04-26 13:25:31 -07001017
1018 free(pCtx->pOutbuf);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001019 }
1020
1021 return ret;
1022}
1023
1024/*
1025 * [Decoder Buffer OPS] Run (Input)
1026 */
1027static ExynosVideoErrorType MFC_Decoder_Run_Inbuf(void *pHandle)
1028{
1029 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1030 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1031
1032 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001033 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001034 ret = VIDEO_ERROR_BADPARAM;
1035 goto EXIT;
1036 }
1037
1038 if (pCtx->bStreamonInbuf == VIDEO_FALSE) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001039 if (exynos_v4l2_streamon(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001040 ALOGE("%s: Failed to streamon for input buffer", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001041 ret = VIDEO_ERROR_APIFAIL;
1042 goto EXIT;
1043 }
1044 pCtx->bStreamonInbuf = VIDEO_TRUE;
1045 }
1046
1047EXIT:
1048 return ret;
1049}
1050
1051/*
1052 * [Decoder Buffer OPS] Run (Output)
1053 */
1054static ExynosVideoErrorType MFC_Decoder_Run_Outbuf(void *pHandle)
1055{
1056 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1057 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1058
1059 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001060 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001061 ret = VIDEO_ERROR_BADPARAM;
1062 goto EXIT;
1063 }
1064
1065 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001066 if (exynos_v4l2_streamon(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001067 ALOGE("%s: Failed to streamon for output buffer", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001068 ret = VIDEO_ERROR_APIFAIL;
1069 goto EXIT;
1070 }
1071 pCtx->bStreamonOutbuf = VIDEO_TRUE;
1072 }
1073
1074EXIT:
1075 return ret;
1076}
1077
1078/*
1079 * [Decoder Buffer OPS] Stop (Input)
1080 */
1081static ExynosVideoErrorType MFC_Decoder_Stop_Inbuf(void *pHandle)
1082{
1083 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1084 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
Jiho Chang38ef2572012-06-01 20:58:55 +00001085 int i = 0;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001086
1087 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001088 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001089 ret = VIDEO_ERROR_BADPARAM;
1090 goto EXIT;
1091 }
1092
1093 if (pCtx->bStreamonInbuf == VIDEO_TRUE) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001094 if (exynos_v4l2_streamoff(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001095 ALOGE("%s: Failed to streamoff for input buffer", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001096 ret = VIDEO_ERROR_APIFAIL;
1097 goto EXIT;
1098 }
1099 pCtx->bStreamonInbuf = VIDEO_FALSE;
1100 }
1101
Jiho Chang38ef2572012-06-01 20:58:55 +00001102 for (i = 0; i < pCtx->nInbufs; i++) {
1103 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
1104 }
1105
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001106EXIT:
1107 return ret;
1108}
1109
1110/*
1111 * [Decoder Buffer OPS] Stop (Output)
1112 */
1113static ExynosVideoErrorType MFC_Decoder_Stop_Outbuf(void *pHandle)
1114{
1115 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1116 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
Jiho Chang38ef2572012-06-01 20:58:55 +00001117 int i = 0;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001118
1119 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001120 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001121 ret = VIDEO_ERROR_BADPARAM;
1122 goto EXIT;
1123 }
1124
1125 if (pCtx->bStreamonOutbuf == VIDEO_TRUE) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001126 if (exynos_v4l2_streamoff(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001127 ALOGE("%s: Failed to streamoff for output buffer", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001128 ret = VIDEO_ERROR_APIFAIL;
1129 goto EXIT;
1130 }
1131 pCtx->bStreamonOutbuf = VIDEO_FALSE;
1132 }
1133
Jiho Chang38ef2572012-06-01 20:58:55 +00001134 for (i = 0; i < pCtx->nOutbufs; i++) {
1135 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
1136 }
1137
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001138EXIT:
1139 return ret;
1140}
1141
1142/*
1143 * [Decoder Buffer OPS] Wait (Input)
1144 */
1145static ExynosVideoErrorType MFC_Decoder_Wait_Inbuf(void *pHandle)
1146{
1147 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1148 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1149
1150 struct pollfd poll_events;
1151 int poll_state;
1152
1153 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001154 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001155 ret = VIDEO_ERROR_BADPARAM;
1156 goto EXIT;
1157 }
1158
1159 poll_events.fd = pCtx->hDec;
1160 poll_events.events = POLLOUT | POLLERR;
1161 poll_events.revents = 0;
1162
1163 do {
1164 poll_state = poll((struct pollfd*)&poll_events, 1, VIDEO_DECODER_POLL_TIMEOUT);
1165 if (poll_state > 0) {
1166 if (poll_events.revents & POLLOUT) {
1167 break;
1168 } else {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001169 ALOGE("%s: Poll return error", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001170 ret = VIDEO_ERROR_POLL;
1171 break;
1172 }
1173 } else if (poll_state < 0) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001174 ALOGE("%s: Poll state error", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001175 ret = VIDEO_ERROR_POLL;
1176 break;
1177 }
1178 } while (poll_state == 0);
1179
1180EXIT:
1181 return ret;
1182}
1183
Jiho Chang38ef2572012-06-01 20:58:55 +00001184static ExynosVideoErrorType MFC_Decoder_Register_Inbuf(
Dima Zavin01fa64f2012-06-13 16:42:27 -07001185 void *pHandle,
1186 ExynosVideoPlane *planes,
1187 int nPlanes)
Jiho Chang38ef2572012-06-01 20:58:55 +00001188{
1189 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1190 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1191 int nIndex;
1192
Dima Zavin01fa64f2012-06-13 16:42:27 -07001193 if ((pCtx == NULL) || (planes == NULL) || (nPlanes != 1)) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001194 ALOGE("%s: params must be supplied", __func__);
1195 ret = VIDEO_ERROR_BADPARAM;
1196 goto EXIT;
1197 }
1198
1199 for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
1200 if (pCtx->pInbuf[nIndex].bRegistered == VIDEO_FALSE) {
Dima Zavin01fa64f2012-06-13 16:42:27 -07001201 pCtx->pInbuf[nIndex].planes[0].addr = planes[0].addr;
1202 pCtx->pInbuf[nIndex].planes[0].allocSize = planes[0].allocSize;
1203 pCtx->pInbuf[nIndex].planes[0].fd = planes[0].fd;
Jiho Chang38ef2572012-06-01 20:58:55 +00001204 pCtx->pInbuf[nIndex].bRegistered = VIDEO_TRUE;
Dima Zavin01fa64f2012-06-13 16:42:27 -07001205 ALOGV("%s: registered buf %d (addr=%p alloc_sz=%ld fd=%d)\n", __func__, nIndex,
1206 planes[0].addr, planes[0].allocSize, planes[0].fd);
Jiho Chang38ef2572012-06-01 20:58:55 +00001207 break;
1208 }
1209 }
1210
1211 if (nIndex == pCtx->nInbufs) {
1212 ALOGE("%s: can not find non-registered input buffer", __func__);
1213 ret = VIDEO_ERROR_NOBUFFERS;
1214 }
1215
1216EXIT:
1217 return ret;
1218}
1219
1220static ExynosVideoErrorType MFC_Decoder_Register_Outbuf(
Dima Zavin01fa64f2012-06-13 16:42:27 -07001221 void *pHandle,
1222 ExynosVideoPlane *planes,
1223 int nPlanes)
Jiho Chang38ef2572012-06-01 20:58:55 +00001224{
1225 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1226 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1227 int nIndex;
1228
Dima Zavin01fa64f2012-06-13 16:42:27 -07001229 if ((pCtx == NULL) || (planes == NULL) || (nPlanes != 2)) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001230 ALOGE("%s: params must be supplied", __func__);
1231 ret = VIDEO_ERROR_BADPARAM;
1232 goto EXIT;
1233 }
1234
1235 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
1236 if (pCtx->pOutbuf[nIndex].bRegistered == VIDEO_FALSE) {
Dima Zavin01fa64f2012-06-13 16:42:27 -07001237 int plane;
1238 for (plane = 0; plane < 2; plane++) {
1239 pCtx->pOutbuf[nIndex].planes[plane].addr = planes[plane].addr;
1240 pCtx->pOutbuf[nIndex].planes[plane].allocSize = planes[plane].allocSize;
1241 pCtx->pOutbuf[nIndex].planes[plane].fd = planes[plane].fd;
1242 }
Jiho Chang38ef2572012-06-01 20:58:55 +00001243 pCtx->pOutbuf[nIndex].bRegistered = VIDEO_TRUE;
Dima Zavin01fa64f2012-06-13 16:42:27 -07001244 ALOGV("%s: registered buf %d 0:(addr=%p alloc_sz=%d fd=%d) 1:(addr=%p alloc_sz=%d fd=%d)\n",
1245 __func__, nIndex, planes[0].addr, planes[0].allocSize, planes[0].fd,
1246 planes[1].addr, planes[1].allocSize, planes[1].fd);
Jiho Chang38ef2572012-06-01 20:58:55 +00001247 break;
1248 }
1249 }
1250
1251 if (nIndex == pCtx->nOutbufs) {
1252 ALOGE("%s: can not find non-registered output buffer", __func__);
1253 ret = VIDEO_ERROR_NOBUFFERS;
1254 }
1255
1256EXIT:
1257 return ret;
1258}
1259
1260static ExynosVideoErrorType MFC_Decoder_Clear_RegisteredBuffer_Inbuf(void *pHandle)
1261{
1262 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1263 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1264 int nIndex;
1265
1266 if (pCtx == NULL) {
1267 ALOGE("%s: Video context info must be supplied", __func__);
1268 ret = VIDEO_ERROR_BADPARAM;
1269 goto EXIT;
1270 }
1271
1272 for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
1273 pCtx->pInbuf[nIndex].planes[0].addr = NULL;
1274 pCtx->pInbuf[nIndex].bRegistered = VIDEO_FALSE;
1275 }
1276
1277EXIT:
1278 return ret;
1279}
1280
1281static ExynosVideoErrorType MFC_Decoder_Clear_RegisteredBuffer_Outbuf(void *pHandle)
1282{
1283 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1284 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1285 int nIndex;
1286
1287 if (pCtx == NULL) {
1288 ALOGE("%s: Video context info must be supplied", __func__);
1289 ret = VIDEO_ERROR_BADPARAM;
1290 goto EXIT;
1291 }
1292
1293 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
1294 pCtx->pOutbuf[nIndex].planes[0].addr = NULL;
1295 pCtx->pOutbuf[nIndex].bRegistered = VIDEO_FALSE;
1296 }
1297
1298EXIT:
1299 return ret;
1300}
1301
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001302/*
1303 * [Decoder Buffer OPS] Find (Input)
1304 */
1305static int MFC_Decoder_Find_Inbuf(
1306 void *pHandle,
1307 unsigned char *pBuffer)
1308{
1309 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1310 int nIndex = -1;
1311
1312 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001313 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001314 goto EXIT;
1315 }
1316
1317 if (pBuffer == NULL) {
1318 for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
1319 if (pCtx->pInbuf[nIndex].bQueued == VIDEO_FALSE)
1320 break;
1321 }
1322 } else {
1323 for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
1324 if (pCtx->pInbuf[nIndex].planes[0].addr == pBuffer)
1325 break;
1326 }
1327 }
1328
1329 if (nIndex == pCtx->nInbufs) {
1330 nIndex = -1;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001331 }
1332
1333EXIT:
1334 return nIndex;
1335}
1336
1337/*
1338 * [Decoder Buffer OPS] Find (Outnput)
1339 */
1340static int MFC_Decoder_Find_Outbuf(
1341 void *pHandle,
1342 unsigned char *pBuffer)
1343{
1344 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1345 int nIndex = -1;
1346
1347 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001348 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001349 goto EXIT;
1350 }
1351
1352 if (pBuffer == NULL) {
1353 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
1354 if (pCtx->pOutbuf[nIndex].bQueued == VIDEO_FALSE)
1355 break;
1356 }
1357 } else {
1358 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
1359 if (pCtx->pOutbuf[nIndex].planes[0].addr == pBuffer)
1360 break;
1361 }
1362 }
1363
1364 if (nIndex == pCtx->nOutbufs) {
1365 nIndex = -1;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001366 }
1367
1368EXIT:
1369 return nIndex;
1370}
1371
1372/*
1373 * [Decoder Buffer OPS] Enqueue (Input)
1374 */
1375static ExynosVideoErrorType MFC_Decoder_Enqueue_Inbuf(
1376 void *pHandle,
1377 unsigned char *pBuffer[],
1378 unsigned int dataSize[],
1379 int nPlanes,
1380 void *pPrivate)
1381{
1382 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1383 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
Jiho Chang38ef2572012-06-01 20:58:55 +00001384 pthread_mutex_t *pMutex = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001385
1386 struct v4l2_plane planes[VIDEO_DECODER_INBUF_PLANES];
1387 struct v4l2_buffer buf;
1388 int index, i;
1389
1390 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001391 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001392 ret = VIDEO_ERROR_BADPARAM;
1393 goto EXIT;
1394 }
1395
Jiho Chang800a8d72012-04-26 13:25:31 -07001396 if (VIDEO_DECODER_INBUF_PLANES < nPlanes) {
1397 ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__,
1398 VIDEO_DECODER_INBUF_PLANES, nPlanes);
1399 ret = VIDEO_ERROR_BADPARAM;
1400 goto EXIT;
1401 }
1402
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001403 memset(&buf, 0, sizeof(buf));
1404
1405 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1406 buf.m.planes = planes;
1407 buf.length = VIDEO_DECODER_INBUF_PLANES;
1408
Jiho Chang38ef2572012-06-01 20:58:55 +00001409 index = MFC_Decoder_Find_Inbuf(pCtx, pBuffer[0]);
1410 if ((index == -1) &&
1411 (pCtx->bShareInbuf == VIDEO_TRUE) &&
1412 (pBuffer[0] != NULL))
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001413 index = MFC_Decoder_Find_Inbuf(pCtx, NULL);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001414 if (index == -1) {
1415 ret = VIDEO_ERROR_NOBUFFERS;
1416 goto EXIT;
1417 }
1418
1419 buf.index = index;
1420
1421 if (pCtx->bShareInbuf == VIDEO_TRUE) {
SeungBeom Kim1f0d5e32012-07-03 15:45:57 +09001422 buf.memory = pCtx->nMemoryType;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001423 for (i = 0; i < nPlanes; i++) {
Dima Zavin01fa64f2012-06-13 16:42:27 -07001424 buf.m.planes[i].m.fd = pCtx->pInbuf[index].planes[i].fd;
Jiho Chang38ef2572012-06-01 20:58:55 +00001425 buf.m.planes[i].length = pCtx->pInbuf[index].planes[i].allocSize;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001426 buf.m.planes[i].bytesused = dataSize[i];
1427 pCtx->pInbuf[buf.index].planes[i].addr = pBuffer[i];
Dima Zavin01fa64f2012-06-13 16:42:27 -07001428 ALOGV("%s: shared inbuf(%d) plane(%d) fd=%d len=%d used=%d\n", __func__,
1429 index, i,
1430 buf.m.planes[i].m.fd,
1431 buf.m.planes[i].length,
1432 buf.m.planes[i].bytesused);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001433 }
1434 } else {
1435 buf.memory = V4L2_MEMORY_MMAP;
1436 for (i = 0; i < nPlanes; i++)
1437 buf.m.planes[i].bytesused = dataSize[i];
1438 }
1439
Jiho Chang38ef2572012-06-01 20:58:55 +00001440 pMutex = (pthread_mutex_t*)pCtx->pInMutex;
1441 pthread_mutex_lock(pMutex);
1442 if (pCtx->pInbuf[buf.index].bQueued == VIDEO_FALSE) {
1443 if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) {
1444 ALOGE("%s: Failed to enqueue input buffer", __func__);
1445 ret = VIDEO_ERROR_APIFAIL;
1446 goto EXIT;
1447 }
1448
1449 pCtx->pInbuf[buf.index].pPrivate = pPrivate;
1450 pCtx->pInbuf[buf.index].bQueued = VIDEO_TRUE;
1451 } else {
1452 ALOGE("Lost Input Buffer");
1453 pthread_mutex_unlock(pMutex);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001454 ret = VIDEO_ERROR_APIFAIL;
1455 goto EXIT;
1456 }
Jiho Chang38ef2572012-06-01 20:58:55 +00001457 pthread_mutex_unlock(pMutex);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001458
1459EXIT:
1460 return ret;
1461}
1462
1463/*
1464 * [Decoder Buffer OPS] Enqueue (Output)
1465 */
1466static ExynosVideoErrorType MFC_Decoder_Enqueue_Outbuf(
1467 void *pHandle,
1468 unsigned char *pBuffer[],
1469 unsigned int dataSize[],
1470 int nPlanes,
1471 void *pPrivate)
1472{
1473 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1474 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
Jiho Chang38ef2572012-06-01 20:58:55 +00001475 pthread_mutex_t *pMutex = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001476
1477 struct v4l2_plane planes[VIDEO_DECODER_OUTBUF_PLANES];
1478 struct v4l2_buffer buf;
1479 int i, index;
1480
1481 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001482 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001483 ret = VIDEO_ERROR_BADPARAM;
1484 goto EXIT;
1485 }
1486
Jiho Chang38ef2572012-06-01 20:58:55 +00001487 if (VIDEO_DECODER_OUTBUF_PLANES < nPlanes) {
1488 ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__,
1489 VIDEO_DECODER_OUTBUF_PLANES, nPlanes);
1490 ret = VIDEO_ERROR_BADPARAM;
1491 goto EXIT;
1492 }
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001493
Jiho Chang38ef2572012-06-01 20:58:55 +00001494 memset(&buf, 0, sizeof(buf));
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001495 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1496 buf.m.planes = planes;
Dima Zavin01fa64f2012-06-13 16:42:27 -07001497 buf.length = nPlanes;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001498
Jiho Chang38ef2572012-06-01 20:58:55 +00001499 index = MFC_Decoder_Find_Outbuf(pCtx, pBuffer[0]);
1500 if ((index == -1) &&
1501 (pCtx->bShareOutbuf == VIDEO_TRUE) &&
1502 (pBuffer[0] != NULL))
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001503 index = MFC_Decoder_Find_Outbuf(pCtx, NULL);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001504 if (index == -1) {
1505 ret = VIDEO_ERROR_NOBUFFERS;
Jiho Chang38ef2572012-06-01 20:58:55 +00001506 ALOGE("Can not Find Buffer Index");
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001507 goto EXIT;
1508 }
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001509 buf.index = index;
1510
1511 if (pCtx->bShareOutbuf == VIDEO_TRUE) {
SeungBeom Kim1f0d5e32012-07-03 15:45:57 +09001512 buf.memory = pCtx->nMemoryType;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001513 for (i = 0; i < nPlanes; i++) {
Dima Zavin01fa64f2012-06-13 16:42:27 -07001514 buf.m.planes[i].m.fd = pCtx->pOutbuf[index].planes[i].fd;
Jiho Chang38ef2572012-06-01 20:58:55 +00001515 buf.m.planes[i].length = pCtx->pOutbuf[index].planes[i].allocSize;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001516 buf.m.planes[i].bytesused = dataSize[i];
Dima Zavin01fa64f2012-06-13 16:42:27 -07001517
1518 ALOGV("%s: shared outbuf(%d) plane=%d addr=%p fd=%d len=%d used=%d\n", __func__,
1519 index, i,
1520 pCtx->pOutbuf[index].planes[i].addr,
1521 buf.m.planes[i].m.fd,
1522 buf.m.planes[i].length,
1523 buf.m.planes[i].bytesused);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001524 }
1525 } else {
Dima Zavin01fa64f2012-06-13 16:42:27 -07001526 ALOGV("%s: non-shared outbuf(%d)\n", __func__, index);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001527 buf.memory = V4L2_MEMORY_MMAP;
1528 }
1529
Jiho Chang38ef2572012-06-01 20:58:55 +00001530 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
1531 pthread_mutex_lock(pMutex);
1532 if (pCtx->pOutbuf[buf.index].bQueued == VIDEO_FALSE) {
1533 if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) {
1534 ALOGE("%s: Failed to enqueue output buffer", __func__);
1535 ret = VIDEO_ERROR_APIFAIL;
1536 goto EXIT;
1537 }
1538
1539 pCtx->pOutbuf[buf.index].pPrivate = pPrivate;
1540 pCtx->pOutbuf[buf.index].bQueued = VIDEO_TRUE;
1541 } else {
1542 ALOGE("Lost Output Buffer");
1543 pthread_mutex_unlock(pMutex);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001544 ret = VIDEO_ERROR_APIFAIL;
1545 goto EXIT;
1546 }
Jiho Chang38ef2572012-06-01 20:58:55 +00001547 pthread_mutex_unlock(pMutex);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001548
1549EXIT:
1550 return ret;
1551}
1552
1553/*
1554 * [Decoder Buffer OPS] Dequeue (Input)
1555 */
1556static ExynosVideoBuffer *MFC_Decoder_Dequeue_Inbuf(void *pHandle)
1557{
Jiho Chang38ef2572012-06-01 20:58:55 +00001558 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1559 ExynosVideoBuffer *pInbuf = NULL;
1560 pthread_mutex_t *pMutex = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001561
1562 struct v4l2_buffer buf;
1563
1564 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001565 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001566 goto EXIT;
1567 }
1568
1569 if (pCtx->bStreamonInbuf == VIDEO_FALSE) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001570 pInbuf = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001571 goto EXIT;
1572 }
1573
1574 memset(&buf, 0, sizeof(buf));
1575
1576 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1577
1578 if (pCtx->bShareInbuf == VIDEO_TRUE)
SeungBeom Kim1f0d5e32012-07-03 15:45:57 +09001579 buf.memory = pCtx->nMemoryType;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001580 else
1581 buf.memory = V4L2_MEMORY_MMAP;
1582
Jiho Chang38ef2572012-06-01 20:58:55 +00001583 if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) {
1584 pInbuf = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001585 goto EXIT;
1586 }
1587
Jiho Chang38ef2572012-06-01 20:58:55 +00001588 pMutex = (pthread_mutex_t*)pCtx->pInMutex;
1589 pthread_mutex_lock(pMutex);
1590 pCtx->pInbuf[buf.index].bQueued = VIDEO_FALSE;
1591 pthread_mutex_unlock(pMutex);
1592 pInbuf = &pCtx->pInbuf[buf.index];
1593
1594 if (pCtx->bStreamonInbuf == VIDEO_FALSE)
1595 pInbuf = NULL;
1596
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001597EXIT:
Jiho Chang38ef2572012-06-01 20:58:55 +00001598 return pInbuf;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001599}
1600
1601/*
1602 * [Decoder Buffer OPS] Enqueue All (Output)
1603 */
1604static ExynosVideoErrorType MFC_Decoder_Enqueue_All_Outbuf(void *pHandle)
1605{
1606 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1607 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1608
Jiho Chang38ef2572012-06-01 20:58:55 +00001609 unsigned char *pBuffer[VIDEO_BUFFER_MAX_PLANES] = {NULL, };
1610 unsigned int dataSize[VIDEO_BUFFER_MAX_PLANES] = {0, };
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001611 int i;
1612
1613 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001614 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001615 ret = VIDEO_ERROR_BADPARAM;
1616 goto EXIT;
1617 }
1618
Jiho Chang38ef2572012-06-01 20:58:55 +00001619 for (i = 0; i < pCtx->nOutbufs; i++) {
1620 ret = MFC_Decoder_Enqueue_Outbuf(pCtx, pBuffer, dataSize, 0, NULL);
1621 if (ret != VIDEO_ERROR_NONE)
1622 goto EXIT;
1623 }
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001624
1625EXIT:
1626 return ret;
1627}
1628
1629/*
1630 * [Decoder Buffer OPS] Dequeue (Output)
1631 */
1632static ExynosVideoBuffer *MFC_Decoder_Dequeue_Outbuf(void *pHandle)
1633{
1634 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1635 ExynosVideoBuffer *pOutbuf = NULL;
Jiho Chang38ef2572012-06-01 20:58:55 +00001636 pthread_mutex_t *pMutex = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001637
1638 struct v4l2_buffer buf;
1639 int value;
1640
1641 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001642 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001643 goto EXIT;
1644 }
1645
1646 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001647 pOutbuf = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001648 goto EXIT;
1649 }
1650
1651 memset(&buf, 0, sizeof(buf));
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001652 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1653
1654 if (pCtx->bShareOutbuf == VIDEO_TRUE)
SeungBeom Kim1f0d5e32012-07-03 15:45:57 +09001655 buf.memory = pCtx->nMemoryType;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001656 else
1657 buf.memory = V4L2_MEMORY_MMAP;
1658
1659 /* HACK: pOutbuf return -1 means DECODING_ONLY for almost cases */
Jiho Chang38ef2572012-06-01 20:58:55 +00001660 if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) {
1661 pOutbuf = NULL;
1662 goto EXIT;
1663 }
1664
1665 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001666 pOutbuf = NULL;
1667 goto EXIT;
1668 }
1669
1670 pOutbuf = &pCtx->pOutbuf[buf.index];
1671
1672 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS, &value);
1673
1674 switch (value) {
1675 case 0:
1676 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_ONLY;
1677 break;
1678 case 1:
1679 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_DECODING;
1680 break;
1681 case 2:
1682 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_ONLY;
1683 break;
1684 case 3:
1685 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_CHANGE_RESOL;
1686 break;
1687 default:
1688 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_UNKNOWN;
1689 break;
1690 }
1691
1692 switch (buf.flags & (0x7 << 3)) {
1693 case V4L2_BUF_FLAG_KEYFRAME:
1694 pOutbuf->frameType = VIDEO_FRAME_I;
1695 break;
1696 case V4L2_BUF_FLAG_PFRAME:
1697 pOutbuf->frameType = VIDEO_FRAME_P;
1698 break;
1699 case V4L2_BUF_FLAG_BFRAME:
1700 pOutbuf->frameType = VIDEO_FRAME_B;
1701 break;
1702 default:
1703 pOutbuf->frameType = VIDEO_FRAME_OTHERS;
1704 break;
1705 };
1706
Jiho Chang38ef2572012-06-01 20:58:55 +00001707 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
1708 pthread_mutex_lock(pMutex);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001709 pOutbuf->bQueued = VIDEO_FALSE;
Jiho Chang38ef2572012-06-01 20:58:55 +00001710 pthread_mutex_unlock(pMutex);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001711
1712EXIT:
1713 return pOutbuf;
1714}
1715
Jiho Chang38ef2572012-06-01 20:58:55 +00001716static ExynosVideoErrorType MFC_Decoder_Clear_Queued_Inbuf(void *pHandle)
1717{
1718 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1719 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1720 int i;
1721
1722 if (pCtx == NULL) {
1723 ALOGE("%s: Video context info must be supplied", __func__);
1724 ret = VIDEO_ERROR_BADPARAM;
1725 goto EXIT;
1726 }
1727
1728 for (i = 0; i < pCtx->nInbufs; i++) {
1729 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
1730 }
1731
1732EXIT:
1733 return ret;
1734}
1735
1736static ExynosVideoErrorType MFC_Decoder_Clear_Queued_Outbuf(void *pHandle)
1737{
1738 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1739 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1740 int i;
1741
1742 if (pCtx == NULL) {
1743 ALOGE("%s: Video context info must be supplied", __func__);
1744 ret = VIDEO_ERROR_BADPARAM;
1745 goto EXIT;
1746 }
1747
1748 for (i = 0; i < pCtx->nOutbufs; i++) {
1749 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
1750 }
1751
1752EXIT:
1753 return ret;
1754}
1755
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001756/*
1757 * [Decoder OPS] Common
1758 */
1759static ExynosVideoDecOps defDecOps = {
Jiho Chang38ef2572012-06-01 20:58:55 +00001760 .nSize = 0,
1761 .Init = MFC_Decoder_Init,
1762 .Finalize = MFC_Decoder_Finalize,
1763 .Set_DisplayDelay = MFC_Decoder_Set_DisplayDelay,
1764 .Enable_PackedPB = MFC_Decoder_Enable_PackedPB,
1765 .Enable_LoopFilter = MFC_Decoder_Enable_LoopFilter,
1766 .Enable_SliceMode = MFC_Decoder_Enable_SliceMode,
1767 .Get_ActualBufferCount = MFC_Decoder_Get_ActualBufferCount,
1768 .Set_FrameTag = MFC_Decoder_Set_FrameTag,
1769 .Get_FrameTag = MFC_Decoder_Get_FrameTag,
1770 .Enable_SEIParsing = MFC_Decoder_Enable_SEIParsing,
1771 .Get_FramePackingInfo = MFC_Decoder_Get_FramePackingInfo,
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001772};
1773
1774/*
1775 * [Decoder Buffer OPS] Input
1776 */
1777static ExynosVideoDecBufferOps defInbufOps = {
Jiho Chang38ef2572012-06-01 20:58:55 +00001778 .nSize = 0,
1779 .Enable_Cacheable = MFC_Decoder_Enable_Cacheable_Inbuf,
1780 .Set_Shareable = MFC_Decoder_Set_Shareable_Inbuf,
1781 .Get_Buffer = NULL,
1782 .Set_Geometry = MFC_Decoder_Set_Geometry_Inbuf,
1783 .Get_Geometry = NULL,
1784 .Setup = MFC_Decoder_Setup_Inbuf,
1785 .Run = MFC_Decoder_Run_Inbuf,
1786 .Stop = MFC_Decoder_Stop_Inbuf,
1787 .Enqueue = MFC_Decoder_Enqueue_Inbuf,
1788 .Enqueue_All = NULL,
1789 .Dequeue = MFC_Decoder_Dequeue_Inbuf,
1790 .Register = MFC_Decoder_Register_Inbuf,
1791 .Clear_RegisteredBuffer = MFC_Decoder_Clear_RegisteredBuffer_Inbuf,
1792 .Clear_Queue = MFC_Decoder_Clear_Queued_Inbuf,
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001793};
1794
1795/*
1796 * [Decoder Buffer OPS] Output
1797 */
1798static ExynosVideoDecBufferOps defOutbufOps = {
Jiho Chang38ef2572012-06-01 20:58:55 +00001799 .nSize = 0,
1800 .Enable_Cacheable = MFC_Decoder_Enable_Cacheable_Outbuf,
1801 .Set_Shareable = MFC_Decoder_Set_Shareable_Outbuf,
1802 .Get_Buffer = MFC_Decoder_Get_Buffer_Outbuf,
1803 .Set_Geometry = MFC_Decoder_Set_Geometry_Outbuf,
1804 .Get_Geometry = MFC_Decoder_Get_Geometry_Outbuf,
1805 .Setup = MFC_Decoder_Setup_Outbuf,
1806 .Run = MFC_Decoder_Run_Outbuf,
1807 .Stop = MFC_Decoder_Stop_Outbuf,
1808 .Enqueue = MFC_Decoder_Enqueue_Outbuf,
1809 .Enqueue_All = MFC_Decoder_Enqueue_All_Outbuf,
1810 .Dequeue = MFC_Decoder_Dequeue_Outbuf,
1811 .Register = MFC_Decoder_Register_Outbuf,
1812 .Clear_RegisteredBuffer = MFC_Decoder_Clear_RegisteredBuffer_Outbuf,
1813 .Clear_Queue = MFC_Decoder_Clear_Queued_Outbuf,
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001814};
1815
1816int Exynos_Video_Register_Decoder(
1817 ExynosVideoDecOps *pDecOps,
1818 ExynosVideoDecBufferOps *pInbufOps,
1819 ExynosVideoDecBufferOps *pOutbufOps)
1820{
1821 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1822
1823 if ((pDecOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) {
1824 ret = VIDEO_ERROR_BADPARAM;
1825 goto EXIT;
1826 }
1827
1828 defDecOps.nSize = sizeof(defDecOps);
1829 defInbufOps.nSize = sizeof(defInbufOps);
1830 defOutbufOps.nSize = sizeof(defOutbufOps);
1831
1832 memcpy((char *)pDecOps + sizeof(pDecOps->nSize), (char *)&defDecOps + sizeof(defDecOps.nSize),
1833 pDecOps->nSize - sizeof(pDecOps->nSize));
1834
1835 memcpy((char *)pInbufOps + sizeof(pInbufOps->nSize), (char *)&defInbufOps + sizeof(defInbufOps.nSize),
1836 pInbufOps->nSize - sizeof(pInbufOps->nSize));
1837
1838 memcpy((char *)pOutbufOps + sizeof(pOutbufOps->nSize), (char *)&defOutbufOps + sizeof(defOutbufOps.nSize),
1839 pOutbufOps->nSize - sizeof(pOutbufOps->nSize));
1840
1841EXIT:
1842 return ret;
1843}