3 * Copyright 2012 Samsung Electronics S.LSI Co. LTD
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * @file ExynosVideoDecoder.c
21 * @author Jinsung Yang (jsgood.yang@samsung.com)
24 * 2012.01.15: Initial Version
33 #include <sys/types.h>
35 #include <sys/ioctl.h>
41 #include "ExynosVideoApi.h"
42 #include "ExynosVideoDec.h"
45 /* #define LOG_NDEBUG 0 */
46 #define LOG_TAG "ExynosVideoDecoder"
47 #include <utils/Log.h>
50 * [Common] __CodingType_To_V4L2PixelFormat
52 static unsigned int __CodingType_To_V4L2PixelFormat(ExynosVideoCodingType codingType
)
54 unsigned int pixelformat
= V4L2_PIX_FMT_H264
;
57 case VIDEO_CODING_AVC
:
58 pixelformat
= V4L2_PIX_FMT_H264
;
60 case VIDEO_CODING_MPEG4
:
61 pixelformat
= V4L2_PIX_FMT_MPEG4
;
63 case VIDEO_CODING_VP8
:
64 pixelformat
= V4L2_PIX_FMT_VP8
;
66 case VIDEO_CODING_H263
:
67 pixelformat
= V4L2_PIX_FMT_H263
;
69 case VIDEO_CODING_VC1
:
70 pixelformat
= V4L2_PIX_FMT_VC1_ANNEX_G
;
72 case VIDEO_CODING_VC1_RCV
:
73 pixelformat
= V4L2_PIX_FMT_VC1_ANNEX_L
;
75 case VIDEO_CODING_MPEG2
:
76 pixelformat
= V4L2_PIX_FMT_MPEG2
;
79 pixelformat
= V4L2_PIX_FMT_H264
;
87 * [Common] __ColorFormatType_To_V4L2PixelFormat
89 static unsigned int __ColorFormatType_To_V4L2PixelFormat(ExynosVideoColorFormatType colorFormatType
)
91 unsigned int pixelformat
= V4L2_PIX_FMT_NV12M
;
93 switch (colorFormatType
) {
94 case VIDEO_COLORFORMAT_NV12_TILED
:
95 pixelformat
= V4L2_PIX_FMT_NV12MT_16X16
;
97 case VIDEO_COLORFORMAT_NV21
:
98 pixelformat
= V4L2_PIX_FMT_NV21M
;
100 case VIDEO_COLORFORMAT_NV12
:
102 pixelformat
= V4L2_PIX_FMT_NV12M
;
112 static void *MFC_Decoder_Init(int nMemoryType
)
114 ExynosVideoDecContext
*pCtx
= NULL
;
115 pthread_mutex_t
*pMutex
= NULL
;
116 int needCaps
= (V4L2_CAP_VIDEO_CAPTURE
| V4L2_CAP_VIDEO_OUTPUT
| V4L2_CAP_STREAMING
);
118 pCtx
= (ExynosVideoDecContext
*)malloc(sizeof(*pCtx
));
120 ALOGE("%s: Failed to allocate decoder context buffer", __func__
);
121 goto EXIT_ALLOC_FAIL
;
124 memset(pCtx
, 0, sizeof(*pCtx
));
126 pCtx
->hDec
= exynos_v4l2_open_devname(VIDEO_DECODER_NAME
, O_RDWR
, 0);
127 if (pCtx
->hDec
< 0) {
128 ALOGE("%s: Failed to open decoder device", __func__
);
132 if (!exynos_v4l2_querycap(pCtx
->hDec
, needCaps
)) {
133 ALOGE("%s: Failed to querycap", __func__
);
134 goto EXIT_QUERYCAP_FAIL
;
137 pCtx
->bStreamonInbuf
= VIDEO_FALSE
;
138 pCtx
->bStreamonOutbuf
= VIDEO_FALSE
;
140 pCtx
->nMemoryType
= nMemoryType
;
142 pMutex
= (pthread_mutex_t
*)malloc(sizeof(pthread_mutex_t
));
143 if (pMutex
== NULL
) {
144 ALOGE("%s: Failed to allocate mutex about input buffer", __func__
);
145 goto EXIT_QUERYCAP_FAIL
;
147 if (pthread_mutex_init(pMutex
, NULL
) != 0) {
149 goto EXIT_QUERYCAP_FAIL
;
151 pCtx
->pInMutex
= (void*)pMutex
;
153 pMutex
= (pthread_mutex_t
*)malloc(sizeof(pthread_mutex_t
));
154 if (pMutex
== NULL
) {
155 ALOGE("%s: Failed to allocate mutex about output buffer", __func__
);
156 goto EXIT_QUERYCAP_FAIL
;
158 if (pthread_mutex_init(pMutex
, NULL
) != 0) {
160 goto EXIT_QUERYCAP_FAIL
;
162 pCtx
->pOutMutex
= (void*)pMutex
;
167 if (pCtx
->pInMutex
!= NULL
) {
168 pthread_mutex_destroy(pCtx
->pInMutex
);
169 free(pCtx
->pInMutex
);
172 if (pCtx
->pOutMutex
!= NULL
) {
173 pthread_mutex_destroy(pCtx
->pOutMutex
);
174 free(pCtx
->pOutMutex
);
187 * [Decoder OPS] Finalize
189 static ExynosVideoErrorType
MFC_Decoder_Finalize(void *pHandle
)
191 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
192 ExynosVideoPlane
*pVideoPlane
= NULL
;
193 pthread_mutex_t
*pMutex
= NULL
;
194 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
198 ALOGE("%s: Video context info must be supplied", __func__
);
199 ret
= VIDEO_ERROR_BADPARAM
;
203 if (pCtx
->pOutMutex
!= NULL
) {
204 pMutex
= (pthread_mutex_t
*)pCtx
->pOutMutex
;
205 pthread_mutex_destroy(pMutex
);
207 pCtx
->pOutMutex
= NULL
;
210 if (pCtx
->pInMutex
!= NULL
) {
211 pMutex
= (pthread_mutex_t
*)pCtx
->pInMutex
;
212 pthread_mutex_destroy(pMutex
);
214 pCtx
->pInMutex
= NULL
;
217 if (pCtx
->bShareInbuf
== VIDEO_FALSE
) {
218 for (i
= 0; i
< pCtx
->nInbufs
; i
++) {
219 for (j
= 0; j
< VIDEO_DECODER_INBUF_PLANES
; j
++) {
220 pVideoPlane
= &pCtx
->pInbuf
[i
].planes
[j
];
221 if (pVideoPlane
->addr
!= NULL
) {
222 munmap(pVideoPlane
->addr
, pVideoPlane
->allocSize
);
223 pVideoPlane
->addr
= NULL
;
224 pVideoPlane
->allocSize
= 0;
225 pVideoPlane
->dataSize
= 0;
228 pCtx
->pInbuf
[i
].pGeometry
= NULL
;
229 pCtx
->pInbuf
[i
].bQueued
= VIDEO_FALSE
;
230 pCtx
->pInbuf
[i
].bRegistered
= VIDEO_FALSE
;
235 if (pCtx
->bShareOutbuf
== VIDEO_FALSE
) {
236 for (i
= 0; i
< pCtx
->nOutbufs
; i
++) {
237 for (j
= 0; j
< VIDEO_DECODER_OUTBUF_PLANES
; j
++) {
238 pVideoPlane
= &pCtx
->pOutbuf
[i
].planes
[j
];
239 if (pVideoPlane
->addr
!= NULL
) {
240 munmap(pVideoPlane
->addr
, pVideoPlane
->allocSize
);
241 pVideoPlane
->addr
= NULL
;
242 pVideoPlane
->allocSize
= 0;
243 pVideoPlane
->dataSize
= 0;
246 pCtx
->pOutbuf
[i
].pGeometry
= NULL
;
247 pCtx
->pOutbuf
[i
].bQueued
= VIDEO_FALSE
;
248 pCtx
->pOutbuf
[i
].bRegistered
= VIDEO_FALSE
;
253 if (pCtx
->pInbuf
!= NULL
)
256 if (pCtx
->pOutbuf
!= NULL
)
269 * [Decoder OPS] Set Frame Tag
271 static ExynosVideoErrorType
MFC_Decoder_Set_FrameTag(
275 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
276 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
279 ALOGE("%s: Video context info must be supplied", __func__
);
280 ret
= VIDEO_ERROR_BADPARAM
;
284 if (exynos_v4l2_s_ctrl(pCtx
->hDec
, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG
, frameTag
) != 0) {
285 ret
= VIDEO_ERROR_APIFAIL
;
294 * [Decoder OPS] Get Frame Tag
296 static int MFC_Decoder_Get_FrameTag(void *pHandle
)
298 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
302 ALOGE("%s: Video context info must be supplied", __func__
);
306 exynos_v4l2_g_ctrl(pCtx
->hDec
, V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG
, &frameTag
);
313 * [Decoder OPS] Get Buffer Count
315 static int MFC_Decoder_Get_ActualBufferCount(void *pHandle
)
317 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
318 int bufferCount
= -1;
321 ALOGE("%s: Video context info must be supplied", __func__
);
325 exynos_v4l2_g_ctrl(pCtx
->hDec
, V4L2_CID_MIN_BUFFERS_FOR_CAPTURE
, &bufferCount
);
332 * [Decoder OPS] Set Display Delay
334 static ExynosVideoErrorType
MFC_Decoder_Set_DisplayDelay(
338 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
339 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
342 ALOGE("%s: Video context info must be supplied", __func__
);
343 ret
= VIDEO_ERROR_BADPARAM
;
347 if (exynos_v4l2_s_ctrl(pCtx
->hDec
, V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY
, delay
) != 0) {
348 ret
= VIDEO_ERROR_APIFAIL
;
357 * [Decoder OPS] Enable Packed PB
359 static ExynosVideoErrorType
MFC_Decoder_Enable_PackedPB(void *pHandle
)
361 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
362 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
365 ALOGE("%s: Video context info must be supplied", __func__
);
366 ret
= VIDEO_ERROR_BADPARAM
;
370 if (exynos_v4l2_s_ctrl(pCtx
->hDec
, V4L2_CID_MPEG_MFC51_VIDEO_PACKED_PB
, 1) != 0) {
371 ret
= VIDEO_ERROR_APIFAIL
;
380 * [Decoder OPS] Enable Loop Filter
382 static ExynosVideoErrorType
MFC_Decoder_Enable_LoopFilter(void *pHandle
)
384 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
385 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
388 ALOGE("%s: Video context info must be supplied", __func__
);
389 ret
= VIDEO_ERROR_BADPARAM
;
393 if (exynos_v4l2_s_ctrl(pCtx
->hDec
, V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER
, 1) != 0) {
394 ret
= VIDEO_ERROR_APIFAIL
;
403 * [Decoder OPS] Enable Slice Mode
405 static ExynosVideoErrorType
MFC_Decoder_Enable_SliceMode(void *pHandle
)
407 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
408 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
411 ALOGE("%s: Video context info must be supplied", __func__
);
412 ret
= VIDEO_ERROR_BADPARAM
;
416 if (exynos_v4l2_s_ctrl(pCtx
->hDec
, V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE
, 1) != 0) {
417 ret
= VIDEO_ERROR_APIFAIL
;
426 * [Decoder OPS] Enable SEI Parsing
428 static ExynosVideoErrorType
MFC_Decoder_Enable_SEIParsing(void *pHandle
)
430 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
431 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
434 ALOGE("%s: Video context info must be supplied", __func__
);
435 ret
= VIDEO_ERROR_BADPARAM
;
439 if (exynos_v4l2_s_ctrl(pCtx
->hDec
, V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING
, 1) != 0) {
440 ret
= VIDEO_ERROR_APIFAIL
;
449 * [Decoder OPS] Get Frame Packing information
451 static ExynosVideoErrorType
MFC_Decoder_Get_FramePackingInfo(
453 ExynosVideoFramePacking
*pFramePacking
)
455 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
456 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
458 struct v4l2_ext_control ext_ctrl
[FRAME_PACK_SEI_INFO_NUM
];
459 struct v4l2_ext_controls ext_ctrls
;
461 int seiAvailable
, seiInfo
, seiGridPos
, i
;
462 unsigned int seiArgmtId
;
465 if ((pCtx
== NULL
) || (pFramePacking
== NULL
)) {
466 ALOGE("%s: Video context info or FramePacking pointer must be supplied", __func__
);
467 ret
= VIDEO_ERROR_BADPARAM
;
471 memset(pFramePacking
, 0, sizeof(*pFramePacking
));
472 memset(ext_ctrl
, 0, (sizeof(struct v4l2_ext_control
) * FRAME_PACK_SEI_INFO_NUM
));
474 ext_ctrls
.ctrl_class
= V4L2_CTRL_CLASS_MPEG
;
475 ext_ctrls
.count
= FRAME_PACK_SEI_INFO_NUM
;
476 ext_ctrls
.controls
= ext_ctrl
;
477 ext_ctrl
[0].id
= V4L2_CID_MPEG_VIDEO_H264_SEI_FP_AVAIL
;
478 ext_ctrl
[1].id
= V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRGMENT_ID
;
479 ext_ctrl
[2].id
= V4L2_CID_MPEG_VIDEO_H264_SEI_FP_INFO
;
480 ext_ctrl
[3].id
= V4L2_CID_MPEG_VIDEO_H264_SEI_FP_GRID_POS
;
482 if (exynos_v4l2_g_ext_ctrl(pCtx
->hDec
, &ext_ctrls
) != 0) {
483 ret
= VIDEO_ERROR_APIFAIL
;
487 seiAvailable
= ext_ctrl
[0].value
;
488 seiArgmtId
= ext_ctrl
[1].value
;
489 seiInfo
= ext_ctrl
[2].value
;
490 seiGridPos
= ext_ctrl
[3].value
;
492 pFramePacking
->available
= seiAvailable
;
493 pFramePacking
->arrangement_id
= seiArgmtId
;
495 pFramePacking
->arrangement_cancel_flag
= OPERATE_BIT(seiInfo
, 0x1, 0);
496 pFramePacking
->arrangement_type
= OPERATE_BIT(seiInfo
, 0x3f, 1);
497 pFramePacking
->quincunx_sampling_flag
= OPERATE_BIT(seiInfo
, 0x1, 8);
498 pFramePacking
->content_interpretation_type
= OPERATE_BIT(seiInfo
, 0x3f, 9);
499 pFramePacking
->spatial_flipping_flag
= OPERATE_BIT(seiInfo
, 0x1, 15);
500 pFramePacking
->frame0_flipped_flag
= OPERATE_BIT(seiInfo
, 0x1, 16);
501 pFramePacking
->field_views_flag
= OPERATE_BIT(seiInfo
, 0x1, 17);
502 pFramePacking
->current_frame_is_frame0_flag
= OPERATE_BIT(seiInfo
, 0x1, 18);
504 pFramePacking
->frame0_grid_pos_x
= OPERATE_BIT(seiGridPos
, 0xf, 0);
505 pFramePacking
->frame0_grid_pos_y
= OPERATE_BIT(seiGridPos
, 0xf, 4);
506 pFramePacking
->frame1_grid_pos_x
= OPERATE_BIT(seiGridPos
, 0xf, 8);
507 pFramePacking
->frame1_grid_pos_y
= OPERATE_BIT(seiGridPos
, 0xf, 12);
514 * [Decoder Buffer OPS] Enable Cacheable (Input)
516 static ExynosVideoErrorType
MFC_Decoder_Enable_Cacheable_Inbuf(void *pHandle
)
518 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
519 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
522 ALOGE("%s: Video context info must be supplied", __func__
);
523 ret
= VIDEO_ERROR_BADPARAM
;
527 if (exynos_v4l2_s_ctrl(pCtx
->hDec
, V4L2_CID_CACHEABLE
, 2) != 0) {
528 ret
= VIDEO_ERROR_APIFAIL
;
537 * [Decoder Buffer OPS] Enable Cacheable (Output)
539 static ExynosVideoErrorType
MFC_Decoder_Enable_Cacheable_Outbuf(void *pHandle
)
541 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
542 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
545 ALOGE("%s: Video context info must be supplied", __func__
);
546 ret
= VIDEO_ERROR_BADPARAM
;
550 if (exynos_v4l2_s_ctrl(pCtx
->hDec
, V4L2_CID_CACHEABLE
, 1) != 0) {
551 ret
= VIDEO_ERROR_APIFAIL
;
560 * [Decoder Buffer OPS] Set Shareable Buffer (Input)
562 static ExynosVideoErrorType
MFC_Decoder_Set_Shareable_Inbuf(void *pHandle
)
564 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
565 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
568 ALOGE("%s: Video context info must be supplied", __func__
);
569 ret
= VIDEO_ERROR_BADPARAM
;
573 pCtx
->bShareInbuf
= VIDEO_TRUE
;
580 * [Decoder Buffer OPS] Set Shareable Buffer (Output)
582 static ExynosVideoErrorType
MFC_Decoder_Set_Shareable_Outbuf(void *pHandle
)
584 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
585 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
588 ALOGE("%s: Video context info must be supplied", __func__
);
589 ret
= VIDEO_ERROR_BADPARAM
;
593 pCtx
->bShareOutbuf
= VIDEO_TRUE
;
600 * [Decoder Buffer OPS] Get Buffer (Input)
602 static ExynosVideoErrorType
MFC_Decoder_Get_Buffer_Inbuf(
605 ExynosVideoBuffer
**pBuffer
)
607 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
608 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
611 ALOGE("%s: Video context info must be supplied", __func__
);
613 ret
= VIDEO_ERROR_BADPARAM
;
617 if (pCtx
->nInbufs
<= nIndex
) {
619 ret
= VIDEO_ERROR_BADPARAM
;
623 *pBuffer
= (ExynosVideoBuffer
*)&pCtx
->pInbuf
[nIndex
];
630 * [Decoder Buffer OPS] Get Buffer (Output)
632 static ExynosVideoErrorType
MFC_Decoder_Get_Buffer_Outbuf(
635 ExynosVideoBuffer
**pBuffer
)
637 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
638 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
641 ALOGE("%s: Video context info must be supplied", __func__
);
643 ret
= VIDEO_ERROR_BADPARAM
;
647 if (pCtx
->nOutbufs
<= nIndex
) {
649 ret
= VIDEO_ERROR_BADPARAM
;
653 *pBuffer
= (ExynosVideoBuffer
*)&pCtx
->pOutbuf
[nIndex
];
660 * [Decoder Buffer OPS] Set Geometry (Input)
662 static ExynosVideoErrorType
MFC_Decoder_Set_Geometry_Inbuf(
664 ExynosVideoGeometry
*bufferConf
)
666 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
667 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
669 struct v4l2_format fmt
;
672 ALOGE("%s: Video context info must be supplied", __func__
);
673 ret
= VIDEO_ERROR_BADPARAM
;
677 if (bufferConf
== NULL
) {
678 ALOGE("%s: Buffer geometry must be supplied", __func__
);
679 ret
= VIDEO_ERROR_BADPARAM
;
683 memset(&fmt
, 0, sizeof(fmt
));
685 fmt
.type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
;
686 fmt
.fmt
.pix_mp
.pixelformat
= __CodingType_To_V4L2PixelFormat(bufferConf
->eCompressionFormat
);
687 fmt
.fmt
.pix_mp
.plane_fmt
[0].sizeimage
= bufferConf
->nSizeImage
;
689 if (exynos_v4l2_s_fmt(pCtx
->hDec
, &fmt
) != 0) {
690 ret
= VIDEO_ERROR_APIFAIL
;
694 memcpy(&pCtx
->inbufGeometry
, bufferConf
, sizeof(pCtx
->inbufGeometry
));
701 * [Decoder Buffer OPS] Set Geometry (Output)
703 static ExynosVideoErrorType
MFC_Decoder_Set_Geometry_Outbuf(
705 ExynosVideoGeometry
*bufferConf
)
707 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
708 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
710 struct v4l2_format fmt
;
713 ALOGE("%s: Video context info must be supplied", __func__
);
714 ret
= VIDEO_ERROR_BADPARAM
;
718 if (bufferConf
== NULL
) {
719 ALOGE("%s: Buffer geometry must be supplied", __func__
);
720 ret
= VIDEO_ERROR_BADPARAM
;
724 memset(&fmt
, 0, sizeof(fmt
));
726 fmt
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
;
727 fmt
.fmt
.pix_mp
.pixelformat
= __ColorFormatType_To_V4L2PixelFormat(bufferConf
->eColorFormat
);
729 if (exynos_v4l2_s_fmt(pCtx
->hDec
, &fmt
) != 0) {
730 ret
= VIDEO_ERROR_APIFAIL
;
734 memcpy(&pCtx
->outbufGeometry
, bufferConf
, sizeof(pCtx
->outbufGeometry
));
741 * [Decoder Buffer OPS] Get Geometry (Output)
743 static ExynosVideoErrorType
MFC_Decoder_Get_Geometry_Outbuf(
745 ExynosVideoGeometry
*bufferConf
)
747 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
748 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
750 struct v4l2_format fmt
;
751 struct v4l2_crop crop
;
754 ALOGE("%s: Video context info must be supplied", __func__
);
755 ret
= VIDEO_ERROR_BADPARAM
;
759 if (bufferConf
== NULL
) {
760 ALOGE("%s: Buffer geometry must be supplied", __func__
);
761 ret
= VIDEO_ERROR_BADPARAM
;
765 memset(&fmt
, 0, sizeof(fmt
));
766 memset(&crop
, 0, sizeof(crop
));
768 fmt
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
;
769 if (exynos_v4l2_g_fmt(pCtx
->hDec
, &fmt
) != 0) {
770 ret
= VIDEO_ERROR_APIFAIL
;
774 crop
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
;
775 if (exynos_v4l2_g_crop(pCtx
->hDec
, &crop
) != 0) {
776 ret
= VIDEO_ERROR_APIFAIL
;
780 bufferConf
->nFrameWidth
= fmt
.fmt
.pix_mp
.width
;
781 bufferConf
->nFrameHeight
= fmt
.fmt
.pix_mp
.height
;
783 bufferConf
->cropRect
.nTop
= crop
.c
.top
;
784 bufferConf
->cropRect
.nLeft
= crop
.c
.left
;
785 bufferConf
->cropRect
.nWidth
= crop
.c
.width
;
786 bufferConf
->cropRect
.nHeight
= crop
.c
.height
;
793 * [Decoder Buffer OPS] Setup (Input)
795 static ExynosVideoErrorType
MFC_Decoder_Setup_Inbuf(
797 unsigned int nBufferCount
)
799 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
800 ExynosVideoPlane
*pVideoPlane
= NULL
;
801 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
803 struct v4l2_requestbuffers req
;
804 struct v4l2_buffer buf
;
805 struct v4l2_plane planes
[VIDEO_DECODER_INBUF_PLANES
];
809 ALOGE("%s: Video context info must be supplied", __func__
);
810 ret
= VIDEO_ERROR_BADPARAM
;
814 if (nBufferCount
== 0) {
815 ALOGE("%s: Buffer count must be greater than 0", __func__
);
816 ret
= VIDEO_ERROR_BADPARAM
;
820 ALOGV("%s: setting up inbufs (%d) shared=%s\n", __func__
, nBufferCount
,
821 pCtx
->bShareInbuf
? "true" : "false");
823 memset(&req
, 0, sizeof(req
));
825 req
.type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
;
826 req
.count
= nBufferCount
;
828 if (pCtx
->bShareInbuf
== VIDEO_TRUE
)
829 req
.memory
= pCtx
->nMemoryType
;
831 req
.memory
= V4L2_MEMORY_MMAP
;
833 if (exynos_v4l2_reqbufs(pCtx
->hDec
, &req
) != 0) {
834 ret
= VIDEO_ERROR_APIFAIL
;
838 if (req
.count
!= nBufferCount
) {
839 ALOGE("%s: asked for %d, got %d\n", __func__
, nBufferCount
, req
.count
);
840 ret
= VIDEO_ERROR_NOMEM
;
844 pCtx
->nInbufs
= (int)req
.count
;
846 pCtx
->pInbuf
= malloc(sizeof(*pCtx
->pInbuf
) * pCtx
->nInbufs
);
847 if (pCtx
->pInbuf
== NULL
) {
848 ALOGE("Failed to allocate input buffer context");
849 ret
= VIDEO_ERROR_NOMEM
;
852 memset(pCtx
->pInbuf
, 0, sizeof(*pCtx
->pInbuf
) * pCtx
->nInbufs
);
854 memset(&buf
, 0, sizeof(buf
));
856 if (pCtx
->bShareInbuf
== VIDEO_FALSE
) {
857 buf
.type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
;
858 buf
.memory
= V4L2_MEMORY_MMAP
;
859 buf
.m
.planes
= planes
;
860 buf
.length
= VIDEO_DECODER_INBUF_PLANES
;
862 for (i
= 0; i
< pCtx
->nInbufs
; i
++) {
864 if (exynos_v4l2_querybuf(pCtx
->hDec
, &buf
) != 0) {
865 ret
= VIDEO_ERROR_APIFAIL
;
869 pVideoPlane
= &pCtx
->pInbuf
[i
].planes
[0];
871 pVideoPlane
->addr
= mmap(NULL
,
872 buf
.m
.planes
[0].length
, PROT_READ
| PROT_WRITE
,
873 MAP_SHARED
, pCtx
->hDec
, buf
.m
.planes
[0].m
.mem_offset
);
875 if (pVideoPlane
->addr
== MAP_FAILED
) {
876 ret
= VIDEO_ERROR_MAPFAIL
;
880 pVideoPlane
->allocSize
= buf
.m
.planes
[0].length
;
881 pVideoPlane
->dataSize
= 0;
883 pCtx
->pInbuf
[i
].pGeometry
= &pCtx
->inbufGeometry
;
884 pCtx
->pInbuf
[i
].bQueued
= VIDEO_FALSE
;
885 pCtx
->pInbuf
[i
].bRegistered
= VIDEO_TRUE
;
892 if ((pCtx
!= NULL
) && (pCtx
->pInbuf
!= NULL
)) {
893 if (pCtx
->bShareInbuf
== VIDEO_FALSE
) {
894 for (i
= 0; i
< pCtx
->nInbufs
; i
++) {
895 pVideoPlane
= &pCtx
->pInbuf
[i
].planes
[0];
896 if (pVideoPlane
->addr
== MAP_FAILED
) {
897 pVideoPlane
->addr
= NULL
;
901 munmap(pVideoPlane
->addr
, pVideoPlane
->allocSize
);
912 * [Decoder Buffer OPS] Setup (Output)
914 static ExynosVideoErrorType
MFC_Decoder_Setup_Outbuf(
916 unsigned int nBufferCount
)
918 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
919 ExynosVideoPlane
*pVideoPlane
= NULL
;
920 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
922 struct v4l2_requestbuffers req
;
923 struct v4l2_buffer buf
;
924 struct v4l2_plane planes
[VIDEO_DECODER_OUTBUF_PLANES
];
928 ALOGE("%s: Video context info must be supplied", __func__
);
929 ret
= VIDEO_ERROR_BADPARAM
;
933 if (nBufferCount
== 0) {
934 ALOGE("%s: Buffer count must be greater than 0", __func__
);
935 ret
= VIDEO_ERROR_BADPARAM
;
939 ALOGV("%s: setting up outbufs (%d) shared=%s\n", __func__
, nBufferCount
,
940 pCtx
->bShareOutbuf
? "true" : "false");
942 memset(&req
, 0, sizeof(req
));
944 req
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
;
945 req
.count
= nBufferCount
;
947 if (pCtx
->bShareOutbuf
== VIDEO_TRUE
)
948 req
.memory
= pCtx
->nMemoryType
;
950 req
.memory
= V4L2_MEMORY_MMAP
;
952 if (exynos_v4l2_reqbufs(pCtx
->hDec
, &req
) != 0) {
953 ret
= VIDEO_ERROR_APIFAIL
;
957 if (req
.count
!= nBufferCount
) {
958 ALOGE("%s: asked for %d, got %d\n", __func__
, nBufferCount
, req
.count
);
959 ret
= VIDEO_ERROR_NOMEM
;
963 pCtx
->nOutbufs
= req
.count
;
965 pCtx
->pOutbuf
= malloc(sizeof(*pCtx
->pOutbuf
) * pCtx
->nOutbufs
);
966 if (pCtx
->pOutbuf
== NULL
) {
967 ALOGE("Failed to allocate output buffer context");
968 ret
= VIDEO_ERROR_NOMEM
;
971 memset(pCtx
->pOutbuf
, 0, sizeof(*pCtx
->pOutbuf
) * pCtx
->nOutbufs
);
973 memset(&buf
, 0, sizeof(buf
));
975 if (pCtx
->bShareOutbuf
== VIDEO_FALSE
) {
976 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
;
977 buf
.memory
= V4L2_MEMORY_MMAP
;
978 buf
.m
.planes
= planes
;
979 buf
.length
= VIDEO_DECODER_OUTBUF_PLANES
;
981 for (i
= 0; i
< pCtx
->nOutbufs
; i
++) {
983 if (exynos_v4l2_querybuf(pCtx
->hDec
, &buf
) != 0) {
984 ret
= VIDEO_ERROR_APIFAIL
;
988 for (j
= 0; j
< VIDEO_DECODER_OUTBUF_PLANES
; j
++) {
989 pVideoPlane
= &pCtx
->pOutbuf
[i
].planes
[j
];
990 pVideoPlane
->addr
= mmap(NULL
,
991 buf
.m
.planes
[j
].length
, PROT_READ
| PROT_WRITE
,
992 MAP_SHARED
, pCtx
->hDec
, buf
.m
.planes
[j
].m
.mem_offset
);
994 if (pVideoPlane
->addr
== MAP_FAILED
) {
995 ret
= VIDEO_ERROR_MAPFAIL
;
999 pVideoPlane
->allocSize
= buf
.m
.planes
[j
].length
;
1000 pVideoPlane
->dataSize
= 0;
1003 pCtx
->pOutbuf
[i
].pGeometry
= &pCtx
->outbufGeometry
;
1004 pCtx
->pOutbuf
[i
].bQueued
= VIDEO_FALSE
;
1005 pCtx
->pOutbuf
[i
].bRegistered
= VIDEO_TRUE
;
1012 if ((pCtx
!= NULL
) && (pCtx
->pOutbuf
!= NULL
)) {
1013 if (pCtx
->bShareOutbuf
== VIDEO_FALSE
) {
1014 for (i
= 0; i
< pCtx
->nOutbufs
; i
++) {
1015 for (j
= 0; j
< VIDEO_DECODER_OUTBUF_PLANES
; j
++) {
1016 pVideoPlane
= &pCtx
->pOutbuf
[i
].planes
[j
];
1017 if (pVideoPlane
->addr
== MAP_FAILED
) {
1018 pVideoPlane
->addr
= NULL
;
1022 munmap(pVideoPlane
->addr
, pVideoPlane
->allocSize
);
1027 free(pCtx
->pOutbuf
);
1034 * [Decoder Buffer OPS] Run (Input)
1036 static ExynosVideoErrorType
MFC_Decoder_Run_Inbuf(void *pHandle
)
1038 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
1039 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
1042 ALOGE("%s: Video context info must be supplied", __func__
);
1043 ret
= VIDEO_ERROR_BADPARAM
;
1047 if (pCtx
->bStreamonInbuf
== VIDEO_FALSE
) {
1048 if (exynos_v4l2_streamon(pCtx
->hDec
, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
) != 0) {
1049 ALOGE("%s: Failed to streamon for input buffer", __func__
);
1050 ret
= VIDEO_ERROR_APIFAIL
;
1053 pCtx
->bStreamonInbuf
= VIDEO_TRUE
;
1061 * [Decoder Buffer OPS] Run (Output)
1063 static ExynosVideoErrorType
MFC_Decoder_Run_Outbuf(void *pHandle
)
1065 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
1066 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
1069 ALOGE("%s: Video context info must be supplied", __func__
);
1070 ret
= VIDEO_ERROR_BADPARAM
;
1074 if (pCtx
->bStreamonOutbuf
== VIDEO_FALSE
) {
1075 if (exynos_v4l2_streamon(pCtx
->hDec
, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
) != 0) {
1076 ALOGE("%s: Failed to streamon for output buffer", __func__
);
1077 ret
= VIDEO_ERROR_APIFAIL
;
1080 pCtx
->bStreamonOutbuf
= VIDEO_TRUE
;
1088 * [Decoder Buffer OPS] Stop (Input)
1090 static ExynosVideoErrorType
MFC_Decoder_Stop_Inbuf(void *pHandle
)
1092 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
1093 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
1097 ALOGE("%s: Video context info must be supplied", __func__
);
1098 ret
= VIDEO_ERROR_BADPARAM
;
1102 if (pCtx
->bStreamonInbuf
== VIDEO_TRUE
) {
1103 if (exynos_v4l2_streamoff(pCtx
->hDec
, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
) != 0) {
1104 ALOGE("%s: Failed to streamoff for input buffer", __func__
);
1105 ret
= VIDEO_ERROR_APIFAIL
;
1108 pCtx
->bStreamonInbuf
= VIDEO_FALSE
;
1111 for (i
= 0; i
< pCtx
->nInbufs
; i
++) {
1112 pCtx
->pInbuf
[i
].bQueued
= VIDEO_FALSE
;
1120 * [Decoder Buffer OPS] Stop (Output)
1122 static ExynosVideoErrorType
MFC_Decoder_Stop_Outbuf(void *pHandle
)
1124 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
1125 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
1129 ALOGE("%s: Video context info must be supplied", __func__
);
1130 ret
= VIDEO_ERROR_BADPARAM
;
1134 if (pCtx
->bStreamonOutbuf
== VIDEO_TRUE
) {
1135 if (exynos_v4l2_streamoff(pCtx
->hDec
, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
) != 0) {
1136 ALOGE("%s: Failed to streamoff for output buffer", __func__
);
1137 ret
= VIDEO_ERROR_APIFAIL
;
1140 pCtx
->bStreamonOutbuf
= VIDEO_FALSE
;
1143 for (i
= 0; i
< pCtx
->nOutbufs
; i
++) {
1144 pCtx
->pOutbuf
[i
].bQueued
= VIDEO_FALSE
;
1152 * [Decoder Buffer OPS] Wait (Input)
1154 static ExynosVideoErrorType
MFC_Decoder_Wait_Inbuf(void *pHandle
)
1156 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
1157 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
1159 struct pollfd poll_events
;
1163 ALOGE("%s: Video context info must be supplied", __func__
);
1164 ret
= VIDEO_ERROR_BADPARAM
;
1168 poll_events
.fd
= pCtx
->hDec
;
1169 poll_events
.events
= POLLOUT
| POLLERR
;
1170 poll_events
.revents
= 0;
1173 poll_state
= poll((struct pollfd
*)&poll_events
, 1, VIDEO_DECODER_POLL_TIMEOUT
);
1174 if (poll_state
> 0) {
1175 if (poll_events
.revents
& POLLOUT
) {
1178 ALOGE("%s: Poll return error", __func__
);
1179 ret
= VIDEO_ERROR_POLL
;
1182 } else if (poll_state
< 0) {
1183 ALOGE("%s: Poll state error", __func__
);
1184 ret
= VIDEO_ERROR_POLL
;
1187 } while (poll_state
== 0);
1193 static ExynosVideoErrorType
MFC_Decoder_Register_Inbuf(
1195 ExynosVideoPlane
*planes
,
1198 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
1199 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
1202 if ((pCtx
== NULL
) || (planes
== NULL
) || (nPlanes
!= VIDEO_DECODER_INBUF_PLANES
)) {
1203 ALOGE("%s: params must be supplied", __func__
);
1204 ret
= VIDEO_ERROR_BADPARAM
;
1208 for (nIndex
= 0; nIndex
< pCtx
->nInbufs
; nIndex
++) {
1209 if (pCtx
->pInbuf
[nIndex
].bRegistered
== VIDEO_FALSE
) {
1210 for (plane
= 0; plane
< nPlanes
; plane
++) {
1211 pCtx
->pInbuf
[nIndex
].planes
[plane
].addr
= planes
[plane
].addr
;
1212 pCtx
->pInbuf
[nIndex
].planes
[plane
].allocSize
= planes
[plane
].allocSize
;
1213 pCtx
->pInbuf
[nIndex
].planes
[plane
].fd
= planes
[plane
].fd
;
1214 ALOGV("%s: registered buf %d (addr=%p alloc_sz=%ld fd=%d)\n", __func__
, nIndex
,
1215 planes
[plane
].addr
, planes
[plane
].allocSize
, planes
[plane
].fd
);
1217 pCtx
->pInbuf
[nIndex
].bRegistered
= VIDEO_TRUE
;
1222 if (nIndex
== pCtx
->nInbufs
) {
1223 ALOGE("%s: can not find non-registered input buffer", __func__
);
1224 ret
= VIDEO_ERROR_NOBUFFERS
;
1231 static ExynosVideoErrorType
MFC_Decoder_Register_Outbuf(
1233 ExynosVideoPlane
*planes
,
1236 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
1237 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
1240 if ((pCtx
== NULL
) || (planes
== NULL
) || (nPlanes
!= VIDEO_DECODER_OUTBUF_PLANES
)) {
1241 ALOGE("%s: params must be supplied", __func__
);
1242 ret
= VIDEO_ERROR_BADPARAM
;
1246 for (nIndex
= 0; nIndex
< pCtx
->nOutbufs
; nIndex
++) {
1247 if (pCtx
->pOutbuf
[nIndex
].bRegistered
== VIDEO_FALSE
) {
1248 for (plane
= 0; plane
< nPlanes
; plane
++) {
1249 pCtx
->pOutbuf
[nIndex
].planes
[plane
].addr
= planes
[plane
].addr
;
1250 pCtx
->pOutbuf
[nIndex
].planes
[plane
].allocSize
= planes
[plane
].allocSize
;
1251 pCtx
->pOutbuf
[nIndex
].planes
[plane
].fd
= planes
[plane
].fd
;
1253 pCtx
->pOutbuf
[nIndex
].bRegistered
= VIDEO_TRUE
;
1254 ALOGV("%s: registered buf %d 0:(addr=%p alloc_sz=%d fd=%d) 1:(addr=%p alloc_sz=%d fd=%d)\n",
1255 __func__
, nIndex
, planes
[0].addr
, planes
[0].allocSize
, planes
[0].fd
,
1256 planes
[1].addr
, planes
[1].allocSize
, planes
[1].fd
);
1261 if (nIndex
== pCtx
->nOutbufs
) {
1262 ALOGE("%s: can not find non-registered output buffer", __func__
);
1263 ret
= VIDEO_ERROR_NOBUFFERS
;
1270 static ExynosVideoErrorType
MFC_Decoder_Clear_RegisteredBuffer_Inbuf(void *pHandle
)
1272 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
1273 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
1277 ALOGE("%s: Video context info must be supplied", __func__
);
1278 ret
= VIDEO_ERROR_BADPARAM
;
1282 for (nIndex
= 0; nIndex
< pCtx
->nInbufs
; nIndex
++) {
1283 pCtx
->pInbuf
[nIndex
].planes
[0].addr
= NULL
;
1284 pCtx
->pInbuf
[nIndex
].bRegistered
= VIDEO_FALSE
;
1291 static ExynosVideoErrorType
MFC_Decoder_Clear_RegisteredBuffer_Outbuf(void *pHandle
)
1293 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
1294 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
1298 ALOGE("%s: Video context info must be supplied", __func__
);
1299 ret
= VIDEO_ERROR_BADPARAM
;
1303 for (nIndex
= 0; nIndex
< pCtx
->nOutbufs
; nIndex
++) {
1304 pCtx
->pOutbuf
[nIndex
].planes
[0].addr
= NULL
;
1305 pCtx
->pOutbuf
[nIndex
].bRegistered
= VIDEO_FALSE
;
1313 * [Decoder Buffer OPS] Find (Input)
1315 static int MFC_Decoder_Find_Inbuf(
1317 unsigned char *pBuffer
)
1319 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
1323 ALOGE("%s: Video context info must be supplied", __func__
);
1327 for (nIndex
= 0; nIndex
< pCtx
->nInbufs
; nIndex
++) {
1328 if (pCtx
->pInbuf
[nIndex
].bQueued
== VIDEO_FALSE
) {
1329 if ((pBuffer
== NULL
) ||
1330 (pCtx
->pInbuf
[nIndex
].planes
[0].addr
== pBuffer
))
1335 if (nIndex
== pCtx
->nInbufs
)
1343 * [Decoder Buffer OPS] Find (Outnput)
1345 static int MFC_Decoder_Find_Outbuf(
1347 unsigned char *pBuffer
)
1349 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
1353 ALOGE("%s: Video context info must be supplied", __func__
);
1357 for (nIndex
= 0; nIndex
< pCtx
->nOutbufs
; nIndex
++) {
1358 if (pCtx
->pOutbuf
[nIndex
].bQueued
== VIDEO_FALSE
) {
1359 if ((pBuffer
== NULL
) ||
1360 (pCtx
->pOutbuf
[nIndex
].planes
[0].addr
== pBuffer
))
1365 if (nIndex
== pCtx
->nOutbufs
)
1373 * [Decoder Buffer OPS] Enqueue (Input)
1375 static ExynosVideoErrorType
MFC_Decoder_Enqueue_Inbuf(
1377 unsigned char *pBuffer
[],
1378 unsigned int dataSize
[],
1382 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
1383 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
1384 pthread_mutex_t
*pMutex
= NULL
;
1386 struct v4l2_plane planes
[VIDEO_DECODER_INBUF_PLANES
];
1387 struct v4l2_buffer buf
;
1391 ALOGE("%s: Video context info must be supplied", __func__
);
1392 ret
= VIDEO_ERROR_BADPARAM
;
1396 if (VIDEO_DECODER_INBUF_PLANES
< nPlanes
) {
1397 ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__
,
1398 VIDEO_DECODER_INBUF_PLANES
, nPlanes
);
1399 ret
= VIDEO_ERROR_BADPARAM
;
1403 memset(&buf
, 0, sizeof(buf
));
1405 buf
.type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
;
1406 buf
.m
.planes
= planes
;
1407 buf
.length
= VIDEO_DECODER_INBUF_PLANES
;
1409 pMutex
= (pthread_mutex_t
*)pCtx
->pInMutex
;
1410 pthread_mutex_lock(pMutex
);
1411 index
= MFC_Decoder_Find_Inbuf(pCtx
, pBuffer
[0]);
1413 pthread_mutex_unlock(pMutex
);
1414 ALOGE("%s: Failed to get index", __func__
);
1415 ret
= VIDEO_ERROR_NOBUFFERS
;
1420 pCtx
->pInbuf
[buf
.index
].bQueued
= VIDEO_TRUE
;
1421 pthread_mutex_unlock(pMutex
);
1423 if (pCtx
->bShareInbuf
== VIDEO_TRUE
) {
1424 buf
.memory
= pCtx
->nMemoryType
;
1425 for (i
= 0; i
< nPlanes
; i
++) {
1426 /* V4L2_MEMORY_USERPTR */
1427 buf
.m
.planes
[i
].m
.userptr
= (unsigned long)pBuffer
[i
];
1428 /* V4L2_MEMORY_DMABUF */
1429 buf
.m
.planes
[i
].m
.fd
= pCtx
->pInbuf
[index
].planes
[i
].fd
;
1430 buf
.m
.planes
[i
].length
= pCtx
->pInbuf
[index
].planes
[i
].allocSize
;
1431 buf
.m
.planes
[i
].bytesused
= dataSize
[i
];
1432 ALOGV("%s: shared inbuf(%d) plane(%d) addr=%p fd=%d len=%d used=%d\n", __func__
,
1434 buf
.m
.planes
[i
].m
.userptr
,
1435 buf
.m
.planes
[i
].m
.fd
,
1436 buf
.m
.planes
[i
].length
,
1437 buf
.m
.planes
[i
].bytesused
);
1440 buf
.memory
= V4L2_MEMORY_MMAP
;
1441 for (i
= 0; i
< nPlanes
; i
++)
1442 buf
.m
.planes
[i
].bytesused
= dataSize
[i
];
1445 if ((((OMX_BUFFERHEADERTYPE
*)pPrivate
)->nFlags
& OMX_BUFFERFLAG_EOS
) == OMX_BUFFERFLAG_EOS
) {
1446 buf
.flags
|= V4L2_BUF_FLAG_LAST_FRAME
;
1447 ALOGD("%s: OMX_BUFFERFLAG_EOS => LAST_FRAME: 0x%x", __func__
,
1448 !!(buf
.flags
& V4L2_BUF_FLAG_LAST_FRAME
));
1451 if (exynos_v4l2_qbuf(pCtx
->hDec
, &buf
) != 0) {
1452 ALOGE("%s: Failed to enqueue input buffer", __func__
);
1453 pCtx
->pInbuf
[buf
.index
].bQueued
= VIDEO_FALSE
;
1454 ret
= VIDEO_ERROR_APIFAIL
;
1458 pCtx
->pInbuf
[buf
.index
].pPrivate
= pPrivate
;
1465 * [Decoder Buffer OPS] Enqueue (Output)
1467 static ExynosVideoErrorType
MFC_Decoder_Enqueue_Outbuf(
1469 unsigned char *pBuffer
[],
1470 unsigned int dataSize
[],
1474 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
1475 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
1476 pthread_mutex_t
*pMutex
= NULL
;
1478 struct v4l2_plane planes
[VIDEO_DECODER_OUTBUF_PLANES
];
1479 struct v4l2_buffer buf
;
1483 ALOGE("%s: Video context info must be supplied", __func__
);
1484 ret
= VIDEO_ERROR_BADPARAM
;
1488 if (VIDEO_DECODER_OUTBUF_PLANES
< nPlanes
) {
1489 ALOGE("%s: Number of max planes : %d, nPlanes : %d", __func__
,
1490 VIDEO_DECODER_OUTBUF_PLANES
, nPlanes
);
1491 ret
= VIDEO_ERROR_BADPARAM
;
1495 memset(&buf
, 0, sizeof(buf
));
1496 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
;
1497 buf
.m
.planes
= planes
;
1498 buf
.length
= VIDEO_DECODER_OUTBUF_PLANES
;
1500 pMutex
= (pthread_mutex_t
*)pCtx
->pOutMutex
;
1501 pthread_mutex_lock(pMutex
);
1502 index
= MFC_Decoder_Find_Outbuf(pCtx
, pBuffer
[0]);
1504 pthread_mutex_unlock(pMutex
);
1505 ALOGE("%s: Failed to get index", __func__
);
1506 ret
= VIDEO_ERROR_NOBUFFERS
;
1510 pCtx
->pOutbuf
[buf
.index
].bQueued
= VIDEO_TRUE
;
1511 pthread_mutex_unlock(pMutex
);
1513 if (pCtx
->bShareOutbuf
== VIDEO_TRUE
) {
1514 buf
.memory
= pCtx
->nMemoryType
;
1515 for (i
= 0; i
< nPlanes
; i
++) {
1516 /* V4L2_MEMORY_USERPTR */
1517 buf
.m
.planes
[i
].m
.userptr
= (unsigned long)pBuffer
[i
];
1518 /* V4L2_MEMORY_DMABUF */
1519 buf
.m
.planes
[i
].m
.fd
= pCtx
->pOutbuf
[index
].planes
[i
].fd
;
1520 buf
.m
.planes
[i
].length
= pCtx
->pOutbuf
[index
].planes
[i
].allocSize
;
1521 buf
.m
.planes
[i
].bytesused
= dataSize
[i
];
1522 ALOGV("%s: shared outbuf(%d) plane=%d addr=%p fd=%d len=%d used=%d\n", __func__
,
1524 buf
.m
.planes
[i
].m
.userptr
,
1525 buf
.m
.planes
[i
].m
.fd
,
1526 buf
.m
.planes
[i
].length
,
1527 buf
.m
.planes
[i
].bytesused
);
1530 ALOGV("%s: non-shared outbuf(%d)\n", __func__
, index
);
1531 buf
.memory
= V4L2_MEMORY_MMAP
;
1534 if (exynos_v4l2_qbuf(pCtx
->hDec
, &buf
) != 0) {
1535 ALOGE("%s: Failed to enqueue output buffer", __func__
);
1536 pCtx
->pOutbuf
[buf
.index
].bQueued
= VIDEO_FALSE
;
1537 ret
= VIDEO_ERROR_APIFAIL
;
1541 pCtx
->pOutbuf
[buf
.index
].pPrivate
= pPrivate
;
1548 * [Decoder Buffer OPS] Dequeue (Input)
1550 static ExynosVideoBuffer
*MFC_Decoder_Dequeue_Inbuf(void *pHandle
)
1552 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
1553 ExynosVideoBuffer
*pInbuf
= NULL
;
1555 struct v4l2_buffer buf
;
1558 ALOGE("%s: Video context info must be supplied", __func__
);
1562 if (pCtx
->bStreamonInbuf
== VIDEO_FALSE
) {
1567 memset(&buf
, 0, sizeof(buf
));
1569 buf
.type
= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
;
1571 if (pCtx
->bShareInbuf
== VIDEO_TRUE
)
1572 buf
.memory
= pCtx
->nMemoryType
;
1574 buf
.memory
= V4L2_MEMORY_MMAP
;
1576 if (exynos_v4l2_dqbuf(pCtx
->hDec
, &buf
) != 0) {
1581 pInbuf
= &pCtx
->pInbuf
[buf
.index
];
1582 pCtx
->pInbuf
[buf
.index
].bQueued
= VIDEO_FALSE
;
1584 if (pCtx
->bStreamonInbuf
== VIDEO_FALSE
)
1592 * [Decoder Buffer OPS] Dequeue (Output)
1594 static ExynosVideoBuffer
*MFC_Decoder_Dequeue_Outbuf(void *pHandle
)
1596 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
1597 ExynosVideoBuffer
*pOutbuf
= NULL
;
1599 struct v4l2_buffer buf
;
1603 ALOGE("%s: Video context info must be supplied", __func__
);
1607 if (pCtx
->bStreamonOutbuf
== VIDEO_FALSE
) {
1612 memset(&buf
, 0, sizeof(buf
));
1613 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
;
1615 if (pCtx
->bShareOutbuf
== VIDEO_TRUE
)
1616 buf
.memory
= pCtx
->nMemoryType
;
1618 buf
.memory
= V4L2_MEMORY_MMAP
;
1620 /* HACK: pOutbuf return -1 means DECODING_ONLY for almost cases */
1621 if (exynos_v4l2_dqbuf(pCtx
->hDec
, &buf
) != 0) {
1626 if (pCtx
->bStreamonOutbuf
== VIDEO_FALSE
) {
1631 pOutbuf
= &pCtx
->pOutbuf
[buf
.index
];
1633 exynos_v4l2_g_ctrl(pCtx
->hDec
, V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS
, &value
);
1637 pOutbuf
->displayStatus
= VIDEO_FRAME_STATUS_DECODING_ONLY
;
1640 pOutbuf
->displayStatus
= VIDEO_FRAME_STATUS_DISPLAY_DECODING
;
1643 pOutbuf
->displayStatus
= VIDEO_FRAME_STATUS_DISPLAY_ONLY
;
1646 pOutbuf
->displayStatus
= VIDEO_FRAME_STATUS_CHANGE_RESOL
;
1649 pOutbuf
->displayStatus
= VIDEO_FRAME_STATUS_UNKNOWN
;
1653 switch (buf
.flags
& (0x7 << 3)) {
1654 case V4L2_BUF_FLAG_KEYFRAME
:
1655 pOutbuf
->frameType
= VIDEO_FRAME_I
;
1657 case V4L2_BUF_FLAG_PFRAME
:
1658 pOutbuf
->frameType
= VIDEO_FRAME_P
;
1660 case V4L2_BUF_FLAG_BFRAME
:
1661 pOutbuf
->frameType
= VIDEO_FRAME_B
;
1664 pOutbuf
->frameType
= VIDEO_FRAME_OTHERS
;
1668 pOutbuf
->bQueued
= VIDEO_FALSE
;
1674 static ExynosVideoErrorType
MFC_Decoder_Clear_Queued_Inbuf(void *pHandle
)
1676 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
1677 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
1681 ALOGE("%s: Video context info must be supplied", __func__
);
1682 ret
= VIDEO_ERROR_BADPARAM
;
1686 for (i
= 0; i
< pCtx
->nInbufs
; i
++) {
1687 pCtx
->pInbuf
[i
].bQueued
= VIDEO_FALSE
;
1694 static ExynosVideoErrorType
MFC_Decoder_Clear_Queued_Outbuf(void *pHandle
)
1696 ExynosVideoDecContext
*pCtx
= (ExynosVideoDecContext
*)pHandle
;
1697 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
1701 ALOGE("%s: Video context info must be supplied", __func__
);
1702 ret
= VIDEO_ERROR_BADPARAM
;
1706 for (i
= 0; i
< pCtx
->nOutbufs
; i
++) {
1707 pCtx
->pOutbuf
[i
].bQueued
= VIDEO_FALSE
;
1715 * [Decoder OPS] Common
1717 static ExynosVideoDecOps defDecOps
= {
1719 .Init
= MFC_Decoder_Init
,
1720 .Finalize
= MFC_Decoder_Finalize
,
1721 .Set_DisplayDelay
= MFC_Decoder_Set_DisplayDelay
,
1722 .Enable_PackedPB
= MFC_Decoder_Enable_PackedPB
,
1723 .Enable_LoopFilter
= MFC_Decoder_Enable_LoopFilter
,
1724 .Enable_SliceMode
= MFC_Decoder_Enable_SliceMode
,
1725 .Get_ActualBufferCount
= MFC_Decoder_Get_ActualBufferCount
,
1726 .Set_FrameTag
= MFC_Decoder_Set_FrameTag
,
1727 .Get_FrameTag
= MFC_Decoder_Get_FrameTag
,
1728 .Enable_SEIParsing
= MFC_Decoder_Enable_SEIParsing
,
1729 .Get_FramePackingInfo
= MFC_Decoder_Get_FramePackingInfo
,
1733 * [Decoder Buffer OPS] Input
1735 static ExynosVideoDecBufferOps defInbufOps
= {
1737 .Enable_Cacheable
= MFC_Decoder_Enable_Cacheable_Inbuf
,
1738 .Set_Shareable
= MFC_Decoder_Set_Shareable_Inbuf
,
1740 .Set_Geometry
= MFC_Decoder_Set_Geometry_Inbuf
,
1741 .Get_Geometry
= NULL
,
1742 .Setup
= MFC_Decoder_Setup_Inbuf
,
1743 .Run
= MFC_Decoder_Run_Inbuf
,
1744 .Stop
= MFC_Decoder_Stop_Inbuf
,
1745 .Enqueue
= MFC_Decoder_Enqueue_Inbuf
,
1746 .Enqueue_All
= NULL
,
1747 .Dequeue
= MFC_Decoder_Dequeue_Inbuf
,
1748 .Register
= MFC_Decoder_Register_Inbuf
,
1749 .Clear_RegisteredBuffer
= MFC_Decoder_Clear_RegisteredBuffer_Inbuf
,
1750 .Clear_Queue
= MFC_Decoder_Clear_Queued_Inbuf
,
1754 * [Decoder Buffer OPS] Output
1756 static ExynosVideoDecBufferOps defOutbufOps
= {
1758 .Enable_Cacheable
= MFC_Decoder_Enable_Cacheable_Outbuf
,
1759 .Set_Shareable
= MFC_Decoder_Set_Shareable_Outbuf
,
1760 .Get_Buffer
= MFC_Decoder_Get_Buffer_Outbuf
,
1761 .Set_Geometry
= MFC_Decoder_Set_Geometry_Outbuf
,
1762 .Get_Geometry
= MFC_Decoder_Get_Geometry_Outbuf
,
1763 .Setup
= MFC_Decoder_Setup_Outbuf
,
1764 .Run
= MFC_Decoder_Run_Outbuf
,
1765 .Stop
= MFC_Decoder_Stop_Outbuf
,
1766 .Enqueue
= MFC_Decoder_Enqueue_Outbuf
,
1767 .Enqueue_All
= NULL
,
1768 .Dequeue
= MFC_Decoder_Dequeue_Outbuf
,
1769 .Register
= MFC_Decoder_Register_Outbuf
,
1770 .Clear_RegisteredBuffer
= MFC_Decoder_Clear_RegisteredBuffer_Outbuf
,
1771 .Clear_Queue
= MFC_Decoder_Clear_Queued_Outbuf
,
1774 int Exynos_Video_Register_Decoder(
1775 ExynosVideoDecOps
*pDecOps
,
1776 ExynosVideoDecBufferOps
*pInbufOps
,
1777 ExynosVideoDecBufferOps
*pOutbufOps
)
1779 ExynosVideoErrorType ret
= VIDEO_ERROR_NONE
;
1781 if ((pDecOps
== NULL
) || (pInbufOps
== NULL
) || (pOutbufOps
== NULL
)) {
1782 ret
= VIDEO_ERROR_BADPARAM
;
1786 defDecOps
.nSize
= sizeof(defDecOps
);
1787 defInbufOps
.nSize
= sizeof(defInbufOps
);
1788 defOutbufOps
.nSize
= sizeof(defOutbufOps
);
1790 memcpy((char *)pDecOps
+ sizeof(pDecOps
->nSize
), (char *)&defDecOps
+ sizeof(defDecOps
.nSize
),
1791 pDecOps
->nSize
- sizeof(pDecOps
->nSize
));
1793 memcpy((char *)pInbufOps
+ sizeof(pInbufOps
->nSize
), (char *)&defInbufOps
+ sizeof(defInbufOps
.nSize
),
1794 pInbufOps
->nSize
- sizeof(pInbufOps
->nSize
));
1796 memcpy((char *)pOutbufOps
+ sizeof(pOutbufOps
->nSize
), (char *)&defOutbufOps
+ sizeof(defOutbufOps
.nSize
),
1797 pOutbufOps
->nSize
- sizeof(pOutbufOps
->nSize
));