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
1 /*
2 *
3 * Copyright 2012 Samsung Electronics S.LSI Co. LTD
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
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>
37 #include <pthread.h>
38
39 #include <sys/poll.h>
40
41 #include "ion.h"
42 #include "ExynosVideoApi.h"
43 #include "ExynosVideoDec.h"
44 #include "OMX_Core.h"
45
46 /* #define LOG_NDEBUG 0 */
47 #define LOG_TAG "ExynosVideoDecoder"
48 #include <utils/Log.h>
49
50 #define MAX_OUTPUTBUFFER_COUNT 32
51
52 /*
53 * [Common] __CodingType_To_V4L2PixelFormat
54 */
55 static 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:
79 pixelformat = V4L2_PIX_FMT_MPEG2;
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 */
92 static 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 */
115 static void *MFC_Decoder_Init(int nMemoryType)
116 {
117 ExynosVideoDecContext *pCtx = NULL;
118 pthread_mutex_t *pMutex = NULL;
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) {
123 ALOGE("%s: Failed to allocate decoder context buffer", __func__);
124 goto EXIT_ALLOC_FAIL;
125 }
126
127 memset(pCtx, 0, sizeof(*pCtx));
128
129 pCtx->hDec = exynos_v4l2_open_devname(VIDEO_DECODER_NAME, O_RDWR, 0);
130 if (pCtx->hDec < 0) {
131 ALOGE("%s: Failed to open decoder device", __func__);
132 goto EXIT_OPEN_FAIL;
133 }
134
135 if (!exynos_v4l2_querycap(pCtx->hDec, needCaps)) {
136 ALOGE("%s: Failed to querycap", __func__);
137 goto EXIT_QUERYCAP_FAIL;
138 }
139
140 pCtx->bStreamonInbuf = VIDEO_FALSE;
141 pCtx->bStreamonOutbuf = VIDEO_FALSE;
142
143 pCtx->nMemoryType = nMemoryType;
144
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 }
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 }
161 if (pthread_mutex_init(pMutex, NULL) != 0) {
162 free(pMutex);
163 goto EXIT_QUERYCAP_FAIL;
164 }
165 pCtx->pOutMutex = (void*)pMutex;
166
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
174 return (void *)pCtx;
175
176 EXIT_QUERYCAP_FAIL:
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
187 close(pCtx->hDec);
188
189 EXIT_OPEN_FAIL:
190 free(pCtx);
191
192 EXIT_ALLOC_FAIL:
193 return NULL;
194 }
195
196 /*
197 * [Decoder OPS] Finalize
198 */
199 static ExynosVideoErrorType MFC_Decoder_Finalize(void *pHandle)
200 {
201 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
202 ExynosVideoPlane *pVideoPlane = NULL;
203 pthread_mutex_t *pMutex = NULL;
204 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
205 int i, j;
206
207 if (pCtx == NULL) {
208 ALOGE("%s: Video context info must be supplied", __func__);
209 ret = VIDEO_ERROR_BADPARAM;
210 goto EXIT;
211 }
212
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
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
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;
244 pCtx->pInbuf[i].bRegistered = VIDEO_FALSE;
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;
262 pCtx->pOutbuf[i].bRegistered = VIDEO_FALSE;
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
278 EXIT:
279 return ret;
280 }
281
282 /*
283 * [Decoder OPS] Set Frame Tag
284 */
285 static 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) {
293 ALOGE("%s: Video context info must be supplied", __func__);
294 ret = VIDEO_ERROR_BADPARAM;
295 goto EXIT;
296 }
297
298 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, frameTag) != 0) {
299 ret = VIDEO_ERROR_APIFAIL;
300 goto EXIT;
301 }
302
303 EXIT:
304 return ret;
305 }
306
307 /*
308 * [Decoder OPS] Get Frame Tag
309 */
310 static int MFC_Decoder_Get_FrameTag(void *pHandle)
311 {
312 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
313 int frameTag = -1;
314
315 if (pCtx == NULL) {
316 ALOGE("%s: Video context info must be supplied", __func__);
317 goto EXIT;
318 }
319
320 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, &frameTag);
321
322 EXIT:
323 return frameTag;
324 }
325
326 /*
327 * [Decoder OPS] Get Buffer Count
328 */
329 static int MFC_Decoder_Get_ActualBufferCount(void *pHandle)
330 {
331 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
332 int bufferCount = -1;
333
334 if (pCtx == NULL) {
335 ALOGE("%s: Video context info must be supplied", __func__);
336 goto EXIT;
337 }
338
339 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, &bufferCount);
340
341 EXIT:
342 return bufferCount;
343 }
344
345 /*
346 * [Decoder OPS] Set Display Delay
347 */
348 static 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) {
356 ALOGE("%s: Video context info must be supplied", __func__);
357 ret = VIDEO_ERROR_BADPARAM;
358 goto EXIT;
359 }
360
361 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY, delay) != 0) {
362 ret = VIDEO_ERROR_APIFAIL;
363 goto EXIT;
364 }
365
366 EXIT:
367 return ret;
368 }
369
370 /*
371 * [Decoder OPS] Set I-Frame Decoding
372 */
373 static 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
390 EXIT:
391 return ret;
392 }
393
394 /*
395 * [Decoder OPS] Enable Packed PB
396 */
397 static ExynosVideoErrorType MFC_Decoder_Enable_PackedPB(void *pHandle)
398 {
399 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
400 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
401
402 if (pCtx == NULL) {
403 ALOGE("%s: Video context info must be supplied", __func__);
404 ret = VIDEO_ERROR_BADPARAM;
405 goto EXIT;
406 }
407
408 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_PACKED_PB, 1) != 0) {
409 ret = VIDEO_ERROR_APIFAIL;
410 goto EXIT;
411 }
412
413 EXIT:
414 return ret;
415 }
416
417 /*
418 * [Decoder OPS] Enable Loop Filter
419 */
420 static ExynosVideoErrorType MFC_Decoder_Enable_LoopFilter(void *pHandle)
421 {
422 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
423 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
424
425 if (pCtx == NULL) {
426 ALOGE("%s: Video context info must be supplied", __func__);
427 ret = VIDEO_ERROR_BADPARAM;
428 goto EXIT;
429 }
430
431 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER, 1) != 0) {
432 ret = VIDEO_ERROR_APIFAIL;
433 goto EXIT;
434 }
435
436 EXIT:
437 return ret;
438 }
439
440 /*
441 * [Decoder OPS] Enable Slice Mode
442 */
443 static ExynosVideoErrorType MFC_Decoder_Enable_SliceMode(void *pHandle)
444 {
445 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
446 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
447
448 if (pCtx == NULL) {
449 ALOGE("%s: Video context info must be supplied", __func__);
450 ret = VIDEO_ERROR_BADPARAM;
451 goto EXIT;
452 }
453
454 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE, 1) != 0) {
455 ret = VIDEO_ERROR_APIFAIL;
456 goto EXIT;
457 }
458
459 EXIT:
460 return ret;
461 }
462
463 /*
464 * [Decoder OPS] Enable SEI Parsing
465 */
466 static 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
477 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING, 1) != 0) {
478 ret = VIDEO_ERROR_APIFAIL;
479 goto EXIT;
480 }
481
482 EXIT:
483 return ret;
484 }
485
486 /*
487 * [Decoder OPS] Get Frame Packing information
488 */
489 static 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
503 if ((pCtx == NULL) || (pFramePacking == NULL)) {
504 ALOGE("%s: Video context info or FramePacking pointer must be supplied", __func__);
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
520 if (exynos_v4l2_g_ext_ctrl(pCtx->hDec, &ext_ctrls) != 0) {
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
547 EXIT:
548 return ret;
549 }
550
551 /*
552 * [Decoder Buffer OPS] Enable Cacheable (Input)
553 */
554 static 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
565 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_CACHEABLE, 2) != 0) {
566 ret = VIDEO_ERROR_APIFAIL;
567 goto EXIT;
568 }
569
570 EXIT:
571 return ret;
572 }
573
574 /*
575 * [Decoder Buffer OPS] Enable Cacheable (Output)
576 */
577 static 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
588 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_CACHEABLE, 1) != 0) {
589 ret = VIDEO_ERROR_APIFAIL;
590 goto EXIT;
591 }
592
593 EXIT:
594 return ret;
595 }
596
597 /*
598 * [Decoder Buffer OPS] Set Shareable Buffer (Input)
599 */
600 static 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) {
606 ALOGE("%s: Video context info must be supplied", __func__);
607 ret = VIDEO_ERROR_BADPARAM;
608 goto EXIT;
609 }
610
611 pCtx->bShareInbuf = VIDEO_TRUE;
612
613 EXIT:
614 return ret;
615 }
616
617 /*
618 * [Decoder Buffer OPS] Set Shareable Buffer (Output)
619 */
620 static 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) {
626 ALOGE("%s: Video context info must be supplied", __func__);
627 ret = VIDEO_ERROR_BADPARAM;
628 goto EXIT;
629 }
630
631 pCtx->bShareOutbuf = VIDEO_TRUE;
632
633 EXIT:
634 return ret;
635 }
636
637 /*
638 * [Decoder Buffer OPS] Get Buffer (Input)
639 */
640 static ExynosVideoErrorType MFC_Decoder_Get_Buffer_Inbuf(
641 void *pHandle,
642 int nIndex,
643 ExynosVideoBuffer **pBuffer)
644 {
645 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
646 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
647
648 if (pCtx == NULL) {
649 ALOGE("%s: Video context info must be supplied", __func__);
650 *pBuffer = NULL;
651 ret = VIDEO_ERROR_BADPARAM;
652 goto EXIT;
653 }
654
655 if (pCtx->nInbufs <= nIndex) {
656 *pBuffer = NULL;
657 ret = VIDEO_ERROR_BADPARAM;
658 goto EXIT;
659 }
660
661 *pBuffer = (ExynosVideoBuffer *)&pCtx->pInbuf[nIndex];
662
663 EXIT:
664 return ret;
665 }
666
667 /*
668 * [Decoder Buffer OPS] Get Buffer (Output)
669 */
670 static ExynosVideoErrorType MFC_Decoder_Get_Buffer_Outbuf(
671 void *pHandle,
672 int nIndex,
673 ExynosVideoBuffer **pBuffer)
674 {
675 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
676 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
677
678 if (pCtx == NULL) {
679 ALOGE("%s: Video context info must be supplied", __func__);
680 *pBuffer = NULL;
681 ret = VIDEO_ERROR_BADPARAM;
682 goto EXIT;
683 }
684
685 if (pCtx->nOutbufs <= nIndex) {
686 *pBuffer = NULL;
687 ret = VIDEO_ERROR_BADPARAM;
688 goto EXIT;
689 }
690
691 *pBuffer = (ExynosVideoBuffer *)&pCtx->pOutbuf[nIndex];
692
693 EXIT:
694 return ret;
695 }
696
697 /*
698 * [Decoder Buffer OPS] Set Geometry (Input)
699 */
700 static 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) {
710 ALOGE("%s: Video context info must be supplied", __func__);
711 ret = VIDEO_ERROR_BADPARAM;
712 goto EXIT;
713 }
714
715 if (bufferConf == NULL) {
716 ALOGE("%s: Buffer geometry must be supplied", __func__);
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
727 if (exynos_v4l2_s_fmt(pCtx->hDec, &fmt) != 0) {
728 ret = VIDEO_ERROR_APIFAIL;
729 goto EXIT;
730 }
731
732 memcpy(&pCtx->inbufGeometry, bufferConf, sizeof(pCtx->inbufGeometry));
733
734 EXIT:
735 return ret;
736 }
737
738 /*
739 * [Decoder Buffer OPS] Set Geometry (Output)
740 */
741 static 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) {
751 ALOGE("%s: Video context info must be supplied", __func__);
752 ret = VIDEO_ERROR_BADPARAM;
753 goto EXIT;
754 }
755
756 if (bufferConf == NULL) {
757 ALOGE("%s: Buffer geometry must be supplied", __func__);
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
767 if (exynos_v4l2_s_fmt(pCtx->hDec, &fmt) != 0) {
768 ret = VIDEO_ERROR_APIFAIL;
769 goto EXIT;
770 }
771
772 memcpy(&pCtx->outbufGeometry, bufferConf, sizeof(pCtx->outbufGeometry));
773
774 EXIT:
775 return ret;
776 }
777
778 /*
779 * [Decoder Buffer OPS] Get Geometry (Output)
780 */
781 static 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) {
792 ALOGE("%s: Video context info must be supplied", __func__);
793 ret = VIDEO_ERROR_BADPARAM;
794 goto EXIT;
795 }
796
797 if (bufferConf == NULL) {
798 ALOGE("%s: Buffer geometry must be supplied", __func__);
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;
807 if (exynos_v4l2_g_fmt(pCtx->hDec, &fmt) != 0) {
808 ret = VIDEO_ERROR_APIFAIL;
809 goto EXIT;
810 }
811
812 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
813 if (exynos_v4l2_g_crop(pCtx->hDec, &crop) != 0) {
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
826 EXIT:
827 return ret;
828 }
829
830 /*
831 * [Decoder Buffer OPS] Setup (Input)
832 */
833 static ExynosVideoErrorType MFC_Decoder_Setup_Inbuf(
834 void *pHandle,
835 unsigned int nBufferCount)
836 {
837 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
838 ExynosVideoPlane *pVideoPlane = NULL;
839 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
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) {
847 ALOGE("%s: Video context info must be supplied", __func__);
848 ret = VIDEO_ERROR_BADPARAM;
849 goto EXIT;
850 }
851
852 if (nBufferCount == 0) {
853 ALOGE("%s: Buffer count must be greater than 0", __func__);
854 ret = VIDEO_ERROR_BADPARAM;
855 goto EXIT;
856 }
857
858 ALOGV("%s: setting up inbufs (%d) shared=%s\n", __func__, nBufferCount,
859 pCtx->bShareInbuf ? "true" : "false");
860
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)
867 req.memory = pCtx->nMemoryType;
868 else
869 req.memory = V4L2_MEMORY_MMAP;
870
871 if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) {
872 ret = VIDEO_ERROR_APIFAIL;
873 goto EXIT;
874 }
875
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 }
881
882 pCtx->nInbufs = (int)req.count;
883
884 pCtx->pInbuf = malloc(sizeof(*pCtx->pInbuf) * pCtx->nInbufs);
885 if (pCtx->pInbuf == NULL) {
886 ALOGE("Failed to allocate input buffer context");
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;
902 if (exynos_v4l2_querybuf(pCtx->hDec, &buf) != 0) {
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;
922 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
923 pCtx->pInbuf[i].bRegistered = VIDEO_TRUE;
924 }
925 }
926
927 return ret;
928
929 EXIT:
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 }
938
939 munmap(pVideoPlane->addr, pVideoPlane->allocSize);
940 }
941 }
942
943 free(pCtx->pInbuf);
944 }
945
946 return ret;
947 }
948
949 /*
950 * [Decoder Buffer OPS] Setup (Output)
951 */
952 static ExynosVideoErrorType MFC_Decoder_Setup_Outbuf(
953 void *pHandle,
954 unsigned int nBufferCount)
955 {
956 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
957 ExynosVideoPlane *pVideoPlane = NULL;
958 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
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) {
966 ALOGE("%s: Video context info must be supplied", __func__);
967 ret = VIDEO_ERROR_BADPARAM;
968 goto EXIT;
969 }
970
971 if (nBufferCount == 0) {
972 nBufferCount = MAX_OUTPUTBUFFER_COUNT;
973 ALOGV("%s: Change buffer count %d", __func__, nBufferCount);
974 }
975
976 ALOGV("%s: setting up outbufs (%d) shared=%s\n", __func__, nBufferCount,
977 pCtx->bShareOutbuf ? "true" : "false");
978
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)
985 req.memory = pCtx->nMemoryType;
986 else
987 req.memory = V4L2_MEMORY_MMAP;
988
989 if (exynos_v4l2_reqbufs(pCtx->hDec, &req) != 0) {
990 ret = VIDEO_ERROR_APIFAIL;
991 goto EXIT;
992 }
993
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
1000 pCtx->nOutbufs = req.count;
1001
1002 pCtx->pOutbuf = malloc(sizeof(*pCtx->pOutbuf) * pCtx->nOutbufs);
1003 if (pCtx->pOutbuf == NULL) {
1004 ALOGE("Failed to allocate output buffer context");
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;
1020 if (exynos_v4l2_querybuf(pCtx->hDec, &buf) != 0) {
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;
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;
1045 }
1046 }
1047
1048 return ret;
1049
1050 EXIT:
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 }
1060
1061 munmap(pVideoPlane->addr, pVideoPlane->allocSize);
1062 }
1063 }
1064 }
1065
1066 free(pCtx->pOutbuf);
1067 pCtx->pOutbuf = NULL;
1068 }
1069
1070 return ret;
1071 }
1072
1073 /*
1074 * [Decoder Buffer OPS] Run (Input)
1075 */
1076 static ExynosVideoErrorType MFC_Decoder_Run_Inbuf(void *pHandle)
1077 {
1078 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1079 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1080
1081 if (pCtx == NULL) {
1082 ALOGE("%s: Video context info must be supplied", __func__);
1083 ret = VIDEO_ERROR_BADPARAM;
1084 goto EXIT;
1085 }
1086
1087 if (pCtx->bStreamonInbuf == VIDEO_FALSE) {
1088 if (exynos_v4l2_streamon(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) {
1089 ALOGE("%s: Failed to streamon for input buffer", __func__);
1090 ret = VIDEO_ERROR_APIFAIL;
1091 goto EXIT;
1092 }
1093 pCtx->bStreamonInbuf = VIDEO_TRUE;
1094 }
1095
1096 EXIT:
1097 return ret;
1098 }
1099
1100 /*
1101 * [Decoder Buffer OPS] Run (Output)
1102 */
1103 static ExynosVideoErrorType MFC_Decoder_Run_Outbuf(void *pHandle)
1104 {
1105 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1106 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1107
1108 if (pCtx == NULL) {
1109 ALOGE("%s: Video context info must be supplied", __func__);
1110 ret = VIDEO_ERROR_BADPARAM;
1111 goto EXIT;
1112 }
1113
1114 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
1115 if (exynos_v4l2_streamon(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) {
1116 ALOGE("%s: Failed to streamon for output buffer", __func__);
1117 ret = VIDEO_ERROR_APIFAIL;
1118 goto EXIT;
1119 }
1120 pCtx->bStreamonOutbuf = VIDEO_TRUE;
1121 }
1122
1123 EXIT:
1124 return ret;
1125 }
1126
1127 /*
1128 * [Decoder Buffer OPS] Stop (Input)
1129 */
1130 static ExynosVideoErrorType MFC_Decoder_Stop_Inbuf(void *pHandle)
1131 {
1132 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1133 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1134 int i = 0;
1135
1136 if (pCtx == NULL) {
1137 ALOGE("%s: Video context info must be supplied", __func__);
1138 ret = VIDEO_ERROR_BADPARAM;
1139 goto EXIT;
1140 }
1141
1142 if (pCtx->bStreamonInbuf == VIDEO_TRUE) {
1143 if (exynos_v4l2_streamoff(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) {
1144 ALOGE("%s: Failed to streamoff for input buffer", __func__);
1145 ret = VIDEO_ERROR_APIFAIL;
1146 goto EXIT;
1147 }
1148 pCtx->bStreamonInbuf = VIDEO_FALSE;
1149 }
1150
1151 for (i = 0; i < pCtx->nInbufs; i++) {
1152 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
1153 }
1154
1155 EXIT:
1156 return ret;
1157 }
1158
1159 /*
1160 * [Decoder Buffer OPS] Stop (Output)
1161 */
1162 static ExynosVideoErrorType MFC_Decoder_Stop_Outbuf(void *pHandle)
1163 {
1164 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1165 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1166 int i = 0;
1167
1168 if (pCtx == NULL) {
1169 ALOGE("%s: Video context info must be supplied", __func__);
1170 ret = VIDEO_ERROR_BADPARAM;
1171 goto EXIT;
1172 }
1173
1174 if (pCtx->bStreamonOutbuf == VIDEO_TRUE) {
1175 if (exynos_v4l2_streamoff(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) {
1176 ALOGE("%s: Failed to streamoff for output buffer", __func__);
1177 ret = VIDEO_ERROR_APIFAIL;
1178 goto EXIT;
1179 }
1180 pCtx->bStreamonOutbuf = VIDEO_FALSE;
1181 }
1182
1183 for (i = 0; i < pCtx->nOutbufs; i++) {
1184 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
1185 pCtx->pOutbuf[i].bSlotUsed = VIDEO_FALSE;
1186 pCtx->pOutbuf[i].nIndexUseCnt = 0;
1187 }
1188
1189 EXIT:
1190 return ret;
1191 }
1192
1193 /*
1194 * [Decoder Buffer OPS] Wait (Input)
1195 */
1196 static 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) {
1205 ALOGE("%s: Video context info must be supplied", __func__);
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 {
1220 ALOGE("%s: Poll return error", __func__);
1221 ret = VIDEO_ERROR_POLL;
1222 break;
1223 }
1224 } else if (poll_state < 0) {
1225 ALOGE("%s: Poll state error", __func__);
1226 ret = VIDEO_ERROR_POLL;
1227 break;
1228 }
1229 } while (poll_state == 0);
1230
1231 EXIT:
1232 return ret;
1233 }
1234
1235 static ExynosVideoErrorType MFC_Decoder_Register_Inbuf(
1236 void *pHandle,
1237 ExynosVideoPlane *planes,
1238 int nPlanes)
1239 {
1240 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1241 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1242 int nIndex, plane;
1243
1244 if ((pCtx == NULL) || (planes == NULL) || (nPlanes != VIDEO_DECODER_INBUF_PLANES)) {
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) {
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 }
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
1269 EXIT:
1270 return ret;
1271 }
1272
1273 static ExynosVideoErrorType MFC_Decoder_Register_Outbuf(
1274 void *pHandle,
1275 ExynosVideoPlane *planes,
1276 int nPlanes)
1277 {
1278 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1279 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1280 int nIndex, plane;
1281
1282 if ((pCtx == NULL) || (planes == NULL) || (nPlanes != VIDEO_DECODER_OUTBUF_PLANES)) {
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) {
1290 for (plane = 0; plane < nPlanes; plane++) {
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 }
1295 pCtx->pOutbuf[nIndex].bRegistered = VIDEO_TRUE;
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);
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
1308 EXIT:
1309 return ret;
1310 }
1311
1312 static 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
1329 EXIT:
1330 return ret;
1331 }
1332
1333 static 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
1350 EXIT:
1351 return ret;
1352 }
1353
1354 /*
1355 * [Decoder Buffer OPS] Find (Input)
1356 */
1357 static 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) {
1365 ALOGE("%s: Video context info must be supplied", __func__);
1366 goto EXIT;
1367 }
1368
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))
1373 break;
1374 }
1375 }
1376
1377 if (nIndex == pCtx->nInbufs)
1378 nIndex = -1;
1379
1380 EXIT:
1381 return nIndex;
1382 }
1383
1384 /*
1385 * [Decoder Buffer OPS] Find (Outnput)
1386 */
1387 static 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) {
1395 ALOGE("%s: Video context info must be supplied", __func__);
1396 goto EXIT;
1397 }
1398
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))
1403 break;
1404 }
1405 }
1406
1407 if (nIndex == pCtx->nOutbufs)
1408 nIndex = -1;
1409
1410 EXIT:
1411 return nIndex;
1412 }
1413
1414 /*
1415 * [Decoder Buffer OPS] Enqueue (Input)
1416 */
1417 static 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;
1426 pthread_mutex_t *pMutex = NULL;
1427
1428 struct v4l2_plane planes[VIDEO_DECODER_INBUF_PLANES];
1429 struct v4l2_buffer buf;
1430 int index, i;
1431
1432 if (pCtx == NULL) {
1433 ALOGE("%s: Video context info must be supplied", __func__);
1434 ret = VIDEO_ERROR_BADPARAM;
1435 goto EXIT;
1436 }
1437
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
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
1451 pMutex = (pthread_mutex_t*)pCtx->pInMutex;
1452 pthread_mutex_lock(pMutex);
1453 index = MFC_Decoder_Find_Inbuf(pCtx, pBuffer[0]);
1454 if (index == -1) {
1455 pthread_mutex_unlock(pMutex);
1456 ALOGE("%s: Failed to get index", __func__);
1457 ret = VIDEO_ERROR_NOBUFFERS;
1458 goto EXIT;
1459 }
1460
1461 buf.index = index;
1462 pCtx->pInbuf[buf.index].bQueued = VIDEO_TRUE;
1463
1464 if (pCtx->bShareInbuf == VIDEO_TRUE) {
1465 buf.memory = pCtx->nMemoryType;
1466 for (i = 0; i < nPlanes; i++) {
1467 /* V4L2_MEMORY_USERPTR */
1468 buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i];
1469 /* V4L2_MEMORY_DMABUF */
1470 buf.m.planes[i].m.fd = pCtx->pInbuf[index].planes[i].fd;
1471 buf.m.planes[i].length = pCtx->pInbuf[index].planes[i].allocSize;
1472 buf.m.planes[i].bytesused = dataSize[i];
1473 ALOGV("%s: shared inbuf(%d) plane(%d) addr=%p fd=%d len=%d used=%d\n", __func__,
1474 index, i,
1475 buf.m.planes[i].m.userptr,
1476 buf.m.planes[i].m.fd,
1477 buf.m.planes[i].length,
1478 buf.m.planes[i].bytesused);
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
1486 // FIXME: figure out why |pPrivate| may be NULL.
1487 if (pPrivate &&
1488 (((OMX_BUFFERHEADERTYPE *)pPrivate)->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) {
1489 buf.flags |= V4L2_BUF_FLAG_LAST_FRAME;
1490 ALOGV("%s: OMX_BUFFERFLAG_EOS => LAST_FRAME: 0x%x", __func__,
1491 !!(buf.flags & V4L2_BUF_FLAG_LAST_FRAME));
1492 }
1493
1494 pCtx->pInbuf[buf.index].pPrivate = pPrivate;
1495
1496 pthread_mutex_unlock(pMutex);
1497
1498 if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) {
1499 ALOGE("%s: Failed to enqueue input buffer", __func__);
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);
1504 ret = VIDEO_ERROR_APIFAIL;
1505 goto EXIT;
1506 }
1507
1508 EXIT:
1509 return ret;
1510 }
1511
1512 /*
1513 * [Decoder Buffer OPS] Enqueue (Output)
1514 */
1515 static 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;
1524 pthread_mutex_t *pMutex = NULL;
1525
1526 struct v4l2_plane planes[VIDEO_DECODER_OUTBUF_PLANES];
1527 struct v4l2_buffer buf;
1528 int i, index;
1529
1530 if (pCtx == NULL) {
1531 ALOGE("%s: Video context info must be supplied", __func__);
1532 ret = VIDEO_ERROR_BADPARAM;
1533 goto EXIT;
1534 }
1535
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 }
1542
1543 memset(&buf, 0, sizeof(buf));
1544 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1545 buf.m.planes = planes;
1546 buf.length = VIDEO_DECODER_OUTBUF_PLANES;
1547
1548 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
1549 pthread_mutex_lock(pMutex);
1550 index = MFC_Decoder_Find_Outbuf(pCtx, pBuffer[0]);
1551 if (index == -1) {
1552 pthread_mutex_unlock(pMutex);
1553 ALOGE("%s: Failed to get index", __func__);
1554 ret = VIDEO_ERROR_NOBUFFERS;
1555 goto EXIT;
1556 }
1557 buf.index = index;
1558 pCtx->pOutbuf[buf.index].bQueued = VIDEO_TRUE;
1559
1560 if (pCtx->bShareOutbuf == VIDEO_TRUE) {
1561 buf.memory = pCtx->nMemoryType;
1562 for (i = 0; i < nPlanes; i++) {
1563 /* V4L2_MEMORY_USERPTR */
1564 buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i];
1565 /* V4L2_MEMORY_DMABUF */
1566 buf.m.planes[i].m.fd = pCtx->pOutbuf[index].planes[i].fd;
1567 buf.m.planes[i].length = pCtx->pOutbuf[index].planes[i].allocSize;
1568 buf.m.planes[i].bytesused = dataSize[i];
1569 ALOGV("%s: shared outbuf(%d) plane=%d addr=%p fd=%d len=%d used=%d\n", __func__,
1570 index, i,
1571 buf.m.planes[i].m.userptr,
1572 buf.m.planes[i].m.fd,
1573 buf.m.planes[i].length,
1574 buf.m.planes[i].bytesused);
1575 }
1576 } else {
1577 ALOGV("%s: non-shared outbuf(%d)\n", __func__, index);
1578 buf.memory = V4L2_MEMORY_MMAP;
1579 }
1580
1581 pCtx->pOutbuf[buf.index].pPrivate = pPrivate;
1582
1583 pthread_mutex_unlock(pMutex);
1584
1585 if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) {
1586 ALOGE("%s: Failed to enqueue output buffer", __func__);
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);
1591 ret = VIDEO_ERROR_APIFAIL;
1592 goto EXIT;
1593 }
1594
1595 EXIT:
1596 return ret;
1597 }
1598
1599 /*
1600 * [Decoder Buffer OPS] Dequeue (Input)
1601 */
1602 static ExynosVideoBuffer *MFC_Decoder_Dequeue_Inbuf(void *pHandle)
1603 {
1604 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1605 ExynosVideoBuffer *pInbuf = NULL;
1606 pthread_mutex_t *pMutex = NULL;
1607
1608 struct v4l2_buffer buf;
1609
1610 if (pCtx == NULL) {
1611 ALOGE("%s: Video context info must be supplied", __func__);
1612 goto EXIT;
1613 }
1614
1615 if (pCtx->bStreamonInbuf == VIDEO_FALSE) {
1616 pInbuf = NULL;
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)
1625 buf.memory = pCtx->nMemoryType;
1626 else
1627 buf.memory = V4L2_MEMORY_MMAP;
1628
1629 if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) {
1630 pInbuf = NULL;
1631 goto EXIT;
1632 }
1633
1634 pMutex = (pthread_mutex_t*)pCtx->pInMutex;
1635 pthread_mutex_lock(pMutex);
1636
1637 pInbuf = &pCtx->pInbuf[buf.index];
1638 pCtx->pInbuf[buf.index].bQueued = VIDEO_FALSE;
1639
1640 if (pCtx->bStreamonInbuf == VIDEO_FALSE)
1641 pInbuf = NULL;
1642
1643 pthread_mutex_unlock(pMutex);
1644
1645 EXIT:
1646 return pInbuf;
1647 }
1648
1649 /*
1650 * [Decoder Buffer OPS] Dequeue (Output)
1651 */
1652 static ExynosVideoBuffer *MFC_Decoder_Dequeue_Outbuf(void *pHandle)
1653 {
1654 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1655 ExynosVideoBuffer *pOutbuf = NULL;
1656 pthread_mutex_t *pMutex = NULL;
1657
1658 struct v4l2_buffer buf;
1659 int value, state;
1660
1661 if (pCtx == NULL) {
1662 ALOGE("%s: Video context info must be supplied", __func__);
1663 goto EXIT;
1664 }
1665
1666 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
1667 pOutbuf = NULL;
1668 goto EXIT;
1669 }
1670
1671 memset(&buf, 0, sizeof(buf));
1672 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1673
1674 if (pCtx->bShareOutbuf == VIDEO_TRUE)
1675 buf.memory = pCtx->nMemoryType;
1676 else
1677 buf.memory = V4L2_MEMORY_MMAP;
1678
1679 /* HACK: pOutbuf return -1 means DECODING_ONLY for almost cases */
1680 if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) {
1681 pOutbuf = NULL;
1682 goto EXIT;
1683 }
1684
1685 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
1686 pOutbuf = NULL;
1687 goto EXIT;
1688 }
1689
1690 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
1691 pthread_mutex_lock(pMutex);
1692
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;
1706 break;
1707 case 3:
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;
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
1736 pthread_mutex_unlock(pMutex);
1737
1738 EXIT:
1739 return pOutbuf;
1740 }
1741
1742 static 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
1758 EXIT:
1759 return ret;
1760 }
1761
1762 static 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
1778 EXIT:
1779 return ret;
1780 }
1781
1782 /*
1783 * [Decoder Buffer OPS] Cleanup Buffer (Input)
1784 */
1785 static 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
1823 EXIT:
1824 return ret;
1825 }
1826
1827 /*
1828 * [Decoder Buffer OPS] Cleanup Buffer (Output)
1829 */
1830 static 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
1868 EXIT:
1869 return ret;
1870 }
1871
1872 /*
1873 * [Decoder Buffer OPS] FindIndex (Output)
1874 */
1875 static 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
1894 EXIT:
1895 return nIndex;
1896 }
1897
1898 /*
1899 * [Decoder Buffer OPS] BufferIndexFree (Output)
1900 */
1901 void 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 */
1943 static 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;
1958 int state, index, i;
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) {
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;
2031 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE, &state);
2032 pthread_mutex_unlock(pMutex);
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 }
2041 goto EXIT;
2042 }
2043
2044 EXIT:
2045 return ret;
2046 }
2047
2048 /*
2049 * [Decoder Buffer OPS] ExtensionDequeue (Output)
2050 */
2051 static 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;
2061 int value, state, i, j;
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:
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;
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
2147 EXIT:
2148 return ret;
2149 }
2150
2151 /*
2152 * [Decoder Buffer OPS] Enable Dynamic DPB
2153 */
2154 static 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
2175 EXIT:
2176 return ret;
2177 }
2178
2179 /*
2180 * [Decoder OPS] Common
2181 */
2182 static ExynosVideoDecOps defDecOps = {
2183 .nSize = 0,
2184 .Init = MFC_Decoder_Init,
2185 .Finalize = MFC_Decoder_Finalize,
2186 .Set_DisplayDelay = MFC_Decoder_Set_DisplayDelay,
2187 .Set_IFrameDecoding = MFC_Decoder_Set_IFrameDecoding,
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,
2196 };
2197
2198 /*
2199 * [Decoder Buffer OPS] Input
2200 */
2201 static ExynosVideoDecBufferOps defInbufOps = {
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,
2217 .Cleanup_Buffer = MFC_Decoder_Cleanup_Buffer_Inbuf,
2218 };
2219
2220 /*
2221 * [Decoder Buffer OPS] Output
2222 */
2223 static ExynosVideoDecBufferOps defOutbufOps = {
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,
2234 .Enqueue_All = NULL,
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,
2239 .Cleanup_Buffer = MFC_Decoder_Cleanup_Buffer_Outbuf,
2240 .ExtensionEnqueue = MFC_Decoder_ExtensionEnqueue_Outbuf,
2241 .ExtensionDequeue = MFC_Decoder_ExtensionDequeue_Outbuf,
2242 .Enable_DynamicDPB = MFC_Decoder_Enable_DynamicDPB,
2243 };
2244
2245 int 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
2270 EXIT:
2271 return ret;
2272 }