exynos_omx: check pointer before use to workaround potential crash.
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos5.git] / exynos_omx / codecs / exynos_codecs / video / exynos5 / mfc_v4l2 / dec / src / ExynosVideoDecoder.c
CommitLineData
20d3e6e3 1/*
20d3e6e3 2 *
38ef2572 3 * Copyright 2012 Samsung Electronics S.LSI Co. LTD
20d3e6e3 4 *
38ef2572 5 * Licensed under the Apache License, Version 2.0 (the "License");
20d3e6e3
JC
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * @file 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>
38ef2572 37#include <pthread.h>
20d3e6e3
JC
38
39#include <sys/poll.h>
40
3b1c2e30 41#include "ion.h"
20d3e6e3
JC
42#include "ExynosVideoApi.h"
43#include "ExynosVideoDec.h"
81a947ba 44#include "OMX_Core.h"
20d3e6e3
JC
45
46/* #define LOG_NDEBUG 0 */
47#define LOG_TAG "ExynosVideoDecoder"
48#include <utils/Log.h>
49
3b1c2e30
SK
50#define MAX_OUTPUTBUFFER_COUNT 32
51
20d3e6e3
JC
52/*
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:
800a8d75 79 pixelformat = V4L2_PIX_FMT_MPEG2;
20d3e6e3
JC
80 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 */
c94beaeb 115static void *MFC_Decoder_Init(int nMemoryType)
20d3e6e3
JC
116{
117 ExynosVideoDecContext *pCtx = NULL;
38ef2572 118 pthread_mutex_t *pMutex = NULL;
20d3e6e3
JC
119 int needCaps = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING);
120
121 pCtx = (ExynosVideoDecContext *)malloc(sizeof(*pCtx));
122 if (pCtx == NULL) {
4a7b2d3c 123 ALOGE("%s: Failed to allocate decoder context buffer", __func__);
20d3e6e3
JC
124 goto EXIT_ALLOC_FAIL;
125 }
126
127 memset(pCtx, 0, sizeof(*pCtx));
128
38ef2572 129 pCtx->hDec = exynos_v4l2_open_devname(VIDEO_DECODER_NAME, O_RDWR, 0);
20d3e6e3 130 if (pCtx->hDec < 0) {
4a7b2d3c 131 ALOGE("%s: Failed to open decoder device", __func__);
20d3e6e3
JC
132 goto EXIT_OPEN_FAIL;
133 }
134
135 if (!exynos_v4l2_querycap(pCtx->hDec, needCaps)) {
4a7b2d3c 136 ALOGE("%s: Failed to querycap", __func__);
20d3e6e3
JC
137 goto EXIT_QUERYCAP_FAIL;
138 }
139
140 pCtx->bStreamonInbuf = VIDEO_FALSE;
141 pCtx->bStreamonOutbuf = VIDEO_FALSE;
142
c94beaeb 143 pCtx->nMemoryType = nMemoryType;
1f0d5e30 144
38ef2572
JC
145 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 }
38ef2572
JC
150 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 }
38ef2572
JC
161 if (pthread_mutex_init(pMutex, NULL) != 0) {
162 free(pMutex);
163 goto EXIT_QUERYCAP_FAIL;
164 }
165 pCtx->pOutMutex = (void*)pMutex;
166
3b1c2e30
SK
167 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
20d3e6e3
JC
174 return (void *)pCtx;
175
176EXIT_QUERYCAP_FAIL:
38ef2572
JC
177 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
20d3e6e3
JC
187 close(pCtx->hDec);
188
189EXIT_OPEN_FAIL:
190 free(pCtx);
20d3e6e3
JC
191
192EXIT_ALLOC_FAIL:
193 return NULL;
194}
195
196/*
197 * [Decoder OPS] Finalize
198 */
199static ExynosVideoErrorType MFC_Decoder_Finalize(void *pHandle)
200{
38ef2572
JC
201 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
202 ExynosVideoPlane *pVideoPlane = NULL;
203 pthread_mutex_t *pMutex = NULL;
204 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
20d3e6e3
JC
205 int i, j;
206
207 if (pCtx == NULL) {
4a7b2d3c 208 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
209 ret = VIDEO_ERROR_BADPARAM;
210 goto EXIT;
211 }
212
3b1c2e30
SK
213 ion_unmap(pCtx->nPrivateDataShareAddress, sizeof(PrivateDataShareBuffer) * VIDEO_BUFFER_MAX_NUM);
214 ion_free(pCtx->nPrivateDataShareFD);
215 ion_client_destroy((ion_client)pCtx->hIONHandle);
216
38ef2572
JC
217 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
20d3e6e3
JC
231 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;
38ef2572 244 pCtx->pInbuf[i].bRegistered = VIDEO_FALSE;
20d3e6e3
JC
245 }
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;
38ef2572 262 pCtx->pOutbuf[i].bRegistered = VIDEO_FALSE;
20d3e6e3
JC
263 }
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) {
4a7b2d3c 293 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
294 ret = VIDEO_ERROR_BADPARAM;
295 goto EXIT;
296 }
297
38ef2572 298 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, frameTag) != 0) {
20d3e6e3
JC
299 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) {
4a7b2d3c 316 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
317 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) {
4a7b2d3c 335 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
336 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/*
800a8d75 346 * [Decoder OPS] Set Display Delay
20d3e6e3 347 */
800a8d75
JC
348static ExynosVideoErrorType MFC_Decoder_Set_DisplayDelay(
349 void *pHandle,
350 int delay)
20d3e6e3
JC
351{
352 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
353 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
354
355 if (pCtx == NULL) {
4a7b2d3c 356 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
357 ret = VIDEO_ERROR_BADPARAM;
358 goto EXIT;
359 }
360
38ef2572 361 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY, delay) != 0) {
20d3e6e3
JC
362 ret = VIDEO_ERROR_APIFAIL;
363 goto EXIT;
364 }
365
366EXIT:
367 return ret;
368}
369
e8aae8ed
SK
370/*
371 * [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
20d3e6e3 394/*
800a8d75 395 * [Decoder OPS] Enable Packed PB
20d3e6e3 396 */
800a8d75 397static ExynosVideoErrorType MFC_Decoder_Enable_PackedPB(void *pHandle)
20d3e6e3
JC
398{
399 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
400 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
401
402 if (pCtx == NULL) {
4a7b2d3c 403 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
404 ret = VIDEO_ERROR_BADPARAM;
405 goto EXIT;
406 }
407
38ef2572 408 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_PACKED_PB, 1) != 0) {
20d3e6e3
JC
409 ret = VIDEO_ERROR_APIFAIL;
410 goto EXIT;
411 }
412
413EXIT:
414 return ret;
415}
416
417/*
800a8d75 418 * [Decoder OPS] Enable Loop Filter
20d3e6e3 419 */
800a8d75 420static ExynosVideoErrorType MFC_Decoder_Enable_LoopFilter(void *pHandle)
20d3e6e3
JC
421{
422 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
423 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
424
425 if (pCtx == NULL) {
4a7b2d3c 426 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
427 ret = VIDEO_ERROR_BADPARAM;
428 goto EXIT;
429 }
430
38ef2572 431 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER, 1) != 0) {
20d3e6e3
JC
432 ret = VIDEO_ERROR_APIFAIL;
433 goto EXIT;
434 }
435
436EXIT:
437 return ret;
438}
439
440/*
800a8d75 441 * [Decoder OPS] Enable Slice Mode
20d3e6e3 442 */
800a8d75 443static ExynosVideoErrorType MFC_Decoder_Enable_SliceMode(void *pHandle)
20d3e6e3
JC
444{
445 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
446 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
447
448 if (pCtx == NULL) {
4a7b2d3c 449 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
450 ret = VIDEO_ERROR_BADPARAM;
451 goto EXIT;
452 }
453
38ef2572 454 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE, 1) != 0) {
20d3e6e3
JC
455 ret = VIDEO_ERROR_APIFAIL;
456 goto EXIT;
457 }
458
459EXIT:
460 return ret;
461}
462
463/*
800a8d75 464 * [Decoder OPS] Enable SEI Parsing
20d3e6e3 465 */
800a8d75 466static ExynosVideoErrorType MFC_Decoder_Enable_SEIParsing(void *pHandle)
20d3e6e3
JC
467{
468 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
469 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
470
471 if (pCtx == NULL) {
4a7b2d3c 472 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
473 ret = VIDEO_ERROR_BADPARAM;
474 goto EXIT;
475 }
476
38ef2572 477 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING, 1) != 0) {
800a8d75
JC
478 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
38ef2572
JC
503 if ((pCtx == NULL) || (pFramePacking == NULL)) {
504 ALOGE("%s: Video context info or FramePacking pointer must be supplied", __func__);
800a8d75
JC
505 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
38ef2572 520 if (exynos_v4l2_g_ext_ctrl(pCtx->hDec, &ext_ctrls) != 0) {
800a8d75
JC
521 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
38ef2572 565 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_CACHEABLE, 2) != 0) {
800a8d75
JC
566 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
38ef2572 588 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_CACHEABLE, 1) != 0) {
20d3e6e3
JC
589 ret = VIDEO_ERROR_APIFAIL;
590 goto EXIT;
591 }
592
593EXIT:
594 return ret;
595}
596
597/*
598 * [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) {
4a7b2d3c 606 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
607 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) {
4a7b2d3c 626 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
627 ret = VIDEO_ERROR_BADPARAM;
628 goto EXIT;
629 }
630
631 pCtx->bShareOutbuf = VIDEO_TRUE;
632
633EXIT:
634 return ret;
635}
636
637/*
38ef2572 638 * [Decoder Buffer OPS] Get Buffer (Input)
20d3e6e3 639 */
38ef2572
JC
640static ExynosVideoErrorType MFC_Decoder_Get_Buffer_Inbuf(
641 void *pHandle,
642 int nIndex,
643 ExynosVideoBuffer **pBuffer)
20d3e6e3
JC
644{
645 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
646 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
647
648 if (pCtx == NULL) {
4a7b2d3c 649 ALOGE("%s: Video context info must be supplied", __func__);
38ef2572
JC
650 *pBuffer = NULL;
651 ret = VIDEO_ERROR_BADPARAM;
20d3e6e3
JC
652 goto EXIT;
653 }
654
38ef2572
JC
655 if (pCtx->nInbufs <= nIndex) {
656 *pBuffer = NULL;
657 ret = VIDEO_ERROR_BADPARAM;
658 goto EXIT;
659 }
660
661 *pBuffer = (ExynosVideoBuffer *)&pCtx->pInbuf[nIndex];
20d3e6e3
JC
662
663EXIT:
664 return ret;
665}
666
667/*
38ef2572 668 * [Decoder Buffer OPS] Get Buffer (Output)
20d3e6e3 669 */
38ef2572
JC
670static ExynosVideoErrorType MFC_Decoder_Get_Buffer_Outbuf(
671 void *pHandle,
672 int nIndex,
673 ExynosVideoBuffer **pBuffer)
20d3e6e3
JC
674{
675 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
676 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
677
678 if (pCtx == NULL) {
4a7b2d3c 679 ALOGE("%s: Video context info must be supplied", __func__);
38ef2572
JC
680 *pBuffer = NULL;
681 ret = VIDEO_ERROR_BADPARAM;
20d3e6e3
JC
682 goto EXIT;
683 }
684
38ef2572
JC
685 if (pCtx->nOutbufs <= nIndex) {
686 *pBuffer = NULL;
687 ret = VIDEO_ERROR_BADPARAM;
688 goto EXIT;
689 }
690
691 *pBuffer = (ExynosVideoBuffer *)&pCtx->pOutbuf[nIndex];
20d3e6e3
JC
692
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) {
4a7b2d3c 710 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
711 ret = VIDEO_ERROR_BADPARAM;
712 goto EXIT;
713 }
714
715 if (bufferConf == NULL) {
4a7b2d3c 716 ALOGE("%s: Buffer geometry must be supplied", __func__);
20d3e6e3
JC
717 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
38ef2572 727 if (exynos_v4l2_s_fmt(pCtx->hDec, &fmt) != 0) {
20d3e6e3
JC
728 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) {
4a7b2d3c 751 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
752 ret = VIDEO_ERROR_BADPARAM;
753 goto EXIT;
754 }
755
756 if (bufferConf == NULL) {
4a7b2d3c 757 ALOGE("%s: Buffer geometry must be supplied", __func__);
20d3e6e3
JC
758 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
38ef2572 767 if (exynos_v4l2_s_fmt(pCtx->hDec, &fmt) != 0) {
20d3e6e3
JC
768 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) {
4a7b2d3c 792 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
793 ret = VIDEO_ERROR_BADPARAM;
794 goto EXIT;
795 }
796
797 if (bufferConf == NULL) {
4a7b2d3c 798 ALOGE("%s: Buffer geometry must be supplied", __func__);
20d3e6e3
JC
799 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;
38ef2572 807 if (exynos_v4l2_g_fmt(pCtx->hDec, &fmt) != 0) {
20d3e6e3
JC
808 ret = VIDEO_ERROR_APIFAIL;
809 goto EXIT;
810 }
811
812 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
38ef2572 813 if (exynos_v4l2_g_crop(pCtx->hDec, &crop) != 0) {
20d3e6e3
JC
814 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{
38ef2572
JC
837 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
838 ExynosVideoPlane *pVideoPlane = NULL;
839 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
20d3e6e3
JC
840
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) {
4a7b2d3c 847 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
848 ret = VIDEO_ERROR_BADPARAM;
849 goto EXIT;
850 }
851
852 if (nBufferCount == 0) {
4a7b2d3c 853 ALOGE("%s: Buffer count must be greater than 0", __func__);
20d3e6e3
JC
854 ret = VIDEO_ERROR_BADPARAM;
855 goto EXIT;
856 }
857
01fa64f5
DZ
858 ALOGV("%s: setting up inbufs (%d) shared=%s\n", __func__, nBufferCount,
859 pCtx->bShareInbuf ? "true" : "false");
860
20d3e6e3
JC
861 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)
1f0d5e30 867 req.memory = pCtx->nMemoryType;
20d3e6e3
JC
868 else
869 req.memory = V4L2_MEMORY_MMAP;
870
38ef2572 871 if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) {
20d3e6e3
JC
872 ret = VIDEO_ERROR_APIFAIL;
873 goto EXIT;
874 }
875
30e79fb1
SK
876 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 }
01fa64f5 881
20d3e6e3
JC
882 pCtx->nInbufs = (int)req.count;
883
884 pCtx->pInbuf = malloc(sizeof(*pCtx->pInbuf) * pCtx->nInbufs);
885 if (pCtx->pInbuf == NULL) {
4a7b2d3c 886 ALOGE("Failed to allocate input buffer context");
20d3e6e3
JC
887 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;
38ef2572 902 if (exynos_v4l2_querybuf(pCtx->hDec, &buf) != 0) {
20d3e6e3
JC
903 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;
38ef2572
JC
922 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
923 pCtx->pInbuf[i].bRegistered = VIDEO_TRUE;
20d3e6e3
JC
924 }
925 }
926
927 return ret;
928
929EXIT:
800a8d75
JC
930 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 }
20d3e6e3 938
800a8d75
JC
939 munmap(pVideoPlane->addr, pVideoPlane->allocSize);
940 }
20d3e6e3 941 }
800a8d75
JC
942
943 free(pCtx->pInbuf);
20d3e6e3
JC
944 }
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{
38ef2572
JC
956 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
957 ExynosVideoPlane *pVideoPlane = NULL;
958 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
20d3e6e3
JC
959
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) {
4a7b2d3c 966 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
967 ret = VIDEO_ERROR_BADPARAM;
968 goto EXIT;
969 }
970
971 if (nBufferCount == 0) {
3b1c2e30
SK
972 nBufferCount = MAX_OUTPUTBUFFER_COUNT;
973 ALOGV("%s: Change buffer count %d", __func__, nBufferCount);
20d3e6e3
JC
974 }
975
01fa64f5
DZ
976 ALOGV("%s: setting up outbufs (%d) shared=%s\n", __func__, nBufferCount,
977 pCtx->bShareOutbuf ? "true" : "false");
978
20d3e6e3
JC
979 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)
1f0d5e30 985 req.memory = pCtx->nMemoryType;
20d3e6e3
JC
986 else
987 req.memory = V4L2_MEMORY_MMAP;
988
38ef2572 989 if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) {
20d3e6e3
JC
990 ret = VIDEO_ERROR_APIFAIL;
991 goto EXIT;
992 }
993
30e79fb1
SK
994 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
20d3e6e3
JC
1000 pCtx->nOutbufs = req.count;
1001
1002 pCtx->pOutbuf = malloc(sizeof(*pCtx->pOutbuf) * pCtx->nOutbufs);
1003 if (pCtx->pOutbuf == NULL) {
4a7b2d3c 1004 ALOGE("Failed to allocate output buffer context");
20d3e6e3
JC
1005 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;
38ef2572 1020 if (exynos_v4l2_querybuf(pCtx->hDec, &buf) != 0) {
20d3e6e3
JC
1021 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;
3b1c2e30
SK
1041 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;
20d3e6e3
JC
1045 }
1046 }
1047
1048 return ret;
1049
1050EXIT:
800a8d75
JC
1051 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 }
20d3e6e3 1060
800a8d75
JC
1061 munmap(pVideoPlane->addr, pVideoPlane->allocSize);
1062 }
20d3e6e3 1063 }
20d3e6e3 1064 }
800a8d75
JC
1065
1066 free(pCtx->pOutbuf);
c01f2434 1067 pCtx->pOutbuf = NULL;
20d3e6e3
JC
1068 }
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) {
4a7b2d3c 1082 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1083 ret = VIDEO_ERROR_BADPARAM;
1084 goto EXIT;
1085 }
1086
1087 if (pCtx->bStreamonInbuf == VIDEO_FALSE) {
38ef2572 1088 if (exynos_v4l2_streamon(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) {
4a7b2d3c 1089 ALOGE("%s: Failed to streamon for input buffer", __func__);
20d3e6e3
JC
1090 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) {
4a7b2d3c 1109 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1110 ret = VIDEO_ERROR_BADPARAM;
1111 goto EXIT;
1112 }
1113
1114 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
38ef2572 1115 if (exynos_v4l2_streamon(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) {
4a7b2d3c 1116 ALOGE("%s: Failed to streamon for output buffer", __func__);
20d3e6e3
JC
1117 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;
38ef2572 1134 int i = 0;
20d3e6e3
JC
1135
1136 if (pCtx == NULL) {
4a7b2d3c 1137 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1138 ret = VIDEO_ERROR_BADPARAM;
1139 goto EXIT;
1140 }
1141
1142 if (pCtx->bStreamonInbuf == VIDEO_TRUE) {
38ef2572 1143 if (exynos_v4l2_streamoff(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) {
4a7b2d3c 1144 ALOGE("%s: Failed to streamoff for input buffer", __func__);
20d3e6e3
JC
1145 ret = VIDEO_ERROR_APIFAIL;
1146 goto EXIT;
1147 }
1148 pCtx->bStreamonInbuf = VIDEO_FALSE;
1149 }
1150
38ef2572
JC
1151 for (i = 0; i < pCtx->nInbufs; i++) {
1152 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
1153 }
1154
20d3e6e3
JC
1155EXIT:
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;
38ef2572 1166 int i = 0;
20d3e6e3
JC
1167
1168 if (pCtx == NULL) {
4a7b2d3c 1169 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1170 ret = VIDEO_ERROR_BADPARAM;
1171 goto EXIT;
1172 }
1173
1174 if (pCtx->bStreamonOutbuf == VIDEO_TRUE) {
38ef2572 1175 if (exynos_v4l2_streamoff(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) {
4a7b2d3c 1176 ALOGE("%s: Failed to streamoff for output buffer", __func__);
20d3e6e3
JC
1177 ret = VIDEO_ERROR_APIFAIL;
1178 goto EXIT;
1179 }
1180 pCtx->bStreamonOutbuf = VIDEO_FALSE;
1181 }
1182
38ef2572 1183 for (i = 0; i < pCtx->nOutbufs; i++) {
3b1c2e30
SK
1184 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
1185 pCtx->pOutbuf[i].bSlotUsed = VIDEO_FALSE;
1186 pCtx->pOutbuf[i].nIndexUseCnt = 0;
38ef2572
JC
1187 }
1188
20d3e6e3
JC
1189EXIT:
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) {
4a7b2d3c 1205 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1206 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 {
4a7b2d3c 1220 ALOGE("%s: Poll return error", __func__);
20d3e6e3
JC
1221 ret = VIDEO_ERROR_POLL;
1222 break;
1223 }
1224 } else if (poll_state < 0) {
4a7b2d3c 1225 ALOGE("%s: Poll state error", __func__);
20d3e6e3
JC
1226 ret = VIDEO_ERROR_POLL;
1227 break;
1228 }
1229 } while (poll_state == 0);
1230
1231EXIT:
1232 return ret;
1233}
1234
38ef2572 1235static ExynosVideoErrorType MFC_Decoder_Register_Inbuf(
01fa64f5
DZ
1236 void *pHandle,
1237 ExynosVideoPlane *planes,
1238 int nPlanes)
38ef2572
JC
1239{
1240 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1241 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
30e79fb1 1242 int nIndex, plane;
38ef2572 1243
30e79fb1 1244 if ((pCtx == NULL) || (planes == NULL) || (nPlanes != VIDEO_DECODER_INBUF_PLANES)) {
38ef2572
JC
1245 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) {
30e79fb1
SK
1252 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 }
38ef2572
JC
1259 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(
01fa64f5
DZ
1274 void *pHandle,
1275 ExynosVideoPlane *planes,
1276 int nPlanes)
38ef2572
JC
1277{
1278 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1279 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
30e79fb1 1280 int nIndex, plane;
38ef2572 1281
30e79fb1 1282 if ((pCtx == NULL) || (planes == NULL) || (nPlanes != VIDEO_DECODER_OUTBUF_PLANES)) {
38ef2572
JC
1283 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) {
30e79fb1 1290 for (plane = 0; plane < nPlanes; plane++) {
01fa64f5
DZ
1291 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 }
38ef2572 1295 pCtx->pOutbuf[nIndex].bRegistered = VIDEO_TRUE;
01fa64f5
DZ
1296 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);
38ef2572
JC
1299 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
20d3e6e3
JC
1354/*
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) {
4a7b2d3c 1365 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1366 goto EXIT;
1367 }
1368
30e79fb1
SK
1369 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))
20d3e6e3
JC
1373 break;
1374 }
1375 }
1376
30e79fb1 1377 if (nIndex == pCtx->nInbufs)
20d3e6e3 1378 nIndex = -1;
20d3e6e3
JC
1379
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) {
4a7b2d3c 1395 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1396 goto EXIT;
1397 }
1398
30e79fb1
SK
1399 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))
20d3e6e3
JC
1403 break;
1404 }
1405 }
1406
30e79fb1 1407 if (nIndex == pCtx->nOutbufs)
20d3e6e3 1408 nIndex = -1;
20d3e6e3
JC
1409
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;
38ef2572 1426 pthread_mutex_t *pMutex = NULL;
20d3e6e3
JC
1427
1428 struct v4l2_plane planes[VIDEO_DECODER_INBUF_PLANES];
1429 struct v4l2_buffer buf;
1430 int index, i;
1431
1432 if (pCtx == NULL) {
4a7b2d3c 1433 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1434 ret = VIDEO_ERROR_BADPARAM;
1435 goto EXIT;
1436 }
1437
800a8d75
JC
1438 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
20d3e6e3
JC
1445 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
30e79fb1
SK
1451 pMutex = (pthread_mutex_t*)pCtx->pInMutex;
1452 pthread_mutex_lock(pMutex);
38ef2572 1453 index = MFC_Decoder_Find_Inbuf(pCtx, pBuffer[0]);
20d3e6e3 1454 if (index == -1) {
30e79fb1
SK
1455 pthread_mutex_unlock(pMutex);
1456 ALOGE("%s: Failed to get index", __func__);
20d3e6e3
JC
1457 ret = VIDEO_ERROR_NOBUFFERS;
1458 goto EXIT;
1459 }
1460
1461 buf.index = index;
30e79fb1 1462 pCtx->pInbuf[buf.index].bQueued = VIDEO_TRUE;
20d3e6e3
JC
1463
1464 if (pCtx->bShareInbuf == VIDEO_TRUE) {
1f0d5e30 1465 buf.memory = pCtx->nMemoryType;
20d3e6e3 1466 for (i = 0; i < nPlanes; i++) {
30e79fb1
SK
1467 /* V4L2_MEMORY_USERPTR */
1468 buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i];
1469 /* V4L2_MEMORY_DMABUF */
01fa64f5 1470 buf.m.planes[i].m.fd = pCtx->pInbuf[index].planes[i].fd;
38ef2572 1471 buf.m.planes[i].length = pCtx->pInbuf[index].planes[i].allocSize;
20d3e6e3 1472 buf.m.planes[i].bytesused = dataSize[i];
30e79fb1 1473 ALOGV("%s: shared inbuf(%d) plane(%d) addr=%p fd=%d len=%d used=%d\n", __func__,
01fa64f5 1474 index, i,
30e79fb1 1475 buf.m.planes[i].m.userptr,
01fa64f5
DZ
1476 buf.m.planes[i].m.fd,
1477 buf.m.planes[i].length,
1478 buf.m.planes[i].bytesused);
20d3e6e3
JC
1479 }
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
29a60df6
RW
1486 // FIXME: figure out why |pPrivate| may be NULL.
1487 if (pPrivate &&
1488 (((OMX_BUFFERHEADERTYPE *)pPrivate)->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) {
81a947ba 1489 buf.flags |= V4L2_BUF_FLAG_LAST_FRAME;
f8d511af 1490 ALOGV("%s: OMX_BUFFERFLAG_EOS => LAST_FRAME: 0x%x", __func__,
81a947ba
SK
1491 !!(buf.flags & V4L2_BUF_FLAG_LAST_FRAME));
1492 }
1493
3b1c2e30
SK
1494 pCtx->pInbuf[buf.index].pPrivate = pPrivate;
1495
1496 pthread_mutex_unlock(pMutex);
1497
30e79fb1
SK
1498 if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) {
1499 ALOGE("%s: Failed to enqueue input buffer", __func__);
3b1c2e30
SK
1500 pthread_mutex_lock(pMutex);
1501 pCtx->pInbuf[buf.index].pPrivate = NULL;
1502 pCtx->pInbuf[buf.index].bQueued = VIDEO_FALSE;
1503 pthread_mutex_unlock(pMutex);
20d3e6e3
JC
1504 ret = VIDEO_ERROR_APIFAIL;
1505 goto EXIT;
1506 }
30e79fb1 1507
20d3e6e3
JC
1508EXIT:
1509 return ret;
1510}
1511
1512/*
1513 * [Decoder Buffer OPS] Enqueue (Output)
1514 */
1515static ExynosVideoErrorType MFC_Decoder_Enqueue_Outbuf(
1516 void *pHandle,
1517 unsigned char *pBuffer[],
1518 unsigned int dataSize[],
1519 int nPlanes,
1520 void *pPrivate)
1521{
1522 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1523 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
38ef2572 1524 pthread_mutex_t *pMutex = NULL;
20d3e6e3
JC
1525
1526 struct v4l2_plane planes[VIDEO_DECODER_OUTBUF_PLANES];
1527 struct v4l2_buffer buf;
1528 int i, index;
1529
1530 if (pCtx == NULL) {
4a7b2d3c 1531 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1532 ret = VIDEO_ERROR_BADPARAM;
1533 goto EXIT;
1534 }
1535
38ef2572
JC
1536 if (VIDEO_DECODER_OUTBUF_PLANES < nPlanes) {
1537 ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__,
1538 VIDEO_DECODER_OUTBUF_PLANES, nPlanes);
1539 ret = VIDEO_ERROR_BADPARAM;
1540 goto EXIT;
1541 }
20d3e6e3 1542
38ef2572 1543 memset(&buf, 0, sizeof(buf));
20d3e6e3
JC
1544 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1545 buf.m.planes = planes;
30e79fb1 1546 buf.length = VIDEO_DECODER_OUTBUF_PLANES;
20d3e6e3 1547
30e79fb1
SK
1548 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
1549 pthread_mutex_lock(pMutex);
38ef2572 1550 index = MFC_Decoder_Find_Outbuf(pCtx, pBuffer[0]);
20d3e6e3 1551 if (index == -1) {
30e79fb1
SK
1552 pthread_mutex_unlock(pMutex);
1553 ALOGE("%s: Failed to get index", __func__);
20d3e6e3
JC
1554 ret = VIDEO_ERROR_NOBUFFERS;
1555 goto EXIT;
1556 }
20d3e6e3 1557 buf.index = index;
30e79fb1 1558 pCtx->pOutbuf[buf.index].bQueued = VIDEO_TRUE;
20d3e6e3
JC
1559
1560 if (pCtx->bShareOutbuf == VIDEO_TRUE) {
1f0d5e30 1561 buf.memory = pCtx->nMemoryType;
20d3e6e3 1562 for (i = 0; i < nPlanes; i++) {
30e79fb1
SK
1563 /* V4L2_MEMORY_USERPTR */
1564 buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i];
1565 /* V4L2_MEMORY_DMABUF */
01fa64f5 1566 buf.m.planes[i].m.fd = pCtx->pOutbuf[index].planes[i].fd;
38ef2572 1567 buf.m.planes[i].length = pCtx->pOutbuf[index].planes[i].allocSize;
20d3e6e3 1568 buf.m.planes[i].bytesused = dataSize[i];
01fa64f5
DZ
1569 ALOGV("%s: shared outbuf(%d) plane=%d addr=%p fd=%d len=%d used=%d\n", __func__,
1570 index, i,
30e79fb1 1571 buf.m.planes[i].m.userptr,
01fa64f5
DZ
1572 buf.m.planes[i].m.fd,
1573 buf.m.planes[i].length,
1574 buf.m.planes[i].bytesused);
20d3e6e3
JC
1575 }
1576 } else {
01fa64f5 1577 ALOGV("%s: non-shared outbuf(%d)\n", __func__, index);
20d3e6e3
JC
1578 buf.memory = V4L2_MEMORY_MMAP;
1579 }
1580
3b1c2e30
SK
1581 pCtx->pOutbuf[buf.index].pPrivate = pPrivate;
1582
1583 pthread_mutex_unlock(pMutex);
1584
30e79fb1
SK
1585 if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) {
1586 ALOGE("%s: Failed to enqueue output buffer", __func__);
3b1c2e30
SK
1587 pthread_mutex_lock(pMutex);
1588 pCtx->pOutbuf[buf.index].pPrivate = NULL;
1589 pCtx->pOutbuf[buf.index].bQueued = VIDEO_FALSE;
1590 pthread_mutex_unlock(pMutex);
20d3e6e3
JC
1591 ret = VIDEO_ERROR_APIFAIL;
1592 goto EXIT;
1593 }
30e79fb1 1594
20d3e6e3
JC
1595EXIT:
1596 return ret;
1597}
1598
1599/*
1600 * [Decoder Buffer OPS] Dequeue (Input)
1601 */
1602static ExynosVideoBuffer *MFC_Decoder_Dequeue_Inbuf(void *pHandle)
1603{
38ef2572
JC
1604 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1605 ExynosVideoBuffer *pInbuf = NULL;
3b1c2e30 1606 pthread_mutex_t *pMutex = NULL;
20d3e6e3
JC
1607
1608 struct v4l2_buffer buf;
1609
1610 if (pCtx == NULL) {
4a7b2d3c 1611 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1612 goto EXIT;
1613 }
1614
1615 if (pCtx->bStreamonInbuf == VIDEO_FALSE) {
38ef2572 1616 pInbuf = NULL;
20d3e6e3
JC
1617 goto EXIT;
1618 }
1619
1620 memset(&buf, 0, sizeof(buf));
1621
1622 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1623
1624 if (pCtx->bShareInbuf == VIDEO_TRUE)
1f0d5e30 1625 buf.memory = pCtx->nMemoryType;
20d3e6e3
JC
1626 else
1627 buf.memory = V4L2_MEMORY_MMAP;
1628
38ef2572
JC
1629 if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) {
1630 pInbuf = NULL;
20d3e6e3
JC
1631 goto EXIT;
1632 }
1633
3b1c2e30
SK
1634 pMutex = (pthread_mutex_t*)pCtx->pInMutex;
1635 pthread_mutex_lock(pMutex);
1636
38ef2572 1637 pInbuf = &pCtx->pInbuf[buf.index];
30e79fb1 1638 pCtx->pInbuf[buf.index].bQueued = VIDEO_FALSE;
38ef2572
JC
1639
1640 if (pCtx->bStreamonInbuf == VIDEO_FALSE)
1641 pInbuf = NULL;
1642
3b1c2e30
SK
1643 pthread_mutex_unlock(pMutex);
1644
20d3e6e3 1645EXIT:
38ef2572 1646 return pInbuf;
20d3e6e3
JC
1647}
1648
20d3e6e3
JC
1649/*
1650 * [Decoder Buffer OPS] Dequeue (Output)
1651 */
1652static ExynosVideoBuffer *MFC_Decoder_Dequeue_Outbuf(void *pHandle)
1653{
1654 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1655 ExynosVideoBuffer *pOutbuf = NULL;
3b1c2e30 1656 pthread_mutex_t *pMutex = NULL;
20d3e6e3
JC
1657
1658 struct v4l2_buffer buf;
c01f2434 1659 int value, state;
20d3e6e3
JC
1660
1661 if (pCtx == NULL) {
4a7b2d3c 1662 ALOGE("%s: Video context info must be supplied", __func__);
20d3e6e3
JC
1663 goto EXIT;
1664 }
1665
1666 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
38ef2572 1667 pOutbuf = NULL;
20d3e6e3
JC
1668 goto EXIT;
1669 }
1670
1671 memset(&buf, 0, sizeof(buf));
20d3e6e3
JC
1672 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1673
1674 if (pCtx->bShareOutbuf == VIDEO_TRUE)
1f0d5e30 1675 buf.memory = pCtx->nMemoryType;
20d3e6e3
JC
1676 else
1677 buf.memory = V4L2_MEMORY_MMAP;
1678
1679 /* HACK: pOutbuf return -1 means DECODING_ONLY for almost cases */
38ef2572
JC
1680 if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) {
1681 pOutbuf = NULL;
1682 goto EXIT;
1683 }
1684
1685 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
20d3e6e3
JC
1686 pOutbuf = NULL;
1687 goto EXIT;
1688 }
1689
3b1c2e30
SK
1690 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
1691 pthread_mutex_lock(pMutex);
1692
20d3e6e3
JC
1693 pOutbuf = &pCtx->pOutbuf[buf.index];
1694
1695 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS, &value);
1696
1697 switch (value) {
1698 case 0:
1699 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_ONLY;
1700 break;
1701 case 1:
1702 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_DECODING;
1703 break;
1704 case 2:
1705 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_ONLY;
3b1c2e30 1706 break;
20d3e6e3 1707 case 3:
c01f2434
SK
1708 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE, &state);
1709 if (state == 1) /* Resolution is changed */
1710 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_CHANGE_RESOL;
1711 else /* Decoding is finished */
1712 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_FINISHED;
20d3e6e3
JC
1713 break;
1714 default:
1715 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_UNKNOWN;
1716 break;
1717 }
1718
1719 switch (buf.flags & (0x7 << 3)) {
1720 case V4L2_BUF_FLAG_KEYFRAME:
1721 pOutbuf->frameType = VIDEO_FRAME_I;
1722 break;
1723 case V4L2_BUF_FLAG_PFRAME:
1724 pOutbuf->frameType = VIDEO_FRAME_P;
1725 break;
1726 case V4L2_BUF_FLAG_BFRAME:
1727 pOutbuf->frameType = VIDEO_FRAME_B;
1728 break;
1729 default:
1730 pOutbuf->frameType = VIDEO_FRAME_OTHERS;
1731 break;
1732 };
1733
1734 pOutbuf->bQueued = VIDEO_FALSE;
1735
3b1c2e30
SK
1736 pthread_mutex_unlock(pMutex);
1737
20d3e6e3
JC
1738EXIT:
1739 return pOutbuf;
1740}
1741
38ef2572
JC
1742static ExynosVideoErrorType MFC_Decoder_Clear_Queued_Inbuf(void *pHandle)
1743{
1744 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1745 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1746 int i;
1747
1748 if (pCtx == NULL) {
1749 ALOGE("%s: Video context info must be supplied", __func__);
1750 ret = VIDEO_ERROR_BADPARAM;
1751 goto EXIT;
1752 }
1753
1754 for (i = 0; i < pCtx->nInbufs; i++) {
1755 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
1756 }
1757
1758EXIT:
1759 return ret;
1760}
1761
1762static ExynosVideoErrorType MFC_Decoder_Clear_Queued_Outbuf(void *pHandle)
1763{
1764 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1765 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1766 int i;
1767
1768 if (pCtx == NULL) {
1769 ALOGE("%s: Video context info must be supplied", __func__);
1770 ret = VIDEO_ERROR_BADPARAM;
1771 goto EXIT;
1772 }
1773
1774 for (i = 0; i < pCtx->nOutbufs; i++) {
1775 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
1776 }
1777
1778EXIT:
1779 return ret;
1780}
1781
c01f2434
SK
1782/*
1783 * [Decoder Buffer OPS] Cleanup Buffer (Input)
1784 */
1785static ExynosVideoErrorType MFC_Decoder_Cleanup_Buffer_Inbuf(void *pHandle)
1786{
1787 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1788 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1789
1790 struct v4l2_requestbuffers req;
1791 int nBufferCount = 0;
1792
1793 if (pCtx == NULL) {
1794 ALOGE("%s: Video context info must be supplied", __func__);
1795 ret = VIDEO_ERROR_BADPARAM;
1796 goto EXIT;
1797 }
1798
1799 nBufferCount = 0; /* for clean-up */
1800
1801 memset(&req, 0, sizeof(req));
1802
1803 req.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1804 req.count = nBufferCount;
1805
1806 if (pCtx->bShareInbuf == VIDEO_TRUE)
1807 req.memory = pCtx->nMemoryType;
1808 else
1809 req.memory = V4L2_MEMORY_MMAP;
1810
1811 if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) {
1812 ret = VIDEO_ERROR_APIFAIL;
1813 goto EXIT;
1814 }
1815
1816 pCtx->nInbufs = (int)req.count;
1817
1818 if (pCtx->pInbuf != NULL) {
1819 free(pCtx->pInbuf);
1820 pCtx->pInbuf = NULL;
1821 }
1822
1823EXIT:
1824 return ret;
1825}
1826
1827/*
1828 * [Decoder Buffer OPS] Cleanup Buffer (Output)
1829 */
1830static ExynosVideoErrorType MFC_Decoder_Cleanup_Buffer_Outbuf(void *pHandle)
1831{
1832 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1833 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1834
1835 struct v4l2_requestbuffers req;
1836 int nBufferCount = 0;
1837
1838 if (pCtx == NULL) {
1839 ALOGE("%s: Video context info must be supplied", __func__);
1840 ret = VIDEO_ERROR_BADPARAM;
1841 goto EXIT;
1842 }
1843
1844 nBufferCount = 0; /* for clean-up */
1845
1846 memset(&req, 0, sizeof(req));
1847
1848 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1849 req.count = nBufferCount;
1850
1851 if (pCtx->bShareOutbuf == VIDEO_TRUE)
1852 req.memory = pCtx->nMemoryType;
1853 else
1854 req.memory = V4L2_MEMORY_MMAP;
1855
1856 if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) {
1857 ret = VIDEO_ERROR_APIFAIL;
1858 goto EXIT;
1859 }
1860
1861 pCtx->nOutbufs = (int)req.count;
1862
1863 if (pCtx->pOutbuf != NULL) {
1864 free(pCtx->pOutbuf);
1865 pCtx->pOutbuf = NULL;
1866 }
1867
1868EXIT:
1869 return ret;
1870}
1871
3b1c2e30
SK
1872/*
1873 * [Decoder Buffer OPS] FindIndex (Output)
1874 */
1875static int MFC_Decoder_FindEmpty_Outbuf(void *pHandle)
1876{
1877 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1878 int nIndex = -1;
1879
1880 if (pCtx == NULL) {
1881 ALOGE("%s: Video context info must be supplied", __func__);
1882 goto EXIT;
1883 }
1884
1885 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
1886 if ((pCtx->pOutbuf[nIndex].bQueued == VIDEO_FALSE) &&
1887 (pCtx->pOutbuf[nIndex].bSlotUsed == VIDEO_FALSE))
1888 break;
1889 }
1890
1891 if (nIndex == pCtx->nOutbufs)
1892 nIndex = -1;
1893
1894EXIT:
1895 return nIndex;
1896}
1897
1898/*
1899 * [Decoder Buffer OPS] BufferIndexFree (Output)
1900 */
1901void MFC_Decoder_BufferIndexFree_Outbuf(void *pHandle, PrivateDataShareBuffer *pPDSB, int index)
1902{
1903 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1904 int i, j;
1905
1906 ALOGV("De-queue buf.index:%d", index);
1907 ALOGV("pOutbuf fd:%d", pCtx->pOutbuf[index].planes[0].fd);
1908
1909 if (pCtx->pOutbuf[index].nIndexUseCnt == 0) {
1910 pCtx->pOutbuf[index].bSlotUsed = VIDEO_FALSE;
1911 }
1912
1913 for (i = 0; pPDSB->dpbFD[i].fd > -1; i++) {
1914 ALOGV("pPDSB->dpbFD[%d].fd:%d", i, pPDSB->dpbFD[i].fd);
1915 for (j = 0; pCtx->nOutbufs > j; j++)
1916 if (pPDSB->dpbFD[i].fd == pCtx->pOutbuf[j].planes[0].fd) {
1917 if (pCtx->pOutbuf[j].bQueued == VIDEO_FALSE) {
1918 if (pCtx->pOutbuf[j].nIndexUseCnt > 0)
1919 pCtx->pOutbuf[j].nIndexUseCnt--;
1920 } else if(pCtx->pOutbuf[j].bQueued == VIDEO_TRUE) {
1921 if (pCtx->pOutbuf[j].nIndexUseCnt > 1) {
1922 /* The buffer being used as the reference buffer came again. */
1923 pCtx->pOutbuf[j].nIndexUseCnt--;
1924 } else {
1925 /* Reference DPB buffer is internally reused. */
1926 }
1927 }
1928 ALOGV("dec FD:%d, pCtx->pOutbuf[%d].nIndexUseCnt:%d", pPDSB->dpbFD[i].fd, j, pCtx->pOutbuf[j].nIndexUseCnt);
1929 if ((pCtx->pOutbuf[j].nIndexUseCnt == 0) &&
1930 (pCtx->pOutbuf[j].bQueued == VIDEO_FALSE)) {
1931 pCtx->pOutbuf[j].bSlotUsed = VIDEO_FALSE;
1932 }
1933 }
1934 }
1935 memset((char *)pPDSB, -1, sizeof(PrivateDataShareBuffer));
1936
1937 return;
1938}
1939
1940/*
1941 * [Decoder Buffer OPS] ExtensionEnqueue (Output)
1942 */
1943static ExynosVideoErrorType MFC_Decoder_ExtensionEnqueue_Outbuf(
1944 void *pHandle,
1945 unsigned char *pBuffer[],
1946 unsigned int *pFd[],
1947 unsigned int allocLen[],
1948 unsigned int dataSize[],
1949 int nPlanes,
1950 void *pPrivate)
1951{
1952 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1953 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1954 pthread_mutex_t *pMutex = NULL;
1955
1956 struct v4l2_plane planes[VIDEO_DECODER_OUTBUF_PLANES];
1957 struct v4l2_buffer buf;
c01f2434 1958 int state, index, i;
3b1c2e30
SK
1959
1960 if (pCtx == NULL) {
1961 ALOGE("%s: Video context info must be supplied", __func__);
1962 ret = VIDEO_ERROR_BADPARAM;
1963 goto EXIT;
1964 }
1965
1966 if (VIDEO_DECODER_OUTBUF_PLANES < nPlanes) {
1967 ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__,
1968 VIDEO_DECODER_OUTBUF_PLANES, nPlanes);
1969 ret = VIDEO_ERROR_BADPARAM;
1970 goto EXIT;
1971 }
1972
1973 memset(&buf, 0, sizeof(buf));
1974 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1975 buf.m.planes = planes;
1976 buf.length = VIDEO_DECODER_OUTBUF_PLANES;
1977
1978 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
1979 pthread_mutex_lock(pMutex);
1980
1981 index = MFC_Decoder_Find_Outbuf(pCtx, pBuffer[0]);
1982 if (index == -1) {
1983 ALOGV("%s: Failed to find index", __func__);
1984 index = MFC_Decoder_FindEmpty_Outbuf(pCtx);
1985 if (index == -1) {
1986 pthread_mutex_unlock(pMutex);
1987 ALOGE("%s: Failed to get index", __func__);
1988 ret = VIDEO_ERROR_NOBUFFERS;
1989 goto EXIT;
1990 }
1991 }
1992
1993 buf.index = index;
1994 ALOGV("En-queue index:%d pCtx->pOutbuf[buf.index].bQueued:%d, pFd[0]:%d",
1995 index, pCtx->pOutbuf[buf.index].bQueued, pFd[0]);
1996 pCtx->pOutbuf[buf.index].bQueued = VIDEO_TRUE;
1997 pCtx->pOutbuf[buf.index].bSlotUsed = VIDEO_TRUE;
1998
1999 buf.memory = pCtx->nMemoryType;
2000 for (i = 0; i < nPlanes; i++) {
2001 /* V4L2_MEMORY_USERPTR */
2002 buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i];
2003 /* V4L2_MEMORY_DMABUF */
2004 buf.m.planes[i].m.fd = pFd[i];
2005 buf.m.planes[i].length = allocLen[i];
2006 buf.m.planes[i].bytesused = dataSize[i];
2007
2008 /* Temporary storage for Dequeue */
2009 pCtx->pOutbuf[buf.index].planes[i].addr = (unsigned long)pBuffer[i];
2010 pCtx->pOutbuf[buf.index].planes[i].fd = (unsigned int)pFd[i];
2011 pCtx->pOutbuf[buf.index].planes[i].allocSize = allocLen[i];
2012
2013 ALOGV("%s: shared outbuf(%d) plane=%d addr=0x%x fd=%d len=%d used=%d\n",
2014 __func__, index, i,
2015 (void*)buf.m.planes[i].m.userptr, buf.m.planes[i].m.fd,
2016 buf.m.planes[i].length, buf.m.planes[i].bytesused);
2017 }
2018
2019 pCtx->pOutbuf[buf.index].pPrivate = pPrivate;
2020 pCtx->pOutbuf[buf.index].nIndexUseCnt++;
2021
2022 pthread_mutex_unlock(pMutex);
2023
2024 if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) {
3b1c2e30
SK
2025 pthread_mutex_lock(pMutex);
2026 pCtx->pOutbuf[buf.index].nIndexUseCnt--;
2027 pCtx->pOutbuf[buf.index].pPrivate = NULL;
2028 pCtx->pOutbuf[buf.index].bQueued = VIDEO_FALSE;
2029 if (pCtx->pOutbuf[buf.index].nIndexUseCnt == 0)
2030 pCtx->pOutbuf[buf.index].bSlotUsed = VIDEO_FALSE;
c01f2434 2031 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE, &state);
3b1c2e30 2032 pthread_mutex_unlock(pMutex);
c01f2434
SK
2033
2034 if (state == 1) {
2035 /* The case of Resolution is changed */
2036 ret = VIDEO_ERROR_WRONGBUFFERSIZE;
2037 } else {
2038 ALOGE("%s: Failed to enqueue output buffer", __func__);
2039 ret = VIDEO_ERROR_APIFAIL;
2040 }
3b1c2e30
SK
2041 goto EXIT;
2042 }
2043
2044EXIT:
2045 return ret;
2046}
2047
2048/*
2049 * [Decoder Buffer OPS] ExtensionDequeue (Output)
2050 */
2051static ExynosVideoErrorType MFC_Decoder_ExtensionDequeue_Outbuf(
2052 void *pHandle,
2053 ExynosVideoBuffer *pVideoBuffer)
2054{
2055 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
2056 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
2057 pthread_mutex_t *pMutex = NULL;
2058 ExynosVideoBuffer *pOutbuf = NULL;
2059 PrivateDataShareBuffer *pPDSB = NULL;
2060 struct v4l2_buffer buf;
c01f2434 2061 int value, state, i, j;
3b1c2e30
SK
2062
2063 if (pCtx == NULL) {
2064 ALOGE("%s: Video context info must be supplied", __func__);
2065 ret = VIDEO_ERROR_BADPARAM;
2066 goto EXIT;
2067 }
2068
2069 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
2070 pOutbuf = NULL;
2071 ret = VIDEO_ERROR_APIFAIL;
2072 goto EXIT;
2073 }
2074
2075 memset(&buf, 0, sizeof(buf));
2076 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2077
2078 if (pCtx->bShareOutbuf == VIDEO_TRUE)
2079 buf.memory = pCtx->nMemoryType;
2080 else
2081 buf.memory = V4L2_MEMORY_MMAP;
2082
2083 /* HACK: pOutbuf return -1 means DECODING_ONLY for almost cases */
2084 if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) {
2085 pOutbuf = NULL;
2086 ret = VIDEO_ERROR_APIFAIL;
2087 goto EXIT;
2088 }
2089
2090 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
2091 pthread_mutex_lock(pMutex);
2092
2093 pOutbuf = &pCtx->pOutbuf[buf.index];
2094 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS, &value);
2095
2096 switch (value) {
2097 case 0:
2098 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_ONLY;
2099 break;
2100 case 1:
2101 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_DECODING;
2102 break;
2103 case 2:
2104 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_ONLY;
2105 break;
2106 case 3:
c01f2434
SK
2107 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE, &state);
2108 if (state == 1) /* Resolution is changed */
2109 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_CHANGE_RESOL;
2110 else /* Decoding is finished */
2111 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_FINISHED;
3b1c2e30
SK
2112 break;
2113 default:
2114 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_UNKNOWN;
2115 break;
2116 }
2117
2118 switch (buf.flags & (0x7 << 3)) {
2119 case V4L2_BUF_FLAG_KEYFRAME:
2120 pOutbuf->frameType = VIDEO_FRAME_I;
2121 break;
2122 case V4L2_BUF_FLAG_PFRAME:
2123 pOutbuf->frameType = VIDEO_FRAME_P;
2124 break;
2125 case V4L2_BUF_FLAG_BFRAME:
2126 pOutbuf->frameType = VIDEO_FRAME_B;
2127 break;
2128 default:
2129 pOutbuf->frameType = VIDEO_FRAME_OTHERS;
2130 break;
2131 };
2132
2133 pPDSB = ((PrivateDataShareBuffer *)pCtx->nPrivateDataShareAddress) + buf.index;
2134 if (pCtx->pOutbuf[buf.index].bQueued == VIDEO_TRUE) {
2135 memcpy(pVideoBuffer, pOutbuf, sizeof(ExynosVideoBuffer));
2136 memcpy((char *)(&(pVideoBuffer->PDSB)), (char *)pPDSB, sizeof(PrivateDataShareBuffer));
2137 } else {
2138 ret = VIDEO_ERROR_NOBUFFERS;
2139 ALOGV("%s :: %d", __FUNCTION__, __LINE__);
2140 }
2141
2142 pCtx->pOutbuf[buf.index].bQueued = VIDEO_FALSE;
2143 MFC_Decoder_BufferIndexFree_Outbuf(pHandle, pPDSB, buf.index);
2144
2145 pthread_mutex_unlock(pMutex);
2146
2147EXIT:
2148 return ret;
2149}
2150
2151/*
2152 * [Decoder Buffer OPS] Enable Dynamic DPB
2153 */
2154static ExynosVideoErrorType MFC_Decoder_Enable_DynamicDPB(void *pHandle)
2155{
2156 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
2157 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
2158
2159 if (pCtx == NULL) {
2160 ALOGE("%s: Video context info must be supplied", __func__);
2161 ret = VIDEO_ERROR_BADPARAM;
2162 goto EXIT;
2163 }
2164
2165 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC_SET_DYNAMIC_DPB_MODE, 1) != 0) {
2166 ret = VIDEO_ERROR_APIFAIL;
2167 goto EXIT;
2168 }
2169
2170 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC_SET_USER_SHARED_HANDLE, pCtx->nPrivateDataShareFD) != 0) {
2171 ret = VIDEO_ERROR_APIFAIL;
2172 goto EXIT;
2173 }
2174
2175EXIT:
2176 return ret;
2177}
2178
20d3e6e3
JC
2179/*
2180 * [Decoder OPS] Common
2181 */
2182static ExynosVideoDecOps defDecOps = {
38ef2572
JC
2183 .nSize = 0,
2184 .Init = MFC_Decoder_Init,
2185 .Finalize = MFC_Decoder_Finalize,
2186 .Set_DisplayDelay = MFC_Decoder_Set_DisplayDelay,
e8aae8ed 2187 .Set_IFrameDecoding = MFC_Decoder_Set_IFrameDecoding,
38ef2572
JC
2188 .Enable_PackedPB = MFC_Decoder_Enable_PackedPB,
2189 .Enable_LoopFilter = MFC_Decoder_Enable_LoopFilter,
2190 .Enable_SliceMode = MFC_Decoder_Enable_SliceMode,
2191 .Get_ActualBufferCount = MFC_Decoder_Get_ActualBufferCount,
2192 .Set_FrameTag = MFC_Decoder_Set_FrameTag,
2193 .Get_FrameTag = MFC_Decoder_Get_FrameTag,
2194 .Enable_SEIParsing = MFC_Decoder_Enable_SEIParsing,
2195 .Get_FramePackingInfo = MFC_Decoder_Get_FramePackingInfo,
20d3e6e3
JC
2196};
2197
2198/*
2199 * [Decoder Buffer OPS] Input
2200 */
2201static ExynosVideoDecBufferOps defInbufOps = {
38ef2572
JC
2202 .nSize = 0,
2203 .Enable_Cacheable = MFC_Decoder_Enable_Cacheable_Inbuf,
2204 .Set_Shareable = MFC_Decoder_Set_Shareable_Inbuf,
2205 .Get_Buffer = NULL,
2206 .Set_Geometry = MFC_Decoder_Set_Geometry_Inbuf,
2207 .Get_Geometry = NULL,
2208 .Setup = MFC_Decoder_Setup_Inbuf,
2209 .Run = MFC_Decoder_Run_Inbuf,
2210 .Stop = MFC_Decoder_Stop_Inbuf,
2211 .Enqueue = MFC_Decoder_Enqueue_Inbuf,
2212 .Enqueue_All = NULL,
2213 .Dequeue = MFC_Decoder_Dequeue_Inbuf,
2214 .Register = MFC_Decoder_Register_Inbuf,
2215 .Clear_RegisteredBuffer = MFC_Decoder_Clear_RegisteredBuffer_Inbuf,
2216 .Clear_Queue = MFC_Decoder_Clear_Queued_Inbuf,
c01f2434 2217 .Cleanup_Buffer = MFC_Decoder_Cleanup_Buffer_Inbuf,
20d3e6e3
JC
2218};
2219
2220/*
2221 * [Decoder Buffer OPS] Output
2222 */
2223static ExynosVideoDecBufferOps defOutbufOps = {
38ef2572
JC
2224 .nSize = 0,
2225 .Enable_Cacheable = MFC_Decoder_Enable_Cacheable_Outbuf,
2226 .Set_Shareable = MFC_Decoder_Set_Shareable_Outbuf,
2227 .Get_Buffer = MFC_Decoder_Get_Buffer_Outbuf,
2228 .Set_Geometry = MFC_Decoder_Set_Geometry_Outbuf,
2229 .Get_Geometry = MFC_Decoder_Get_Geometry_Outbuf,
2230 .Setup = MFC_Decoder_Setup_Outbuf,
2231 .Run = MFC_Decoder_Run_Outbuf,
2232 .Stop = MFC_Decoder_Stop_Outbuf,
2233 .Enqueue = MFC_Decoder_Enqueue_Outbuf,
30e79fb1 2234 .Enqueue_All = NULL,
38ef2572
JC
2235 .Dequeue = MFC_Decoder_Dequeue_Outbuf,
2236 .Register = MFC_Decoder_Register_Outbuf,
2237 .Clear_RegisteredBuffer = MFC_Decoder_Clear_RegisteredBuffer_Outbuf,
2238 .Clear_Queue = MFC_Decoder_Clear_Queued_Outbuf,
c01f2434 2239 .Cleanup_Buffer = MFC_Decoder_Cleanup_Buffer_Outbuf,
3b1c2e30
SK
2240 .ExtensionEnqueue = MFC_Decoder_ExtensionEnqueue_Outbuf,
2241 .ExtensionDequeue = MFC_Decoder_ExtensionDequeue_Outbuf,
2242 .Enable_DynamicDPB = MFC_Decoder_Enable_DynamicDPB,
20d3e6e3
JC
2243};
2244
2245int Exynos_Video_Register_Decoder(
2246 ExynosVideoDecOps *pDecOps,
2247 ExynosVideoDecBufferOps *pInbufOps,
2248 ExynosVideoDecBufferOps *pOutbufOps)
2249{
2250 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
2251
2252 if ((pDecOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) {
2253 ret = VIDEO_ERROR_BADPARAM;
2254 goto EXIT;
2255 }
2256
2257 defDecOps.nSize = sizeof(defDecOps);
2258 defInbufOps.nSize = sizeof(defInbufOps);
2259 defOutbufOps.nSize = sizeof(defOutbufOps);
2260
2261 memcpy((char *)pDecOps + sizeof(pDecOps->nSize), (char *)&defDecOps + sizeof(defDecOps.nSize),
2262 pDecOps->nSize - sizeof(pDecOps->nSize));
2263
2264 memcpy((char *)pInbufOps + sizeof(pInbufOps->nSize), (char *)&defInbufOps + sizeof(defInbufOps.nSize),
2265 pInbufOps->nSize - sizeof(pInbufOps->nSize));
2266
2267 memcpy((char *)pOutbufOps + sizeof(pOutbufOps->nSize), (char *)&defOutbufOps + sizeof(defOutbufOps.nSize),
2268 pOutbufOps->nSize - sizeof(pOutbufOps->nSize));
2269
2270EXIT:
2271 return ret;
2272}