diff options
author | codeworkx <daniel.hillenbrand@codeworkx.de> | 2012-05-20 12:00:36 +0200 |
---|---|---|
committer | codeworkx <daniel.hillenbrand@codeworkx.de> | 2012-05-20 12:00:36 +0200 |
commit | 62f02ba4f4b7b561aa15408ebd9951600bdd71aa (patch) | |
tree | ac05dc645945a58edbc26e96df1a78ac16f27706 /exynos/multimedia/codecs | |
parent | e54debb12ecdf92d12acab00a261c0c5a6ef1d64 (diff) | |
download | android_hardware_samsung-62f02ba4f4b7b561aa15408ebd9951600bdd71aa.tar.gz android_hardware_samsung-62f02ba4f4b7b561aa15408ebd9951600bdd71aa.tar.bz2 android_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')
43 files changed, 12416 insertions, 0 deletions
diff --git a/exynos/multimedia/codecs/Android.mk b/exynos/multimedia/codecs/Android.mk new file mode 100644 index 0000000..6571161 --- /dev/null +++ b/exynos/multimedia/codecs/Android.mk @@ -0,0 +1 @@ +include $(all-subdir-makefiles) diff --git a/exynos/multimedia/codecs/audio/Android.mk b/exynos/multimedia/codecs/audio/Android.mk new file mode 100644 index 0000000..3bc3577 --- /dev/null +++ b/exynos/multimedia/codecs/audio/Android.mk @@ -0,0 +1,11 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +ifeq ($(filter-out exynos4,$(TARGET_BOARD_PLATFORM)),) +include $(LOCAL_PATH)/exynos4/Android.mk +endif + +ifeq ($(filter-out exynos5,$(TARGET_BOARD_PLATFORM)),) +include $(LOCAL_PATH)/exynos5/Android.mk +endif diff --git a/exynos/multimedia/codecs/audio/exynos4/Android.mk b/exynos/multimedia/codecs/audio/exynos4/Android.mk new file mode 100644 index 0000000..df938be --- /dev/null +++ b/exynos/multimedia/codecs/audio/exynos4/Android.mk @@ -0,0 +1,14 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_AUDIO_PATH :=$(LOCAL_PATH) + +ifeq ($(BOARD_USE_ALP_AUDIO), true) + include $(LOCAL_AUDIO_PATH)/srp/alp/Android.mk +else + ifeq ($(USE_ULP_AUDIO), true) + include $(LOCAL_AUDIO_PATH)/srp/ulp/Android.mk + include $(LOCAL_AUDIO_PATH)/srp/libsa_jni/Android.mk + endif +endif diff --git a/exynos/multimedia/codecs/audio/exynos4/srp/alp/Android.mk b/exynos/multimedia/codecs/audio/exynos4/srp/alp/Android.mk new file mode 100644 index 0000000..7393f68 --- /dev/null +++ b/exynos/multimedia/codecs/audio/exynos4/srp/alp/Android.mk @@ -0,0 +1,26 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_COPY_HEADERS_TO := libsecmm +LOCAL_COPY_HEADERS := \ + include/srp_api.h \ + include/srp_ioctl.h \ + include/srp_error.h + +LOCAL_SRC_FILES := \ + src/srp_api.c + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/include + +LOCAL_MODULE := libsrpapi + +LOCAL_MODULE_TAGS := optional + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := + +LOCAL_SHARED_LIBRARIES := + +include $(BUILD_STATIC_LIBRARY) diff --git a/exynos/multimedia/codecs/audio/exynos4/srp/alp/include/srp_api.h b/exynos/multimedia/codecs/audio/exynos4/srp/alp/include/srp_api.h new file mode 100644 index 0000000..ad65b90 --- /dev/null +++ b/exynos/multimedia/codecs/audio/exynos4/srp/alp/include/srp_api.h @@ -0,0 +1,52 @@ +#ifndef __SRP_API_H__ +#define __SRP_API_H__ + +#include "srp_ioctl.h" +#include "srp_error.h" + +#define SRP_DEV_NAME "dev/srp" + +#define SRP_INIT_BLOCK_MODE 0 +#define SRP_INIT_NONBLOCK_MODE 1 + +#define SRP_PENDING_STATE_RUNNING 0 +#define SRP_PENDING_STATE_PENDING 1 + +struct srp_buf_info { + void *mmapped_addr; + void *addr; + unsigned int mmapped_size; + unsigned int size; + int num; +}; + +struct srp_dec_info { + unsigned int sample_rate; + unsigned int channels; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +int SRP_Create(int block_mode); +int SRP_Init(); +int SRP_Decode(void *buff, int size_byte); +int SRP_Send_EOS(void); +int SRP_SetParams(int id, unsigned long val); +int SRP_GetParams(int id, unsigned long *pval); +int SRP_Deinit(void); +int SRP_Terminate(void); +int SRP_IsOpen(void); + +int SRP_Get_Ibuf_Info(void **addr, unsigned int *size, unsigned int *num); +int SRP_Get_Obuf_Info(void **addr, unsigned int *size, unsigned int *num); +int SRP_Get_Dec_Info(struct srp_dec_info *dec_info); +int SRP_Get_PCM(void **addr, unsigned int *size); +int SRP_Flush(void); + +#ifdef __cplusplus +} +#endif + +#endif /*__SRP_API_H__ */ diff --git a/exynos/multimedia/codecs/audio/exynos4/srp/alp/include/srp_error.h b/exynos/multimedia/codecs/audio/exynos4/srp/alp/include/srp_error.h new file mode 100644 index 0000000..7f79452 --- /dev/null +++ b/exynos/multimedia/codecs/audio/exynos4/srp/alp/include/srp_error.h @@ -0,0 +1,22 @@ +#ifndef _SRP_ERROR_H_ +#define _SRP_ERROR_H_ + +typedef enum { + SRP_RETURN_OK = 0, + + SRP_ERROR_OPEN_FAIL = -1000, + SRP_ERROR_ALREADY_OPEN = -1001, + SRP_ERROR_NOT_READY = -1002, + + SRP_ERROR_IBUF_OVERFLOW = -2000, + SRP_ERROR_IBUF_INFO = -2001, + + SRP_ERROR_OBUF_READ = -3000, + SRP_ERROR_OBUF_INFO = -3001, + SRP_ERROR_OBUF_MMAP = -3002, + + SRP_ERROR_INVALID_SETTING = -4000, + SRP_ERROR_GETINFO_FAIL = -4001 +} SRP_ERRORTYPE; + +#endif /* _SRP_ERROR_H_ */ diff --git a/exynos/multimedia/codecs/audio/exynos4/srp/alp/include/srp_ioctl.h b/exynos/multimedia/codecs/audio/exynos4/srp/alp/include/srp_ioctl.h new file mode 100644 index 0000000..21d55df --- /dev/null +++ b/exynos/multimedia/codecs/audio/exynos4/srp/alp/include/srp_ioctl.h @@ -0,0 +1,23 @@ +#ifndef __SRP_IOCTL_H__ +#define __SRP_IOCTL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SRP_INIT (0x10000) +#define SRP_DEINIT (0x10001) +#define SRP_GET_MMAP_SIZE (0x10002) +#define SRP_FLUSH (0x20002) +#define SRP_SEND_EOS (0x20005) +#define SRP_GET_IBUF_INFO (0x20007) +#define SRP_GET_OBUF_INFO (0x20008) +#define SRP_STOP_EOS_STATE (0x30007) +#define SRP_GET_DEC_INFO (0x30008) + +#ifdef __cplusplus +} +#endif + +#endif /* __SRP_IOCTL_H__ */ + diff --git a/exynos/multimedia/codecs/audio/exynos4/srp/alp/src/srp_api.c b/exynos/multimedia/codecs/audio/exynos4/srp/alp/src/srp_api.c new file mode 100644 index 0000000..56125fb --- /dev/null +++ b/exynos/multimedia/codecs/audio/exynos4/srp/alp/src/srp_api.c @@ -0,0 +1,265 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/time.h> +#include <fcntl.h> +#include <ctype.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <stdio.h> + +#include "srp_api.h" + +#define LOG_NDEBUG 1 +#define LOG_TAG "libsrpapi" +#include <utils/Log.h> + +static struct srp_buf_info ibuf_info; +static struct srp_buf_info obuf_info; +static struct srp_buf_info pcm_info; + +static int srp_dev = -1; +static int srp_block_mode = SRP_INIT_BLOCK_MODE; + +int SRP_Create(int block_mode) +{ + if (srp_dev == -1) { + srp_block_mode = block_mode; + srp_dev = open(SRP_DEV_NAME, O_RDWR | + ((block_mode == SRP_INIT_NONBLOCK_MODE) ? O_NDELAY : 0)); + if (srp_dev > 0) + return srp_dev; + else + return SRP_ERROR_OPEN_FAIL; + } + + LOGE("%s: Device is already opened", __func__); + return SRP_ERROR_ALREADY_OPEN; +} + +int SRP_Init() +{ + int ret = SRP_RETURN_OK; + unsigned int mmapped_size = 0; + + if (srp_dev != -1) { + ret = ioctl(srp_dev, SRP_INIT); + if (ret < 0) + return ret; + + /* mmap for OBUF */ + ret = ioctl(srp_dev, SRP_GET_MMAP_SIZE, &mmapped_size); + if (ret < 0) { + LOGE("%s: SRP_GET_MMAP_SIZE is failed", __func__); + return SRP_ERROR_OBUF_MMAP; + } + obuf_info.mmapped_addr = mmap(0, mmapped_size, + PROT_READ | PROT_WRITE, MAP_SHARED, srp_dev, 0); + if (!obuf_info.mmapped_addr) { + LOGE("%s: mmap is failed", __func__); + return SRP_ERROR_OBUF_MMAP; + } + obuf_info.mmapped_size = mmapped_size; + + ret = SRP_RETURN_OK; + } else { + LOGE("%s: Device is not ready", __func__); + ret = SRP_ERROR_NOT_READY; /* device is not created */ + } + + return ret; +} + +int SRP_Decode(void *buff, int size_byte) +{ + int ret = SRP_RETURN_OK; + + if (srp_dev != -1) { + if (size_byte > 0) { + LOGV("%s: Send data to RP (%d bytes)", __func__, size_byte); + + ret = write(srp_dev, buff, size_byte); /* Write Buffer to RP Driver */ + if (ret < 0) { + if (ret != SRP_ERROR_IBUF_OVERFLOW) + LOGE("SRP_Decode returned error code: %d", ret); + } + return ret; /* Write Success */ + } else { + return ret; + } + } + + LOGE("%s: Device is not ready", __func__); + return SRP_ERROR_NOT_READY; +} + +int SRP_Send_EOS(void) +{ + if (srp_dev != -1) + return ioctl(srp_dev, SRP_SEND_EOS); + + return SRP_ERROR_NOT_READY; +} + +int SRP_SetParams(int id, unsigned long val) +{ + if (srp_dev != -1) + return 0; /* not yet */ + + return SRP_ERROR_NOT_READY; +} + +int SRP_GetParams(int id, unsigned long *pval) +{ + if (srp_dev != -1) + return ioctl(srp_dev, id, pval); + + return SRP_ERROR_NOT_READY; +} + +int SRP_Flush(void) +{ + if (srp_dev != -1) + return ioctl(srp_dev, SRP_FLUSH); + + return SRP_ERROR_NOT_READY; +} + +int SRP_Get_PCM(void **addr, unsigned int *size) +{ + int ret = SRP_RETURN_OK; + + if (srp_dev != -1) { + ret = read(srp_dev, &pcm_info, 0); + if (ret == -1) { + *size = 0; + LOGE("%s: PCM read fail", __func__); + return SRP_ERROR_OBUF_READ; + } + + *addr = pcm_info.addr; + *size = pcm_info.size; + } else { + return SRP_ERROR_NOT_READY; + } + + return ret; /* Read Success */ +} + +int SRP_Get_Dec_Info(struct srp_dec_info *dec_info) +{ + int ret; + + if (srp_dev != -1) { + ret = ioctl(srp_dev, SRP_GET_DEC_INFO, dec_info); + if (ret < 0) { + LOGE("%s: Failed to get dec info", __func__); + return SRP_ERROR_GETINFO_FAIL; + } + + LOGV("numChannels(%d), samplingRate(%d)", dec_info->channels, dec_info->sample_rate); + + ret = SRP_RETURN_OK; + } else { + ret = SRP_ERROR_NOT_READY; + } + + return ret; +} + +int SRP_Get_Ibuf_Info(void **addr, unsigned int *size, unsigned int *num) +{ + int ret = SRP_RETURN_OK; + + if (srp_dev != -1) { + ret = ioctl(srp_dev, SRP_GET_IBUF_INFO, &ibuf_info); + if (ret == -1) { + LOGE("%s: Failed to get Ibuf info", __func__); + return SRP_ERROR_IBUF_INFO; + } + + *addr = ibuf_info.addr; + *size = ibuf_info.size; + *num = ibuf_info.num; + + if (*num == 0) { + LOGE("%s: IBUF num is 0", __func__); + return SRP_ERROR_INVALID_SETTING; + } + + ret = SRP_RETURN_OK; + } else { + ret = SRP_ERROR_NOT_READY; + } + + return ret; +} + +int SRP_Get_Obuf_Info(void **addr, unsigned int *size, unsigned int *num) +{ + int ret = SRP_RETURN_OK; + + if (srp_dev != -1) { + if (obuf_info.addr == NULL) { + ret = ioctl(srp_dev, SRP_GET_OBUF_INFO, &obuf_info); + if (ret < 0) { + LOGE("%s: SRP_GET_OBUF_INFO is failed", __func__); + return SRP_ERROR_OBUF_INFO; + } + } + + *addr = obuf_info.addr; + *size = obuf_info.size; + *num = obuf_info.num; + + if (*num == 0) { + LOGE("%s: OBUF num is 0", __func__); + return SRP_ERROR_INVALID_SETTING; + } + + ret = SRP_RETURN_OK; + } else { + ret = SRP_ERROR_NOT_READY; + } + + return ret; +} + +int SRP_Deinit(void) +{ + if (srp_dev != -1) { + munmap(obuf_info.mmapped_addr, obuf_info.mmapped_size); + return ioctl(srp_dev, SRP_DEINIT); + } + + return SRP_ERROR_NOT_READY; +} + +int SRP_Terminate(void) +{ + int ret; + + if (srp_dev != -1) { + ret = close(srp_dev); + + if (ret == 0) { + srp_dev = -1; /* device closed */ + return SRP_RETURN_OK; + } + } + + return SRP_ERROR_NOT_READY; +} + +int SRP_IsOpen(void) +{ + if (srp_dev == -1) { + LOGV("%s: Device is not opened", __func__); + return 0; + } + + LOGV("%s: Device is opened", __func__); + return 1; +} diff --git a/exynos/multimedia/codecs/audio/exynos4/srp/libsa_jni/Android.mk b/exynos/multimedia/codecs/audio/exynos4/srp/libsa_jni/Android.mk new file mode 100644 index 0000000..8450845 --- /dev/null +++ b/exynos/multimedia/codecs/audio/exynos4/srp/libsa_jni/Android.mk @@ -0,0 +1,13 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false + +LOCAL_MODULE := libsa_jni +LOCAL_SRC_FILES := SACtrl.c + +LOCAL_SHARED_LIBRARIES := libcutils +LOCAL_STATIC_LIBRARIES := libsrpapi + +include $(BUILD_SHARED_LIBRARY) diff --git a/exynos/multimedia/codecs/audio/exynos4/srp/libsa_jni/SACtrl.c b/exynos/multimedia/codecs/audio/exynos4/srp/libsa_jni/SACtrl.c new file mode 100644 index 0000000..6b99dc3 --- /dev/null +++ b/exynos/multimedia/codecs/audio/exynos4/srp/libsa_jni/SACtrl.c @@ -0,0 +1,33 @@ +#include <jni.h> +#include <time.h> + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> + +#include "srp_api_ctrl.h" + +#define LOG_TAG "libsa_jni" +#include <cutils/log.h> + +void Java_com_android_music_SetSACtrlJNI_set(JNIEnv * env, jobject obj, int effect_num) +{ + unsigned long effect_enable = effect_num ? 1 : 0; + unsigned int ret; + + LOGD("Sound effect[%d]", effect_num); + + ret = SRP_Ctrl_Enable_Effect(effect_enable); + if (ret < 0) { + LOGE("%s: Couldn't enabled effect\n", __func__); + return; + } + + SRP_Ctrl_Set_Effect_Def(effect_num << 5); + if (ret < 0) { + LOGE("%s: Couldn't defined effect\n", __func__); + return; + } + + return; +} diff --git a/exynos/multimedia/codecs/audio/exynos4/srp/ulp/Android.mk b/exynos/multimedia/codecs/audio/exynos4/srp/ulp/Android.mk new file mode 100644 index 0000000..5b1d397 --- /dev/null +++ b/exynos/multimedia/codecs/audio/exynos4/srp/ulp/Android.mk @@ -0,0 +1,23 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + src/srp_api.c \ + src/srp_api_ctrl.c + +LOCAL_MODULE := libsrpapi + +LOCAL_MODULE_TAGS := optional + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := + +LOCAL_SHARED_LIBRARIES := + +LOCAL_COPY_HEADERS := \ + include/srp_api.h \ + include/srp_api_ctrl.h \ + include/srp_ioctl.h + +include $(BUILD_STATIC_LIBRARY) diff --git a/exynos/multimedia/codecs/audio/exynos4/srp/ulp/include/srp_api.h b/exynos/multimedia/codecs/audio/exynos4/srp/ulp/include/srp_api.h new file mode 100644 index 0000000..74598e5 --- /dev/null +++ b/exynos/multimedia/codecs/audio/exynos4/srp/ulp/include/srp_api.h @@ -0,0 +1,55 @@ +#ifndef __SRP_API_H__ +#define __SRP_API_H__ + +#include "srp_ioctl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int SRP_Create(int block_mode); +int SRP_Init(unsigned int ibuf_size); +int SRP_Decode(void *buff, int size_byte); +int SRP_Send_EOS(void); +int SRP_Resume_EOS(void); +int SRP_Pause(void); +int SRP_Stop(void); +int SRP_Flush(void); +int SRP_SetParams(int id, unsigned long val); +int SRP_GetParams(int id, unsigned long *pval); +int SRP_Deinit(void); +int SRP_Terminate(void); +int SRP_IsOpen(void); + +#define SRP_DEV_NAME "dev/srp" + +#define SRP_INIT_BLOCK_MODE 0 +#define SRP_INIT_NONBLOCK_MODE 1 + +#define SRP_PENDING_STATE_RUNNING 0 +#define SRP_PENDING_STATE_PENDING 1 + +#define SRP_ERROR_LOSTSYNC 0x00101 +#define SRP_ERROR_BADLAYER 0x00102 +#define SRP_ERROR_BADBITRATE 0x00103 +#define SRP_ERROR_BADSAMPLERATE 0x00104 +#define SRP_ERROR_BADEMPHASIS 0x00105 + +#define SRP_ERROR_BADCRC 0x00201 +#define SRP_ERROR_BADBITALLOC 0x00211 +#define SRP_ERROR_BADBADSCALEFACTOR 0x00221 +#define SRP_ERROR_BADFRAMELEN 0x00231 +#define SRP_ERROR_BADBIGVALUES 0x00232 +#define SRP_ERROR_BADBLOCKTYPE 0x00233 +#define SRP_ERROR_BADSCFSI 0x00234 +#define SRP_ERROR_BADDATAPTR 0x00235 +#define SRP_ERROR_BADPART3LEN 0x00236 +#define SRP_ERROR_BADHUFFTABLE 0x00237 +#define SRP_ERROR_BADHUFFDATA 0x00238 +#define SRP_ERROR_BADSTEREO 0x00239 + +#ifdef __cplusplus +} +#endif + +#endif /*__SRP_API_H__ */ diff --git a/exynos/multimedia/codecs/audio/exynos4/srp/ulp/include/srp_api_ctrl.h b/exynos/multimedia/codecs/audio/exynos4/srp/ulp/include/srp_api_ctrl.h new file mode 100644 index 0000000..3b17acf --- /dev/null +++ b/exynos/multimedia/codecs/audio/exynos4/srp/ulp/include/srp_api_ctrl.h @@ -0,0 +1,25 @@ +#ifndef __SRP_API_CTRL_H__ +#define __SRP_API_CTRL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SRP_CTRL_DEV_NAME "dev/srp_ctrl" + +int SRP_Ctrl_Set_Effect(int effect); /* test only */ +int SRP_Ctrl_Enable_Effect(int on); +int SRP_Ctrl_Set_Effect_Def(unsigned long effect_def); +int SRP_Ctrl_Set_Effect_EQ_User(unsigned long eq_user); +int SRP_Ctrl_Set_Pcm_Dump(int on); +int SRP_Ctrl_Get_Pcm_Dump_State(void); +int SRP_Ctrl_Set_Gain(float value); +int SRP_Ctrl_Get_Running_Stat(void); +int SRP_Ctrl_Get_Open_Stat(void); +short *SRP_Ctrl_Get_Pcm(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __SRP_API_CTRL_H__ */ diff --git a/exynos/multimedia/codecs/audio/exynos4/srp/ulp/include/srp_ioctl.h b/exynos/multimedia/codecs/audio/exynos4/srp/ulp/include/srp_ioctl.h new file mode 100644 index 0000000..a20b1ac --- /dev/null +++ b/exynos/multimedia/codecs/audio/exynos4/srp/ulp/include/srp_ioctl.h @@ -0,0 +1,66 @@ +#ifndef __SRP_IOCTL_H__ +#define __SRP_IOCTL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* constants for srp device node */ +#define SRP_INIT (0x10000) +#define SRP_DEINIT (0x10001) + +#define SRP_PAUSE (0x20000) +#define SRP_STOP (0x20001) +#define SRP_FLUSH (0x20002) +#define SRP_WAIT_EOS (0x20003) +#define SRP_EFFECT (0x20004) +#define SRP_SEND_EOS (0x20005) +#define SRP_RESUME_EOS (0x20006) + +#define SRP_PENDING_STATE (0x30000) +#define SRP_ERROR_STATE (0x30001) +#define SRP_DECODED_FRAME_NO (0x30002) +#define SRP_DECODED_ONE_FRAME_SIZE (0x30003) +#define SRP_DECODED_FRAME_SIZE (0x30004) +#define SRP_DECODED_PCM_SIZE (0x30005) +#define SRP_CHANNEL_COUNT (0x30006) +#define SRP_STOP_EOS_STATE (0x30007) + +/* constants for srp_ctrl device node*/ +#define SRP_CTRL_SET_GAIN (0xFF000) +#define SRP_CTRL_SET_EFFECT (0xFF001) +#define SRP_CTRL_GET_PCM_1KFRAME (0xFF002) +#define SRP_CTRL_PCM_DUMP_OP (0xFF003) + +#define SRP_CTRL_EFFECT_ENABLE (0xFF010) +#define SRP_CTRL_EFFECT_DEF (0xFF011) +#define SRP_CTRL_EFFECT_EQ_USR (0xFF012) +#define SRP_CTRL_EFFECT_SPEAKER (0xFF013) + +#define SRP_CTRL_IS_RUNNING (0xFF100) +#define SRP_CTRL_IS_OPENED (0xFF101) +#define SRP_CTRL_GET_OP_LEVEL (0xFF102) +#define SRP_CTRL_IS_PCM_DUMP (0xFF103) + +#define SRP_CTRL_ALTFW_STATE (0xFF200) +#define SRP_CTRL_ALTFW_LOAD (0xFF201) + +/* constants for SRP firmware */ +#define SRP_FW_CODE1 0 +#define SRP_FW_CODE20 1 +#define SRP_FW_CODE21 2 +#define SRP_FW_CODE22 3 +#define SRP_FW_CODE30 4 +#define SRP_FW_CODE31 5 + +#define SRP_FW_VLIW 0 +#define SRP_FW_CGA 1 +#define SRP_FW_CGA_SA 2 +#define SRP_FW_DATA 3 + +#ifdef __cplusplus +} +#endif + +#endif /* __SRP_IOCTL_H__ */ + diff --git a/exynos/multimedia/codecs/audio/exynos4/srp/ulp/src/srp_api.c b/exynos/multimedia/codecs/audio/exynos4/srp/ulp/src/srp_api.c new file mode 100644 index 0000000..b0c0e5e --- /dev/null +++ b/exynos/multimedia/codecs/audio/exynos4/srp/ulp/src/srp_api.c @@ -0,0 +1,381 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/time.h> +#include <fcntl.h> +#include <ctype.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <stdio.h> + +#include "srp_api.h" + +#define LOG_TAG "libsrpapi" +#include <cutils/log.h> + +/* Disable LOGD message */ +#ifdef LOGD +#undef LOGD +#endif +#define LOGD(...) + +//#define _USE_WBUF_ /* Buffering before writing srp-rp device */ +//#define _DUMP_TO_FILE_ +//#define _USE_FW_FROM_DISK_ + +#ifdef _USE_WBUF_ +#define WBUF_LEN_MUL 2 +#endif + +static int srp_dev = -1; +static int srp_ibuf_size = 0; +static int srp_block_mode = SRP_INIT_BLOCK_MODE; + +static unsigned char *wbuf; +static int wbuf_size; +static int wbuf_pos; + +#ifdef _DUMP_TO_FILE_ +static FILE *fp_dump = NULL; +#endif + +#ifdef _USE_WBUF_ +static int WriteBuff_Init(void) +{ + if (wbuf == NULL) { + wbuf_size = srp_ibuf_size * WBUF_LEN_MUL; + wbuf_pos = 0; + wbuf = (unsigned char *)malloc(wbuf_size); + LOGD("%s: WriteBuffer %dbytes allocated", __func__, wbuf_size); + return 0; + } + + LOGE("%s: WriteBuffer already allocated", __func__); + return -1; +} + +static int WriteBuff_Deinit(void) +{ + if (wbuf != NULL) { + free(wbuf); + wbuf = NULL; + return 0; + } + + LOGE("%s: WriteBuffer is not ready", __func__); + return -1; +} + +static int WriteBuff_Write(unsigned char *buff, int size_byte) +{ + int write_byte; + + if ((wbuf_pos + size_byte) < wbuf_size) { + memcpy(&wbuf[wbuf_pos], buff, size_byte); + wbuf_pos += size_byte; + } else { + LOGE("%s: WriteBuffer is filled [%d], ignoring write [%d]", __func__, wbuf_pos, size_byte); + return -1; /* Insufficient buffer */ + } + + return wbuf_pos; +} + +static void WriteBuff_Consume(void) +{ + memcpy(wbuf, &wbuf[srp_ibuf_size], srp_ibuf_size * (WBUF_LEN_MUL - 1)); + wbuf_pos -= srp_ibuf_size; +} + +static void WriteBuff_Flush(void) +{ + wbuf_pos = 0; +} +#endif + +int SRP_Create(int block_mode) +{ + if (srp_dev == -1) { +#ifdef _USE_FW_FROM_DISK_ + SRP_Check_AltFirmware(); +#endif + + srp_block_mode = block_mode; + srp_dev = open(SRP_DEV_NAME, O_RDWR | + ((block_mode == SRP_INIT_NONBLOCK_MODE) ? O_NDELAY : 0)); + + return srp_dev; + } + + LOGE("%s: Device is not ready", __func__); + return -1; /* device alreay opened */ +} + +int SRP_Init(unsigned int ibuf_size) +{ + int ret; + + if (srp_dev != -1) { + srp_ibuf_size = ibuf_size; + ret = ioctl(srp_dev, SRP_INIT, srp_ibuf_size); /* Initialize IBUF size (4KB ~ 18KB) */ + +#ifdef _DUMP_TO_FILE_ + char outname[256]; + int cnt = 0; + + while (1) { + sprintf(outname, "/data/rp_dump_%04d.mp3", cnt++); + if (fp_dump = fopen(outname, "rb")) { /* file exist? */ + fclose(fp_dump); + } else { + break; + } + } + + LOGD("%s: Dump MP3 to %s", __func__, outname); + if (fp_dump = fopen(outname, "wb")) + LOGD("%s: Success to open %s", __func__, outname); + else + LOGD("%s: Fail to open %s", __func__, outname); +#endif + +#ifdef _USE_WBUF_ + if (ret != -1) + return WriteBuff_Init(); +#else + return ret; +#endif + } + + LOGE("%s: Device is not ready", __func__); + return -1; /* device is not created */ +} + +#ifdef _USE_WBUF_ +int SRP_Decode(void *buff, int size_byte) +{ + int ret; + int val; + int err_code = 0; + + if (srp_dev != -1) { + /* Check wbuf before writing buff */ + while (wbuf_pos >= srp_ibuf_size) { /* Write_Buffer filled? (IBUF Size)*/ + LOGD("%s: Write Buffer is full, Send data to RP", __func__); + + ret = write(srp_dev, wbuf, srp_ibuf_size); /* Write Buffer to RP Driver */ + if (ret == -1) { /* Fail? */ + ioctl(srp_dev, SRP_ERROR_STATE, &val); + if (!val) { /* Write error? */ + LOGE("%s: IBUF write fail", __func__); + return -1; + } else { /* Write OK, but RP decode error? */ + err_code = val; + LOGE("%s: RP decode error [0x%05X]", __func__, err_code); + } + } +#ifdef _DUMP_TO_FILE_ + if (fp_dump) + fwrite(wbuf, srp_ibuf_size, 1, fp_dump); +#endif + WriteBuff_Consume(); + } + + ret = WriteBuff_Write((unsigned char *)buff, size_byte); + if (ret == -1) + return -1; /* Buffering error */ + + LOGD("%s: Write Buffer remain [%d]", __func__, wbuf_pos); + return err_code; /* Write Success */ + } + + LOGE("%s: Device is not ready", __func__); + return -1; /* device is not created */ +} + +int SRP_Send_EOS(void) +{ + int ret; + int val; + + if (srp_dev != -1) { + /* Check wbuf before writing buff */ + while (wbuf_pos) { /* Write_Buffer ramain?*/ + if (wbuf_pos < srp_ibuf_size) { + memset(wbuf + wbuf_pos, 0xFF, srp_ibuf_size - wbuf_pos); /* Fill dummy data */ + wbuf_pos = srp_ibuf_size; + } + + ret = write(srp_dev, wbuf, srp_ibuf_size); /* Write Buffer to RP Driver */ + if (ret == -1) { /* Fail? */ + ret = ioctl(srp_dev, SRP_ERROR_STATE, &val); + if (!val) { /* Write error? */ + LOGE("%s: IBUF write fail", __func__); + return -1; + } else { /* RP decoe error? */ + LOGE("%s: RP decode error [0x%05X]", __func__, val); + return -1; + } + } else { /* Success? */ +#ifdef _DUMP_TO_FILE_ + if (fp_dump) + fwrite(wbuf, srp_ibuf_size, 1, fp_dump); +#endif + WriteBuff_Consume(); + } + } + + memset(wbuf, 0xFF, srp_ibuf_size); /* Fill dummy data */ + write(srp_dev, wbuf, srp_ibuf_size); /* Write Buffer to RP Driver */ + + /* Wait until RP decoding over */ + return ioctl(srp_dev, SRP_WAIT_EOS); + } + + return -1; /* device is not created */ +} +#else /* Without WBUF */ +int SRP_Decode(void *buff, int size_byte) +{ + int ret; + int val; + int err_code = 0; + + if (srp_dev != -1) { + LOGD("%s: Send data to RP (%d bytes)", __func__, size_byte); + + ret = write(srp_dev, buff, size_byte); /* Write Buffer to RP Driver */ + if (ret == -1) { /* Fail? */ + ioctl(srp_dev, SRP_ERROR_STATE, &val); + if (!val) { /* Write error? */ + LOGE("%s: IBUF write fail", __func__); + return -1; + } else { /* Write OK, but RP decode error? */ + err_code = val; + LOGE("%s: RP decode error [0x%05X]", __func__, err_code); + } + } +#ifdef _DUMP_TO_FILE_ + if (fp_dump) + fwrite(buff, size_byte, 1, fp_dump); +#endif + + return err_code; /* Write Success */ + } + + LOGE("%s: Device is not ready", __func__); + return -1; /* device is not created */ +} + +int SRP_Send_EOS(void) +{ + /* Wait until RP decoding over */ + if (srp_dev != -1) + return ioctl(srp_dev, SRP_SEND_EOS); + + return -1; /* device is not created */ +} + +int SRP_Resume_EOS(void) +{ + if (srp_dev != -1) + return ioctl(srp_dev, SRP_RESUME_EOS); + + return -1; /* device is not created */ +} +#endif + +int SRP_Pause(void) +{ + if (srp_dev != -1) + return ioctl(srp_dev, SRP_PAUSE); + + return -1; /* device is not created */ +} + +int SRP_Stop(void) +{ + if (srp_dev != -1) + return ioctl(srp_dev, SRP_STOP); + + return -1; /* device is not created */ +} + +int SRP_Flush(void) +{ + if (srp_dev != -1) { + if (ioctl(srp_dev, SRP_FLUSH) != -1) { +#ifdef _USE_WBUF_ + WriteBuff_Flush(); +#endif + return 0; + } + } + + return -1; /* device is not created */ +} + + +int SRP_SetParams(int id, unsigned long val) +{ + if (srp_dev != -1) + return 0; /* not yet */ + + return -1; /* device is not created */ +} + +int SRP_GetParams(int id, unsigned long *pval) +{ + if (srp_dev != -1) + return ioctl(srp_dev, id, pval); + + return -1; /* device is not created */ +} + +int SRP_Deinit(void) +{ + if (srp_dev != -1) { +#ifdef _DUMP_TO_FILE_ + if (fp_dump) + fclose(fp_dump); +#endif + +#ifdef _USE_WBUF_ + WriteBuff_Deinit(); +#endif + return ioctl(srp_dev, SRP_DEINIT); /* Deinialize */ + } + + LOGE("%s: Device is not ready", __func__); + return -1; /* device is not created */ +} + +int SRP_Terminate(void) +{ + int ret; + + if (srp_dev != -1) { + ret = close(srp_dev); + + if (ret == 0) { + srp_dev = -1; /* device closed */ + return 0; + } + } + + LOGE("%s: Device is not ready", __func__); + return -1; /* device is not created or close error*/ +} + +int SRP_IsOpen(void) +{ + if (srp_dev == -1) { + LOGD("%s: Device is not opened", __func__); + return 0; + } + + LOGD("%s: Device is opened", __func__); + return 1; +} diff --git a/exynos/multimedia/codecs/audio/exynos4/srp/ulp/src/srp_api_ctrl.c b/exynos/multimedia/codecs/audio/exynos4/srp/ulp/src/srp_api_ctrl.c new file mode 100644 index 0000000..bdc2310 --- /dev/null +++ b/exynos/multimedia/codecs/audio/exynos4/srp/ulp/src/srp_api_ctrl.c @@ -0,0 +1,331 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/time.h> +#include <fcntl.h> +#include <ctype.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <stdio.h> + +#include "srp_api_ctrl.h" +#include "srp_ioctl.h" + +#define LOG_TAG "libsrpapi" +#include <cutils/log.h> + +/* Disable LOGD message */ +#ifdef LOGD +#undef LOGD +#endif +#define LOGD(...) + +static int srp_ctrl = -1; +static int srp_ctrl_cnt = 0; +static short pcm_buf[2048]; /* 4KBytes data, 1K frames (16bit stereo data) */ + +#ifdef _USE_FW_FROM_DISK_ +static char srp_alt_fw_name_pre[6][32] = { + "sdcard/rp_fw/rp_fw_code1", + "sdcard/rp_fw/rp_fw_code20", + "sdcard/rp_fw/rp_fw_code21", + "sdcard/rp_fw/rp_fw_code22", + "sdcard/rp_fw/rp_fw_code30", + "sdcard/rp_fw/rp_fw_code31", +}; +#endif + +static int SRP_Ctrl_Open(void) +{ + if (srp_ctrl_cnt == 0) { + srp_ctrl = open(SRP_CTRL_DEV_NAME, O_RDWR | O_NDELAY); + if (srp_ctrl < 0) { + LOGE("%s: Failed open device file %d", __func__, srp_ctrl); + return -1; + } + srp_ctrl_cnt++; + LOGV("%s: Device is opened[%d]: cnt %d", __func__, srp_ctrl, srp_ctrl_cnt); + } + + return srp_ctrl; +} + +static int SRP_Ctrl_Close(void) +{ + int ret = 0; + + if (srp_ctrl_cnt == 1) { + ret = close(srp_ctrl); + if (ret < 0) { + LOGE("%s: Failed closen device file %d", __func__, srp_ctrl); + return -1; + } + srp_ctrl_cnt--; + LOGV("%s: Device is closed[%d]: cnt %d", __func__, srp_ctrl, srp_ctrl_cnt); + srp_ctrl = -1; + } + + return ret; +} + +#ifdef _USE_FW_FROM_DISK_ +/* This will check & download alternate firmware */ +static int SRP_Check_AltFirmware(void) +{ + unsigned long *temp_buff; + FILE *fp = NULL; + + char alt_fw_name[128]; + unsigned long alt_fw_set; + unsigned long alt_fw_loaded = 0; + int alt_fw_text_ok,alt_fw_data_ok; + + if ((srp_ctrl = SRP_Ctrl_Open()) >= 0) { + ioctl(srp_ctrl, SRP_CTRL_ALTFW_STATE, &alt_fw_loaded); + + if (!alt_fw_loaded) { /* Not loaded yet? */ + LOGE("Try to download alternate RP firmware"); + temp_buff = (unsigned long *)malloc(256*1024); /* temp buffer */ + + for (alt_fw_set = 0; alt_fw_set < 6; alt_fw_set++) { + sprintf(alt_fw_name, "%s_text.bin", srp_alt_fw_name_pre[alt_fw_set]); + if (fp = fopen(alt_fw_name, "rb")) { + LOGE("RP Alt-Firmware Loading: %s", alt_fw_name); + fread(temp_buff, 64*1024, 1, fp); + close(fp); + alt_fw_text_ok = 1; + } else { + alt_fw_text_ok = 0; + } + + sprintf(alt_fw_name, "%s_data.bin", srp_alt_fw_name_pre[alt_fw_set]); + if (fp = fopen(alt_fw_name, "rb")) { + LOGE("RP Alt-Firmware Loading: %s", alt_fw_name); + fread(&temp_buff[64*1024/4], 96*1024, 1, fp); + close(fp); + alt_fw_data_ok = 1; + } else { + alt_fw_data_ok = 0; + } + + if (alt_fw_text_ok && alt_fw_data_ok) { + temp_buff[160*1024/4] = alt_fw_set; + ioctl(srp_ctrl, SRP_CTRL_ALTFW_LOAD, temp_buff); + } + } + free(temp_buff); + } + SRP_Ctrl_Close(); + } + + return 0; +} +#endif + +int SRP_Ctrl_Set_Effect(int effect) +{ + int ret; + unsigned long effect_mode = (unsigned long)effect; + + ret = SRP_Ctrl_Open(); + if (ret < 0) { + LOGE("%s: SRP_Ctrl_Open error", __func__); + return -1; + } + + ioctl(srp_ctrl, SRP_CTRL_SET_EFFECT, effect_mode); + + SRP_Ctrl_Close(); + + return 0; +} + +int SRP_Ctrl_Enable_Effect(int on) +{ + int ret; + unsigned long effect_switch = on ? 1 : 0; + + ret = SRP_Ctrl_Open(); + if (ret < 0) { + LOGE("%s: SRP_Ctrl_Open error", __func__); + return -1; + } + + ioctl(srp_ctrl, SRP_CTRL_EFFECT_ENABLE, effect_switch); + + SRP_Ctrl_Close(); + + return 0; +} + +int SRP_Ctrl_Set_Effect_Def(unsigned long effect_def) +{ + int ret; + + ret = SRP_Ctrl_Open(); + if (ret < 0) { + LOGE("%s: SRP_Ctrl_Open error", __func__); + return -1; + } + + ioctl(srp_ctrl, SRP_CTRL_EFFECT_DEF, effect_def); + + SRP_Ctrl_Close(); + + return 0; +} + +int SRP_Ctrl_Set_Effect_EQ_User(unsigned long eq_user) +{ + int ret; + + ret = SRP_Ctrl_Open(); + if (ret < 0) { + LOGE("%s: SRP_Ctrl_Open error", __func__); + return -1; + } + + ioctl(srp_ctrl, SRP_CTRL_EFFECT_EQ_USR, eq_user); + + SRP_Ctrl_Close(); + + return 0; +} + +int SRP_Ctrl_Set_Pcm_Dump(int on) +{ + int ret; + + ret = SRP_Ctrl_Open(); + if (ret < 0) { + LOGE("%s: SRP_Ctrl_Open error", __func__); + return -1; + } + + ioctl(srp_ctrl, SRP_CTRL_PCM_DUMP_OP, on); + + LOGV("dump_op: %d", on); + + SRP_Ctrl_Close(); + + return 0; +} + +int SRP_Ctrl_Get_Pcm_Dump_State(void) +{ + int ret; + int srp_dump_stat = 0; + + ret = SRP_Ctrl_Open(); + if (ret < 0) { + LOGE("%s: SRP_Ctrl_Open error", __func__); + return -1; + } + + ioctl(srp_ctrl, SRP_CTRL_IS_PCM_DUMP, &srp_dump_stat); + + LOGV("srp_dump_stat: %d", srp_dump_stat); + + SRP_Ctrl_Close(); + + return srp_dump_stat; +} + +int SRP_Ctrl_Set_Gain(float value) +{ + int ret; + unsigned long gain = 0; + + ret = SRP_Ctrl_Open(); + if (ret < 0) { + LOGE("%s: SRP_Ctrl_Open error", __func__); + return -1; + } + + gain = (unsigned long)((1 << 24) * value); + ioctl(srp_ctrl, SRP_CTRL_SET_GAIN, gain); + + SRP_Ctrl_Close(); + + return 0; +} + +int SRP_Ctrl_Get_Running_Stat(void) +{ + int ret; + int srp_running_stat = 0; + + ret = SRP_Ctrl_Open(); + if (ret < 0) { + LOGE("%s: SRP_Ctrl_Open error", __func__); + return -1; + } + + ioctl(srp_ctrl, SRP_CTRL_IS_RUNNING, &srp_running_stat); + + LOGV("srp_running_stat: %d", srp_running_stat); + + SRP_Ctrl_Close(); + + return srp_running_stat; +} + +int SRP_Ctrl_Get_Open_Stat(void) +{ + int ret; + int srp_open_stat = 0; + + ret = SRP_Ctrl_Open(); + if (ret < 0) { + LOGE("%s: SRP_Ctrl_Open error", __func__); + return -1; + } + + ioctl(srp_ctrl, SRP_CTRL_IS_OPENED, &srp_open_stat); + + LOGV("srp_open_stat: %d", srp_open_stat); + + SRP_Ctrl_Close(); + + return srp_open_stat; +} + +short *SRP_Ctrl_Get_Pcm(void) +{ + int ret; + int rp_is_running = 0; + int dump_is_on = 0; + int rp_is_opened = 0; + + ret = SRP_Ctrl_Open(); + if (ret < 0) { + LOGE("%s: SRP_Ctrl_Open error", __func__); + return NULL; + } + + ioctl(srp_ctrl, SRP_CTRL_IS_RUNNING, &rp_is_running); + if (rp_is_running) { + ioctl(srp_ctrl, SRP_CTRL_IS_PCM_DUMP, &dump_is_on); + if (dump_is_on == 0) { + ioctl(srp_ctrl, SRP_CTRL_PCM_DUMP_OP, 1); + dump_is_on = 1; + } + + ioctl(srp_ctrl, SRP_CTRL_GET_PCM_1KFRAME, pcm_buf); + return pcm_buf; + } + + /* SRP is not running */ + if (srp_ctrl > 0) { + if (dump_is_on) { + ioctl(srp_ctrl, SRP_CTRL_IS_OPENED, &rp_is_opened); + if (rp_is_opened) + ioctl(srp_ctrl, SRP_CTRL_PCM_DUMP_OP, 0); + } + SRP_Ctrl_Close(); + } + + return NULL; +} diff --git a/exynos/multimedia/codecs/audio/exynos5/Android.mk b/exynos/multimedia/codecs/audio/exynos5/Android.mk new file mode 100644 index 0000000..4b113e7 --- /dev/null +++ b/exynos/multimedia/codecs/audio/exynos5/Android.mk @@ -0,0 +1,9 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_AUDIO_PATH :=$(LOCAL_PATH) + +ifeq ($(BOARD_USE_ALP_AUDIO), true) + include $(LOCAL_AUDIO_PATH)/srp/alp/Android.mk +endif diff --git a/exynos/multimedia/codecs/audio/exynos5/srp/alp/Android.mk b/exynos/multimedia/codecs/audio/exynos5/srp/alp/Android.mk new file mode 100644 index 0000000..7393f68 --- /dev/null +++ b/exynos/multimedia/codecs/audio/exynos5/srp/alp/Android.mk @@ -0,0 +1,26 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_COPY_HEADERS_TO := libsecmm +LOCAL_COPY_HEADERS := \ + include/srp_api.h \ + include/srp_ioctl.h \ + include/srp_error.h + +LOCAL_SRC_FILES := \ + src/srp_api.c + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/include + +LOCAL_MODULE := libsrpapi + +LOCAL_MODULE_TAGS := optional + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := + +LOCAL_SHARED_LIBRARIES := + +include $(BUILD_STATIC_LIBRARY) diff --git a/exynos/multimedia/codecs/audio/exynos5/srp/alp/include/srp_api.h b/exynos/multimedia/codecs/audio/exynos5/srp/alp/include/srp_api.h new file mode 100644 index 0000000..ad65b90 --- /dev/null +++ b/exynos/multimedia/codecs/audio/exynos5/srp/alp/include/srp_api.h @@ -0,0 +1,52 @@ +#ifndef __SRP_API_H__ +#define __SRP_API_H__ + +#include "srp_ioctl.h" +#include "srp_error.h" + +#define SRP_DEV_NAME "dev/srp" + +#define SRP_INIT_BLOCK_MODE 0 +#define SRP_INIT_NONBLOCK_MODE 1 + +#define SRP_PENDING_STATE_RUNNING 0 +#define SRP_PENDING_STATE_PENDING 1 + +struct srp_buf_info { + void *mmapped_addr; + void *addr; + unsigned int mmapped_size; + unsigned int size; + int num; +}; + +struct srp_dec_info { + unsigned int sample_rate; + unsigned int channels; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +int SRP_Create(int block_mode); +int SRP_Init(); +int SRP_Decode(void *buff, int size_byte); +int SRP_Send_EOS(void); +int SRP_SetParams(int id, unsigned long val); +int SRP_GetParams(int id, unsigned long *pval); +int SRP_Deinit(void); +int SRP_Terminate(void); +int SRP_IsOpen(void); + +int SRP_Get_Ibuf_Info(void **addr, unsigned int *size, unsigned int *num); +int SRP_Get_Obuf_Info(void **addr, unsigned int *size, unsigned int *num); +int SRP_Get_Dec_Info(struct srp_dec_info *dec_info); +int SRP_Get_PCM(void **addr, unsigned int *size); +int SRP_Flush(void); + +#ifdef __cplusplus +} +#endif + +#endif /*__SRP_API_H__ */ diff --git a/exynos/multimedia/codecs/audio/exynos5/srp/alp/include/srp_error.h b/exynos/multimedia/codecs/audio/exynos5/srp/alp/include/srp_error.h new file mode 100644 index 0000000..7f79452 --- /dev/null +++ b/exynos/multimedia/codecs/audio/exynos5/srp/alp/include/srp_error.h @@ -0,0 +1,22 @@ +#ifndef _SRP_ERROR_H_ +#define _SRP_ERROR_H_ + +typedef enum { + SRP_RETURN_OK = 0, + + SRP_ERROR_OPEN_FAIL = -1000, + SRP_ERROR_ALREADY_OPEN = -1001, + SRP_ERROR_NOT_READY = -1002, + + SRP_ERROR_IBUF_OVERFLOW = -2000, + SRP_ERROR_IBUF_INFO = -2001, + + SRP_ERROR_OBUF_READ = -3000, + SRP_ERROR_OBUF_INFO = -3001, + SRP_ERROR_OBUF_MMAP = -3002, + + SRP_ERROR_INVALID_SETTING = -4000, + SRP_ERROR_GETINFO_FAIL = -4001 +} SRP_ERRORTYPE; + +#endif /* _SRP_ERROR_H_ */ diff --git a/exynos/multimedia/codecs/audio/exynos5/srp/alp/include/srp_ioctl.h b/exynos/multimedia/codecs/audio/exynos5/srp/alp/include/srp_ioctl.h new file mode 100644 index 0000000..21d55df --- /dev/null +++ b/exynos/multimedia/codecs/audio/exynos5/srp/alp/include/srp_ioctl.h @@ -0,0 +1,23 @@ +#ifndef __SRP_IOCTL_H__ +#define __SRP_IOCTL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SRP_INIT (0x10000) +#define SRP_DEINIT (0x10001) +#define SRP_GET_MMAP_SIZE (0x10002) +#define SRP_FLUSH (0x20002) +#define SRP_SEND_EOS (0x20005) +#define SRP_GET_IBUF_INFO (0x20007) +#define SRP_GET_OBUF_INFO (0x20008) +#define SRP_STOP_EOS_STATE (0x30007) +#define SRP_GET_DEC_INFO (0x30008) + +#ifdef __cplusplus +} +#endif + +#endif /* __SRP_IOCTL_H__ */ + diff --git a/exynos/multimedia/codecs/audio/exynos5/srp/alp/src/srp_api.c b/exynos/multimedia/codecs/audio/exynos5/srp/alp/src/srp_api.c new file mode 100644 index 0000000..56125fb --- /dev/null +++ b/exynos/multimedia/codecs/audio/exynos5/srp/alp/src/srp_api.c @@ -0,0 +1,265 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/time.h> +#include <fcntl.h> +#include <ctype.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <stdio.h> + +#include "srp_api.h" + +#define LOG_NDEBUG 1 +#define LOG_TAG "libsrpapi" +#include <utils/Log.h> + +static struct srp_buf_info ibuf_info; +static struct srp_buf_info obuf_info; +static struct srp_buf_info pcm_info; + +static int srp_dev = -1; +static int srp_block_mode = SRP_INIT_BLOCK_MODE; + +int SRP_Create(int block_mode) +{ + if (srp_dev == -1) { + srp_block_mode = block_mode; + srp_dev = open(SRP_DEV_NAME, O_RDWR | + ((block_mode == SRP_INIT_NONBLOCK_MODE) ? O_NDELAY : 0)); + if (srp_dev > 0) + return srp_dev; + else + return SRP_ERROR_OPEN_FAIL; + } + + LOGE("%s: Device is already opened", __func__); + return SRP_ERROR_ALREADY_OPEN; +} + +int SRP_Init() +{ + int ret = SRP_RETURN_OK; + unsigned int mmapped_size = 0; + + if (srp_dev != -1) { + ret = ioctl(srp_dev, SRP_INIT); + if (ret < 0) + return ret; + + /* mmap for OBUF */ + ret = ioctl(srp_dev, SRP_GET_MMAP_SIZE, &mmapped_size); + if (ret < 0) { + LOGE("%s: SRP_GET_MMAP_SIZE is failed", __func__); + return SRP_ERROR_OBUF_MMAP; + } + obuf_info.mmapped_addr = mmap(0, mmapped_size, + PROT_READ | PROT_WRITE, MAP_SHARED, srp_dev, 0); + if (!obuf_info.mmapped_addr) { + LOGE("%s: mmap is failed", __func__); + return SRP_ERROR_OBUF_MMAP; + } + obuf_info.mmapped_size = mmapped_size; + + ret = SRP_RETURN_OK; + } else { + LOGE("%s: Device is not ready", __func__); + ret = SRP_ERROR_NOT_READY; /* device is not created */ + } + + return ret; +} + +int SRP_Decode(void *buff, int size_byte) +{ + int ret = SRP_RETURN_OK; + + if (srp_dev != -1) { + if (size_byte > 0) { + LOGV("%s: Send data to RP (%d bytes)", __func__, size_byte); + + ret = write(srp_dev, buff, size_byte); /* Write Buffer to RP Driver */ + if (ret < 0) { + if (ret != SRP_ERROR_IBUF_OVERFLOW) + LOGE("SRP_Decode returned error code: %d", ret); + } + return ret; /* Write Success */ + } else { + return ret; + } + } + + LOGE("%s: Device is not ready", __func__); + return SRP_ERROR_NOT_READY; +} + +int SRP_Send_EOS(void) +{ + if (srp_dev != -1) + return ioctl(srp_dev, SRP_SEND_EOS); + + return SRP_ERROR_NOT_READY; +} + +int SRP_SetParams(int id, unsigned long val) +{ + if (srp_dev != -1) + return 0; /* not yet */ + + return SRP_ERROR_NOT_READY; +} + +int SRP_GetParams(int id, unsigned long *pval) +{ + if (srp_dev != -1) + return ioctl(srp_dev, id, pval); + + return SRP_ERROR_NOT_READY; +} + +int SRP_Flush(void) +{ + if (srp_dev != -1) + return ioctl(srp_dev, SRP_FLUSH); + + return SRP_ERROR_NOT_READY; +} + +int SRP_Get_PCM(void **addr, unsigned int *size) +{ + int ret = SRP_RETURN_OK; + + if (srp_dev != -1) { + ret = read(srp_dev, &pcm_info, 0); + if (ret == -1) { + *size = 0; + LOGE("%s: PCM read fail", __func__); + return SRP_ERROR_OBUF_READ; + } + + *addr = pcm_info.addr; + *size = pcm_info.size; + } else { + return SRP_ERROR_NOT_READY; + } + + return ret; /* Read Success */ +} + +int SRP_Get_Dec_Info(struct srp_dec_info *dec_info) +{ + int ret; + + if (srp_dev != -1) { + ret = ioctl(srp_dev, SRP_GET_DEC_INFO, dec_info); + if (ret < 0) { + LOGE("%s: Failed to get dec info", __func__); + return SRP_ERROR_GETINFO_FAIL; + } + + LOGV("numChannels(%d), samplingRate(%d)", dec_info->channels, dec_info->sample_rate); + + ret = SRP_RETURN_OK; + } else { + ret = SRP_ERROR_NOT_READY; + } + + return ret; +} + +int SRP_Get_Ibuf_Info(void **addr, unsigned int *size, unsigned int *num) +{ + int ret = SRP_RETURN_OK; + + if (srp_dev != -1) { + ret = ioctl(srp_dev, SRP_GET_IBUF_INFO, &ibuf_info); + if (ret == -1) { + LOGE("%s: Failed to get Ibuf info", __func__); + return SRP_ERROR_IBUF_INFO; + } + + *addr = ibuf_info.addr; + *size = ibuf_info.size; + *num = ibuf_info.num; + + if (*num == 0) { + LOGE("%s: IBUF num is 0", __func__); + return SRP_ERROR_INVALID_SETTING; + } + + ret = SRP_RETURN_OK; + } else { + ret = SRP_ERROR_NOT_READY; + } + + return ret; +} + +int SRP_Get_Obuf_Info(void **addr, unsigned int *size, unsigned int *num) +{ + int ret = SRP_RETURN_OK; + + if (srp_dev != -1) { + if (obuf_info.addr == NULL) { + ret = ioctl(srp_dev, SRP_GET_OBUF_INFO, &obuf_info); + if (ret < 0) { + LOGE("%s: SRP_GET_OBUF_INFO is failed", __func__); + return SRP_ERROR_OBUF_INFO; + } + } + + *addr = obuf_info.addr; + *size = obuf_info.size; + *num = obuf_info.num; + + if (*num == 0) { + LOGE("%s: OBUF num is 0", __func__); + return SRP_ERROR_INVALID_SETTING; + } + + ret = SRP_RETURN_OK; + } else { + ret = SRP_ERROR_NOT_READY; + } + + return ret; +} + +int SRP_Deinit(void) +{ + if (srp_dev != -1) { + munmap(obuf_info.mmapped_addr, obuf_info.mmapped_size); + return ioctl(srp_dev, SRP_DEINIT); + } + + return SRP_ERROR_NOT_READY; +} + +int SRP_Terminate(void) +{ + int ret; + + if (srp_dev != -1) { + ret = close(srp_dev); + + if (ret == 0) { + srp_dev = -1; /* device closed */ + return SRP_RETURN_OK; + } + } + + return SRP_ERROR_NOT_READY; +} + +int SRP_IsOpen(void) +{ + if (srp_dev == -1) { + LOGV("%s: Device is not opened", __func__); + return 0; + } + + LOGV("%s: Device is opened", __func__); + return 1; +} diff --git a/exynos/multimedia/codecs/video/Android.mk b/exynos/multimedia/codecs/video/Android.mk new file mode 100644 index 0000000..3bc3577 --- /dev/null +++ b/exynos/multimedia/codecs/video/Android.mk @@ -0,0 +1,11 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +ifeq ($(filter-out exynos4,$(TARGET_BOARD_PLATFORM)),) +include $(LOCAL_PATH)/exynos4/Android.mk +endif + +ifeq ($(filter-out exynos5,$(TARGET_BOARD_PLATFORM)),) +include $(LOCAL_PATH)/exynos5/Android.mk +endif diff --git a/exynos/multimedia/codecs/video/exynos4/Android.mk b/exynos/multimedia/codecs/video/exynos4/Android.mk new file mode 100644 index 0000000..1a8c419 --- /dev/null +++ b/exynos/multimedia/codecs/video/exynos4/Android.mk @@ -0,0 +1,11 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_VIDEO_PATH :=$(LOCAL_PATH) + +ifeq ($(BOARD_USE_V4L2), true) +include $(LOCAL_VIDEO_PATH)/mfc_v4l2/Android.mk +else +include $(LOCAL_VIDEO_PATH)/mfc/Android.mk +endif diff --git a/exynos/multimedia/codecs/video/exynos4/mfc/Android.mk b/exynos/multimedia/codecs/video/exynos4/mfc/Android.mk new file mode 100644 index 0000000..b23f603 --- /dev/null +++ b/exynos/multimedia/codecs/video/exynos4/mfc/Android.mk @@ -0,0 +1,38 @@ +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/ + +LOCAL_MODULE := libsecmfcapi + +LOCAL_PRELINK_MODULE := false + +ifeq ($(BOARD_USES_MFC_FPS),true) +LOCAL_CFLAGS := -DCONFIG_MFC_FPS +#LOCAL_CFLAGS += -DCONFIG_MFC_PERF_LOG +endif + +ifeq ($(BOARD_USE_S3D_SUPPORT), true) +LOCAL_CFLAGS += -DS3D_SUPPORT +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/dec/src/SsbSipMfcDecAPI.c b/exynos/multimedia/codecs/video/exynos4/mfc/dec/src/SsbSipMfcDecAPI.c new file mode 100644 index 0000000..92a8ca6 --- /dev/null +++ b/exynos/multimedia/codecs/video/exynos4/mfc/dec/src/SsbSipMfcDecAPI.c @@ -0,0 +1,1100 @@ +/* + * 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 "mfc_interface.h" +#include "SsbSipMfcApi.h" + +#include <utils/Log.h> +/*#define LOG_NDEBUG 0*/ +#undef LOG_TAG +#define LOG_TAG "MFC_DEC_APP" + +#ifdef CONFIG_MFC_FPS +#include <sys/time.h> +#endif + +#define _MFCLIB_MAGIC_NUMBER 0x92241000 + +#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 mDec1, mDec2, mAvg; +#endif + +static char *mfc_dev_name = SAMSUNG_MFC_DEV_NAME; + +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("isPBPacked] VOP START Found !!.....return"); + LOGW("isPBPacked] Non Packed PB"); + return 0; + } + getAByte(strmBuffer, &startCode); + LOGV(">> StartCode = 0x%08x <<\n", startCode); + strmBuffer++; + leng_idx++; + } + LOGI("isPBPacked] User Data Found !!"); + + do { + if (*strmBuffer == 'p') { + /*LOGI(">> peter strmBuffer = 0x%08x <<\n", *strmBuffer);*/ + LOGW("isPBPacked] Packed PB\n"); + return 1; + } + getAByte(strmBuffer, &startCode); + strmBuffer++; leng_idx++; + } while ((leng_idx <= Frameleng) && ((startCode >> 8) != MP4_START_CODE)); + + if (leng_idx > Frameleng) + break; + } + + LOGW("isPBPacked] Non Packed PB"); + + return 0; +} + +void SsbSipMfcDecSetMFCName(char *devicename) +{ + mfc_dev_name = devicename; +} + +void *SsbSipMfcDecOpen(void) +{ + int hMFCOpen; + unsigned int mapped_addr; + _MFCLIB *pCTX = NULL; + int mapped_size; + struct mfc_common_args CommonArg; + + LOGI("[%s] MFC Library Ver %d.%02d\n",__func__, MFC_LIB_VER_MAJOR, MFC_LIB_VER_MINOR); +#ifdef CONFIG_MFC_FPS + framecount = 0; + over30ms = 0; + mAvg.tv_sec = 0; + mAvg.tv_usec = 0; +#endif + pCTX = (_MFCLIB *)malloc(sizeof(_MFCLIB)); + if (pCTX == NULL) { + LOGE("SsbSipMfcDecOpen] malloc failed.\n"); + return NULL; + } + memset(pCTX, 0, sizeof(_MFCLIB)); + + if (access(mfc_dev_name, F_OK) != 0) { + LOGE("SsbSipMfcDecOpen] MFC device node not exists"); + free(pCTX); + return NULL; + } + + hMFCOpen = open(mfc_dev_name, O_RDWR | O_NDELAY); + if (hMFCOpen < 0) { + LOGE("SsbSipMfcDecOpen] MFC Open failure"); + free(pCTX); + return NULL; + } + + mapped_size = ioctl(hMFCOpen, IOCTL_MFC_GET_MMAP_SIZE, &CommonArg); + if ((mapped_size < 0) || (CommonArg.ret_code != MFC_OK)) { + LOGE("SsbSipMfcDecOpen] 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("SsbSipMfcDecOpen] 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 *SsbSipMfcDecOpenExt(void *value) +{ + int hMFCOpen; + unsigned int mapped_addr; + _MFCLIB *pCTX = NULL; + int mapped_size; + int err; + struct mfc_common_args CommonArg; + + LOGI("[%s] MFC Library Ver %d.%02d\n",__func__, MFC_LIB_VER_MAJOR, MFC_LIB_VER_MINOR); + + pCTX = (_MFCLIB *)malloc(sizeof(_MFCLIB)); + if (pCTX == NULL) { + LOGE("SsbSipMfcDecOpenExt] malloc failed.\n"); + return NULL; + } + memset(pCTX, 0, sizeof(_MFCLIB)); + + if (access(mfc_dev_name, F_OK) != 0) { + LOGE("SsbSipMfcDecOpen] MFC device node not exists"); + free(pCTX); + return NULL; + } + + hMFCOpen = open(mfc_dev_name, O_RDWR | O_NDELAY); + if (hMFCOpen < 0) { + LOGE("SsbSipMfcDecOpenExt] MFC Open failure"); + free(pCTX); + return NULL; + } + + 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("SsbSipMfcDecOpenExt] 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("SsbSipMfcDecOpenExt] 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("SsbSipMfcDecOpenExt] 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 SsbSipMfcDecInit (void *openHandle, SSBSIP_MFC_CODEC_TYPE codec_type, int Frameleng) +{ + int r; + int packedPB = 0; + struct mfc_common_args DecArg; + _MFCLIB *pCTX; + + if (openHandle == NULL) { + LOGE("SsbSipMfcDecInit] openHandle is NULL"); + return MFC_RET_INVALID_PARAM; + } + + pCTX = (_MFCLIB *)openHandle; + memset(&DecArg, 0x00, sizeof(DecArg)); + + if ((codec_type != MPEG4_DEC) && + (codec_type != H264_DEC) && + (codec_type != H263_DEC) && + (codec_type != MPEG1_DEC) && + (codec_type != MPEG2_DEC) && + (codec_type != FIMV1_DEC) && + (codec_type != FIMV2_DEC) && + (codec_type != FIMV3_DEC) && + (codec_type != FIMV4_DEC) && + (codec_type != XVID_DEC) && + (codec_type != VC1RCV_DEC) && + (codec_type != VC1_DEC)) { + LOGE("SsbSipMfcDecInit] Undefined codec type"); + return MFC_RET_INVALID_PARAM; + } + 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); + + /* init args */ + DecArg.args.dec_init.in_codec_type = pCTX->codecType; + DecArg.args.dec_init.in_strm_size = Frameleng; + DecArg.args.dec_init.in_strm_buf = pCTX->phyStrmBuf; + + DecArg.args.dec_init.in_numextradpb = pCTX->dec_numextradpb; + DecArg.args.dec_init.in_slice= pCTX->dec_slice; + DecArg.args.dec_init.in_crc = pCTX->dec_crc; + DecArg.args.dec_init.in_pixelcache = pCTX->dec_pixelcache; + + DecArg.args.dec_init.in_packed_PB = packedPB; + + /* mem alloc args */ + DecArg.args.dec_init.in_mapped_addr = pCTX->mapped_addr; + + /* get pyhs addr args */ + /* no needs */ + + /* sequence start args */ + /* no needs */ + + r = ioctl(pCTX->hMFC, IOCTL_MFC_DEC_INIT, &DecArg); + if (DecArg.ret_code != MFC_OK) { + LOGE("SsbSipMfcDecInit] IOCTL_MFC_DEC_INIT failed"); + return MFC_RET_DEC_INIT_FAIL; + } + + pCTX->decOutInfo.img_width = DecArg.args.dec_init.out_frm_width; + pCTX->decOutInfo.img_height = DecArg.args.dec_init.out_frm_height; + pCTX->decOutInfo.buf_width = DecArg.args.dec_init.out_buf_width; + pCTX->decOutInfo.buf_height = DecArg.args.dec_init.out_buf_height; + + pCTX->decOutInfo.crop_top_offset = DecArg.args.dec_init.out_crop_top_offset; + pCTX->decOutInfo.crop_bottom_offset = DecArg.args.dec_init.out_crop_bottom_offset; + pCTX->decOutInfo.crop_left_offset = DecArg.args.dec_init.out_crop_left_offset; + pCTX->decOutInfo.crop_right_offset = DecArg.args.dec_init.out_crop_right_offset; + + /* + pCTX->virFrmBuf.luma = DecArg.args.dec_init.out_u_addr.luma; + pCTX->virFrmBuf.chroma = DecArg.args.dec_init.out_u_addr.chroma; + + pCTX->phyFrmBuf.luma = DecArg.args.dec_init.out_p_addr.luma; + pCTX->phyFrmBuf.chroma = DecArg.args.dec_init.out_p_addr.chroma; + pCTX->sizeFrmBuf.luma = DecArg.args.dec_init.out_frame_buf_size.luma; + pCTX->sizeFrmBuf.chroma = DecArg.args.dec_init.out_frame_buf_size.chroma; + */ + + pCTX->inter_buff_status |= MFC_USE_YUV_BUFF; + + return MFC_RET_OK; +} + +SSBSIP_MFC_ERROR_CODE SsbSipMfcDecExe(void *openHandle, int lengthBufFill) +{ + int ret; + int Yoffset; + int Coffset; + _MFCLIB *pCTX; + struct mfc_common_args DecArg; + +#ifdef CONFIG_MFC_FPS + long int diffTime, avgTime; +#endif + if (openHandle == NULL) { + LOGE("SsbSipMfcDecExe] openHandle is NULL\n"); + return MFC_RET_INVALID_PARAM; + } + + if ((lengthBufFill < 0) || (lengthBufFill > MAX_DECODER_INPUT_BUFFER_SIZE)) { + LOGE("SsbSipMfcDecExe] lengthBufFill is invalid. (lengthBufFill=%d)", lengthBufFill); + return MFC_RET_INVALID_PARAM; + } + + pCTX = (_MFCLIB *) openHandle; + memset(&DecArg, 0x00, sizeof(DecArg)); + + DecArg.args.dec_exe.in_codec_type = pCTX->codecType; + DecArg.args.dec_exe.in_strm_buf = pCTX->phyStrmBuf; + DecArg.args.dec_exe.in_strm_size = lengthBufFill; + DecArg.args.dec_exe.in_frm_buf.luma = pCTX->phyFrmBuf.luma; + DecArg.args.dec_exe.in_frm_buf.chroma = pCTX->phyFrmBuf.chroma; + DecArg.args.dec_exe.in_frm_size.luma = pCTX->sizeFrmBuf.luma; + DecArg.args.dec_exe.in_frm_size.chroma = pCTX->sizeFrmBuf.chroma; + DecArg.args.dec_exe.in_frametag = pCTX->inframetag; + DecArg.args.dec_exe.in_immediately_disp = pCTX->immediatelydisp; + +#ifdef CONFIG_MFC_FPS + gettimeofday(&mDec1, NULL); + +#ifdef CONFIG_MFC_PERF_LOG + if (framecount != 0) { + if (mDec2.tv_sec == mDec1.tv_sec) + LOGI("SsbSipMfcDecExe] Interval between IOCTL_MFC_DEC_EXE's (end to start) = %8d", (mDec1.tv_usec - mDec2.tv_usec)); + else + LOGI("SsbSipMfcDecExe] Interval between IOCTL_MFC_DEC_EXE's (end to start) = %8d", (1000000 + (mDec1.tv_usec - mDec2.tv_usec))); + } +#endif +#endif + + ret = ioctl(pCTX->hMFC, IOCTL_MFC_DEC_EXE, &DecArg); + + if (DecArg.ret_code != MFC_OK) { + LOGE("SsbSipMfcDecExe] IOCTL_MFC_DEC_EXE failed(ret : %d)", DecArg.ret_code); + return MFC_RET_DEC_EXE_ERR; + } + +#ifdef CONFIG_MFC_FPS + gettimeofday(&mDec2, NULL); + framecount++; + + if (mDec1.tv_sec == mDec2.tv_sec) { + if (mDec2.tv_usec - mDec1.tv_usec > 30000) + over30ms++; +#ifdef CONFIG_MFC_PERF_LOG + LOGI("SsbSipMfcDecExe] Time consumed for IOCTL_MFC_DEC_EXE = %8d", ((mDec2.tv_usec - mDec1.tv_usec))); +#endif + } else { + if (1000000 + mDec2.tv_usec - mDec1.tv_usec > 30000) + over30ms++; +#ifdef CONFIG_MFC_PERF_LOG + LOGI("SsbSipMfcDecExe] Time consumed for IOCTL_MFC_DEC_EXE = %8d", (1000000 + (mDec2.tv_usec - mDec1.tv_usec))); +#endif + } + + diffTime = ((mDec2.tv_sec * 1000000) + mDec2.tv_usec) - ((mDec1.tv_sec * 1000000) + mDec1.tv_usec); + avgTime = (mAvg.tv_sec * 1000000) + mAvg.tv_usec; + avgTime = ((framecount - 1) * avgTime + diffTime) / framecount; + + mAvg.tv_sec = avgTime / 1000000; + mAvg.tv_usec = avgTime % 1000000; +#endif + + /* FIXME: dynamic resolution change */ + if (DecArg.args.dec_exe.out_display_status == 4) { + LOGI("SsbSipMfcDecExe] Resolution is chagned"); + /* + pCTX->virFrmBuf.chroma = DecArg.args.dec_exe.out_u_addr.chroma; + pCTX->virFrmBuf.luma = DecArg.args.dec_exe.out_u_addr.luma; + pCTX->phyFrmBuf.chroma = DecArg.args.dec_exe.out_p_addr.chroma; + pCTX->phyFrmBuf.luma = DecArg.args.dec_exe.out_p_addr.luma; + pCTX->sizeFrmBuf.chroma = DecArg.args.dec_exe.out_frame_buf_size.chroma; + pCTX->sizeFrmBuf.luma = DecArg.args.dec_exe.out_frame_buf_size.luma; + */ + pCTX->decOutInfo.img_width = DecArg.args.dec_exe.out_img_width; + pCTX->decOutInfo.img_height = DecArg.args.dec_exe.out_img_height; + pCTX->decOutInfo.buf_width = DecArg.args.dec_exe.out_buf_width; + pCTX->decOutInfo.buf_height = DecArg.args.dec_exe.out_buf_height; + } + + Yoffset = DecArg.args.dec_exe.out_display_Y_addr - DecArg.args.dec_exe.in_frm_buf.luma; + Coffset = DecArg.args.dec_exe.out_display_C_addr - DecArg.args.dec_exe.in_frm_buf.chroma; + + pCTX->decOutInfo.YPhyAddr = (void*)(DecArg.args.dec_exe.out_display_Y_addr); + pCTX->decOutInfo.CPhyAddr = (void*)(DecArg.args.dec_exe.out_display_C_addr); + + pCTX->decOutInfo.YVirAddr = (void*)(pCTX->virFrmBuf.luma + Yoffset); + pCTX->decOutInfo.CVirAddr = (void*)(pCTX->virFrmBuf.chroma + Coffset); + + /* for new driver */ + pCTX->decOutInfo.YVirAddr = (void*)(pCTX->mapped_addr + DecArg.args.dec_exe.out_y_offset); + pCTX->decOutInfo.CVirAddr = (void*)(pCTX->mapped_addr + DecArg.args.dec_exe.out_c_offset); + + pCTX->displayStatus = DecArg.args.dec_exe.out_display_status; + + pCTX->decOutInfo.disp_pic_frame_type = DecArg.args.dec_exe.out_disp_pic_frame_type; + + /* clear immediately display flag */ + pCTX->immediatelydisp = 0; + pCTX->outframetagtop = DecArg.args.dec_exe.out_frametag_top; + pCTX->outframetagbottom = DecArg.args.dec_exe.out_frametag_bottom; + pCTX->decOutInfo.timestamp_top = DecArg.args.dec_exe.out_pic_time_top; + pCTX->decOutInfo.timestamp_bottom = DecArg.args.dec_exe.out_pic_time_bottom; + pCTX->decOutInfo.consumedByte = DecArg.args.dec_exe.out_consumed_byte; + + pCTX->decOutInfo.crop_right_offset = DecArg.args.dec_exe.out_crop_right_offset; + pCTX->decOutInfo.crop_left_offset = DecArg.args.dec_exe.out_crop_left_offset; + pCTX->decOutInfo.crop_bottom_offset = DecArg.args.dec_exe.out_crop_bottom_offset; + pCTX->decOutInfo.crop_top_offset = DecArg.args.dec_exe.out_crop_top_offset; + + return MFC_RET_OK; +} + +SSBSIP_MFC_ERROR_CODE SsbSipMfcDecClose(void *openHandle) +{ + int ret; + _MFCLIB *pCTX; + struct mfc_common_args free_arg; + +#ifdef CONFIG_MFC_FPS + LOGI(">>> Statistics in MFC API:"); + LOGI(">>> Total number of IOCTL_MFC_DEC_EXE = %d", framecount); + LOGI(">>> Number of IOCTL_MFC_DEC_EXE taking more than 30ms = %d", over30ms); + LOGI(">>> Avg IOCTL_MFC_DEC_EXE time = %dsec %.2fmsec", (int)mAvg.tv_sec, (float)(mAvg.tv_usec / 1000.0)); +#endif + + if (openHandle == NULL) { + LOGE("SsbSipMfcDecClose] openHandle is NULL"); + return MFC_RET_INVALID_PARAM; + } + + pCTX = (_MFCLIB *) openHandle; + + /* FIXME: free buffer? */ +#if 0 + if (pCTX->inter_buff_status & MFC_USE_YUV_BUFF) { + free_arg.args.mem_free.key = pCTX->virFrmBuf.luma; + ret = ioctl(pCTX->hMFC, IOCTL_MFC_FREE_BUF, &free_arg); + free_arg.args.mem_free.key = pCTX->virFrmBuf.chroma; + ret = ioctl(pCTX->hMFC, IOCTL_MFC_FREE_BUF, &free_arg); + } +#endif + + if (pCTX->inter_buff_status & MFC_USE_STRM_BUFF) { + free_arg.args.mem_free.key = pCTX->virStrmBuf; + ret = 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; +} + + +void *SsbSipMfcDecGetInBuf(void *openHandle, void **phyInBuf, int inputBufferSize) +{ + int ret_code; + _MFCLIB *pCTX; + struct mfc_common_args user_addr_arg, phys_addr_arg; + + if (inputBufferSize < 0) { + LOGE("SsbSipMfcDecGetInBuf] inputBufferSize = %d is invalid", inputBufferSize); + return NULL; + } + + if (openHandle == NULL) { + LOGE("SsbSipMfcDecGetInBuf] openHandle is NULL\n"); + return NULL; + } + + pCTX = (_MFCLIB *) openHandle; + + /*user_addr_arg.args.mem_alloc.codec_type = pCTX->codec_type; */ + user_addr_arg.args.mem_alloc.type = DECODER; + user_addr_arg.args.mem_alloc.buff_size = inputBufferSize; + 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("SsbSipMfcDecGetInBuf] IOCTL_MFC_GET_IN_BUF failed"); + return NULL; + } + + phys_addr_arg.args.real_addr.key = user_addr_arg.args.mem_alloc.offset; + ret_code = ioctl(pCTX->hMFC, IOCTL_MFC_GET_REAL_ADDR, &phys_addr_arg); + if (ret_code < 0) { + LOGE("SsbSipMfcDecGetInBuf] IOCTL_MFC_GET_PHYS_ADDR failed"); + return NULL; + } + + /* + pCTX->virStrmBuf = user_addr_arg.args.mem_alloc.offset; + */ + pCTX->virStrmBuf = pCTX->mapped_addr + user_addr_arg.args.mem_alloc.offset; + pCTX->phyStrmBuf = phys_addr_arg.args.real_addr.addr; + + pCTX->sizeStrmBuf = inputBufferSize; + pCTX->inter_buff_status |= MFC_USE_STRM_BUFF; + + *phyInBuf = (void *)pCTX->phyStrmBuf; + + return (void *)pCTX->virStrmBuf; +} + +SSBSIP_MFC_ERROR_CODE SsbSipMfcDecSetInBuf(void *openHandle, void *phyInBuf, void *virInBuf, int size) +{ + _MFCLIB *pCTX; + + if (openHandle == NULL) { + LOGE("SsbSipMfcDecSetInBuf] openHandle is NULL"); + return MFC_RET_INVALID_PARAM; + } + + pCTX = (_MFCLIB *) openHandle; + + pCTX->phyStrmBuf = (int)phyInBuf; + pCTX->virStrmBuf = (int)virInBuf; + pCTX->sizeStrmBuf = size; + return MFC_RET_OK; +} + +SSBSIP_MFC_DEC_OUTBUF_STATUS SsbSipMfcDecGetOutBuf(void *openHandle, SSBSIP_MFC_DEC_OUTPUT_INFO *output_info) +{ + _MFCLIB *pCTX; + + if (openHandle == NULL) { + LOGE("SsbSipMfcDecGetOutBuf] openHandle is NULL"); + 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->timestamp_top = pCTX->decOutInfo.timestamp_top; + output_info->timestamp_bottom = pCTX->decOutInfo.timestamp_bottom; + output_info->consumedByte = pCTX->decOutInfo.consumedByte; + + 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; + + if (pCTX->displayStatus == 3) + return MFC_GETOUTBUF_DISPLAY_END; + else if (pCTX->displayStatus == 1) + return MFC_GETOUTBUF_DISPLAY_DECODING; + else if (pCTX->displayStatus == 2) + return MFC_GETOUTBUF_DISPLAY_ONLY; + else if (pCTX->displayStatus == 0) + return MFC_GETOUTBUF_DECODING_ONLY; + else if (pCTX->displayStatus == 4) + return MFC_GETOUTBUF_CHANGE_RESOL; + else + return MFC_GETOUTBUF_DISPLAY_END; +} + +SSBSIP_MFC_ERROR_CODE SsbSipMfcDecSetConfig(void *openHandle, SSBSIP_MFC_DEC_CONF conf_type, void *value) +{ + int ret_code; + _MFCLIB *pCTX; + struct mfc_common_args DecArg; + struct mfc_dec_fimv1_info *fimv1_res; + + if (openHandle == NULL) { + LOGE("SsbSipMfcDecSetConfig] openHandle is NULL"); + return MFC_RET_INVALID_PARAM; + } + + if (value == NULL) { + LOGE("SsbSipMfcDecSetConfig] value is NULL"); + return MFC_RET_INVALID_PARAM; + } + + pCTX = (_MFCLIB *)openHandle; + memset(&DecArg, 0x00, sizeof(DecArg)); +#ifdef S3D_SUPPORT + DecArg.args.config.type = conf_type; +#else + DecArg.args.set_config.in_config_param = conf_type; +#endif + switch (conf_type) { + case MFC_DEC_SETCONF_EXTRA_BUFFER_NUM: + pCTX->dec_numextradpb = *((unsigned int *) value); + return MFC_RET_OK; + + case MFC_DEC_SETCONF_SLICE_ENABLE: + pCTX->dec_slice = *((unsigned int *) value); + return MFC_RET_OK; + + case MFC_DEC_SETCONF_CRC_ENABLE: + pCTX->dec_crc = *((unsigned int *) value); + return MFC_RET_OK; + + case MFC_DEC_SETCONF_PIXEL_CACHE: + pCTX->dec_pixelcache = *((unsigned int *) value); + return MFC_RET_OK; + + case MFC_DEC_SETCONF_FRAME_TAG: /* be set before calling SsbSipMfcDecExe */ + pCTX->inframetag = *((unsigned int *) value); + return MFC_RET_OK; + + case MFC_DEC_SETCONF_IMMEDIATELY_DISPLAY: /* be set before calling SsbSipMfcDecExe */ + pCTX->immediatelydisp = *((unsigned int *) value); + return MFC_RET_OK; + + case MFC_DEC_SETCONF_FIMV1_WIDTH_HEIGHT: + fimv1_res = (struct mfc_dec_fimv1_info *)value; + LOGI("fimv1->width = %d\n", fimv1_res->width); + LOGI("fimv1->height = %d\n", fimv1_res->height); +#ifdef S3D_SUPPORT + DecArg.args.config.args.basic.values[0] = (int)(fimv1_res->width); + DecArg.args.config.args.basic.values[1] = (int)(fimv1_res->height); +#else + DecArg.args.set_config.in_config_value[0] = (int)(fimv1_res->width); + DecArg.args.set_config.in_config_value[1] = (int)(fimv1_res->height); +#endif + break; + case MFC_DEC_SETCONF_IS_LAST_FRAME: + case MFC_DEC_SETCONF_DPB_FLUSH: +#ifdef S3D_SUPPORT + case MFC_DEC_SETCONF_SEI_PARSE: + default: + DecArg.args.config.args.basic.values[0] = *((int *) value); + DecArg.args.config.args.basic.values[1] = 0; +#else + default: + DecArg.args.set_config.in_config_value[0] = *((unsigned int *) value); + DecArg.args.set_config.in_config_value[1] = 0; +#endif + break; + } + + ret_code = ioctl(pCTX->hMFC, IOCTL_MFC_SET_CONFIG, &DecArg); + if (DecArg.ret_code != MFC_OK) { + LOGE("SsbSipMfcDecSetConfig] IOCTL_MFC_SET_CONFIG failed(ret : %d, conf_type: 0x%08x)", DecArg.ret_code, 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) +{ + int ret_code; + _MFCLIB *pCTX; + struct mfc_common_args DecArg; + + /* + s3c_mfc_common_args phys_addr_arg; + SSBSIP_MFC_BUFFER_ADDR *buf_addr; + */ + + SSBSIP_MFC_IMG_RESOLUTION *img_resolution; + SSBSIP_MFC_CRC_DATA *crc_data; + SSBSIP_MFC_CROP_INFORMATION *crop_information; +#ifdef S3D_SUPPORT + SSBSIP_MFC_FRAME_PACKING *frame_packing; +#endif + + if (openHandle == NULL) { + LOGE("SsbSipMfcDecGetConfig] openHandle is NULL"); + return MFC_RET_INVALID_PARAM; + } + + if (value == NULL) { + LOGE("SsbSipMfcDecGetConfig] value is NULL"); + return MFC_RET_INVALID_PARAM; + } + + pCTX = (_MFCLIB *) openHandle; + + switch (conf_type) { +#if 0 + case MFC_DEC_GETCONF_PHYS_ADDR: + buf_addr = (SSBSIP_MFC_BUFFER_ADDR *)value; + phys_addr_arg.args.get_phys_addr.u_addr = buf_addr->u_addr; + r = ioctl(pCTX->hMFC, IOCTL_MFC_GET_PHYS_ADDR, &phys_addr_arg); + if (r < 0) { + LOGE("SsbSipMfcDecGetConfig] IOCTL_MFC_GET_PHYS_ADDR failed"); + return MFC_API_FAIL; + } + buf_addr->p_addr = phys_addr_arg.args.get_phys_addr.p_addr; + break; +#endif + 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_FRAME_TAG: + *((unsigned int *)value) = pCTX->outframetagtop; + 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; + case MFC_DEC_GETCONF_CRC_DATA: +#ifdef S3D_SUPPORT + case MFC_DEC_GETCONF_FRAME_PACKING: + memset(&DecArg, 0x00, sizeof(DecArg)); + DecArg.args.config.type = conf_type; + + ret_code = ioctl(pCTX->hMFC, IOCTL_MFC_GET_CONFIG, &DecArg); + if (DecArg.ret_code != MFC_OK) { + LOGE("SsbSipMfcDecGetConfig] IOCTL_MFC_GET_CONFIG failed(ret : %d, conf_type: 0x%08x)", DecArg.ret_code, conf_type); + return MFC_RET_DEC_GET_CONF_FAIL; + } + + if (conf_type == MFC_DEC_GETCONF_CRC_DATA) { + crc_data = (SSBSIP_MFC_CRC_DATA *)value; + + crc_data->luma0 = DecArg.args.config.args.basic.values[0]; + crc_data->chroma0 = DecArg.args.config.args.basic.values[1]; + } else { + frame_packing = (SSBSIP_MFC_FRAME_PACKING *)value; + memcpy(frame_packing, &DecArg.args.config.args.frame_packing, + sizeof(SSBSIP_MFC_FRAME_PACKING)); + } +#else + crc_data = (SSBSIP_MFC_CRC_DATA *)value; + + memset(&DecArg, 0x00, sizeof(DecArg)); + DecArg.args.get_config.in_config_param = conf_type; + + ret_code = ioctl(pCTX->hMFC, IOCTL_MFC_GET_CONFIG, &DecArg); + if (DecArg.ret_code != MFC_OK) { + LOGE("SsbSipMfcDecGetConfig] IOCTL_MFC_GET_CONFIG failed(ret : %d, conf_type: 0x%08x)", DecArg.ret_code, conf_type); + return MFC_RET_DEC_GET_CONF_FAIL; + } + crc_data->luma0 = DecArg.args.get_config.out_config_value[0]; + crc_data->chroma0 = DecArg.args.get_config.out_config_value[1]; +#endif + break; + default: + LOGE("SsbSipMfcDecGetConfig] No such conf_type is supported"); + return MFC_RET_DEC_GET_CONF_FAIL; + } + + return MFC_RET_OK; +} + +/* CRESPO */ +#if 1 +int tile_4x2_read(int x_size, int y_size, int x_pos, int y_pos) +{ + int pixel_x_m1, pixel_y_m1; + int roundup_x, roundup_y; + int linear_addr0, linear_addr1, bank_addr ; + int x_addr; + int trans_addr; + + pixel_x_m1 = x_size -1; + pixel_y_m1 = y_size -1; + + roundup_x = ((pixel_x_m1 >> 7) + 1); + roundup_y = ((pixel_x_m1 >> 6) + 1); + + x_addr = x_pos >> 2; + + if ((y_size <= y_pos+32) && ( y_pos < y_size) && + (((pixel_y_m1 >> 5) & 0x1) == 0) && (((y_pos >> 5) & 0x1) == 0)) { + linear_addr0 = (((y_pos & 0x1f) <<4) | (x_addr & 0xf)); + linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 6) & 0x3f)); + + if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1)) + bank_addr = ((x_addr >> 4) & 0x1); + else + bank_addr = 0x2 | ((x_addr >> 4) & 0x1); + } else { + linear_addr0 = (((y_pos & 0x1f) << 4) | (x_addr & 0xf)); + linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 5) & 0x7f)); + + if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1)) + bank_addr = ((x_addr >> 4) & 0x1); + else + bank_addr = 0x2 | ((x_addr >> 4) & 0x1); + } + + linear_addr0 = linear_addr0 << 2; + trans_addr = (linear_addr1 <<13) | (bank_addr << 11) | linear_addr0; + + return trans_addr; +} + +void Y_tile_to_linear_4x2(unsigned char *p_linear_addr, unsigned char *p_tiled_addr, unsigned int x_size, unsigned int y_size) +{ + int trans_addr; + unsigned int i, j, k, index; + unsigned char data8[4]; + unsigned int max_index = x_size * y_size; + + for (i = 0; i < y_size; i = i + 16) { + for (j = 0; j < x_size; j = j + 16) { + trans_addr = tile_4x2_read(x_size, y_size, j, i); + for (k = 0; k < 16; k++) { + /* limit check - prohibit segmentation fault */ + index = (i * x_size) + (x_size * k) + j; + /* remove equal condition to solve thumbnail bug */ + if (index + 16 > max_index) { + continue; + } + + data8[0] = p_tiled_addr[trans_addr + 64 * k + 0]; + data8[1] = p_tiled_addr[trans_addr + 64 * k + 1]; + data8[2] = p_tiled_addr[trans_addr + 64 * k + 2]; + data8[3] = p_tiled_addr[trans_addr + 64 * k + 3]; + + p_linear_addr[index] = data8[0]; + p_linear_addr[index + 1] = data8[1]; + p_linear_addr[index + 2] = data8[2]; + p_linear_addr[index + 3] = data8[3]; + + data8[0] = p_tiled_addr[trans_addr + 64 * k + 4]; + data8[1] = p_tiled_addr[trans_addr + 64 * k + 5]; + data8[2] = p_tiled_addr[trans_addr + 64 * k + 6]; + data8[3] = p_tiled_addr[trans_addr + 64 * k + 7]; + + p_linear_addr[index + 4] = data8[0]; + p_linear_addr[index + 5] = data8[1]; + p_linear_addr[index + 6] = data8[2]; + p_linear_addr[index + 7] = data8[3]; + + data8[0] = p_tiled_addr[trans_addr + 64 * k + 8]; + data8[1] = p_tiled_addr[trans_addr + 64 * k + 9]; + data8[2] = p_tiled_addr[trans_addr + 64 * k + 10]; + data8[3] = p_tiled_addr[trans_addr + 64 * k + 11]; + + p_linear_addr[index + 8] = data8[0]; + p_linear_addr[index + 9] = data8[1]; + p_linear_addr[index + 10] = data8[2]; + p_linear_addr[index + 11] = data8[3]; + + data8[0] = p_tiled_addr[trans_addr + 64 * k + 12]; + data8[1] = p_tiled_addr[trans_addr + 64 * k + 13]; + data8[2] = p_tiled_addr[trans_addr + 64 * k + 14]; + data8[3] = p_tiled_addr[trans_addr + 64 * k + 15]; + + p_linear_addr[index + 12] = data8[0]; + p_linear_addr[index + 13] = data8[1]; + p_linear_addr[index + 14] = data8[2]; + p_linear_addr[index + 15] = data8[3]; + } + } + } +} + +void CbCr_tile_to_linear_4x2(unsigned char *p_linear_addr, unsigned char *p_tiled_addr, unsigned int x_size, unsigned int y_size) +{ + int trans_addr; + unsigned int i, j, k, index; + unsigned char data8[4]; + unsigned int half_y_size = y_size / 2; + unsigned int max_index = x_size * half_y_size; + unsigned char *pUVAddr[2]; + + pUVAddr[0] = p_linear_addr; + pUVAddr[1] = p_linear_addr + ((x_size * half_y_size) / 2); + + for (i = 0; i < half_y_size; i = i + 16) { + for (j = 0; j < x_size; j = j + 16) { + trans_addr = tile_4x2_read(x_size, half_y_size, j, i); + for (k = 0; k < 16; k++) { + /* limit check - prohibit segmentation fault */ + index = (i * x_size) + (x_size * k) + j; + /* remove equal condition to solve thumbnail bug */ + if (index + 16 > max_index) { + continue; + } + + data8[0] = p_tiled_addr[trans_addr + 64 * k + 0]; + data8[1] = p_tiled_addr[trans_addr + 64 * k + 1]; + data8[2] = p_tiled_addr[trans_addr + 64 * k + 2]; + data8[3] = p_tiled_addr[trans_addr + 64 * k + 3]; + + pUVAddr[index%2][index/2] = data8[0]; + pUVAddr[(index+1)%2][(index+1)/2] = data8[1]; + pUVAddr[(index+2)%2][(index+2)/2] = data8[2]; + pUVAddr[(index+3)%2][(index+3)/2] = data8[3]; + + data8[0] = p_tiled_addr[trans_addr + 64 * k + 4]; + data8[1] = p_tiled_addr[trans_addr + 64 * k + 5]; + data8[2] = p_tiled_addr[trans_addr + 64 * k + 6]; + data8[3] = p_tiled_addr[trans_addr + 64 * k + 7]; + + pUVAddr[(index+4)%2][(index+4)/2] = data8[0]; + pUVAddr[(index+5)%2][(index+5)/2] = data8[1]; + pUVAddr[(index+6)%2][(index+6)/2] = data8[2]; + pUVAddr[(index+7)%2][(index+7)/2] = data8[3]; + + data8[0] = p_tiled_addr[trans_addr + 64 * k + 8]; + data8[1] = p_tiled_addr[trans_addr + 64 * k + 9]; + data8[2] = p_tiled_addr[trans_addr + 64 * k + 10]; + data8[3] = p_tiled_addr[trans_addr + 64 * k + 11]; + + pUVAddr[(index+8)%2][(index+8)/2] = data8[0]; + pUVAddr[(index+9)%2][(index+9)/2] = data8[1]; + pUVAddr[(index+10)%2][(index+10)/2] = data8[2]; + pUVAddr[(index+11)%2][(index+11)/2] = data8[3]; + + data8[0] = p_tiled_addr[trans_addr + 64 * k + 12]; + data8[1] = p_tiled_addr[trans_addr + 64 * k + 13]; + data8[2] = p_tiled_addr[trans_addr + 64 * k + 14]; + data8[3] = p_tiled_addr[trans_addr + 64 * k + 15]; + + pUVAddr[(index+12)%2][(index+12)/2] = data8[0]; + pUVAddr[(index+13)%2][(index+13)/2] = data8[1]; + pUVAddr[(index+14)%2][(index+14)/2] = data8[2]; + pUVAddr[(index+15)%2][(index+15)/2] = data8[3]; + } + } + } +} +#else +int tile_4x2_read(int x_size, int y_size, int x_pos, int y_pos) +{ + int pixel_x_m1, pixel_y_m1; + int roundup_x, roundup_y; + int linear_addr0, linear_addr1, bank_addr; + int x_addr; + int trans_addr; + + pixel_x_m1 = x_size -1; + pixel_y_m1 = y_size -1; + + roundup_x = ((pixel_x_m1 >> 7) + 1); + roundup_y = ((pixel_x_m1 >> 6) + 1); + + x_addr = x_pos >> 2; + + if ((y_size <= y_pos+32) && + ( y_pos < y_size) && + (((pixel_y_m1 >> 5) & 0x1) == 0) && + (((y_pos >> 5) & 0x1) == 0)) { + linear_addr0 = (((y_pos & 0x1f) <<4) | (x_addr & 0xf)); + linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 6) & 0x3f)); + + if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1)) + bank_addr = ((x_addr >> 4) & 0x1); + else + bank_addr = 0x2 | ((x_addr >> 4) & 0x1); + } else { + linear_addr0 = (((y_pos & 0x1f) << 4) | (x_addr & 0xf)); + linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 5) & 0x7f)); + + if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1)) + bank_addr = ((x_addr >> 4) & 0x1); + else + bank_addr = 0x2 | ((x_addr >> 4) & 0x1); + } + + linear_addr0 = linear_addr0 << 2; + trans_addr = (linear_addr1 <<13) | (bank_addr << 11) | linear_addr0; + + return trans_addr; +} + + +void tile_to_linear_4x2(unsigned char *p_linear_addr, unsigned char *p_tiled_addr, unsigned int x_size, unsigned int y_size) +{ + int trans_addr; + unsigned int i, j, k, nn, mm; + unsigned int ix,iy, nx, ny; + + nx = x_size % 16; + ny = y_size % 16; + + if (nx != 0) + ix = 16; + else + ix = 1; + + if (ny != 0) + iy = 16; + else + iy = 1; + + for (i = 0; i < y_size - iy; i = i + 16) { + for (j = 0; j < x_size -ix; j = j + 16) { + trans_addr = tile_4x2_read(x_size, y_size, j, i); + + k = 0; nn = trans_addr + (k << 6); mm =x_size*(i+k) + j; + memcpy(p_linear_addr+mm, p_tiled_addr+nn, 16); + + k = 1; nn = trans_addr + (k << 6); mm =x_size*(i+k) + j; + memcpy(p_linear_addr+mm, p_tiled_addr+nn, 16); + + k = 2; nn = trans_addr + (k << 6); mm =x_size*(i+k) + j; + memcpy(p_linear_addr+mm, p_tiled_addr+nn, 16); + + k = 3; nn = trans_addr + (k << 6); mm =x_size*(i+k) + j; + memcpy(p_linear_addr+mm, p_tiled_addr+nn, 16); + + k = 4; nn = trans_addr + (k << 6); mm =x_size*(i+k) + j; + memcpy(p_linear_addr+mm, p_tiled_addr+nn, 16); + + k = 5; nn = trans_addr + (k << 6); mm =x_size*(i+k) + j; + memcpy(p_linear_addr+mm, p_tiled_addr+nn, 16); + + k = 6; nn = trans_addr + (k << 6); mm =x_size*(i+k) + j; + memcpy(p_linear_addr+mm, p_tiled_addr+nn, 16); + + k = 7; nn = trans_addr + (k << 6); mm =x_size*(i+k) + j; + memcpy(p_linear_addr+mm, p_tiled_addr+nn, 16); + + k = 8; nn = trans_addr + (k << 6); mm =x_size*(i+k) + j; + memcpy(p_linear_addr+mm, p_tiled_addr+nn, 16); + + k = 9; nn = trans_addr + (k << 6); mm =x_size*(i+k) + j; + memcpy(p_linear_addr+mm, p_tiled_addr+nn, 16); + + k = 10; nn = trans_addr + (k << 6); mm =x_size*(i+k) + j; + memcpy(p_linear_addr+mm, p_tiled_addr+nn, 16); + + k = 11; nn = trans_addr + (k << 6); mm =x_size*(i+k) + j; + memcpy(p_linear_addr+mm, p_tiled_addr+nn, 16); + + k = 12; nn = trans_addr + (k << 6); mm =x_size*(i+k) + j; + memcpy(p_linear_addr+mm, p_tiled_addr+nn, 16); + + k = 13; nn = trans_addr + (k << 6); mm =x_size*(i+k) + j; + memcpy(p_linear_addr+mm, p_tiled_addr+nn, 16); + + k = 14; nn = trans_addr + (k << 6); mm =x_size*(i+k) + j; + memcpy(p_linear_addr+mm, p_tiled_addr+nn, 16); + + k = 15; nn = trans_addr + (k << 6); mm =x_size*(i+k) + j; + memcpy(p_linear_addr+mm, p_tiled_addr+nn, 16); + } + } +} +#endif 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; +} + diff --git a/exynos/multimedia/codecs/video/exynos4/mfc/include/SsbSipMfcApi.h b/exynos/multimedia/codecs/video/exynos4/mfc/include/SsbSipMfcApi.h new file mode 100644 index 0000000..462c45d --- /dev/null +++ b/exynos/multimedia/codecs/video/exynos4/mfc/include/SsbSipMfcApi.h @@ -0,0 +1,409 @@ +/* + * 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/s3c-mfc" + + +/*--------------------------------------------------------------------------------*/ +/* 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, +#ifndef S3D_SUPPORT + MFC_DEC_GETCONF_WIDTH_HEIGHT +#else + MFC_DEC_GETCONF_WIDTH_HEIGHT, + MFC_DEC_SETCONF_SEI_PARSE, + MFC_DEC_GETCONF_FRAME_PACKING +#endif +} 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, +#ifndef S3D_SUPPORT + MFC_ENC_SETCONF_HIER_P +#else + MFC_ENC_SETCONF_HIER_P, + MFC_ENC_SETCONF_SEI_GEN, + MFC_ENC_SETCONF_FRAME_PACKING +#endif +} 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 S3D_SUPPORT +typedef struct { + int available; + unsigned int arrangement_id; + int arrangement_cancel_flag; + unsigned char arrangement_type; + int quincunx_sampling_flag; + unsigned char content_interpretation_type; + int spatial_flipping_flag; + int frame0_flipped_flag; + int field_views_flag; + int current_frame_is_frame0_flag; + unsigned char frame0_grid_pos_x; + unsigned char frame0_grid_pos_y; + unsigned char frame1_grid_pos_x; + unsigned char frame1_grid_pos_y; +} SSBSIP_MFC_FRAME_PACKING; +#endif + +#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 SsbSipMfcDecClose(void *openHandle); +void *SsbSipMfcDecGetInBuf(void *openHandle, void **phyInBuf, int inputBufferSize); + + +#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/include/mfc_errno.h b/exynos/multimedia/codecs/video/exynos4/mfc/include/mfc_errno.h new file mode 100644 index 0000000..305a28e --- /dev/null +++ b/exynos/multimedia/codecs/video/exynos4/mfc/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/include/mfc_interface.h b/exynos/multimedia/codecs/video/exynos4/mfc/include/mfc_interface.h new file mode 100644 index 0000000..7fa6b94 --- /dev/null +++ b/exynos/multimedia/codecs/video/exynos4/mfc/include/mfc_interface.h @@ -0,0 +1,524 @@ +/* + * 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 __FILE__ + +#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)) + +enum inst_type { + DECODER = 0x1, + ENCODER = 0x2, +}; + +typedef enum { + MFC_UNPACKED_PB = 0, + MFC_PACKED_PB = 1 +} mfc_packed_mode; + + +typedef enum +{ + MFC_USE_NONE = 0x00, + MFC_USE_YUV_BUFF = 0x01, + MFC_USE_STRM_BUFF = 0x10 +} 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 */ +}; + +#ifdef S3D_SUPPORT +struct mfc_basic_config { + int values[4]; +}; + +struct mfc_frame_packing { + int available; + unsigned int arrangement_id; + int arrangement_cancel_flag; + unsigned char arrangement_type; + int quincunx_sampling_flag; + unsigned char content_interpretation_type; + int spatial_flipping_flag; + int frame0_flipped_flag; + int field_views_flag; + int current_frame_is_frame0_flag; + unsigned char frame0_grid_pos_x; + unsigned char frame0_grid_pos_y; + unsigned char frame1_grid_pos_x; + unsigned char frame1_grid_pos_y; +}; + +union _mfc_config_arg { + struct mfc_basic_config basic; + struct mfc_frame_packing frame_packing; +}; + +struct mfc_config_arg { + int type; + union _mfc_config_arg args; +}; +#else +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]; +}; +#endif + +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; + +#ifdef S3D_SUPPORT + struct mfc_config_arg config; +#else + struct mfc_get_config_arg get_config; + struct mfc_set_config_arg set_config; +#endif + + 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; +}; + +#ifdef S3D_SUPPORT +struct mfc_enc_set_config { + int enable; + int number; +}; +#endif + +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; +} _MFCLIB; + +#define ENC_PROFILE_LEVEL(profile, level) ((profile) | ((level) << 8)) +#define ENC_RC_QBOUND(min_qp, max_qp) ((min_qp) | ((max_qp) << 8)) + +#endif /* __MFC_INTERFACE_H */ 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 */ diff --git a/exynos/multimedia/codecs/video/exynos5/Android.mk b/exynos/multimedia/codecs/video/exynos5/Android.mk new file mode 100644 index 0000000..949c637 --- /dev/null +++ b/exynos/multimedia/codecs/video/exynos5/Android.mk @@ -0,0 +1,7 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_VIDEO_PATH :=$(LOCAL_PATH) + +include $(LOCAL_VIDEO_PATH)/mfc_v4l2/Android.mk diff --git a/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/Android.mk b/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/Android.mk new file mode 100644 index 0000000..f7ae2ec --- /dev/null +++ b/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/Android.mk @@ -0,0 +1,39 @@ +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 + +#ifeq ($(BOARD_USE_V4L2_ION),true) +#LOCAL_CFLAGS += -DUSE_ION +#LOCAL_SHARED_LIBRARIES += libion +#endif + +include $(BUILD_STATIC_LIBRARY) diff --git a/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/dec/src/SsbSipMfcDecAPI.c b/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/dec/src/SsbSipMfcDecAPI.c new file mode 100644 index 0000000..cfb5dcc --- /dev/null +++ b/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/dec/src/SsbSipMfcDecAPI.c @@ -0,0 +1,1669 @@ +/* + * 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" +#ifdef USE_ION +#include "ion.h" +#endif + +/* #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 +#define CLEAR(x) memset (&(x), 0, sizeof(x)) + +enum { + NV12MT_FMT = 0, + NV12M_FMT, + NV21M_FMT, +}; + +static char *mfc_dev_name = SAMSUNG_MFC_DEV_NAME; +static int mfc_dev_node = 6; + +int read_header_data(void *openHandle); +int init_mfc_output_stream(void *openHandle); +int isBreak_loop(void *openHandle); + +int v4l2_mfc_querycap(int fd) +{ + struct v4l2_capability cap; + int ret; + + CLEAR(cap); + + ret = ioctl(fd, VIDIOC_QUERYCAP, &cap); + if (ret != 0) { + LOGE("[%s] VIDIOC_QUERYCAP failed", __func__); + return ret; + } + + if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { + LOGE("[%s] Device does not support capture", __func__); + return -1; + } + + if (!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) { + LOGE("[%s] Device does not support output", __func__); + return -1; + } + + if (!(cap.capabilities & V4L2_CAP_STREAMING)) { + LOGE("[%s] Device does not support streaming", __func__); + return -1; + } + + return 0; +} + +int v4l2_mfc_s_fmt(int fd, enum v4l2_buf_type type, + int pixelformat, unsigned int sizeimage, int width, int height) +{ + int ret; + struct v4l2_format fmt; + + CLEAR(fmt); + + fmt.type = type; + + if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + switch (pixelformat) { + 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 = width; + fmt.fmt.pix_mp.height = 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; + case VP8_DEC: + fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_VP8; + break; + default: + LOGE("[%s] Does NOT support the codec type (%d)", __func__, pixelformat); + return -1; + } + fmt.fmt.pix_mp.plane_fmt[0].sizeimage = sizeimage; + } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + switch (pixelformat) { + case NV12MT_FMT: + fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT_16X16; + break; + case NV12M_FMT: + fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M; + break; + case NV21M_FMT: + fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV21M; + break; + default: + LOGE("[%s] Does NOT support the pixel format (%d)", __func__, pixelformat); + return -1; + } + } else { + LOGE("[%s] Wrong buffer type", __func__); + return -1; + } + + ret = ioctl(fd, VIDIOC_S_FMT, &fmt); + + return ret; +} + +int v4l2_mfc_reqbufs(int fd, enum v4l2_buf_type type, enum v4l2_memory memory, int *buf_cnt) +{ + struct v4l2_requestbuffers reqbuf; + int ret; + + CLEAR(reqbuf); + + reqbuf.type = type; + reqbuf.memory = memory; + reqbuf.count = *buf_cnt; + + ret = ioctl(fd, VIDIOC_REQBUFS, &reqbuf); + *buf_cnt = reqbuf.count; + + return ret; +} + +int v4l2_mfc_querybuf(int fd, struct v4l2_buffer *buf, enum v4l2_buf_type type, + enum v4l2_memory memory, int index, struct v4l2_plane *planes) +{ + int length = -1, ret; + + if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) + length = 1; + else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) + length = 2; + + CLEAR(*buf); + buf->type = type; + buf->memory = memory; + buf->index = index; + buf->m.planes = planes; + buf->length = length; + + ret = ioctl(fd, VIDIOC_QUERYBUF, buf); + + return ret; +} + +int v4l2_mfc_streamon(int fd, enum v4l2_buf_type type) +{ + int ret; + + ret = ioctl(fd, VIDIOC_STREAMON, &type); + + return ret; +} + +int v4l2_mfc_streamoff(int fd, enum v4l2_buf_type type) +{ + int ret; + + ret = ioctl(fd, VIDIOC_STREAMOFF, &type); + + return ret; +} + +int v4l2_mfc_s_ctrl(int fd, int id, int value) +{ + struct v4l2_control ctrl; + int ret; + + CLEAR(ctrl); + ctrl.id = id; + ctrl.value = value; + + ret = ioctl(fd, VIDIOC_S_CTRL, &ctrl); + + return ret; +} + +int v4l2_mfc_g_ctrl(int fd, int id, int *value) +{ + struct v4l2_control ctrl; + int ret; + + CLEAR(ctrl); + ctrl.id = id; + + ret = ioctl(fd, VIDIOC_G_CTRL, &ctrl); + *value = ctrl.value; + + return ret; +} + +int v4l2_mfc_qbuf(int fd, struct v4l2_buffer *qbuf, enum v4l2_buf_type type, + enum v4l2_memory memory, int index, + struct v4l2_plane *planes, int frame_length) +{ + int ret, length = 0; + + if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + CLEAR(*qbuf); + length = 1; + } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + length = 2; + } + + qbuf->type = type; + qbuf->memory = memory; + qbuf->index = index; + qbuf->m.planes = planes; + qbuf->length = length; + qbuf->m.planes[0].bytesused = frame_length; + + ret = ioctl(fd, VIDIOC_QBUF, qbuf); + + return ret; +} + +int v4l2_mfc_dqbuf(int fd, struct v4l2_buffer *dqbuf, enum v4l2_buf_type type, + enum v4l2_memory memory) +{ + struct v4l2_plane planes[MFC_DEC_NUM_PLANES]; + int ret, length = 0; + + CLEAR(*dqbuf); + if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) + length = 1; + else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) + length = 2; + + dqbuf->type = type; + dqbuf->memory = memory; + dqbuf->m.planes = planes; + dqbuf->length = length; + + ret = ioctl(fd, VIDIOC_DQBUF, dqbuf); + + return ret; +} + +int v4l2_mfc_g_fmt(int fd, struct v4l2_format *fmt, enum v4l2_buf_type type) +{ + int ret; + + CLEAR(*fmt); + fmt->type = type; + ret = ioctl(fd, VIDIOC_G_FMT, fmt); + + return ret; +} + +int v4l2_mfc_g_crop(int fd, struct v4l2_crop *crop, enum v4l2_buf_type type) +{ + int ret; + + CLEAR(*crop); + crop->type = type; + ret = ioctl(fd, VIDIOC_G_CROP, crop); + + return ret; +} + +int v4l2_mfc_poll(int fd, int *revents, int timeout) +{ + struct pollfd poll_events; + int ret; + + poll_events.fd = fd; + poll_events.events = POLLOUT | POLLERR; + poll_events.revents = 0; + + ret = poll((struct pollfd*)&poll_events, 1, timeout); + *revents = poll_events.revents; + + return ret; +} + +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; + int req_count; + unsigned int i, j; + + 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; + + ret = v4l2_mfc_querycap(pCTX->hMFC); + if (ret != 0) { + LOGE("[%s] QUERYCAP failed", __func__); + goto error_case2; + } + + pCTX->inter_buff_status = MFC_USE_NONE; + ret = v4l2_mfc_s_fmt(pCTX->hMFC, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + H264_DEC, MAX_DECODER_INPUT_BUFFER_SIZE, 0, 0); + if (ret != 0) { + LOGE("[%s] S_FMT failed",__func__); + goto error_case2; + } + + pCTX->v4l2_dec.mfc_src_bufs_len = MAX_DECODER_INPUT_BUFFER_SIZE; + + req_count = MFC_DEC_NUM_SRC_BUFS; + ret = v4l2_mfc_reqbufs(pCTX->hMFC, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + V4L2_MEMORY_MMAP, &req_count); + if (ret != 0) { + LOGE("[%s] VIDIOC_REQBUFS failed",__func__); + goto error_case2; + } + + pCTX->v4l2_dec.mfc_num_src_bufs = req_count; + + for (i = 0; i < pCTX->v4l2_dec.mfc_num_src_bufs; ++i) { + ret = v4l2_mfc_querybuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + V4L2_MEMORY_MMAP, i, planes); + 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; + +#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) { + ret = v4l2_mfc_streamoff(pCTX->hMFC, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + 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) { + ret = v4l2_mfc_streamoff(pCTX->hMFC, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + 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); + } + +#ifdef USE_ION + ion_client_destroy(pCTX->ion_fd); +#endif + 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; + + int width, height; + int ctrl_value; + + struct v4l2_buffer buf; + struct v4l2_plane planes[MFC_DEC_NUM_PLANES]; + + int poll_state, poll_revents; + + 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); + + if (pCTX->codecType == FIMV1_DEC) { + width = pCTX->fimv1_res.width; + height = pCTX->fimv1_res.height; + } else { + width = 0; + height = 0; + } + ret = v4l2_mfc_s_fmt(pCTX->hMFC, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, pCTX->codecType, + MAX_DECODER_INPUT_BUFFER_SIZE, width, height); + if (ret != 0) { + LOGE("[%s] S_FMT failed", __func__); + ret = MFC_RET_DEC_INIT_FAIL; + goto error_case1; + } + + /* Set default destination format as NV12MT */ + ret = v4l2_mfc_s_fmt(pCTX->hMFC, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, NV12MT_FMT, + 0, width, height); + if (ret != 0) { + LOGE("[%s] S_FMT failed",__func__); + ret = MFC_RET_DEC_INIT_FAIL; + goto error_case1; + } + + /* PackedPB should be set after VIDIOC_S_FMT */ + if (packedPB) { + ret = v4l2_mfc_s_ctrl(pCTX->hMFC, V4L2_CID_CODEC_PACKED_PB, 1); + if (ret != 0) { + LOGE("[%s] VIDIOC_S_CTRL failed of PACKED_PB\n", __func__); + return MFC_RET_DEC_SET_CONF_FAIL; + } + } + + ret = v4l2_mfc_qbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + V4L2_MEMORY_MMAP, pCTX->v4l2_dec.beingUsedIndex, planes, Frameleng); + if (ret != 0) { + LOGE("[%s] VIDIOC_QBUF failed, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE",__func__); + ret = MFC_RET_DEC_INIT_FAIL; + goto error_case1; + } + + /* Processing the header requires running streamon + on OUTPUT queue */ + ret = v4l2_mfc_streamon(pCTX->hMFC, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + 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; + + ret = read_header_data(pCTX); + if (ret != 0) + goto error_case1; + + /* cacheable buffer */ + if (pCTX->cacheablebuffer == NO_CACHE) + ctrl_value = 0; + else + ctrl_value = 1; + + ret = v4l2_mfc_s_ctrl(pCTX->hMFC, V4L2_CID_CACHEABLE, ctrl_value); + if (ret != 0) { + LOGE("[%s] VIDIOC_S_CTRL failed, V4L2_CID_CACHEABLE", __func__); + ret = MFC_RET_DEC_INIT_FAIL; + goto error_case1; + } + +#ifdef USE_ION + pCTX->ion_fd = ion_client_create(); + if (pCTX->ion_fd < 3) { + LOGE("[%s] Failed to get ion_fd : %d", __func__, pCTX->ion_fd); + ret = MFC_RET_DEC_INIT_FAIL; + goto error_case1; + } +#endif + + ret = init_mfc_output_stream(pCTX); + if (ret != 0) + goto error_case1; + + ret = v4l2_mfc_streamon(pCTX->hMFC, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + 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; + + do { + poll_state = v4l2_mfc_poll(pCTX->hMFC, &poll_revents, POLL_DEC_WAIT_TIMEOUT); + if (poll_state > 0) { + if (poll_revents & POLLOUT) { + ret = v4l2_mfc_dqbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_MMAP); + if (ret == 0) + break; + } else if (poll_revents & POLLERR) { + LOGE("[%s] POLLERR\n", __func__); + return MFC_GETOUTBUF_STATUS_NULL; + } else { + LOGE("[%s] poll() returns 0x%x\n", __func__, poll_revents); + return MFC_GETOUTBUF_STATUS_NULL; + } + } else if (poll_state < 0) { + return MFC_GETOUTBUF_STATUS_NULL; + } + } while (poll_state == 0); + + return MFC_RET_OK; + +error_case1: + SsbSipMfcDecClose(openHandle); + return ret; +} + +int read_header_data(void *openHandle) +{ + struct v4l2_format fmt; + struct v4l2_crop crop; + struct v4l2_pix_format_mplane pix_mp; + int ctrl_value; + int ret; + + _MFCLIB *pCTX; + pCTX = (_MFCLIB *) openHandle; + + ret = v4l2_mfc_g_fmt(pCTX->hMFC, &fmt, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (ret != 0) { + LOGE("[%s] VIDIOC_G_FMT failed",__func__); + ret = MFC_RET_DEC_INIT_FAIL; + goto error_case; + } + + 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; + + ret = v4l2_mfc_g_crop(pCTX->hMFC, &crop, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (ret != 0) { + LOGE("[%s] VIDIOC_G_CROP failed",__func__); + ret = MFC_RET_DEC_INIT_FAIL; + goto error_case; + } + + 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; + + ret = v4l2_mfc_g_ctrl(pCTX->hMFC, V4L2_CID_CODEC_REQ_NUM_BUFS, &ctrl_value); + if (ret != 0) { + LOGE("[%s] VIDIOC_G_CTRL failed",__func__); + ret = MFC_RET_DEC_INIT_FAIL; + goto error_case; + } + + pCTX->v4l2_dec.mfc_num_dst_bufs = ctrl_value + pCTX->dec_numextradpb; + + LOGV("[%s] Num of allocated buffers: %d\n",__func__, pCTX->v4l2_dec.mfc_num_dst_bufs); + + return 0; + +error_case: + return ret; + } + +/* Initialize output stream of MFC */ +int init_mfc_output_stream(void *openHandle) +{ + struct v4l2_buffer buf; + struct v4l2_plane planes[MFC_DEC_NUM_PLANES]; + int ret; + int i, j; + _MFCLIB *pCTX; + pCTX = (_MFCLIB *) openHandle; + + ret = v4l2_mfc_reqbufs(pCTX->hMFC, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, + V4L2_MEMORY_MMAP, (int *)&pCTX->v4l2_dec.mfc_num_dst_bufs); + if (ret != 0) { + LOGE("[%s] VIDIOC_REQBUFS failed (destination buffers)",__func__); + ret = MFC_RET_DEC_INIT_FAIL; + goto error_case1; + } + + for (i = 0; i < pCTX->v4l2_dec.mfc_num_dst_bufs; ++i) { + ret = v4l2_mfc_querybuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, + V4L2_MEMORY_MMAP, i, planes); + 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] = buf.m.planes[0].length; + pCTX->v4l2_dec.mfc_dst_bufs_len[1] = buf.m.planes[1].length; + + pCTX->v4l2_dec.mfc_dst_phys[i][0] = buf.m.planes[0].cookie; + pCTX->v4l2_dec.mfc_dst_phys[i][1] = buf.m.planes[1].cookie; + +#ifdef USE_ION + pCTX->dst_ion_fd[i][0] = (int)buf.m.planes[0].share; + pCTX->dst_ion_fd[i][1] = (int)buf.m.planes[1].share; + + pCTX->v4l2_dec.mfc_dst_bufs[i][0] = + ion_map(pCTX->dst_ion_fd[i][0],pCTX->v4l2_dec.mfc_dst_bufs_len[0],0); + pCTX->v4l2_dec.mfc_dst_bufs[i][1] = + ion_map(pCTX->dst_ion_fd[i][1],pCTX->v4l2_dec.mfc_dst_bufs_len[1],0); + if (pCTX->v4l2_dec.mfc_dst_bufs[i][0] == MAP_FAILED || + pCTX->v4l2_dec.mfc_dst_bufs[i][0] == MAP_FAILED) + goto error_case2; +#else + pCTX->v4l2_dec.mfc_dst_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_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, buf.m.planes[1].length, + PROT_READ | PROT_WRITE, MAP_SHARED, pCTX->hMFC, buf.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; + } +#endif + + ret = v4l2_mfc_qbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, + V4L2_MEMORY_MMAP, i, planes, 0); + 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; + + return 0; + +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: + return ret; +} + +int resolution_change(void *openHandle) +{ + int i, ret; + int req_count; + _MFCLIB *pCTX; + pCTX = (_MFCLIB *) openHandle; + + ret = v4l2_mfc_streamoff(pCTX->hMFC, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + if (ret != 0) + goto error_case; + + pCTX->inter_buff_status &= ~(MFC_USE_DST_STREAMON); + + 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); + + req_count = 0; + ret = v4l2_mfc_reqbufs(pCTX->hMFC, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, + V4L2_MEMORY_MMAP, &req_count); + if (ret != 0) + goto error_case; + + read_header_data(pCTX); + init_mfc_output_stream(pCTX); + + ret = v4l2_mfc_streamon(pCTX->hMFC, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (ret != 0) + goto error_case; + pCTX->inter_buff_status |= MFC_USE_DST_STREAMON; + + return 0; + +error_case: + return ret; +} + +SSBSIP_MFC_ERROR_CODE SsbSipMfcDecExe(void *openHandle, int lengthBufFill) +{ + _MFCLIB *pCTX; + int ret; + + struct v4l2_buffer buf; + struct v4l2_plane planes[MFC_DEC_NUM_PLANES]; + int loop_count, ctrl_value; + + int poll_state; + int poll_revents; + +#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; + + if ((lengthBufFill > 0) && (SSBSIP_MFC_LAST_FRAME_PROCESSED != pCTX->lastframe)) { + /* Queue the stream frame */ + ret = v4l2_mfc_qbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + V4L2_MEMORY_MMAP, pCTX->v4l2_dec.beingUsedIndex, planes, lengthBufFill); + if (ret != 0) { + LOGE("[%s] VIDIOC_QBUF failed, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE",__func__); + return MFC_RET_DEC_EXE_ERR; + } + + memset(&buf, 0, sizeof(buf)); + buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + buf.memory = V4L2_MEMORY_MMAP; + buf.m.planes = planes; + buf.length = 1; + + /* wait for decoding */ + do { + poll_state = v4l2_mfc_poll(pCTX->hMFC, &poll_revents, POLL_DEC_WAIT_TIMEOUT); + if (poll_state > 0) { + if (poll_revents & POLLOUT) { + ret = v4l2_mfc_dqbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_MMAP); + if (ret == 0) { + if (buf.flags & V4L2_BUF_FLAG_ERROR) + return MFC_RET_DEC_EXE_ERR; + pCTX->v4l2_dec.mfc_src_buf_flags[buf.index] = BUF_DEQUEUED; + break; + } + } else if (poll_revents & POLLERR) { + LOGE("[%s] POLLERR\n",__func__); + return MFC_RET_DEC_EXE_ERR; + } else { + LOGE("[%s] poll() returns 0x%x\n", __func__, poll_revents); + return MFC_RET_DEC_EXE_ERR; + } + } else if (poll_state < 0) { + return MFC_RET_DEC_EXE_ERR; + } + + if (isBreak_loop(pCTX)) + break; + + } while(0 == poll_state); + + ret = v4l2_mfc_dqbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, V4L2_MEMORY_MMAP); + if (ret != 0) { + pCTX->displayStatus = MFC_GETOUTBUF_DECODING_ONLY; + pCTX->decOutInfo.disp_pic_frame_type = -1; + return MFC_RET_OK; + } else { + ret = v4l2_mfc_g_ctrl(pCTX->hMFC, V4L2_CID_CODEC_DISPLAY_STATUS, &ctrl_value); + if (ret != 0) { + LOGE("[%s] VIDIOC_G_CTRL failed", __func__); + return MFC_RET_DEC_GET_CONF_FAIL; + } + + switch (ctrl_value) { + case 0: + pCTX->displayStatus = MFC_GETOUTBUF_DECODING_ONLY; + break; + case 1: + pCTX->displayStatus = MFC_GETOUTBUF_DISPLAY_DECODING; + break; + case 2: + pCTX->displayStatus = MFC_GETOUTBUF_DISPLAY_ONLY; + break; + case 3: + pCTX->displayStatus = MFC_GETOUTBUF_CHANGE_RESOL; + break; + } + } + + if (pCTX->displayStatus == MFC_GETOUTBUF_CHANGE_RESOL) { + resolution_change(pCTX); + } else { + pCTX->decOutInfo.YVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[buf.index][0]; + pCTX->decOutInfo.CVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[buf.index][1]; + + pCTX->decOutInfo.YPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[buf.index][0]; + pCTX->decOutInfo.CPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[buf.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 */ + + /* Queue the stream frame */ + ret = v4l2_mfc_qbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + V4L2_MEMORY_MMAP, pCTX->v4l2_dec.beingUsedIndex, planes, 0); + if (ret != 0) { + LOGE("[%s] VIDIOC_QBUF failed, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE",__func__); + return MFC_RET_DEC_EXE_ERR; + } + + /* wait for decoding */ + loop_count = 0; + do { + ret = v4l2_mfc_dqbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, V4L2_MEMORY_MMAP); + if (ret != 0) + usleep(1000); + loop_count++; + if (loop_count >= 1000) { + LOGE("[%s] Error in do-while loop",__func__); + break; + } + } while (ret != 0); + + pCTX->displayStatus = MFC_GETOUTBUF_DISPLAY_ONLY; + + pCTX->decOutInfo.YVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[buf.index][0]; + pCTX->decOutInfo.CVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[buf.index][1]; + + pCTX->decOutInfo.YPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[buf.index][0]; + pCTX->decOutInfo.CPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[buf.index][1]; + } else { + loop_count = 0; + do { + ret = v4l2_mfc_dqbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, V4L2_MEMORY_MMAP); + if (ret != 0) + usleep(1000); + loop_count++; + if (loop_count >= 1000) { + LOGE("[%s] Error in do-while loop",__func__); + break; + } + } while (ret != 0); + + if (buf.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[buf.index][0]; + pCTX->decOutInfo.CVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[buf.index][1]; + + pCTX->decOutInfo.YPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[buf.index][0]; + pCTX->decOutInfo.CPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[buf.index][1]; + } + + pCTX->decOutInfo.disp_pic_frame_type = (buf.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 = v4l2_mfc_qbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, V4L2_MEMORY_MMAP, + buf.index, planes, 0); + +#ifdef CONFIG_MFC_FPS + gettimeofday(&mDec2, NULL); + if (mDec2.tv_usec-mDec1.tv_usec > 30000) over30ms++; +#endif + return MFC_RET_OK; +} + +SSBSIP_MFC_ERROR_CODE SsbSipMfcDecExeNb(void *openHandle, int lengthBufFill) +{ + _MFCLIB *pCTX; + int ret; + + struct v4l2_buffer buf; + 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 */ + ret = v4l2_mfc_qbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + V4L2_MEMORY_MMAP, pCTX->v4l2_dec.beingUsedIndex, planes, lengthBufFill); + 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 */ + ret = v4l2_mfc_qbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + V4L2_MEMORY_MMAP, pCTX->v4l2_dec.beingUsedIndex, planes, 0); + 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; +} + +int isBreak_loop(void *openHandle) +{ + _MFCLIB *pCTX; + pCTX = (_MFCLIB *) openHandle; + int ctrl_value; + int ret = 0; + + if (pCTX->displayStatus == MFC_GETOUTBUF_DISPLAY_ONLY) + return 1; + + ret = v4l2_mfc_g_ctrl(pCTX->hMFC, V4L2_CID_CODEC_CHECK_STATE, &ctrl_value); + if (ret != 0) { + LOGE("[%s] VIDIOC_G_CTRL failed", __func__); + return 0; + } + + if (ctrl_value == MFCSTATE_DEC_RES_DETECT) { + LOGV("[%s] Resolution Change detect",__func__); + return 1; + } else if (ctrl_value == MFCSTATE_DEC_TERMINATING) { + LOGV("[%s] Decoding Finish!!!",__func__); + return 1; + } + + return 0; +} + +SSBSIP_MFC_DEC_OUTBUF_STATUS SsbSipMfcDecWaitForOutBuf(void *openHandle, SSBSIP_MFC_DEC_OUTPUT_INFO *output_info) +{ + _MFCLIB *pCTX; + int ret; + + struct v4l2_buffer buf; + struct v4l2_plane planes[MFC_DEC_NUM_PLANES]; + int loop_count, ctrl_value; + + int poll_state; + int poll_revents; + + pCTX = (_MFCLIB *) openHandle; + + if (SSBSIP_MFC_LAST_FRAME_PROCESSED != pCTX->lastframe) { + /* wait for decoding */ + do { + poll_state = v4l2_mfc_poll(pCTX->hMFC, &poll_revents, POLL_DEC_WAIT_TIMEOUT); + if (poll_state > 0) { + if (poll_revents & POLLOUT) { + buf.m.planes = planes; + buf.length = 1; + ret = v4l2_mfc_dqbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_MMAP); + if (ret == 0) { + if (buf.flags & V4L2_BUF_FLAG_ERROR) + return MFC_GETOUTBUF_STATUS_NULL; + pCTX->v4l2_dec.mfc_src_buf_flags[buf.index] = BUF_DEQUEUED; + break; + } + } else if (poll_revents & POLLERR) { + LOGE("[%s] POLLERR\n",__func__); + return MFC_GETOUTBUF_STATUS_NULL; + } else { + LOGE("[%s] poll() returns 0x%x\n", __func__, poll_revents); + return MFC_GETOUTBUF_STATUS_NULL; + } + } else if (poll_state < 0) { + return MFC_GETOUTBUF_STATUS_NULL; + } + + if (isBreak_loop(pCTX)) + break; + + } while (poll_state == 0); + + ret = v4l2_mfc_dqbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, V4L2_MEMORY_MMAP); + if (ret != 0) { + pCTX->displayStatus = MFC_GETOUTBUF_DECODING_ONLY; + pCTX->decOutInfo.disp_pic_frame_type = -1; + return SsbSipMfcDecGetOutBuf(pCTX, output_info);; + } else { + ret = v4l2_mfc_g_ctrl(pCTX->hMFC, V4L2_CID_CODEC_DISPLAY_STATUS, &ctrl_value); + if (ret != 0) { + LOGE("[%s] VIDIOC_G_CTRL failed", __func__); + return MFC_RET_DEC_GET_CONF_FAIL; + } + + switch (ctrl_value) { + case 0: + pCTX->displayStatus = MFC_GETOUTBUF_DECODING_ONLY; + break; + case 1: + pCTX->displayStatus = MFC_GETOUTBUF_DISPLAY_DECODING; + break; + case 2: + pCTX->displayStatus = MFC_GETOUTBUF_DISPLAY_ONLY; + break; + case 3: + pCTX->displayStatus = MFC_GETOUTBUF_CHANGE_RESOL; + break; + } + } + + if (pCTX->displayStatus == MFC_GETOUTBUF_CHANGE_RESOL) { + resolution_change(pCTX); + } else { + pCTX->decOutInfo.YVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[buf.index][0]; + pCTX->decOutInfo.CVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[buf.index][1]; + + pCTX->decOutInfo.YPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[buf.index][0]; + pCTX->decOutInfo.CPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[buf.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 */ + + /* wait for decoding */ + loop_count = 0; + do { + ret = v4l2_mfc_dqbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, V4L2_MEMORY_MMAP); + if (ret != 0) + usleep(1000); + loop_count++; + if (loop_count >= 1000) { + LOGE("[%s] Error in do-while loop",__func__); + break; + } + } while (ret != 0); + + pCTX->displayStatus = MFC_GETOUTBUF_DISPLAY_ONLY; + + pCTX->decOutInfo.YVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[buf.index][0]; + pCTX->decOutInfo.CVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[buf.index][1]; + + pCTX->decOutInfo.YPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[buf.index][0]; + pCTX->decOutInfo.CPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[buf.index][1]; + } else { + loop_count = 0; + do { + ret = v4l2_mfc_dqbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, V4L2_MEMORY_MMAP); + if (ret != 0) + usleep(1000); + loop_count++; + if (loop_count >= 1000) { + LOGE("[%s] Error in do-while loop",__func__); + break; + } + } while (ret != 0); + + if (buf.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[buf.index][0]; + pCTX->decOutInfo.CVirAddr = pCTX->v4l2_dec.mfc_dst_bufs[buf.index][1]; + + pCTX->decOutInfo.YPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[buf.index][0]; + pCTX->decOutInfo.CPhyAddr = (unsigned int)pCTX->v4l2_dec.mfc_dst_phys[buf.index][1]; + } + + pCTX->decOutInfo.disp_pic_frame_type = (buf.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 = v4l2_mfc_qbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, V4L2_MEMORY_MMAP, + buf.index, planes, 0); + + return SsbSipMfcDecGetOutBuf(pCTX, output_info); +} + +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]; + pCTX->v4l2_dec.beingUsedIndex = 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) +{ + _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: + 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 buf; + struct v4l2_plane planes[MFC_DEC_NUM_PLANES]; + + int id, ctrl_value; + + 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: + ret = v4l2_mfc_streamoff(pCTX->hMFC, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + 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) { + ret = v4l2_mfc_qbuf(pCTX->hMFC, &buf, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, + V4L2_MEMORY_MMAP, i, planes, 0); + if (ret != 0) { + LOGE("[%s] VIDIOC_QBUF failed, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE",__func__); + return MFC_RET_DEC_SET_CONF_FAIL; + } + } + + ret = v4l2_mfc_streamon(pCTX->hMFC, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + 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 */ + switch (conf_type) { + case MFC_DEC_SETCONF_DISPLAY_DELAY: /* be set before calling SsbSipMfcDecInit */ + id = V4L2_CID_CODEC_DISPLAY_DELAY; + ctrl_value = *((unsigned int *) value); + break; + + case MFC_DEC_SETCONF_CRC_ENABLE: + id = V4L2_CID_CODEC_CRC_ENABLE; + ctrl_value = 1; + break; + + case MFC_DEC_SETCONF_SLICE_ENABLE: + id = V4L2_CID_CODEC_SLICE_INTERFACE; + ctrl_value = 1; + break; + + case MFC_DEC_SETCONF_FRAME_TAG: /*be set before calling SsbSipMfcDecExe */ + id = V4L2_CID_CODEC_FRAME_TAG; + ctrl_value = *((unsigned int*)value); + break; + + case MFC_DEC_SETCONF_POST_ENABLE: + 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 = v4l2_mfc_s_ctrl(pCTX->hMFC, id, ctrl_value); + 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; + + 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_FRAME_TAG: + ret = v4l2_mfc_g_ctrl(pCTX->hMFC, V4L2_CID_CODEC_FRAME_TAG, (int*)value); + if (ret != 0) + LOGE("[%s] VIDIOC_G_CTRL failed, V4L2_CID_CODEC_FRAME_TAG", __func__); + break; + + case MFC_DEC_GETCONF_CRC_DATA: + crc_data = (SSBSIP_MFC_CRC_DATA *) value; + + ret = v4l2_mfc_g_ctrl(pCTX->hMFC, V4L2_CID_CODEC_CRC_DATA_LUMA, &crc_data->luma0); + if (ret != 0) { + LOGE("[%s] VIDIOC_G_CTRL failed, V4L2_CID_CODEC_CRC_DATA_LUMA",__func__); + return MFC_RET_DEC_GET_CONF_FAIL; + } + + ret = v4l2_mfc_g_ctrl(pCTX->hMFC, V4L2_CID_CODEC_CRC_DATA_CHROMA, &crc_data->chroma0); + if (ret != 0) { + LOGE("[%s] VIDIOC_G_CTRL failed, V4L2_CID_CODEC_CRC_DATA_CHROMA",__func__); + return MFC_RET_DEC_GET_CONF_FAIL; + } + LOGI("[%s] crc_data->luma0=0x%x\n", __func__, crc_data->luma0); + LOGI("[%s] crc_data->chroma0=0x%x\n", __func__, crc_data->chroma0); + 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/exynos5/mfc_v4l2/enc/src/SsbSipMfcEncAPI.c b/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/enc/src/SsbSipMfcEncAPI.c new file mode 100644 index 0000000..a4a841f --- /dev/null +++ b/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/enc/src/SsbSipMfcEncAPI.c @@ -0,0 +1,1318 @@ +/* + * 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; + + LOGI("[%s] MFC Library Ver %d.%02d",__func__, MFC_LIB_VER_MAJOR, MFC_LIB_VER_MINOR); + 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 ret, i; + + enum v4l2_buf_type type; + + 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->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[28]; + struct v4l2_ext_control ext_ctrl_h263[20]; + struct v4l2_ext_control ext_ctrl[48]; + 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 = 2800; /* based on MFC6.x */ + } 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 = 2800; /* based on MFC6.x */ + } 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; + + ext_ctrl_mpeg4[27].id = V4L2_CID_CODEC_MFC5X_ENC_MPEG4_RC_MB_ENABLE; /* MFC 6.x Only */ + ext_ctrl_mpeg4[27].value = mpeg4_arg->EnableMBRateControl; + 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; + + ext_ctrl_h263[19].id = V4L2_CID_CODEC_MFC5X_ENC_H263_RC_MB_ENABLE; /* MFC 6.x Only */ + ext_ctrl_h263[19].value = h263_arg->EnableMBRateControl; + 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 = 2800; /* based on MFC6.x */ + } 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 = 2800; /* based on MFC6.x */ + } 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; /* MFC5.x Only */ + 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; + + if (pCTX->hier_p_enable) { + ext_ctrl[44].id = V4L2_CID_CODEC_MFC5X_ENC_H264_HIER_P_ENABLE; + ext_ctrl[44].value = V4L2_CODEC_MFC5X_ENC_SW_ENABLE; + ext_ctrl[45].id = V4L2_CID_CODEC_MFC5X_ENC_H264_LAYER0_QP; + ext_ctrl[45].value = pCTX->hier_qp_value.t0_frame_qp; + ext_ctrl[46].id = V4L2_CID_CODEC_MFC5X_ENC_H264_LAYER1_QP; + ext_ctrl[46].value = pCTX->hier_qp_value.t2_frame_qp; + ext_ctrl[47].id = V4L2_CID_CODEC_MFC5X_ENC_H264_LAYER2_QP; + ext_ctrl[47].value = pCTX->hier_qp_value.t3_frame_qp; + } else { + ext_ctrl[44].id = V4L2_CID_CODEC_MFC5X_ENC_H264_HIER_P_ENABLE; + ext_ctrl[44].value = V4L2_CODEC_MFC5X_ENC_SW_DISABLE; + ext_ctrl[45].id = V4L2_CID_CODEC_MFC5X_ENC_H264_LAYER0_QP; + ext_ctrl[45].value = 0; + ext_ctrl[46].id = V4L2_CID_CODEC_MFC5X_ENC_H264_LAYER1_QP; + ext_ctrl[46].value = 0; + ext_ctrl[47].id = V4L2_CID_CODEC_MFC5X_ENC_H264_LAYER2_QP; + ext_ctrl[47].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 = 28; + ext_ctrls.controls = ext_ctrl_mpeg4; + } else if (pCTX->codecType == H264_ENC) { + ext_ctrls.count = 48; + ext_ctrls.controls = ext_ctrl; + } else if (pCTX->codecType == H263_ENC) { + ext_ctrls.count = 20; + 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; +#if 0 + 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 */ + } +#else /* FIXME: */ + if (NV12_TILE == pCTX->framemap) { + fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT; /* 4:2:0, 2 Planes, 16x16 Tiles */ + } else { /* NV12_LINEAR (default) */ + fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M; /* 4:2:0, 2 Planes, linear */ + } +#endif + 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; + } + + pCTX->inter_buff_status |= MFC_USE_DST_STREAMON; + + 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 (1 == 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; + + /* FIXME check this if GetInBuf() is not called for UserPtr */ + 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; + + /* FIXME check whether Y & C sizes should be set or not*/ + 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((pCTX->width * pCTX->height), 2048); /* linear mode, 2K align */ + input_info->CSize = Align((pCTX->width * (pCTX->height >> 1)), 2048); /* linear mode, 2K 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 { + 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; + struct v4l2_control ctrl; + unsigned int encoded_y_addr, encoded_c_addr; + int ret; + + 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; + } + + ctrl.id = V4L2_CID_CODEC_ENCODED_LUMA_ADDR; + ctrl.value = 0; + ret = ioctl(pCTX->hMFC, VIDIOC_G_CTRL, &ctrl); + if (ret != 0) + LOGE("[%s] Error to do g_ctrl",__func__); + encoded_y_addr = (unsigned int)ctrl.value; + + ctrl.id = V4L2_CID_CODEC_ENCODED_CHROMA_ADDR; + ctrl.value = 0; + ret = ioctl(pCTX->hMFC, VIDIOC_G_CTRL, &ctrl); + if (ret != 0) + LOGE("[%s] Error to do g_ctrl",__func__); + encoded_c_addr = (unsigned int)ctrl.value; + + 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*)encoded_y_addr; + output_info->encodedCPhyAddr = (void*)encoded_c_addr; + + 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; + } + + pCTX->inter_buff_status |= MFC_USE_SRC_STREAMON; + + 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; + } else { /* in the case of B frame encoding */ + ctrl.id = V4L2_CID_CODEC_CHECK_STATE; + ctrl.value = 0; + ret = ioctl(pCTX->hMFC, VIDIOC_G_CTRL, &ctrl); + LOGV("[%s] ctx state = %d\n",__func__, ctrl.value); + if (ctrl.value == MFCSTATE_ENC_NO_OUTPUT) + return MFC_RET_OK; + } + loopcnt++; + } while ((0 == poll_state) && (loopcnt < 5)); + + if (pCTX->v4l2_enc.bRunning != 0) { + pCTX->encodedframeType = (qbuf.flags & 0x38) >> 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; + struct v4l2_control ctrl; + struct mfc_enc_hier_p_qp hier_p_qp; + int ret; + + 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_FRAME_TYPE: + ctrl.id = V4L2_CID_CODEC_FRAME_INSERTION; + ctrl.value = *((unsigned int*)value); + break; + + case MFC_ENC_SETCONF_I_PERIOD: + ctrl.id = V4L2_CID_CODEC_ENCODED_I_PERIOD_CH; + ctrl.value = *((unsigned int*)value); + break; + + case MFC_ENC_SETCONF_CHANGE_FRAME_RATE: + ctrl.id = V4L2_CID_CODEC_ENCODED_FRAME_RATE_CH; + ctrl.value = *((unsigned int*)value); + break; + + case MFC_ENC_SETCONF_CHANGE_BIT_RATE: + ctrl.id = V4L2_CID_CODEC_ENCODED_BIT_RATE_CH; + ctrl.value = *((unsigned int*)value); + break; + + 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; +#endif + case MFC_ENC_SETCONF_HIER_P: + hier_p_qp = *((struct mfc_enc_hier_p_qp *) value); + pCTX->hier_p_enable = 1; + pCTX->hier_qp_value.t0_frame_qp = (int)(hier_p_qp.t0_frame_qp); + pCTX->hier_qp_value.t2_frame_qp = (int)(hier_p_qp.t2_frame_qp); + pCTX->hier_qp_value.t3_frame_qp = (int)(hier_p_qp.t3_frame_qp); + return MFC_RET_OK; + + default: + LOGE("[%s] conf_type(%d) is NOT supported\n",__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_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; + + 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/exynos5/mfc_v4l2/include/SsbSipMfcApi.h b/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/include/SsbSipMfcApi.h new file mode 100644 index 0000000..28b2d8a --- /dev/null +++ b/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/include/SsbSipMfcApi.h @@ -0,0 +1,384 @@ +/* + * 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, + VP8_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) */ + int EnableMBRateControl; /* [IN] Enable macroblock-level rate control, MFC6.x Only */ + + /* 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) */ + int EnableMBRateControl; /* [IN] Enable macroblock-level rate control, MFC6.x Only */ + + /* 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/exynos5/mfc_v4l2/include/mfc_errno.h b/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/include/mfc_errno.h new file mode 100644 index 0000000..b8e96ab --- /dev/null +++ b/exynos/multimedia/codecs/video/exynos5/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/exynos5/mfc_v4l2/include/mfc_interface.h b/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/include/mfc_interface.h new file mode 100644 index 0000000..2200e10 --- /dev/null +++ b/exynos/multimedia/codecs/video/exynos5/mfc_v4l2/include/mfc_interface.h @@ -0,0 +1,555 @@ +/* + * 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, +}; + +enum mfc_check_state { + MFCSTATE_PROCESSING = 0, + MFCSTATE_DEC_RES_DETECT, + MFCSTATE_DEC_TERMINATING, + MFCSTATE_ENC_NO_OUTPUT, +}; + +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; + + int hier_p_enable; + struct mfc_enc_hier_p_qp hier_qp_value; + + /*ION related*/ + int ion_fd; + int dst_ion_fd[MFC_DEC_MAX_DST_BUFS][MFC_DEC_NUM_PLANES]; +} _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 */ |