summaryrefslogtreecommitdiffstats
path: root/exynos/multimedia/codecs/video/exynos4/mfc_v4l2/enc/src/SsbSipMfcEncAPI.c
diff options
context:
space:
mode:
authorcodeworkx <daniel.hillenbrand@codeworkx.de>2012-05-20 12:00:36 +0200
committercodeworkx <daniel.hillenbrand@codeworkx.de>2012-05-20 12:00:36 +0200
commit62f02ba4f4b7b561aa15408ebd9951600bdd71aa (patch)
treeac05dc645945a58edbc26e96df1a78ac16f27706 /exynos/multimedia/codecs/video/exynos4/mfc_v4l2/enc/src/SsbSipMfcEncAPI.c
parente54debb12ecdf92d12acab00a261c0c5a6ef1d64 (diff)
downloadhardware_samsung-62f02ba4f4b7b561aa15408ebd9951600bdd71aa.tar.gz
hardware_samsung-62f02ba4f4b7b561aa15408ebd9951600bdd71aa.tar.bz2
hardware_samsung-62f02ba4f4b7b561aa15408ebd9951600bdd71aa.zip
exynos: reorganized and updated from insignal
Changes needed on exynos4210 devices: libcsc -> libseccscapi libswconverter -> remove TARGET_HAL_PATH := hardware/samsung/exynos4/hal TARGET_OMX_PATH := hardware/samsung/exynos/multimedia/openmax $(call inherit-product, hardware/samsung/exynos4210.mk) Change-Id: Ic59ef95b85ef37b3f38fb36cf6a364a5414685ee
Diffstat (limited to 'exynos/multimedia/codecs/video/exynos4/mfc_v4l2/enc/src/SsbSipMfcEncAPI.c')
-rw-r--r--exynos/multimedia/codecs/video/exynos4/mfc_v4l2/enc/src/SsbSipMfcEncAPI.c1206
1 files changed, 1206 insertions, 0 deletions
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;
+}
+