am f8d511af: exynos_omx: multi_thread: Code clean up.
[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 }
1068
1069 return ret;
1070 }
1071
1072 /*
1073 * [Decoder Buffer OPS] Run (Input)
1074 */
1075 static ExynosVideoErrorType MFC_Decoder_Run_Inbuf(void *pHandle)
1076 {
1077 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1078 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1079
1080 if (pCtx == NULL) {
1081 ALOGE("%s: Video context info must be supplied", __func__);
1082 ret = VIDEO_ERROR_BADPARAM;
1083 goto EXIT;
1084 }
1085
1086 if (pCtx->bStreamonInbuf == VIDEO_FALSE) {
1087 if (exynos_v4l2_streamon(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) {
1088 ALOGE("%s: Failed to streamon for input buffer", __func__);
1089 ret = VIDEO_ERROR_APIFAIL;
1090 goto EXIT;
1091 }
1092 pCtx->bStreamonInbuf = VIDEO_TRUE;
1093 }
1094
1095 EXIT:
1096 return ret;
1097 }
1098
1099 /*
1100 * [Decoder Buffer OPS] Run (Output)
1101 */
1102 static ExynosVideoErrorType MFC_Decoder_Run_Outbuf(void *pHandle)
1103 {
1104 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1105 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1106
1107 if (pCtx == NULL) {
1108 ALOGE("%s: Video context info must be supplied", __func__);
1109 ret = VIDEO_ERROR_BADPARAM;
1110 goto EXIT;
1111 }
1112
1113 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
1114 if (exynos_v4l2_streamon(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) {
1115 ALOGE("%s: Failed to streamon for output buffer", __func__);
1116 ret = VIDEO_ERROR_APIFAIL;
1117 goto EXIT;
1118 }
1119 pCtx->bStreamonOutbuf = VIDEO_TRUE;
1120 }
1121
1122 EXIT:
1123 return ret;
1124 }
1125
1126 /*
1127 * [Decoder Buffer OPS] Stop (Input)
1128 */
1129 static ExynosVideoErrorType MFC_Decoder_Stop_Inbuf(void *pHandle)
1130 {
1131 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1132 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1133 int i = 0;
1134
1135 if (pCtx == NULL) {
1136 ALOGE("%s: Video context info must be supplied", __func__);
1137 ret = VIDEO_ERROR_BADPARAM;
1138 goto EXIT;
1139 }
1140
1141 if (pCtx->bStreamonInbuf == VIDEO_TRUE) {
1142 if (exynos_v4l2_streamoff(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) != 0) {
1143 ALOGE("%s: Failed to streamoff for input buffer", __func__);
1144 ret = VIDEO_ERROR_APIFAIL;
1145 goto EXIT;
1146 }
1147 pCtx->bStreamonInbuf = VIDEO_FALSE;
1148 }
1149
1150 for (i = 0; i < pCtx->nInbufs; i++) {
1151 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
1152 }
1153
1154 EXIT:
1155 return ret;
1156 }
1157
1158 /*
1159 * [Decoder Buffer OPS] Stop (Output)
1160 */
1161 static ExynosVideoErrorType MFC_Decoder_Stop_Outbuf(void *pHandle)
1162 {
1163 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1164 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1165 int i = 0;
1166
1167 if (pCtx == NULL) {
1168 ALOGE("%s: Video context info must be supplied", __func__);
1169 ret = VIDEO_ERROR_BADPARAM;
1170 goto EXIT;
1171 }
1172
1173 if (pCtx->bStreamonOutbuf == VIDEO_TRUE) {
1174 if (exynos_v4l2_streamoff(pCtx->hDec, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) != 0) {
1175 ALOGE("%s: Failed to streamoff for output buffer", __func__);
1176 ret = VIDEO_ERROR_APIFAIL;
1177 goto EXIT;
1178 }
1179 pCtx->bStreamonOutbuf = VIDEO_FALSE;
1180 }
1181
1182 for (i = 0; i < pCtx->nOutbufs; i++) {
1183 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
1184 pCtx->pOutbuf[i].bSlotUsed = VIDEO_FALSE;
1185 pCtx->pOutbuf[i].nIndexUseCnt = 0;
1186 }
1187
1188 EXIT:
1189 return ret;
1190 }
1191
1192 /*
1193 * [Decoder Buffer OPS] Wait (Input)
1194 */
1195 static ExynosVideoErrorType MFC_Decoder_Wait_Inbuf(void *pHandle)
1196 {
1197 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1198 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1199
1200 struct pollfd poll_events;
1201 int poll_state;
1202
1203 if (pCtx == NULL) {
1204 ALOGE("%s: Video context info must be supplied", __func__);
1205 ret = VIDEO_ERROR_BADPARAM;
1206 goto EXIT;
1207 }
1208
1209 poll_events.fd = pCtx->hDec;
1210 poll_events.events = POLLOUT | POLLERR;
1211 poll_events.revents = 0;
1212
1213 do {
1214 poll_state = poll((struct pollfd*)&poll_events, 1, VIDEO_DECODER_POLL_TIMEOUT);
1215 if (poll_state > 0) {
1216 if (poll_events.revents & POLLOUT) {
1217 break;
1218 } else {
1219 ALOGE("%s: Poll return error", __func__);
1220 ret = VIDEO_ERROR_POLL;
1221 break;
1222 }
1223 } else if (poll_state < 0) {
1224 ALOGE("%s: Poll state error", __func__);
1225 ret = VIDEO_ERROR_POLL;
1226 break;
1227 }
1228 } while (poll_state == 0);
1229
1230 EXIT:
1231 return ret;
1232 }
1233
1234 static ExynosVideoErrorType MFC_Decoder_Register_Inbuf(
1235 void *pHandle,
1236 ExynosVideoPlane *planes,
1237 int nPlanes)
1238 {
1239 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1240 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1241 int nIndex, plane;
1242
1243 if ((pCtx == NULL) || (planes == NULL) || (nPlanes != VIDEO_DECODER_INBUF_PLANES)) {
1244 ALOGE("%s: params must be supplied", __func__);
1245 ret = VIDEO_ERROR_BADPARAM;
1246 goto EXIT;
1247 }
1248
1249 for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
1250 if (pCtx->pInbuf[nIndex].bRegistered == VIDEO_FALSE) {
1251 for (plane = 0; plane < nPlanes; plane++) {
1252 pCtx->pInbuf[nIndex].planes[plane].addr = planes[plane].addr;
1253 pCtx->pInbuf[nIndex].planes[plane].allocSize = planes[plane].allocSize;
1254 pCtx->pInbuf[nIndex].planes[plane].fd = planes[plane].fd;
1255 ALOGV("%s: registered buf %d (addr=%p alloc_sz=%ld fd=%d)\n", __func__, nIndex,
1256 planes[plane].addr, planes[plane].allocSize, planes[plane].fd);
1257 }
1258 pCtx->pInbuf[nIndex].bRegistered = VIDEO_TRUE;
1259 break;
1260 }
1261 }
1262
1263 if (nIndex == pCtx->nInbufs) {
1264 ALOGE("%s: can not find non-registered input buffer", __func__);
1265 ret = VIDEO_ERROR_NOBUFFERS;
1266 }
1267
1268 EXIT:
1269 return ret;
1270 }
1271
1272 static ExynosVideoErrorType MFC_Decoder_Register_Outbuf(
1273 void *pHandle,
1274 ExynosVideoPlane *planes,
1275 int nPlanes)
1276 {
1277 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1278 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1279 int nIndex, plane;
1280
1281 if ((pCtx == NULL) || (planes == NULL) || (nPlanes != VIDEO_DECODER_OUTBUF_PLANES)) {
1282 ALOGE("%s: params must be supplied", __func__);
1283 ret = VIDEO_ERROR_BADPARAM;
1284 goto EXIT;
1285 }
1286
1287 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
1288 if (pCtx->pOutbuf[nIndex].bRegistered == VIDEO_FALSE) {
1289 for (plane = 0; plane < nPlanes; plane++) {
1290 pCtx->pOutbuf[nIndex].planes[plane].addr = planes[plane].addr;
1291 pCtx->pOutbuf[nIndex].planes[plane].allocSize = planes[plane].allocSize;
1292 pCtx->pOutbuf[nIndex].planes[plane].fd = planes[plane].fd;
1293 }
1294 pCtx->pOutbuf[nIndex].bRegistered = VIDEO_TRUE;
1295 ALOGV("%s: registered buf %d 0:(addr=%p alloc_sz=%d fd=%d) 1:(addr=%p alloc_sz=%d fd=%d)\n",
1296 __func__, nIndex, planes[0].addr, planes[0].allocSize, planes[0].fd,
1297 planes[1].addr, planes[1].allocSize, planes[1].fd);
1298 break;
1299 }
1300 }
1301
1302 if (nIndex == pCtx->nOutbufs) {
1303 ALOGE("%s: can not find non-registered output buffer", __func__);
1304 ret = VIDEO_ERROR_NOBUFFERS;
1305 }
1306
1307 EXIT:
1308 return ret;
1309 }
1310
1311 static ExynosVideoErrorType MFC_Decoder_Clear_RegisteredBuffer_Inbuf(void *pHandle)
1312 {
1313 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1314 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1315 int nIndex;
1316
1317 if (pCtx == NULL) {
1318 ALOGE("%s: Video context info must be supplied", __func__);
1319 ret = VIDEO_ERROR_BADPARAM;
1320 goto EXIT;
1321 }
1322
1323 for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
1324 pCtx->pInbuf[nIndex].planes[0].addr = NULL;
1325 pCtx->pInbuf[nIndex].bRegistered = VIDEO_FALSE;
1326 }
1327
1328 EXIT:
1329 return ret;
1330 }
1331
1332 static ExynosVideoErrorType MFC_Decoder_Clear_RegisteredBuffer_Outbuf(void *pHandle)
1333 {
1334 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1335 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1336 int nIndex;
1337
1338 if (pCtx == NULL) {
1339 ALOGE("%s: Video context info must be supplied", __func__);
1340 ret = VIDEO_ERROR_BADPARAM;
1341 goto EXIT;
1342 }
1343
1344 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
1345 pCtx->pOutbuf[nIndex].planes[0].addr = NULL;
1346 pCtx->pOutbuf[nIndex].bRegistered = VIDEO_FALSE;
1347 }
1348
1349 EXIT:
1350 return ret;
1351 }
1352
1353 /*
1354 * [Decoder Buffer OPS] Find (Input)
1355 */
1356 static int MFC_Decoder_Find_Inbuf(
1357 void *pHandle,
1358 unsigned char *pBuffer)
1359 {
1360 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1361 int nIndex = -1;
1362
1363 if (pCtx == NULL) {
1364 ALOGE("%s: Video context info must be supplied", __func__);
1365 goto EXIT;
1366 }
1367
1368 for (nIndex = 0; nIndex < pCtx->nInbufs; nIndex++) {
1369 if (pCtx->pInbuf[nIndex].bQueued == VIDEO_FALSE) {
1370 if ((pBuffer == NULL) ||
1371 (pCtx->pInbuf[nIndex].planes[0].addr == pBuffer))
1372 break;
1373 }
1374 }
1375
1376 if (nIndex == pCtx->nInbufs)
1377 nIndex = -1;
1378
1379 EXIT:
1380 return nIndex;
1381 }
1382
1383 /*
1384 * [Decoder Buffer OPS] Find (Outnput)
1385 */
1386 static int MFC_Decoder_Find_Outbuf(
1387 void *pHandle,
1388 unsigned char *pBuffer)
1389 {
1390 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1391 int nIndex = -1;
1392
1393 if (pCtx == NULL) {
1394 ALOGE("%s: Video context info must be supplied", __func__);
1395 goto EXIT;
1396 }
1397
1398 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
1399 if (pCtx->pOutbuf[nIndex].bQueued == VIDEO_FALSE) {
1400 if ((pBuffer == NULL) ||
1401 (pCtx->pOutbuf[nIndex].planes[0].addr == pBuffer))
1402 break;
1403 }
1404 }
1405
1406 if (nIndex == pCtx->nOutbufs)
1407 nIndex = -1;
1408
1409 EXIT:
1410 return nIndex;
1411 }
1412
1413 /*
1414 * [Decoder Buffer OPS] Enqueue (Input)
1415 */
1416 static ExynosVideoErrorType MFC_Decoder_Enqueue_Inbuf(
1417 void *pHandle,
1418 unsigned char *pBuffer[],
1419 unsigned int dataSize[],
1420 int nPlanes,
1421 void *pPrivate)
1422 {
1423 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1424 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1425 pthread_mutex_t *pMutex = NULL;
1426
1427 struct v4l2_plane planes[VIDEO_DECODER_INBUF_PLANES];
1428 struct v4l2_buffer buf;
1429 int index, i;
1430
1431 if (pCtx == NULL) {
1432 ALOGE("%s: Video context info must be supplied", __func__);
1433 ret = VIDEO_ERROR_BADPARAM;
1434 goto EXIT;
1435 }
1436
1437 if (VIDEO_DECODER_INBUF_PLANES < nPlanes) {
1438 ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__,
1439 VIDEO_DECODER_INBUF_PLANES, nPlanes);
1440 ret = VIDEO_ERROR_BADPARAM;
1441 goto EXIT;
1442 }
1443
1444 memset(&buf, 0, sizeof(buf));
1445
1446 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1447 buf.m.planes = planes;
1448 buf.length = VIDEO_DECODER_INBUF_PLANES;
1449
1450 pMutex = (pthread_mutex_t*)pCtx->pInMutex;
1451 pthread_mutex_lock(pMutex);
1452 index = MFC_Decoder_Find_Inbuf(pCtx, pBuffer[0]);
1453 if (index == -1) {
1454 pthread_mutex_unlock(pMutex);
1455 ALOGE("%s: Failed to get index", __func__);
1456 ret = VIDEO_ERROR_NOBUFFERS;
1457 goto EXIT;
1458 }
1459
1460 buf.index = index;
1461 pCtx->pInbuf[buf.index].bQueued = VIDEO_TRUE;
1462
1463 if (pCtx->bShareInbuf == VIDEO_TRUE) {
1464 buf.memory = pCtx->nMemoryType;
1465 for (i = 0; i < nPlanes; i++) {
1466 /* V4L2_MEMORY_USERPTR */
1467 buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i];
1468 /* V4L2_MEMORY_DMABUF */
1469 buf.m.planes[i].m.fd = pCtx->pInbuf[index].planes[i].fd;
1470 buf.m.planes[i].length = pCtx->pInbuf[index].planes[i].allocSize;
1471 buf.m.planes[i].bytesused = dataSize[i];
1472 ALOGV("%s: shared inbuf(%d) plane(%d) addr=%p fd=%d len=%d used=%d\n", __func__,
1473 index, i,
1474 buf.m.planes[i].m.userptr,
1475 buf.m.planes[i].m.fd,
1476 buf.m.planes[i].length,
1477 buf.m.planes[i].bytesused);
1478 }
1479 } else {
1480 buf.memory = V4L2_MEMORY_MMAP;
1481 for (i = 0; i < nPlanes; i++)
1482 buf.m.planes[i].bytesused = dataSize[i];
1483 }
1484
1485 if ((((OMX_BUFFERHEADERTYPE *)pPrivate)->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) {
1486 buf.flags |= V4L2_BUF_FLAG_LAST_FRAME;
1487 ALOGV("%s: OMX_BUFFERFLAG_EOS => LAST_FRAME: 0x%x", __func__,
1488 !!(buf.flags & V4L2_BUF_FLAG_LAST_FRAME));
1489 }
1490
1491 pCtx->pInbuf[buf.index].pPrivate = pPrivate;
1492
1493 pthread_mutex_unlock(pMutex);
1494
1495 if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) {
1496 ALOGE("%s: Failed to enqueue input buffer", __func__);
1497 pthread_mutex_lock(pMutex);
1498 pCtx->pInbuf[buf.index].pPrivate = NULL;
1499 pCtx->pInbuf[buf.index].bQueued = VIDEO_FALSE;
1500 pthread_mutex_unlock(pMutex);
1501 ret = VIDEO_ERROR_APIFAIL;
1502 goto EXIT;
1503 }
1504
1505 EXIT:
1506 return ret;
1507 }
1508
1509 /*
1510 * [Decoder Buffer OPS] Enqueue (Output)
1511 */
1512 static ExynosVideoErrorType MFC_Decoder_Enqueue_Outbuf(
1513 void *pHandle,
1514 unsigned char *pBuffer[],
1515 unsigned int dataSize[],
1516 int nPlanes,
1517 void *pPrivate)
1518 {
1519 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1520 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1521 pthread_mutex_t *pMutex = NULL;
1522
1523 struct v4l2_plane planes[VIDEO_DECODER_OUTBUF_PLANES];
1524 struct v4l2_buffer buf;
1525 int i, index;
1526
1527 if (pCtx == NULL) {
1528 ALOGE("%s: Video context info must be supplied", __func__);
1529 ret = VIDEO_ERROR_BADPARAM;
1530 goto EXIT;
1531 }
1532
1533 if (VIDEO_DECODER_OUTBUF_PLANES < nPlanes) {
1534 ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__,
1535 VIDEO_DECODER_OUTBUF_PLANES, nPlanes);
1536 ret = VIDEO_ERROR_BADPARAM;
1537 goto EXIT;
1538 }
1539
1540 memset(&buf, 0, sizeof(buf));
1541 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1542 buf.m.planes = planes;
1543 buf.length = VIDEO_DECODER_OUTBUF_PLANES;
1544
1545 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
1546 pthread_mutex_lock(pMutex);
1547 index = MFC_Decoder_Find_Outbuf(pCtx, pBuffer[0]);
1548 if (index == -1) {
1549 pthread_mutex_unlock(pMutex);
1550 ALOGE("%s: Failed to get index", __func__);
1551 ret = VIDEO_ERROR_NOBUFFERS;
1552 goto EXIT;
1553 }
1554 buf.index = index;
1555 pCtx->pOutbuf[buf.index].bQueued = VIDEO_TRUE;
1556
1557 if (pCtx->bShareOutbuf == VIDEO_TRUE) {
1558 buf.memory = pCtx->nMemoryType;
1559 for (i = 0; i < nPlanes; i++) {
1560 /* V4L2_MEMORY_USERPTR */
1561 buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i];
1562 /* V4L2_MEMORY_DMABUF */
1563 buf.m.planes[i].m.fd = pCtx->pOutbuf[index].planes[i].fd;
1564 buf.m.planes[i].length = pCtx->pOutbuf[index].planes[i].allocSize;
1565 buf.m.planes[i].bytesused = dataSize[i];
1566 ALOGV("%s: shared outbuf(%d) plane=%d addr=%p fd=%d len=%d used=%d\n", __func__,
1567 index, i,
1568 buf.m.planes[i].m.userptr,
1569 buf.m.planes[i].m.fd,
1570 buf.m.planes[i].length,
1571 buf.m.planes[i].bytesused);
1572 }
1573 } else {
1574 ALOGV("%s: non-shared outbuf(%d)\n", __func__, index);
1575 buf.memory = V4L2_MEMORY_MMAP;
1576 }
1577
1578 pCtx->pOutbuf[buf.index].pPrivate = pPrivate;
1579
1580 pthread_mutex_unlock(pMutex);
1581
1582 if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) {
1583 ALOGE("%s: Failed to enqueue output buffer", __func__);
1584 pthread_mutex_lock(pMutex);
1585 pCtx->pOutbuf[buf.index].pPrivate = NULL;
1586 pCtx->pOutbuf[buf.index].bQueued = VIDEO_FALSE;
1587 pthread_mutex_unlock(pMutex);
1588 ret = VIDEO_ERROR_APIFAIL;
1589 goto EXIT;
1590 }
1591
1592 EXIT:
1593 return ret;
1594 }
1595
1596 /*
1597 * [Decoder Buffer OPS] Dequeue (Input)
1598 */
1599 static ExynosVideoBuffer *MFC_Decoder_Dequeue_Inbuf(void *pHandle)
1600 {
1601 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1602 ExynosVideoBuffer *pInbuf = NULL;
1603 pthread_mutex_t *pMutex = NULL;
1604
1605 struct v4l2_buffer buf;
1606
1607 if (pCtx == NULL) {
1608 ALOGE("%s: Video context info must be supplied", __func__);
1609 goto EXIT;
1610 }
1611
1612 if (pCtx->bStreamonInbuf == VIDEO_FALSE) {
1613 pInbuf = NULL;
1614 goto EXIT;
1615 }
1616
1617 memset(&buf, 0, sizeof(buf));
1618
1619 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1620
1621 if (pCtx->bShareInbuf == VIDEO_TRUE)
1622 buf.memory = pCtx->nMemoryType;
1623 else
1624 buf.memory = V4L2_MEMORY_MMAP;
1625
1626 if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) {
1627 pInbuf = NULL;
1628 goto EXIT;
1629 }
1630
1631 pMutex = (pthread_mutex_t*)pCtx->pInMutex;
1632 pthread_mutex_lock(pMutex);
1633
1634 pInbuf = &pCtx->pInbuf[buf.index];
1635 pCtx->pInbuf[buf.index].bQueued = VIDEO_FALSE;
1636
1637 if (pCtx->bStreamonInbuf == VIDEO_FALSE)
1638 pInbuf = NULL;
1639
1640 pthread_mutex_unlock(pMutex);
1641
1642 EXIT:
1643 return pInbuf;
1644 }
1645
1646 /*
1647 * [Decoder Buffer OPS] Dequeue (Output)
1648 */
1649 static ExynosVideoBuffer *MFC_Decoder_Dequeue_Outbuf(void *pHandle)
1650 {
1651 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1652 ExynosVideoBuffer *pOutbuf = NULL;
1653 pthread_mutex_t *pMutex = NULL;
1654
1655 struct v4l2_buffer buf;
1656 int value;
1657
1658 if (pCtx == NULL) {
1659 ALOGE("%s: Video context info must be supplied", __func__);
1660 goto EXIT;
1661 }
1662
1663 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
1664 pOutbuf = NULL;
1665 goto EXIT;
1666 }
1667
1668 memset(&buf, 0, sizeof(buf));
1669 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1670
1671 if (pCtx->bShareOutbuf == VIDEO_TRUE)
1672 buf.memory = pCtx->nMemoryType;
1673 else
1674 buf.memory = V4L2_MEMORY_MMAP;
1675
1676 /* HACK: pOutbuf return -1 means DECODING_ONLY for almost cases */
1677 if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) {
1678 pOutbuf = NULL;
1679 goto EXIT;
1680 }
1681
1682 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
1683 pOutbuf = NULL;
1684 goto EXIT;
1685 }
1686
1687 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
1688 pthread_mutex_lock(pMutex);
1689
1690 pOutbuf = &pCtx->pOutbuf[buf.index];
1691
1692 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS, &value);
1693
1694 switch (value) {
1695 case 0:
1696 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_ONLY;
1697 break;
1698 case 1:
1699 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_DECODING;
1700 break;
1701 case 2:
1702 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_ONLY;
1703 break;
1704 case 3:
1705 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_CHANGE_RESOL;
1706 break;
1707 default:
1708 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_UNKNOWN;
1709 break;
1710 }
1711
1712 switch (buf.flags & (0x7 << 3)) {
1713 case V4L2_BUF_FLAG_KEYFRAME:
1714 pOutbuf->frameType = VIDEO_FRAME_I;
1715 break;
1716 case V4L2_BUF_FLAG_PFRAME:
1717 pOutbuf->frameType = VIDEO_FRAME_P;
1718 break;
1719 case V4L2_BUF_FLAG_BFRAME:
1720 pOutbuf->frameType = VIDEO_FRAME_B;
1721 break;
1722 default:
1723 pOutbuf->frameType = VIDEO_FRAME_OTHERS;
1724 break;
1725 };
1726
1727 pOutbuf->bQueued = VIDEO_FALSE;
1728
1729 pthread_mutex_unlock(pMutex);
1730
1731 EXIT:
1732 return pOutbuf;
1733 }
1734
1735 static ExynosVideoErrorType MFC_Decoder_Clear_Queued_Inbuf(void *pHandle)
1736 {
1737 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1738 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1739 int i;
1740
1741 if (pCtx == NULL) {
1742 ALOGE("%s: Video context info must be supplied", __func__);
1743 ret = VIDEO_ERROR_BADPARAM;
1744 goto EXIT;
1745 }
1746
1747 for (i = 0; i < pCtx->nInbufs; i++) {
1748 pCtx->pInbuf[i].bQueued = VIDEO_FALSE;
1749 }
1750
1751 EXIT:
1752 return ret;
1753 }
1754
1755 static ExynosVideoErrorType MFC_Decoder_Clear_Queued_Outbuf(void *pHandle)
1756 {
1757 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1758 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1759 int i;
1760
1761 if (pCtx == NULL) {
1762 ALOGE("%s: Video context info must be supplied", __func__);
1763 ret = VIDEO_ERROR_BADPARAM;
1764 goto EXIT;
1765 }
1766
1767 for (i = 0; i < pCtx->nOutbufs; i++) {
1768 pCtx->pOutbuf[i].bQueued = VIDEO_FALSE;
1769 }
1770
1771 EXIT:
1772 return ret;
1773 }
1774
1775 /*
1776 * [Decoder Buffer OPS] FindIndex (Output)
1777 */
1778 static int MFC_Decoder_FindEmpty_Outbuf(void *pHandle)
1779 {
1780 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1781 int nIndex = -1;
1782
1783 if (pCtx == NULL) {
1784 ALOGE("%s: Video context info must be supplied", __func__);
1785 goto EXIT;
1786 }
1787
1788 for (nIndex = 0; nIndex < pCtx->nOutbufs; nIndex++) {
1789 if ((pCtx->pOutbuf[nIndex].bQueued == VIDEO_FALSE) &&
1790 (pCtx->pOutbuf[nIndex].bSlotUsed == VIDEO_FALSE))
1791 break;
1792 }
1793
1794 if (nIndex == pCtx->nOutbufs)
1795 nIndex = -1;
1796
1797 EXIT:
1798 return nIndex;
1799 }
1800
1801 /*
1802 * [Decoder Buffer OPS] BufferIndexFree (Output)
1803 */
1804 void MFC_Decoder_BufferIndexFree_Outbuf(void *pHandle, PrivateDataShareBuffer *pPDSB, int index)
1805 {
1806 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1807 int i, j;
1808
1809 ALOGV("De-queue buf.index:%d", index);
1810 ALOGV("pOutbuf fd:%d", pCtx->pOutbuf[index].planes[0].fd);
1811
1812 if (pCtx->pOutbuf[index].nIndexUseCnt == 0) {
1813 pCtx->pOutbuf[index].bSlotUsed = VIDEO_FALSE;
1814 }
1815
1816 for (i = 0; pPDSB->dpbFD[i].fd > -1; i++) {
1817 ALOGV("pPDSB->dpbFD[%d].fd:%d", i, pPDSB->dpbFD[i].fd);
1818 for (j = 0; pCtx->nOutbufs > j; j++)
1819 if (pPDSB->dpbFD[i].fd == pCtx->pOutbuf[j].planes[0].fd) {
1820 if (pCtx->pOutbuf[j].bQueued == VIDEO_FALSE) {
1821 if (pCtx->pOutbuf[j].nIndexUseCnt > 0)
1822 pCtx->pOutbuf[j].nIndexUseCnt--;
1823 } else if(pCtx->pOutbuf[j].bQueued == VIDEO_TRUE) {
1824 if (pCtx->pOutbuf[j].nIndexUseCnt > 1) {
1825 /* The buffer being used as the reference buffer came again. */
1826 pCtx->pOutbuf[j].nIndexUseCnt--;
1827 } else {
1828 /* Reference DPB buffer is internally reused. */
1829 }
1830 }
1831 ALOGV("dec FD:%d, pCtx->pOutbuf[%d].nIndexUseCnt:%d", pPDSB->dpbFD[i].fd, j, pCtx->pOutbuf[j].nIndexUseCnt);
1832 if ((pCtx->pOutbuf[j].nIndexUseCnt == 0) &&
1833 (pCtx->pOutbuf[j].bQueued == VIDEO_FALSE)) {
1834 pCtx->pOutbuf[j].bSlotUsed = VIDEO_FALSE;
1835 }
1836 }
1837 }
1838 memset((char *)pPDSB, -1, sizeof(PrivateDataShareBuffer));
1839
1840 return;
1841 }
1842
1843 /*
1844 * [Decoder Buffer OPS] ExtensionEnqueue (Output)
1845 */
1846 static ExynosVideoErrorType MFC_Decoder_ExtensionEnqueue_Outbuf(
1847 void *pHandle,
1848 unsigned char *pBuffer[],
1849 unsigned int *pFd[],
1850 unsigned int allocLen[],
1851 unsigned int dataSize[],
1852 int nPlanes,
1853 void *pPrivate)
1854 {
1855 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1856 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1857 pthread_mutex_t *pMutex = NULL;
1858
1859 struct v4l2_plane planes[VIDEO_DECODER_OUTBUF_PLANES];
1860 struct v4l2_buffer buf;
1861 int index, i;
1862
1863 if (pCtx == NULL) {
1864 ALOGE("%s: Video context info must be supplied", __func__);
1865 ret = VIDEO_ERROR_BADPARAM;
1866 goto EXIT;
1867 }
1868
1869 if (VIDEO_DECODER_OUTBUF_PLANES < nPlanes) {
1870 ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__,
1871 VIDEO_DECODER_OUTBUF_PLANES, nPlanes);
1872 ret = VIDEO_ERROR_BADPARAM;
1873 goto EXIT;
1874 }
1875
1876 memset(&buf, 0, sizeof(buf));
1877 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1878 buf.m.planes = planes;
1879 buf.length = VIDEO_DECODER_OUTBUF_PLANES;
1880
1881 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
1882 pthread_mutex_lock(pMutex);
1883
1884 index = MFC_Decoder_Find_Outbuf(pCtx, pBuffer[0]);
1885 if (index == -1) {
1886 ALOGV("%s: Failed to find index", __func__);
1887 index = MFC_Decoder_FindEmpty_Outbuf(pCtx);
1888 if (index == -1) {
1889 pthread_mutex_unlock(pMutex);
1890 ALOGE("%s: Failed to get index", __func__);
1891 ret = VIDEO_ERROR_NOBUFFERS;
1892 goto EXIT;
1893 }
1894 }
1895
1896 buf.index = index;
1897 ALOGV("En-queue index:%d pCtx->pOutbuf[buf.index].bQueued:%d, pFd[0]:%d",
1898 index, pCtx->pOutbuf[buf.index].bQueued, pFd[0]);
1899 pCtx->pOutbuf[buf.index].bQueued = VIDEO_TRUE;
1900 pCtx->pOutbuf[buf.index].bSlotUsed = VIDEO_TRUE;
1901
1902 buf.memory = pCtx->nMemoryType;
1903 for (i = 0; i < nPlanes; i++) {
1904 /* V4L2_MEMORY_USERPTR */
1905 buf.m.planes[i].m.userptr = (unsigned long)pBuffer[i];
1906 /* V4L2_MEMORY_DMABUF */
1907 buf.m.planes[i].m.fd = pFd[i];
1908 buf.m.planes[i].length = allocLen[i];
1909 buf.m.planes[i].bytesused = dataSize[i];
1910
1911 /* Temporary storage for Dequeue */
1912 pCtx->pOutbuf[buf.index].planes[i].addr = (unsigned long)pBuffer[i];
1913 pCtx->pOutbuf[buf.index].planes[i].fd = (unsigned int)pFd[i];
1914 pCtx->pOutbuf[buf.index].planes[i].allocSize = allocLen[i];
1915
1916 ALOGV("%s: shared outbuf(%d) plane=%d addr=0x%x fd=%d len=%d used=%d\n",
1917 __func__, index, i,
1918 (void*)buf.m.planes[i].m.userptr, buf.m.planes[i].m.fd,
1919 buf.m.planes[i].length, buf.m.planes[i].bytesused);
1920 }
1921
1922 pCtx->pOutbuf[buf.index].pPrivate = pPrivate;
1923 pCtx->pOutbuf[buf.index].nIndexUseCnt++;
1924
1925 pthread_mutex_unlock(pMutex);
1926
1927 if (exynos_v4l2_qbuf(pCtx->hDec, &buf) != 0) {
1928 ALOGE("%s: Failed to enqueue output buffer", __func__);
1929 pthread_mutex_lock(pMutex);
1930 pCtx->pOutbuf[buf.index].nIndexUseCnt--;
1931 pCtx->pOutbuf[buf.index].pPrivate = NULL;
1932 pCtx->pOutbuf[buf.index].bQueued = VIDEO_FALSE;
1933 if (pCtx->pOutbuf[buf.index].nIndexUseCnt == 0)
1934 pCtx->pOutbuf[buf.index].bSlotUsed = VIDEO_FALSE;
1935 pthread_mutex_unlock(pMutex);
1936 ret = VIDEO_ERROR_APIFAIL;
1937 goto EXIT;
1938 }
1939
1940 EXIT:
1941 return ret;
1942 }
1943
1944 /*
1945 * [Decoder Buffer OPS] ExtensionDequeue (Output)
1946 */
1947 static ExynosVideoErrorType MFC_Decoder_ExtensionDequeue_Outbuf(
1948 void *pHandle,
1949 ExynosVideoBuffer *pVideoBuffer)
1950 {
1951 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
1952 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
1953 pthread_mutex_t *pMutex = NULL;
1954 ExynosVideoBuffer *pOutbuf = NULL;
1955 PrivateDataShareBuffer *pPDSB = NULL;
1956 struct v4l2_buffer buf;
1957 int value, i, j;
1958
1959 if (pCtx == NULL) {
1960 ALOGE("%s: Video context info must be supplied", __func__);
1961 ret = VIDEO_ERROR_BADPARAM;
1962 goto EXIT;
1963 }
1964
1965 if (pCtx->bStreamonOutbuf == VIDEO_FALSE) {
1966 pOutbuf = NULL;
1967 ret = VIDEO_ERROR_APIFAIL;
1968 goto EXIT;
1969 }
1970
1971 memset(&buf, 0, sizeof(buf));
1972 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1973
1974 if (pCtx->bShareOutbuf == VIDEO_TRUE)
1975 buf.memory = pCtx->nMemoryType;
1976 else
1977 buf.memory = V4L2_MEMORY_MMAP;
1978
1979 /* HACK: pOutbuf return -1 means DECODING_ONLY for almost cases */
1980 if (exynos_v4l2_dqbuf(pCtx->hDec, &buf) != 0) {
1981 pOutbuf = NULL;
1982 ret = VIDEO_ERROR_APIFAIL;
1983 goto EXIT;
1984 }
1985
1986 pMutex = (pthread_mutex_t*)pCtx->pOutMutex;
1987 pthread_mutex_lock(pMutex);
1988
1989 pOutbuf = &pCtx->pOutbuf[buf.index];
1990 exynos_v4l2_g_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS, &value);
1991
1992 switch (value) {
1993 case 0:
1994 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_ONLY;
1995 break;
1996 case 1:
1997 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_DECODING;
1998 break;
1999 case 2:
2000 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_ONLY;
2001 break;
2002 case 3:
2003 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_CHANGE_RESOL;
2004 break;
2005 default:
2006 pOutbuf->displayStatus = VIDEO_FRAME_STATUS_UNKNOWN;
2007 break;
2008 }
2009
2010 switch (buf.flags & (0x7 << 3)) {
2011 case V4L2_BUF_FLAG_KEYFRAME:
2012 pOutbuf->frameType = VIDEO_FRAME_I;
2013 break;
2014 case V4L2_BUF_FLAG_PFRAME:
2015 pOutbuf->frameType = VIDEO_FRAME_P;
2016 break;
2017 case V4L2_BUF_FLAG_BFRAME:
2018 pOutbuf->frameType = VIDEO_FRAME_B;
2019 break;
2020 default:
2021 pOutbuf->frameType = VIDEO_FRAME_OTHERS;
2022 break;
2023 };
2024
2025 pPDSB = ((PrivateDataShareBuffer *)pCtx->nPrivateDataShareAddress) + buf.index;
2026 if (pCtx->pOutbuf[buf.index].bQueued == VIDEO_TRUE) {
2027 memcpy(pVideoBuffer, pOutbuf, sizeof(ExynosVideoBuffer));
2028 memcpy((char *)(&(pVideoBuffer->PDSB)), (char *)pPDSB, sizeof(PrivateDataShareBuffer));
2029 } else {
2030 ret = VIDEO_ERROR_NOBUFFERS;
2031 ALOGV("%s :: %d", __FUNCTION__, __LINE__);
2032 }
2033
2034 pCtx->pOutbuf[buf.index].bQueued = VIDEO_FALSE;
2035 MFC_Decoder_BufferIndexFree_Outbuf(pHandle, pPDSB, buf.index);
2036
2037 pthread_mutex_unlock(pMutex);
2038
2039 EXIT:
2040 return ret;
2041 }
2042
2043 /*
2044 * [Decoder Buffer OPS] Enable Dynamic DPB
2045 */
2046 static ExynosVideoErrorType MFC_Decoder_Enable_DynamicDPB(void *pHandle)
2047 {
2048 ExynosVideoDecContext *pCtx = (ExynosVideoDecContext *)pHandle;
2049 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
2050
2051 if (pCtx == NULL) {
2052 ALOGE("%s: Video context info must be supplied", __func__);
2053 ret = VIDEO_ERROR_BADPARAM;
2054 goto EXIT;
2055 }
2056
2057 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC_SET_DYNAMIC_DPB_MODE, 1) != 0) {
2058 ret = VIDEO_ERROR_APIFAIL;
2059 goto EXIT;
2060 }
2061
2062 if (exynos_v4l2_s_ctrl(pCtx->hDec, V4L2_CID_MPEG_MFC_SET_USER_SHARED_HANDLE, pCtx->nPrivateDataShareFD) != 0) {
2063 ret = VIDEO_ERROR_APIFAIL;
2064 goto EXIT;
2065 }
2066
2067 EXIT:
2068 return ret;
2069 }
2070
2071 /*
2072 * [Decoder OPS] Common
2073 */
2074 static ExynosVideoDecOps defDecOps = {
2075 .nSize = 0,
2076 .Init = MFC_Decoder_Init,
2077 .Finalize = MFC_Decoder_Finalize,
2078 .Set_DisplayDelay = MFC_Decoder_Set_DisplayDelay,
2079 .Set_IFrameDecoding = MFC_Decoder_Set_IFrameDecoding,
2080 .Enable_PackedPB = MFC_Decoder_Enable_PackedPB,
2081 .Enable_LoopFilter = MFC_Decoder_Enable_LoopFilter,
2082 .Enable_SliceMode = MFC_Decoder_Enable_SliceMode,
2083 .Get_ActualBufferCount = MFC_Decoder_Get_ActualBufferCount,
2084 .Set_FrameTag = MFC_Decoder_Set_FrameTag,
2085 .Get_FrameTag = MFC_Decoder_Get_FrameTag,
2086 .Enable_SEIParsing = MFC_Decoder_Enable_SEIParsing,
2087 .Get_FramePackingInfo = MFC_Decoder_Get_FramePackingInfo,
2088 };
2089
2090 /*
2091 * [Decoder Buffer OPS] Input
2092 */
2093 static ExynosVideoDecBufferOps defInbufOps = {
2094 .nSize = 0,
2095 .Enable_Cacheable = MFC_Decoder_Enable_Cacheable_Inbuf,
2096 .Set_Shareable = MFC_Decoder_Set_Shareable_Inbuf,
2097 .Get_Buffer = NULL,
2098 .Set_Geometry = MFC_Decoder_Set_Geometry_Inbuf,
2099 .Get_Geometry = NULL,
2100 .Setup = MFC_Decoder_Setup_Inbuf,
2101 .Run = MFC_Decoder_Run_Inbuf,
2102 .Stop = MFC_Decoder_Stop_Inbuf,
2103 .Enqueue = MFC_Decoder_Enqueue_Inbuf,
2104 .Enqueue_All = NULL,
2105 .Dequeue = MFC_Decoder_Dequeue_Inbuf,
2106 .Register = MFC_Decoder_Register_Inbuf,
2107 .Clear_RegisteredBuffer = MFC_Decoder_Clear_RegisteredBuffer_Inbuf,
2108 .Clear_Queue = MFC_Decoder_Clear_Queued_Inbuf,
2109 };
2110
2111 /*
2112 * [Decoder Buffer OPS] Output
2113 */
2114 static ExynosVideoDecBufferOps defOutbufOps = {
2115 .nSize = 0,
2116 .Enable_Cacheable = MFC_Decoder_Enable_Cacheable_Outbuf,
2117 .Set_Shareable = MFC_Decoder_Set_Shareable_Outbuf,
2118 .Get_Buffer = MFC_Decoder_Get_Buffer_Outbuf,
2119 .Set_Geometry = MFC_Decoder_Set_Geometry_Outbuf,
2120 .Get_Geometry = MFC_Decoder_Get_Geometry_Outbuf,
2121 .Setup = MFC_Decoder_Setup_Outbuf,
2122 .Run = MFC_Decoder_Run_Outbuf,
2123 .Stop = MFC_Decoder_Stop_Outbuf,
2124 .Enqueue = MFC_Decoder_Enqueue_Outbuf,
2125 .Enqueue_All = NULL,
2126 .Dequeue = MFC_Decoder_Dequeue_Outbuf,
2127 .Register = MFC_Decoder_Register_Outbuf,
2128 .Clear_RegisteredBuffer = MFC_Decoder_Clear_RegisteredBuffer_Outbuf,
2129 .Clear_Queue = MFC_Decoder_Clear_Queued_Outbuf,
2130 .ExtensionEnqueue = MFC_Decoder_ExtensionEnqueue_Outbuf,
2131 .ExtensionDequeue = MFC_Decoder_ExtensionDequeue_Outbuf,
2132 .Enable_DynamicDPB = MFC_Decoder_Enable_DynamicDPB,
2133 };
2134
2135 int Exynos_Video_Register_Decoder(
2136 ExynosVideoDecOps *pDecOps,
2137 ExynosVideoDecBufferOps *pInbufOps,
2138 ExynosVideoDecBufferOps *pOutbufOps)
2139 {
2140 ExynosVideoErrorType ret = VIDEO_ERROR_NONE;
2141
2142 if ((pDecOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) {
2143 ret = VIDEO_ERROR_BADPARAM;
2144 goto EXIT;
2145 }
2146
2147 defDecOps.nSize = sizeof(defDecOps);
2148 defInbufOps.nSize = sizeof(defInbufOps);
2149 defOutbufOps.nSize = sizeof(defOutbufOps);
2150
2151 memcpy((char *)pDecOps + sizeof(pDecOps->nSize), (char *)&defDecOps + sizeof(defDecOps.nSize),
2152 pDecOps->nSize - sizeof(pDecOps->nSize));
2153
2154 memcpy((char *)pInbufOps + sizeof(pInbufOps->nSize), (char *)&defInbufOps + sizeof(defInbufOps.nSize),
2155 pInbufOps->nSize - sizeof(pInbufOps->nSize));
2156
2157 memcpy((char *)pOutbufOps + sizeof(pOutbufOps->nSize), (char *)&defOutbufOps + sizeof(defOutbufOps.nSize),
2158 pOutbufOps->nSize - sizeof(pOutbufOps->nSize));
2159
2160 EXIT:
2161 return ret;
2162 }