diff options
Diffstat (limited to 'exynos/multimedia/codecs/video/exynos4/mfc/enc/src/SsbSipMfcEncAPI.c')
-rw-r--r-- | exynos/multimedia/codecs/video/exynos4/mfc/enc/src/SsbSipMfcEncAPI.c | 862 |
1 files changed, 862 insertions, 0 deletions
diff --git a/exynos/multimedia/codecs/video/exynos4/mfc/enc/src/SsbSipMfcEncAPI.c b/exynos/multimedia/codecs/video/exynos4/mfc/enc/src/SsbSipMfcEncAPI.c new file mode 100644 index 0000000..797baad --- /dev/null +++ b/exynos/multimedia/codecs/video/exynos4/mfc/enc/src/SsbSipMfcEncAPI.c @@ -0,0 +1,862 @@ +/* + * 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 <math.h> + +#include "mfc_interface.h" +#include "SsbSipMfcApi.h" + +#include <utils/Log.h> +/* #define LOG_NDEBUG 0 */ +#undef LOG_TAG +#define LOG_TAG "MFC_ENC_APP" + +#define _MFCLIB_MAGIC_NUMBER 0x92241001 + +static char *mfc_dev_name = SAMSUNG_MFC_DEV_NAME; + +void SsbSipMfcEncSetMFCName(char *devicename) +{ + mfc_dev_name = devicename; +} + +void *SsbSipMfcEncOpen(void) +{ + int hMFCOpen; + _MFCLIB *pCTX = NULL; + unsigned int mapped_addr; + int mapped_size; + struct mfc_common_args CommonArg; + + LOGI("[%s] MFC Library Ver %d.%02d",__func__, MFC_LIB_VER_MAJOR, MFC_LIB_VER_MINOR); + +#if 0 + if ((codecType != MPEG4_ENC) && + (codecType != H264_ENC) && + (codecType != H263_ENC)) { + LOGE("SsbSipMfcEncOpen] Undefined codec type"); + return NULL; + } +#endif + + if (access(mfc_dev_name, F_OK) != 0) { + LOGE("SsbSipMfcEncOpen] MFC device node not exists"); + return NULL; + } + + hMFCOpen = open(mfc_dev_name, O_RDWR | O_NDELAY); + if (hMFCOpen < 0) { + LOGE("SsbSipMfcEncOpen] MFC Open failure"); + return NULL; + } + + pCTX = (_MFCLIB *)malloc(sizeof(_MFCLIB)); + if (pCTX == NULL) { + LOGE("SsbSipMfcEncOpen] malloc failed."); + close(hMFCOpen); + return NULL; + } + memset(pCTX, 0, sizeof(_MFCLIB)); + + mapped_size = ioctl(hMFCOpen, IOCTL_MFC_GET_MMAP_SIZE, &CommonArg); + if ((mapped_size < 0) || (CommonArg.ret_code != MFC_OK)) { + LOGE("SsbSipMfcEncOpen] IOCTL_MFC_GET_MMAP_SIZE failed"); + free(pCTX); + close(hMFCOpen); + return NULL; + } + + mapped_addr = (unsigned int)mmap(0, mapped_size, PROT_READ | PROT_WRITE, MAP_SHARED, hMFCOpen, 0); + if (!mapped_addr) { + LOGE("SsbSipMfcEncOpen] FIMV5.x driver address mapping failed"); + free(pCTX); + close(hMFCOpen); + return NULL; + } + + pCTX->magic = _MFCLIB_MAGIC_NUMBER; + pCTX->hMFC = hMFCOpen; + pCTX->mapped_addr = mapped_addr; + pCTX->mapped_size = mapped_size; + pCTX->inter_buff_status = MFC_USE_NONE; + + return (void *) pCTX; +} + + +void *SsbSipMfcEncOpenExt(void *value) +{ + int hMFCOpen; + _MFCLIB *pCTX = NULL; + unsigned int mapped_addr; + int mapped_size; + int err; + struct mfc_common_args CommonArg; + + LOGI("[%s] MFC Library Ver %d.%02d",__func__, MFC_LIB_VER_MAJOR, MFC_LIB_VER_MINOR); + +#if 0 + if ((codecType != MPEG4_ENC) && + (codecType != H264_ENC) && + (codecType != H263_ENC)) { + LOGE("SsbSipMfcEncOpen] Undefined codec type"); + return NULL; + } +#endif + + if (access(mfc_dev_name, F_OK) != 0) { + LOGE("SsbSipMfcEncOpenExt] MFC device node not exists"); + return NULL; + } + + hMFCOpen = open(mfc_dev_name, O_RDWR | O_NDELAY); + if (hMFCOpen < 0) { + LOGE("SsbSipMfcEncOpenExt] MFC Open failure"); + return NULL; + } + + pCTX = (_MFCLIB *)malloc(sizeof(_MFCLIB)); + if (pCTX == NULL) { + LOGE("SsbSipMfcEncOpenExt] malloc failed."); + close(hMFCOpen); + return NULL; + } + memset(pCTX, 0, sizeof(_MFCLIB)); + + CommonArg.args.mem_alloc.buf_cache_type = *(SSBIP_MFC_BUFFER_TYPE *)value; + + err = ioctl(hMFCOpen, IOCTL_MFC_SET_BUF_CACHE, &CommonArg); + if ((err < 0) || (CommonArg.ret_code != MFC_OK)) { + LOGE("SsbSipMfcEncOpenExt] IOCTL_MFC_SET_BUF_CACHE failed"); + free(pCTX); + close(hMFCOpen); + return NULL; + } + + mapped_size = ioctl(hMFCOpen, IOCTL_MFC_GET_MMAP_SIZE, &CommonArg); + if ((mapped_size < 0) || (CommonArg.ret_code != MFC_OK)) { + LOGE("SsbSipMfcEncOpenExt] IOCTL_MFC_GET_MMAP_SIZE failed"); + free(pCTX); + close(hMFCOpen); + return NULL; + } + + mapped_addr = (unsigned int)mmap(0, mapped_size, PROT_READ | PROT_WRITE, MAP_SHARED, hMFCOpen, 0); + if (!mapped_addr) { + LOGE("SsbSipMfcEncOpenExt] FIMV5.x driver address mapping failed"); + free(pCTX); + close(hMFCOpen); + return NULL; + } + + pCTX->magic = _MFCLIB_MAGIC_NUMBER; + pCTX->hMFC = hMFCOpen; + pCTX->mapped_addr = mapped_addr; + pCTX->mapped_size = mapped_size; + pCTX->inter_buff_status = MFC_USE_NONE; + + return (void *) pCTX; +} + +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncInit(void *openHandle, void *param) +{ + int ret_code; + + _MFCLIB *pCTX; + struct mfc_common_args EncArg; + SSBSIP_MFC_ENC_H264_PARAM *h264_arg; + SSBSIP_MFC_ENC_MPEG4_PARAM *mpeg4_arg; + SSBSIP_MFC_ENC_H263_PARAM *h263_arg; + + pCTX = (_MFCLIB *) openHandle; + memset(&EncArg, 0, sizeof(struct mfc_common_args)); + + pCTX->encode_cnt = 0; + + mpeg4_arg = (SSBSIP_MFC_ENC_MPEG4_PARAM*)param; + if (mpeg4_arg->codecType == MPEG4_ENC) { + pCTX->codecType= MPEG4_ENC; + } else { + h263_arg = (SSBSIP_MFC_ENC_H263_PARAM*)param; + if (h263_arg->codecType == H263_ENC) { + pCTX->codecType = H263_ENC; + } else { + h264_arg = (SSBSIP_MFC_ENC_H264_PARAM*)param; + if (h264_arg->codecType == H264_ENC) { + pCTX->codecType = H264_ENC; + } else { + LOGE("SsbSipMfcEncInit] Undefined codec type"); + return MFC_RET_INVALID_PARAM; + } + } + } + + LOGI("SsbSipMfcEncInit] Encode Init start"); + + switch (pCTX->codecType) { + case MPEG4_ENC: + LOGI("SsbSipMfcEncInit] MPEG4 Encode"); + mpeg4_arg = (SSBSIP_MFC_ENC_MPEG4_PARAM *)param; + + pCTX->width = mpeg4_arg->SourceWidth; + pCTX->height = mpeg4_arg->SourceHeight; + break; + + case H263_ENC: + LOGI("SsbSipMfcEncInit] H263 Encode"); + h263_arg = (SSBSIP_MFC_ENC_H263_PARAM *)param; + + pCTX->width = h263_arg->SourceWidth; + pCTX->height = h263_arg->SourceHeight; + break; + + case H264_ENC: + LOGI("SsbSipMfcEncInit] H264 Encode"); + h264_arg = (SSBSIP_MFC_ENC_H264_PARAM *)param; + + pCTX->width = h264_arg->SourceWidth; + pCTX->height = h264_arg->SourceHeight; + break; + + default: + break; + } + + switch (pCTX->codecType) { + case MPEG4_ENC: + mpeg4_arg = (SSBSIP_MFC_ENC_MPEG4_PARAM *)param; + + EncArg.args.enc_init.cmn.in_codec_type = pCTX->codecType; + + EncArg.args.enc_init.cmn.in_width = mpeg4_arg->SourceWidth; + EncArg.args.enc_init.cmn.in_height = mpeg4_arg->SourceHeight; + EncArg.args.enc_init.cmn.in_gop_num = mpeg4_arg->IDRPeriod; + + EncArg.args.enc_init.cmn.in_ms_mode = mpeg4_arg->SliceMode; + EncArg.args.enc_init.cmn.in_ms_arg = mpeg4_arg->SliceArgument; + + EncArg.args.enc_init.cmn.in_mb_refresh = mpeg4_arg->RandomIntraMBRefresh; + + /* rate control*/ + EncArg.args.enc_init.cmn.in_rc_fr_en = mpeg4_arg->EnableFRMRateControl; + if ((mpeg4_arg->QSCodeMin > 31) || (mpeg4_arg->QSCodeMax > 31)) { + LOGE("SsbSipMfcEncInit] No such Min/Max QP is supported"); + return MFC_RET_INVALID_PARAM; + } + EncArg.args.enc_init.cmn.in_rc_qbound_min = mpeg4_arg->QSCodeMin; + EncArg.args.enc_init.cmn.in_rc_qbound_max = mpeg4_arg->QSCodeMax; + EncArg.args.enc_init.cmn.in_rc_rpara = mpeg4_arg->CBRPeriodRf; + + /* pad control */ + EncArg.args.enc_init.cmn.in_pad_ctrl_on = mpeg4_arg->PadControlOn; + if ((mpeg4_arg->LumaPadVal > 255) || (mpeg4_arg->CbPadVal > 255) || (mpeg4_arg->CrPadVal > 255)) { + LOGE("SsbSipMfcEncInit] No such Pad value is supported"); + return MFC_RET_INVALID_PARAM; + } + EncArg.args.enc_init.cmn.in_y_pad_val = mpeg4_arg->LumaPadVal; + EncArg.args.enc_init.cmn.in_cb_pad_val = mpeg4_arg->CbPadVal; + EncArg.args.enc_init.cmn.in_cr_pad_val = mpeg4_arg->CrPadVal; + + /* Input stream Mode NV12_Linear or NV12_Tile*/ + EncArg.args.enc_init.cmn.in_frame_map = mpeg4_arg->FrameMap; + + EncArg.args.enc_init.cmn.in_rc_bitrate = mpeg4_arg->Bitrate; + if ((mpeg4_arg->FrameQp > 31) || (mpeg4_arg->FrameQp_P > 31)) { + LOGE("SsbSipMfcEncInit] No such FrameQp is supported"); + return MFC_RET_INVALID_PARAM; + } + EncArg.args.enc_init.cmn.in_vop_quant = mpeg4_arg->FrameQp; + EncArg.args.enc_init.cmn.in_vop_quant_p = mpeg4_arg->FrameQp_P; + + /* MPEG4 only */ + EncArg.args.enc_init.codec.mpeg4.in_profile = mpeg4_arg->ProfileIDC; + EncArg.args.enc_init.codec.mpeg4.in_level = mpeg4_arg->LevelIDC; + + if (mpeg4_arg->FrameQp_B > 31) { + LOGE("SsbSipMfcEncInit] No such FrameQp is supported"); + return MFC_RET_INVALID_PARAM; + } + EncArg.args.enc_init.codec.mpeg4.in_vop_quant_b = mpeg4_arg->FrameQp_B; + + if (mpeg4_arg->NumberBFrames > 2) { + LOGE("SsbSipMfcEncInit] No such BframeNum is supported"); + return MFC_RET_INVALID_PARAM; + } + EncArg.args.enc_init.codec.mpeg4.in_bframenum = mpeg4_arg->NumberBFrames; + + EncArg.args.enc_init.codec.mpeg4.in_quart_pixel = mpeg4_arg->DisableQpelME; + + EncArg.args.enc_init.codec.mpeg4.in_TimeIncreamentRes = mpeg4_arg->TimeIncreamentRes; + EncArg.args.enc_init.codec.mpeg4.in_VopTimeIncreament = mpeg4_arg->VopTimeIncreament; + + break; + + case H263_ENC: + h263_arg = (SSBSIP_MFC_ENC_H263_PARAM *)param; + + EncArg.args.enc_init.cmn.in_codec_type = pCTX->codecType; + + EncArg.args.enc_init.cmn.in_width = h263_arg->SourceWidth; + EncArg.args.enc_init.cmn.in_height = h263_arg->SourceHeight; + EncArg.args.enc_init.cmn.in_gop_num = h263_arg->IDRPeriod; + + EncArg.args.enc_init.cmn.in_ms_mode = h263_arg->SliceMode; + EncArg.args.enc_init.cmn.in_ms_arg = 0; + + EncArg.args.enc_init.cmn.in_mb_refresh = h263_arg->RandomIntraMBRefresh; + + /* rate control*/ + EncArg.args.enc_init.cmn.in_rc_fr_en = h263_arg->EnableFRMRateControl; + if ((h263_arg->QSCodeMin > 31) || (h263_arg->QSCodeMax > 31)) { + LOGE("SsbSipMfcEncInit] No such Min/Max QP is supported"); + return MFC_RET_INVALID_PARAM; + } + EncArg.args.enc_init.cmn.in_rc_qbound_min = h263_arg->QSCodeMin; + EncArg.args.enc_init.cmn.in_rc_qbound_max = h263_arg->QSCodeMax; + EncArg.args.enc_init.cmn.in_rc_rpara = h263_arg->CBRPeriodRf; + + /* pad control */ + EncArg.args.enc_init.cmn.in_pad_ctrl_on = h263_arg->PadControlOn; + if ((h263_arg->LumaPadVal > 255) || (h263_arg->CbPadVal > 255) || (h263_arg->CrPadVal > 255)) { + LOGE("SsbSipMfcEncInit] No such Pad value is supported"); + return MFC_RET_INVALID_PARAM; + } + EncArg.args.enc_init.cmn.in_y_pad_val = h263_arg->LumaPadVal; + EncArg.args.enc_init.cmn.in_cb_pad_val = h263_arg->CbPadVal; + EncArg.args.enc_init.cmn.in_cr_pad_val = h263_arg->CrPadVal; + + /* Input stream Mode NV12_Linear or NV12_Tile*/ + EncArg.args.enc_init.cmn.in_frame_map = h263_arg->FrameMap; + + EncArg.args.enc_init.cmn.in_rc_bitrate = h263_arg->Bitrate; + if ((h263_arg->FrameQp > 31) || (h263_arg->FrameQp_P > 31)) { + LOGE("SsbSipMfcEncInit] No such FrameQp is supported"); + return MFC_RET_INVALID_PARAM; + } + EncArg.args.enc_init.cmn.in_vop_quant = h263_arg->FrameQp; + EncArg.args.enc_init.cmn.in_vop_quant_p = h263_arg->FrameQp_P; + + /* H.263 only */ + EncArg.args.enc_init.codec.h263.in_rc_framerate = h263_arg->FrameRate; + + break; + + case H264_ENC: + h264_arg = (SSBSIP_MFC_ENC_H264_PARAM *)param; + + EncArg.args.enc_init.cmn.in_codec_type = H264_ENC; + + EncArg.args.enc_init.cmn.in_width = h264_arg->SourceWidth; + EncArg.args.enc_init.cmn.in_height = h264_arg->SourceHeight; + EncArg.args.enc_init.cmn.in_gop_num = h264_arg->IDRPeriod; + + if ((h264_arg->SliceMode == 0)||(h264_arg->SliceMode == 1)|| + (h264_arg->SliceMode == 2)||(h264_arg->SliceMode == 4)) { + EncArg.args.enc_init.cmn.in_ms_mode = h264_arg->SliceMode; + } else { + LOGE("SsbSipMfcEncInit] No such slice mode is supported"); + return MFC_RET_INVALID_PARAM; + } + EncArg.args.enc_init.cmn.in_ms_arg = h264_arg->SliceArgument; + + EncArg.args.enc_init.cmn.in_mb_refresh = h264_arg->RandomIntraMBRefresh; + /* pad control */ + EncArg.args.enc_init.cmn.in_pad_ctrl_on = h264_arg->PadControlOn; + if ((h264_arg->LumaPadVal > 255) || (h264_arg->CbPadVal > 255) || (h264_arg->CrPadVal > 255)) { + LOGE("SsbSipMfcEncInit] No such Pad value is supported"); + return MFC_RET_INVALID_PARAM; + } + EncArg.args.enc_init.cmn.in_y_pad_val = h264_arg->LumaPadVal; + EncArg.args.enc_init.cmn.in_cb_pad_val = h264_arg->CbPadVal; + EncArg.args.enc_init.cmn.in_cr_pad_val = h264_arg->CrPadVal; + + /* Input stream Mode NV12_Linear or NV12_Tile*/ + EncArg.args.enc_init.cmn.in_frame_map = h264_arg->FrameMap; + + /* rate control*/ + EncArg.args.enc_init.cmn.in_rc_fr_en = h264_arg->EnableFRMRateControl; + EncArg.args.enc_init.cmn.in_rc_bitrate = h264_arg->Bitrate; + if ((h264_arg->FrameQp > 51) || (h264_arg->FrameQp_P > 51)) { + LOGE("SsbSipMfcEncInit] No such FrameQp is supported"); + return MFC_RET_INVALID_PARAM; + } + EncArg.args.enc_init.cmn.in_vop_quant = h264_arg->FrameQp; + EncArg.args.enc_init.cmn.in_vop_quant_p = h264_arg->FrameQp_P; + + if ((h264_arg->QSCodeMin > 51) || (h264_arg->QSCodeMax > 51)) { + LOGE("SsbSipMfcEncInit] No such Min/Max QP is supported"); + return MFC_RET_INVALID_PARAM; + } + EncArg.args.enc_init.cmn.in_rc_qbound_min = h264_arg->QSCodeMin; + EncArg.args.enc_init.cmn.in_rc_qbound_max = h264_arg->QSCodeMax; + EncArg.args.enc_init.cmn.in_rc_rpara = h264_arg->CBRPeriodRf; + + + /* H.264 Only */ + EncArg.args.enc_init.codec.h264.in_profile = h264_arg->ProfileIDC; + EncArg.args.enc_init.codec.h264.in_level = h264_arg->LevelIDC; + + if (h264_arg->FrameQp_B > 51) { + LOGE("SsbSipMfcEncInit] No such FrameQp is supported"); + return MFC_RET_INVALID_PARAM; + } + EncArg.args.enc_init.codec.h264.in_vop_quant_b = h264_arg->FrameQp_B; + + if (h264_arg->NumberBFrames > 2) { + LOGE("SsbSipMfcEncInit] No such BframeNum is supported"); + return MFC_RET_INVALID_PARAM; + } + EncArg.args.enc_init.codec.h264.in_bframenum = h264_arg->NumberBFrames; + + EncArg.args.enc_init.codec.h264.in_interlace_mode = h264_arg->PictureInterlace; + + if ((h264_arg->NumberRefForPframes > 2)||(h264_arg->NumberReferenceFrames >2)) { + LOGE("SsbSipMfcEncInit] No such ref Num is supported"); + return MFC_RET_INVALID_PARAM; + } + EncArg.args.enc_init.codec.h264.in_reference_num = h264_arg->NumberReferenceFrames; + EncArg.args.enc_init.codec.h264.in_ref_num_p = h264_arg->NumberRefForPframes; + + EncArg.args.enc_init.codec.h264.in_rc_framerate = h264_arg->FrameRate; + + EncArg.args.enc_init.codec.h264.in_rc_mb_en = h264_arg->EnableMBRateControl; + EncArg.args.enc_init.codec.h264.in_rc_mb_dark_dis = h264_arg->DarkDisable; + EncArg.args.enc_init.codec.h264.in_rc_mb_smooth_dis = h264_arg->SmoothDisable; + EncArg.args.enc_init.codec.h264.in_rc_mb_static_dis = h264_arg->StaticDisable; + EncArg.args.enc_init.codec.h264.in_rc_mb_activity_dis = h264_arg->ActivityDisable; + + EncArg.args.enc_init.codec.h264.in_deblock_dis = h264_arg->LoopFilterDisable; + if ((abs(h264_arg->LoopFilterAlphaC0Offset) > 6) || (abs(h264_arg->LoopFilterBetaOffset) > 6)) { + LOGE("SsbSipMfcEncInit] No such AlphaC0Offset or BetaOffset is supported"); + return MFC_RET_INVALID_PARAM; + } + EncArg.args.enc_init.codec.h264.in_deblock_alpha_c0 = h264_arg->LoopFilterAlphaC0Offset; + EncArg.args.enc_init.codec.h264.in_deblock_beta = h264_arg->LoopFilterBetaOffset; + + EncArg.args.enc_init.codec.h264.in_symbolmode = h264_arg->SymbolMode; + EncArg.args.enc_init.codec.h264.in_transform8x8_mode = h264_arg->Transform8x8Mode; + + /* FIXME: is it removed? */ + EncArg.args.enc_init.codec.h264.in_md_interweight_pps = 300; + EncArg.args.enc_init.codec.h264.in_md_intraweight_pps = 170; + + break; + + default: + LOGE("SsbSipMfcEncInit] No such codec type is supported"); + return MFC_RET_INVALID_PARAM; + } + + EncArg.args.enc_init.cmn.in_mapped_addr = pCTX->mapped_addr; + + ret_code = ioctl(pCTX->hMFC, IOCTL_MFC_ENC_INIT, &EncArg); + if (EncArg.ret_code != MFC_OK) { + LOGE("SsbSipMfcEncInit] IOCTL_MFC_ENC_INIT failed"); + return MFC_RET_ENC_INIT_FAIL; + } + + pCTX->virStrmBuf = EncArg.args.enc_init.cmn.out_u_addr.strm_ref_y; + pCTX->phyStrmBuf = EncArg.args.enc_init.cmn.out_p_addr.strm_ref_y; + + pCTX->sizeStrmBuf = MAX_ENCODER_OUTPUT_BUFFER_SIZE; + pCTX->encodedHeaderSize = EncArg.args.enc_init.cmn.out_header_size; + + pCTX->virMvRefYC = EncArg.args.enc_init.cmn.out_u_addr.mv_ref_yc; + + pCTX->inter_buff_status |= MFC_USE_STRM_BUFF; + + return MFC_RET_OK; +} + +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncExe(void *openHandle) +{ + int ret_code; + _MFCLIB *pCTX; + struct mfc_common_args EncArg; + + if (openHandle == NULL) { + LOGE("SsbSipMfcEncExe] openHandle is NULL"); + return MFC_RET_INVALID_PARAM; + } + + pCTX = (_MFCLIB *)openHandle; + + memset(&EncArg, 0x00, sizeof(struct mfc_common_args)); + + EncArg.args.enc_exe.in_codec_type = pCTX->codecType; + EncArg.args.enc_exe.in_Y_addr = (unsigned int)pCTX->phyFrmBuf.luma; + EncArg.args.enc_exe.in_CbCr_addr = (unsigned int)pCTX->phyFrmBuf.chroma; +#if 0 /* peter for debug */ + EncArg.args.enc_exe.in_Y_addr_vir = (unsigned int)pCTX->virFrmBuf.luma; + EncArg.args.enc_exe.in_CbCr_addr_vir = (unsigned int)pCTX->virFrmBuf.chroma; +#endif + EncArg.args.enc_exe.in_frametag = pCTX->inframetag; + if (pCTX->encode_cnt == 0) { + EncArg.args.enc_exe.in_strm_st = (unsigned int)pCTX->phyStrmBuf; + EncArg.args.enc_exe.in_strm_end = (unsigned int)pCTX->phyStrmBuf + pCTX->sizeStrmBuf; + } else { + EncArg.args.enc_exe.in_strm_st = (unsigned int)pCTX->phyStrmBuf + (MAX_ENCODER_OUTPUT_BUFFER_SIZE / 2); + EncArg.args.enc_exe.in_strm_end = (unsigned int)pCTX->phyStrmBuf + pCTX->sizeStrmBuf + (MAX_ENCODER_OUTPUT_BUFFER_SIZE / 2); + } + + ret_code = ioctl(pCTX->hMFC, IOCTL_MFC_ENC_EXE, &EncArg); + if (EncArg.ret_code != MFC_OK) { + LOGE("SsbSipMfcEncExe] IOCTL_MFC_ENC_EXE failed(ret : %d)", EncArg.ret_code); + return MFC_RET_ENC_EXE_ERR; + } + + pCTX->encodedDataSize = EncArg.args.enc_exe.out_encoded_size; + pCTX->encodedframeType = EncArg.args.enc_exe.out_frame_type; + pCTX->encodedphyFrmBuf.luma = EncArg.args.enc_exe.out_Y_addr; + pCTX->encodedphyFrmBuf.chroma = EncArg.args.enc_exe.out_CbCr_addr; + pCTX->outframetagtop = EncArg.args.enc_exe.out_frametag_top; + pCTX->outframetagbottom = EncArg.args.enc_exe.out_frametag_bottom; + + LOGV("SsbSipMfcEncExe] Encode success =================="); + + return MFC_RET_OK; +} + +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncClose(void *openHandle) +{ + int ret_code; + _MFCLIB *pCTX; + struct mfc_common_args free_arg; + + if (openHandle == NULL) { + LOGE("SsbSipMfcEncClose] openHandle is NULL"); + return MFC_RET_INVALID_PARAM; + } + + pCTX = (_MFCLIB *)openHandle; + + /* FIXME: free buffer? */ + if (pCTX->inter_buff_status & MFC_USE_YUV_BUFF) { + free_arg.args.mem_free.key = pCTX->virFrmBuf.luma; + ret_code = ioctl(pCTX->hMFC, IOCTL_MFC_FREE_BUF, &free_arg); + } + + if (pCTX->inter_buff_status & MFC_USE_STRM_BUFF) { + free_arg.args.mem_free.key = pCTX->virStrmBuf; + ret_code = ioctl(pCTX->hMFC, IOCTL_MFC_FREE_BUF, &free_arg); + free_arg.args.mem_free.key = pCTX->virMvRefYC; + ret_code = ioctl(pCTX->hMFC, IOCTL_MFC_FREE_BUF, &free_arg); + } + + pCTX->inter_buff_status = MFC_USE_NONE; + + munmap((void *)pCTX->mapped_addr, pCTX->mapped_size); + + close(pCTX->hMFC); + + free(pCTX); + + return MFC_RET_OK; +} + +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncGetInBuf(void *openHandle, SSBSIP_MFC_ENC_INPUT_INFO *input_info) +{ + int ret_code; + _MFCLIB *pCTX; + struct mfc_common_args user_addr_arg, real_addr_arg; + int y_size, c_size; + int aligned_y_size, aligned_c_size; + + if (openHandle == NULL) { + LOGE("SsbSipMfcEncGetInBuf] openHandle is NULL"); + return MFC_RET_INVALID_PARAM; + } + + pCTX = (_MFCLIB *) openHandle; + + /* FIXME: */ + y_size = pCTX->width * pCTX->height; + c_size = (pCTX->width * pCTX->height) >> 1; + + /* lenear: 2KB, tile: 8KB */ + aligned_y_size = Align(y_size, 64 * BUF_L_UNIT); + aligned_c_size = Align(c_size, 64 * BUF_L_UNIT); + + /* Allocate luma & chroma buf */ + user_addr_arg.args.mem_alloc.type = ENCODER; + user_addr_arg.args.mem_alloc.buff_size = aligned_y_size + aligned_c_size; + user_addr_arg.args.mem_alloc.mapped_addr = pCTX->mapped_addr; + ret_code = ioctl(pCTX->hMFC, IOCTL_MFC_GET_IN_BUF, &user_addr_arg); + if (ret_code < 0) { + LOGE("SsbSipMfcEncGetInBuf] IOCTL_MFC_GET_IN_BUF failed"); + return MFC_RET_ENC_GET_INBUF_FAIL; + } + + pCTX->virFrmBuf.luma = pCTX->mapped_addr + user_addr_arg.args.mem_alloc.offset; + pCTX->virFrmBuf.chroma = pCTX->mapped_addr + user_addr_arg.args.mem_alloc.offset + (unsigned int)aligned_y_size; + + real_addr_arg.args.real_addr.key = user_addr_arg.args.mem_alloc.offset; + ret_code = ioctl(pCTX->hMFC, IOCTL_MFC_GET_REAL_ADDR, &real_addr_arg); + if (ret_code < 0) { + LOGE("SsbSipMfcEncGetInBuf] IOCTL_MFC_GET_REAL_ADDR failed"); + return MFC_RET_ENC_GET_INBUF_FAIL; + } + pCTX->phyFrmBuf.luma = real_addr_arg.args.real_addr.addr; + pCTX->phyFrmBuf.chroma = real_addr_arg.args.real_addr.addr + (unsigned int)aligned_y_size; + + pCTX->sizeFrmBuf.luma = (unsigned int)y_size; + pCTX->sizeFrmBuf.chroma = (unsigned int)c_size; + pCTX->inter_buff_status |= MFC_USE_YUV_BUFF; + + input_info->YPhyAddr = (void*)pCTX->phyFrmBuf.luma; + input_info->CPhyAddr = (void*)pCTX->phyFrmBuf.chroma; + input_info->YVirAddr = (void*)pCTX->virFrmBuf.luma; + input_info->CVirAddr = (void*)pCTX->virFrmBuf.chroma; + + return MFC_RET_OK; +} + +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncSetInBuf(void *openHandle, SSBSIP_MFC_ENC_INPUT_INFO *input_info) +{ + _MFCLIB *pCTX; + int ret_code; + struct mfc_common_args user_addr_arg, real_addr_arg; + int y_size, c_size; + int aligned_y_size, aligned_c_size; + + if (openHandle == NULL) { + LOGE("SsbSipMfcEncSetInBuf] openHandle is NULL"); + return MFC_RET_INVALID_PARAM; + } + + LOGV("SsbSipMfcEncSetInBuf] input_info->YPhyAddr & input_info->CPhyAddr should be 64KB aligned"); + + pCTX = (_MFCLIB *) openHandle; + + /* FIXME: */ + y_size = pCTX->width * pCTX->height; + c_size = (pCTX->width * pCTX->height) >> 1; + + /* lenear: 2KB, tile: 8KB */ + aligned_y_size = Align(y_size, 64 * BUF_L_UNIT); + aligned_c_size = Align(c_size, 64 * BUF_L_UNIT); + + pCTX->phyFrmBuf.luma = (unsigned int)input_info->YPhyAddr; + pCTX->phyFrmBuf.chroma = (unsigned int)input_info->CPhyAddr; + + pCTX->sizeFrmBuf.luma = (unsigned int)input_info->YSize; + pCTX->sizeFrmBuf.chroma = (unsigned int)input_info->CSize; + + return MFC_RET_OK; +} + +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncGetOutBuf(void *openHandle, SSBSIP_MFC_ENC_OUTPUT_INFO *output_info) +{ + _MFCLIB *pCTX; + + if (openHandle == NULL) { + LOGE("SsbSipMfcEncGetOutBuf] openHandle is NULL"); + return MFC_RET_INVALID_PARAM; + } + + pCTX = (_MFCLIB *)openHandle; + + output_info->headerSize = pCTX->encodedHeaderSize; + output_info->dataSize = pCTX->encodedDataSize; + output_info->frameType = pCTX->encodedframeType; + + if (pCTX->encode_cnt == 0) { + output_info->StrmPhyAddr = (void *)pCTX->phyStrmBuf; + output_info->StrmVirAddr = (unsigned char *)pCTX->virStrmBuf + pCTX->mapped_addr; + } else { + output_info->StrmPhyAddr = (unsigned char *)pCTX->phyStrmBuf + (MAX_ENCODER_OUTPUT_BUFFER_SIZE / 2); + output_info->StrmVirAddr = (unsigned char *)pCTX->virStrmBuf + pCTX->mapped_addr + (MAX_ENCODER_OUTPUT_BUFFER_SIZE / 2); + } + + pCTX->encode_cnt ++; + pCTX->encode_cnt %= 2; + + output_info->encodedYPhyAddr = (void*)pCTX->encodedphyFrmBuf.luma; + output_info->encodedCPhyAddr = (void*)pCTX->encodedphyFrmBuf.chroma; + + return MFC_RET_OK; +} + +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncSetOutBuf(void *openHandle, void *phyOutbuf, void *virOutbuf, int outputBufferSize) +{ + _MFCLIB *pCTX; + + if (openHandle == NULL) { + LOGE("SsbSipMfcEncSetOutBuf] openHandle is NULL"); + return MFC_RET_INVALID_PARAM; + } + + pCTX = (_MFCLIB *) openHandle; + + pCTX->phyStrmBuf = (int)phyOutbuf; + pCTX->virStrmBuf = (int)virOutbuf; + pCTX->sizeStrmBuf = outputBufferSize; + + return MFC_RET_OK; +} + +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncSetConfig(void *openHandle, SSBSIP_MFC_ENC_CONF conf_type, void *value) +{ + int ret_code; + _MFCLIB *pCTX; + struct mfc_common_args EncArg; + struct mfc_enc_vui_info vui_info; + struct mfc_enc_hier_p_qp hier_p_qp; +#ifdef S3D_SUPPORT + struct mfc_enc_set_config set_info; + struct mfc_frame_packing *frame_packing; +#endif + + if (openHandle == NULL) { + LOGE("SsbSipMfcEncSetConfig] openHandle is NULL"); + return MFC_RET_INVALID_PARAM; + } + + if (value == NULL) { + LOGE("SsbSipMfcEncSetConfig] value is NULL"); + return MFC_RET_INVALID_PARAM; + } + + pCTX = (_MFCLIB *) openHandle; + memset(&EncArg, 0x00, sizeof(struct mfc_common_args)); + +#ifdef S3D_SUPPORT + EncArg.args.config.type = conf_type; + + 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: + set_info = *((struct mfc_enc_set_config *) value); + EncArg.args.config.args.basic.values[0] = set_info.enable; + if (set_info.enable == 2) + EncArg.args.config.args.basic.values[1] = set_info.number; + else + EncArg.args.config.args.basic.values[1] = 0; + break; + case MFC_ENC_SETCONF_VUI_INFO: + set_info = *((struct mfc_enc_set_config *) value); + EncArg.args.config.args.basic.values[0] = set_info.enable; + if (set_info.enable == 255) //Re-check this part of code with Jeongtae Park + EncArg.args.config.args.basic.values[1] = set_info.number; + else + EncArg.args.config.args.basic.values[1] = 0; + + EncArg.args.config.args.basic.values[1] = set_info.number; + break; + case MFC_ENC_SETCONF_FRAME_PACKING: + frame_packing = (struct mfc_frame_packing *)value; + /* + memcpy(&EncArg.args.config.args.frame_packing, frame_packing, + sizeof(struct mfc_frame_packing)); + */ + EncArg.args.config.args.basic.values[0] = frame_packing->arrangement_type; + EncArg.args.config.args.basic.values[1] = frame_packing->current_frame_is_frame0_flag; + break; + case MFC_ENC_SETCONF_FRAME_TYPE: + case MFC_ENC_SETCONF_CHANGE_FRAME_RATE: + case MFC_ENC_SETCONF_CHANGE_BIT_RATE: + case MFC_ENC_SETCONF_I_PERIOD: + case MFC_ENC_SETCONF_HIER_P: + case MFC_ENC_SETCONF_SEI_GEN: + EncArg.args.config.args.basic.values[0] = *((int *) value); + EncArg.args.config.args.basic.values[1] = 0; + break; + default: + LOGE("SsbSipMfcEncSetConfig] not supported type"); + return MFC_RET_ENC_SET_CONF_FAIL; + } +#else + EncArg.args.set_config.in_config_param = conf_type; + switch (conf_type) { + case MFC_ENC_SETCONF_FRAME_TAG: + pCTX->inframetag = *((unsigned int *)value); + return MFC_RET_OK; + 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; + default: + EncArg.args.set_config.in_config_value[0] = *((int *) value); + EncArg.args.set_config.in_config_value[1] = 0; + break; + } +#endif + + ret_code = ioctl(pCTX->hMFC, IOCTL_MFC_SET_CONFIG, &EncArg); + if (EncArg.ret_code != MFC_OK) { + LOGE("SsbSipMfcEncSetConfig] IOCTL_MFC_SET_CONFIG failed(ret : %d)", EncArg.ret_code); + return MFC_RET_ENC_SET_CONF_FAIL; + } + + return MFC_RET_OK; +} + + +SSBSIP_MFC_ERROR_CODE SsbSipMfcEncGetConfig(void *openHandle, SSBSIP_MFC_ENC_CONF conf_type, void *value) +{ + _MFCLIB *pCTX; + /* + unsigned int *encoded_header_size; + */ + + pCTX = (_MFCLIB *)openHandle; + + if (openHandle == NULL) { + LOGE("SsbSipMfcEncGetConfig] openHandle is NULL"); + return MFC_RET_INVALID_PARAM; + } + if (value == NULL) { + LOGE("SsbSipMfcEncGetConfig] value is NULL"); + return MFC_RET_INVALID_PARAM; + } + + switch (conf_type) { + case MFC_ENC_GETCONF_FRAME_TAG: + *((unsigned int *)value) = pCTX->outframetagtop; + break; +#if 0 + case MFC_ENC_GETCONF_HEADER_SIZE: + encoded_header_size = (unsigned int *)value; + *encoded_header_size = pCTX->encodedHeaderSize; + break; +#endif + default: + LOGE("SsbSipMfcEncGetConfig] No such conf_type is supported."); + return MFC_RET_INVALID_PARAM; + } + + return MFC_RET_OK; +} + |