summaryrefslogtreecommitdiffstats
path: root/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/dec/src/SsbSipMfcDecAPI.c
diff options
context:
space:
mode:
Diffstat (limited to 'exynos/multimedia/codecs/video/exynos4/mfc_v4l2/dec/src/SsbSipMfcDecAPI.c')
-rw-r--r--exynos/multimedia/codecs/video/exynos4/mfc_v4l2/dec/src/SsbSipMfcDecAPI.c1352
1 files changed, 1352 insertions, 0 deletions
diff --git a/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/dec/src/SsbSipMfcDecAPI.c b/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/dec/src/SsbSipMfcDecAPI.c
new file mode 100644
index 0000000..510a351
--- /dev/null
+++ b/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/dec/src/SsbSipMfcDecAPI.c
@@ -0,0 +1,1352 @@
+/*
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include <sys/poll.h>
+#include "videodev2.h"
+
+#include "mfc_interface.h"
+#include "SsbSipMfcApi.h"
+
+/* #define LOG_NDEBUG 0 */
+#define LOG_TAG "MFC_DEC_APP"
+#include <utils/Log.h>
+
+#ifdef CONFIG_MFC_FPS
+#include <sys/time.h>
+#endif
+
+/*#define CRC_ENABLE
+#define SLICE_MODE_ENABLE */
+#define POLL_DEC_WAIT_TIMEOUT 25
+
+#define USR_DATA_START_CODE (0x000001B2)
+#define VOP_START_CODE (0x000001B6)
+#define MP4_START_CODE (0x000001)
+
+#ifdef CONFIG_MFC_FPS
+unsigned int framecount, over30ms;
+struct timeval mTS1, mTS2, mDec1, mDec2;
+#endif
+
+#define DEFAULT_NUMBER_OF_EXTRA_DPB 5
+
+static char *mfc_dev_name = SAMSUNG_MFC_DEV_NAME;
+static int mfc_dev_node = 6;
+
+static void getAByte(char *buff, int *code)
+{
+ int byte;
+
+ *code = (*code << 8);
+ byte = (int)*buff;
+ byte &= 0xFF;
+ *code |= byte;
+}
+
+static int isPBPacked(_MFCLIB *pCtx, int Frameleng)
+{
+ char *strmBuffer = NULL;
+ int startCode = 0xFFFFFFFF;
+ int leng_idx = 1;
+
+ strmBuffer = (char*)pCtx->virStrmBuf;
+
+ while (1) {
+ while (startCode != USR_DATA_START_CODE) {
+ if ((startCode == VOP_START_CODE) || (leng_idx == Frameleng)) {
+ LOGI("[%s] VOP START Found !!.....return",__func__);
+ LOGW("[%s] Non Packed PB",__func__);
+ return 0;
+ }
+ getAByte(strmBuffer, &startCode);
+ LOGV(">> StartCode = 0x%08x <<\n", startCode);
+ strmBuffer++;
+ leng_idx++;
+ }
+ LOGI("[%s] User Data Found !!",__func__);
+
+ do {
+ if (*strmBuffer == 'p') {
+ LOGW("[%s] Packed PB",__func__);
+ return 1;
+ }
+ getAByte(strmBuffer, &startCode);
+ strmBuffer++; leng_idx++;
+ } while ((leng_idx <= Frameleng) && ((startCode >> 8) != MP4_START_CODE));
+
+ if (leng_idx > Frameleng)
+ break;
+ }
+
+ LOGW("[%s] Non Packed PB",__func__);
+
+ return 0;
+}
+
+static void getMFCName(char *devicename, int size)
+{
+ snprintf(devicename, size, "%s%d", SAMSUNG_MFC_DEV_NAME, mfc_dev_node);
+}
+
+void SsbSipMfcDecSetMFCNode(int devicenode)
+{
+ mfc_dev_node = devicenode;
+}
+
+void SsbSipMfcDecSetMFCName(char *devicename)
+{
+ mfc_dev_name = devicename;
+}
+
+void *SsbSipMfcDecOpen(void)
+{
+ int hMFCOpen;
+ _MFCLIB *pCTX;
+
+ char mfc_dev_name[64];
+
+ int ret;
+ unsigned int i, j;
+ struct v4l2_capability cap;
+ struct v4l2_format fmt;
+
+ struct v4l2_requestbuffers reqbuf;
+ struct v4l2_buffer buf;
+ struct v4l2_plane planes[MFC_DEC_NUM_PLANES];
+
+ LOGI("[%s] MFC Library Ver %d.%02d",__func__, MFC_LIB_VER_MAJOR, MFC_LIB_VER_MINOR);
+#ifdef CONFIG_MFC_FPS
+ framecount = 0;
+ over30ms = 0;
+ gettimeofday(&mTS1, NULL);
+#endif
+ pCTX = (_MFCLIB *)malloc(sizeof(_MFCLIB));
+ if (pCTX == NULL) {
+ LOGE("[%s] malloc failed.",__func__);
+ return NULL;
+ }
+
+ memset(pCTX, 0, sizeof(_MFCLIB));
+
+ getMFCName(mfc_dev_name, 64);
+ LOGI("[%s] dev name is %s",__func__,mfc_dev_name);
+
+ if (access(mfc_dev_name, F_OK) != 0) {
+ LOGE("[%s] MFC device node not exists",__func__);
+ goto error_case1;
+ }
+
+ hMFCOpen = open(mfc_dev_name, O_RDWR|O_NONBLOCK, 0);
+ if (hMFCOpen < 0) {
+ LOGE("[%s] Failed to open MFC device",__func__);
+ goto error_case1;
+ }
+
+ pCTX->hMFC = hMFCOpen;
+
+ memset(&cap, 0, sizeof(cap));
+ ret = ioctl(pCTX->hMFC, VIDIOC_QUERYCAP, &cap);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_QUERYCAP failed",__func__);
+ goto error_case2;
+ }
+
+ if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
+ LOGE("[%s] Device does not support capture",__func__);
+ goto error_case2;
+ }
+
+ if (!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) {
+ LOGE("[%s] Device does not support output",__func__);
+ goto error_case2;
+ }
+
+ if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
+ LOGE("[%s] Device does not support streaming",__func__);
+ goto error_case2;
+ }
+
+ pCTX->inter_buff_status = MFC_USE_NONE;
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264; /* Default is set to H264 */
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ fmt.fmt.pix_mp.plane_fmt[0].sizeimage = MAX_DECODER_INPUT_BUFFER_SIZE;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_S_FMT, &fmt);
+ if (ret != 0) {
+ LOGE("[%s] S_FMT failed",__func__);
+ goto error_case2;
+ }
+
+ pCTX->v4l2_dec.mfc_src_bufs_len = MAX_DECODER_INPUT_BUFFER_SIZE;
+
+ memset(&(reqbuf), 0, sizeof (reqbuf));
+ reqbuf.count = MFC_DEC_NUM_SRC_BUFS;
+ reqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ reqbuf.memory = V4L2_MEMORY_MMAP;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_REQBUFS, &reqbuf);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_REQBUFS failed",__func__);
+ goto error_case2;
+ }
+
+ pCTX->v4l2_dec.mfc_num_src_bufs = reqbuf.count;
+
+ for (i = 0; i < pCTX->v4l2_dec.mfc_num_src_bufs; ++i) {
+ memset(&(buf), 0, sizeof (buf));
+ buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ buf.memory = V4L2_MEMORY_MMAP;
+ buf.index = i;
+ buf.m.planes = planes;
+ buf.length = 1;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_QUERYBUF, &buf);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_QUERYBUF failed",__func__);
+ goto error_case3;
+ }
+
+ pCTX->v4l2_dec.mfc_src_bufs[i] = mmap(NULL, buf.m.planes[0].length,
+ PROT_READ | PROT_WRITE, MAP_SHARED, pCTX->hMFC, buf.m.planes[0].m.mem_offset);
+ if (pCTX->v4l2_dec.mfc_src_bufs[i] == MAP_FAILED) {
+ LOGE("[%s] mmap failed (%d)",__func__,i);
+ goto error_case3;
+ }
+ }
+ pCTX->inter_buff_status |= MFC_USE_STRM_BUFF;
+
+ /* set extra DPB size to 5 as default for optimal performce (heuristic method) */
+ pCTX->dec_numextradpb = DEFAULT_NUMBER_OF_EXTRA_DPB;
+
+ pCTX->v4l2_dec.bBeingFinalized = 0;
+ pCTX->lastframe = SSBSIP_MFC_LAST_FRAME_NOT_RECEIVED;
+
+ pCTX->cacheablebuffer = NO_CACHE;
+
+ for (i = 0; i<MFC_DEC_NUM_SRC_BUFS; i++)
+ pCTX->v4l2_dec.mfc_src_buf_flags[i] = BUF_DEQUEUED;
+
+ pCTX->v4l2_dec.beingUsedIndex = 0;
+
+ return (void *) pCTX;
+
+error_case3:
+ for (j = 0; j < i; j++)
+ munmap(pCTX->v4l2_dec.mfc_src_bufs[j], pCTX->v4l2_dec.mfc_src_bufs_len);
+
+error_case2:
+ close(pCTX->hMFC);
+
+error_case1:
+ free(pCTX);
+
+ return NULL;
+}
+
+void *SsbSipMfcDecOpenExt(void *value)
+{
+ _MFCLIB *pCTX;
+
+ pCTX = SsbSipMfcDecOpen();
+
+ if (pCTX == NULL)
+ return NULL;
+
+ if (NO_CACHE == (*(SSBIP_MFC_BUFFER_TYPE *)value)) {
+ pCTX->cacheablebuffer = NO_CACHE;
+ LOGI("[%s] non cacheable buffer",__func__);
+ } else {
+ pCTX->cacheablebuffer = CACHE;
+ LOGI("[%s] cacheable buffer",__func__);
+ }
+
+ return (void *)pCTX;
+}
+
+SSBSIP_MFC_ERROR_CODE SsbSipMfcDecClose(void *openHandle)
+{
+ int ret, i;
+ _MFCLIB *pCTX;
+
+ enum v4l2_buf_type type;
+#ifdef CONFIG_MFC_FPS
+ LOGI(">>> MFC");
+ gettimeofday(&mTS2, NULL);
+ LOGI(">>> time=%d", mTS2.tv_sec-mTS1.tv_sec);
+ LOGI(">>> framecount=%d", framecount);
+ LOGI(">>> 30ms over=%d", over30ms);
+#endif
+ if (openHandle == NULL) {
+ LOGE("[%s] openHandle is NULL",__func__);
+ return MFC_RET_INVALID_PARAM;
+ }
+
+ pCTX = (_MFCLIB *) openHandle;
+
+ if (pCTX->inter_buff_status & MFC_USE_DST_STREAMON) {
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ ret = ioctl(pCTX->hMFC, VIDIOC_STREAMOFF, &type);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_STREAMOFF failed (destination buffers)",__func__);
+ return MFC_RET_CLOSE_FAIL;
+ }
+ pCTX->inter_buff_status &= ~(MFC_USE_DST_STREAMON);
+ }
+
+ if (pCTX->inter_buff_status & MFC_USE_SRC_STREAMON) {
+ type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ ret = ioctl(pCTX->hMFC, VIDIOC_STREAMOFF, &type);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_STREAMOFF failed (source buffers)",__func__);
+ return MFC_RET_CLOSE_FAIL;
+ }
+ pCTX->inter_buff_status &= ~(MFC_USE_SRC_STREAMON);
+ }
+
+ if (pCTX->inter_buff_status & MFC_USE_STRM_BUFF) {
+ for (i = 0; i < pCTX->v4l2_dec.mfc_num_src_bufs; i++)
+ munmap(pCTX->v4l2_dec.mfc_src_bufs[i], pCTX->v4l2_dec.mfc_src_bufs_len);
+ pCTX->inter_buff_status &= ~(MFC_USE_STRM_BUFF);
+ }
+
+ if (pCTX->inter_buff_status & MFC_USE_YUV_BUFF) {
+ for (i = 0; i < pCTX->v4l2_dec.mfc_num_dst_bufs; i++) {
+ munmap(pCTX->v4l2_dec.mfc_dst_bufs[i][0], pCTX->v4l2_dec.mfc_dst_bufs_len[0]);
+ munmap(pCTX->v4l2_dec.mfc_dst_bufs[i][1], pCTX->v4l2_dec.mfc_dst_bufs_len[1]);
+ }
+ pCTX->inter_buff_status &= ~(MFC_USE_YUV_BUFF);
+ }
+
+ close(pCTX->hMFC);
+ free(pCTX);
+
+ return MFC_RET_OK;
+}
+
+SSBSIP_MFC_ERROR_CODE SsbSipMfcDecInit(void *openHandle, SSBSIP_MFC_CODEC_TYPE codec_type, int Frameleng)
+{
+ int packedPB = 0;
+ _MFCLIB *pCTX;
+ int ret;
+ unsigned int i, j;
+
+ struct v4l2_requestbuffers reqbuf;
+ struct v4l2_buffer qbuf;
+ struct v4l2_plane planes[MFC_DEC_NUM_PLANES];
+
+ struct v4l2_format fmt;
+ struct v4l2_pix_format_mplane pix_mp;
+ struct v4l2_control ctrl;
+ struct v4l2_crop crop;
+ enum v4l2_buf_type type;
+
+ if (openHandle == NULL) {
+ LOGE("[%s] openHandle is NULL",__func__);
+ return MFC_RET_INVALID_PARAM;
+ }
+
+ pCTX = (_MFCLIB *) openHandle;
+
+ pCTX->codecType = codec_type;
+
+ if ((pCTX->codecType == MPEG4_DEC) || (pCTX->codecType == XVID_DEC) ||
+ (pCTX->codecType == FIMV1_DEC) || (pCTX->codecType == FIMV2_DEC) ||
+ (pCTX->codecType == FIMV3_DEC) || (pCTX->codecType == FIMV4_DEC))
+ packedPB = isPBPacked(pCTX, Frameleng);
+
+ memset(&fmt, 0, sizeof(fmt));
+
+ switch (pCTX->codecType) {
+ case H264_DEC:
+ fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
+ break;
+ case MPEG4_DEC:
+ fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_MPEG4;
+ break;
+ case H263_DEC:
+ fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H263;
+ break;
+ case XVID_DEC:
+ fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_XVID;
+ break;
+ case MPEG2_DEC:
+ fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_MPEG12;
+ break;
+ case FIMV1_DEC:
+ fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_FIMV1;
+ fmt.fmt.pix_mp.width = pCTX->fimv1_res.width;
+ fmt.fmt.pix_mp.height = pCTX->fimv1_res.height;
+ break;
+ case FIMV2_DEC:
+ fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_FIMV2;
+ break;
+ case FIMV3_DEC:
+ fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_FIMV3;
+ break;
+ case FIMV4_DEC:
+ fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_FIMV4;
+ break;
+ case VC1_DEC:
+ fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_VC1;
+ break;
+ case VC1RCV_DEC:
+ fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_VC1_RCV;
+ break;
+ default:
+ LOGE("[%s] Does NOT support the standard (%d)",__func__,pCTX->codecType);
+ ret = MFC_RET_INVALID_PARAM;
+ goto error_case1;
+ }
+
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ fmt.fmt.pix_mp.plane_fmt[0].sizeimage = MAX_DECODER_INPUT_BUFFER_SIZE;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_S_FMT, &fmt);
+ if (ret != 0) {
+ LOGE("[%s] S_FMT failed",__func__);
+ ret = MFC_RET_DEC_INIT_FAIL;
+ goto error_case1;
+ }
+
+ memset(&qbuf, 0, sizeof(qbuf));
+
+ qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ qbuf.memory = V4L2_MEMORY_MMAP;
+ qbuf.index = pCTX->v4l2_dec.beingUsedIndex;
+ qbuf.m.planes = planes;
+ qbuf.length = 1;
+ qbuf.m.planes[0].bytesused = Frameleng;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_QBUF, &qbuf);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_QBUF failed, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE",__func__);
+ ret = MFC_RET_DEC_INIT_FAIL;
+ goto error_case1;
+ }
+
+ type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+
+ // Processing the header requires running streamon
+ // on OUTPUT queue
+ ret = ioctl(pCTX->hMFC, VIDIOC_STREAMON, &type);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_STREAMON failed",__func__);
+ ret = MFC_RET_DEC_INIT_FAIL;
+ goto error_case1;
+ }
+
+ pCTX->inter_buff_status |= MFC_USE_SRC_STREAMON;
+
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_G_FMT, &fmt);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_G_FMT failed",__func__);
+ ret = MFC_RET_DEC_INIT_FAIL;
+ goto error_case1;
+ }
+
+ pix_mp = fmt.fmt.pix_mp;
+ pCTX->decOutInfo.buf_width = pix_mp.plane_fmt[0].bytesperline;
+ pCTX->decOutInfo.buf_height =
+ pix_mp.plane_fmt[0].sizeimage / pix_mp.plane_fmt[0].bytesperline;
+
+ pCTX->decOutInfo.img_width = pix_mp.width;
+ pCTX->decOutInfo.img_height = pix_mp.height;
+
+ memset(&crop, 0, sizeof(crop));
+ crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_G_CROP, &crop);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_G_CROP failed",__func__);
+ ret = MFC_RET_DEC_INIT_FAIL;
+ goto error_case1;
+ }
+
+ pCTX->decOutInfo.crop_left_offset = crop.c.left;
+ pCTX->decOutInfo.crop_top_offset = crop.c.top;
+ pCTX->decOutInfo.crop_right_offset =
+ pix_mp.width - crop.c.width - crop.c.left;
+ pCTX->decOutInfo.crop_bottom_offset =
+ pix_mp.height - crop.c.height - crop.c.top;
+
+ memset(&ctrl, 0, sizeof(ctrl));
+ ctrl.id = V4L2_CID_CODEC_REQ_NUM_BUFS;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_G_CTRL, &ctrl);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_G_CTRL failed",__func__);
+ ret = MFC_RET_DEC_INIT_FAIL;
+ goto error_case1;
+ }
+
+ pCTX->v4l2_dec.mfc_num_dst_bufs = ctrl.value + pCTX->dec_numextradpb;
+
+ /* Cacheable buffer */
+ ctrl.id = V4L2_CID_CACHEABLE;
+ if(pCTX->cacheablebuffer == NO_CACHE)
+ ctrl.value = 0;
+ else
+ ctrl.value = 1;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_S_CTRL, &ctrl);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_S_CTRL failed, V4L2_CID_CACHEABLE",__func__);
+ ret = MFC_RET_DEC_INIT_FAIL;
+ goto error_case1;
+ }
+
+ memset(&reqbuf, 0, sizeof(reqbuf));
+ reqbuf.count = pCTX->v4l2_dec.mfc_num_dst_bufs;
+ reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ reqbuf.memory = V4L2_MEMORY_MMAP;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_REQBUFS, &reqbuf);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_REQBUFS failed (destination buffers)",__func__);
+ ret = MFC_RET_DEC_INIT_FAIL;
+ goto error_case1;
+ }
+
+ pCTX->v4l2_dec.mfc_num_dst_bufs = reqbuf.count;
+
+ for (i = 0; i < pCTX->v4l2_dec.mfc_num_dst_bufs; ++i) {
+ memset(&qbuf, 0, sizeof(qbuf));
+ qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ qbuf.memory = V4L2_MEMORY_MMAP;
+ qbuf.index = i;
+ qbuf.m.planes = planes;
+ qbuf.length = 2;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_QUERYBUF, &qbuf);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_QUERYBUF failed (destination buffers)",__func__);
+ ret = MFC_RET_DEC_INIT_FAIL;
+ goto error_case1;
+ }
+
+ pCTX->v4l2_dec.mfc_dst_bufs_len[0] = qbuf.m.planes[0].length;
+ pCTX->v4l2_dec.mfc_dst_bufs_len[1] = qbuf.m.planes[1].length;
+
+ pCTX->v4l2_dec.mfc_dst_phys[i][0] = qbuf.m.planes[0].cookie;
+ pCTX->v4l2_dec.mfc_dst_phys[i][1] = qbuf.m.planes[1].cookie;
+
+ pCTX->v4l2_dec.mfc_dst_bufs[i][0] = mmap(NULL, qbuf.m.planes[0].length,
+ PROT_READ | PROT_WRITE, MAP_SHARED, pCTX->hMFC, qbuf.m.planes[0].m.mem_offset);
+
+ if (pCTX->v4l2_dec.mfc_dst_bufs[i][0] == MAP_FAILED) {
+ LOGE("[%s] mmap failed (destination buffers (Y))",__func__);
+ ret = MFC_RET_DEC_INIT_FAIL;
+ goto error_case2;
+ }
+
+ pCTX->v4l2_dec.mfc_dst_bufs[i][1] = mmap(NULL, qbuf.m.planes[1].length,
+ PROT_READ | PROT_WRITE, MAP_SHARED, pCTX->hMFC, qbuf.m.planes[1].m.mem_offset);
+ if (pCTX->v4l2_dec.mfc_dst_bufs[i][1] == MAP_FAILED) {
+ LOGE("[%s] mmap failed (destination buffers (UV))",__func__);
+ ret = MFC_RET_DEC_INIT_FAIL;
+ goto error_case2;
+ }
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_QBUF, &qbuf);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_QBUF failed, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE",__func__);
+ ret = MFC_RET_DEC_INIT_FAIL;
+ goto error_case2;
+ }
+ }
+ pCTX->inter_buff_status |= MFC_USE_YUV_BUFF;
+
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ ret = ioctl(pCTX->hMFC, VIDIOC_STREAMON, &type);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_STREAMON failed (destination buffers)",__func__);
+ ret = MFC_RET_DEC_INIT_FAIL;
+ goto error_case1;
+ }
+ pCTX->inter_buff_status |= MFC_USE_DST_STREAMON;
+
+ memset(&qbuf, 0, sizeof(qbuf));
+ qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ qbuf.memory = V4L2_MEMORY_MMAP;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_DQBUF, &qbuf);
+ if(ret != 0) {
+ LOGE("[%s] VIDIOC_DQBUF failed, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE",__func__);
+ ret = MFC_RET_DEC_INIT_FAIL;
+ goto error_case1;
+ }
+
+ return MFC_RET_OK;
+
+error_case2:
+ for (j = 0; j < i; j++) {
+ munmap(pCTX->v4l2_dec.mfc_dst_bufs[j][0], pCTX->v4l2_dec.mfc_dst_bufs_len[0]);
+ munmap(pCTX->v4l2_dec.mfc_dst_bufs[j][1], pCTX->v4l2_dec.mfc_dst_bufs_len[1]);
+ }
+error_case1:
+ SsbSipMfcDecClose(openHandle);
+ return ret;
+}
+
+SSBSIP_MFC_ERROR_CODE SsbSipMfcDecExe(void *openHandle, int lengthBufFill)
+{
+ _MFCLIB *pCTX;
+ int ret;
+ struct v4l2_buffer qbuf;
+ struct v4l2_plane planes[MFC_DEC_NUM_PLANES];
+
+ struct pollfd poll_events;
+ int poll_state;
+
+#ifdef CONFIG_MFC_FPS
+ framecount++;
+#endif
+ if (openHandle == NULL) {
+ LOGE("[%s] openHandle is NULL",__func__);
+ return MFC_RET_INVALID_PARAM;
+ }
+
+ if ((lengthBufFill < 0) || (lengthBufFill > MAX_DECODER_INPUT_BUFFER_SIZE)) {
+ LOGE("[%s] lengthBufFill is invalid. (lengthBufFill=%d)",__func__, lengthBufFill);
+ return MFC_RET_INVALID_PARAM;
+ }
+
+#ifdef CONFIG_MFC_FPS
+ gettimeofday(&mDec1, NULL);
+#endif
+ pCTX = (_MFCLIB *) openHandle;
+
+ /* note: #define POLLOUT 0x0004 */
+ poll_events.fd = pCTX->hMFC;
+ poll_events.events = POLLOUT | POLLERR;
+ poll_events.revents = 0;
+
+ if ((lengthBufFill > 0) && (SSBSIP_MFC_LAST_FRAME_PROCESSED != pCTX->lastframe)) {
+ /* Queue the stream frame */
+ memset(&qbuf, 0, sizeof(qbuf));
+ qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ qbuf.memory = V4L2_MEMORY_MMAP;
+ qbuf.index = pCTX->v4l2_dec.beingUsedIndex;
+ qbuf.m.planes = planes;
+ qbuf.length = 1;
+ qbuf.m.planes[0].bytesused = lengthBufFill;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_QBUF, &qbuf);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_QBUF failed, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE",__func__);
+ return MFC_RET_DEC_EXE_ERR;
+ }
+
+ memset(&qbuf, 0, sizeof(qbuf));
+ qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ qbuf.memory = V4L2_MEMORY_MMAP;
+ qbuf.m.planes = planes;
+ qbuf.length = 1;
+
+ /* wait for decoding */
+ do {
+ poll_state = poll((struct pollfd*)&poll_events, 1, POLL_DEC_WAIT_TIMEOUT);
+ if (0 < poll_state) {
+ if (poll_events.revents & POLLOUT) { /* POLLOUT */
+ ret = ioctl(pCTX->hMFC, VIDIOC_DQBUF, &qbuf);
+ if (ret == 0) {
+ if (qbuf.flags & V4L2_BUF_FLAG_ERROR)
+ return MFC_RET_DEC_EXE_ERR;
+ break;
+ }
+ } else if (poll_events.revents & POLLERR) { /* POLLERR */
+ LOGE("[%s] POLLERR\n",__func__);
+ return MFC_RET_DEC_EXE_ERR;
+ } else {
+ LOGE("[%s] poll() returns 0x%x\n",__func__, poll_events.revents);
+ return MFC_RET_DEC_EXE_ERR;
+ }
+ } else if (0 > poll_state) {
+ return MFC_RET_DEC_EXE_ERR;
+ }
+ } while (0 == poll_state);
+
+ memset(&qbuf, 0, sizeof(qbuf));
+ qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ qbuf.memory = V4L2_MEMORY_MMAP;
+ qbuf.m.planes = planes;
+ qbuf.length = MFC_DEC_NUM_PLANES;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_DQBUF, &qbuf);
+
+ if (ret != 0) {
+ pCTX->displayStatus = MFC_GETOUTBUF_DECODING_ONLY;
+ pCTX->decOutInfo.disp_pic_frame_type = -1;
+ return MFC_RET_OK;
+ } else {
+ pCTX->displayStatus = MFC_GETOUTBUF_DISPLAY_DECODING;
+ }
+
+ pCTX->decOutInfo.YVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[qbuf.index][0];
+ pCTX->decOutInfo.CVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[qbuf.index][1];
+
+ pCTX->decOutInfo.YPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[qbuf.index][0];
+ pCTX->decOutInfo.CPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[qbuf.index][1];
+
+ if (SSBSIP_MFC_LAST_FRAME_RECEIVED == pCTX->lastframe)
+ pCTX->lastframe = SSBSIP_MFC_LAST_FRAME_PROCESSED;
+
+ } else if(pCTX->v4l2_dec.bBeingFinalized == 0) {
+ pCTX->lastframe = SSBSIP_MFC_LAST_FRAME_PROCESSED;
+
+ /* Queue the stream frame */
+ memset(&qbuf, 0, sizeof(qbuf));
+ qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ qbuf.memory = V4L2_MEMORY_MMAP;
+ qbuf.index = pCTX->v4l2_dec.beingUsedIndex;
+ qbuf.m.planes = planes;
+ qbuf.length = 1;
+ qbuf.m.planes[0].bytesused = 0;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_QBUF, &qbuf);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_QBUF failed, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE",__func__);
+ return MFC_RET_DEC_EXE_ERR;
+ }
+
+ pCTX->v4l2_dec.bBeingFinalized = 1; /* true */
+
+ memset(&qbuf, 0, sizeof(qbuf));
+ qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ qbuf.memory = V4L2_MEMORY_MMAP;
+ qbuf.m.planes = planes;
+ qbuf.length = MFC_DEC_NUM_PLANES;
+ /* FIXME
+ wait for decoding */
+ do {
+ ret = ioctl(pCTX->hMFC, VIDIOC_DQBUF, &qbuf);
+ } while (ret != 0);
+
+ pCTX->displayStatus = MFC_GETOUTBUF_DISPLAY_ONLY;
+
+ pCTX->decOutInfo.YVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[qbuf.index][0];
+ pCTX->decOutInfo.CVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[qbuf.index][1];
+
+ pCTX->decOutInfo.YPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[qbuf.index][0];
+ pCTX->decOutInfo.CPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[qbuf.index][1];
+ } else {
+ memset(&qbuf, 0, sizeof(qbuf));
+ qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ qbuf.memory = V4L2_MEMORY_MMAP;
+ qbuf.m.planes = planes;
+ qbuf.length = MFC_DEC_NUM_PLANES;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_DQBUF, &qbuf);
+
+ if (qbuf.m.planes[0].bytesused == 0) {
+ pCTX->displayStatus = MFC_GETOUTBUF_DISPLAY_END;
+ pCTX->decOutInfo.disp_pic_frame_type = -1;
+ return MFC_RET_OK;
+ } else {
+ pCTX->displayStatus = MFC_GETOUTBUF_DISPLAY_ONLY;
+ }
+
+ pCTX->decOutInfo.YVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[qbuf.index][0];
+ pCTX->decOutInfo.CVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[qbuf.index][1];
+
+ pCTX->decOutInfo.YPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[qbuf.index][0];
+ pCTX->decOutInfo.CPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[qbuf.index][1];
+ }
+
+ pCTX->decOutInfo.disp_pic_frame_type = (qbuf.flags & (0x7 << 3));
+
+ switch (pCTX->decOutInfo.disp_pic_frame_type) {
+ case V4L2_BUF_FLAG_KEYFRAME:
+ pCTX->decOutInfo.disp_pic_frame_type = 1;
+ break;
+ case V4L2_BUF_FLAG_PFRAME:
+ pCTX->decOutInfo.disp_pic_frame_type = 2;
+ break;
+ case V4L2_BUF_FLAG_BFRAME:
+ pCTX->decOutInfo.disp_pic_frame_type = 3;
+ break;
+ default:
+ pCTX->decOutInfo.disp_pic_frame_type = 0;
+ break;
+ }
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_QBUF, &qbuf);
+
+#ifdef CONFIG_MFC_FPS
+ gettimeofday(&mDec2, NULL);
+ if (mDec2.tv_usec-mDec1.tv_usec > 30000) over30ms++;
+#endif
+ return MFC_RET_OK;
+}
+
+#if 0
+SSBSIP_MFC_ERROR_CODE SsbSipMfcDecExeNb(void *openHandle, int lengthBufFill)
+{
+ _MFCLIB *pCTX;
+ int ret;
+
+ struct v4l2_buffer qbuf;
+ struct v4l2_plane planes[MFC_DEC_NUM_PLANES];
+
+#ifdef CONFIG_MFC_FPS
+ framecount++;
+#endif
+ if (openHandle == NULL) {
+ LOGE("[%s] openHandle is NULL",__func__);
+ return MFC_RET_INVALID_PARAM;
+ }
+
+ if ((lengthBufFill < 0) || (lengthBufFill > MAX_DECODER_INPUT_BUFFER_SIZE)) {
+ LOGE("[%s] lengthBufFill is invalid. (lengthBufFill=%d)",__func__, lengthBufFill);
+ return MFC_RET_INVALID_PARAM;
+ }
+
+ pCTX = (_MFCLIB *) openHandle;
+
+ if ((lengthBufFill > 0) && (SSBSIP_MFC_LAST_FRAME_PROCESSED != pCTX->lastframe)) {
+ /* Queue the stream frame */
+ memset(&qbuf, 0, sizeof(qbuf));
+ qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ qbuf.memory = V4L2_MEMORY_MMAP;
+ qbuf.index = pCTX->v4l2_dec.beingUsedIndex;
+ qbuf.m.planes = planes;
+ qbuf.length = 1;
+ qbuf.m.planes[0].bytesused = lengthBufFill;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_QBUF, &qbuf);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_QBUF failed, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE",__func__);
+ return MFC_RET_DEC_EXE_ERR;
+ }
+ } else if(pCTX->v4l2_dec.bBeingFinalized == 0) {
+ /* Queue the stream frame */
+ memset(&qbuf, 0, sizeof(qbuf));
+ qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ qbuf.memory = V4L2_MEMORY_MMAP;
+ qbuf.index = pCTX->v4l2_dec.beingUsedIndex;
+ qbuf.m.planes = planes;
+ qbuf.length = 1;
+ qbuf.m.planes[0].bytesused = 0;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_QBUF, &qbuf);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_QBUF failed, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE",__func__);
+ return MFC_RET_DEC_EXE_ERR;
+ }
+ }
+
+ if ((SSBSIP_MFC_LAST_FRAME_PROCESSED != pCTX->lastframe) && (lengthBufFill == 0))
+ pCTX->lastframe = SSBSIP_MFC_LAST_FRAME_RECEIVED;
+
+ return MFC_RET_OK;
+}
+
+SSBSIP_MFC_DEC_OUTBUF_STATUS SsbSipMfcDecWaitForOutBuf(void *openHandle, SSBSIP_MFC_DEC_OUTPUT_INFO *output_info)
+{
+ _MFCLIB *pCTX;
+ int ret;
+
+ struct v4l2_buffer qbuf;
+ struct v4l2_plane planes[MFC_DEC_NUM_PLANES];
+
+ struct pollfd poll_events;
+ int poll_state;
+
+ pCTX = (_MFCLIB *) openHandle;
+
+ /* note: #define POLLOUT 0x0004 */
+ poll_events.fd = pCTX->hMFC;
+ poll_events.events = POLLOUT | POLLERR;
+ poll_events.revents = 0;
+
+ if (SSBSIP_MFC_LAST_FRAME_PROCESSED != pCTX->lastframe) {
+ memset(&qbuf, 0, sizeof(qbuf));
+ qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ qbuf.memory = V4L2_MEMORY_MMAP;
+ qbuf.m.planes = planes;
+ qbuf.length = 1;
+
+ /* wait for decoding */
+ do {
+ poll_state = poll((struct pollfd*)&poll_events, 1, POLL_DEC_WAIT_TIMEOUT);
+ if (0 < poll_state) {
+ if (poll_events.revents & POLLOUT) { /* POLLOUT */
+ ret = ioctl(pCTX->hMFC, VIDIOC_DQBUF, &qbuf);
+ if (ret == 0) {
+ if (qbuf.flags & V4L2_BUF_FLAG_ERROR)
+ return MFC_GETOUTBUF_STATUS_NULL;
+ break;
+ }
+ } else if (poll_events.revents & POLLERR) { /* POLLERR */
+ LOGE("[%s] POLLERR\n",__func__);
+ return MFC_GETOUTBUF_STATUS_NULL;
+ } else {
+ LOGE("[%s] poll() returns 0x%x\n",__func__, poll_events.revents);
+ return MFC_GETOUTBUF_STATUS_NULL;
+ }
+ } else if (0 > poll_state) {
+ return MFC_GETOUTBUF_STATUS_NULL;
+ }
+ } while (0 == poll_state);
+
+ pCTX->v4l2_dec.mfc_src_buf_flags[qbuf.index] = BUF_DEQUEUED;
+
+ memset(&qbuf, 0, sizeof(qbuf));
+ qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ qbuf.memory = V4L2_MEMORY_MMAP;
+ qbuf.m.planes = planes;
+ qbuf.length = MFC_DEC_NUM_PLANES;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_DQBUF, &qbuf);
+
+ if (ret != 0) {
+ pCTX->displayStatus = MFC_GETOUTBUF_DECODING_ONLY;
+ pCTX->decOutInfo.disp_pic_frame_type = -1;
+ return SsbSipMfcDecGetOutBuf(pCTX, output_info);;
+ } else {
+ pCTX->displayStatus = MFC_GETOUTBUF_DISPLAY_DECODING;
+ }
+
+ pCTX->decOutInfo.YVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[qbuf.index][0];
+ pCTX->decOutInfo.CVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[qbuf.index][1];
+
+ pCTX->decOutInfo.YPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[qbuf.index][0];
+ pCTX->decOutInfo.CPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[qbuf.index][1];
+
+ if (SSBSIP_MFC_LAST_FRAME_RECEIVED == pCTX->lastframe)
+ pCTX->lastframe = SSBSIP_MFC_LAST_FRAME_PROCESSED;
+ } else if (pCTX->v4l2_dec.bBeingFinalized == 0) {
+ pCTX->lastframe = SSBSIP_MFC_LAST_FRAME_PROCESSED;
+
+ pCTX->v4l2_dec.bBeingFinalized = 1; /* true */
+
+ memset(&qbuf, 0, sizeof(qbuf));
+ qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ qbuf.memory = V4L2_MEMORY_MMAP;
+ qbuf.m.planes = planes;
+ qbuf.length = MFC_DEC_NUM_PLANES;
+
+ /* wait for decoding */
+ do {
+ ret = ioctl(pCTX->hMFC, VIDIOC_DQBUF, &qbuf);
+ } while (ret != 0);
+
+ pCTX->displayStatus = MFC_GETOUTBUF_DISPLAY_ONLY;
+
+ pCTX->decOutInfo.YVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[qbuf.index][0];
+ pCTX->decOutInfo.CVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[qbuf.index][1];
+
+ pCTX->decOutInfo.YPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[qbuf.index][0];
+ pCTX->decOutInfo.CPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[qbuf.index][1];
+ } else {
+ memset(&qbuf, 0, sizeof(qbuf));
+ qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ qbuf.memory = V4L2_MEMORY_MMAP;
+ qbuf.m.planes = planes;
+ qbuf.length = MFC_DEC_NUM_PLANES;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_DQBUF, &qbuf);
+
+ if (qbuf.m.planes[0].bytesused == 0) {
+ pCTX->displayStatus = MFC_GETOUTBUF_DISPLAY_END;
+ pCTX->decOutInfo.disp_pic_frame_type = -1;
+ return SsbSipMfcDecGetOutBuf(pCTX, output_info);;
+ } else {
+ pCTX->displayStatus = MFC_GETOUTBUF_DISPLAY_ONLY;
+ }
+
+ pCTX->decOutInfo.YVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[qbuf.index][0];
+ pCTX->decOutInfo.CVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[qbuf.index][1];
+
+ pCTX->decOutInfo.YPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[qbuf.index][0];
+ pCTX->decOutInfo.CPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[qbuf.index][1];
+ }
+
+ pCTX->decOutInfo.disp_pic_frame_type = (qbuf.flags & (0x7 << 3));
+
+ switch (pCTX->decOutInfo.disp_pic_frame_type) {
+ case V4L2_BUF_FLAG_KEYFRAME:
+ pCTX->decOutInfo.disp_pic_frame_type = 1;
+ break;
+ case V4L2_BUF_FLAG_PFRAME:
+ pCTX->decOutInfo.disp_pic_frame_type = 2;
+ break;
+ case V4L2_BUF_FLAG_BFRAME:
+ pCTX->decOutInfo.disp_pic_frame_type = 3;
+ break;
+ default:
+ pCTX->decOutInfo.disp_pic_frame_type = 0;
+ break;
+ }
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_QBUF, &qbuf);
+
+ return SsbSipMfcDecGetOutBuf(pCTX, output_info);
+}
+#endif
+
+void *SsbSipMfcDecGetInBuf(void *openHandle, void **phyInBuf, int inputBufferSize)
+{
+ _MFCLIB *pCTX;
+ int i;
+
+ if (openHandle == NULL) {
+ LOGE("[%s] openHandle is NULL",__func__);
+ return NULL;
+ }
+
+ if ((inputBufferSize < 0) || (inputBufferSize > MAX_DECODER_INPUT_BUFFER_SIZE)) {
+ LOGE("[%s] inputBufferSize = %d is invalid",__func__, inputBufferSize);
+ return NULL;
+ }
+
+ pCTX = (_MFCLIB *) openHandle;
+
+ for (i = 0; i < MFC_DEC_NUM_SRC_BUFS; i++)
+ if (BUF_DEQUEUED == pCTX->v4l2_dec.mfc_src_buf_flags[i])
+ break;
+
+ if (i == MFC_DEC_NUM_SRC_BUFS) {
+ LOGV("[%s] No buffer is available.",__func__);
+ return NULL;
+ } else {
+ pCTX->virStrmBuf = (unsigned int)pCTX->v4l2_dec.mfc_src_bufs[i];
+ /* Set the buffer flag as Enqueued for NB_mode_process*/
+ /* FIXME: Check this assignment in case of using New API ExeNb() */
+ pCTX->v4l2_dec.mfc_src_buf_flags[i] = BUF_ENQUEUED;
+ }
+
+ return (void *)pCTX->virStrmBuf;
+}
+
+SSBSIP_MFC_ERROR_CODE SsbSipMfcDecSetInBuf(void *openHandle, void *phyInBuf, void *virInBuf, int size)
+{
+ _MFCLIB *pCTX;
+ int i;
+
+ LOGV("[%s] Enter",__func__);
+ if (openHandle == NULL) {
+ LOGE("[%s] openHandle is NULL",__func__);
+ return MFC_RET_INVALID_PARAM;
+ }
+
+ pCTX = (_MFCLIB *) openHandle;
+
+ for (i = 0; i<MFC_DEC_NUM_SRC_BUFS; i++)
+ if (pCTX->v4l2_dec.mfc_src_bufs[i] == virInBuf)
+ break;
+
+ if (i == MFC_DEC_NUM_SRC_BUFS) {
+ LOGE("[%s] Can not use the buffer",__func__);
+ return MFC_RET_INVALID_PARAM;
+ } else {
+ pCTX->virStrmBuf = (unsigned int)virInBuf;
+ pCTX->v4l2_dec.beingUsedIndex = i;
+ pCTX->v4l2_dec.mfc_src_buf_flags[i] = BUF_ENQUEUED;
+ }
+ LOGV("[%s] Exit idx %d",__func__,pCTX->v4l2_dec.beingUsedIndex);
+ return MFC_RET_OK;
+}
+
+SSBSIP_MFC_DEC_OUTBUF_STATUS SsbSipMfcDecGetOutBuf(void *openHandle, SSBSIP_MFC_DEC_OUTPUT_INFO *output_info)
+{
+ int ret;
+ _MFCLIB *pCTX;
+
+ if (openHandle == NULL) {
+ LOGE("[%s] openHandle is NULL",__func__);
+ return MFC_GETOUTBUF_DISPLAY_END;
+ }
+
+ pCTX = (_MFCLIB *) openHandle;
+
+ output_info->YPhyAddr = pCTX->decOutInfo.YPhyAddr;
+ output_info->CPhyAddr = pCTX->decOutInfo.CPhyAddr;
+
+ output_info->YVirAddr = pCTX->decOutInfo.YVirAddr;
+ output_info->CVirAddr = pCTX->decOutInfo.CVirAddr;
+
+ output_info->img_width = pCTX->decOutInfo.img_width;
+ output_info->img_height= pCTX->decOutInfo.img_height;
+
+ output_info->buf_width = pCTX->decOutInfo.buf_width;
+ output_info->buf_height= pCTX->decOutInfo.buf_height;
+
+ output_info->crop_right_offset = pCTX->decOutInfo.crop_right_offset;
+ output_info->crop_left_offset = pCTX->decOutInfo.crop_left_offset;
+ output_info->crop_bottom_offset = pCTX->decOutInfo.crop_bottom_offset;
+ output_info->crop_top_offset = pCTX->decOutInfo.crop_top_offset;
+
+ output_info->disp_pic_frame_type = pCTX->decOutInfo.disp_pic_frame_type;
+
+ switch (pCTX->displayStatus) {
+ case MFC_GETOUTBUF_DISPLAY_ONLY:
+ case MFC_GETOUTBUF_DISPLAY_DECODING:
+ case MFC_GETOUTBUF_DISPLAY_END:
+#ifdef SSB_UMP
+ ret = ump_secure_id_get_from_vaddr(pCTX->decOutInfo.YVirAddr, &output_info->y_cookie);
+ if (ret) {
+ LOGV("[%s] fail to get secure id(%d) from vaddr(%x)\n",__func__, \
+ output_info->y_cookie, pCTX->decOutInfo.YVirAddr);
+ }
+
+ ret = ump_secure_id_get_from_vaddr(pCTX->decOutInfo.CVirAddr, &output_info->c_cookie);
+ if (ret) {
+ LOGV("[%s] fail to get secure id(%d) from vaddr(%x)\n",__func__, \
+ output_info->c_cookie, pCTX->decOutInfo.CVirAddr);
+ }
+ break;
+#endif
+ case MFC_GETOUTBUF_DECODING_ONLY:
+ case MFC_GETOUTBUF_CHANGE_RESOL:
+ break;
+ default:
+ return MFC_GETOUTBUF_DISPLAY_END;
+ }
+
+ return pCTX->displayStatus;
+}
+
+SSBSIP_MFC_ERROR_CODE SsbSipMfcDecSetConfig(void *openHandle, SSBSIP_MFC_DEC_CONF conf_type, void *value)
+{
+ int ret, i;
+
+ _MFCLIB *pCTX;
+ struct mfc_dec_fimv1_info *fimv1_res;
+
+ struct v4l2_buffer qbuf;
+ struct v4l2_plane planes[MFC_DEC_NUM_PLANES];
+ struct v4l2_control ctrl;
+
+ enum v4l2_buf_type type;
+
+ if (openHandle == NULL) {
+ LOGE("[%s] openHandle is NULL",__func__);
+ return MFC_RET_INVALID_PARAM;
+ }
+
+ if ((value == NULL) && (MFC_DEC_SETCONF_IS_LAST_FRAME !=conf_type)) {
+ LOGE("[%s] value is NULL",__func__);
+ return MFC_RET_INVALID_PARAM;
+ }
+
+ pCTX = (_MFCLIB *) openHandle;
+
+ /* First, process non-ioctl calling settings */
+ switch (conf_type) {
+ case MFC_DEC_SETCONF_EXTRA_BUFFER_NUM:
+ pCTX->dec_numextradpb = *((unsigned int *) value);
+ return MFC_RET_OK;
+
+ case MFC_DEC_SETCONF_FIMV1_WIDTH_HEIGHT: /* be set before calling SsbSipMfcDecInit */
+ fimv1_res = (struct mfc_dec_fimv1_info *)value;
+ LOGI("fimv1->width = %d\n", fimv1_res->width);
+ LOGI("fimv1->height = %d\n", fimv1_res->height);
+ pCTX->fimv1_res.width = (int)(fimv1_res->width);
+ pCTX->fimv1_res.height = (int)(fimv1_res->height);
+ return MFC_RET_OK;
+
+ case MFC_DEC_SETCONF_IS_LAST_FRAME:
+ if (SSBSIP_MFC_LAST_FRAME_PROCESSED != pCTX->lastframe) {
+ pCTX->lastframe = SSBSIP_MFC_LAST_FRAME_RECEIVED;
+ return MFC_RET_OK;
+ } else {
+ return MFC_RET_FAIL;
+ }
+
+ case MFC_DEC_SETCONF_DPB_FLUSH:
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ ret = ioctl(pCTX->hMFC, VIDIOC_STREAMOFF, &type);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_STREAMOFF failed (destination buffers)",__func__);
+ return MFC_RET_DEC_SET_CONF_FAIL;
+ }
+ pCTX->inter_buff_status &= ~(MFC_USE_DST_STREAMON);
+
+ for (i = 0; i < pCTX->v4l2_dec.mfc_num_dst_bufs; ++i) {
+ memset(&qbuf, 0, sizeof(qbuf));
+
+ qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ qbuf.memory = V4L2_MEMORY_MMAP;
+ qbuf.index = i;
+ qbuf.m.planes = planes;
+ qbuf.length = 2;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_QBUF, &qbuf);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_QBUF failed, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE",__func__);
+ return MFC_RET_DEC_SET_CONF_FAIL;
+ }
+ }
+
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ ret = ioctl(pCTX->hMFC, VIDIOC_STREAMON, &type);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_STREAMON failed (destination buffers)",__func__);
+ return MFC_RET_DEC_SET_CONF_FAIL;
+ }
+ pCTX->inter_buff_status |= MFC_USE_DST_STREAMON;
+ return MFC_RET_OK;
+ default:
+ /* Others will be processed next */
+ break;
+ }
+
+ /* Process ioctl calling settings */
+ memset(&ctrl, 0, sizeof(ctrl));
+ switch (conf_type) {
+ case MFC_DEC_SETCONF_DISPLAY_DELAY: /* be set before calling SsbSipMfcDecInit */
+ ctrl.id = V4L2_CID_CODEC_DISPLAY_DELAY;
+ ctrl.value = *((unsigned int *) value);
+ break;
+
+ case MFC_DEC_SETCONF_CRC_ENABLE:
+ ctrl.id = V4L2_CID_CODEC_CRC_ENABLE;
+ ctrl.value = 1;
+ break;
+
+ case MFC_DEC_SETCONF_SLICE_ENABLE:
+ ctrl.id = V4L2_CID_CODEC_SLICE_INTERFACE;
+ ctrl.value = 1;
+ break;
+
+ case MFC_DEC_SETCONF_FRAME_TAG: /*be set before calling SsbSipMfcDecExe */
+ ctrl.id = V4L2_CID_CODEC_FRAME_TAG;
+ ctrl.value = *((unsigned int*)value);
+ break;
+
+ case MFC_DEC_SETCONF_POST_ENABLE:
+ ctrl.id = V4L2_CID_CODEC_LOOP_FILTER_MPEG4_ENABLE;
+ ctrl.value = *((unsigned int*)value);
+ break;
+
+ default:
+ LOGE("[%s] conf_type(%d) is NOT supported",__func__, conf_type);
+ return MFC_RET_INVALID_PARAM;
+ }
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_S_CTRL, &ctrl);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_S_CTRL failed (conf_type = %d)",__func__, conf_type);
+ return MFC_RET_DEC_SET_CONF_FAIL;
+ }
+
+ return MFC_RET_OK;
+}
+
+SSBSIP_MFC_ERROR_CODE SsbSipMfcDecGetConfig(void *openHandle, SSBSIP_MFC_DEC_CONF conf_type, void *value)
+{
+ _MFCLIB *pCTX;
+
+ SSBSIP_MFC_IMG_RESOLUTION *img_resolution;
+ int ret;
+ SSBSIP_MFC_CRC_DATA *crc_data;
+ SSBSIP_MFC_CROP_INFORMATION *crop_information;
+ struct v4l2_control ctrl;
+
+ if (openHandle == NULL) {
+ LOGE("[%s] openHandle is NULL",__func__);
+ return MFC_RET_INVALID_PARAM;
+ }
+
+ if (value == NULL) {
+ LOGE("[%s] value is NULL",__func__);
+ return MFC_RET_INVALID_PARAM;
+ }
+
+ pCTX = (_MFCLIB *) openHandle;
+
+ switch (conf_type) {
+ case MFC_DEC_GETCONF_BUF_WIDTH_HEIGHT:
+ img_resolution = (SSBSIP_MFC_IMG_RESOLUTION *)value;
+ img_resolution->width = pCTX->decOutInfo.img_width;
+ img_resolution->height = pCTX->decOutInfo.img_height;
+ img_resolution->buf_width = pCTX->decOutInfo.buf_width;
+ img_resolution->buf_height = pCTX->decOutInfo.buf_height;
+ break;
+
+ case MFC_DEC_GETCONF_CRC_DATA:
+ crc_data = (SSBSIP_MFC_CRC_DATA *) value;
+
+ ctrl.id = V4L2_CID_CODEC_CRC_DATA_LUMA;
+ ctrl.value = 0;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_G_CTRL, &ctrl);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_G_CTRL failed, V4L2_CID_CODEC_CRC_DATA_LUMA",__func__);
+ return MFC_RET_DEC_GET_CONF_FAIL;
+ }
+ crc_data->luma0 = ctrl.value;
+
+ ctrl.id = V4L2_CID_CODEC_CRC_DATA_CHROMA;
+ ctrl.value = 0;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_G_CTRL, &ctrl);
+ if (ret != 0) {
+ LOGE("[%s] VIDIOC_G_CTRL failed, V4L2_CID_CODEC_CRC_DATA_CHROMA",__func__);
+ return MFC_RET_DEC_GET_CONF_FAIL;
+ }
+ crc_data->chroma0 = ctrl.value;
+
+ LOGI("[%s] crc_data->luma0=%d",__func__,ctrl.value);
+ LOGI("[%s] crc_data->chroma0=%d",__func__,ctrl.value);
+ break;
+
+ case MFC_DEC_GETCONF_FRAME_TAG:
+ ctrl.id = V4L2_CID_CODEC_FRAME_TAG;
+ ctrl.value = 0;
+
+ ret = ioctl(pCTX->hMFC, VIDIOC_G_CTRL, &ctrl);
+ if (ret != 0) {
+ printf("Error to do g_ctrl.\n");
+ }
+ *((unsigned int *)value) = ctrl.value;
+ break;
+
+ case MFC_DEC_GETCONF_CROP_INFO:
+ crop_information = (SSBSIP_MFC_CROP_INFORMATION *)value;
+ crop_information->crop_top_offset = pCTX->decOutInfo.crop_top_offset;
+ crop_information->crop_bottom_offset = pCTX->decOutInfo.crop_bottom_offset;
+ crop_information->crop_left_offset = pCTX->decOutInfo.crop_left_offset;
+ crop_information->crop_right_offset = pCTX->decOutInfo.crop_right_offset;
+ break;
+
+ default:
+ LOGE("[%s] conf_type(%d) is NOT supported",__func__, conf_type);
+ return MFC_RET_INVALID_PARAM;
+ }
+
+ return MFC_RET_OK;
+}