diff options
Diffstat (limited to 'exynos/multimedia/codecs/video/exynos4/mfc_v4l2')
6 files changed, 3593 insertions, 0 deletions
diff --git a/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/Android.mk b/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/Android.mk new file mode 100644 index 0000000..6025b43 --- /dev/null +++ b/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/Android.mk @@ -0,0 +1,34 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_COPY_HEADERS_TO := libsecmm +LOCAL_COPY_HEADERS := \ + include/mfc_errno.h \ + include/mfc_interface.h \ + include/SsbSipMfcApi.h + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + dec/src/SsbSipMfcDecAPI.c \ + enc/src/SsbSipMfcEncAPI.c + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/include \ + device/samsung/$(TARGET_BOARD_PLATFORM)/include + +LOCAL_MODULE := libsecmfcapi + +LOCAL_PRELINK_MODULE := false + +ifeq ($(BOARD_USES_MFC_FPS),true) +LOCAL_CFLAGS := -DCONFIG_MFC_FPS +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := +LOCAL_SHARED_LIBRARIES := liblog + +include $(BUILD_STATIC_LIBRARY) 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; +} diff --git a/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/enc/src/SsbSipMfcEncAPI.c b/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/enc/src/SsbSipMfcEncAPI.c new file mode 100644 index 0000000..45888c6 --- /dev/null +++ b/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/enc/src/SsbSipMfcEncAPI.c @@ -0,0 +1,1206 @@ +/* + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * + * 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_ENC_APP" +#include <utils/Log.h> + +#define POLL_ENC_WAIT_TIMEOUT 25 + +#ifndef true +#define true (1) +#endif + +#ifndef false +#define false (0) +#endif + +#define MAX_STREAM_SIZE (2*1024*1024) + +static char *mfc_dev_name = SAMSUNG_MFC_DEV_NAME; +static int mfc_dev_node = 7; + +static void getMFCName(char *devicename, int size) +{ + snprintf(devicename, size, "%s%d", SAMSUNG_MFC_DEV_NAME, mfc_dev_node); +} + +void SsbSipMfcEncSetMFCName(char *devicename) +{ + mfc_dev_name = devicename; +} + +void *SsbSipMfcEncOpen(void) +{ + int hMFCOpen; + _MFCLIB *pCTX; + + char mfc_dev_name[64]; + + int ret; + struct v4l2_capability cap; + + getMFCName(mfc_dev_name, 64); + LOGI("[%s] dev name is %s\n",__func__,mfc_dev_name); + + if (access(mfc_dev_name, F_OK) != 0) { + LOGE("[%s] MFC device node not exists",__func__); + return NULL; + } + + hMFCOpen = open(mfc_dev_name, O_RDWR | O_NONBLOCK, 0); + if (hMFCOpen < 0) { + LOGE("[%s] Failed to open MFC device",__func__); + return NULL; + } + + pCTX = (_MFCLIB *)malloc(sizeof(_MFCLIB)); + if (pCTX == NULL) { + LOGE("[%s] malloc failed.",__func__); + return NULL; + } + memset(pCTX, 0, sizeof(_MFCLIB)); + + pCTX->hMFC = hMFCOpen; + + memset(&cap, 0, sizeof(cap)); + ret = ioctl(pCTX->hMFC, VIDIOC_QUERYCAP, &cap); + if (ret != 0) { + LOGE("[%s] VIDIOC_QUERYCAP failed",__func__); + close(pCTX->hMFC); + free(pCTX); + return NULL; + } + + if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { + LOGE("[%s] Device does not support capture",__func__); + close(pCTX->hMFC); + free(pCTX); + return NULL; + } + + if (!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) { + LOGE("[%s] Device does not support output",__func__); + close(pCTX->hMFC); + free(pCTX); + return NULL; + } + + if (!(cap.capabilities & V4L2_CAP_STREAMING)) { + LOGE("[%s] Device does not support streaming",__func__); + close(pCTX->hMFC); + free(pCTX); + return NULL; + } + + pCTX->v4l2_enc.bRunning = 0; + /* physical address is used for Input source */ + pCTX->v4l2_enc.bInputPhyVir = 1; + + pCTX->cacheablebuffer = NO_CACHE; + + return (void *)pCTX; +} + +void *SsbSipMfcEncOpenExt(void *value) +{ + _MFCLIB *pCTX; + + pCTX = SsbSipMfcEncOpen(); + if (pCTX == NULL) + return NULL; + + if (NO_CACHE == (*(SSBIP_MFC_BUFFER_TYPE *)value)) { + pCTX->cacheablebuffer = NO_CACHE; + /* physical address is used for Input source */ + pCTX->v4l2_enc.bInputPhyVir = 1; + LOGI("[%s] non cacheable buffer",__func__); + } + else { + pCTX->cacheablebuffer = CACHE; + /* vitual address is used for Input source */ + pCTX->v4l2_enc.bInputPhyVir = 0; + LOGI("[%s] cacheable buffer",__func__); + } + + return (void *)pCTX; +} + +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncClose(void *openHandle) +{ + _MFCLIB *pCTX; + int i; + + if (openHandle == NULL) { + LOGE("[%s] openHandle is NULL",__func__); + return MFC_RET_INVALID_PARAM; + } + + pCTX = (_MFCLIB *) openHandle; + + if (!pCTX->v4l2_enc.bInputPhyVir) { + for (i = 0; i < pCTX->v4l2_enc.mfc_num_src_bufs; i++) { + munmap(pCTX->v4l2_enc.mfc_src_bufs[i][0], pCTX->v4l2_enc.mfc_src_bufs_len[0]); + munmap(pCTX->v4l2_enc.mfc_src_bufs[i][1], pCTX->v4l2_enc.mfc_src_bufs_len[1]); + } + } + + for (i = 0; i < pCTX->v4l2_enc.mfc_num_dst_bufs; i++) + munmap(pCTX->v4l2_enc.mfc_dst_bufs[i], pCTX->v4l2_enc.mfc_dst_bufs_len); + + pCTX->inter_buff_status = MFC_USE_NONE; + + close(pCTX->hMFC); + + free(pCTX); + + return MFC_RET_OK; +} + +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncInit(void *openHandle, void *param) +{ + int ret, i, j,index; + _MFCLIB *pCTX; + + enum v4l2_buf_type type; + struct v4l2_format fmt; + struct v4l2_plane planes[MFC_ENC_NUM_PLANES]; + + struct v4l2_buffer buf; + struct v4l2_requestbuffers reqbuf; + + struct v4l2_control ctrl; + + struct pollfd poll_events; + int poll_state; + + struct v4l2_ext_control ext_ctrl_mpeg4[27]; + struct v4l2_ext_control ext_ctrl_h263[19]; + struct v4l2_ext_control ext_ctrl[44]; + struct v4l2_ext_controls ext_ctrls; + + SSBSIP_MFC_ENC_H264_PARAM *h264_arg; + SSBSIP_MFC_ENC_MPEG4_PARAM *mpeg4_arg; + SSBSIP_MFC_ENC_H263_PARAM *h263_arg; + + if (openHandle == NULL) { + return MFC_RET_INVALID_PARAM; + } + + pCTX = (_MFCLIB *) openHandle; + + mpeg4_arg = (SSBSIP_MFC_ENC_MPEG4_PARAM*)param; + if (mpeg4_arg->codecType == MPEG4_ENC) { + pCTX->codecType= MPEG4_ENC; + pCTX->width = mpeg4_arg->SourceWidth; + pCTX->height = mpeg4_arg->SourceHeight; + pCTX->framemap = mpeg4_arg->FrameMap; + } else { + h263_arg = (SSBSIP_MFC_ENC_H263_PARAM*)param; + if (h263_arg->codecType == H263_ENC) { + pCTX->codecType = H263_ENC; + pCTX->width = h263_arg->SourceWidth; + pCTX->height = h263_arg->SourceHeight; + pCTX->framemap = h263_arg->FrameMap; + } else { + h264_arg = (SSBSIP_MFC_ENC_H264_PARAM*)param; + if (h264_arg->codecType == H264_ENC) { + pCTX->codecType = H264_ENC; + pCTX->width = h264_arg->SourceWidth; + pCTX->height = h264_arg->SourceHeight; + pCTX->framemap = h264_arg->FrameMap; + } else { + LOGE("[%s] Undefined codec type \n",__func__); + ret = MFC_RET_INVALID_PARAM; + goto error_case1; + } + } + } + + switch (pCTX->codecType) { + case MPEG4_ENC: + ext_ctrl_mpeg4[0].id = V4L2_CID_CODEC_MFC5X_ENC_MPEG4_PROFILE; + ext_ctrl_mpeg4[0].value = mpeg4_arg->ProfileIDC; + ext_ctrl_mpeg4[1].id = V4L2_CID_CODEC_MFC5X_ENC_MPEG4_LEVEL; + ext_ctrl_mpeg4[1].value = mpeg4_arg->LevelIDC; + ext_ctrl_mpeg4[2].id = V4L2_CID_CODEC_MFC5X_ENC_GOP_SIZE; + ext_ctrl_mpeg4[2].value = mpeg4_arg->IDRPeriod; + ext_ctrl_mpeg4[3].id = V4L2_CID_CODEC_MFC5X_ENC_MPEG4_QUARTER_PIXEL; + ext_ctrl_mpeg4[3].value = mpeg4_arg->DisableQpelME; + + ext_ctrl_mpeg4[4].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_MODE; + ext_ctrl_mpeg4[4].value = mpeg4_arg->SliceMode; /* 0: one, 1: fixed #mb, 3: fixed #bytes */ + if (mpeg4_arg->SliceMode == 0) { + ext_ctrl_mpeg4[5].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_MB; + ext_ctrl_mpeg4[5].value = 1; /* default */ + ext_ctrl_mpeg4[6].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_BIT; + ext_ctrl_mpeg4[6].value = 1900; /* default */ + } else if (mpeg4_arg->SliceMode == 1) { + ext_ctrl_mpeg4[5].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_MB; + ext_ctrl_mpeg4[5].value = mpeg4_arg->SliceArgument; + ext_ctrl_mpeg4[6].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_BIT; + ext_ctrl_mpeg4[6].value = 1900; /* default */ + } else if (mpeg4_arg->SliceMode == 3) { + ext_ctrl_mpeg4[5].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_MB; + ext_ctrl_mpeg4[5].value = 1; /* default */ + ext_ctrl_mpeg4[6].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_BIT; + ext_ctrl_mpeg4[6].value = mpeg4_arg->SliceArgument; + } + /* + It should be set using mpeg4_arg->NumberBFrames after being handled by appl. + */ + ext_ctrl_mpeg4[7].id = V4L2_CID_CODEC_MFC5X_ENC_MPEG4_B_FRAMES; + ext_ctrl_mpeg4[7].value = mpeg4_arg->NumberBFrames; + ext_ctrl_mpeg4[8].id = V4L2_CID_CODEC_MFC5X_ENC_INTRA_REFRESH_MB; + ext_ctrl_mpeg4[8].value = mpeg4_arg->RandomIntraMBRefresh; + + ext_ctrl_mpeg4[9].id = V4L2_CID_CODEC_MFC5X_ENC_PAD_CTRL_ENABLE; + ext_ctrl_mpeg4[9].value = mpeg4_arg->PadControlOn; + ext_ctrl_mpeg4[10].id = V4L2_CID_CODEC_MFC5X_ENC_PAD_LUMA_VALUE; + ext_ctrl_mpeg4[10].value = mpeg4_arg->LumaPadVal; + ext_ctrl_mpeg4[11].id = V4L2_CID_CODEC_MFC5X_ENC_PAD_CB_VALUE; + ext_ctrl_mpeg4[11].value = mpeg4_arg->CbPadVal; + ext_ctrl_mpeg4[12].id = V4L2_CID_CODEC_MFC5X_ENC_PAD_CR_VALUE; + ext_ctrl_mpeg4[12].value = mpeg4_arg->CrPadVal; + + ext_ctrl_mpeg4[13].id = V4L2_CID_CODEC_MFC5X_ENC_RC_FRAME_ENABLE; + ext_ctrl_mpeg4[13].value = mpeg4_arg->EnableFRMRateControl; + ext_ctrl_mpeg4[14].id = V4L2_CID_CODEC_MFC5X_ENC_MPEG4_VOP_TIME_RES; + ext_ctrl_mpeg4[14].value = mpeg4_arg->TimeIncreamentRes; + ext_ctrl_mpeg4[15].id = V4L2_CID_CODEC_MFC5X_ENC_MPEG4_VOP_FRM_DELTA; + ext_ctrl_mpeg4[15].value = mpeg4_arg->VopTimeIncreament; + ext_ctrl_mpeg4[16].id = V4L2_CID_CODEC_MFC5X_ENC_RC_BIT_RATE; + ext_ctrl_mpeg4[16].value = mpeg4_arg->Bitrate; + + ext_ctrl_mpeg4[17].id = V4L2_CID_CODEC_MFC5X_ENC_MPEG4_RC_FRAME_QP; + ext_ctrl_mpeg4[17].value = mpeg4_arg->FrameQp; + ext_ctrl_mpeg4[18].id = V4L2_CID_CODEC_MFC5X_ENC_MPEG4_RC_P_FRAME_QP; + ext_ctrl_mpeg4[18].value = mpeg4_arg->FrameQp_P; + ext_ctrl_mpeg4[19].id = V4L2_CID_CODEC_MFC5X_ENC_MPEG4_RC_B_FRAME_QP; + ext_ctrl_mpeg4[19].value = mpeg4_arg->FrameQp_B; + + ext_ctrl_mpeg4[20].id = V4L2_CID_CODEC_MFC5X_ENC_MPEG4_RC_MAX_QP; + ext_ctrl_mpeg4[20].value = mpeg4_arg->QSCodeMax; + ext_ctrl_mpeg4[21].id = V4L2_CID_CODEC_MFC5X_ENC_MPEG4_RC_MIN_QP; + ext_ctrl_mpeg4[21].value = mpeg4_arg->QSCodeMin; + ext_ctrl_mpeg4[22].id = V4L2_CID_CODEC_MFC5X_ENC_RC_REACTION_COEFF; + ext_ctrl_mpeg4[22].value = mpeg4_arg->CBRPeriodRf; + + if (V4L2_CODEC_MFC5X_ENC_FRAME_SKIP_MODE_LEVEL == pCTX->enc_frameskip) { + ext_ctrl_mpeg4[23].id = V4L2_CID_CODEC_MFC5X_ENC_FRAME_SKIP_MODE; + ext_ctrl_mpeg4[23].value = V4L2_CODEC_MFC5X_ENC_FRAME_SKIP_MODE_LEVEL; + } else if(V4L2_CODEC_MFC5X_ENC_FRAME_SKIP_MODE_VBV_BUF_SIZE == pCTX->enc_frameskip) { + ext_ctrl_mpeg4[23].id = V4L2_CID_CODEC_MFC5X_ENC_FRAME_SKIP_MODE; + ext_ctrl_mpeg4[23].value = V4L2_CODEC_MFC5X_ENC_FRAME_SKIP_MODE_VBV_BUF_SIZE; + } else { /* ENC_FRAME_SKIP_MODE_DISABLE (default) */ + ext_ctrl_mpeg4[23].id = V4L2_CID_CODEC_MFC5X_ENC_FRAME_SKIP_MODE; + ext_ctrl_mpeg4[23].value = V4L2_CODEC_MFC5X_ENC_FRAME_SKIP_MODE_DISABLE; + } + + ext_ctrl_mpeg4[24].id = V4L2_CID_CODEC_MFC5X_ENC_VBV_BUF_SIZE; + ext_ctrl_mpeg4[24].value = 0; + + ext_ctrl_mpeg4[25].id = V4L2_CID_CODEC_MFC5X_ENC_SEQ_HDR_MODE; + ext_ctrl_mpeg4[25].value = 0; + + ext_ctrl_mpeg4[26].id = V4L2_CID_CODEC_MFC5X_ENC_RC_FIXED_TARGET_BIT; + ext_ctrl_mpeg4[26].value = V4L2_CODEC_MFC5X_ENC_SW_ENABLE; + break; + + case H263_ENC: + ext_ctrl_h263[0].id = V4L2_CID_CODEC_MFC5X_ENC_GOP_SIZE; + ext_ctrl_h263[0].value = h263_arg->IDRPeriod; + + ext_ctrl_h263[1].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_MODE; + ext_ctrl_h263[1].value = h263_arg->SliceMode; /* 0: one, Check is needed if h264 support multi-slice */ + + ext_ctrl_h263[2].id = V4L2_CID_CODEC_MFC5X_ENC_INTRA_REFRESH_MB; + ext_ctrl_h263[2].value = h263_arg->RandomIntraMBRefresh; + + ext_ctrl_h263[3].id = V4L2_CID_CODEC_MFC5X_ENC_PAD_CTRL_ENABLE; + ext_ctrl_h263[3].value = h263_arg->PadControlOn; + ext_ctrl_h263[4].id = V4L2_CID_CODEC_MFC5X_ENC_PAD_LUMA_VALUE; + ext_ctrl_h263[4].value = h263_arg->LumaPadVal; + ext_ctrl_h263[5].id = V4L2_CID_CODEC_MFC5X_ENC_PAD_CB_VALUE; + ext_ctrl_h263[5].value = h263_arg->CbPadVal; + ext_ctrl_h263[6].id = V4L2_CID_CODEC_MFC5X_ENC_PAD_CR_VALUE; + ext_ctrl_h263[6].value = h263_arg->CrPadVal; + + ext_ctrl_h263[7].id = V4L2_CID_CODEC_MFC5X_ENC_RC_FRAME_ENABLE; + ext_ctrl_h263[7].value = h263_arg->EnableFRMRateControl; + + ext_ctrl_h263[8].id = V4L2_CID_CODEC_MFC5X_ENC_H263_RC_FRAME_RATE; + ext_ctrl_h263[8].value = h263_arg->FrameRate; + + ext_ctrl_h263[9].id = V4L2_CID_CODEC_MFC5X_ENC_RC_BIT_RATE; + ext_ctrl_h263[9].value = h263_arg->Bitrate; + + ext_ctrl_h263[10].id = V4L2_CID_CODEC_MFC5X_ENC_H263_RC_FRAME_QP; + ext_ctrl_h263[10].value = h263_arg->FrameQp; + ext_ctrl_h263[11].id = V4L2_CID_CODEC_MFC5X_ENC_H263_RC_P_FRAME_QP; + ext_ctrl_h263[11].value = h263_arg->FrameQp_P; + + ext_ctrl_h263[12].id = V4L2_CID_CODEC_MFC5X_ENC_H263_RC_MAX_QP; + ext_ctrl_h263[12].value = h263_arg->QSCodeMax; + ext_ctrl_h263[13].id = V4L2_CID_CODEC_MFC5X_ENC_H263_RC_MIN_QP; + ext_ctrl_h263[13].value = h263_arg->QSCodeMin; + ext_ctrl_h263[14].id = V4L2_CID_CODEC_MFC5X_ENC_RC_REACTION_COEFF; + ext_ctrl_h263[14].value = h263_arg->CBRPeriodRf; + + if (V4L2_CODEC_MFC5X_ENC_FRAME_SKIP_MODE_LEVEL == pCTX->enc_frameskip) { + ext_ctrl_h263[15].id = V4L2_CID_CODEC_MFC5X_ENC_FRAME_SKIP_MODE; + ext_ctrl_h263[15].value = V4L2_CODEC_MFC5X_ENC_FRAME_SKIP_MODE_LEVEL; + } else if(V4L2_CODEC_MFC5X_ENC_FRAME_SKIP_MODE_VBV_BUF_SIZE== pCTX->enc_frameskip) { + ext_ctrl_h263[15].id = V4L2_CID_CODEC_MFC5X_ENC_FRAME_SKIP_MODE; + ext_ctrl_h263[15].value = V4L2_CODEC_MFC5X_ENC_FRAME_SKIP_MODE_VBV_BUF_SIZE; + } else { /* ENC_FRAME_SKIP_MODE_DISABLE (default) */ + ext_ctrl_h263[15].id = V4L2_CID_CODEC_MFC5X_ENC_FRAME_SKIP_MODE; + ext_ctrl_h263[15].value = V4L2_CODEC_MFC5X_ENC_FRAME_SKIP_MODE_DISABLE; + } + + ext_ctrl_h263[16].id = V4L2_CID_CODEC_MFC5X_ENC_VBV_BUF_SIZE; + ext_ctrl_h263[16].value = 0; + + ext_ctrl_h263[17].id = V4L2_CID_CODEC_MFC5X_ENC_SEQ_HDR_MODE; + ext_ctrl_h263[17].value = 0; + + ext_ctrl_h263[18].id = V4L2_CID_CODEC_MFC5X_ENC_RC_FIXED_TARGET_BIT; + ext_ctrl_h263[18].value = V4L2_CODEC_MFC5X_ENC_SW_ENABLE; + break; + + case H264_ENC: + ext_ctrl[0].id = V4L2_CID_CODEC_MFC5X_ENC_H264_PROFILE; + ext_ctrl[0].value = h264_arg->ProfileIDC; + ext_ctrl[1].id = V4L2_CID_CODEC_MFC5X_ENC_H264_LEVEL; + ext_ctrl[1].value = h264_arg->LevelIDC; + ext_ctrl[2].id = V4L2_CID_CODEC_MFC5X_ENC_GOP_SIZE; + ext_ctrl[2].value = h264_arg->IDRPeriod; + ext_ctrl[3].id = V4L2_CID_CODEC_MFC5X_ENC_H264_MAX_REF_PIC; + ext_ctrl[3].value = h264_arg->NumberReferenceFrames; + ext_ctrl[4].id = V4L2_CID_CODEC_MFC5X_ENC_H264_NUM_REF_PIC_4P; + ext_ctrl[4].value = h264_arg->NumberRefForPframes; + ext_ctrl[5].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_MODE; + ext_ctrl[5].value = h264_arg->SliceMode; /* 0: one, 1: fixed #mb, 3: fixed #bytes */ + if (h264_arg->SliceMode == 0) { + ext_ctrl[6].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_MB; + ext_ctrl[6].value = 1; /* default */ + ext_ctrl[7].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_BIT; + ext_ctrl[7].value = 1900; /* default */ + } else if (h264_arg->SliceMode == 1) { + ext_ctrl[6].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_MB; + ext_ctrl[6].value = h264_arg->SliceArgument; + ext_ctrl[7].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_BIT; + ext_ctrl[7].value = 1900; /* default */ + } else if (h264_arg->SliceMode == 3) { + ext_ctrl[6].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_MB; + ext_ctrl[6].value = 1; /* default */ + ext_ctrl[7].id = V4L2_CID_CODEC_MFC5X_ENC_MULTI_SLICE_BIT; + ext_ctrl[7].value = h264_arg->SliceArgument; + } + /* + It should be set using h264_arg->NumberBFrames after being handled by appl. + */ + ext_ctrl[8].id = V4L2_CID_CODEC_MFC5X_ENC_H264_B_FRAMES; + ext_ctrl[8].value = h264_arg->NumberBFrames; + ext_ctrl[9].id = V4L2_CID_CODEC_MFC5X_ENC_H264_LOOP_FILTER_MODE; + ext_ctrl[9].value = h264_arg->LoopFilterDisable; + ext_ctrl[10].id = V4L2_CID_CODEC_MFC5X_ENC_H264_LOOP_FILTER_ALPHA; + ext_ctrl[10].value = h264_arg->LoopFilterAlphaC0Offset; + ext_ctrl[11].id = V4L2_CID_CODEC_MFC5X_ENC_H264_LOOP_FILTER_BETA; + ext_ctrl[11].value = h264_arg->LoopFilterBetaOffset; + ext_ctrl[12].id = V4L2_CID_CODEC_MFC5X_ENC_H264_ENTROPY_MODE; + ext_ctrl[12].value = h264_arg->SymbolMode; + ext_ctrl[13].id = V4L2_CID_CODEC_MFC5X_ENC_H264_INTERLACE; + ext_ctrl[13].value = h264_arg->PictureInterlace; + ext_ctrl[14].id = V4L2_CID_CODEC_MFC5X_ENC_H264_8X8_TRANSFORM; + ext_ctrl[14].value = h264_arg->Transform8x8Mode; + ext_ctrl[15].id = V4L2_CID_CODEC_MFC5X_ENC_INTRA_REFRESH_MB; + ext_ctrl[15].value = h264_arg->RandomIntraMBRefresh; + ext_ctrl[16].id = V4L2_CID_CODEC_MFC5X_ENC_PAD_CTRL_ENABLE; + ext_ctrl[16].value = h264_arg->PadControlOn; + ext_ctrl[17].id = V4L2_CID_CODEC_MFC5X_ENC_PAD_LUMA_VALUE; + ext_ctrl[17].value = h264_arg->LumaPadVal; + ext_ctrl[18].id = V4L2_CID_CODEC_MFC5X_ENC_PAD_CB_VALUE; + ext_ctrl[18].value = h264_arg->CbPadVal; + ext_ctrl[19].id = V4L2_CID_CODEC_MFC5X_ENC_PAD_CR_VALUE; + ext_ctrl[19].value = h264_arg->CrPadVal; + ext_ctrl[20].id = V4L2_CID_CODEC_MFC5X_ENC_RC_FRAME_ENABLE; + ext_ctrl[20].value = h264_arg->EnableFRMRateControl; + ext_ctrl[21].id = V4L2_CID_CODEC_MFC5X_ENC_H264_RC_MB_ENABLE; + ext_ctrl[21].value = h264_arg->EnableMBRateControl; + ext_ctrl[22].id = V4L2_CID_CODEC_MFC5X_ENC_H264_RC_FRAME_RATE; + ext_ctrl[22].value = h264_arg->FrameRate; + ext_ctrl[23].id = V4L2_CID_CODEC_MFC5X_ENC_RC_BIT_RATE; + /* FIXME temporary fix */ + if (h264_arg->Bitrate) + ext_ctrl[23].value = h264_arg->Bitrate; + else + ext_ctrl[23].value = 1; /* just for testing Movi studio */ + ext_ctrl[24].id = V4L2_CID_CODEC_MFC5X_ENC_H264_RC_FRAME_QP; + ext_ctrl[24].value = h264_arg->FrameQp; + ext_ctrl[25].id = V4L2_CID_CODEC_MFC5X_ENC_H264_RC_P_FRAME_QP; + ext_ctrl[25].value = h264_arg->FrameQp_P; + ext_ctrl[26].id = V4L2_CID_CODEC_MFC5X_ENC_H264_RC_B_FRAME_QP; + ext_ctrl[26].value = h264_arg->FrameQp_B; + ext_ctrl[27].id = V4L2_CID_CODEC_MFC5X_ENC_H264_RC_MAX_QP; + ext_ctrl[27].value = h264_arg->QSCodeMax; + ext_ctrl[28].id = V4L2_CID_CODEC_MFC5X_ENC_H264_RC_MIN_QP; + ext_ctrl[28].value = h264_arg->QSCodeMin; + ext_ctrl[29].id = V4L2_CID_CODEC_MFC5X_ENC_RC_REACTION_COEFF; + ext_ctrl[29].value = h264_arg->CBRPeriodRf; + ext_ctrl[30].id = V4L2_CID_CODEC_MFC5X_ENC_H264_RC_MB_DARK; + ext_ctrl[30].value = h264_arg->DarkDisable; + ext_ctrl[31].id = V4L2_CID_CODEC_MFC5X_ENC_H264_RC_MB_SMOOTH; + ext_ctrl[31].value = h264_arg->SmoothDisable; + ext_ctrl[32].id = V4L2_CID_CODEC_MFC5X_ENC_H264_RC_MB_STATIC; + ext_ctrl[32].value = h264_arg->StaticDisable; + ext_ctrl[33].id = V4L2_CID_CODEC_MFC5X_ENC_H264_RC_MB_ACTIVITY; + ext_ctrl[33].value = h264_arg->ActivityDisable; + + /* doesn't have to be set */ + ext_ctrl[34].id = V4L2_CID_CODEC_MFC5X_ENC_H264_OPEN_GOP; + ext_ctrl[34].value = V4L2_CODEC_MFC5X_ENC_SW_DISABLE; + ext_ctrl[35].id = V4L2_CID_CODEC_MFC5X_ENC_H264_I_PERIOD; + ext_ctrl[35].value = 10; + + if (V4L2_CODEC_MFC5X_ENC_FRAME_SKIP_MODE_LEVEL == pCTX->enc_frameskip) { + ext_ctrl[36].id = V4L2_CID_CODEC_MFC5X_ENC_FRAME_SKIP_MODE; + ext_ctrl[36].value = V4L2_CODEC_MFC5X_ENC_FRAME_SKIP_MODE_LEVEL; + } else if(V4L2_CODEC_MFC5X_ENC_FRAME_SKIP_MODE_VBV_BUF_SIZE== pCTX->enc_frameskip) { + ext_ctrl[36].id = V4L2_CID_CODEC_MFC5X_ENC_FRAME_SKIP_MODE; + ext_ctrl[36].value = V4L2_CODEC_MFC5X_ENC_FRAME_SKIP_MODE_VBV_BUF_SIZE; + } else { /* ENC_FRAME_SKIP_MODE_DISABLE (default) */ + ext_ctrl[36].id = V4L2_CID_CODEC_MFC5X_ENC_FRAME_SKIP_MODE; + ext_ctrl[36].value = V4L2_CODEC_MFC5X_ENC_FRAME_SKIP_MODE_DISABLE; + } + + ext_ctrl[37].id = V4L2_CID_CODEC_MFC5X_ENC_VBV_BUF_SIZE; + ext_ctrl[37].value = 0; + + ext_ctrl[38].id = V4L2_CID_CODEC_MFC5X_ENC_SEQ_HDR_MODE; + ext_ctrl[38].value = 0; /* 0: seperated header + 1: header + first frame */ + + ext_ctrl[39].id = V4L2_CID_CODEC_MFC5X_ENC_RC_FIXED_TARGET_BIT; + ext_ctrl[39].value = V4L2_CODEC_MFC5X_ENC_SW_ENABLE; + + ext_ctrl[40].id = V4L2_CID_CODEC_MFC5X_ENC_H264_AR_VUI_ENABLE; + ext_ctrl[40].value = V4L2_CODEC_MFC5X_ENC_SW_DISABLE; + ext_ctrl[41].id = V4L2_CID_CODEC_MFC5X_ENC_H264_AR_VUI_IDC; + ext_ctrl[41].value = 0; + ext_ctrl[42].id = V4L2_CID_CODEC_MFC5X_ENC_H264_EXT_SAR_WIDTH; + ext_ctrl[42].value = 0; + ext_ctrl[43].id = V4L2_CID_CODEC_MFC5X_ENC_H264_EXT_SAR_HEIGHT; + ext_ctrl[43].value = 0; + + break; + + default: + LOGE("[%s] Undefined codec type",__func__); + ret = MFC_RET_INVALID_PARAM; + goto error_case1; + } + + ext_ctrls.ctrl_class = V4L2_CTRL_CLASS_CODEC; + if (pCTX->codecType == MPEG4_ENC) { + ext_ctrls.count = 27; + ext_ctrls.controls = ext_ctrl_mpeg4; + } else if (pCTX->codecType == H264_ENC) { + ext_ctrls.count = 44; + ext_ctrls.controls = ext_ctrl; + } else if (pCTX->codecType == H263_ENC) { + ext_ctrls.count = 19; + ext_ctrls.controls = ext_ctrl_h263; + } + + ret = ioctl(pCTX->hMFC, VIDIOC_S_EXT_CTRLS, &ext_ctrls); + if (ret != 0) { + LOGE("[%s] Failed to set extended controls",__func__); + ret = MFC_RET_ENC_INIT_FAIL; + goto error_case1; + } + + memset(&fmt, 0, sizeof(fmt)); + fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + + fmt.fmt.pix_mp.width = pCTX->width; + fmt.fmt.pix_mp.height = pCTX->height; + fmt.fmt.pix_mp.num_planes = 2; + fmt.fmt.pix_mp.plane_fmt[0].bytesperline = Align(fmt.fmt.pix_mp.width, 128); + fmt.fmt.pix_mp.plane_fmt[1].bytesperline = Align(fmt.fmt.pix_mp.width, 128); + + if (NV12_TILE == pCTX->framemap) { + fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT; /* 4:2:0, 2 Planes, 64x32 Tiles */ + fmt.fmt.pix_mp.plane_fmt[0].sizeimage = + Align(Align(fmt.fmt.pix_mp.width, 128) * Align(fmt.fmt.pix_mp.height, 32), 8192); /* tiled mode */ + fmt.fmt.pix_mp.plane_fmt[1].sizeimage = + Align(Align(fmt.fmt.pix_mp.width, 128) * Align(fmt.fmt.pix_mp.height >> 1, 32), 8192); /* tiled mode */ + } else { /* NV12_LINEAR (default) */ + fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M; /* 4:2:0, 2 Planes, linear */ + fmt.fmt.pix_mp.plane_fmt[0].sizeimage = + Align((fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height), 2048); /* linear mode, 2K align */ + fmt.fmt.pix_mp.plane_fmt[1].sizeimage = + Align((fmt.fmt.pix_mp.width * (fmt.fmt.pix_mp.height >> 1)), 2048); /* linear mode, 2K align */ + } + + ret = ioctl(pCTX->hMFC, VIDIOC_S_FMT, &fmt); + if (ret != 0) { + LOGE("[%s] S_FMT failed on MFC output stream",__func__); + ret = MFC_RET_ENC_INIT_FAIL; + goto error_case1; + } + + /* capture (dst) */ + memset(&fmt, 0, sizeof(fmt)); + + switch (pCTX->codecType) { + case H264_ENC: + fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264; + break; + case MPEG4_ENC: + fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_MPEG4; + break; + case H263_ENC: + fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H263; + break; + default: + LOGE("[%s] Codec has not been recognised",__func__); + return MFC_RET_ENC_INIT_FAIL; + } + + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + fmt.fmt.pix_mp.plane_fmt[0].sizeimage = MAX_STREAM_SIZE; + + ret = ioctl(pCTX->hMFC, VIDIOC_S_FMT, &fmt); + if (ret != 0) { + LOGE("[%s] S_FMT failed on MFC output stream",__func__); + ret = MFC_RET_ENC_INIT_FAIL; + goto error_case1; + } + + /* 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_ENC_INIT_FAIL; + goto error_case1; + } + + /* Initialize streams for input */ + memset(&reqbuf, 0, sizeof(reqbuf)); + reqbuf.count = MFC_ENC_NUM_SRC_BUFS; + reqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + if (pCTX->v4l2_enc.bInputPhyVir) + reqbuf.memory = V4L2_MEMORY_USERPTR; + else + reqbuf.memory = V4L2_MEMORY_MMAP; + + ret = ioctl(pCTX->hMFC, VIDIOC_REQBUFS, &reqbuf); + if (ret != 0) { + LOGE("[%s] Reqbufs src ioctl failed",__func__); + ret = MFC_RET_ENC_INIT_FAIL; + goto error_case1; + } + pCTX->v4l2_enc.mfc_num_src_bufs = reqbuf.count; + + if (!pCTX->v4l2_enc.bInputPhyVir) { + /* Then the buffers have to be queried and mmaped */ + for (i = 0; i < pCTX->v4l2_enc.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 = 2; + + ret = ioctl(pCTX->hMFC, VIDIOC_QUERYBUF, &buf); + if (ret != 0) { + LOGE("[%s] Querybuf src ioctl failed",__func__); + ret = MFC_RET_ENC_INIT_FAIL; + goto error_case2; + } + + pCTX->v4l2_enc.mfc_src_bufs_len[0] = buf.m.planes[0].length; + pCTX->v4l2_enc.mfc_src_bufs_len[1] = buf.m.planes[1].length; + + pCTX->v4l2_enc.mfc_src_phys[i][0] = buf.m.planes[0].cookie; + pCTX->v4l2_enc.mfc_src_phys[i][1] = buf.m.planes[1].cookie; + + pCTX->v4l2_enc.mfc_src_bufs[i][0] = + 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_enc.mfc_src_bufs[i][0] == MAP_FAILED) { + LOGE("[%s] Mmap on src buffer (0) failed",__func__); + ret = MFC_RET_ENC_INIT_FAIL; + goto error_case2; + } + + pCTX->v4l2_enc.mfc_src_bufs[i][1] = + mmap(NULL, buf.m.planes[1].length, PROT_READ | PROT_WRITE, + MAP_SHARED, pCTX->hMFC, buf.m.planes[1].m.mem_offset); + if (pCTX->v4l2_enc.mfc_src_bufs[i][1] == MAP_FAILED) { + munmap(pCTX->v4l2_enc.mfc_src_bufs[i][0], pCTX->v4l2_enc.mfc_src_bufs_len[0]); + LOGE("[%s] Mmap on src buffer (1) failed",__func__); + ret = MFC_RET_ENC_INIT_FAIL; + goto error_case2; + } + } + } else + LOGV("[%s] Camera Phys src buf %d",__func__,reqbuf.count); + + for (i = 0; i<pCTX->v4l2_enc.mfc_num_src_bufs; i++) + pCTX->v4l2_enc.mfc_src_buf_flags[i] = BUF_DEQUEUED; + + pCTX->v4l2_enc.beingUsedIndex = 0; + + pCTX->sizeFrmBuf.luma = (unsigned int)(pCTX->width * pCTX->height); + pCTX->sizeFrmBuf.chroma = (unsigned int)((pCTX->width * pCTX->height) >> 1); + pCTX->inter_buff_status |= MFC_USE_YUV_BUFF; + + /* Initialize stream for output */ + memset(&reqbuf, 0, sizeof(reqbuf)); + reqbuf.count = MFC_ENC_MAX_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] Reqbufs dst ioctl failed",__func__); + ret = MFC_RET_ENC_INIT_FAIL; + goto error_case2; + } + + pCTX->v4l2_enc.mfc_num_dst_bufs = reqbuf.count; + + for (i = 0; i<MFC_ENC_MAX_DST_BUFS; ++i) { + memset(&buf, 0, sizeof(buf)); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_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] Querybuf dst ioctl failed",__func__); + ret = MFC_RET_ENC_INIT_FAIL; + goto error_case3; + } + + pCTX->v4l2_enc.mfc_dst_bufs_len = buf.m.planes[0].length; + pCTX->v4l2_enc.mfc_dst_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_enc.mfc_dst_bufs[i] == MAP_FAILED) { + LOGE("[%s] Mmap on dst buffer failed",__func__); + ret = MFC_RET_ENC_INIT_FAIL; + goto error_case3; + } + + ret = ioctl(pCTX->hMFC, VIDIOC_QBUF, &buf); + if (ret != 0) { + LOGE("[%s] VIDIOC_QBUF failed, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE",__func__); + ret = MFC_RET_ENC_INIT_FAIL; + goto error_case3; + } + } + + pCTX->sizeStrmBuf = MAX_ENCODER_OUTPUT_BUFFER_SIZE; + pCTX->inter_buff_status |= MFC_USE_STRM_BUFF; + + type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + + ret = ioctl(pCTX->hMFC, VIDIOC_STREAMON, &type); + if (ret != 0) { + LOGE("[%s] V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, VIDIOC_STREAMON failed",__func__); + ret = MFC_RET_ENC_INIT_FAIL; + goto error_case3; + } + + memset(&buf, 0, sizeof(buf)); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + buf.memory = V4L2_MEMORY_MMAP; + buf.m.planes = planes; + buf.length = 1; + + /* note: #define POLLOUT 0x0004 */ + poll_events.fd = pCTX->hMFC; + poll_events.events = POLLIN | POLLERR; + poll_events.revents = 0; + + /* wait for header encoding */ + do { + poll_state = poll((struct pollfd*)&poll_events, 1, POLL_ENC_WAIT_TIMEOUT); + if (0 < poll_state) { + if (poll_events.revents & POLLIN) { /* POLLIN */ + ret = ioctl(pCTX->hMFC, VIDIOC_DQBUF, &buf); + if (ret == 0) + break; + } else if(poll_events.revents & POLLERR) { /*POLLERR */ + LOGE("[%s] POLLERR\n",__func__); + ret = MFC_RET_ENC_INIT_FAIL; + goto error_case3; + } else { + LOGE("[%s] poll() returns 0x%x\n",__func__, poll_events.revents); + ret = MFC_RET_ENC_INIT_FAIL; + goto error_case3; + } + } else if(0 > poll_state) { + ret = MFC_RET_ENC_INIT_FAIL; + goto error_case3; + } + } while (0 == poll_state); + + pCTX->v4l2_enc.mfc_dst_bufs_bytes_used_len = buf.m.planes[0].bytesused; + pCTX->virStrmBuf = pCTX->v4l2_enc.mfc_dst_bufs[buf.index]; + + /* stream dequeued index */ + index = buf.index; + memset(&buf, 0, sizeof(buf)); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = index; + buf.m.planes = planes; + buf.length = 1; + + ret = ioctl(pCTX->hMFC, VIDIOC_QBUF, &buf); + if (ret != 0) { + LOGE("[%s] VIDIOC_QBUF failed, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE",__func__); + ret = MFC_RET_ENC_INIT_FAIL; + goto error_case3; + } + LOGV("[%s] Strm out idx %d",__func__,index); + + return MFC_RET_OK; +error_case3: + for (j = 0; j < i; j++) + munmap(pCTX->v4l2_enc.mfc_dst_bufs[j], pCTX->v4l2_enc.mfc_dst_bufs_len); + + i = pCTX->v4l2_enc.mfc_num_src_bufs; +error_case2: + if (!pCTX->v4l2_enc.bInputPhyVir) { + for (j = 0; j < i; j++) { + munmap(pCTX->v4l2_enc.mfc_src_bufs[j][0], pCTX->v4l2_enc.mfc_src_bufs_len[0]); + munmap(pCTX->v4l2_enc.mfc_src_bufs[j][1], pCTX->v4l2_enc.mfc_src_bufs_len[1]); + } + } +error_case1: + return ret; +} + +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncGetInBuf(void *openHandle, SSBSIP_MFC_ENC_INPUT_INFO *input_info) +{ + _MFCLIB *pCTX; + int i; + + if (openHandle == NULL) { + LOGE("[%s] openHandle is NULL\n",__func__); + return MFC_RET_INVALID_PARAM; + } + + pCTX = (_MFCLIB *) openHandle; + + if (pCTX->v4l2_enc.bInputPhyVir) { + input_info->YPhyAddr = (void*)0; + input_info->CPhyAddr = (void*)0; + input_info->YVirAddr = (void*)0; + input_info->CVirAddr = (void*)0; + + if (NV12_TILE == pCTX->framemap) { + /* 4:2:0, 2 Planes, 64x32 Tiles */ + input_info->YSize = Align(Align(pCTX->width, 128) * Align(pCTX->height, 32), 8192); /* tiled mode */ + input_info->CSize = Align(Align(pCTX->width, 128) * Align(pCTX->height >> 1, 32), 8192); /* tiled mode */ + } else { /* NV12_LINEAR (default) */ + /* 4:2:0, 2 Planes, linear */ + input_info->YSize = Align(Align(pCTX->width, 16) * Align(pCTX->height, 16), 2048); /* width = 16B, height = 16B align */ + input_info->CSize = Align(Align(pCTX->width, 16) * Align(pCTX->height >> 1, 8), 2048); /* width = 16B, height = 8B align */ + } + } else { + for (i = 0; i < pCTX->v4l2_enc.mfc_num_src_bufs; i++) + if (BUF_DEQUEUED == pCTX->v4l2_enc.mfc_src_buf_flags[i]) + break; + + if (i == pCTX->v4l2_enc.mfc_num_src_bufs) { + LOGV("[%s] No buffer is available.",__func__); + return MFC_RET_ENC_GET_INBUF_FAIL; + } else { + /* FIXME check this for correct physical address */ + input_info->YPhyAddr = (void*)pCTX->v4l2_enc.mfc_src_phys[i][0]; + input_info->CPhyAddr = (void*)pCTX->v4l2_enc.mfc_src_phys[i][1]; + input_info->YVirAddr = (void*)pCTX->v4l2_enc.mfc_src_bufs[i][0]; + input_info->CVirAddr = (void*)pCTX->v4l2_enc.mfc_src_bufs[i][1]; + input_info->YSize = (int)pCTX->v4l2_enc.mfc_src_bufs_len[0]; + input_info->CSize = (int)pCTX->v4l2_enc.mfc_src_bufs_len[1]; + + pCTX->v4l2_enc.mfc_src_buf_flags[i] = BUF_ENQUEUED; + } + } + LOGV("[%s] Input Buffer idx %d",__func__,i); + return MFC_RET_OK; +} + + +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncSetInBuf(void *openHandle, SSBSIP_MFC_ENC_INPUT_INFO *input_info) +{ + _MFCLIB *pCTX; + struct v4l2_buffer qbuf; + struct v4l2_plane planes[MFC_ENC_NUM_PLANES]; + int ret,i; + + if (openHandle == NULL) { + LOGE("[%s] openHandle is NULL\n",__func__); + return MFC_RET_INVALID_PARAM; + } + + pCTX = (_MFCLIB *) openHandle; + + memset(&qbuf, 0, sizeof(qbuf)); + if (pCTX->v4l2_enc.bInputPhyVir) { + qbuf.memory = V4L2_MEMORY_USERPTR; + qbuf.index = pCTX->v4l2_enc.beingUsedIndex; + planes[0].m.userptr = (unsigned long)input_info->YPhyAddr; + planes[0].length = input_info->YSize; + planes[0].bytesused = input_info->YSize; + planes[1].m.userptr = (unsigned long)input_info->CPhyAddr; + planes[1].length = input_info->CSize; + planes[1].bytesused = input_info->CSize; + + /* FIXME, this is only for case of not using B frame, + Camera side should know which buffer is queued() refering to index of + MFC dqbuf() */ + pCTX->v4l2_enc.beingUsedIndex++; + pCTX->v4l2_enc.beingUsedIndex %= MFC_ENC_NUM_SRC_BUFS; + LOGV("[%s] Phy Input Buffer idx Queued %d",__func__,pCTX->v4l2_enc.beingUsedIndex); + } else { + for (i = 0; i < pCTX->v4l2_enc.mfc_num_src_bufs; i++) + if (pCTX->v4l2_enc.mfc_src_bufs[i][0] == input_info->YVirAddr) + break; + + if (i == pCTX->v4l2_enc.mfc_num_src_bufs) { + LOGE("[%s] Can not use the buffer",__func__); + return MFC_RET_INVALID_PARAM; + } else { + pCTX->v4l2_enc.beingUsedIndex = i; + //pCTX->v4l2_enc.mfc_src_buf_flags[i] = BUF_ENQUEUED; + } + qbuf.memory = V4L2_MEMORY_MMAP; + qbuf.index = pCTX->v4l2_enc.beingUsedIndex; + planes[0].bytesused = pCTX->width * pCTX->height; + planes[1].bytesused = (pCTX->width * pCTX->height) >> 1; + LOGV("[%s] Input Buffer idx Queued %d",__func__,pCTX->v4l2_enc.beingUsedIndex); + } + + qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + 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_OUTPUT_MPLANE",__func__); + return MFC_RET_ENC_SET_INBUF_FAIL; + } + + return MFC_RET_OK; +} + +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncGetOutBuf(void *openHandle, SSBSIP_MFC_ENC_OUTPUT_INFO *output_info) +{ + _MFCLIB *pCTX; + + if (openHandle == NULL) { + LOGE("[%s] openHandle is NULL\n",__func__); + return MFC_RET_INVALID_PARAM; + } + + pCTX = (_MFCLIB *) openHandle; + + if (pCTX->v4l2_enc.bRunning == 0) { + pCTX->encodedHeaderSize = pCTX->v4l2_enc.mfc_dst_bufs_bytes_used_len; + output_info->dataSize = 0; + } else { + output_info->dataSize = pCTX->v4l2_enc.mfc_dst_bufs_bytes_used_len; + } + + output_info->headerSize = pCTX->encodedHeaderSize; + output_info->frameType = pCTX->encodedframeType; + output_info->StrmPhyAddr = (void *)0; + output_info->StrmVirAddr = (void *)pCTX->virStrmBuf; + output_info->encodedYPhyAddr = (void*)0; + output_info->encodedCPhyAddr = (void*)0; + + return MFC_RET_OK; +} + +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncSetOutBuf(void *openHandle, void *phyOutbuf, void *virOutbuf, int outputBufferSize) +{ + if (openHandle == NULL) { + LOGE("[%s] openHandle is NULL\n",__func__); + return MFC_RET_INVALID_PARAM; + } + + return MFC_RET_ENC_SET_OUTBUF_FAIL; +} + +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncExe(void *openHandle) +{ + int ret; + int dequeued_index; + int loopcnt = 0; + _MFCLIB *pCTX; + + struct v4l2_buffer qbuf; + struct v4l2_plane planes[MFC_ENC_NUM_PLANES]; + enum v4l2_buf_type type; + + struct v4l2_control ctrl; + + struct pollfd poll_events; + int poll_state; + + LOGV("[%s] Enter \n",__func__); + if (openHandle == NULL) { + LOGE("[%s] openHandle is NULL\n",__func__); + return MFC_RET_INVALID_PARAM; + } + + pCTX = (_MFCLIB *) openHandle; + + ctrl.id = V4L2_CID_CODEC_FRAME_TAG; + ctrl.value = pCTX->inframetag; + + ret = ioctl(pCTX->hMFC, VIDIOC_S_CTRL, &ctrl); + if (ret != 0) { + LOGE("[%s] VIDIOC_S_CTRL failed, V4L2_CID_CODEC_FRAME_TAG",__func__); + return MFC_RET_ENC_EXE_ERR; + } + + if (pCTX->v4l2_enc.bRunning == 0) { + type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + ret = ioctl(pCTX->hMFC, VIDIOC_STREAMON, &type); + if (ret != 0) { + LOGE("[%s] VIDIOC_STREAMON failed, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE",__func__); + return MFC_RET_ENC_EXE_ERR; + } + + pCTX->v4l2_enc.bRunning = 1; + } + + memset(&qbuf, 0, sizeof(qbuf)); + qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + qbuf.memory = V4L2_MEMORY_MMAP; + qbuf.m.planes = planes; + qbuf.length = 1; + + /* note: #define POLLOUT 0x0004 */ + poll_events.fd = pCTX->hMFC; + poll_events.events = POLLIN | POLLERR; + poll_events.revents = 0; + + /* wait for encoding */ + do { + poll_state = poll((struct pollfd*)&poll_events, 1, POLL_ENC_WAIT_TIMEOUT); + if (0 < poll_state) { + if (poll_events.revents & POLLIN) { /* POLLIN */ + ret = ioctl(pCTX->hMFC, VIDIOC_DQBUF, &qbuf); + if (ret == 0) + break; + } else if (poll_events.revents & POLLERR) { /* POLLERR */ + LOGE("[%s] POLLERR\n",__func__); + return MFC_RET_ENC_EXE_ERR; + } else { + LOGE("[%s] poll() returns 0x%x\n",__func__, poll_events.revents); + return MFC_RET_ENC_EXE_ERR; + } + } else if (0 > poll_state) { + LOGE("[%s] poll() Encoder POLL Timeout 0x%x\n",__func__, poll_events.revents); + return MFC_RET_ENC_EXE_ERR; + } + loopcnt++; + } while ((0 == poll_state) && (loopcnt < 5)); + + if (pCTX->v4l2_enc.bRunning != 0) { + pCTX->encodedframeType = (qbuf.flags & 0x18) >> 3; /* encoded frame type */ + + LOGV("[%s] encoded frame type = %d\n",__func__, pCTX->encodedframeType); + switch (pCTX->encodedframeType) { + case 1: + pCTX->encodedframeType = MFC_FRAME_TYPE_I_FRAME; + break; + case 2: + pCTX->encodedframeType = MFC_FRAME_TYPE_P_FRAME; + break; + case 4: + pCTX->encodedframeType = MFC_FRAME_TYPE_B_FRAME; + break; + default: + LOGE("[%s] VIDIOC_DQBUF failed, encoded frame type is wrong",__func__); + } + } + + dequeued_index = qbuf.index; + + if (qbuf.m.planes[0].bytesused > 0) { /* FIXME later */ + pCTX->v4l2_enc.mfc_dst_bufs_bytes_used_len = qbuf.m.planes[0].bytesused; + } + + ctrl.id = V4L2_CID_CODEC_FRAME_TAG; + ctrl.value = 0; + + ret = ioctl(pCTX->hMFC, VIDIOC_G_CTRL, &ctrl); + if (ret != 0) { + LOGE("[%s] VIDIOC_G_CTRL failed, V4L2_CID_CODEC_FRAME_TAG",__func__); + return MFC_RET_ENC_EXE_ERR; + } + + pCTX->outframetagtop = ctrl.value; + + memset(&qbuf, 0, sizeof(qbuf)); + qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + qbuf.memory = V4L2_MEMORY_MMAP; + qbuf.index = dequeued_index; + qbuf.m.planes = planes; + qbuf.length = 1; + + 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_ENC_EXE_ERR; + } + + if (pCTX->v4l2_enc.bRunning != 0) { + memset(&qbuf, 0, sizeof(qbuf)); + qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + + if (pCTX->v4l2_enc.bInputPhyVir) + qbuf.memory = V4L2_MEMORY_USERPTR; + else + 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__); + return MFC_RET_ENC_EXE_ERR; + } + } + pCTX->v4l2_enc.mfc_src_buf_flags[qbuf.index] = BUF_DEQUEUED; + + /* Update context stream buffer address */ + pCTX->virStrmBuf = pCTX->v4l2_enc.mfc_dst_bufs[dequeued_index]; + LOGV("[%s] Strm out idx %d",__func__,dequeued_index); + + return MFC_RET_OK; +} + +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncSetConfig(void *openHandle, SSBSIP_MFC_ENC_CONF conf_type, void *value) +{ + _MFCLIB *pCTX; + + if (openHandle == NULL) { + LOGE("[%s] openHandle is NULL\n",__func__); + return MFC_RET_INVALID_PARAM; + } + + if (value == NULL) { + LOGE("[%s] value is NULL\n",__func__); + return MFC_RET_INVALID_PARAM; + } + + pCTX = (_MFCLIB *) openHandle; + + switch (conf_type) { + case MFC_ENC_SETCONF_FRAME_TAG: + pCTX->inframetag = *((unsigned int *)value); + return MFC_RET_OK; + + case MFC_ENC_SETCONF_ALLOW_FRAME_SKIP: + pCTX->enc_frameskip = *((int *)value); + return MFC_RET_OK; +#if 0 + case MFC_ENC_SETCONF_VUI_INFO: + vui_info = *((struct mfc_enc_vui_info *) value); + EncArg.args.set_config.in_config_value[0] = (int)(vui_info.aspect_ratio_idc); + EncArg.args.set_config.in_config_value[1] = 0; + break; + + case MFC_ENC_SETCONF_HIER_P: + hier_p_qp = *((struct mfc_enc_hier_p_qp *) value); + EncArg.args.set_config.in_config_value[0] = (int)(hier_p_qp.t0_frame_qp); + EncArg.args.set_config.in_config_value[1] = (int)(hier_p_qp.t2_frame_qp); + EncArg.args.set_config.in_config_value[2] = (int)(hier_p_qp.t3_frame_qp); + break; + + case MFC_ENC_SETCONF_I_PERIOD: +#endif + default: + LOGE("[%s] conf_type(%d) is NOT supported\n",__func__, conf_type); + return MFC_RET_INVALID_PARAM; + } + + return MFC_RET_OK; +} + +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncGetConfig(void *openHandle, SSBSIP_MFC_ENC_CONF conf_type, void *value) +{ + _MFCLIB *pCTX; + + pCTX = (_MFCLIB *) openHandle; + + if (openHandle == NULL) { + LOGE("[%s] openHandle is NULL\n",__func__); + return MFC_RET_INVALID_PARAM; + } + + if (value == NULL) { + LOGE("[%s] value is NULL\n",__func__); + return MFC_RET_INVALID_PARAM; + } + + switch (conf_type) { + case MFC_ENC_GETCONF_FRAME_TAG: + *((unsigned int *)value) = pCTX->outframetagtop; + break; + + default: + LOGE("[%s] conf_type(%d) is NOT supported\n",__func__, conf_type); + return MFC_RET_INVALID_PARAM; + } + + return MFC_RET_OK; +} + diff --git a/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/include/SsbSipMfcApi.h b/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/include/SsbSipMfcApi.h new file mode 100644 index 0000000..43e4ba0 --- /dev/null +++ b/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/include/SsbSipMfcApi.h @@ -0,0 +1,381 @@ +/* + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Global header for Samsung MFC (Multi Function Codec - FIMV) driver + * + * 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. + */ + +#ifndef _SSBSIP_MFC_API_H_ +#define _SSBSIP_MFC_API_H_ + +/*--------------------------------------------------------------------------------*/ +/* Definition */ +/*--------------------------------------------------------------------------------*/ +#define MAX_DECODER_INPUT_BUFFER_SIZE (1024 * 3072) +#define MAX_ENCODER_OUTPUT_BUFFER_SIZE (1024 * 3072) + +#define SUPPORT_1080P 1 + +#if SUPPORT_1080P +#define MMAP_BUFFER_SIZE_MMAP (70*1024*1024) /* only C110 use this value. in C210, memory size is decided in menuconfig*/ +#else +#define MMAP_BUFFER_SIZE_MMAP (62*1024*1024) +#endif + +#define SAMSUNG_MFC_DEV_NAME "/dev/video" + +#define SSBSIP_MFC_OK (1) +#define SSBSIP_MFC_FAIL (0) + +/*--------------------------------------------------------------------------------*/ +/* Structure and Type */ +/*--------------------------------------------------------------------------------*/ +typedef enum { + H264_DEC, + VC1_DEC, /* VC1 advaced Profile decoding */ + MPEG4_DEC, + XVID_DEC, + MPEG1_DEC, + MPEG2_DEC, + H263_DEC, + VC1RCV_DEC, /* VC1 simple/main profile decoding */ + FIMV1_DEC, + FIMV2_DEC, + FIMV3_DEC, + FIMV4_DEC, + H264_ENC, + MPEG4_ENC, + H263_ENC, + UNKNOWN_TYPE +} SSBSIP_MFC_CODEC_TYPE; + +typedef enum { + DONT_CARE = 0, + I_FRAME = 1, + NOT_CODED = 2 +} SSBSIP_MFC_FORCE_SET_FRAME_TYPE; + +typedef enum { + NV12_LINEAR = 0, + NV12_TILE +} SSBSIP_MFC_INSTRM_MODE_TYPE; + +typedef enum { + NO_CACHE = 0, + CACHE = 1 +} SSBIP_MFC_BUFFER_TYPE; + +typedef enum { + MFC_DEC_SETCONF_POST_ENABLE = 1, + MFC_DEC_SETCONF_EXTRA_BUFFER_NUM, + MFC_DEC_SETCONF_DISPLAY_DELAY, + MFC_DEC_SETCONF_IS_LAST_FRAME, + MFC_DEC_SETCONF_SLICE_ENABLE, + MFC_DEC_SETCONF_CRC_ENABLE, + MFC_DEC_SETCONF_FIMV1_WIDTH_HEIGHT, + MFC_DEC_SETCONF_FRAME_TAG, + MFC_DEC_GETCONF_CRC_DATA, + MFC_DEC_GETCONF_BUF_WIDTH_HEIGHT, + MFC_DEC_GETCONF_CROP_INFO, + MFC_DEC_GETCONF_FRAME_TAG, + + /* C210 specific feature */ + MFC_DEC_SETCONF_IMMEDIATELY_DISPLAY, + MFC_DEC_SETCONF_DPB_FLUSH, + MFC_DEC_SETCONF_PIXEL_CACHE, + MFC_DEC_GETCONF_WIDTH_HEIGHT +} SSBSIP_MFC_DEC_CONF; + +typedef enum { + MFC_ENC_SETCONF_FRAME_TYPE = 100, + MFC_ENC_SETCONF_CHANGE_FRAME_RATE, + MFC_ENC_SETCONF_CHANGE_BIT_RATE, + MFC_ENC_SETCONF_FRAME_TAG, + MFC_ENC_SETCONF_ALLOW_FRAME_SKIP, + MFC_ENC_GETCONF_FRAME_TAG, + + /* C210 specific feature */ + MFC_ENC_SETCONF_VUI_INFO, + MFC_ENC_SETCONF_I_PERIOD, + MFC_ENC_SETCONF_HIER_P +} SSBSIP_MFC_ENC_CONF; + +typedef enum { + MFC_GETOUTBUF_STATUS_NULL = 0, + MFC_GETOUTBUF_DECODING_ONLY = 1, + MFC_GETOUTBUF_DISPLAY_DECODING, + MFC_GETOUTBUF_DISPLAY_ONLY, + MFC_GETOUTBUF_DISPLAY_END, + MFC_GETOUTBUF_CHANGE_RESOL +} SSBSIP_MFC_DEC_OUTBUF_STATUS; + +typedef enum { + MFC_FRAME_TYPE_NOT_CODED, + MFC_FRAME_TYPE_I_FRAME, + MFC_FRAME_TYPE_P_FRAME, + MFC_FRAME_TYPE_B_FRAME, + MFC_FRAME_TYPE_OTHERS +} SSBSIP_MFC_FRAME_TYPE; + +typedef enum { + MFC_RET_OK = 1, + MFC_RET_FAIL = -1000, + MFC_RET_OPEN_FAIL = -1001, + MFC_RET_CLOSE_FAIL = -1002, + + MFC_RET_DEC_INIT_FAIL = -2000, + MFC_RET_DEC_EXE_TIME_OUT = -2001, + MFC_RET_DEC_EXE_ERR = -2002, + MFC_RET_DEC_GET_INBUF_FAIL = -2003, + MFC_RET_DEC_SET_INBUF_FAIL = -2004, + MFC_RET_DEC_GET_OUTBUF_FAIL = -2005, + MFC_RET_DEC_GET_CONF_FAIL = -2006, + MFC_RET_DEC_SET_CONF_FAIL = -2007, + + MFC_RET_ENC_INIT_FAIL = -3000, + MFC_RET_ENC_EXE_TIME_OUT = -3001, + MFC_RET_ENC_EXE_ERR = -3002, + MFC_RET_ENC_GET_INBUF_FAIL = -3003, + MFC_RET_ENC_SET_INBUF_FAIL = -3004, + MFC_RET_ENC_GET_OUTBUF_FAIL = -3005, + MFC_RET_ENC_SET_OUTBUF_FAIL = -3006, + MFC_RET_ENC_GET_CONF_FAIL = -3007, + MFC_RET_ENC_SET_CONF_FAIL = -3008, + + MFC_RET_INVALID_PARAM = -4000 +} SSBSIP_MFC_ERROR_CODE; + +typedef struct { + void *YPhyAddr; /* [OUT] physical address of Y */ + void *CPhyAddr; /* [OUT] physical address of CbCr */ + void *YVirAddr; /* [OUT] virtual address of Y */ + void *CVirAddr; /* [OUT] virtual address of CbCr */ + + int img_width; /* [OUT] width of real image */ + int img_height; /* [OUT] height of real image */ + int buf_width; /* [OUT] width aligned to 16 */ + int buf_height; /* [OUT] height alighed to 16 */ + + int timestamp_top; /* [OUT] timestamp of top filed(This is used for interlaced stream) */ + int timestamp_bottom; /* [OUT] timestamp of bottom filed(This is used for interlaced stream) */ + int consumedByte; /* [OUT] the number of byte consumed during decoding */ + int res_change; /* [OUT] whether resolution is changed or not. 0: not change, 1: increased, 2: decreased */ + int crop_top_offset; /* [OUT] crop information, top_offset */ + int crop_bottom_offset; /* [OUT] crop information, bottom_offset */ + int crop_left_offset; /* [OUT] crop information, left_offset */ + int crop_right_offset; /* [OUT] crop information, right_offset */ + int disp_pic_frame_type; /* [OUT] display picture frame type information */ + + /* C210 UMP feature */ + unsigned int y_cookie; /* [OUT] cookie for Y address */ + unsigned int c_cookie; /* [OUT] cookie for CbCr address, If it is 0, Y and CbCr is in continous memory */ +} SSBSIP_MFC_DEC_OUTPUT_INFO; + +typedef struct { + void *YPhyAddr; /* [IN/OUT] physical address of Y */ + void *CPhyAddr; /* [IN/OUT] physical address of CbCr */ + void *YVirAddr; /* [IN/OUT] virtual address of Y */ + void *CVirAddr; /* [IN/OUT] virtual address of CbCr */ + int YSize; /* [IN/OUT] input size of Y data */ + int CSize; /* [IN/OUT] input size of CbCr data */ + + /* C210 UMP feature */ + unsigned int y_cookie; /* [OUT] cookie for Y address */ + unsigned int c_cookie; /* [OUT] cookie for CbCr address, If it is 0, Y and CbCr is in continous memory */ +} SSBSIP_MFC_ENC_INPUT_INFO; + +typedef struct { + unsigned int dataSize; /* [OUT] encoded data size(without header) */ + unsigned int headerSize; /* [OUT] encoded header size */ + unsigned int frameType; /* [OUT] frame type of encoded stream */ + void *StrmPhyAddr; /* [OUT] physical address of Y */ + void *StrmVirAddr; /* [OUT] virtual address of Y */ + void *encodedYPhyAddr; /* [OUT] physical address of Y which is flushed */ + void *encodedCPhyAddr; /* [OUT] physical address of C which is flushed */ + + /* C210 UMP feature */ + unsigned int strm_cookie; /* [OUT] cooke for stream buffer */ + unsigned int y_encoded_cookie; /* [OUT] cookie for Y address */ + unsigned int c_encoded_cookie; /* [OUT] cookie for CbCr address, If it is 0, Y and CbCr is in continous memory */ +} SSBSIP_MFC_ENC_OUTPUT_INFO; + +typedef struct { + /* common parameters */ + SSBSIP_MFC_CODEC_TYPE codecType; /* [IN] codec type */ + int SourceWidth; /* [IN] width of video to be encoded */ + int SourceHeight; /* [IN] height of video to be encoded */ + int IDRPeriod; /* [IN] GOP number(interval of I-frame) */ + int SliceMode; /* [IN] Multi slice mode */ + int RandomIntraMBRefresh; /* [IN] cyclic intra refresh */ + int EnableFRMRateControl; /* [IN] frame based rate control enable */ + int Bitrate; /* [IN] rate control parameter(bit rate) */ + int FrameQp; /* [IN] The quantization parameter of the frame */ + int FrameQp_P; /* [IN] The quantization parameter of the P frame */ + int QSCodeMax; /* [IN] Maximum Quantization value */ + int QSCodeMin; /* [IN] Minimum Quantization value */ + int CBRPeriodRf; /* [IN] Reaction coefficient parameter for rate control */ + int PadControlOn; /* [IN] Enable padding control */ + int LumaPadVal; /* [IN] Luma pel value used to fill padding area */ + int CbPadVal; /* [IN] CB pel value used to fill padding area */ + int CrPadVal; /* [IN] CR pel value used to fill padding area */ + int FrameMap; /* [IN] Encoding input mode(tile mode or linear mode) */ + + /* H.264 specific parameters */ + int ProfileIDC; /* [IN] profile */ + int LevelIDC; /* [IN] level */ + int FrameQp_B; /* [IN] The quantization parameter of the B frame */ + int FrameRate; /* [IN] rate control parameter(frame rate) */ + int SliceArgument; /* [IN] MB number or byte number */ + int NumberBFrames; /* [IN] The number of consecutive B frame inserted */ + int NumberReferenceFrames; /* [IN] The number of reference pictures used */ + int NumberRefForPframes; /* [IN] The number of reference pictures used for encoding P pictures */ + int LoopFilterDisable; /* [IN] disable the loop filter */ + int LoopFilterAlphaC0Offset; /* [IN] Alpha & C0 offset for H.264 loop filter */ + int LoopFilterBetaOffset; /* [IN] Beta offset for H.264 loop filter */ + int SymbolMode; /* [IN] The mode of entropy coding(CABAC, CAVLC) */ + int PictureInterlace; /* [IN] Enables the interlace mode */ + int Transform8x8Mode; /* [IN] Allow 8x8 transform(This is allowed only for high profile) */ + int EnableMBRateControl; /* [IN] Enable macroblock-level rate control */ + int DarkDisable; /* [IN] Disable adaptive rate control on dark region */ + int SmoothDisable; /* [IN] Disable adaptive rate control on smooth region */ + int StaticDisable; /* [IN] Disable adaptive rate control on static region */ + int ActivityDisable; /* [IN] Disable adaptive rate control on high activity region */ +} SSBSIP_MFC_ENC_H264_PARAM; + +typedef struct { + /* common parameters */ + SSBSIP_MFC_CODEC_TYPE codecType; /* [IN] codec type */ + int SourceWidth; /* [IN] width of video to be encoded */ + int SourceHeight; /* [IN] height of video to be encoded */ + int IDRPeriod; /* [IN] GOP number(interval of I-frame) */ + int SliceMode; /* [IN] Multi slice mode */ + int RandomIntraMBRefresh; /* [IN] cyclic intra refresh */ + int EnableFRMRateControl; /* [IN] frame based rate control enable */ + int Bitrate; /* [IN] rate control parameter(bit rate) */ + int FrameQp; /* [IN] The quantization parameter of the frame */ + int FrameQp_P; /* [IN] The quantization parameter of the P frame */ + int QSCodeMax; /* [IN] Maximum Quantization value */ + int QSCodeMin; /* [IN] Minimum Quantization value */ + int CBRPeriodRf; /* [IN] Reaction coefficient parameter for rate control */ + int PadControlOn; /* [IN] Enable padding control */ + int LumaPadVal; /* [IN] Luma pel value used to fill padding area */ + int CbPadVal; /* [IN] CB pel value used to fill padding area */ + int CrPadVal; /* [IN] CR pel value used to fill padding area */ + int FrameMap; /* [IN] Encoding input mode(tile mode or linear mode) */ + + /* MPEG4 specific parameters */ + int ProfileIDC; /* [IN] profile */ + int LevelIDC; /* [IN] level */ + int FrameQp_B; /* [IN] The quantization parameter of the B frame */ + int TimeIncreamentRes; /* [IN] frame rate */ + int VopTimeIncreament; /* [IN] frame rate */ + int SliceArgument; /* [IN] MB number or byte number */ + int NumberBFrames; /* [IN] The number of consecutive B frame inserted */ + int DisableQpelME; /* [IN] disable quarter-pixel motion estimation */ +} SSBSIP_MFC_ENC_MPEG4_PARAM; + +typedef struct { + /* common parameters */ + SSBSIP_MFC_CODEC_TYPE codecType; /* [IN] codec type */ + int SourceWidth; /* [IN] width of video to be encoded */ + int SourceHeight; /* [IN] height of video to be encoded */ + int IDRPeriod; /* [IN] GOP number(interval of I-frame) */ + int SliceMode; /* [IN] Multi slice mode */ + int RandomIntraMBRefresh; /* [IN] cyclic intra refresh */ + int EnableFRMRateControl; /* [IN] frame based rate control enable */ + int Bitrate; /* [IN] rate control parameter(bit rate) */ + int FrameQp; /* [IN] The quantization parameter of the frame */ + int FrameQp_P; /* [IN] The quantization parameter of the P frame */ + int QSCodeMax; /* [IN] Maximum Quantization value */ + int QSCodeMin; /* [IN] Minimum Quantization value */ + int CBRPeriodRf; /* [IN] Reaction coefficient parameter for rate control */ + int PadControlOn; /* [IN] Enable padding control */ + int LumaPadVal; /* [IN] Luma pel value used to fill padding area */ + int CbPadVal; /* [IN] CB pel value used to fill padding area */ + int CrPadVal; /* [IN] CR pel value used to fill padding area */ + int FrameMap; /* [IN] Encoding input mode(tile mode or linear mode) */ + + /* H.263 specific parameters */ + int FrameRate; /* [IN] rate control parameter(frame rate) */ +} SSBSIP_MFC_ENC_H263_PARAM; + +typedef struct { + int width; + int height; + int buf_width; + int buf_height; +} SSBSIP_MFC_IMG_RESOLUTION; + +typedef struct { + int crop_top_offset; + int crop_bottom_offset; + int crop_left_offset; + int crop_right_offset; +} SSBSIP_MFC_CROP_INFORMATION; + +#ifdef __cplusplus +extern "C" { +#endif + +/*--------------------------------------------------------------------------------*/ +/* Decoding APIs */ +/*--------------------------------------------------------------------------------*/ +void *SsbSipMfcDecOpen(void); +void *SsbSipMfcDecOpenExt(void *value); +SSBSIP_MFC_ERROR_CODE SsbSipMfcDecInit(void *openHandle, SSBSIP_MFC_CODEC_TYPE codec_type, int Frameleng); +SSBSIP_MFC_ERROR_CODE SsbSipMfcDecExe(void *openHandle, int lengthBufFill); +//SSBSIP_MFC_ERROR_CODE SsbSipMfcDecExeNb(void *openHandle, int lengthBufFill); +SSBSIP_MFC_ERROR_CODE SsbSipMfcDecClose(void *openHandle); +void *SsbSipMfcDecGetInBuf(void *openHandle, void **phyInBuf, int inputBufferSize); +//SSBSIP_MFC_DEC_OUTBUF_STATUS SsbSipMfcDecWaitForOutBuf(void *openHandle, SSBSIP_MFC_DEC_OUTPUT_INFO *output_info); + +#if (defined(CONFIG_VIDEO_MFC_VCM_UMP) || defined(USE_UMP)) +SSBSIP_MFC_ERROR_CODE SsbSipMfcDecSetInBuf(void *openHandle, unsigned int secure_id, int size); +#else +SSBSIP_MFC_ERROR_CODE SsbSipMfcDecSetInBuf(void *openHandle, void *phyInBuf, void *virInBuf, int size); +#endif + +SSBSIP_MFC_DEC_OUTBUF_STATUS SsbSipMfcDecGetOutBuf(void *openHandle, SSBSIP_MFC_DEC_OUTPUT_INFO *output_info); + +SSBSIP_MFC_ERROR_CODE SsbSipMfcDecSetConfig(void *openHandle, SSBSIP_MFC_DEC_CONF conf_type, void *value); +SSBSIP_MFC_ERROR_CODE SsbSipMfcDecGetConfig(void *openHandle, SSBSIP_MFC_DEC_CONF conf_type, void *value); + +/*--------------------------------------------------------------------------------*/ +/* Encoding APIs */ +/*--------------------------------------------------------------------------------*/ +void *SsbSipMfcEncOpen(void); +void *SsbSipMfcEncOpenExt(void *value); +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncInit(void *openHandle, void *param); +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncExe(void *openHandle); +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncClose(void *openHandle); + +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncGetInBuf(void *openHandle, SSBSIP_MFC_ENC_INPUT_INFO *input_info); +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncSetInBuf(void *openHandle, SSBSIP_MFC_ENC_INPUT_INFO *input_info); + +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncGetOutBuf(void *openHandle, SSBSIP_MFC_ENC_OUTPUT_INFO *output_info); +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncSetOutBuf(void *openHandle, void *phyOutbuf, void *virOutbuf, int outputBufferSize); + +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncSetConfig(void *openHandle, SSBSIP_MFC_ENC_CONF conf_type, void *value); +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncGetConfig(void *openHandle, SSBSIP_MFC_ENC_CONF conf_type, void *value); + +#ifdef __cplusplus +} +#endif + +#endif /* _SSBSIP_MFC_API_H_ */ diff --git a/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/include/mfc_errno.h b/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/include/mfc_errno.h new file mode 100644 index 0000000..b8e96ab --- /dev/null +++ b/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/include/mfc_errno.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Global header for Samsung MFC (Multi Function Codec - FIMV) driver + * + * 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. + */ + +#ifndef __MFC_ERRNO_H +#define __MFC_ERRNO_H __FILE__ + +enum mfc_ret_code { + MFC_OK = 1, + MFC_FAIL = -1000, + MFC_OPEN_FAIL = -1001, + MFC_CLOSE_FAIL = -1002, + + MFC_DEC_INIT_FAIL = -2000, + MFC_DEC_EXE_TIME_OUT = -2001, + MFC_DEC_EXE_ERR = -2002, + MFC_DEC_GET_INBUF_FAIL = 2003, + MFC_DEC_SET_INBUF_FAIL = 2004, + MFC_DEC_GET_OUTBUF_FAIL = -2005, + MFC_DEC_GET_CONF_FAIL = -2006, + MFC_DEC_SET_CONF_FAIL = -2007, + + MFC_ENC_INIT_FAIL = -3000, + MFC_ENC_EXE_TIME_OUT = -3001, + MFC_ENC_EXE_ERR = -3002, + MFC_ENC_GET_INBUF_FAIL = -3003, + MFC_ENC_SET_INBUF_FAIL = -3004, + MFC_ENC_GET_OUTBUF_FAIL = -3005, + MFC_ENC_SET_OUTBUF_FAIL = -3006, + MFC_ENC_GET_CONF_FAIL = -3007, + MFC_ENC_SET_CONF_FAIL = -3008, + + MFC_STATE_INVALID = -4000, + MFC_DEC_HEADER_FAIL = -4001, + MFC_DEC_INIT_BUF_FAIL = -4002, + MFC_ENC_HEADER_FAIL = -5000, + MFC_ENC_PARAM_FAIL = -5001, + MFC_FRM_BUF_SIZE_FAIL = -6000, + MFC_FW_LOAD_FAIL = -6001, + MFC_FW_INIT_FAIL = -6002, + MFC_INST_NUM_EXCEEDED_FAIL = -6003, + MFC_MEM_ALLOC_FAIL = -6004, + MFC_MEM_INVALID_ADDR_FAIL = -6005, + MFC_MEM_MAPPING_FAIL = -6006, + MFC_GET_CONF_FAIL = -6007, + MFC_SET_CONF_FAIL = -6008, + MFC_INVALID_PARAM_FAIL = -6009, + MFC_API_FAIL = -9000, + + MFC_CMD_FAIL = -1003, + MFC_SLEEP_FAIL = -1010, + MFC_WAKEUP_FAIL = -1020, + + MFC_CLK_ON_FAIL = -1030, + MFC_CLK_OFF_FAIL = -1030, + MFC_PWR_ON_FAIL = -1040, + MFC_PWR_OFF_FAIL = -1041, +}; + +#endif /* __MFC_ERRNO_H */ diff --git a/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/include/mfc_interface.h b/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/include/mfc_interface.h new file mode 100644 index 0000000..b7289c4 --- /dev/null +++ b/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/include/mfc_interface.h @@ -0,0 +1,541 @@ +/* + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Global header for Samsung MFC (Multi Function Codec - FIMV) driver + * + * 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. + */ + +#ifndef __MFC_INTERFACE_H +#define __MFC_INTERFACE_H + +#include "mfc_errno.h" +#include "SsbSipMfcApi.h" + +#define IOCTL_MFC_DEC_INIT (0x00800001) +#define IOCTL_MFC_ENC_INIT (0x00800002) +#define IOCTL_MFC_DEC_EXE (0x00800003) +#define IOCTL_MFC_ENC_EXE (0x00800004) + +#define IOCTL_MFC_GET_IN_BUF (0x00800010) +#define IOCTL_MFC_FREE_BUF (0x00800011) +#define IOCTL_MFC_GET_REAL_ADDR (0x00800012) +#define IOCTL_MFC_GET_MMAP_SIZE (0x00800014) +#define IOCTL_MFC_SET_IN_BUF (0x00800018) + +#define IOCTL_MFC_SET_CONFIG (0x00800101) +#define IOCTL_MFC_GET_CONFIG (0x00800102) + +#define IOCTL_MFC_SET_BUF_CACHE (0x00800201) + +/* MFC H/W support maximum 32 extra DPB. */ +#define MFC_MAX_EXTRA_DPB 5 +#define MFC_MAX_DISP_DELAY 0xF + +#define MFC_LIB_VER_MAJOR 1 +#define MFC_LIB_VER_MINOR 00 + +#define BUF_L_UNIT (1024) +#define Align(x, alignbyte) (((x)+(alignbyte)-1)/(alignbyte)*(alignbyte)) + +#define MFC_ENC_NUM_SRC_BUFS 2 /* Number of source buffers to request */ +#define MFC_ENC_MAX_DST_BUFS 2 /* The maximum number of buffers */ +#define MFC_ENC_NUM_PLANES 2 /* Number of planes used by MFC Input */ + +#define MFC_DEC_NUM_SRC_BUFS 2 /* Number of source buffers to request */ +#define MFC_DEC_MAX_DST_BUFS 32 /* The maximum number of buffers */ +#define MFC_DEC_NUM_PLANES 2 /* Number of planes used by MFC output */ + +enum inst_type { + DECODER = 0x1, + ENCODER = 0x2, +}; + +typedef enum { + MFC_UNPACKED_PB = 0, + MFC_PACKED_PB = 1 +} mfc_packed_mode; + +typedef enum { + SSBSIP_MFC_LAST_FRAME_NOT_RECEIVED = 0, + SSBSIP_MFC_LAST_FRAME_RECEIVED = 1, + SSBSIP_MFC_LAST_FRAME_PROCESSED = 2 +} SSBSIP_MFC_LAST_FRAME_STATUS; + +typedef enum { + MFC_USE_NONE = 0x0000, + MFC_USE_YUV_BUFF = 0x0001, + MFC_USE_STRM_BUFF = 0x0010, + MFC_USE_SRC_STREAMON = 0x0100, + MFC_USE_DST_STREAMON = 0x1000, +} s3c_mfc_interbuff_status; + +typedef struct { + int luma0; /* per frame (or top field) */ + int chroma0; /* per frame (or top field) */ + int luma1; /* per frame (or bottom field) */ + int chroma1; /* per frame (or bottom field) */ +} SSBSIP_MFC_CRC_DATA; + +struct mfc_strm_ref_buf_arg { + unsigned int strm_ref_y; + unsigned int mv_ref_yc; +}; + +struct mfc_frame_buf_arg { + unsigned int luma; + unsigned int chroma; +}; + +struct mfc_enc_init_common_arg { + SSBSIP_MFC_CODEC_TYPE in_codec_type; /* [IN] codec type */ + + int in_width; /* [IN] width of YUV420 frame to be encoded */ + int in_height; /* [IN] height of YUV420 frame to be encoded */ + + int in_gop_num; /* [IN] GOP Number (interval of I-frame) */ + int in_vop_quant; /* [IN] VOP quant */ + int in_vop_quant_p; /* [IN] VOP quant for P frame */ + + /* [IN] RC enable */ + /* [IN] RC enable (0:disable, 1:frame level RC) */ + int in_rc_fr_en; + int in_rc_bitrate; /* [IN] RC parameter (bitrate in kbps) */ + + int in_rc_qbound_min; /* [IN] RC parameter (Q bound Min) */ + int in_rc_qbound_max; /* [IN] RC parameter (Q bound Max) */ + int in_rc_rpara; /* [IN] RC parameter (Reaction Coefficient) */ + + /* [IN] Multi-slice mode (0:single, 1:multiple) */ + int in_ms_mode; + /* [IN] Multi-slice size (in num. of mb or byte) */ + int in_ms_arg; + + int in_mb_refresh; /* [IN] Macroblock refresh */ + + /* [IN] Enable (1) / Disable (0) padding with the specified values */ + int in_pad_ctrl_on; + + /* [IN] pad value if pad_ctrl_on is Enable */ + int in_y_pad_val; + int in_cb_pad_val; + int in_cr_pad_val; + + /* linear or tiled */ + int in_frame_map; + + unsigned int in_pixelcache; + + unsigned int in_mapped_addr; + struct mfc_strm_ref_buf_arg out_u_addr; + struct mfc_strm_ref_buf_arg out_p_addr; + struct mfc_strm_ref_buf_arg out_buf_size; + unsigned int out_header_size; +}; + +struct mfc_enc_init_h263_arg { + int in_rc_framerate; /* [IN] RC parameter (framerate) */ +}; + +struct mfc_enc_init_mpeg4_arg { + int in_profile; /* [IN] profile */ + int in_level; /* [IN] level */ + + int in_vop_quant_b; /* [IN] VOP quant for B frame */ + + /* [IN] B frame number */ + int in_bframenum; + + /* [IN] Quarter-pel MC enable (1:enabled, 0:disabled) */ + int in_quart_pixel; + + int in_TimeIncreamentRes; /* [IN] VOP time resolution */ + int in_VopTimeIncreament; /* [IN] Frame delta */ +}; + +struct mfc_enc_init_h264_arg { + int in_profile; /* [IN] profile */ + int in_level; /* [IN] level */ + + int in_vop_quant_b; /* [IN] VOP quant for B frame */ + + /* [IN] B frame number */ + int in_bframenum; + + /* [IN] interlace mode(0:progressive, 1:interlace) */ + int in_interlace_mode; + + /* [IN] reference number */ + int in_reference_num; + /* [IN] reference number of P frame */ + int in_ref_num_p; + + int in_rc_framerate; /* [IN] RC parameter (framerate) */ + int in_rc_mb_en; /* [IN] RC enable (0:disable, 1:MB level RC) */ + /* [IN] MB level rate control dark region adaptive feature */ + int in_rc_mb_dark_dis; /* (0:enable, 1:disable) */ + /* [IN] MB level rate control smooth region adaptive feature */ + int in_rc_mb_smooth_dis; /* (0:enable, 1:disable) */ + /* [IN] MB level rate control static region adaptive feature */ + int in_rc_mb_static_dis; /* (0:enable, 1:disable) */ + /* [IN] MB level rate control activity region adaptive feature */ + int in_rc_mb_activity_dis; /* (0:enable, 1:disable) */ + + /* [IN] disable deblocking filter idc */ + int in_deblock_dis; /* (0: enable,1: disable, 2:Disable at slice boundary) */ + /* [IN] slice alpha c0 offset of deblocking filter */ + int in_deblock_alpha_c0; + /* [IN] slice beta offset of deblocking filter */ + int in_deblock_beta; + + /* [IN] ( 0 : CAVLC, 1 : CABAC ) */ + int in_symbolmode; + /* [IN] (0: only 4x4 transform, 1: allow using 8x8 transform) */ + int in_transform8x8_mode; + + /* [IN] Inter weighted parameter for mode decision */ + int in_md_interweight_pps; + /* [IN] Intra weighted parameter for mode decision */ + int in_md_intraweight_pps; +}; + +struct mfc_enc_init_arg { + struct mfc_enc_init_common_arg cmn; + union { + struct mfc_enc_init_h264_arg h264; + struct mfc_enc_init_mpeg4_arg mpeg4; + struct mfc_enc_init_h263_arg h263; + } codec; +}; + +struct mfc_enc_exe_arg { + SSBSIP_MFC_CODEC_TYPE in_codec_type; /* [IN] codec type */ + unsigned int in_Y_addr; /* [IN] In-buffer addr of Y component */ + unsigned int in_CbCr_addr; /* [IN] In-buffer addr of CbCr component */ + unsigned int in_Y_addr_vir; /* [IN] In-buffer addr of Y component */ + unsigned int in_CbCr_addr_vir; /* [IN] In-buffer addr of CbCr component */ + unsigned int in_strm_st; /* [IN] Out-buffer start addr of encoded strm */ + unsigned int in_strm_end; /* [IN] Out-buffer end addr of encoded strm */ + unsigned int in_frametag; /* [IN] unique frame ID */ + + unsigned int out_frame_type; /* [OUT] frame type */ + int out_encoded_size; /* [OUT] Length of Encoded video stream */ + unsigned int out_Y_addr; /*[OUT]Out-buffer addr of encoded Y component */ + unsigned int out_CbCr_addr; /*[OUT]Out-buffer addr of encoded CbCr component */ + unsigned int out_frametag_top; /* [OUT] unique frame ID of an output frame or top field */ + unsigned int out_frametag_bottom;/* [OUT] unique frame ID of bottom field */ + +#if defined(CONFIG_VIDEO_MFC_VCM_UMP) + unsigned int out_y_secure_id; + unsigned int out_c_secure_id; +#elif defined(CONFIG_S5P_VMEM) + unsigned int out_y_cookie; + unsigned int out_c_cookie; +#endif +}; + +struct mfc_dec_init_arg { + SSBSIP_MFC_CODEC_TYPE in_codec_type; /* [IN] codec type */ + int in_strm_buf; /* [IN] address of stream buffer */ + int in_strm_size; /* [IN] filled size in stream buffer */ + int in_packed_PB; /* [IN] Is packed PB frame or not, 1: packedPB 0: unpacked */ + + unsigned int in_crc; /* [IN] */ + unsigned int in_pixelcache; /* [IN] */ + unsigned int in_slice; /* [IN] */ + unsigned int in_numextradpb; /* [IN] */ + + unsigned int in_mapped_addr; + + int out_frm_width; /* [OUT] width of YUV420 frame */ + int out_frm_height; /* [OUT] height of YUV420 frame */ + int out_buf_width; /* [OUT] width of YUV420 frame */ + int out_buf_height; /* [OUT] height of YUV420 frame */ + + int out_dpb_cnt; /* [OUT] the number of buffers which is nessary during decoding. */ + + int out_crop_right_offset; /* [OUT] crop information for h264 */ + int out_crop_left_offset; + int out_crop_bottom_offset; + int out_crop_top_offset; +}; + +struct mfc_dec_exe_arg { + SSBSIP_MFC_CODEC_TYPE in_codec_type; /* [IN] codec type */ + int in_strm_buf; /* [IN] the physical address of STRM_BUF */ + /* [IN] Size of video stream filled in STRM_BUF */ + int in_strm_size; + /* [IN] the address of dpb FRAME_BUF */ + struct mfc_frame_buf_arg in_frm_buf; + /* [IN] size of dpb FRAME_BUF */ + struct mfc_frame_buf_arg in_frm_size; + /* [IN] Unique frame ID eg. application specific timestamp */ + unsigned int in_frametag; + /* [IN] immdiate Display for seek,thumbnail and one frame */ + int in_immediately_disp; + /* [OUT] the physical address of display buf */ + int out_display_Y_addr; + /* [OUT] the physical address of display buf */ + int out_display_C_addr; + int out_display_status; + /* [OUT] unique frame ID of an output frame or top field */ + unsigned int out_frametag_top; + /* [OUT] unique frame ID of bottom field */ + unsigned int out_frametag_bottom; + int out_pic_time_top; + int out_pic_time_bottom; + int out_consumed_byte; + + int out_crop_right_offset; + int out_crop_left_offset; + int out_crop_bottom_offset; + int out_crop_top_offset; + + /* in new driver, each buffer offset must be return to the user */ + int out_y_offset; + int out_c_offset; + +#if defined(CONFIG_VIDEO_MFC_VCM_UMP) + unsigned int out_y_secure_id; + unsigned int out_c_secure_id; +#elif defined(CONFIG_S5P_VMEM) + unsigned int out_y_cookie; + unsigned int out_c_cookie; +#endif + int out_img_width; /* [OUT] width of YUV420 frame */ + int out_img_height; /* [OUT] height of YUV420 frame */ + int out_buf_width; /* [OUT] width of YUV420 frame */ + int out_buf_height; /* [OUT] height of YUV420 frame */ + + int out_disp_pic_frame_type; /* [OUT] display picture frame type information */ +}; + +struct mfc_get_config_arg { + /* [IN] Configurable parameter type */ + int in_config_param; + + /* [IN] Values to get for the configurable parameter. */ + /* Maximum four integer values can be obtained; */ + int out_config_value[4]; +}; + +struct mfc_set_config_arg { + /* [IN] Configurable parameter type */ + int in_config_param; + + /* [IN] Values to be set for the configurable parameter. */ + /* Maximum four integer values can be set. */ + int in_config_value[4]; +}; + +struct mfc_get_real_addr_arg { + unsigned int key; + unsigned int addr; +}; + +struct mfc_buf_alloc_arg { + enum inst_type type; + int size; + /* + unsigned int mapped; + */ + unsigned int align; + + unsigned int addr; + /* + unsigned int phys; + */ +#if defined(CONFIG_VIDEO_MFC_VCM_UMP) + /* FIMXE: invalid secure id == -1 */ + unsigned int secure_id; +#elif defined(CONFIG_S5P_VMEM) + unsigned int cookie; +#else + unsigned int offset; +#endif +}; + +struct mfc_buf_free_arg { + unsigned int addr; +}; + +/* RMVME */ +struct mfc_mem_alloc_arg { + enum inst_type type; + int buff_size; + SSBIP_MFC_BUFFER_TYPE buf_cache_type; + unsigned int mapped_addr; +#if defined(CONFIG_VIDEO_MFC_VCM_UMP) + unsigned int secure_id; +#elif defined(CONFIG_S5P_VMEM) + unsigned int cookie; +#else + unsigned int offset; +#endif +}; + +struct mfc_mem_free_arg { + unsigned int key; +}; +/* RMVME */ + +union mfc_args { + /* + struct mfc_enc_init_arg enc_init; + + struct mfc_enc_init_mpeg4_arg enc_init_mpeg4; + struct mfc_enc_init_mpeg4_arg enc_init_h263; + struct mfc_enc_init_h264_arg enc_init_h264; + */ + struct mfc_enc_init_arg enc_init; + struct mfc_enc_exe_arg enc_exe; + + struct mfc_dec_init_arg dec_init; + struct mfc_dec_exe_arg dec_exe; + + struct mfc_get_config_arg get_config; + struct mfc_set_config_arg set_config; + + struct mfc_buf_alloc_arg buf_alloc; + struct mfc_buf_free_arg buf_free; + struct mfc_get_real_addr_arg real_addr; + + /* RMVME */ + struct mfc_mem_alloc_arg mem_alloc; + struct mfc_mem_free_arg mem_free; + /* RMVME */ +}; + +struct mfc_common_args { + enum mfc_ret_code ret_code; /* [OUT] error code */ + union mfc_args args; +}; + +struct mfc_enc_vui_info { + int aspect_ratio_idc; +}; + +struct mfc_dec_fimv1_info { + int width; + int height; +}; + +struct mfc_enc_hier_p_qp { + int t0_frame_qp; + int t2_frame_qp; + int t3_frame_qp; +}; + +enum BUF_STATUS { + BUF_ENQUEUED, + BUF_DEQUEUED +}; + +struct mfc_dec_v4l2 { + char *mfc_src_bufs[MFC_DEC_NUM_SRC_BUFS]; /* information of source buffers */ + char *mfc_dst_bufs[MFC_DEC_MAX_DST_BUFS][MFC_DEC_NUM_PLANES]; /* information of destination buffers */ + char *mfc_dst_phys[MFC_DEC_MAX_DST_BUFS][MFC_DEC_NUM_PLANES]; /* cma information of destination buffers */ + + unsigned int mfc_src_bufs_len; /* needed for munmap */ + unsigned int mfc_dst_bufs_len[MFC_DEC_NUM_PLANES]; /* needed for munmap */ + + unsigned int mfc_num_src_bufs; /* the number of source buffers */ + unsigned int mfc_num_dst_bufs; /* the number of destination buffers */ + + char mfc_src_buf_flags[MFC_DEC_NUM_SRC_BUFS]; + int bBeingFinalized; + int allocIndex; + int beingUsedIndex; +}; + +struct mfc_enc_v4l2 { + char *mfc_src_bufs[MFC_ENC_NUM_SRC_BUFS][MFC_ENC_NUM_PLANES]; + char *mfc_src_phys[MFC_ENC_NUM_SRC_BUFS][MFC_ENC_NUM_PLANES]; + char *mfc_dst_bufs[MFC_ENC_MAX_DST_BUFS]; + + unsigned int mfc_src_bufs_len[MFC_ENC_NUM_PLANES]; + unsigned int mfc_dst_bufs_len; + + unsigned int mfc_num_src_bufs; + unsigned int mfc_num_dst_bufs; + + unsigned int mfc_dst_bufs_bytes_used_len; + char mfc_src_buf_flags[MFC_ENC_NUM_SRC_BUFS]; + int bRunning; + int bInputPhyVir; /* Flag to use MFC src as physical or virtual 0: virtual 1: physical */ + int beingUsedIndex; +}; + +typedef struct { + int magic; + int hMFC; + int hVMEM; + int width; + int height; + int sizeStrmBuf; + struct mfc_frame_buf_arg sizeFrmBuf; + int displayStatus; + int inter_buff_status; + unsigned int virFreeStrmAddr; + unsigned int phyStrmBuf; + unsigned int virStrmBuf; + unsigned int virMvRefYC; + struct mfc_frame_buf_arg phyFrmBuf; + struct mfc_frame_buf_arg virFrmBuf; + unsigned int mapped_addr; + unsigned int mapped_size; + struct mfc_common_args MfcArg; + SSBSIP_MFC_CODEC_TYPE codecType; + SSBSIP_MFC_DEC_OUTPUT_INFO decOutInfo; + unsigned int inframetag; + unsigned int outframetagtop; + unsigned int outframetagbottom; + unsigned int immediatelydisp; + unsigned int encodedHeaderSize; + int encodedDataSize; + unsigned int encodedframeType; + struct mfc_frame_buf_arg encodedphyFrmBuf; + + unsigned int dec_crc; + unsigned int dec_pixelcache; + unsigned int dec_slice; + unsigned int dec_numextradpb; + + int input_cookie; + int input_secure_id; + int input_size; + + /* to support non-blocking mode */ + unsigned int encode_cnt; + + struct mfc_dec_v4l2 v4l2_dec; + struct mfc_enc_v4l2 v4l2_enc; + + int enc_frameskip; + int cacheablebuffer; + struct mfc_dec_fimv1_info fimv1_res; + SSBSIP_MFC_LAST_FRAME_STATUS lastframe; + SSBSIP_MFC_INSTRM_MODE_TYPE framemap; +} _MFCLIB; + +#define ENC_PROFILE_LEVEL(profile, level) ((profile) | ((level) << 8)) +#define ENC_RC_QBOUND(min_qp, max_qp) ((min_qp) | ((max_qp) << 8)) + +#define SSBSIP_MFC_FAIL (0) + +#endif /* __MFC_INTERFACE_H */ |