blob: a456a2be231fdb8ec2704d660eb5db31aba0efae [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
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +090041#include "ion.h"
Jiho Chang20d3e6e2012-03-24 03:43:08 +090042#include "ExynosVideoApi.h"
43#include "ExynosVideoDec.h"
SeungBeom Kim81a947b2013-01-16 15:23:19 +090044#include "OMX_Core.h"
Jiho Chang20d3e6e2012-03-24 03:43:08 +090045
46/* #define LOG_NDEBUG 0 */
47#define LOG_TAG "ExynosVideoDecoder"
48#include <utils/Log.h>
49
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +090050#define MAX_OUTPUTBUFFER_COUNT 32
51
Jiho Chang20d3e6e2012-03-24 03:43:08 +090052/*
53 * [Common] __CodingType_To_V4L2PixelFormat
54 */
55static unsigned int __CodingType_To_V4L2PixelFormat(ExynosVideoCodingType codingType)
56{
57 unsigned int pixelformat = V4L2_PIX_FMT_H264;
58
59 switch (codingType) {
60 case VIDEO_CODING_AVC:
61 pixelformat = V4L2_PIX_FMT_H264;
62 break;
63 case VIDEO_CODING_MPEG4:
64 pixelformat = V4L2_PIX_FMT_MPEG4;
65 break;
66 case VIDEO_CODING_VP8:
67 pixelformat = V4L2_PIX_FMT_VP8;
68 break;
69 case VIDEO_CODING_H263:
70 pixelformat = V4L2_PIX_FMT_H263;
71 break;
72 case VIDEO_CODING_VC1:
73 pixelformat = V4L2_PIX_FMT_VC1_ANNEX_G;
74 break;
75 case VIDEO_CODING_VC1_RCV:
76 pixelformat = V4L2_PIX_FMT_VC1_ANNEX_L;
77 break;
78 case VIDEO_CODING_MPEG2:
Jiho Chang800a8d72012-04-26 13:25:31 -070079 pixelformat = V4L2_PIX_FMT_MPEG2;
Jiho Chang20d3e6e2012-03-24 03:43:08 +090080 break;
81 default:
82 pixelformat = V4L2_PIX_FMT_H264;
83 break;
84 }
85
86 return pixelformat;
87}
88
89/*
90 * [Common] __ColorFormatType_To_V4L2PixelFormat
91 */
92static unsigned int __ColorFormatType_To_V4L2PixelFormat(ExynosVideoColorFormatType colorFormatType)
93{
94 unsigned int pixelformat = V4L2_PIX_FMT_NV12M;
95
96 switch (colorFormatType) {
97 case VIDEO_COLORFORMAT_NV12_TILED:
98 pixelformat = V4L2_PIX_FMT_NV12MT_16X16;
99 break;
100 case VIDEO_COLORFORMAT_NV21:
101 pixelformat = V4L2_PIX_FMT_NV21M;
102 break;
103 case VIDEO_COLORFORMAT_NV12:
104 default:
105 pixelformat = V4L2_PIX_FMT_NV12M;
106 break;
107 }
108
109 return pixelformat;
110}
111
112/*
113 * [Decoder OPS] Init
114 */
SeungBeom Kimc94beae2012-07-05 14:59:40 +0900115static void *MFC_Decoder_Init(int nMemoryType)
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900116{
117 ExynosVideoDecContext *pCtx = NULL;
Jiho Chang38ef2572012-06-01 20:58:55 +0000118 pthread_mutex_t *pMutex = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900119 int needCaps = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING);
120
121 pCtx = (ExynosVideoDecContext *)malloc(sizeof(*pCtx));
122 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700123 ALOGE("%s: Failed to allocate decoder context buffer", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900124 goto EXIT_ALLOC_FAIL;
125 }
126
127 memset(pCtx, 0, sizeof(*pCtx));
128
Jiho Chang38ef2572012-06-01 20:58:55 +0000129 pCtx->hDec = exynos_v4l2_open_devname(VIDEO_DECODER_NAME, O_RDWR, 0);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900130 if (pCtx->hDec < 0) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700131 ALOGE("%s: Failed to open decoder device", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900132 goto EXIT_OPEN_FAIL;
133 }
134
135 if (!exynos_v4l2_querycap(pCtx->hDec, needCaps)) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700136 ALOGE("%s: Failed to querycap", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900137 goto EXIT_QUERYCAP_FAIL;
138 }
139
140 pCtx->bStreamonInbuf = VIDEO_FALSE;
141 pCtx->bStreamonOutbuf = VIDEO_FALSE;
142
SeungBeom Kimc94beae2012-07-05 14:59:40 +0900143 pCtx->nMemoryType = nMemoryType;
SeungBeom Kim1f0d5e32012-07-03 15:45:57 +0900144
Jiho Chang38ef2572012-06-01 20:58:55 +0000145 pMutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
146 if (pMutex == NULL) {
147 ALOGE("%s: Failed to allocate mutex about input buffer", __func__);
148 goto EXIT_QUERYCAP_FAIL;
149 }
Jiho Chang38ef2572012-06-01 20:58:55 +0000150 if (pthread_mutex_init(pMutex, NULL) != 0) {
151 free(pMutex);
152 goto EXIT_QUERYCAP_FAIL;
153 }
154 pCtx->pInMutex = (void*)pMutex;
155
156 pMutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
157 if (pMutex == NULL) {
158 ALOGE("%s: Failed to allocate mutex about output buffer", __func__);
159 goto EXIT_QUERYCAP_FAIL;
160 }
Jiho Chang38ef2572012-06-01 20:58:55 +0000161 if (pthread_mutex_init(pMutex, NULL) != 0) {
162 free(pMutex);
163 goto EXIT_QUERYCAP_FAIL;
164 }
165 pCtx->pOutMutex = (void*)pMutex;
166
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +0900167 pCtx->hIONHandle = (void*)ion_client_create();
168 pCtx->nPrivateDataShareFD = ion_alloc((ion_client)pCtx->hIONHandle,
169 sizeof(PrivateDataShareBuffer) * VIDEO_BUFFER_MAX_NUM, 0, ION_HEAP_SYSTEM_MASK, ION_FLAG_CACHED);
170 pCtx->nPrivateDataShareAddress =
171 ion_map(pCtx->nPrivateDataShareFD, sizeof(PrivateDataShareBuffer) * VIDEO_BUFFER_MAX_NUM, 0);
172 memset(pCtx->nPrivateDataShareAddress, -1, sizeof(PrivateDataShareBuffer) * VIDEO_BUFFER_MAX_NUM);
173
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900174 return (void *)pCtx;
175
176EXIT_QUERYCAP_FAIL:
Jiho Chang38ef2572012-06-01 20:58:55 +0000177 if (pCtx->pInMutex != NULL) {
178 pthread_mutex_destroy(pCtx->pInMutex);
179 free(pCtx->pInMutex);
180 }
181
182 if (pCtx->pOutMutex != NULL) {
183 pthread_mutex_destroy(pCtx->pOutMutex);
184 free(pCtx->pOutMutex);
185 }
186
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900187 close(pCtx->hDec);
188
189EXIT_OPEN_FAIL:
190 free(pCtx);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900191
192EXIT_ALLOC_FAIL:
193 return NULL;
194}
195
196/*
197 * [Decoder OPS] Finalize
198 */
199static ExynosVideoErrorType MFC_Decoder_Finalize(void *pHandle)
200{
Jiho Chang38ef2572012-06-01 20:58:55 +0000201 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
202 ExynosVideoPlane *pVideoPlane = NULL;
203 pthread_mutex_t *pMutex = NULL;
204 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900205 int i, j;
206
207 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700208 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900209 ret = VIDEO_ERROR_BADPARAM;
210 goto EXIT;
211 }
212
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +0900213 ion_unmap(pCtx->nPrivateDataShareAddress, sizeof(PrivateDataShareBuffer) * VIDEO_BUFFER_MAX_NUM);
214 ion_free(pCtx->nPrivateDataShareFD);
215 ion_client_destroy((ion_client)pCtx->hIONHandle);
216
Jiho Chang38ef2572012-06-01 20:58:55 +0000217 if (pCtx->pOutMutex != NULL) {
218 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
219 pthread_mutex_destroy(pMutex);
220 free(pMutex);
221 pCtx->pOutMutex = NULL;
222 }
223
224 if (pCtx->pInMutex != NULL) {
225 pMutex = (pthread_mutex_t*)pCtx->pInMutex;
226 pthread_mutex_destroy(pMutex);
227 free(pMutex);
228 pCtx->pInMutex = NULL;
229 }
230
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900231 if (pCtx->bShareInbuf == VIDEO_FALSE) {
232 for (i = 0; i < pCtx->nInbufs; i++) {
233 for (j = 0; j < VIDEO_DECODER_INBUF_PLANES; j++) {
234 pVideoPlane = &pCtx->pInbuf[i].planes[j];
235 if (pVideoPlane->addr != NULL) {
236 munmap(pVideoPlane->addr, pVideoPlane->allocSize);
237 pVideoPlane->addr = NULL;
238 pVideoPlane->allocSize = 0;
239 pVideoPlane->dataSize = 0;
240 }
241
242 pCtx->pInbuf[i].pGeometry = NULL;
243 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
Jiho Chang38ef2572012-06-01 20:58:55 +0000244 pCtx->pInbuf[i].bRegistered = VIDEO_FALSE;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900245 }
246 }
247 }
248
249 if (pCtx->bShareOutbuf == VIDEO_FALSE) {
250 for (i = 0; i < pCtx->nOutbufs; i++) {
251 for (j = 0; j < VIDEO_DECODER_OUTBUF_PLANES; j++) {
252 pVideoPlane = &pCtx->pOutbuf[i].planes[j];
253 if (pVideoPlane->addr != NULL) {
254 munmap(pVideoPlane->addr, pVideoPlane->allocSize);
255 pVideoPlane->addr = NULL;
256 pVideoPlane->allocSize = 0;
257 pVideoPlane->dataSize = 0;
258 }
259
260 pCtx->pOutbuf[i].pGeometry = NULL;
261 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
Jiho Chang38ef2572012-06-01 20:58:55 +0000262 pCtx->pOutbuf[i].bRegistered = VIDEO_FALSE;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900263 }
264 }
265 }
266
267 if (pCtx->pInbuf != NULL)
268 free(pCtx->pInbuf);
269
270 if (pCtx->pOutbuf != NULL)
271 free(pCtx->pOutbuf);
272
273 if (pCtx->hDec > 0)
274 close(pCtx->hDec);
275
276 free(pCtx);
277
278EXIT:
279 return ret;
280}
281
282/*
283 * [Decoder OPS] Set Frame Tag
284 */
285static ExynosVideoErrorType MFC_Decoder_Set_FrameTag(
286 void *pHandle,
287 int frameTag)
288{
289 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
290 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
291
292 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700293 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900294 ret = VIDEO_ERROR_BADPARAM;
295 goto EXIT;
296 }
297
Jiho Chang38ef2572012-06-01 20:58:55 +0000298 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, frameTag) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900299 ret = VIDEO_ERROR_APIFAIL;
300 goto EXIT;
301 }
302
303EXIT:
304 return ret;
305}
306
307/*
308 * [Decoder OPS] Get Frame Tag
309 */
310static int MFC_Decoder_Get_FrameTag(void *pHandle)
311{
312 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
313 int frameTag = -1;
314
315 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700316 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900317 goto EXIT;
318 }
319
320 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, &frameTag);
321
322EXIT:
323 return frameTag;
324}
325
326/*
327 * [Decoder OPS] Get Buffer Count
328 */
329static int MFC_Decoder_Get_ActualBufferCount(void *pHandle)
330{
331 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
332 int bufferCount = -1;
333
334 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700335 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900336 goto EXIT;
337 }
338
339 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, &bufferCount);
340
341EXIT:
342 return bufferCount;
343}
344
345/*
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900346 * [Decoder OPS] Set Display Delay
347 */
348static ExynosVideoErrorType MFC_Decoder_Set_DisplayDelay(
349 void *pHandle,
350 int delay)
351{
352 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
353 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
354
355 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700356 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900357 ret = VIDEO_ERROR_BADPARAM;
358 goto EXIT;
359 }
360
Jiho Chang38ef2572012-06-01 20:58:55 +0000361 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 +0900362 ret = VIDEO_ERROR_APIFAIL;
363 goto EXIT;
364 }
365
366EXIT:
367 return ret;
368}
369
370/*
SeungBeom Kime8aae8e2013-06-13 12:17:56 +0900371 * [Decoder OPS] Set I-Frame Decoding
372 */
373static ExynosVideoErrorType MFC_Decoder_Set_IFrameDecoding(
374 void *pHandle)
375{
376 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
377 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
378
379 if (pCtx == NULL) {
380 ALOGE("%s: Video context info must be supplied", __func__);
381 ret = VIDEO_ERROR_BADPARAM;
382 goto EXIT;
383 }
384
385 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_I_FRAME_DECODING, 1) != 0) {
386 ret = VIDEO_ERROR_APIFAIL;
387 goto EXIT;
388 }
389
390EXIT:
391 return ret;
392}
393
394/*
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900395 * [Decoder OPS] Enable Packed PB
396 */
397static ExynosVideoErrorType MFC_Decoder_Enable_PackedPB(void *pHandle)
398{
399 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
400 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
401
402 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700403 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900404 ret = VIDEO_ERROR_BADPARAM;
405 goto EXIT;
406 }
407
Jiho Chang38ef2572012-06-01 20:58:55 +0000408 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_PACKED_PB, 1) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900409 ret = VIDEO_ERROR_APIFAIL;
410 goto EXIT;
411 }
412
413EXIT:
414 return ret;
415}
416
417/*
418 * [Decoder OPS] Enable Loop Filter
419 */
420static ExynosVideoErrorType MFC_Decoder_Enable_LoopFilter(void *pHandle)
421{
422 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
423 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
424
425 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700426 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900427 ret = VIDEO_ERROR_BADPARAM;
428 goto EXIT;
429 }
430
Jiho Chang38ef2572012-06-01 20:58:55 +0000431 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER, 1) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900432 ret = VIDEO_ERROR_APIFAIL;
433 goto EXIT;
434 }
435
436EXIT:
437 return ret;
438}
439
440/*
441 * [Decoder OPS] Enable Slice Mode
442 */
443static ExynosVideoErrorType MFC_Decoder_Enable_SliceMode(void *pHandle)
444{
445 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
446 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
447
448 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700449 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900450 ret = VIDEO_ERROR_BADPARAM;
451 goto EXIT;
452 }
453
Jiho Chang38ef2572012-06-01 20:58:55 +0000454 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE, 1) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900455 ret = VIDEO_ERROR_APIFAIL;
456 goto EXIT;
457 }
458
459EXIT:
460 return ret;
461}
462
463/*
Jiho Chang800a8d72012-04-26 13:25:31 -0700464 * [Decoder OPS] Enable SEI Parsing
465 */
466static ExynosVideoErrorType MFC_Decoder_Enable_SEIParsing(void *pHandle)
467{
468 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
469 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
470
471 if (pCtx == NULL) {
472 ALOGE("%s: Video context info must be supplied", __func__);
473 ret = VIDEO_ERROR_BADPARAM;
474 goto EXIT;
475 }
476
Jiho Chang38ef2572012-06-01 20:58:55 +0000477 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING, 1) != 0) {
Jiho Chang800a8d72012-04-26 13:25:31 -0700478 ret = VIDEO_ERROR_APIFAIL;
479 goto EXIT;
480 }
481
482EXIT:
483 return ret;
484}
485
486/*
487 * [Decoder OPS] Get Frame Packing information
488 */
489static ExynosVideoErrorType MFC_Decoder_Get_FramePackingInfo(
490 void *pHandle,
491 ExynosVideoFramePacking *pFramePacking)
492{
493 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
494 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
495
496 struct v4l2_ext_control ext_ctrl[FRAME_PACK_SEI_INFO_NUM];
497 struct v4l2_ext_controls ext_ctrls;
498
499 int seiAvailable, seiInfo, seiGridPos, i;
500 unsigned int seiArgmtId;
501
502
Jiho Chang38ef2572012-06-01 20:58:55 +0000503 if ((pCtx == NULL) || (pFramePacking == NULL)) {
504 ALOGE("%s: Video context info or FramePacking pointer must be supplied", __func__);
Jiho Chang800a8d72012-04-26 13:25:31 -0700505 ret = VIDEO_ERROR_BADPARAM;
506 goto EXIT;
507 }
508
509 memset(pFramePacking, 0, sizeof(*pFramePacking));
510 memset(ext_ctrl, 0, (sizeof(struct v4l2_ext_control) * FRAME_PACK_SEI_INFO_NUM));
511
512 ext_ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
513 ext_ctrls.count = FRAME_PACK_SEI_INFO_NUM;
514 ext_ctrls.controls = ext_ctrl;
515 ext_ctrl[0].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_AVAIL;
516 ext_ctrl[1].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRGMENT_ID;
517 ext_ctrl[2].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_INFO;
518 ext_ctrl[3].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_GRID_POS;
519
Jiho Chang38ef2572012-06-01 20:58:55 +0000520 if (exynos_v4l2_g_ext_ctrl(pCtx->hDec, &ext_ctrls) != 0) {
Jiho Chang800a8d72012-04-26 13:25:31 -0700521 ret = VIDEO_ERROR_APIFAIL;
522 goto EXIT;
523 }
524
525 seiAvailable = ext_ctrl[0].value;
526 seiArgmtId = ext_ctrl[1].value;
527 seiInfo = ext_ctrl[2].value;
528 seiGridPos = ext_ctrl[3].value;
529
530 pFramePacking->available = seiAvailable;
531 pFramePacking->arrangement_id = seiArgmtId;
532
533 pFramePacking->arrangement_cancel_flag = OPERATE_BIT(seiInfo, 0x1, 0);
534 pFramePacking->arrangement_type = OPERATE_BIT(seiInfo, 0x3f, 1);
535 pFramePacking->quincunx_sampling_flag = OPERATE_BIT(seiInfo, 0x1, 8);
536 pFramePacking->content_interpretation_type = OPERATE_BIT(seiInfo, 0x3f, 9);
537 pFramePacking->spatial_flipping_flag = OPERATE_BIT(seiInfo, 0x1, 15);
538 pFramePacking->frame0_flipped_flag = OPERATE_BIT(seiInfo, 0x1, 16);
539 pFramePacking->field_views_flag = OPERATE_BIT(seiInfo, 0x1, 17);
540 pFramePacking->current_frame_is_frame0_flag = OPERATE_BIT(seiInfo, 0x1, 18);
541
542 pFramePacking->frame0_grid_pos_x = OPERATE_BIT(seiGridPos, 0xf, 0);
543 pFramePacking->frame0_grid_pos_y = OPERATE_BIT(seiGridPos, 0xf, 4);
544 pFramePacking->frame1_grid_pos_x = OPERATE_BIT(seiGridPos, 0xf, 8);
545 pFramePacking->frame1_grid_pos_y = OPERATE_BIT(seiGridPos, 0xf, 12);
546
547EXIT:
548 return ret;
549}
550
551/*
552 * [Decoder Buffer OPS] Enable Cacheable (Input)
553 */
554static ExynosVideoErrorType MFC_Decoder_Enable_Cacheable_Inbuf(void *pHandle)
555{
556 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
557 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
558
559 if (pCtx == NULL) {
560 ALOGE("%s: Video context info must be supplied", __func__);
561 ret = VIDEO_ERROR_BADPARAM;
562 goto EXIT;
563 }
564
Jiho Chang38ef2572012-06-01 20:58:55 +0000565 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_CACHEABLE, 2) != 0) {
Jiho Chang800a8d72012-04-26 13:25:31 -0700566 ret = VIDEO_ERROR_APIFAIL;
567 goto EXIT;
568 }
569
570EXIT:
571 return ret;
572}
573
574/*
575 * [Decoder Buffer OPS] Enable Cacheable (Output)
576 */
577static ExynosVideoErrorType MFC_Decoder_Enable_Cacheable_Outbuf(void *pHandle)
578{
579 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
580 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
581
582 if (pCtx == NULL) {
583 ALOGE("%s: Video context info must be supplied", __func__);
584 ret = VIDEO_ERROR_BADPARAM;
585 goto EXIT;
586 }
587
Jiho Chang38ef2572012-06-01 20:58:55 +0000588 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_CACHEABLE, 1) != 0) {
Jiho Chang800a8d72012-04-26 13:25:31 -0700589 ret = VIDEO_ERROR_APIFAIL;
590 goto EXIT;
591 }
592
593EXIT:
594 return ret;
595}
596
597/*
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900598 * [Decoder Buffer OPS] Set Shareable Buffer (Input)
599 */
600static ExynosVideoErrorType MFC_Decoder_Set_Shareable_Inbuf(void *pHandle)
601{
602 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
603 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
604
605 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700606 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900607 ret = VIDEO_ERROR_BADPARAM;
608 goto EXIT;
609 }
610
611 pCtx->bShareInbuf = VIDEO_TRUE;
612
613EXIT:
614 return ret;
615}
616
617/*
618 * [Decoder Buffer OPS] Set Shareable Buffer (Output)
619 */
620static ExynosVideoErrorType MFC_Decoder_Set_Shareable_Outbuf(void *pHandle)
621{
622 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
623 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
624
625 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700626 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900627 ret = VIDEO_ERROR_BADPARAM;
628 goto EXIT;
629 }
630
631 pCtx->bShareOutbuf = VIDEO_TRUE;
632
633EXIT:
634 return ret;
635}
636
637/*
Jiho Chang38ef2572012-06-01 20:58:55 +0000638 * [Decoder Buffer OPS] Get Buffer (Input)
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900639 */
Jiho Chang38ef2572012-06-01 20:58:55 +0000640static ExynosVideoErrorType MFC_Decoder_Get_Buffer_Inbuf(
641 void *pHandle,
642 int nIndex,
643 ExynosVideoBuffer **pBuffer)
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900644{
645 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
646 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
647
648 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700649 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang38ef2572012-06-01 20:58:55 +0000650 *pBuffer = NULL;
651 ret = VIDEO_ERROR_BADPARAM;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900652 goto EXIT;
653 }
654
Jiho Chang38ef2572012-06-01 20:58:55 +0000655 if (pCtx->nInbufs <= nIndex) {
656 *pBuffer = NULL;
657 ret = VIDEO_ERROR_BADPARAM;
658 goto EXIT;
659 }
660
661 *pBuffer = (ExynosVideoBuffer *)&pCtx->pInbuf[nIndex];
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900662
663EXIT:
664 return ret;
665}
666
667/*
Jiho Chang38ef2572012-06-01 20:58:55 +0000668 * [Decoder Buffer OPS] Get Buffer (Output)
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900669 */
Jiho Chang38ef2572012-06-01 20:58:55 +0000670static ExynosVideoErrorType MFC_Decoder_Get_Buffer_Outbuf(
671 void *pHandle,
672 int nIndex,
673 ExynosVideoBuffer **pBuffer)
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900674{
675 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
676 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
677
678 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700679 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang38ef2572012-06-01 20:58:55 +0000680 *pBuffer = NULL;
681 ret = VIDEO_ERROR_BADPARAM;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900682 goto EXIT;
683 }
684
Jiho Chang38ef2572012-06-01 20:58:55 +0000685 if (pCtx->nOutbufs <= nIndex) {
686 *pBuffer = NULL;
687 ret = VIDEO_ERROR_BADPARAM;
688 goto EXIT;
689 }
690
691 *pBuffer = (ExynosVideoBuffer *)&pCtx->pOutbuf[nIndex];
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900692
693EXIT:
694 return ret;
695}
696
697/*
698 * [Decoder Buffer OPS] Set Geometry (Input)
699 */
700static ExynosVideoErrorType MFC_Decoder_Set_Geometry_Inbuf(
701 void *pHandle,
702 ExynosVideoGeometry *bufferConf)
703{
704 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
705 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
706
707 struct v4l2_format fmt;
708
709 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700710 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900711 ret = VIDEO_ERROR_BADPARAM;
712 goto EXIT;
713 }
714
715 if (bufferConf == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700716 ALOGE("%s: Buffer geometry must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900717 ret = VIDEO_ERROR_BADPARAM;
718 goto EXIT;
719 }
720
721 memset(&fmt, 0, sizeof(fmt));
722
723 fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
724 fmt.fmt.pix_mp.pixelformat = __CodingType_To_V4L2PixelFormat(bufferConf->eCompressionFormat);
725 fmt.fmt.pix_mp.plane_fmt[0].sizeimage = bufferConf->nSizeImage;
726
Jiho Chang38ef2572012-06-01 20:58:55 +0000727 if (exynos_v4l2_s_fmt(pCtx->hDec, &fmt) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900728 ret = VIDEO_ERROR_APIFAIL;
729 goto EXIT;
730 }
731
732 memcpy(&pCtx->inbufGeometry, bufferConf, sizeof(pCtx->inbufGeometry));
733
734EXIT:
735 return ret;
736}
737
738/*
739 * [Decoder Buffer OPS] Set Geometry (Output)
740 */
741static ExynosVideoErrorType MFC_Decoder_Set_Geometry_Outbuf(
742 void *pHandle,
743 ExynosVideoGeometry *bufferConf)
744{
745 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
746 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
747
748 struct v4l2_format fmt;
749
750 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700751 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900752 ret = VIDEO_ERROR_BADPARAM;
753 goto EXIT;
754 }
755
756 if (bufferConf == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700757 ALOGE("%s: Buffer geometry must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900758 ret = VIDEO_ERROR_BADPARAM;
759 goto EXIT;
760 }
761
762 memset(&fmt, 0, sizeof(fmt));
763
764 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
765 fmt.fmt.pix_mp.pixelformat = __ColorFormatType_To_V4L2PixelFormat(bufferConf->eColorFormat);
766
Jiho Chang38ef2572012-06-01 20:58:55 +0000767 if (exynos_v4l2_s_fmt(pCtx->hDec, &fmt) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900768 ret = VIDEO_ERROR_APIFAIL;
769 goto EXIT;
770 }
771
772 memcpy(&pCtx->outbufGeometry, bufferConf, sizeof(pCtx->outbufGeometry));
773
774EXIT:
775 return ret;
776}
777
778/*
779 * [Decoder Buffer OPS] Get Geometry (Output)
780 */
781static ExynosVideoErrorType MFC_Decoder_Get_Geometry_Outbuf(
782 void *pHandle,
783 ExynosVideoGeometry *bufferConf)
784{
785 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
786 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
787
788 struct v4l2_format fmt;
789 struct v4l2_crop crop;
790
791 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700792 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900793 ret = VIDEO_ERROR_BADPARAM;
794 goto EXIT;
795 }
796
797 if (bufferConf == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700798 ALOGE("%s: Buffer geometry must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900799 ret = VIDEO_ERROR_BADPARAM;
800 goto EXIT;
801 }
802
803 memset(&fmt, 0, sizeof(fmt));
804 memset(&crop, 0, sizeof(crop));
805
806 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
Jiho Chang38ef2572012-06-01 20:58:55 +0000807 if (exynos_v4l2_g_fmt(pCtx->hDec, &fmt) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900808 ret = VIDEO_ERROR_APIFAIL;
809 goto EXIT;
810 }
811
812 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
Jiho Chang38ef2572012-06-01 20:58:55 +0000813 if (exynos_v4l2_g_crop(pCtx->hDec, &crop) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900814 ret = VIDEO_ERROR_APIFAIL;
815 goto EXIT;
816 }
817
818 bufferConf->nFrameWidth = fmt.fmt.pix_mp.width;
819 bufferConf->nFrameHeight = fmt.fmt.pix_mp.height;
820
821 bufferConf->cropRect.nTop = crop.c.top;
822 bufferConf->cropRect.nLeft = crop.c.left;
823 bufferConf->cropRect.nWidth = crop.c.width;
824 bufferConf->cropRect.nHeight = crop.c.height;
825
826EXIT:
827 return ret;
828}
829
830/*
831 * [Decoder Buffer OPS] Setup (Input)
832 */
833static ExynosVideoErrorType MFC_Decoder_Setup_Inbuf(
834 void *pHandle,
835 unsigned int nBufferCount)
836{
Jiho Chang38ef2572012-06-01 20:58:55 +0000837 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
838 ExynosVideoPlane *pVideoPlane = NULL;
839 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900840
841 struct v4l2_requestbuffers req;
842 struct v4l2_buffer buf;
843 struct v4l2_plane planes[VIDEO_DECODER_INBUF_PLANES];
844 int i;
845
846 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700847 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900848 ret = VIDEO_ERROR_BADPARAM;
849 goto EXIT;
850 }
851
852 if (nBufferCount == 0) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700853 ALOGE("%s: Buffer count must be greater than 0", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900854 ret = VIDEO_ERROR_BADPARAM;
855 goto EXIT;
856 }
857
Dima Zavin01fa64f2012-06-13 16:42:27 -0700858 ALOGV("%s: setting up inbufs (%d) shared=%s\n", __func__, nBufferCount,
859 pCtx->bShareInbuf ? "true" : "false");
860
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900861 memset(&req, 0, sizeof(req));
862
863 req.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
864 req.count = nBufferCount;
865
866 if (pCtx->bShareInbuf == VIDEO_TRUE)
SeungBeom Kim1f0d5e32012-07-03 15:45:57 +0900867 req.memory = pCtx->nMemoryType;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900868 else
869 req.memory = V4L2_MEMORY_MMAP;
870
Jiho Chang38ef2572012-06-01 20:58:55 +0000871 if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900872 ret = VIDEO_ERROR_APIFAIL;
873 goto EXIT;
874 }
875
SeungBeom Kim30e79fb2012-07-03 18:31:30 +0900876 if (req.count != nBufferCount) {
877 ALOGE("%s: asked for %d, got %d\n", __func__, nBufferCount, req.count);
878 ret = VIDEO_ERROR_NOMEM;
879 goto EXIT;
880 }
Dima Zavin01fa64f2012-06-13 16:42:27 -0700881
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900882 pCtx->nInbufs = (int)req.count;
883
884 pCtx->pInbuf = malloc(sizeof(*pCtx->pInbuf) * pCtx->nInbufs);
885 if (pCtx->pInbuf == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700886 ALOGE("Failed to allocate input buffer context");
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900887 ret = VIDEO_ERROR_NOMEM;
888 goto EXIT;
889 }
890 memset(pCtx->pInbuf, 0, sizeof(*pCtx->pInbuf) * pCtx->nInbufs);
891
892 memset(&buf, 0, sizeof(buf));
893
894 if (pCtx->bShareInbuf == VIDEO_FALSE) {
895 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
896 buf.memory = V4L2_MEMORY_MMAP;
897 buf.m.planes = planes;
898 buf.length = VIDEO_DECODER_INBUF_PLANES;
899
900 for (i = 0; i < pCtx->nInbufs; i++) {
901 buf.index = i;
Jiho Chang38ef2572012-06-01 20:58:55 +0000902 if (exynos_v4l2_querybuf(pCtx->hDec, &buf) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900903 ret = VIDEO_ERROR_APIFAIL;
904 goto EXIT;
905 }
906
907 pVideoPlane = &pCtx->pInbuf[i].planes[0];
908
909 pVideoPlane->addr = mmap(NULL,
910 buf.m.planes[0].length, PROT_READ | PROT_WRITE,
911 MAP_SHARED, pCtx->hDec, buf.m.planes[0].m.mem_offset);
912
913 if (pVideoPlane->addr == MAP_FAILED) {
914 ret = VIDEO_ERROR_MAPFAIL;
915 goto EXIT;
916 }
917
918 pVideoPlane->allocSize = buf.m.planes[0].length;
919 pVideoPlane->dataSize = 0;
920
921 pCtx->pInbuf[i].pGeometry = &pCtx->inbufGeometry;
Jiho Chang38ef2572012-06-01 20:58:55 +0000922 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
923 pCtx->pInbuf[i].bRegistered = VIDEO_TRUE;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900924 }
925 }
926
927 return ret;
928
929EXIT:
Jiho Chang800a8d72012-04-26 13:25:31 -0700930 if ((pCtx != NULL) && (pCtx->pInbuf != NULL)) {
931 if (pCtx->bShareInbuf == VIDEO_FALSE) {
932 for (i = 0; i < pCtx->nInbufs; i++) {
933 pVideoPlane = &pCtx->pInbuf[i].planes[0];
934 if (pVideoPlane->addr == MAP_FAILED) {
935 pVideoPlane->addr = NULL;
936 break;
937 }
938
939 munmap(pVideoPlane->addr, pVideoPlane->allocSize);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900940 }
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900941 }
Jiho Chang800a8d72012-04-26 13:25:31 -0700942
943 free(pCtx->pInbuf);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900944 }
945
946 return ret;
947}
948
949/*
950 * [Decoder Buffer OPS] Setup (Output)
951 */
952static ExynosVideoErrorType MFC_Decoder_Setup_Outbuf(
953 void *pHandle,
954 unsigned int nBufferCount)
955{
Jiho Chang38ef2572012-06-01 20:58:55 +0000956 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
957 ExynosVideoPlane *pVideoPlane = NULL;
958 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900959
960 struct v4l2_requestbuffers req;
961 struct v4l2_buffer buf;
962 struct v4l2_plane planes[VIDEO_DECODER_OUTBUF_PLANES];
963 int i, j;
964
965 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -0700966 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900967 ret = VIDEO_ERROR_BADPARAM;
968 goto EXIT;
969 }
970
971 if (nBufferCount == 0) {
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +0900972 nBufferCount = MAX_OUTPUTBUFFER_COUNT;
973 ALOGV("%s: Change buffer count %d", __func__, nBufferCount);
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900974 }
975
Dima Zavin01fa64f2012-06-13 16:42:27 -0700976 ALOGV("%s: setting up outbufs (%d) shared=%s\n", __func__, nBufferCount,
977 pCtx->bShareOutbuf ? "true" : "false");
978
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900979 memset(&req, 0, sizeof(req));
980
981 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
982 req.count = nBufferCount;
983
984 if (pCtx->bShareOutbuf == VIDEO_TRUE)
SeungBeom Kim1f0d5e32012-07-03 15:45:57 +0900985 req.memory = pCtx->nMemoryType;
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900986 else
987 req.memory = V4L2_MEMORY_MMAP;
988
Jiho Chang38ef2572012-06-01 20:58:55 +0000989 if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +0900990 ret = VIDEO_ERROR_APIFAIL;
991 goto EXIT;
992 }
993
SeungBeom Kim30e79fb2012-07-03 18:31:30 +0900994 if (req.count != nBufferCount) {
995 ALOGE("%s: asked for %d, got %d\n", __func__, nBufferCount, req.count);
996 ret = VIDEO_ERROR_NOMEM;
997 goto EXIT;
998 }
999
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001000 pCtx->nOutbufs = req.count;
1001
1002 pCtx->pOutbuf = malloc(sizeof(*pCtx->pOutbuf) * pCtx->nOutbufs);
1003 if (pCtx->pOutbuf == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001004 ALOGE("Failed to allocate output buffer context");
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001005 ret = VIDEO_ERROR_NOMEM;
1006 goto EXIT;
1007 }
1008 memset(pCtx->pOutbuf, 0, sizeof(*pCtx->pOutbuf) * pCtx->nOutbufs);
1009
1010 memset(&buf, 0, sizeof(buf));
1011
1012 if (pCtx->bShareOutbuf == VIDEO_FALSE) {
1013 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1014 buf.memory = V4L2_MEMORY_MMAP;
1015 buf.m.planes = planes;
1016 buf.length = VIDEO_DECODER_OUTBUF_PLANES;
1017
1018 for (i = 0; i < pCtx->nOutbufs; i++) {
1019 buf.index = i;
Jiho Chang38ef2572012-06-01 20:58:55 +00001020 if (exynos_v4l2_querybuf(pCtx->hDec, &buf) != 0) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001021 ret = VIDEO_ERROR_APIFAIL;
1022 goto EXIT;
1023 }
1024
1025 for (j = 0; j < VIDEO_DECODER_OUTBUF_PLANES; j++) {
1026 pVideoPlane = &pCtx->pOutbuf[i].planes[j];
1027 pVideoPlane->addr = mmap(NULL,
1028 buf.m.planes[j].length, PROT_READ | PROT_WRITE,
1029 MAP_SHARED, pCtx->hDec, buf.m.planes[j].m.mem_offset);
1030
1031 if (pVideoPlane->addr == MAP_FAILED) {
1032 ret = VIDEO_ERROR_MAPFAIL;
1033 goto EXIT;
1034 }
1035
1036 pVideoPlane->allocSize = buf.m.planes[j].length;
1037 pVideoPlane->dataSize = 0;
1038 }
1039
1040 pCtx->pOutbuf[i].pGeometry = &pCtx->outbufGeometry;
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +09001041 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
1042 pCtx->pOutbuf[i].bSlotUsed = VIDEO_FALSE;
1043 pCtx->pOutbuf[i].nIndexUseCnt = 0;
1044 pCtx->pOutbuf[i].bRegistered = VIDEO_TRUE;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001045 }
1046 }
1047
1048 return ret;
1049
1050EXIT:
Jiho Chang800a8d72012-04-26 13:25:31 -07001051 if ((pCtx != NULL) && (pCtx->pOutbuf != NULL)) {
1052 if (pCtx->bShareOutbuf == VIDEO_FALSE) {
1053 for (i = 0; i < pCtx->nOutbufs; i++) {
1054 for (j = 0; j < VIDEO_DECODER_OUTBUF_PLANES; j++) {
1055 pVideoPlane = &pCtx->pOutbuf[i].planes[j];
1056 if (pVideoPlane->addr == MAP_FAILED) {
1057 pVideoPlane->addr = NULL;
1058 break;
1059 }
1060
1061 munmap(pVideoPlane->addr, pVideoPlane->allocSize);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001062 }
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001063 }
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001064 }
Jiho Chang800a8d72012-04-26 13:25:31 -07001065
1066 free(pCtx->pOutbuf);
SeungBeom Kimc01f2432013-08-02 08:33:37 +09001067 pCtx->pOutbuf = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001068 }
1069
1070 return ret;
1071}
1072
1073/*
1074 * [Decoder Buffer OPS] Run (Input)
1075 */
1076static ExynosVideoErrorType MFC_Decoder_Run_Inbuf(void *pHandle)
1077{
1078 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1079 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1080
1081 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001082 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001083 ret = VIDEO_ERROR_BADPARAM;
1084 goto EXIT;
1085 }
1086
1087 if (pCtx->bStreamonInbuf == VIDEO_FALSE) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001088 if (exynos_v4l2_streamon(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001089 ALOGE("%s: Failed to streamon for input buffer", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001090 ret = VIDEO_ERROR_APIFAIL;
1091 goto EXIT;
1092 }
1093 pCtx->bStreamonInbuf = VIDEO_TRUE;
1094 }
1095
1096EXIT:
1097 return ret;
1098}
1099
1100/*
1101 * [Decoder Buffer OPS] Run (Output)
1102 */
1103static ExynosVideoErrorType MFC_Decoder_Run_Outbuf(void *pHandle)
1104{
1105 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1106 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1107
1108 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001109 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001110 ret = VIDEO_ERROR_BADPARAM;
1111 goto EXIT;
1112 }
1113
1114 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001115 if (exynos_v4l2_streamon(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001116 ALOGE("%s: Failed to streamon for output buffer", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001117 ret = VIDEO_ERROR_APIFAIL;
1118 goto EXIT;
1119 }
1120 pCtx->bStreamonOutbuf = VIDEO_TRUE;
1121 }
1122
1123EXIT:
1124 return ret;
1125}
1126
1127/*
1128 * [Decoder Buffer OPS] Stop (Input)
1129 */
1130static ExynosVideoErrorType MFC_Decoder_Stop_Inbuf(void *pHandle)
1131{
1132 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1133 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
Jiho Chang38ef2572012-06-01 20:58:55 +00001134 int i = 0;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001135
1136 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001137 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001138 ret = VIDEO_ERROR_BADPARAM;
1139 goto EXIT;
1140 }
1141
1142 if (pCtx->bStreamonInbuf == VIDEO_TRUE) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001143 if (exynos_v4l2_streamoff(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001144 ALOGE("%s: Failed to streamoff for input buffer", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001145 ret = VIDEO_ERROR_APIFAIL;
1146 goto EXIT;
1147 }
1148 pCtx->bStreamonInbuf = VIDEO_FALSE;
1149 }
1150
Jiho Chang38ef2572012-06-01 20:58:55 +00001151 for (i = 0; i < pCtx->nInbufs; i++) {
1152 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
1153 }
1154
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001155EXIT:
1156 return ret;
1157}
1158
1159/*
1160 * [Decoder Buffer OPS] Stop (Output)
1161 */
1162static ExynosVideoErrorType MFC_Decoder_Stop_Outbuf(void *pHandle)
1163{
1164 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1165 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
Jiho Chang38ef2572012-06-01 20:58:55 +00001166 int i = 0;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001167
1168 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001169 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001170 ret = VIDEO_ERROR_BADPARAM;
1171 goto EXIT;
1172 }
1173
1174 if (pCtx->bStreamonOutbuf == VIDEO_TRUE) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001175 if (exynos_v4l2_streamoff(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001176 ALOGE("%s: Failed to streamoff for output buffer", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001177 ret = VIDEO_ERROR_APIFAIL;
1178 goto EXIT;
1179 }
1180 pCtx->bStreamonOutbuf = VIDEO_FALSE;
1181 }
1182
Jiho Chang38ef2572012-06-01 20:58:55 +00001183 for (i = 0; i < pCtx->nOutbufs; i++) {
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +09001184 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
1185 pCtx->pOutbuf[i].bSlotUsed = VIDEO_FALSE;
1186 pCtx->pOutbuf[i].nIndexUseCnt = 0;
Jiho Chang38ef2572012-06-01 20:58:55 +00001187 }
1188
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001189EXIT:
1190 return ret;
1191}
1192
1193/*
1194 * [Decoder Buffer OPS] Wait (Input)
1195 */
1196static ExynosVideoErrorType MFC_Decoder_Wait_Inbuf(void *pHandle)
1197{
1198 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1199 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1200
1201 struct pollfd poll_events;
1202 int poll_state;
1203
1204 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001205 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001206 ret = VIDEO_ERROR_BADPARAM;
1207 goto EXIT;
1208 }
1209
1210 poll_events.fd = pCtx->hDec;
1211 poll_events.events = POLLOUT | POLLERR;
1212 poll_events.revents = 0;
1213
1214 do {
1215 poll_state = poll((struct pollfd*)&poll_events, 1, VIDEO_DECODER_POLL_TIMEOUT);
1216 if (poll_state > 0) {
1217 if (poll_events.revents & POLLOUT) {
1218 break;
1219 } else {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001220 ALOGE("%s: Poll return error", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001221 ret = VIDEO_ERROR_POLL;
1222 break;
1223 }
1224 } else if (poll_state < 0) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001225 ALOGE("%s: Poll state error", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001226 ret = VIDEO_ERROR_POLL;
1227 break;
1228 }
1229 } while (poll_state == 0);
1230
1231EXIT:
1232 return ret;
1233}
1234
Jiho Chang38ef2572012-06-01 20:58:55 +00001235static ExynosVideoErrorType MFC_Decoder_Register_Inbuf(
Dima Zavin01fa64f2012-06-13 16:42:27 -07001236 void *pHandle,
1237 ExynosVideoPlane *planes,
1238 int nPlanes)
Jiho Chang38ef2572012-06-01 20:58:55 +00001239{
1240 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1241 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001242 int nIndex, plane;
Jiho Chang38ef2572012-06-01 20:58:55 +00001243
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001244 if ((pCtx == NULL) || (planes == NULL) || (nPlanes != VIDEO_DECODER_INBUF_PLANES)) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001245 ALOGE("%s: params must be supplied", __func__);
1246 ret = VIDEO_ERROR_BADPARAM;
1247 goto EXIT;
1248 }
1249
1250 for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
1251 if (pCtx->pInbuf[nIndex].bRegistered == VIDEO_FALSE) {
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001252 for (plane = 0; plane < nPlanes; plane++) {
1253 pCtx->pInbuf[nIndex].planes[plane].addr = planes[plane].addr;
1254 pCtx->pInbuf[nIndex].planes[plane].allocSize = planes[plane].allocSize;
1255 pCtx->pInbuf[nIndex].planes[plane].fd = planes[plane].fd;
1256 ALOGV("%s: registered buf %d (addr=%p alloc_sz=%ld fd=%d)\n", __func__, nIndex,
1257 planes[plane].addr, planes[plane].allocSize, planes[plane].fd);
1258 }
Jiho Chang38ef2572012-06-01 20:58:55 +00001259 pCtx->pInbuf[nIndex].bRegistered = VIDEO_TRUE;
1260 break;
1261 }
1262 }
1263
1264 if (nIndex == pCtx->nInbufs) {
1265 ALOGE("%s: can not find non-registered input buffer", __func__);
1266 ret = VIDEO_ERROR_NOBUFFERS;
1267 }
1268
1269EXIT:
1270 return ret;
1271}
1272
1273static ExynosVideoErrorType MFC_Decoder_Register_Outbuf(
Dima Zavin01fa64f2012-06-13 16:42:27 -07001274 void *pHandle,
1275 ExynosVideoPlane *planes,
1276 int nPlanes)
Jiho Chang38ef2572012-06-01 20:58:55 +00001277{
1278 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1279 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001280 int nIndex, plane;
Jiho Chang38ef2572012-06-01 20:58:55 +00001281
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001282 if ((pCtx == NULL) || (planes == NULL) || (nPlanes != VIDEO_DECODER_OUTBUF_PLANES)) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001283 ALOGE("%s: params must be supplied", __func__);
1284 ret = VIDEO_ERROR_BADPARAM;
1285 goto EXIT;
1286 }
1287
1288 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
1289 if (pCtx->pOutbuf[nIndex].bRegistered == VIDEO_FALSE) {
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001290 for (plane = 0; plane < nPlanes; plane++) {
Dima Zavin01fa64f2012-06-13 16:42:27 -07001291 pCtx->pOutbuf[nIndex].planes[plane].addr = planes[plane].addr;
1292 pCtx->pOutbuf[nIndex].planes[plane].allocSize = planes[plane].allocSize;
1293 pCtx->pOutbuf[nIndex].planes[plane].fd = planes[plane].fd;
1294 }
Jiho Chang38ef2572012-06-01 20:58:55 +00001295 pCtx->pOutbuf[nIndex].bRegistered = VIDEO_TRUE;
Dima Zavin01fa64f2012-06-13 16:42:27 -07001296 ALOGV("%s: registered buf %d 0:(addr=%p alloc_sz=%d fd=%d) 1:(addr=%p alloc_sz=%d fd=%d)\n",
1297 __func__, nIndex, planes[0].addr, planes[0].allocSize, planes[0].fd,
1298 planes[1].addr, planes[1].allocSize, planes[1].fd);
Jiho Chang38ef2572012-06-01 20:58:55 +00001299 break;
1300 }
1301 }
1302
1303 if (nIndex == pCtx->nOutbufs) {
1304 ALOGE("%s: can not find non-registered output buffer", __func__);
1305 ret = VIDEO_ERROR_NOBUFFERS;
1306 }
1307
1308EXIT:
1309 return ret;
1310}
1311
1312static ExynosVideoErrorType MFC_Decoder_Clear_RegisteredBuffer_Inbuf(void *pHandle)
1313{
1314 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1315 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1316 int nIndex;
1317
1318 if (pCtx == NULL) {
1319 ALOGE("%s: Video context info must be supplied", __func__);
1320 ret = VIDEO_ERROR_BADPARAM;
1321 goto EXIT;
1322 }
1323
1324 for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
1325 pCtx->pInbuf[nIndex].planes[0].addr = NULL;
1326 pCtx->pInbuf[nIndex].bRegistered = VIDEO_FALSE;
1327 }
1328
1329EXIT:
1330 return ret;
1331}
1332
1333static ExynosVideoErrorType MFC_Decoder_Clear_RegisteredBuffer_Outbuf(void *pHandle)
1334{
1335 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1336 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1337 int nIndex;
1338
1339 if (pCtx == NULL) {
1340 ALOGE("%s: Video context info must be supplied", __func__);
1341 ret = VIDEO_ERROR_BADPARAM;
1342 goto EXIT;
1343 }
1344
1345 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
1346 pCtx->pOutbuf[nIndex].planes[0].addr = NULL;
1347 pCtx->pOutbuf[nIndex].bRegistered = VIDEO_FALSE;
1348 }
1349
1350EXIT:
1351 return ret;
1352}
1353
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001354/*
1355 * [Decoder Buffer OPS] Find (Input)
1356 */
1357static int MFC_Decoder_Find_Inbuf(
1358 void *pHandle,
1359 unsigned char *pBuffer)
1360{
1361 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1362 int nIndex = -1;
1363
1364 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001365 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001366 goto EXIT;
1367 }
1368
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001369 for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
1370 if (pCtx->pInbuf[nIndex].bQueued == VIDEO_FALSE) {
1371 if ((pBuffer == NULL) ||
1372 (pCtx->pInbuf[nIndex].planes[0].addr == pBuffer))
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001373 break;
1374 }
1375 }
1376
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001377 if (nIndex == pCtx->nInbufs)
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001378 nIndex = -1;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001379
1380EXIT:
1381 return nIndex;
1382}
1383
1384/*
1385 * [Decoder Buffer OPS] Find (Outnput)
1386 */
1387static int MFC_Decoder_Find_Outbuf(
1388 void *pHandle,
1389 unsigned char *pBuffer)
1390{
1391 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1392 int nIndex = -1;
1393
1394 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001395 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001396 goto EXIT;
1397 }
1398
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001399 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
1400 if (pCtx->pOutbuf[nIndex].bQueued == VIDEO_FALSE) {
1401 if ((pBuffer == NULL) ||
1402 (pCtx->pOutbuf[nIndex].planes[0].addr == pBuffer))
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001403 break;
1404 }
1405 }
1406
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001407 if (nIndex == pCtx->nOutbufs)
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001408 nIndex = -1;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001409
1410EXIT:
1411 return nIndex;
1412}
1413
1414/*
1415 * [Decoder Buffer OPS] Enqueue (Input)
1416 */
1417static ExynosVideoErrorType MFC_Decoder_Enqueue_Inbuf(
1418 void *pHandle,
1419 unsigned char *pBuffer[],
1420 unsigned int dataSize[],
1421 int nPlanes,
1422 void *pPrivate)
1423{
1424 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1425 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
Jiho Chang38ef2572012-06-01 20:58:55 +00001426 pthread_mutex_t *pMutex = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001427
1428 struct v4l2_plane planes[VIDEO_DECODER_INBUF_PLANES];
1429 struct v4l2_buffer buf;
1430 int index, i;
1431
1432 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001433 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001434 ret = VIDEO_ERROR_BADPARAM;
1435 goto EXIT;
1436 }
1437
Jiho Chang800a8d72012-04-26 13:25:31 -07001438 if (VIDEO_DECODER_INBUF_PLANES < nPlanes) {
1439 ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__,
1440 VIDEO_DECODER_INBUF_PLANES, nPlanes);
1441 ret = VIDEO_ERROR_BADPARAM;
1442 goto EXIT;
1443 }
1444
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001445 memset(&buf, 0, sizeof(buf));
1446
1447 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1448 buf.m.planes = planes;
1449 buf.length = VIDEO_DECODER_INBUF_PLANES;
1450
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001451 pMutex = (pthread_mutex_t*)pCtx->pInMutex;
1452 pthread_mutex_lock(pMutex);
Jiho Chang38ef2572012-06-01 20:58:55 +00001453 index = MFC_Decoder_Find_Inbuf(pCtx, pBuffer[0]);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001454 if (index == -1) {
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001455 pthread_mutex_unlock(pMutex);
1456 ALOGE("%s: Failed to get index", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001457 ret = VIDEO_ERROR_NOBUFFERS;
1458 goto EXIT;
1459 }
1460
1461 buf.index = index;
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001462 pCtx->pInbuf[buf.index].bQueued = VIDEO_TRUE;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001463
1464 if (pCtx->bShareInbuf == VIDEO_TRUE) {
SeungBeom Kim1f0d5e32012-07-03 15:45:57 +09001465 buf.memory = pCtx->nMemoryType;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001466 for (i = 0; i < nPlanes; i++) {
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001467 /* V4L2_MEMORY_USERPTR */
1468 buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i];
1469 /* V4L2_MEMORY_DMABUF */
Dima Zavin01fa64f2012-06-13 16:42:27 -07001470 buf.m.planes[i].m.fd = pCtx->pInbuf[index].planes[i].fd;
Jiho Chang38ef2572012-06-01 20:58:55 +00001471 buf.m.planes[i].length = pCtx->pInbuf[index].planes[i].allocSize;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001472 buf.m.planes[i].bytesused = dataSize[i];
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001473 ALOGV("%s: shared inbuf(%d) plane(%d) addr=%p fd=%d len=%d used=%d\n", __func__,
Dima Zavin01fa64f2012-06-13 16:42:27 -07001474 index, i,
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001475 buf.m.planes[i].m.userptr,
Dima Zavin01fa64f2012-06-13 16:42:27 -07001476 buf.m.planes[i].m.fd,
1477 buf.m.planes[i].length,
1478 buf.m.planes[i].bytesused);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001479 }
1480 } else {
1481 buf.memory = V4L2_MEMORY_MMAP;
1482 for (i = 0; i < nPlanes; i++)
1483 buf.m.planes[i].bytesused = dataSize[i];
1484 }
1485
SeungBeom Kim81a947b2013-01-16 15:23:19 +09001486 if ((((OMX_BUFFERHEADERTYPE *)pPrivate)->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) {
1487 buf.flags |= V4L2_BUF_FLAG_LAST_FRAME;
SeungBeom Kimf8d511a2013-08-02 10:05:22 +09001488 ALOGV("%s: OMX_BUFFERFLAG_EOS => LAST_FRAME: 0x%x", __func__,
SeungBeom Kim81a947b2013-01-16 15:23:19 +09001489 !!(buf.flags & V4L2_BUF_FLAG_LAST_FRAME));
1490 }
1491
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +09001492 pCtx->pInbuf[buf.index].pPrivate = pPrivate;
1493
1494 pthread_mutex_unlock(pMutex);
1495
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001496 if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) {
1497 ALOGE("%s: Failed to enqueue input buffer", __func__);
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +09001498 pthread_mutex_lock(pMutex);
1499 pCtx->pInbuf[buf.index].pPrivate = NULL;
1500 pCtx->pInbuf[buf.index].bQueued = VIDEO_FALSE;
1501 pthread_mutex_unlock(pMutex);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001502 ret = VIDEO_ERROR_APIFAIL;
1503 goto EXIT;
1504 }
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001505
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001506EXIT:
1507 return ret;
1508}
1509
1510/*
1511 * [Decoder Buffer OPS] Enqueue (Output)
1512 */
1513static ExynosVideoErrorType MFC_Decoder_Enqueue_Outbuf(
1514 void *pHandle,
1515 unsigned char *pBuffer[],
1516 unsigned int dataSize[],
1517 int nPlanes,
1518 void *pPrivate)
1519{
1520 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1521 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
Jiho Chang38ef2572012-06-01 20:58:55 +00001522 pthread_mutex_t *pMutex = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001523
1524 struct v4l2_plane planes[VIDEO_DECODER_OUTBUF_PLANES];
1525 struct v4l2_buffer buf;
1526 int i, index;
1527
1528 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001529 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001530 ret = VIDEO_ERROR_BADPARAM;
1531 goto EXIT;
1532 }
1533
Jiho Chang38ef2572012-06-01 20:58:55 +00001534 if (VIDEO_DECODER_OUTBUF_PLANES < nPlanes) {
1535 ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__,
1536 VIDEO_DECODER_OUTBUF_PLANES, nPlanes);
1537 ret = VIDEO_ERROR_BADPARAM;
1538 goto EXIT;
1539 }
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001540
Jiho Chang38ef2572012-06-01 20:58:55 +00001541 memset(&buf, 0, sizeof(buf));
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001542 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1543 buf.m.planes = planes;
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001544 buf.length = VIDEO_DECODER_OUTBUF_PLANES;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001545
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001546 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
1547 pthread_mutex_lock(pMutex);
Jiho Chang38ef2572012-06-01 20:58:55 +00001548 index = MFC_Decoder_Find_Outbuf(pCtx, pBuffer[0]);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001549 if (index == -1) {
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001550 pthread_mutex_unlock(pMutex);
1551 ALOGE("%s: Failed to get index", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001552 ret = VIDEO_ERROR_NOBUFFERS;
1553 goto EXIT;
1554 }
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001555 buf.index = index;
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001556 pCtx->pOutbuf[buf.index].bQueued = VIDEO_TRUE;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001557
1558 if (pCtx->bShareOutbuf == VIDEO_TRUE) {
SeungBeom Kim1f0d5e32012-07-03 15:45:57 +09001559 buf.memory = pCtx->nMemoryType;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001560 for (i = 0; i < nPlanes; i++) {
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001561 /* V4L2_MEMORY_USERPTR */
1562 buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i];
1563 /* V4L2_MEMORY_DMABUF */
Dima Zavin01fa64f2012-06-13 16:42:27 -07001564 buf.m.planes[i].m.fd = pCtx->pOutbuf[index].planes[i].fd;
Jiho Chang38ef2572012-06-01 20:58:55 +00001565 buf.m.planes[i].length = pCtx->pOutbuf[index].planes[i].allocSize;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001566 buf.m.planes[i].bytesused = dataSize[i];
Dima Zavin01fa64f2012-06-13 16:42:27 -07001567 ALOGV("%s: shared outbuf(%d) plane=%d addr=%p fd=%d len=%d used=%d\n", __func__,
1568 index, i,
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001569 buf.m.planes[i].m.userptr,
Dima Zavin01fa64f2012-06-13 16:42:27 -07001570 buf.m.planes[i].m.fd,
1571 buf.m.planes[i].length,
1572 buf.m.planes[i].bytesused);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001573 }
1574 } else {
Dima Zavin01fa64f2012-06-13 16:42:27 -07001575 ALOGV("%s: non-shared outbuf(%d)\n", __func__, index);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001576 buf.memory = V4L2_MEMORY_MMAP;
1577 }
1578
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +09001579 pCtx->pOutbuf[buf.index].pPrivate = pPrivate;
1580
1581 pthread_mutex_unlock(pMutex);
1582
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001583 if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) {
1584 ALOGE("%s: Failed to enqueue output buffer", __func__);
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +09001585 pthread_mutex_lock(pMutex);
1586 pCtx->pOutbuf[buf.index].pPrivate = NULL;
1587 pCtx->pOutbuf[buf.index].bQueued = VIDEO_FALSE;
1588 pthread_mutex_unlock(pMutex);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001589 ret = VIDEO_ERROR_APIFAIL;
1590 goto EXIT;
1591 }
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001592
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001593EXIT:
1594 return ret;
1595}
1596
1597/*
1598 * [Decoder Buffer OPS] Dequeue (Input)
1599 */
1600static ExynosVideoBuffer *MFC_Decoder_Dequeue_Inbuf(void *pHandle)
1601{
Jiho Chang38ef2572012-06-01 20:58:55 +00001602 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1603 ExynosVideoBuffer *pInbuf = NULL;
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +09001604 pthread_mutex_t *pMutex = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001605
1606 struct v4l2_buffer buf;
1607
1608 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001609 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001610 goto EXIT;
1611 }
1612
1613 if (pCtx->bStreamonInbuf == VIDEO_FALSE) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001614 pInbuf = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001615 goto EXIT;
1616 }
1617
1618 memset(&buf, 0, sizeof(buf));
1619
1620 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1621
1622 if (pCtx->bShareInbuf == VIDEO_TRUE)
SeungBeom Kim1f0d5e32012-07-03 15:45:57 +09001623 buf.memory = pCtx->nMemoryType;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001624 else
1625 buf.memory = V4L2_MEMORY_MMAP;
1626
Jiho Chang38ef2572012-06-01 20:58:55 +00001627 if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) {
1628 pInbuf = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001629 goto EXIT;
1630 }
1631
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +09001632 pMutex = (pthread_mutex_t*)pCtx->pInMutex;
1633 pthread_mutex_lock(pMutex);
1634
Jiho Chang38ef2572012-06-01 20:58:55 +00001635 pInbuf = &pCtx->pInbuf[buf.index];
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09001636 pCtx->pInbuf[buf.index].bQueued = VIDEO_FALSE;
Jiho Chang38ef2572012-06-01 20:58:55 +00001637
1638 if (pCtx->bStreamonInbuf == VIDEO_FALSE)
1639 pInbuf = NULL;
1640
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +09001641 pthread_mutex_unlock(pMutex);
1642
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001643EXIT:
Jiho Chang38ef2572012-06-01 20:58:55 +00001644 return pInbuf;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001645}
1646
1647/*
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001648 * [Decoder Buffer OPS] Dequeue (Output)
1649 */
1650static ExynosVideoBuffer *MFC_Decoder_Dequeue_Outbuf(void *pHandle)
1651{
1652 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1653 ExynosVideoBuffer *pOutbuf = NULL;
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +09001654 pthread_mutex_t *pMutex = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001655
1656 struct v4l2_buffer buf;
SeungBeom Kimc01f2432013-08-02 08:33:37 +09001657 int value, state;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001658
1659 if (pCtx == NULL) {
Dima Zavin4a7b2d32012-04-02 23:43:51 -07001660 ALOGE("%s: Video context info must be supplied", __func__);
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001661 goto EXIT;
1662 }
1663
1664 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
Jiho Chang38ef2572012-06-01 20:58:55 +00001665 pOutbuf = NULL;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001666 goto EXIT;
1667 }
1668
1669 memset(&buf, 0, sizeof(buf));
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001670 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1671
1672 if (pCtx->bShareOutbuf == VIDEO_TRUE)
SeungBeom Kim1f0d5e32012-07-03 15:45:57 +09001673 buf.memory = pCtx->nMemoryType;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001674 else
1675 buf.memory = V4L2_MEMORY_MMAP;
1676
1677 /* HACK: pOutbuf return -1 means DECODING_ONLY for almost cases */
Jiho Chang38ef2572012-06-01 20:58:55 +00001678 if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) {
1679 pOutbuf = NULL;
1680 goto EXIT;
1681 }
1682
1683 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001684 pOutbuf = NULL;
1685 goto EXIT;
1686 }
1687
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +09001688 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
1689 pthread_mutex_lock(pMutex);
1690
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001691 pOutbuf = &pCtx->pOutbuf[buf.index];
1692
1693 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS, &value);
1694
1695 switch (value) {
1696 case 0:
1697 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_ONLY;
1698 break;
1699 case 1:
1700 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_DECODING;
1701 break;
1702 case 2:
1703 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_ONLY;
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +09001704 break;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001705 case 3:
SeungBeom Kimc01f2432013-08-02 08:33:37 +09001706 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE, &state);
1707 if (state == 1) /* Resolution is changed */
1708 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_CHANGE_RESOL;
1709 else /* Decoding is finished */
1710 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_FINISHED;
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001711 break;
1712 default:
1713 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_UNKNOWN;
1714 break;
1715 }
1716
1717 switch (buf.flags & (0x7 << 3)) {
1718 case V4L2_BUF_FLAG_KEYFRAME:
1719 pOutbuf->frameType = VIDEO_FRAME_I;
1720 break;
1721 case V4L2_BUF_FLAG_PFRAME:
1722 pOutbuf->frameType = VIDEO_FRAME_P;
1723 break;
1724 case V4L2_BUF_FLAG_BFRAME:
1725 pOutbuf->frameType = VIDEO_FRAME_B;
1726 break;
1727 default:
1728 pOutbuf->frameType = VIDEO_FRAME_OTHERS;
1729 break;
1730 };
1731
1732 pOutbuf->bQueued = VIDEO_FALSE;
1733
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +09001734 pthread_mutex_unlock(pMutex);
1735
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001736EXIT:
1737 return pOutbuf;
1738}
1739
Jiho Chang38ef2572012-06-01 20:58:55 +00001740static ExynosVideoErrorType MFC_Decoder_Clear_Queued_Inbuf(void *pHandle)
1741{
1742 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1743 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1744 int i;
1745
1746 if (pCtx == NULL) {
1747 ALOGE("%s: Video context info must be supplied", __func__);
1748 ret = VIDEO_ERROR_BADPARAM;
1749 goto EXIT;
1750 }
1751
1752 for (i = 0; i < pCtx->nInbufs; i++) {
1753 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
1754 }
1755
1756EXIT:
1757 return ret;
1758}
1759
1760static ExynosVideoErrorType MFC_Decoder_Clear_Queued_Outbuf(void *pHandle)
1761{
1762 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1763 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1764 int i;
1765
1766 if (pCtx == NULL) {
1767 ALOGE("%s: Video context info must be supplied", __func__);
1768 ret = VIDEO_ERROR_BADPARAM;
1769 goto EXIT;
1770 }
1771
1772 for (i = 0; i < pCtx->nOutbufs; i++) {
1773 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
1774 }
1775
1776EXIT:
1777 return ret;
1778}
1779
Jiho Chang20d3e6e2012-03-24 03:43:08 +09001780/*
SeungBeom Kimc01f2432013-08-02 08:33:37 +09001781 * [Decoder Buffer OPS] Cleanup Buffer (Input)
1782 */
1783static ExynosVideoErrorType MFC_Decoder_Cleanup_Buffer_Inbuf(void *pHandle)
1784{
1785 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1786 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1787
1788 struct v4l2_requestbuffers req;
1789 int nBufferCount = 0;
1790
1791 if (pCtx == NULL) {
1792 ALOGE("%s: Video context info must be supplied", __func__);
1793 ret = VIDEO_ERROR_BADPARAM;
1794 goto EXIT;
1795 }
1796
1797 nBufferCount = 0; /* for clean-up */
1798
1799 memset(&req, 0, sizeof(req));
1800
1801 req.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1802 req.count = nBufferCount;
1803
1804 if (pCtx->bShareInbuf == VIDEO_TRUE)
1805 req.memory = pCtx->nMemoryType;
1806 else
1807 req.memory = V4L2_MEMORY_MMAP;
1808
1809 if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) {
1810 ret = VIDEO_ERROR_APIFAIL;
1811 goto EXIT;
1812 }
1813
1814 pCtx->nInbufs = (int)req.count;
1815
1816 if (pCtx->pInbuf != NULL) {
1817 free(pCtx->pInbuf);
1818 pCtx->pInbuf = NULL;
1819 }
1820
1821EXIT:
1822 return ret;
1823}
1824
1825/*
1826 * [Decoder Buffer OPS] Cleanup Buffer (Output)
1827 */
1828static ExynosVideoErrorType MFC_Decoder_Cleanup_Buffer_Outbuf(void *pHandle)
1829{
1830 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1831 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1832
1833 struct v4l2_requestbuffers req;
1834 int nBufferCount = 0;
1835
1836 if (pCtx == NULL) {
1837 ALOGE("%s: Video context info must be supplied", __func__);
1838 ret = VIDEO_ERROR_BADPARAM;
1839 goto EXIT;
1840 }
1841
1842 nBufferCount = 0; /* for clean-up */
1843
1844 memset(&req, 0, sizeof(req));
1845
1846 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1847 req.count = nBufferCount;
1848
1849 if (pCtx->bShareOutbuf == VIDEO_TRUE)
1850 req.memory = pCtx->nMemoryType;
1851 else
1852 req.memory = V4L2_MEMORY_MMAP;
1853
1854 if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) {
1855 ret = VIDEO_ERROR_APIFAIL;
1856 goto EXIT;
1857 }
1858
1859 pCtx->nOutbufs = (int)req.count;
1860
1861 if (pCtx->pOutbuf != NULL) {
1862 free(pCtx->pOutbuf);
1863 pCtx->pOutbuf = NULL;
1864 }
1865
1866EXIT:
1867 return ret;
1868}
1869
1870/*
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +09001871 * [Decoder Buffer OPS] FindIndex (Output)
1872 */
1873static int MFC_Decoder_FindEmpty_Outbuf(void *pHandle)
1874{
1875 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1876 int nIndex = -1;
1877
1878 if (pCtx == NULL) {
1879 ALOGE("%s: Video context info must be supplied", __func__);
1880 goto EXIT;
1881 }
1882
1883 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
1884 if ((pCtx->pOutbuf[nIndex].bQueued == VIDEO_FALSE) &&
1885 (pCtx->pOutbuf[nIndex].bSlotUsed == VIDEO_FALSE))
1886 break;
1887 }
1888
1889 if (nIndex == pCtx->nOutbufs)
1890 nIndex = -1;
1891
1892EXIT:
1893 return nIndex;
1894}
1895
1896/*
1897 * [Decoder Buffer OPS] BufferIndexFree (Output)
1898 */
1899void MFC_Decoder_BufferIndexFree_Outbuf(void *pHandle, PrivateDataShareBuffer *pPDSB, int index)
1900{
1901 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1902 int i, j;
1903
1904 ALOGV("De-queue buf.index:%d", index);
1905 ALOGV("pOutbuf fd:%d", pCtx->pOutbuf[index].planes[0].fd);
1906
1907 if (pCtx->pOutbuf[index].nIndexUseCnt == 0) {
1908 pCtx->pOutbuf[index].bSlotUsed = VIDEO_FALSE;
1909 }
1910
1911 for (i = 0; pPDSB->dpbFD[i].fd > -1; i++) {
1912 ALOGV("pPDSB->dpbFD[%d].fd:%d", i, pPDSB->dpbFD[i].fd);
1913 for (j = 0; pCtx->nOutbufs > j; j++)
1914 if (pPDSB->dpbFD[i].fd == pCtx->pOutbuf[j].planes[0].fd) {
1915 if (pCtx->pOutbuf[j].bQueued == VIDEO_FALSE) {
1916 if (pCtx->pOutbuf[j].nIndexUseCnt > 0)
1917 pCtx->pOutbuf[j].nIndexUseCnt--;
1918 } else if(pCtx->pOutbuf[j].bQueued == VIDEO_TRUE) {
1919 if (pCtx->pOutbuf[j].nIndexUseCnt > 1) {
1920 /* The buffer being used as the reference buffer came again. */
1921 pCtx->pOutbuf[j].nIndexUseCnt--;
1922 } else {
1923 /* Reference DPB buffer is internally reused. */
1924 }
1925 }
1926 ALOGV("dec FD:%d, pCtx->pOutbuf[%d].nIndexUseCnt:%d", pPDSB->dpbFD[i].fd, j, pCtx->pOutbuf[j].nIndexUseCnt);
1927 if ((pCtx->pOutbuf[j].nIndexUseCnt == 0) &&
1928 (pCtx->pOutbuf[j].bQueued == VIDEO_FALSE)) {
1929 pCtx->pOutbuf[j].bSlotUsed = VIDEO_FALSE;
1930 }
1931 }
1932 }
1933 memset((char *)pPDSB, -1, sizeof(PrivateDataShareBuffer));
1934
1935 return;
1936}
1937
1938/*
1939 * [Decoder Buffer OPS] ExtensionEnqueue (Output)
1940 */
1941static ExynosVideoErrorType MFC_Decoder_ExtensionEnqueue_Outbuf(
1942 void *pHandle,
1943 unsigned char *pBuffer[],
1944 unsigned int *pFd[],
1945 unsigned int allocLen[],
1946 unsigned int dataSize[],
1947 int nPlanes,
1948 void *pPrivate)
1949{
1950 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1951 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1952 pthread_mutex_t *pMutex = NULL;
1953
1954 struct v4l2_plane planes[VIDEO_DECODER_OUTBUF_PLANES];
1955 struct v4l2_buffer buf;
SeungBeom Kimc01f2432013-08-02 08:33:37 +09001956 int state, index, i;
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +09001957
1958 if (pCtx == NULL) {
1959 ALOGE("%s: Video context info must be supplied", __func__);
1960 ret = VIDEO_ERROR_BADPARAM;
1961 goto EXIT;
1962 }
1963
1964 if (VIDEO_DECODER_OUTBUF_PLANES < nPlanes) {
1965 ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__,
1966 VIDEO_DECODER_OUTBUF_PLANES, nPlanes);
1967 ret = VIDEO_ERROR_BADPARAM;
1968 goto EXIT;
1969 }
1970
1971 memset(&buf, 0, sizeof(buf));
1972 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1973 buf.m.planes = planes;
1974 buf.length = VIDEO_DECODER_OUTBUF_PLANES;
1975
1976 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
1977 pthread_mutex_lock(pMutex);
1978
1979 index = MFC_Decoder_Find_Outbuf(pCtx, pBuffer[0]);
1980 if (index == -1) {
1981 ALOGV("%s: Failed to find index", __func__);
1982 index = MFC_Decoder_FindEmpty_Outbuf(pCtx);
1983 if (index == -1) {
1984 pthread_mutex_unlock(pMutex);
1985 ALOGE("%s: Failed to get index", __func__);
1986 ret = VIDEO_ERROR_NOBUFFERS;
1987 goto EXIT;
1988 }
1989 }
1990
1991 buf.index = index;
1992 ALOGV("En-queue index:%d pCtx->pOutbuf[buf.index].bQueued:%d, pFd[0]:%d",
1993 index, pCtx->pOutbuf[buf.index].bQueued, pFd[0]);
1994 pCtx->pOutbuf[buf.index].bQueued = VIDEO_TRUE;
1995 pCtx->pOutbuf[buf.index].bSlotUsed = VIDEO_TRUE;
1996
1997 buf.memory = pCtx->nMemoryType;
1998 for (i = 0; i < nPlanes; i++) {
1999 /* V4L2_MEMORY_USERPTR */
2000 buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i];
2001 /* V4L2_MEMORY_DMABUF */
2002 buf.m.planes[i].m.fd = pFd[i];
2003 buf.m.planes[i].length = allocLen[i];
2004 buf.m.planes[i].bytesused = dataSize[i];
2005
2006 /* Temporary storage for Dequeue */
2007 pCtx->pOutbuf[buf.index].planes[i].addr = (unsigned long)pBuffer[i];
2008 pCtx->pOutbuf[buf.index].planes[i].fd = (unsigned int)pFd[i];
2009 pCtx->pOutbuf[buf.index].planes[i].allocSize = allocLen[i];
2010
2011 ALOGV("%s: shared outbuf(%d) plane=%d addr=0x%x fd=%d len=%d used=%d\n",
2012 __func__, index, i,
2013 (void*)buf.m.planes[i].m.userptr, buf.m.planes[i].m.fd,
2014 buf.m.planes[i].length, buf.m.planes[i].bytesused);
2015 }
2016
2017 pCtx->pOutbuf[buf.index].pPrivate = pPrivate;
2018 pCtx->pOutbuf[buf.index].nIndexUseCnt++;
2019
2020 pthread_mutex_unlock(pMutex);
2021
2022 if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) {
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +09002023 pthread_mutex_lock(pMutex);
2024 pCtx->pOutbuf[buf.index].nIndexUseCnt--;
2025 pCtx->pOutbuf[buf.index].pPrivate = NULL;
2026 pCtx->pOutbuf[buf.index].bQueued = VIDEO_FALSE;
2027 if (pCtx->pOutbuf[buf.index].nIndexUseCnt == 0)
2028 pCtx->pOutbuf[buf.index].bSlotUsed = VIDEO_FALSE;
SeungBeom Kimc01f2432013-08-02 08:33:37 +09002029 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE, &state);
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +09002030 pthread_mutex_unlock(pMutex);
SeungBeom Kimc01f2432013-08-02 08:33:37 +09002031
2032 if (state == 1) {
2033 /* The case of Resolution is changed */
2034 ret = VIDEO_ERROR_WRONGBUFFERSIZE;
2035 } else {
2036 ALOGE("%s: Failed to enqueue output buffer", __func__);
2037 ret = VIDEO_ERROR_APIFAIL;
2038 }
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +09002039 goto EXIT;
2040 }
2041
2042EXIT:
2043 return ret;
2044}
2045
2046/*
2047 * [Decoder Buffer OPS] ExtensionDequeue (Output)
2048 */
2049static ExynosVideoErrorType MFC_Decoder_ExtensionDequeue_Outbuf(
2050 void *pHandle,
2051 ExynosVideoBuffer *pVideoBuffer)
2052{
2053 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
2054 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
2055 pthread_mutex_t *pMutex = NULL;
2056 ExynosVideoBuffer *pOutbuf = NULL;
2057 PrivateDataShareBuffer *pPDSB = NULL;
2058 struct v4l2_buffer buf;
SeungBeom Kimc01f2432013-08-02 08:33:37 +09002059 int value, state, i, j;
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +09002060
2061 if (pCtx == NULL) {
2062 ALOGE("%s: Video context info must be supplied", __func__);
2063 ret = VIDEO_ERROR_BADPARAM;
2064 goto EXIT;
2065 }
2066
2067 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
2068 pOutbuf = NULL;
2069 ret = VIDEO_ERROR_APIFAIL;
2070 goto EXIT;
2071 }
2072
2073 memset(&buf, 0, sizeof(buf));
2074 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2075
2076 if (pCtx->bShareOutbuf == VIDEO_TRUE)
2077 buf.memory = pCtx->nMemoryType;
2078 else
2079 buf.memory = V4L2_MEMORY_MMAP;
2080
2081 /* HACK: pOutbuf return -1 means DECODING_ONLY for almost cases */
2082 if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) {
2083 pOutbuf = NULL;
2084 ret = VIDEO_ERROR_APIFAIL;
2085 goto EXIT;
2086 }
2087
2088 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
2089 pthread_mutex_lock(pMutex);
2090
2091 pOutbuf = &pCtx->pOutbuf[buf.index];
2092 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS, &value);
2093
2094 switch (value) {
2095 case 0:
2096 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_ONLY;
2097 break;
2098 case 1:
2099 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_DECODING;
2100 break;
2101 case 2:
2102 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_ONLY;
2103 break;
2104 case 3:
SeungBeom Kimc01f2432013-08-02 08:33:37 +09002105 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE, &state);
2106 if (state == 1) /* Resolution is changed */
2107 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_CHANGE_RESOL;
2108 else /* Decoding is finished */
2109 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_FINISHED;
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +09002110 break;
2111 default:
2112 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_UNKNOWN;
2113 break;
2114 }
2115
2116 switch (buf.flags & (0x7 << 3)) {
2117 case V4L2_BUF_FLAG_KEYFRAME:
2118 pOutbuf->frameType = VIDEO_FRAME_I;
2119 break;
2120 case V4L2_BUF_FLAG_PFRAME:
2121 pOutbuf->frameType = VIDEO_FRAME_P;
2122 break;
2123 case V4L2_BUF_FLAG_BFRAME:
2124 pOutbuf->frameType = VIDEO_FRAME_B;
2125 break;
2126 default:
2127 pOutbuf->frameType = VIDEO_FRAME_OTHERS;
2128 break;
2129 };
2130
2131 pPDSB = ((PrivateDataShareBuffer *)pCtx->nPrivateDataShareAddress) + buf.index;
2132 if (pCtx->pOutbuf[buf.index].bQueued == VIDEO_TRUE) {
2133 memcpy(pVideoBuffer, pOutbuf, sizeof(ExynosVideoBuffer));
2134 memcpy((char *)(&(pVideoBuffer->PDSB)), (char *)pPDSB, sizeof(PrivateDataShareBuffer));
2135 } else {
2136 ret = VIDEO_ERROR_NOBUFFERS;
2137 ALOGV("%s :: %d", __FUNCTION__, __LINE__);
2138 }
2139
2140 pCtx->pOutbuf[buf.index].bQueued = VIDEO_FALSE;
2141 MFC_Decoder_BufferIndexFree_Outbuf(pHandle, pPDSB, buf.index);
2142
2143 pthread_mutex_unlock(pMutex);
2144
2145EXIT:
2146 return ret;
2147}
2148
2149/*
2150 * [Decoder Buffer OPS] Enable Dynamic DPB
2151 */
2152static ExynosVideoErrorType MFC_Decoder_Enable_DynamicDPB(void *pHandle)
2153{
2154 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
2155 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
2156
2157 if (pCtx == NULL) {
2158 ALOGE("%s: Video context info must be supplied", __func__);
2159 ret = VIDEO_ERROR_BADPARAM;
2160 goto EXIT;
2161 }
2162
2163 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC_SET_DYNAMIC_DPB_MODE, 1) != 0) {
2164 ret = VIDEO_ERROR_APIFAIL;
2165 goto EXIT;
2166 }
2167
2168 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC_SET_USER_SHARED_HANDLE, pCtx->nPrivateDataShareFD) != 0) {
2169 ret = VIDEO_ERROR_APIFAIL;
2170 goto EXIT;
2171 }
2172
2173EXIT:
2174 return ret;
2175}
2176
2177/*
Jiho Chang20d3e6e2012-03-24 03:43:08 +09002178 * [Decoder OPS] Common
2179 */
2180static ExynosVideoDecOps defDecOps = {
Jiho Chang38ef2572012-06-01 20:58:55 +00002181 .nSize = 0,
2182 .Init = MFC_Decoder_Init,
2183 .Finalize = MFC_Decoder_Finalize,
2184 .Set_DisplayDelay = MFC_Decoder_Set_DisplayDelay,
SeungBeom Kime8aae8e2013-06-13 12:17:56 +09002185 .Set_IFrameDecoding = MFC_Decoder_Set_IFrameDecoding,
Jiho Chang38ef2572012-06-01 20:58:55 +00002186 .Enable_PackedPB = MFC_Decoder_Enable_PackedPB,
2187 .Enable_LoopFilter = MFC_Decoder_Enable_LoopFilter,
2188 .Enable_SliceMode = MFC_Decoder_Enable_SliceMode,
2189 .Get_ActualBufferCount = MFC_Decoder_Get_ActualBufferCount,
2190 .Set_FrameTag = MFC_Decoder_Set_FrameTag,
2191 .Get_FrameTag = MFC_Decoder_Get_FrameTag,
2192 .Enable_SEIParsing = MFC_Decoder_Enable_SEIParsing,
2193 .Get_FramePackingInfo = MFC_Decoder_Get_FramePackingInfo,
Jiho Chang20d3e6e2012-03-24 03:43:08 +09002194};
2195
2196/*
2197 * [Decoder Buffer OPS] Input
2198 */
2199static ExynosVideoDecBufferOps defInbufOps = {
Jiho Chang38ef2572012-06-01 20:58:55 +00002200 .nSize = 0,
2201 .Enable_Cacheable = MFC_Decoder_Enable_Cacheable_Inbuf,
2202 .Set_Shareable = MFC_Decoder_Set_Shareable_Inbuf,
2203 .Get_Buffer = NULL,
2204 .Set_Geometry = MFC_Decoder_Set_Geometry_Inbuf,
2205 .Get_Geometry = NULL,
2206 .Setup = MFC_Decoder_Setup_Inbuf,
2207 .Run = MFC_Decoder_Run_Inbuf,
2208 .Stop = MFC_Decoder_Stop_Inbuf,
2209 .Enqueue = MFC_Decoder_Enqueue_Inbuf,
2210 .Enqueue_All = NULL,
2211 .Dequeue = MFC_Decoder_Dequeue_Inbuf,
2212 .Register = MFC_Decoder_Register_Inbuf,
2213 .Clear_RegisteredBuffer = MFC_Decoder_Clear_RegisteredBuffer_Inbuf,
2214 .Clear_Queue = MFC_Decoder_Clear_Queued_Inbuf,
SeungBeom Kimc01f2432013-08-02 08:33:37 +09002215 .Cleanup_Buffer = MFC_Decoder_Cleanup_Buffer_Inbuf,
Jiho Chang20d3e6e2012-03-24 03:43:08 +09002216};
2217
2218/*
2219 * [Decoder Buffer OPS] Output
2220 */
2221static ExynosVideoDecBufferOps defOutbufOps = {
Jiho Chang38ef2572012-06-01 20:58:55 +00002222 .nSize = 0,
2223 .Enable_Cacheable = MFC_Decoder_Enable_Cacheable_Outbuf,
2224 .Set_Shareable = MFC_Decoder_Set_Shareable_Outbuf,
2225 .Get_Buffer = MFC_Decoder_Get_Buffer_Outbuf,
2226 .Set_Geometry = MFC_Decoder_Set_Geometry_Outbuf,
2227 .Get_Geometry = MFC_Decoder_Get_Geometry_Outbuf,
2228 .Setup = MFC_Decoder_Setup_Outbuf,
2229 .Run = MFC_Decoder_Run_Outbuf,
2230 .Stop = MFC_Decoder_Stop_Outbuf,
2231 .Enqueue = MFC_Decoder_Enqueue_Outbuf,
SeungBeom Kim30e79fb2012-07-03 18:31:30 +09002232 .Enqueue_All = NULL,
Jiho Chang38ef2572012-06-01 20:58:55 +00002233 .Dequeue = MFC_Decoder_Dequeue_Outbuf,
2234 .Register = MFC_Decoder_Register_Outbuf,
2235 .Clear_RegisteredBuffer = MFC_Decoder_Clear_RegisteredBuffer_Outbuf,
2236 .Clear_Queue = MFC_Decoder_Clear_Queued_Outbuf,
SeungBeom Kimc01f2432013-08-02 08:33:37 +09002237 .Cleanup_Buffer = MFC_Decoder_Cleanup_Buffer_Outbuf,
SeungBeom Kim3b1c2e32013-07-31 13:46:35 +09002238 .ExtensionEnqueue = MFC_Decoder_ExtensionEnqueue_Outbuf,
2239 .ExtensionDequeue = MFC_Decoder_ExtensionDequeue_Outbuf,
2240 .Enable_DynamicDPB = MFC_Decoder_Enable_DynamicDPB,
Jiho Chang20d3e6e2012-03-24 03:43:08 +09002241};
2242
2243int Exynos_Video_Register_Decoder(
2244 ExynosVideoDecOps *pDecOps,
2245 ExynosVideoDecBufferOps *pInbufOps,
2246 ExynosVideoDecBufferOps *pOutbufOps)
2247{
2248 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
2249
2250 if ((pDecOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) {
2251 ret = VIDEO_ERROR_BADPARAM;
2252 goto EXIT;
2253 }
2254
2255 defDecOps.nSize = sizeof(defDecOps);
2256 defInbufOps.nSize = sizeof(defInbufOps);
2257 defOutbufOps.nSize = sizeof(defOutbufOps);
2258
2259 memcpy((char *)pDecOps + sizeof(pDecOps->nSize), (char *)&defDecOps + sizeof(defDecOps.nSize),
2260 pDecOps->nSize - sizeof(pDecOps->nSize));
2261
2262 memcpy((char *)pInbufOps + sizeof(pInbufOps->nSize), (char *)&defInbufOps + sizeof(defInbufOps.nSize),
2263 pInbufOps->nSize - sizeof(pInbufOps->nSize));
2264
2265 memcpy((char *)pOutbufOps + sizeof(pOutbufOps->nSize), (char *)&defOutbufOps + sizeof(defOutbufOps.nSize),
2266 pOutbufOps->nSize - sizeof(pOutbufOps->nSize));
2267
2268EXIT:
2269 return ret;
2270}