3878 lines
119 KiB
C
3878 lines
119 KiB
C
#define LOG_TAG "rt_media"
|
|
#include <linux/init.h>
|
|
#include <linux/module.h>
|
|
#include <linux/ioctl.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/device.h>
|
|
#include <linux/err.h>
|
|
#include <linux/list.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/cdev.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/rmap.h>
|
|
#include <linux/wait.h>
|
|
#include <linux/semaphore.h>
|
|
#include <linux/mm.h>
|
|
|
|
#include <net/net_namespace.h>
|
|
#include <net/netlink.h>
|
|
#include <net/genetlink.h>
|
|
|
|
#include <asm/uaccess.h>
|
|
#include "mem_interface.h"
|
|
|
|
#include "rt_media.h"
|
|
#include <uapi_rt_media.h>
|
|
|
|
#include "component/rt_common.h"
|
|
#include "component/rt_component.h"
|
|
#include "component/rt_venc_component.h"
|
|
#include "component/rt_vi_component.h"
|
|
#include <linux/rpmsg.h>
|
|
|
|
#ifndef RT_MEDIA_DEV_MAJOR
|
|
#define RT_MEDIA_DEV_MAJOR (160)
|
|
#endif
|
|
#ifndef RT_MEDIA_DEV_MINOR
|
|
#define RT_MEDIA_DEV_MINOR (0)
|
|
#endif
|
|
|
|
#define MOTION_TOTAL_REGION_NUM_DEFAULT (50)
|
|
#define REGION_D3D_TOTAL_REGION_NUM_DEFAULT (120)
|
|
|
|
#define MAX_SENSOR_NUM 3
|
|
|
|
int g_rt_media_dev_major = RT_MEDIA_DEV_MAJOR;
|
|
int g_rt_media_dev_minor = RT_MEDIA_DEV_MINOR;
|
|
/*S_IRUGO represent that g_rt_media_dev_major can be read,but canot be write*/
|
|
module_param(g_rt_media_dev_major, int, 0444);
|
|
module_param(g_rt_media_dev_minor, int, 0444);
|
|
|
|
typedef struct stream_buffer_manager {
|
|
struct list_head empty_stream_list; //video_stream_node
|
|
struct list_head valid_stream_list;
|
|
struct list_head caller_hold_stream_list;
|
|
struct mutex mutex;
|
|
int empty_num;
|
|
|
|
wait_queue_head_t wait_bitstream;
|
|
unsigned int wait_bitstream_condition;
|
|
unsigned int need_wait_up_flag;
|
|
} stream_buffer_manager;
|
|
|
|
|
|
typedef struct tdm_data_node {
|
|
struct vin_isp_tdm_event_status tdm_data;
|
|
struct list_head mList;
|
|
} tdm_data_node;
|
|
|
|
|
|
typedef struct tdm_data_manager {
|
|
int b_inited;
|
|
struct list_head empty_list;
|
|
struct list_head valid_list;
|
|
spinlock_t s_lock;
|
|
int empty_num;
|
|
} tdm_data_manager;
|
|
|
|
|
|
typedef enum rt_media_state {
|
|
RT_MEDIA_STATE_IDLE = 0,
|
|
RT_MEDIA_STATE_CONFIGED = 1,
|
|
RT_MEDIA_STATE_EXCUTING = 2,
|
|
RT_MEDIA_STATE_PAUSE = 3,
|
|
} rt_media_state;
|
|
|
|
typedef struct media_private_info {
|
|
int channel;
|
|
} media_private_info;
|
|
|
|
typedef struct video_recoder {
|
|
int activate_vi_flag;
|
|
int activate_venc_flag;
|
|
rt_component_type *venc_comp;
|
|
rt_component_type *vi_comp;
|
|
stream_buffer_manager stream_buf_manager;
|
|
int bcreate_comp_flag;
|
|
rt_media_state state;
|
|
rt_media_config_s config;
|
|
config_yuv_buf_info yuv_buf_info;
|
|
rt_pixelformat_type pixelformat;
|
|
unsigned char *enc_yuv_phy_addr;
|
|
struct mutex yuv_mutex;
|
|
int stream_data_cb_count;
|
|
int max_fps;
|
|
int enable_high_fps;
|
|
int bReset_high_fps_finish;
|
|
int bsetup_recorder_finish;
|
|
int bvin_is_ready;//rt_media thread setup not ready fact.
|
|
VencMotionSearchParam motion_search_param;
|
|
VencMotionSearchRegion *motion_region;
|
|
int motion_region_len; //unit:bytes
|
|
VencRegionD3DParam region_d3d_param;
|
|
VencRegionD3DRegion *region_d3d_region;
|
|
int region_d3d_region_len; //unit:bytes
|
|
VencInsertData insert_data;
|
|
int mNLDstPid; //netlink dst port ID
|
|
} video_recoder;
|
|
|
|
typedef struct encode_config {
|
|
int b_get_from_dts;
|
|
char *name;
|
|
int ch_id;//vipp_num
|
|
RT_VENC_CODEC_TYPE codec_type;
|
|
int res_w;
|
|
int res_h;
|
|
int fps;
|
|
int bit_rate;//kb
|
|
int gop;
|
|
int enable_sharp;
|
|
int vbr;
|
|
RTeVencProductMode product_mode;
|
|
video_qp_range qp_range;
|
|
RTVencVbrParam vbr_param;
|
|
VIDEO_OUTPUT_MODE out_mode;
|
|
RT_PIXELFORMAT_TYPE pix_fmt;//* just set it to: RT_PIXELFORMAT_UNKNOWN
|
|
int reduce_refrec_mem;//Can reduce memory usage and optimize memory efficiency. default set enable
|
|
int aiisp_en;
|
|
unsigned int tdm_rxbuf_cnt;
|
|
} encode_config;
|
|
struct rt_media_dev {
|
|
struct cdev cdev; /* char device struct */
|
|
struct device *dev; /* ptr to class device struct */
|
|
struct device *platform_dev; /* ptr to class device struct */
|
|
struct class *class; /* class for auto create device node */
|
|
|
|
struct semaphore sem; /* mutual exclusion semaphore */
|
|
|
|
wait_queue_head_t wq; /* wait queue for poll ops */
|
|
|
|
struct mutex lock_vdec;
|
|
|
|
video_recoder recoder[VIDEO_INPUT_CHANNEL_NUM]; //1: major, 2: minor, 3: yuv
|
|
|
|
struct task_struct *setup_thread;
|
|
|
|
struct task_struct *reset_high_fps_thread;
|
|
|
|
int in_high_fps_status;
|
|
video_recoder *need_start_recoder_1;
|
|
video_recoder *need_start_recoder_2;
|
|
int bcsi_err;
|
|
int bcsi_status_set[VIDEO_INPUT_CHANNEL_NUM];
|
|
tdm_data_manager st_tdm_data_manager[MAX_SENSOR_NUM];
|
|
encode_config enc_conf[MAX_SENSOR_NUM];
|
|
};
|
|
|
|
struct vi_part_cfg {
|
|
int wdr;
|
|
int width;
|
|
int height;
|
|
int venc_format; //1:H264 2:H265
|
|
int flicker_mode; ////0:disable,1:50HZ,2:60HZ, default 50HZ
|
|
int fps;
|
|
};
|
|
struct csi_status_pair {
|
|
int bset;
|
|
int status;
|
|
};
|
|
static struct rt_media_dev *rt_media_devp;
|
|
|
|
static int bvin_is_ready_rt_not_probe[VIDEO_INPUT_CHANNEL_NUM];//Deal with the fact that rt_media not registered
|
|
static struct csi_status_pair g_csi_status_pair[VIDEO_INPUT_CHANNEL_NUM];
|
|
|
|
static video_stream_s *ioctl_get_stream_data(video_recoder *recoder);
|
|
static int ioctl_return_stream_data(video_recoder *recoder,
|
|
video_stream_s *video_stream);
|
|
int ioctl_start(video_recoder *recoder);
|
|
|
|
/**
|
|
read record channel id, find matching recorder, then store source port id to NLDstPid.
|
|
|
|
Then rt_media recorder in kernel can send message to dst AWVideoInput_cxt.
|
|
*/
|
|
static int cmd_attr_chnid(struct genl_info *info)
|
|
{
|
|
int rc = 0;
|
|
int nRecordChannelId = nla_get_s32(info->attrs[RT_MEDIA_CMD_ATTR_CHNID]);
|
|
if (nRecordChannelId >= 0 && nRecordChannelId < VIDEO_INPUT_CHANNEL_NUM) {
|
|
video_recoder *pRecorder = &rt_media_devp->recoder[nRecordChannelId];
|
|
if (0 == pRecorder->mNLDstPid) {
|
|
pRecorder->mNLDstPid = info->snd_portid;
|
|
} else {
|
|
if (pRecorder->mNLDstPid != info->snd_portid) {
|
|
RT_LOGW("Be careful! recorder[%d] netlink dst port id change [%d->%d]", nRecordChannelId,
|
|
pRecorder->mNLDstPid, info->snd_portid);
|
|
pRecorder->mNLDstPid = info->snd_portid;
|
|
}
|
|
}
|
|
rc = 0;
|
|
RT_LOGD("recorder[%d] netlink dst port id=%d", nRecordChannelId, pRecorder->mNLDstPid);
|
|
} else {
|
|
RT_LOGE("fatal error! recorder[%d] wrong!", nRecordChannelId);
|
|
rc = -EINVAL;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
static int rt_media_user_cmd(struct sk_buff *skb, struct genl_info *info)
|
|
{
|
|
if (info->attrs[RT_MEDIA_CMD_ATTR_CHNID]) {
|
|
return cmd_attr_chnid(info);
|
|
} else {
|
|
RT_LOGW("Be careful! user space should send attr chnid, we only process attr chnid now.");
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
static int rt_media_genl_family_registered;
|
|
|
|
static struct genl_family rt_media_genl_family = {
|
|
.id = GENL_ID_GENERATE,
|
|
.name = RT_MEDIA_GENL_NAME,
|
|
.version = RT_MEDIA_GENL_VERSION,
|
|
.maxattr = RT_MEDIA_CMD_ATTR_MAX,
|
|
};
|
|
|
|
static const struct nla_policy rt_media_cmd_get_policy[RT_MEDIA_CMD_ATTR_MAX+1] = {
|
|
[RT_MEDIA_CMD_ATTR_CHNID] = { .type = NLA_S32 },
|
|
[RT_MEDIA_CMD_ATTR_RTCBEVENT] = { .type = NLA_BINARY, .len = sizeof(RTCbEvent) }
|
|
};
|
|
|
|
static const struct genl_ops rt_media_genl_ops[] = {
|
|
{
|
|
.cmd = RT_MEDIA_CMD_SEND,
|
|
.doit = rt_media_user_cmd,
|
|
.policy = rt_media_cmd_get_policy,
|
|
}
|
|
};
|
|
|
|
static int __init rt_media_genetlink_init(void)
|
|
{
|
|
int ret = genl_register_family_with_ops(&rt_media_genl_family, rt_media_genl_ops);
|
|
if (ret) {
|
|
RT_LOGE("fatal error! genl register rt_media family fail:%d", ret);
|
|
return ret;
|
|
}
|
|
rt_media_genl_family_registered = 1;
|
|
RT_LOGD("registered rt_media genl family version:%d", rt_media_genl_family.version);
|
|
return 0;
|
|
}
|
|
|
|
static int __exit rt_media_genetlink_exit(void)
|
|
{
|
|
int ret = 0;
|
|
if (rt_media_genl_family_registered) {
|
|
ret = genl_unregister_family(&rt_media_genl_family);
|
|
if (ret) {
|
|
RT_LOGE("fatal error! genl unregister rt_media family fail:%d", ret);
|
|
}
|
|
rt_media_genl_family_registered = 0;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
send netlink message to user process AWChannel_cxt of AWVideoInput_cxt.
|
|
|
|
@param pid
|
|
dst port id in user space.
|
|
|
|
@return
|
|
ERROR_TYPE_NOMEM
|
|
ERROR_TYPE_ERROR
|
|
ERROR_TYPE_OK
|
|
*/
|
|
static error_type rt_media_send_genl_RTCbEvent(int pid, RTCbEvent *pEvent)
|
|
{
|
|
int size = nla_total_size(sizeof(RTCbEvent));
|
|
struct sk_buff *skb = genlmsg_new(size, GFP_KERNEL);
|
|
if (!skb) {
|
|
RT_LOGE("fatal error! malloc fail!");
|
|
return ERROR_TYPE_NOMEM;
|
|
}
|
|
void *user_hdr = genlmsg_put(skb, 0, 0, &rt_media_genl_family, 0, RT_MEDIA_CMD_CB_EVENT);
|
|
if (user_hdr == NULL) {
|
|
RT_LOGE("fatal error! check code!");
|
|
nlmsg_free(skb);
|
|
return ERROR_TYPE_NOMEM;
|
|
}
|
|
int rc = nla_put(skb, RT_MEDIA_CMD_ATTR_RTCBEVENT, sizeof(RTCbEvent), pEvent);
|
|
if (rc != 0) {
|
|
RT_LOGE("fatal error! check code[%d]!", rc);
|
|
nlmsg_free(skb);
|
|
return ERROR_TYPE_NOMEM;
|
|
}
|
|
genlmsg_end(skb, user_hdr);
|
|
rc = genlmsg_unicast(&init_net, skb, pid);
|
|
if (rc < 0) {
|
|
RT_LOGE("fatal error! check code[%d]!", rc);
|
|
nlmsg_free(skb);
|
|
return ERROR_TYPE_NOMEM;
|
|
}
|
|
return ERROR_TYPE_OK;
|
|
}
|
|
|
|
error_type venc_event_handler(
|
|
PARAM_IN comp_handle component,
|
|
PARAM_IN void *pAppData,
|
|
PARAM_IN comp_event_type eEvent,
|
|
PARAM_IN unsigned int nData1,
|
|
PARAM_IN unsigned int nData2,
|
|
PARAM_IN void *pEventData)
|
|
{
|
|
error_type ret = ERROR_TYPE_ERROR;
|
|
video_recoder *pRecorder = (video_recoder *)pAppData;
|
|
switch (eEvent) {
|
|
case COMP_EVENT_CMD_COMPLETE: {
|
|
break;
|
|
}
|
|
case COMP_EVENT_CMD_ERROR: {
|
|
break;
|
|
}
|
|
case COMP_EVENT_VENC_DROP_FRAME: {
|
|
//notify user space AWChannel_cxt using netlink socket
|
|
ret = ERROR_TYPE_OK;
|
|
if (pRecorder->mNLDstPid != 0) {
|
|
RTCbEvent stDropFrameEvent;
|
|
memset(&stDropFrameEvent, 0, sizeof(RTCbEvent));
|
|
stDropFrameEvent.eEventType = RTCB_EVENT_VENC_DROP_FRAME;
|
|
stDropFrameEvent.nData1 = 1; //drop one frame.
|
|
ret = rt_media_send_genl_RTCbEvent(pRecorder->mNLDstPid, &stDropFrameEvent);
|
|
if (ret != ERROR_TYPE_OK) {
|
|
RT_LOGE("fatal error! recorder[%d] send nl msg to user space portid[%d] fail[%d]",
|
|
pRecorder->config.channelId, pRecorder->mNLDstPid, ret);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
RT_LOGI("not support venc_event_handler:0x%x", eEvent);
|
|
break;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
error_type rt_venc_empty_in_buffer_done(
|
|
PARAM_IN comp_handle component,
|
|
PARAM_IN void *pAppData,
|
|
PARAM_IN comp_buffer_header_type *pBuffer)
|
|
{
|
|
video_recoder *recoder = (video_recoder *)pAppData;
|
|
video_frame_s *pvideo_frame = (video_frame_s *)pBuffer->private;
|
|
|
|
mutex_lock(&recoder->yuv_mutex);
|
|
if (recoder->enc_yuv_phy_addr != NULL)
|
|
RT_LOGE("the enc_yuv_phy_addr[%p] is not null", recoder->enc_yuv_phy_addr);
|
|
recoder->enc_yuv_phy_addr = (unsigned char *)pvideo_frame->phy_addr[0];
|
|
mutex_unlock(&recoder->yuv_mutex);
|
|
RT_LOGI("set recoder->enc_yuv_phy_addr: %p", recoder->enc_yuv_phy_addr);
|
|
return 0;
|
|
}
|
|
|
|
/* empty_list --> valid_list*/
|
|
error_type rt_venc_fill_out_buffer_done(
|
|
PARAM_IN comp_handle component,
|
|
PARAM_IN void *pAppData,
|
|
PARAM_IN comp_buffer_header_type *pBuffer)
|
|
{
|
|
video_stream_node *stream_node = NULL;
|
|
video_recoder *recoder = (video_recoder *)pAppData;
|
|
video_stream_s *video_stream = (video_stream_s *)pBuffer->private;
|
|
stream_buffer_manager *stream_buf_mgr = &recoder->stream_buf_manager;
|
|
|
|
recoder->stream_data_cb_count++;
|
|
if (recoder->stream_data_cb_count == 1) {
|
|
RT_LOGW("channel %d first stream data, pts = %lld, time = %lld, width = %d", recoder->config.channelId,
|
|
video_stream->pts, get_cur_time(), recoder->config.width);
|
|
}
|
|
|
|
mutex_lock(&stream_buf_mgr->mutex);
|
|
|
|
if (list_empty(&stream_buf_mgr->empty_stream_list)) {
|
|
RT_LOGE("rt_venc_fill_out_buffer_done error: empty list is null");
|
|
mutex_unlock(&stream_buf_mgr->mutex);
|
|
return ERROR_TYPE_ERROR;
|
|
}
|
|
stream_node = list_first_entry(&stream_buf_mgr->empty_stream_list, video_stream_node, mList);
|
|
memcpy(&stream_node->video_stream, video_stream, sizeof(video_stream_s));
|
|
|
|
stream_buf_mgr->empty_num--;
|
|
list_move_tail(&stream_node->mList, &stream_buf_mgr->valid_stream_list);
|
|
|
|
if (stream_buf_mgr->need_wait_up_flag == 1) {
|
|
stream_buf_mgr->need_wait_up_flag = 0;
|
|
stream_buf_mgr->wait_bitstream_condition = 1;
|
|
wake_up(&stream_buf_mgr->wait_bitstream);
|
|
}
|
|
mutex_unlock(&stream_buf_mgr->mutex);
|
|
|
|
/* todo; */
|
|
return 0;
|
|
}
|
|
|
|
comp_callback_type venc_callback = {
|
|
.EventHandler = venc_event_handler,
|
|
.empty_in_buffer_done = rt_venc_empty_in_buffer_done,
|
|
.fill_out_buffer_done = rt_venc_fill_out_buffer_done,
|
|
};
|
|
|
|
static int thread_reset_high_fps(void *param)
|
|
{
|
|
int ret = 0;
|
|
int channel_id = 0;
|
|
video_recoder *recoder = &rt_media_devp->recoder[channel_id];
|
|
|
|
RT_LOGW("start");
|
|
/* set config: reset high fps */
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_SET_RESET_HIGH_FPS, NULL);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_POWER_LINE_FREQ failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
|
|
ioctl_start(recoder);
|
|
|
|
recoder->bReset_high_fps_finish = 1;
|
|
|
|
RT_LOGW("rt_media_devp->need_start_recoder = %p, %p",
|
|
rt_media_devp->need_start_recoder_1, rt_media_devp->need_start_recoder_2);
|
|
|
|
if (rt_media_devp->need_start_recoder_1) {
|
|
ioctl_start(rt_media_devp->need_start_recoder_1);
|
|
rt_media_devp->need_start_recoder_1 = NULL;
|
|
}
|
|
|
|
if (rt_media_devp->need_start_recoder_2) {
|
|
ioctl_start(rt_media_devp->need_start_recoder_2);
|
|
rt_media_devp->need_start_recoder_2 = NULL;
|
|
}
|
|
|
|
rt_media_devp->in_high_fps_status = 0;
|
|
RT_LOGW("finish");
|
|
return 0;
|
|
}
|
|
|
|
static int wdr_get_from_partition(struct vi_part_cfg *vi_part_cfg, int sensor_num)
|
|
{
|
|
#if defined CONFIG_ISP_SERVER_MELIS
|
|
int ret = 0;
|
|
void *vaddr = NULL;
|
|
int check_sign = -1;
|
|
SENSOR_ISP_CONFIG_S *sensor_isp_cfg;
|
|
|
|
#ifdef CONFIG_SUPPORT_THREE_CAMERA_MELIS
|
|
if (sensor_num == 1) {
|
|
check_sign = SENSOR_1_SIGN;
|
|
vaddr = vin_map_kernel(VIN_SENSOR1_RESERVE_ADDR, VIN_RESERVE_SIZE);
|
|
} else if (sensor_num == 0) {
|
|
check_sign = SENSOR_0_SIGN;
|
|
vaddr = vin_map_kernel(VIN_SENSOR0_RESERVE_ADDR, VIN_RESERVE_SIZE);
|
|
} else if (sensor_num == 2) {
|
|
check_sign = SENSOR_2_SIGN;
|
|
vaddr = vin_map_kernel(VIN_SENSOR2_RESERVE_ADDR, VIN_RESERVE_SIZE);
|
|
}
|
|
#else
|
|
if (sensor_num == 1) {
|
|
check_sign = SENSOR_1_SIGN;
|
|
vaddr = vin_map_kernel(VIN_SENSOR1_RESERVE_ADDR, VIN_RESERVE_SIZE);
|
|
} else {
|
|
check_sign = SENSOR_0_SIGN;
|
|
vaddr = vin_map_kernel(VIN_SENSOR0_RESERVE_ADDR, VIN_RESERVE_SIZE);
|
|
}
|
|
#endif
|
|
|
|
if (vaddr == NULL) {
|
|
RT_LOGE("%s:map 0x%x paddr err!!!", __func__, VIN_SENSOR0_RESERVE_ADDR);
|
|
ret = -EFAULT;
|
|
goto ekzalloc;
|
|
}
|
|
|
|
sensor_isp_cfg = (SENSOR_ISP_CONFIG_S *)vaddr;
|
|
|
|
/* check id */
|
|
if (sensor_isp_cfg->sign != check_sign) {
|
|
RT_LOGW("%s:sign is 0x%x but not 0x%x\n", __func__, sensor_isp_cfg->sign, check_sign);
|
|
ret = -EINVAL;
|
|
goto unmap;
|
|
}
|
|
|
|
vi_part_cfg->wdr = sensor_isp_cfg->wdr_mode > 1 ? 0 : sensor_isp_cfg->wdr_mode;
|
|
vi_part_cfg->width = sensor_isp_cfg->width;
|
|
vi_part_cfg->height = sensor_isp_cfg->height;
|
|
vi_part_cfg->venc_format = sensor_isp_cfg->venc_format > 2 ? 1 : (sensor_isp_cfg->venc_format == 0 ? 1 : sensor_isp_cfg->venc_format);
|
|
vi_part_cfg->flicker_mode = sensor_isp_cfg->flicker_mode > 2 ? 1 : sensor_isp_cfg->flicker_mode;
|
|
|
|
vi_part_cfg->fps = sensor_isp_cfg->fps <= 0 ? 15 : sensor_isp_cfg->fps;
|
|
|
|
RT_LOGS("wdr/width/height/vformat/flicker get from partiton is %d/%d/%d/%d %d %d %d\n",
|
|
sensor_isp_cfg->wdr_mode, sensor_isp_cfg->width,
|
|
sensor_isp_cfg->height, sensor_isp_cfg->venc_format,
|
|
vi_part_cfg->flicker_mode, vi_part_cfg->fps, sensor_isp_cfg->fps);
|
|
|
|
//sensor_isp_cfg->sign = 0xFFFFFFFF;
|
|
|
|
unmap:
|
|
vin_unmap_kernel(vaddr);
|
|
ekzalloc:
|
|
return ret;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
error_type vi_event_handler(
|
|
PARAM_IN comp_handle component,
|
|
PARAM_IN void *pAppData,
|
|
PARAM_IN comp_event_type eEvent,
|
|
PARAM_IN unsigned int nData1,
|
|
PARAM_IN unsigned int nData2,
|
|
PARAM_IN void *pEventData)
|
|
{
|
|
/*video_recoder *recoder = (video_recoder *)pAppData;*/
|
|
RT_LOGI("vi_event_handler, eEvent = %d", eEvent);
|
|
|
|
if (eEvent == COMP_EVENT_CMD_RESET_ISP_HIGH_FPS) {
|
|
struct sched_param param = {.sched_priority = 1 };
|
|
rt_media_devp->reset_high_fps_thread = kthread_create(thread_reset_high_fps,
|
|
rt_media_devp, "reset-high-fps");
|
|
sched_setscheduler(rt_media_devp->reset_high_fps_thread, SCHED_FIFO, ¶m);
|
|
wake_up_process(rt_media_devp->reset_high_fps_thread);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
error_type rt_vi_empty_in_buffer_done(
|
|
PARAM_IN comp_handle component,
|
|
PARAM_IN void *pAppData,
|
|
PARAM_IN comp_buffer_header_type *pBuffer)
|
|
{
|
|
/* todo; */
|
|
RT_LOGE("not support rt_vi_empty_in_buffer_done");
|
|
return -1;
|
|
}
|
|
|
|
error_type rt_vi_fill_out_buffer_done(
|
|
PARAM_IN comp_handle component,
|
|
PARAM_IN void *pAppData,
|
|
PARAM_IN comp_buffer_header_type *pBuffer)
|
|
{
|
|
/* todo; */
|
|
RT_LOGE("not support rt_vi_fill_out_buffer_done");
|
|
return -1;
|
|
}
|
|
|
|
comp_callback_type vi_callback = {
|
|
.EventHandler = vi_event_handler,
|
|
.empty_in_buffer_done = rt_vi_empty_in_buffer_done,
|
|
.fill_out_buffer_done = rt_vi_fill_out_buffer_done,
|
|
};
|
|
|
|
static int get_component_handle(video_recoder *recoder)
|
|
{
|
|
int ret = 0;
|
|
|
|
RT_LOGD("recoder->activate_vi_flag: %d", recoder->activate_vi_flag);
|
|
if (recoder->activate_vi_flag == 1) {
|
|
ret = comp_get_handle((comp_handle *)&recoder->vi_comp,
|
|
"video.vipp",
|
|
recoder,
|
|
&recoder->config,
|
|
&vi_callback);
|
|
if (ret != ERROR_TYPE_OK) {
|
|
RT_LOGE("get vi comp handle error: %d", ret);
|
|
return -1;
|
|
}
|
|
}
|
|
RT_LOGD("recoder->activate_venc_flag: %d", recoder->activate_venc_flag);
|
|
if (recoder->activate_venc_flag == 1) {
|
|
ret = comp_get_handle((comp_handle *)&recoder->venc_comp,
|
|
"video.encoder",
|
|
recoder,
|
|
&recoder->config,
|
|
&venc_callback);
|
|
if (ret != ERROR_TYPE_OK) {
|
|
RT_LOGE("get venc comp handle error: %d", ret);
|
|
return -1;
|
|
}
|
|
}
|
|
recoder->bcreate_comp_flag = 1;
|
|
|
|
return ret;
|
|
}
|
|
|
|
int fps_change_id_1;
|
|
int fps_change_id_2;
|
|
|
|
static void set_fps_change_channel_id_1(int id)
|
|
{
|
|
fps_change_id_1 = id;
|
|
}
|
|
|
|
int get_fps_change_channel_id_1(void)
|
|
{
|
|
return fps_change_id_1;
|
|
}
|
|
|
|
void rt_media_csi_fps_change_first(int change_fps)
|
|
{
|
|
int ret = 0;
|
|
int channel_id = get_fps_change_channel_id_1();
|
|
video_recoder *recoder = &rt_media_devp->recoder[channel_id];
|
|
|
|
if (change_fps <= 0 || change_fps > recoder->max_fps) {
|
|
RT_LOGW("IOCTL_SET_FPS: invalid change_fps[%d], setup to max_fps[%d]", change_fps, recoder->max_fps);
|
|
change_fps = recoder->max_fps;
|
|
}
|
|
|
|
RT_LOGI("IOCTL_SET_FPS: change_fps = %d, max_fps = %d, vi_comp = %p, venc_comp = %p",
|
|
change_fps, recoder->max_fps, recoder->vi_comp, recoder->venc_comp);
|
|
|
|
if (!recoder->vi_comp)
|
|
return;
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_SET_FPS, (void *)change_fps);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_FPS failed, ret = %d, change_fps = %d", ret, change_fps);
|
|
return ;
|
|
}
|
|
|
|
if (!recoder->venc_comp)
|
|
return;
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_Dynamic_SET_FPS, (void *)change_fps);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_FPS failed, ret = %d, change_fps = %d", ret, change_fps);
|
|
return ;
|
|
}
|
|
}
|
|
/* to do
|
|
static void set_fps_change_channel_id_2(int id)
|
|
{
|
|
fps_change_id_2 = id;
|
|
}*/
|
|
|
|
int get_fps_change_channel_id_2(void)
|
|
{
|
|
return fps_change_id_2;
|
|
}
|
|
void rt_media_csi_fps_change_second(int change_fps)
|
|
{
|
|
int ret = 0;
|
|
int channel_id = get_fps_change_channel_id_2();
|
|
video_recoder *recoder = &rt_media_devp->recoder[channel_id];
|
|
|
|
if (change_fps <= 0 || change_fps > recoder->max_fps) {
|
|
RT_LOGW("IOCTL_SET_FPS: invalid change_fps[%d], setup to max_fps[%d]", change_fps, recoder->max_fps);
|
|
change_fps = recoder->max_fps;
|
|
}
|
|
|
|
RT_LOGI("IOCTL_SET_FPS: change_fps = %d, max_fps = %d, vi_comp = %p, venc_comp = %p",
|
|
change_fps, recoder->max_fps, recoder->vi_comp, recoder->venc_comp);
|
|
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_SET_FPS, (void *)change_fps);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_FPS failed, ret = %d, change_fps = %d", ret, change_fps);
|
|
return ;
|
|
}
|
|
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_Dynamic_SET_FPS, (void *)change_fps);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_FPS failed, ret = %d, change_fps = %d", ret, change_fps);
|
|
return ;
|
|
}
|
|
}
|
|
|
|
static void rt_vin_sensor_fps_change_callback(int channel_id)
|
|
{
|
|
set_fps_change_channel_id_1(channel_id);
|
|
vin_sensor_fps_change_callback(channel_id, rt_media_csi_fps_change_first);
|
|
}
|
|
|
|
static void rt_tdm_buffer_done_callback(struct vin_isp_tdm_event_status *status)
|
|
{
|
|
tdm_data_manager *p_tdm_data_manager = NULL;
|
|
tdm_data_node *p_tdm_note = NULL;
|
|
unsigned long flags;
|
|
|
|
//RT_LOGW("tdm%d iommu_buf %p buf_size %d buf_id %d", status->dev_id, status->iommu_buf, status->buf_size, status->buf_id);
|
|
|
|
if (status->dev_id < MAX_SENSOR_NUM)
|
|
p_tdm_data_manager = &rt_media_devp->st_tdm_data_manager[status->dev_id];
|
|
else {
|
|
RT_LOGE("dev_id not support %d", status->dev_id);
|
|
return ;
|
|
}
|
|
|
|
if (0 == p_tdm_data_manager->b_inited) {
|
|
RT_LOGW("tdm%d data manager is not inited!", status->dev_id);
|
|
return ;
|
|
}
|
|
|
|
spin_lock_irqsave(&p_tdm_data_manager->s_lock, flags);
|
|
|
|
if (list_empty(&p_tdm_data_manager->empty_list)) {
|
|
RT_LOGW("empty list is null, tdm%d drop data!", status->dev_id);
|
|
spin_unlock_irqrestore(&p_tdm_data_manager->s_lock, flags);
|
|
return ;
|
|
}
|
|
p_tdm_note = list_first_entry(&p_tdm_data_manager->empty_list, tdm_data_node, mList);
|
|
memcpy(&p_tdm_note->tdm_data, status, sizeof(struct vin_isp_tdm_event_status));
|
|
|
|
p_tdm_data_manager->empty_num--;
|
|
list_move_tail(&p_tdm_note->mList, &p_tdm_data_manager->valid_list);
|
|
|
|
spin_unlock_irqrestore(&p_tdm_data_manager->s_lock, flags);
|
|
|
|
return ;
|
|
}
|
|
|
|
static void rt_tdm_get_buf(struct vin_isp_tdm_event_status *status)
|
|
{
|
|
tdm_data_node *p_tdm_note = NULL;
|
|
tdm_data_manager *p_tdm_data_manager = NULL;
|
|
|
|
if (status->dev_id < MAX_SENSOR_NUM)
|
|
p_tdm_data_manager = &rt_media_devp->st_tdm_data_manager[status->dev_id];
|
|
else {
|
|
RT_LOGE("dev_id not support %d", status->dev_id);
|
|
return ;
|
|
}
|
|
|
|
if (0 == p_tdm_data_manager->b_inited) {
|
|
RT_LOGW("tdm%d data manager is not inited!", status->dev_id);
|
|
return ;
|
|
}
|
|
|
|
spin_lock(&p_tdm_data_manager->s_lock);
|
|
|
|
if (list_empty(&p_tdm_data_manager->valid_list)) {
|
|
RT_LOGD("tdm valid list is null");
|
|
spin_unlock(&p_tdm_data_manager->s_lock);
|
|
return ;
|
|
}
|
|
p_tdm_note = list_first_entry(&p_tdm_data_manager->valid_list, tdm_data_node, mList);
|
|
|
|
list_move_tail(&p_tdm_note->mList, &p_tdm_data_manager->empty_list);
|
|
p_tdm_data_manager->empty_num++;
|
|
|
|
spin_unlock(&p_tdm_data_manager->s_lock);
|
|
memcpy(status, &p_tdm_note->tdm_data, sizeof(struct vin_isp_tdm_event_status));
|
|
|
|
//RT_LOGW("tdm%d get buf[%d] %p %d", status->dev_id, status->buf_id, status->iommu_buf, status->buf_size);
|
|
|
|
return ;
|
|
}
|
|
|
|
static void fill_venc_config(venc_comp_base_config *pvenc_config, video_recoder *recoder)
|
|
{
|
|
rt_media_config_s *media_config = &recoder->config;
|
|
|
|
/* setup venc config */
|
|
if (media_config->encodeType == 0)
|
|
pvenc_config->codec_type = RT_VENC_CODEC_H264;
|
|
else if (media_config->encodeType == 1)
|
|
pvenc_config->codec_type = RT_VENC_CODEC_JPEG;
|
|
else if (media_config->encodeType == 2)
|
|
pvenc_config->codec_type = RT_VENC_CODEC_H265;
|
|
else {
|
|
RT_LOGE("codec_type[%d] not support, use h264", media_config->encodeType);
|
|
pvenc_config->codec_type = RT_VENC_CODEC_H264;
|
|
}
|
|
|
|
pvenc_config->qp_range = media_config->qp_range;
|
|
pvenc_config->profile = media_config->profile;
|
|
pvenc_config->level = media_config->level;
|
|
pvenc_config->src_width = media_config->width;
|
|
if (media_config->en_16_align_fill_data) {
|
|
pvenc_config->src_height = RT_ALIGN(media_config->height, 16);
|
|
} else {
|
|
pvenc_config->src_height = media_config->height;
|
|
}
|
|
pvenc_config->dst_width = media_config->dst_width;
|
|
pvenc_config->dst_height = media_config->dst_height;
|
|
pvenc_config->frame_rate = media_config->dst_fps;
|
|
pvenc_config->product_mode = media_config->product_mode;
|
|
pvenc_config->bit_rate = media_config->bitrate * 1024;
|
|
pvenc_config->vbv_thresh_size = media_config->vbv_thresh_size;
|
|
pvenc_config->vbv_buf_size = media_config->vbv_buf_size;
|
|
pvenc_config->pixelformat = recoder->pixelformat;
|
|
pvenc_config->outputformat = media_config->outputformat;
|
|
pvenc_config->max_keyframe_interval = media_config->gop;
|
|
pvenc_config->enable_overlay = media_config->enable_overlay;
|
|
pvenc_config->channel_id = media_config->channelId;
|
|
pvenc_config->quality = media_config->jpg_quality;
|
|
pvenc_config->jpg_mode = media_config->jpg_mode;
|
|
pvenc_config->bit_rate_range.bitRateMax = media_config->bit_rate_range.bitRateMax * 1024;
|
|
pvenc_config->bit_rate_range.bitRateMin = media_config->bit_rate_range.bitRateMin * 1024;
|
|
pvenc_config->bOnlineChannel = media_config->bonline_channel;
|
|
pvenc_config->share_buf_num = media_config->share_buf_num;
|
|
pvenc_config->en_encpp_sharp = media_config->enable_sharp;
|
|
pvenc_config->breduce_refrecmem = media_config->breduce_refrecmem;
|
|
|
|
memcpy(&pvenc_config->s_crop_info, &media_config->s_crop_info, sizeof(RTCropInfo));
|
|
memcpy(&pvenc_config->venc_video_signal, &media_config->venc_video_signal, sizeof(VencH264VideoSignal));
|
|
|
|
if (media_config->vbr == 0)
|
|
pvenc_config->rc_mode = VENC_COMP_RC_MODE_CBR;
|
|
else if (media_config->vbr == 1) {
|
|
pvenc_config->rc_mode = VENC_COMP_RC_MODE_VBR;
|
|
pvenc_config->vbr_param.uMaxBitRate = media_config->vbr_param.uMaxBitRate;
|
|
pvenc_config->vbr_param.nMovingTh = media_config->vbr_param.nMovingTh;
|
|
pvenc_config->vbr_param.nQuality = media_config->vbr_param.nQuality;
|
|
pvenc_config->vbr_param.nIFrmBitsCoef = media_config->vbr_param.nIFrmBitsCoef;
|
|
pvenc_config->vbr_param.nPFrmBitsCoef = media_config->vbr_param.nPFrmBitsCoef;
|
|
} else {
|
|
RT_LOGE("media_config->vbr[%d] not support, use cbr", media_config->vbr);
|
|
pvenc_config->rc_mode = VENC_COMP_RC_MODE_CBR;
|
|
}
|
|
if (rt_is_format422(pvenc_config->pixelformat)) {
|
|
pvenc_config->en_encpp_sharp = 0;
|
|
}
|
|
pvenc_config->enable_ve_isp_linkage = media_config->enable_ve_isp_linkage;
|
|
pvenc_config->skip_sharp_param_frame_num = media_config->skip_sharp_param_frame_num;
|
|
if ((media_config->ve_encpp_sharp_atten_coef_per < 0) || (media_config->ve_encpp_sharp_atten_coef_per > 100)) {
|
|
RT_LOGE("invalid encpp_sharp_atten_coef_per %d use dafault 0!",
|
|
media_config->ve_encpp_sharp_atten_coef_per);
|
|
pvenc_config->encpp_sharp_atten_coef_per = 0;
|
|
} else
|
|
pvenc_config->encpp_sharp_atten_coef_per = media_config->ve_encpp_sharp_atten_coef_per;
|
|
}
|
|
|
|
static void flush_stream_buff(video_recoder *recoder)
|
|
{
|
|
video_stream_s *video_stream = NULL;
|
|
|
|
video_stream = ioctl_get_stream_data(recoder);
|
|
|
|
while (video_stream) {
|
|
ioctl_return_stream_data(recoder, video_stream);
|
|
|
|
video_stream = ioctl_get_stream_data(recoder);
|
|
}
|
|
}
|
|
|
|
static int rt_init_tdm_manager(tdm_data_manager *p_tdm_data_manager, const rt_media_config_s *rt_config)
|
|
{
|
|
int i = 0;
|
|
//init tdm buffer list manager.
|
|
spin_lock_init(&p_tdm_data_manager->s_lock);
|
|
if (rt_config->tdm_rxbuf_cnt)
|
|
p_tdm_data_manager->empty_num = rt_config->tdm_rxbuf_cnt;
|
|
else
|
|
p_tdm_data_manager->empty_num = 5;//default 5 num
|
|
|
|
INIT_LIST_HEAD(&p_tdm_data_manager->empty_list);
|
|
INIT_LIST_HEAD(&p_tdm_data_manager->valid_list);
|
|
for (i = 0; i < p_tdm_data_manager->empty_num; i++) {
|
|
tdm_data_node *pNode = kmalloc(sizeof(tdm_data_node), GFP_KERNEL);
|
|
|
|
if (pNode == NULL) {
|
|
RT_LOGE("fatal error! kmalloc fail!");
|
|
return ERROR_TYPE_NOMEM;
|
|
}
|
|
memset(pNode, 0, sizeof(tdm_data_node));
|
|
list_add_tail(&pNode->mList, &p_tdm_data_manager->empty_list);
|
|
}
|
|
p_tdm_data_manager->b_inited = 1;
|
|
return 0;
|
|
}
|
|
|
|
int ioctl_init(video_recoder *recoder)
|
|
{
|
|
int i = 0;
|
|
int ret = 0;
|
|
stream_buffer_manager *stream_buf_mgr = &recoder->stream_buf_manager;
|
|
|
|
ret = get_component_handle(recoder);
|
|
|
|
/* init stream buf manager*/
|
|
mutex_init(&stream_buf_mgr->mutex);
|
|
stream_buf_mgr->empty_num = VENC_OUT_BUFFER_LIST_NODE_NUM;
|
|
INIT_LIST_HEAD(&stream_buf_mgr->empty_stream_list);
|
|
INIT_LIST_HEAD(&stream_buf_mgr->valid_stream_list);
|
|
INIT_LIST_HEAD(&stream_buf_mgr->caller_hold_stream_list);
|
|
for (i = 0; i < VENC_OUT_BUFFER_LIST_NODE_NUM; i++) {
|
|
video_stream_node *pNode = kmalloc(sizeof(video_stream_node), GFP_KERNEL);
|
|
|
|
if (pNode == NULL) {
|
|
RT_LOGE("fatal error! kmalloc fail!");
|
|
return ERROR_TYPE_NOMEM;
|
|
}
|
|
memset(pNode, 0, sizeof(video_stream_node));
|
|
list_add_tail(&pNode->mList, &stream_buf_mgr->empty_stream_list);
|
|
}
|
|
init_waitqueue_head(&stream_buf_mgr->wait_bitstream);
|
|
|
|
//init tdm buffer list manager.
|
|
#if defined CONFIG_RT_MEDIA_SINGEL_SENSOR || defined CONFIG_RT_MEDIA_DUAL_SENSOR || defined CONFIG_RT_MEDIA_THREE_SENSOR
|
|
if (recoder->config.enable_aiisp && recoder->config.channelId == CSI_SENSOR_0_VIPP_0)
|
|
rt_init_tdm_manager(&rt_media_devp->st_tdm_data_manager[0], &recoder->config);
|
|
#endif
|
|
#if defined CONFIG_RT_MEDIA_DUAL_SENSOR || defined CONFIG_RT_MEDIA_THREE_SENSOR
|
|
if (recoder->config.enable_aiisp && recoder->config.channelId == CSI_SENSOR_1_VIPP_0)
|
|
rt_init_tdm_manager(&rt_media_devp->st_tdm_data_manager[1], &recoder->config);
|
|
#endif
|
|
#if defined CONFIG_RT_MEDIA_THREE_SENSOR
|
|
if (recoder->config.enable_aiisp && recoder->config.channelId == CSI_SENSOR_2_VIPP_0)
|
|
rt_init_tdm_manager(&rt_media_devp->st_tdm_data_manager[2], &recoder->config);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
int ioctl_config(video_recoder *recoder, rt_media_config_s *config)
|
|
{
|
|
int connect_flag = 0;
|
|
venc_comp_base_config venc_config;
|
|
vi_comp_base_config vi_config;
|
|
rt_media_config_s *media_config = &recoder->config;
|
|
ve_proc_setting_info proc_ve_info;
|
|
RT_LOGD("Ryan kernel rt-media config recoder->config.output_mode: %d", recoder->config.output_mode);
|
|
|
|
if (bvin_is_ready_rt_not_probe[config->channelId]) {
|
|
int i = 0;
|
|
for (; i < VIDEO_INPUT_CHANNEL_NUM; i++) {
|
|
if (g_csi_status_pair[i].bset) {
|
|
rt_media_devp->bcsi_status_set[i] = g_csi_status_pair[i].status;
|
|
}
|
|
}
|
|
}
|
|
/*LOG_LEVEL_VERBOSE = 2,
|
|
LOG_LEVEL_DEBUG = 3,
|
|
LOG_LEVEL_INFO = 4,
|
|
LOG_LEVEL_WARNING = 5,
|
|
LOG_LEVEL_ERROR = 6,*/
|
|
cdc_log_set_level(CONFIG_RT_MEDIA_CDC_LOG_LEVEL);
|
|
|
|
if (config->vin_buf_num < CONFIG_YUV_BUF_NUM)
|
|
config->vin_buf_num = CONFIG_YUV_BUF_NUM;
|
|
|
|
memset(&venc_config, 0, sizeof(venc_comp_base_config));
|
|
memset(&vi_config, 0, sizeof(vi_comp_base_config));
|
|
memset(&proc_ve_info, 0, sizeof(ve_proc_setting_info));
|
|
|
|
venc_config.channel_id = recoder->config.channelId;
|
|
if (media_config == NULL) {
|
|
RT_LOGE("ioctl_config: param is null");
|
|
return -1;
|
|
}
|
|
|
|
if (recoder->state != RT_MEDIA_STATE_IDLE) {
|
|
RT_LOGW("channel %d the state[%d] is not idle", config->channelId, recoder->state);
|
|
return 0;
|
|
}
|
|
cedar_get_ve_setting_info(&proc_ve_info, config->channelId);
|
|
if (proc_ve_info.bve_proc_setting) {
|
|
if (proc_ve_info.src_w && proc_ve_info.src_h) {
|
|
config->width = proc_ve_info.src_w;
|
|
config->height = proc_ve_info.src_h;
|
|
config->dst_width = proc_ve_info.src_w;
|
|
config->dst_height = proc_ve_info.src_h;
|
|
RT_LOGW("get from ve proc w %d h %d", config->width, config->height);
|
|
}
|
|
}
|
|
|
|
if (config->dst_width == 0 || config->dst_height == 0) {
|
|
config->dst_width = config->width;
|
|
config->dst_height = config->height;
|
|
}
|
|
|
|
if (config->dst_fps == 0) {
|
|
config->dst_fps = config->fps;
|
|
}
|
|
|
|
memcpy(media_config, config, sizeof(rt_media_config_s));
|
|
|
|
/* set the init-config-fps as max_fps */
|
|
recoder->max_fps = media_config->fps;
|
|
|
|
if (media_config->channelId < 0 || media_config->channelId > (VIDEO_INPUT_CHANNEL_NUM - 1)) {
|
|
RT_LOGE("channel[%d] is error", media_config->channelId);
|
|
return -1;
|
|
}
|
|
RT_LOGD("recoder->activate_vi_flag: %d recoder->config.output_mode: %d", recoder->activate_vi_flag, recoder->config.output_mode);
|
|
if (recoder->config.output_mode == OUTPUT_MODE_STREAM) {
|
|
recoder->activate_venc_flag = 1;
|
|
recoder->activate_vi_flag = 1;
|
|
} else if (recoder->config.output_mode == OUTPUT_MODE_YUV) {
|
|
recoder->activate_venc_flag = 0;
|
|
recoder->activate_vi_flag = 1;
|
|
} else if (recoder->config.output_mode == OUTPUT_MODE_ENCODE_FILE_YUV
|
|
|| recoder->config.output_mode == OUTPUT_MODE_ENCODE_OUTSIDE_YUV) {
|
|
recoder->activate_venc_flag = 1;
|
|
recoder->activate_vi_flag = 0;
|
|
}
|
|
|
|
RT_LOGD("recoder->activate_vi_flag: %d", recoder->activate_vi_flag);
|
|
if (recoder->state == RT_MEDIA_STATE_IDLE)
|
|
ioctl_init(recoder);
|
|
|
|
#if defined CONFIG_RT_MEDIA_SETUP_RECORDER_IN_KERNEL && defined CONFIG_VIDEO_RT_MEDIA
|
|
RT_LOGW("CONFIG_RT_MEDIA_SETUP_RECORDER_IN_KERNEL = %d, configSize = %d",
|
|
CONFIG_RT_MEDIA_SETUP_RECORDER_IN_KERNEL, sizeof(rt_media_config_s));
|
|
#else
|
|
RT_LOGW("CONFIG_RT_MEDIA_SETUP_RECORDER_IN_KERNEL id not enable, configSize = %d", sizeof(rt_media_config_s));
|
|
#endif
|
|
|
|
RT_LOGW("out_mode = %d, activate_venc = %d, vi = %d, venc_comp = %p, vi = %p, max_fps = %d",
|
|
recoder->config.output_mode,
|
|
recoder->activate_venc_flag, recoder->activate_vi_flag,
|
|
recoder->venc_comp, recoder->vi_comp, recoder->max_fps);
|
|
|
|
if (recoder->config.pixelformat == RT_PIXEL_NUM) {
|
|
if (recoder->config.output_mode == OUTPUT_MODE_STREAM)
|
|
recoder->pixelformat = RT_PIXEL_LBC_25X;
|
|
else
|
|
recoder->pixelformat = RT_PIXEL_YVU420SP; //* nv21
|
|
}
|
|
else {
|
|
recoder->pixelformat = recoder->config.pixelformat;
|
|
}
|
|
|
|
fill_venc_config(&venc_config, recoder);
|
|
|
|
/* setup vipp config */
|
|
vi_config.width = media_config->width;
|
|
vi_config.height = media_config->height;
|
|
vi_config.frame_rate = media_config->fps;
|
|
vi_config.dst_fps = media_config->dst_fps;
|
|
vi_config.channel_id = media_config->channelId;
|
|
vi_config.output_mode = media_config->output_mode;
|
|
vi_config.pixelformat = recoder->pixelformat;
|
|
vi_config.enable_wdr = media_config->enable_wdr;
|
|
vi_config.drop_frame_num = media_config->drop_frame_num;
|
|
vi_config.bonline_channel = media_config->bonline_channel;
|
|
vi_config.share_buf_num = media_config->share_buf_num;
|
|
vi_config.en_16_align_fill_data = media_config->en_16_align_fill_data;
|
|
vi_config.vin_buf_num = media_config->vin_buf_num;
|
|
vi_config.enable_aiisp = media_config->enable_aiisp;
|
|
vi_config.tdm_rxbuf_cnt = media_config->tdm_rxbuf_cnt;
|
|
|
|
if (media_config->dst_fps < media_config->fps) {
|
|
vi_config.st_adapter_venc_fps.enable = 1;
|
|
vi_config.st_adapter_venc_fps.frame_cnt = -1;
|
|
vi_config.st_adapter_venc_fps.dst_fps = config->dst_fps;
|
|
} else if (config->dst_fps > config->fps) {
|
|
RT_LOGW("Notice dst_fps[%d] > src_fps[%d]", media_config->dst_fps, media_config->fps);
|
|
}
|
|
|
|
memcpy(&vi_config.venc_video_signal, &media_config->venc_video_signal, sizeof(VencH264VideoSignal));
|
|
|
|
RT_LOGI("enable_wdr = %d, %d", media_config->enable_wdr, vi_config.enable_wdr);
|
|
if (recoder->vi_comp)
|
|
comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Base, &vi_config);
|
|
|
|
if (recoder->venc_comp)
|
|
comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_Base, &venc_config);
|
|
|
|
if (recoder->vi_comp && recoder->venc_comp) {
|
|
connect_flag = 1;
|
|
comp_setup_tunnel(recoder->venc_comp, COMP_INPUT_PORT, recoder->vi_comp, connect_flag);
|
|
comp_setup_tunnel(recoder->vi_comp, COMP_OUTPUT_PORT, recoder->venc_comp, connect_flag);
|
|
}
|
|
if (recoder->vi_comp) {
|
|
if (comp_init(recoder->vi_comp) != 0) {
|
|
RT_LOGE("comp_init error");
|
|
return -1;
|
|
}
|
|
}
|
|
RT_LOGD("ch%d enable_aiisp:%d", config->channelId, media_config->enable_aiisp);
|
|
if (media_config->enable_aiisp) {
|
|
vin_register_tdmbuffer_done_callback(config->channelId, rt_tdm_buffer_done_callback);
|
|
}
|
|
if (media_config->width == 0 || media_config->height == 0) {
|
|
vi_comp_base_config tmp_vi_config;
|
|
|
|
RT_LOGW("err, width x height: %d %d", media_config->width, media_config->height);
|
|
comp_get_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_GET_BASE_CONFIG, &tmp_vi_config);
|
|
media_config->width = tmp_vi_config.width;
|
|
media_config->height = tmp_vi_config.height;
|
|
if (media_config->dst_width == 0 || media_config->dst_height == 0) {
|
|
media_config->dst_width = media_config->width;
|
|
media_config->dst_height = media_config->height;
|
|
}
|
|
venc_config.src_width = media_config->width;
|
|
venc_config.src_height = media_config->height;
|
|
venc_config.dst_width = media_config->dst_width;
|
|
venc_config.dst_height = media_config->dst_height;
|
|
if (recoder->venc_comp)
|
|
comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_Base, &venc_config);
|
|
if (recoder->vi_comp)
|
|
comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Base, &tmp_vi_config);
|
|
}
|
|
RT_LOGI("begin init venc comp");
|
|
//* init venc comp
|
|
if (recoder->venc_comp) {
|
|
comp_init(recoder->venc_comp);
|
|
|
|
// RT_LOGI("media_config->enable_bin_image = %d, th = %d",
|
|
// media_config->enable_bin_image, media_config->bin_image_moving_th);
|
|
// if (media_config->enable_bin_image == 1) {
|
|
// rt_venc_bin_image_param bin_param;
|
|
//
|
|
// bin_param.enable = 1;
|
|
// bin_param.moving_th = media_config->bin_image_moving_th;
|
|
// comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_ENABLE_BIN_IMAGE, &bin_param);
|
|
// }
|
|
// if (media_config->enable_mv_info == 1)
|
|
// comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_ENABLE_MV_INFO, &media_config->enable_mv_info);
|
|
}
|
|
|
|
if (vi_config.st_adapter_venc_fps.enable == 0 && recoder->activate_vi_flag)
|
|
rt_vin_sensor_fps_change_callback(media_config->channelId);
|
|
|
|
if (recoder->config.output_mode == OUTPUT_MODE_ENCODE_FILE_YUV
|
|
|| recoder->config.output_mode == OUTPUT_MODE_ENCODE_OUTSIDE_YUV) {
|
|
recoder->enc_yuv_phy_addr = NULL;
|
|
mutex_init(&recoder->yuv_mutex);
|
|
}
|
|
recoder->state = RT_MEDIA_STATE_CONFIGED;
|
|
RT_LOGI("ioctl_config finish");
|
|
return 0;
|
|
}
|
|
|
|
int ioctl_start(video_recoder *recoder)
|
|
{
|
|
RT_LOGI("ioctl_start begin");
|
|
if (recoder->state != RT_MEDIA_STATE_CONFIGED && recoder->state != RT_MEDIA_STATE_PAUSE) {
|
|
RT_LOGW("channel %d ioctl_start: state[%d] is not right", recoder->config.channelId, recoder->state);
|
|
return -1;
|
|
}
|
|
|
|
/* int64_t time_end = get_cur_time(); */
|
|
|
|
|
|
/* start vi comp */
|
|
/*int64_t time_start = get_cur_time(); */
|
|
if (recoder->vi_comp)
|
|
comp_start(recoder->vi_comp);
|
|
/* start venc */
|
|
if (recoder->venc_comp)
|
|
comp_start(recoder->venc_comp);
|
|
/*
|
|
int64_t time_end_1 = get_cur_time();
|
|
|
|
RT_LOGD("time[vi start] = %lld, time[venc start] = %lld",
|
|
(time_end - time_start), (time_end_1 - time_end));
|
|
*/
|
|
|
|
RT_LOGI("ioctl_start finish");
|
|
recoder->state = RT_MEDIA_STATE_EXCUTING;
|
|
return 0;
|
|
}
|
|
|
|
int ioctl_pause(video_recoder *recoder)
|
|
{
|
|
if (recoder->state != RT_MEDIA_STATE_EXCUTING) {
|
|
RT_LOGE("ioctl_start: state[%d] is not right", recoder->state);
|
|
return -1;
|
|
}
|
|
|
|
RT_LOGD("comp_pause vi start");
|
|
/* todo : pause vi comp */
|
|
if (recoder->vi_comp)
|
|
comp_pause(recoder->vi_comp);
|
|
RT_LOGD("comp_pause vi end");
|
|
|
|
/* pause venc */
|
|
if (recoder->venc_comp)
|
|
comp_pause(recoder->venc_comp);
|
|
|
|
RT_LOGD("comp_pause venc end");
|
|
|
|
recoder->state = RT_MEDIA_STATE_PAUSE;
|
|
return 0;
|
|
}
|
|
|
|
static void rt_destroy_tdm_list(tdm_data_manager *p_tdm_data_manager)
|
|
{
|
|
tdm_data_node *p_tdm_node = NULL;
|
|
int free_cout = 0;
|
|
while ((!list_empty(&p_tdm_data_manager->empty_list))) {
|
|
p_tdm_node = list_first_entry(&p_tdm_data_manager->empty_list, tdm_data_node, mList);
|
|
if (p_tdm_node) {
|
|
free_cout++;
|
|
list_del(&p_tdm_node->mList);
|
|
kfree(p_tdm_node);
|
|
}
|
|
}
|
|
|
|
while ((!list_empty(&p_tdm_data_manager->valid_list))) {
|
|
p_tdm_node = list_first_entry(&p_tdm_data_manager->valid_list, tdm_data_node, mList);
|
|
if (p_tdm_node) {
|
|
free_cout++;
|
|
list_del(&p_tdm_node->mList);
|
|
kfree(p_tdm_node);
|
|
}
|
|
}
|
|
p_tdm_data_manager->b_inited = 0;
|
|
|
|
RT_LOGW("tdm date free cnt %d", free_cout);
|
|
}
|
|
|
|
int ioctl_destroy(video_recoder *recoder)
|
|
{
|
|
/* todo */
|
|
video_stream_node *stream_node = NULL;
|
|
int free_stream_cout = 0;
|
|
|
|
if (recoder->state == RT_MEDIA_STATE_IDLE) {
|
|
RT_LOGW("state is RT_MEDIA_STATE_IDLE, dont need destroy!");
|
|
return -1;
|
|
}
|
|
|
|
/*free the comp*/
|
|
if (recoder->venc_comp) {
|
|
comp_stop(recoder->venc_comp);
|
|
comp_free_handle(recoder->venc_comp);
|
|
recoder->venc_comp = NULL;
|
|
}
|
|
if (recoder->vi_comp) {
|
|
comp_stop(recoder->vi_comp);
|
|
comp_free_handle(recoder->vi_comp);
|
|
recoder->vi_comp = NULL;
|
|
}
|
|
|
|
mutex_destroy(&recoder->stream_buf_manager.mutex);
|
|
if (recoder->config.output_mode == OUTPUT_MODE_ENCODE_FILE_YUV
|
|
|| recoder->config.output_mode == OUTPUT_MODE_ENCODE_OUTSIDE_YUV) {
|
|
mutex_destroy(&recoder->yuv_mutex);
|
|
recoder->enc_yuv_phy_addr = NULL;
|
|
}
|
|
while ((!list_empty(&recoder->stream_buf_manager.empty_stream_list))) {
|
|
stream_node = list_first_entry(&recoder->stream_buf_manager.empty_stream_list, video_stream_node, mList);
|
|
if (stream_node) {
|
|
free_stream_cout++;
|
|
list_del(&stream_node->mList);
|
|
kfree(stream_node);
|
|
}
|
|
}
|
|
|
|
while ((!list_empty(&recoder->stream_buf_manager.valid_stream_list))) {
|
|
stream_node = list_first_entry(&recoder->stream_buf_manager.valid_stream_list, video_stream_node, mList);
|
|
if (stream_node) {
|
|
free_stream_cout++;
|
|
list_del(&stream_node->mList);
|
|
kfree(stream_node);
|
|
}
|
|
}
|
|
|
|
while ((!list_empty(&recoder->stream_buf_manager.caller_hold_stream_list))) {
|
|
stream_node = list_first_entry(&recoder->stream_buf_manager.caller_hold_stream_list, video_stream_node, mList);
|
|
if (stream_node) {
|
|
free_stream_cout++;
|
|
list_del(&stream_node->mList);
|
|
kfree(stream_node);
|
|
}
|
|
}
|
|
|
|
RT_LOGD("free_stream_cout = %d", free_stream_cout);
|
|
|
|
if (free_stream_cout != VENC_OUT_BUFFER_LIST_NODE_NUM)
|
|
RT_LOGE("free num of stream node is not match: %d, %d", free_stream_cout, VENC_OUT_BUFFER_LIST_NODE_NUM);
|
|
|
|
if (recoder->mNLDstPid != 0) {
|
|
recoder->mNLDstPid = 0;
|
|
}
|
|
|
|
if (recoder->config.enable_aiisp)
|
|
vin_register_tdmbuffer_done_callback(recoder->config.channelId, NULL);
|
|
|
|
#if defined CONFIG_RT_MEDIA_SINGEL_SENSOR || defined CONFIG_RT_MEDIA_DUAL_SENSOR || defined CONFIG_RT_MEDIA_THREE_SENSOR
|
|
if (recoder->config.enable_aiisp && recoder->config.channelId == CSI_SENSOR_0_VIPP_0)
|
|
rt_destroy_tdm_list(&rt_media_devp->st_tdm_data_manager[0]);
|
|
#endif
|
|
#if defined CONFIG_RT_MEDIA_DUAL_SENSOR || defined CONFIG_RT_MEDIA_THREE_SENSOR
|
|
if (recoder->config.enable_aiisp && recoder->config.channelId == CSI_SENSOR_1_VIPP_0)
|
|
rt_destroy_tdm_list(&rt_media_devp->st_tdm_data_manager[1]);
|
|
#endif
|
|
#if defined CONFIG_RT_MEDIA_THREE_SENSOR
|
|
if (recoder->config.enable_aiisp && recoder->config.channelId == CSI_SENSOR_2_VIPP_0)
|
|
rt_destroy_tdm_list(&rt_media_devp->st_tdm_data_manager[2]);
|
|
#endif
|
|
|
|
recoder->state = RT_MEDIA_STATE_IDLE;
|
|
recoder->enable_high_fps = 0;
|
|
recoder->bReset_high_fps_finish = 0;
|
|
|
|
if (recoder->motion_region) {
|
|
kfree(recoder->motion_region);
|
|
recoder->motion_region = NULL;
|
|
recoder->motion_region_len = 0;
|
|
}
|
|
|
|
if (recoder->region_d3d_region) {
|
|
kfree(recoder->region_d3d_region);
|
|
recoder->region_d3d_region = NULL;
|
|
recoder->region_d3d_region_len = 0;
|
|
}
|
|
|
|
if (recoder->insert_data.pBuffer) {
|
|
kfree(recoder->insert_data.pBuffer);
|
|
recoder->insert_data.pBuffer = NULL;
|
|
recoder->insert_data.nDataLen = 0;
|
|
recoder->insert_data.nBufLen = 0;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static int ioctl_get_vbv_buf_info(video_recoder *recoder,
|
|
KERNEL_VBV_BUFFER_INFO *vbv_buf_info)
|
|
{
|
|
error_type error = ERROR_TYPE_OK;
|
|
KERNEL_VBV_BUFFER_INFO venc_vbv_info;
|
|
|
|
memset(&venc_vbv_info, 0, sizeof(KERNEL_VBV_BUFFER_INFO));
|
|
|
|
error = comp_get_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_GET_VBV_BUF_INFO, &venc_vbv_info);
|
|
if (error != ERROR_TYPE_OK) {
|
|
RT_LOGI("get vbv buf info failed");
|
|
return -1;
|
|
}
|
|
|
|
vbv_buf_info->share_fd = venc_vbv_info.share_fd;
|
|
vbv_buf_info->size = venc_vbv_info.size;
|
|
return 0;
|
|
}
|
|
|
|
static int ioctl_get_stream_header(video_recoder *recoder, venc_comp_header_data *header_data)
|
|
{
|
|
error_type error = ERROR_TYPE_OK;
|
|
|
|
RT_LOGD("call comp_get_config start");
|
|
error = comp_get_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_GET_STREAM_HEADER, header_data);
|
|
RT_LOGD("call comp_get_config finish, error = %d", error);
|
|
|
|
if (error != ERROR_TYPE_OK) {
|
|
RT_LOGW("get vbv buf info failed");
|
|
return -1;
|
|
}
|
|
|
|
RT_LOGD("ioctl_get_header_data: size = %d, data = %p\n",
|
|
header_data->nLength, header_data->pBuffer);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* valid_list --> caller_hold_list */
|
|
static video_stream_s *ioctl_get_stream_data(video_recoder *recoder)
|
|
{
|
|
video_stream_node *stream_node = NULL;
|
|
stream_buffer_manager *stream_buf_mgr = &recoder->stream_buf_manager;
|
|
|
|
mutex_lock(&stream_buf_mgr->mutex);
|
|
|
|
if (list_empty(&stream_buf_mgr->valid_stream_list)) {
|
|
RT_LOGD("stream buf valid list is null");
|
|
mutex_unlock(&stream_buf_mgr->mutex);
|
|
return NULL;
|
|
}
|
|
stream_node = list_first_entry(&stream_buf_mgr->valid_stream_list, video_stream_node, mList);
|
|
|
|
list_move_tail(&stream_node->mList, &stream_buf_mgr->caller_hold_stream_list);
|
|
|
|
mutex_unlock(&stream_buf_mgr->mutex);
|
|
|
|
return &stream_node->video_stream;
|
|
}
|
|
|
|
/* caller_hold_list --> empty_list*/
|
|
static int ioctl_return_stream_data(video_recoder *recoder,
|
|
video_stream_s *video_stream)
|
|
{
|
|
video_stream_node *stream_node = NULL;
|
|
stream_buffer_manager *stream_buf_mgr = &recoder->stream_buf_manager;
|
|
comp_buffer_header_type buffer_header;
|
|
video_stream_s mvideo_stream;
|
|
|
|
memset(&mvideo_stream, 0, sizeof(video_stream_s));
|
|
memset(&buffer_header, 0, sizeof(comp_buffer_header_type));
|
|
|
|
mutex_lock(&stream_buf_mgr->mutex);
|
|
|
|
if (list_empty(&stream_buf_mgr->caller_hold_stream_list)) {
|
|
RT_LOGW("ioctl_return_stream_data: error, caller_hold_list is null");
|
|
mutex_unlock(&stream_buf_mgr->mutex);
|
|
return -1;
|
|
}
|
|
|
|
stream_node = list_first_entry(&stream_buf_mgr->caller_hold_stream_list, video_stream_node, mList);
|
|
memmove(&stream_node->video_stream, video_stream, sizeof(video_stream_s));
|
|
memcpy(&mvideo_stream, &stream_node->video_stream, sizeof(video_stream_s));
|
|
|
|
list_move_tail(&stream_node->mList, &stream_buf_mgr->empty_stream_list);
|
|
stream_buf_mgr->empty_num++;
|
|
|
|
mutex_unlock(&stream_buf_mgr->mutex);
|
|
|
|
if (mvideo_stream.id != video_stream->id) {
|
|
RT_LOGW("ioctl_return_stream_data: id not match: %d, %d",
|
|
mvideo_stream.id, video_stream->id);
|
|
}
|
|
|
|
buffer_header.private = &mvideo_stream;
|
|
|
|
comp_fill_this_out_buffer(recoder->venc_comp, &buffer_header);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int copy_jpeg_data(void *user_buf_info, video_stream_s *video_stream)
|
|
{
|
|
int result = 0;
|
|
catch_jpeg_buf_info src_buf_info;
|
|
|
|
memset(&src_buf_info, 0, sizeof(catch_jpeg_buf_info));
|
|
|
|
if (copy_from_user(&src_buf_info, (void __user *)user_buf_info, sizeof(struct catch_jpeg_buf_info))) {
|
|
RT_LOGE("IOCTL_CATCH_JPEG_START copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (video_stream->size0 > src_buf_info.buf_size) {
|
|
RT_LOGE("buf_size overflow: %d > %d", video_stream->size0, src_buf_info.buf_size);
|
|
result = -1;
|
|
goto copy_jpeg_data_exit;
|
|
}
|
|
|
|
if (copy_to_user((void *)src_buf_info.buf, video_stream->data0, video_stream->size0)) {
|
|
RT_LOGE(" copy_to_user fail\n");
|
|
result = -1;
|
|
goto copy_jpeg_data_exit;
|
|
}
|
|
|
|
if (copy_to_user((void *)user_buf_info, &video_stream->size0, sizeof(unsigned int))) {
|
|
RT_LOGE(" copy_to_user fail\n");
|
|
result = -1;
|
|
goto copy_jpeg_data_exit;
|
|
}
|
|
|
|
copy_jpeg_data_exit:
|
|
|
|
return result;
|
|
}
|
|
|
|
static int ioctl_output_yuv_catch_jpeg_start(video_recoder *recoder,
|
|
catch_jpeg_config *jpeg_config)
|
|
{
|
|
int ret = 0;
|
|
int connect_flag = 0;
|
|
int catch_jpeg_flag = 0;
|
|
venc_comp_base_config venc_config;
|
|
rt_media_config_s *media_config = &recoder->config;
|
|
|
|
memset(&venc_config, 0, sizeof(venc_comp_base_config));
|
|
ret = comp_get_handle((comp_handle *)&recoder->venc_comp,
|
|
"video.encoder",
|
|
recoder,
|
|
&recoder->config,
|
|
&venc_callback);
|
|
if (ret != ERROR_TYPE_OK) {
|
|
RT_LOGE("get venc comp handle error: %d", ret);
|
|
return -1;
|
|
}
|
|
|
|
venc_config.quality = jpeg_config->qp;
|
|
venc_config.codec_type = RT_VENC_CODEC_JPEG;
|
|
venc_config.src_width = media_config->width;
|
|
venc_config.src_height = media_config->height;
|
|
venc_config.dst_width = jpeg_config->width;
|
|
venc_config.dst_height = jpeg_config->height;
|
|
venc_config.frame_rate = media_config->dst_fps;
|
|
venc_config.bit_rate = media_config->bitrate * 1024;
|
|
venc_config.pixelformat = recoder->pixelformat;
|
|
venc_config.max_keyframe_interval = media_config->gop;
|
|
venc_config.rotate_angle = jpeg_config->rotate_angle;
|
|
memcpy(&venc_config.venc_video_signal, &media_config->venc_video_signal, sizeof(VencH264VideoSignal));
|
|
venc_config.rc_mode = VENC_COMP_RC_MODE_CBR;
|
|
venc_config.en_encpp_sharp = media_config->enable_sharp;
|
|
if (rt_is_format422(venc_config.pixelformat)) {
|
|
venc_config.en_encpp_sharp = 0;
|
|
}
|
|
RT_LOGI("src_w&h = %d, %d; dst_w&h = %d, %d, pixelformat = %d", venc_config.src_width, venc_config.src_height,
|
|
venc_config.dst_width, venc_config.dst_height, venc_config.pixelformat);
|
|
|
|
comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_Base, &venc_config);
|
|
|
|
connect_flag = 1;
|
|
|
|
comp_setup_tunnel(recoder->venc_comp, COMP_INPUT_PORT, recoder->vi_comp, connect_flag);
|
|
|
|
comp_setup_tunnel(recoder->vi_comp, COMP_OUTPUT_PORT, recoder->venc_comp, connect_flag);
|
|
|
|
comp_init(recoder->venc_comp);
|
|
|
|
comp_start(recoder->venc_comp);
|
|
|
|
catch_jpeg_flag = 1;
|
|
comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_CATCH_JPEG, (void *)catch_jpeg_flag);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int ioctl_output_yuv_catch_jpeg_stop(video_recoder *recoder)
|
|
{
|
|
int connect_flag = 0;
|
|
int catch_jpeg_flag = 0;
|
|
|
|
comp_pause(recoder->vi_comp);
|
|
|
|
/* disconnect the tunnel */
|
|
comp_setup_tunnel(recoder->vi_comp, COMP_OUTPUT_PORT, recoder->venc_comp, connect_flag);
|
|
|
|
comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_CATCH_JPEG, (void *)catch_jpeg_flag);
|
|
|
|
comp_start(recoder->vi_comp);
|
|
|
|
/* destroy venc comp*/
|
|
comp_pause(recoder->venc_comp);
|
|
|
|
comp_stop(recoder->venc_comp);
|
|
|
|
comp_free_handle(recoder->venc_comp);
|
|
|
|
recoder->venc_comp = NULL;
|
|
RT_LOGI(" recoder->venc_comp = %p", recoder->venc_comp);
|
|
return 0;
|
|
}
|
|
|
|
static int ioctl_output_yuv_catch_jpeg_getData(video_recoder *recoder,
|
|
void *user_buf_info)
|
|
{
|
|
video_stream_s *video_stream = NULL;
|
|
int loop_count = 0;
|
|
int loop_max_count = 200; /* mean 2 s*/
|
|
|
|
catch_jpeg_get_stream_data:
|
|
|
|
video_stream = ioctl_get_stream_data(recoder);
|
|
if (video_stream == NULL) {
|
|
if (loop_count >= loop_max_count) {
|
|
RT_LOGE("get stream data timeout");
|
|
return -EFAULT;
|
|
}
|
|
|
|
RT_LOGD("catch_jpeg_getData: video stream is null\n");
|
|
|
|
mutex_lock(&recoder->stream_buf_manager.mutex);
|
|
recoder->stream_buf_manager.wait_bitstream_condition = 0;
|
|
recoder->stream_buf_manager.need_wait_up_flag = 1;
|
|
mutex_unlock(&recoder->stream_buf_manager.mutex);
|
|
|
|
wait_event_timeout(recoder->stream_buf_manager.wait_bitstream,
|
|
recoder->stream_buf_manager.wait_bitstream_condition, 1);
|
|
|
|
loop_count++;
|
|
goto catch_jpeg_get_stream_data;
|
|
}
|
|
|
|
RT_LOGI("video_stream->offset0 = %d, size0 = %d, data0 = %p",
|
|
video_stream->offset0, video_stream->size0, video_stream->data0);
|
|
|
|
copy_jpeg_data(user_buf_info, video_stream);
|
|
|
|
ioctl_return_stream_data(recoder, video_stream);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int ioctl_reset_encoder_type(video_recoder *recoder, int encoder_type)
|
|
{
|
|
venc_comp_base_config venc_config;
|
|
int connect_flag = 0;
|
|
int ret = 0;
|
|
comp_state_type comp_state = 0;
|
|
|
|
memset(&venc_config, 0, sizeof(venc_comp_base_config));
|
|
|
|
if (recoder->config.encodeType == encoder_type) {
|
|
RT_LOGE("encoder type is the same, no need to reset: %d, %d",
|
|
recoder->config.encodeType, encoder_type);
|
|
return -1;
|
|
}
|
|
|
|
/* pause venc and vi comp */
|
|
comp_get_state(recoder->venc_comp, &comp_state);
|
|
RT_LOGI("state of venc_comp: %d", comp_state);
|
|
if (comp_state != COMP_STATE_PAUSE)
|
|
comp_pause(recoder->venc_comp);
|
|
|
|
comp_get_state(recoder->vi_comp, &comp_state);
|
|
RT_LOGI("state of vi_comp: %d", comp_state);
|
|
if (comp_state != COMP_STATE_PAUSE)
|
|
comp_pause(recoder->vi_comp);
|
|
|
|
flush_stream_buff(recoder);
|
|
|
|
/* flush buffer of venc comp */
|
|
comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_FLUSH_IN_BUFFER, NULL);
|
|
|
|
comp_stop(recoder->venc_comp);
|
|
|
|
/* disconnect the tunnel */
|
|
connect_flag = 0;
|
|
comp_setup_tunnel(recoder->vi_comp, COMP_OUTPUT_PORT, recoder->venc_comp, connect_flag);
|
|
|
|
/* destroy venc comp*/
|
|
comp_free_handle(recoder->venc_comp);
|
|
|
|
recoder->venc_comp = NULL;
|
|
|
|
/* create and init venc comp */
|
|
ret = comp_get_handle((comp_handle *)&recoder->venc_comp,
|
|
"video.encoder",
|
|
recoder,
|
|
&recoder->config,
|
|
&venc_callback);
|
|
if (ret != ERROR_TYPE_OK) {
|
|
RT_LOGE("get venc comp handle error: %d", ret);
|
|
return -1;
|
|
}
|
|
|
|
recoder->config.encodeType = encoder_type;
|
|
|
|
fill_venc_config(&venc_config, recoder);
|
|
|
|
comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_Base, &venc_config);
|
|
|
|
connect_flag = 1;
|
|
|
|
comp_setup_tunnel(recoder->venc_comp, COMP_INPUT_PORT, recoder->vi_comp, connect_flag);
|
|
|
|
comp_setup_tunnel(recoder->vi_comp, COMP_OUTPUT_PORT, recoder->venc_comp, connect_flag);
|
|
|
|
comp_init(recoder->venc_comp);
|
|
|
|
/* restart venc and vi comp*/
|
|
//comp_start(recoder->venc_comp);
|
|
|
|
//comp_start(recoder->vi_comp);
|
|
|
|
return 0;
|
|
}
|
|
static int fops_mmap(struct file *filp, struct vm_area_struct *vma)
|
|
{
|
|
//* todo
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int fops_open(struct inode *inode, struct file *filp)
|
|
{
|
|
media_private_info *media_info;
|
|
|
|
media_info = kmalloc(sizeof(media_private_info), GFP_KERNEL);
|
|
if (!media_info)
|
|
return -ENOMEM;
|
|
|
|
memset(media_info, 0, sizeof(media_private_info));
|
|
media_info->channel = -1;
|
|
|
|
filp->private_data = media_info;
|
|
|
|
nonseekable_open(inode, filp);
|
|
return 0;
|
|
}
|
|
|
|
static int fops_release(struct inode *inode, struct file *filp)
|
|
{
|
|
/* todo */
|
|
media_private_info *media_info = filp->private_data;
|
|
|
|
kfree(media_info);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static long fops_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
|
{
|
|
/* todo */
|
|
int ret = 0;
|
|
int i = 0;
|
|
media_private_info *media_info = filp->private_data;
|
|
video_recoder *recoder = &rt_media_devp->recoder[media_info->channel];
|
|
|
|
switch (cmd) {
|
|
case IOCTL_CONFIG: {
|
|
rt_media_config_s config;
|
|
|
|
memset(&config, 0, sizeof(rt_media_config_s));
|
|
|
|
if (copy_from_user(&config, (void __user *)arg, sizeof(struct rt_media_config_s))) {
|
|
RT_LOGE("IOCTL_CONFIG copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (rt_media_devp->bcsi_err
|
|
&& (config.output_mode == OUTPUT_MODE_STREAM
|
|
|| config.output_mode == OUTPUT_MODE_YUV)) {
|
|
RT_LOGE("csi is err\n");
|
|
return -1;
|
|
}
|
|
|
|
if (config.channelId < 0 || config.channelId > (VIDEO_INPUT_CHANNEL_NUM - 1)) {
|
|
RT_LOGE("IOCTL_CONFIG: channel[%d] is error", config.channelId);
|
|
return -1;
|
|
}
|
|
|
|
RT_LOGD("IOCTL_CONFIG: media_info->channel = %d, config->channelId = %d",
|
|
media_info->channel, config.channelId);
|
|
|
|
if (media_info->channel == -1)
|
|
media_info->channel = config.channelId;
|
|
|
|
if (media_info->channel != config.channelId) {
|
|
RT_LOGE("IOCTL_CONFIG: channel id not match = %d, %d",
|
|
media_info->channel, config.channelId);
|
|
return -1;
|
|
}
|
|
|
|
recoder = &rt_media_devp->recoder[media_info->channel];
|
|
if (ioctl_config(recoder, &config) != 0) {
|
|
RT_LOGE("config err");
|
|
return -1;
|
|
}
|
|
RT_LOGD("IOCTL_CONFIG end");
|
|
break;
|
|
}
|
|
case IOCTL_START: {
|
|
RT_LOGD("IOCTL_START start %d", recoder->config.width);
|
|
RT_LOGS("rt_media_devp->in_high_fps_status %d", rt_media_devp->in_high_fps_status);
|
|
if (recoder->enable_high_fps == 1 && recoder->bReset_high_fps_finish == 0) {
|
|
RT_LOGW("bReset_high_fps_finish is not 1, not start, state = %d", recoder->state);
|
|
return EFAULT;
|
|
}
|
|
|
|
if (recoder->config.channelId == 1 && rt_media_devp->in_high_fps_status == 1) {
|
|
rt_media_devp->need_start_recoder_1 = recoder;
|
|
RT_LOGW("the high fps is not finish , not start the second recoder channel");
|
|
return 0;
|
|
}
|
|
|
|
if (recoder->config.channelId == 2 && rt_media_devp->in_high_fps_status == 1) {
|
|
rt_media_devp->need_start_recoder_2 = recoder;
|
|
RT_LOGW("the high fps is not finish , not start the third recoder channel");
|
|
return 0;
|
|
}
|
|
|
|
#if defined CONFIG_VIDEO_RT_MEDIA
|
|
if (recoder->config.output_mode == OUTPUT_MODE_STREAM || recoder->config.output_mode == OUTPUT_MODE_YUV) {
|
|
if (rt_media_devp->bcsi_status_set[media_info->channel]) {
|
|
ioctl_start(recoder);
|
|
} else {
|
|
RT_LOGW("csi not ready.");
|
|
return -1;
|
|
}
|
|
} else {
|
|
ioctl_start(recoder);
|
|
}
|
|
#else
|
|
ioctl_start(recoder);
|
|
#endif
|
|
|
|
RT_LOGD("IOCTL_START end");
|
|
break;
|
|
}
|
|
case IOCTL_PAUSE: {
|
|
RT_LOGD("IOCTL_PAUSE start");
|
|
ioctl_pause(recoder);
|
|
RT_LOGD("IOCTL_PAUSE end");
|
|
break;
|
|
}
|
|
case IOCTL_DESTROY: {
|
|
RT_LOGD("IOCTL_DESTROY start");
|
|
ioctl_destroy(recoder);
|
|
RT_LOGD("IOCTL_DESTROY end");
|
|
break;
|
|
}
|
|
case IOCTL_GET_VBV_BUFFER_INFO: {
|
|
KERNEL_VBV_BUFFER_INFO vbv_buf_info;
|
|
|
|
memset(&vbv_buf_info, 0, sizeof(vbv_buf_info));
|
|
|
|
if (recoder->venc_comp == NULL) {
|
|
RT_LOGE("IOCTL_GET_VBV_BUFFER_INFO: recoder->venc_comp is null\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (ioctl_get_vbv_buf_info(recoder, &vbv_buf_info) != 0) {
|
|
RT_LOGI("ioctl_get_vbv_buf_info failed");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (copy_to_user((void *)arg, &vbv_buf_info, sizeof(KERNEL_VBV_BUFFER_INFO))) {
|
|
RT_LOGE("IOCTL_GET_VBV_BUFFER_INFO copy_to_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_GET_STREAM_HEADER_SIZE: {
|
|
venc_comp_header_data header_data;
|
|
|
|
memset(&header_data, 0, sizeof(venc_comp_header_data));
|
|
|
|
if (recoder->venc_comp == NULL) {
|
|
RT_LOGE("IOCTL_GET_STREAM_HEADER_SIZE: recoder->venc_comp is null\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (ioctl_get_stream_header(recoder, &header_data) != 0) {
|
|
RT_LOGW("ioctl_get_stream_header failed");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (copy_to_user((void *)arg, &header_data.nLength, sizeof(int))) {
|
|
RT_LOGE("IOCTL_GET_VBV_BUFFER_INFO copy_to_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
RT_LOGD("end IOCTL_GET_STREAM_HEADER_SIZE: header_data.nLength %d\n", header_data.nLength);
|
|
break;
|
|
}
|
|
case IOCTL_GET_STREAM_HEADER_DATA: {
|
|
venc_comp_header_data header_data;
|
|
memset(&header_data, 0, sizeof(venc_comp_header_data));
|
|
|
|
if (recoder->venc_comp == NULL) {
|
|
RT_LOGE("IOCTL_GET_STREAM_HEADER_DATA: recoder->venc_comp is null\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (ioctl_get_stream_header(recoder, &header_data) != 0) {
|
|
RT_LOGW("ioctl_get_stream_header failed");
|
|
return -EFAULT;
|
|
}
|
|
if (copy_to_user((void *)arg, header_data.pBuffer, header_data.nLength)) {
|
|
RT_LOGE("IOCTL_GET_VBV_BUFFER_INFO copy_to_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
RT_LOGD("IOCTL_GET_STREAM_HEADER_DATA: %x %x %x %x %x %x",
|
|
header_data.pBuffer[0],
|
|
header_data.pBuffer[1],
|
|
header_data.pBuffer[2],
|
|
header_data.pBuffer[3],
|
|
header_data.pBuffer[4],
|
|
header_data.pBuffer[5]);
|
|
break;
|
|
}
|
|
case IOCTL_GET_STREAM_DATA: {
|
|
video_stream_s *video_stream = NULL;
|
|
|
|
if (recoder->venc_comp == NULL) {
|
|
RT_LOGE("IOCTL_GET_STREAM_DATA: recoder->venc_comp is null\n");
|
|
return -EFAULT;
|
|
}
|
|
video_stream = ioctl_get_stream_data(recoder);
|
|
if (video_stream == NULL) {
|
|
RT_LOGD("IOCTL_GET_STREAM_DATA: video stream is null\n");
|
|
|
|
mutex_lock(&recoder->stream_buf_manager.mutex);
|
|
recoder->stream_buf_manager.wait_bitstream_condition = 0;
|
|
recoder->stream_buf_manager.need_wait_up_flag = 1;
|
|
mutex_unlock(&recoder->stream_buf_manager.mutex);
|
|
|
|
wait_event_timeout(recoder->stream_buf_manager.wait_bitstream,
|
|
recoder->stream_buf_manager.wait_bitstream_condition, HZ/5);
|
|
return -EFAULT;
|
|
}
|
|
|
|
RT_LOGD("video_stream->offset0 = %d, size0 = %d",
|
|
video_stream->offset0, video_stream->size0);
|
|
|
|
RT_LOGI("get stream, pts = %lld", video_stream->pts);
|
|
if (copy_to_user((void *)arg, video_stream, sizeof(video_stream_s))) {
|
|
RT_LOGE("IOCTL_GET_STREAM_DATA copy_to_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case IOCTL_RETURN_STREAM_DATA: {
|
|
video_stream_s cur_stream;
|
|
|
|
memset(&cur_stream, 0, sizeof(video_stream_s));
|
|
|
|
if (recoder->venc_comp == NULL) {
|
|
RT_LOGE("IOCTL_RETURN_STREAM_DATA: recoder->venc_comp is null\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (copy_from_user(&cur_stream, (void __user *)arg, sizeof(struct video_stream_s))) {
|
|
RT_LOGE("IOCTL_CONFIG copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
ioctl_return_stream_data(recoder, &cur_stream);
|
|
|
|
break;
|
|
}
|
|
case IOCTL_CATCH_JPEG_START: {
|
|
catch_jpeg_config jpeg_config;
|
|
memset(&jpeg_config, 0, sizeof(catch_jpeg_config));
|
|
|
|
if (copy_from_user(&jpeg_config, (void __user *)arg, sizeof(struct catch_jpeg_config))) {
|
|
RT_LOGE("IOCTL_CATCH_JPEG_START copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (recoder->config.output_mode == OUTPUT_MODE_STREAM) {
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_CATCH_JPEG_START, &jpeg_config);
|
|
if (ret != 0) {
|
|
RT_LOGE("COMP_INDEX_VENC_CONFIG_CATCH_JPEG_START failed");
|
|
return -EFAULT;
|
|
}
|
|
} else {
|
|
ioctl_output_yuv_catch_jpeg_start(recoder, &jpeg_config);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case IOCTL_CATCH_JPEG_STOP: {
|
|
if (recoder->config.output_mode == OUTPUT_MODE_STREAM) {
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_CATCH_JPEG_STOP, 0);
|
|
if (ret != 0) {
|
|
RT_LOGE("COMP_INDEX_VENC_CONFIG_CATCH_JPEG_START failed");
|
|
return -EFAULT;
|
|
}
|
|
} else
|
|
ioctl_output_yuv_catch_jpeg_stop(recoder);
|
|
|
|
break;
|
|
}
|
|
case IOCTL_CATCH_JPEG_GET_DATA: {
|
|
if (recoder->config.output_mode == OUTPUT_MODE_STREAM) {
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_CATCH_JPEG_GET_DATA, (void *)arg);
|
|
if (ret != 0) {
|
|
RT_LOGE("COMP_INDEX_VENC_CONFIG_CATCH_JPEG_GET_DATA failed");
|
|
return -EFAULT;
|
|
}
|
|
} else
|
|
return ioctl_output_yuv_catch_jpeg_getData(recoder, (void *)arg);
|
|
|
|
break;
|
|
}
|
|
case IOCTL_SET_OSD: {
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_OSD, (void *)arg);
|
|
if (ret != 0) {
|
|
RT_LOGE("IOCTL_SET_OSD failed");
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
// case IOCTL_GET_BIN_IMAGE_DATA: {
|
|
// ret = comp_get_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_GET_BIN_IMAGE_DATA, (void *)arg);
|
|
// if (ret <= 0) {
|
|
// RT_LOGE("IOCTL_GET_BIN_IMAGE_DATA failed");
|
|
// return -EFAULT;
|
|
// }
|
|
// RT_LOGI("IOCTL_GET_BIN_IMAGE_DATA, ret = %d", ret);
|
|
// return ret;
|
|
// }
|
|
// case IOCTL_GET_MV_INFO_DATA: {
|
|
// ret = comp_get_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_GET_MV_INFO_DATA, (void *)arg);
|
|
// if (ret <= 0) {
|
|
// RT_LOGE("IOCTL_GET_MV_INFO_DATA failed");
|
|
// return -EFAULT;
|
|
// }
|
|
// RT_LOGI("IOCTL_GET_MV_INFO_DATA, ret = %d", ret);
|
|
// return ret;
|
|
// }
|
|
case IOCTL_CONFIG_YUV_BUF_INFO: {
|
|
if (copy_from_user(&recoder->yuv_buf_info, (void __user *)arg, sizeof(struct config_yuv_buf_info))) {
|
|
RT_LOGE("copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_SET_YUV_BUF_INFO, (void *)&recoder->yuv_buf_info);
|
|
if (ret < 0) {
|
|
RT_LOGE("failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case IOCTL_REQUEST_YUV_FRAME: {
|
|
unsigned char *phy_addr = NULL;
|
|
rt_yuv_info s_yuv_info;
|
|
|
|
memset(&s_yuv_info, 0, sizeof(rt_yuv_info));
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_REQUEST_YUV_FRAME, (void *)&s_yuv_info);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_REQUEST_YUV_FRAME failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (copy_to_user((void *)arg, &s_yuv_info, sizeof(s_yuv_info))) {
|
|
RT_LOGE("IOCTL_REQUEST_YUV_FRAME copy_to_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_RETURN_YUV_FRAME: {
|
|
unsigned char *phy_addr = NULL;
|
|
|
|
if (copy_from_user(&phy_addr, (void __user *)arg, sizeof(unsigned char *))) {
|
|
RT_LOGE("IOCTL_RETURN_YUV_FRAME copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_RETURN_YUV_FRAME, (void *)phy_addr);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_RETURN_YUV_FRAME failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case IOCTL_GET_ISP_LV: {
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_GET_LV, NULL);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_GET_ISP_LV failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
return ret;
|
|
}
|
|
case IOCTL_GET_ISP_HIST: {
|
|
unsigned int hist[256];
|
|
|
|
memset(&hist, 0, 256 * sizeof(unsigned int));
|
|
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_GET_HIST, (void *)&hist[0]);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_GET_ISP_HIST failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (copy_to_user((void *)arg, &hist[0], 256 * sizeof(unsigned int))) {
|
|
RT_LOGE("IOCTL_GET_ISP_HIST copy_to_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
return ret;
|
|
}
|
|
case IOCTL_SET_SENSOR_EXP: {
|
|
int exp_time = (int)arg;
|
|
|
|
RT_LOGI("exp_time = %d", exp_time);
|
|
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_SET_EXP, (void *)exp_time);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_ISP_EXP failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
return ret;
|
|
}
|
|
case IOCTL_SET_SENSOR_GAIN: {
|
|
int sensor_gain = (int)arg;
|
|
|
|
RT_LOGI("sensor_gain = %d", sensor_gain);
|
|
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_SET_GAIN, (void *)sensor_gain);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_ISP_GAIN failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
case IOCTL_GET_ISP_EXP_GAIN: {
|
|
RTIspExpGain exp_gain;
|
|
|
|
memset(&exp_gain, 0, sizeof(RTIspExpGain));
|
|
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_GET_EXP_GAIN, (void *)&exp_gain);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_GET_ISP_EXP_GAIN failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (copy_to_user((void *)arg, &exp_gain, sizeof(RTIspExpGain))) {
|
|
RT_LOGE("IOCTL_GET_ISP_EXP_GAIN copy_to_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
return ret;
|
|
}
|
|
case IOCTL_SET_ISP_ATTR_CFG: {
|
|
RTIspCtrlAttr ctrlattr;
|
|
|
|
memset(&ctrlattr, 0, sizeof(RTIspCtrlAttr));
|
|
|
|
if (copy_from_user(&ctrlattr, (void __user *)arg, sizeof(RTIspCtrlAttr))) {
|
|
RT_LOGE("IOCTL_SET_ISP_ATTR_CFG copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
RT_LOGD("IOCTL_SET_ISP_ATTR_CFG:ctrl id:%d\n", ctrlattr.isp_attr_cfg.cfg_id);
|
|
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_SET_ISP_ARRT_CFG, (void *)&ctrlattr);
|
|
if (ret < 0) {
|
|
RT_LOGE("COMP_INDEX_VI_CONFIG_Dynamic_SET_ISP_ARRT_CFG failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_GET_ISP_ATTR_CFG: {
|
|
RTIspCtrlAttr ctrlattr;
|
|
|
|
memset(&ctrlattr, 0, sizeof(RTIspCtrlAttr));
|
|
|
|
if (copy_from_user(&ctrlattr, (void __user *)arg, sizeof(RTIspCtrlAttr))) {
|
|
RT_LOGE("IOCTL_GET_ISP_ATTR_CFG copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
RT_LOGD("IOCTL_GET_ISP_ATTR_CFG:ctrl id:%d\n", ctrlattr.isp_attr_cfg.cfg_id);
|
|
|
|
ret = comp_get_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_GET_ISP_ARRT_CFG, (void *)&ctrlattr);
|
|
if (ret < 0) {
|
|
RT_LOGE("COMP_INDEX_VI_CONFIG_Dynamic_GET_ISP_ARRT_CFG failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (copy_to_user((void *)arg, &ctrlattr, sizeof(RTIspCtrlAttr))) {
|
|
RT_LOGE("IOCTL_GET_ISP_ATTR_CFG copy_to_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case IOCTL_SET_ISP_ORL: {
|
|
RTIspOrl isp_orl;
|
|
|
|
memset(&isp_orl, 0, sizeof(RTIspOrl));
|
|
|
|
if (copy_from_user(&isp_orl, (void __user *)arg, sizeof(RTIspOrl))) {
|
|
RT_LOGE("IOCTL_SET_ISP_ATTR_CFG copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_SET_ORL, (void *)&isp_orl);
|
|
if (ret < 0) {
|
|
RT_LOGE("COMP_INDEX_VI_CONFIG_Dynamic_SET_ORL failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_GET_ISP_AE_METERING_MODE: {
|
|
int ae_metering_mode = (int)arg;
|
|
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_SET_AE_METERING_MODE, (void *)ae_metering_mode);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_POWER_LINE_FREQ failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_ISP_AE_MODE: {
|
|
int ae_mode = (int)arg;
|
|
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_SET_AE_MODE, (void *)ae_mode);
|
|
|
|
if (ret < 0) {
|
|
RT_LOGE("COMP_INDEX_VI_CONFIG_Dynamic_SET_AE_MODE failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
return ret;
|
|
}
|
|
case IOCTL_SET_IR_PARAM: {
|
|
RTIrParam mIrParam;
|
|
int is_night_case = 0;
|
|
|
|
memset(&mIrParam, 0, sizeof(RTIrParam));
|
|
|
|
if (copy_from_user(&mIrParam, (void __user *)arg, sizeof(RTIrParam))) {
|
|
RT_LOGE("IOCTL_SET_IR_COLOR2GREY copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (mIrParam.grey == 1)
|
|
is_night_case = 1;
|
|
|
|
RT_LOGW("is_night_case = %d, venc_comp = %p", is_night_case, recoder->venc_comp);
|
|
|
|
if (recoder->venc_comp) {
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_Dynamic_SET_IS_NIGHT_CASE, (void *)&is_night_case);
|
|
if (ret < 0)
|
|
RT_LOGW("VENC_CONFIG_Dynamic_SET_IS_NIGHT_CASE failed, ret = %d", ret);
|
|
}
|
|
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_SET_IR_PARAM, (void *)&mIrParam);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_IR_COLOR2GREY failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_HORIZONTAL_FLIP: {
|
|
int bhflip = (int)arg;
|
|
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_SET_H_FLIP, (void *)bhflip);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_HORIZONTAL_FLIP failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_VERTICAL_FLIP: {
|
|
int bvflip = (int)arg;
|
|
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_SET_V_FLIP, (void *)bvflip);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_VERTICAL_FLIP failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_FORCE_KEYFRAME: {
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_Dynamic_ForceKeyFrame, NULL);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_FORCE_KEYFRAME failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_RESET_ENCODER_TYPE: {
|
|
int encoder_type = (int)arg;
|
|
|
|
ret = ioctl_reset_encoder_type(recoder, encoder_type);
|
|
if (ret != 0) {
|
|
RT_LOGE("reset encoder type, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_REQUEST_ENC_YUV_FRAME: {
|
|
unsigned char *phy_addr = NULL;
|
|
|
|
mutex_lock(&recoder->yuv_mutex);
|
|
if (recoder->enc_yuv_phy_addr == NULL) {
|
|
RT_LOGI(" enc_yuv_phy_addr is null");
|
|
mutex_unlock(&recoder->yuv_mutex);
|
|
return -1;
|
|
}
|
|
phy_addr = recoder->enc_yuv_phy_addr;
|
|
recoder->enc_yuv_phy_addr = NULL;
|
|
mutex_unlock(&recoder->yuv_mutex);
|
|
if (copy_to_user((void *)arg, &phy_addr, sizeof(unsigned char *))) {
|
|
RT_LOGE("IOCTL_REQUEST_ENC_YUV_FRAME copy_to_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SUBMIT_ENC_YUV_FRAME: {
|
|
unsigned char *phy_addr = NULL;
|
|
comp_buffer_header_type mbuffer_header;
|
|
video_frame_s mvideo_frame;
|
|
int align_width = RT_ALIGN(recoder->config.width, 16);
|
|
int align_height = RT_ALIGN(recoder->config.height, 16);
|
|
int y_size = align_width * align_height;
|
|
|
|
memset(&mbuffer_header, 0, sizeof(comp_buffer_header_type));
|
|
memset(&mvideo_frame, 0, sizeof(video_frame_s));
|
|
|
|
if (copy_from_user(&phy_addr, (void __user *)arg, sizeof(unsigned char *))) {
|
|
RT_LOGE("IOCTL_RETURN_YUV_FRAME copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
mvideo_frame.phy_addr[0] = (unsigned int)phy_addr;
|
|
mvideo_frame.phy_addr[1] = (unsigned int)phy_addr + y_size;
|
|
mbuffer_header.private = &mvideo_frame;
|
|
comp_empty_this_in_buffer(recoder->venc_comp, &mbuffer_header);
|
|
|
|
break;
|
|
}
|
|
case IOCTL_SET_POWER_LINE_FREQ: {
|
|
int power_line_freq = (int)arg;
|
|
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_SET_POWER_LINE_FREQ, (void *)power_line_freq);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_POWER_LINE_FREQ failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_BRIGHTNESS: {
|
|
int brightness_level = (int)arg;
|
|
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_SET_BRIGHTNESS, (void *)brightness_level);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_BRIGHTNESS failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_CONTRAST: {
|
|
int contrast_level = (int)arg;
|
|
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_SET_CONTRAST, (void *)contrast_level);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_CONTRAST failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_SATURATION: {
|
|
int saturation_level = (int)arg;
|
|
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_SET_SATURATION, (void *)saturation_level);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_SATURATION failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_HUE: {
|
|
int hue_level = (int)arg;
|
|
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_SET_HUE, (void *)hue_level);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_HUE failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_SHARPNESS: {
|
|
int sharpness_level = (int)arg;
|
|
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_SET_SHARPNESS, (void *)sharpness_level);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_SHARPNESS failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_GET_SENSOR_NAME: {
|
|
char sensor_name[30];
|
|
memset(sensor_name, 0, sizeof(sensor_name));
|
|
|
|
ret = comp_get_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_GET_SENSOR_NAME, (void *)&sensor_name[0]);
|
|
if (ret < 0) {
|
|
RT_LOGE("COMP_INDEX_VI_CONFIG_Dynamic_GET_SENSOR_NAME failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (copy_to_user((void *)arg, &sensor_name, sizeof(sensor_name))) {
|
|
RT_LOGE("IOCTL_GET_SENSOR_NAME copy_to_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_GET_SENSOR_RESOLUTION: {
|
|
RTSensorResolution sensor_resolution;
|
|
|
|
if (copy_from_user(&sensor_resolution, (void __user *)arg, sizeof(RTSensorResolution))) {
|
|
RT_LOGE("IOCTL_GET_SENSOR_RESOLUTION copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
ret = comp_get_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_GET_SENSOR_RESOLUTION, (void *)&sensor_resolution);
|
|
if (ret < 0) {
|
|
RT_LOGE("COMP_INDEX_VI_CONFIG_Dynamic_GET_SENSOR_RESOLUTION failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (copy_to_user((void *)arg, &sensor_resolution, sizeof(RTSensorResolution))) {
|
|
RT_LOGE("IOCTL_GET_SENSOR_RESOLUTION copy_to_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_GET_TUNNING_CTL_DATA: {
|
|
RTTunningCtlData TunningCtlData;
|
|
|
|
if (copy_from_user(&TunningCtlData, (void __user *)arg, sizeof(RTTunningCtlData))) {
|
|
RT_LOGE("IOCTL_GET_TUNNING_CTL_DATA copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
ret = comp_get_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_GET_TUNNING_CTL_DATA, (void *)&TunningCtlData);
|
|
if (ret < 0) {
|
|
RT_LOGE("COMP_INDEX_VI_CONFIG_Dynamic_GET_TUNNING_CTL_DATA failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (copy_to_user((void *)arg, &TunningCtlData, sizeof(RTTunningCtlData))) {
|
|
RT_LOGE("IOCTL_GET_TUNNING_CTL_DATA copy_to_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_FIX_QP: {
|
|
RTVencFixQP fix_qp;
|
|
|
|
if (copy_from_user(&fix_qp, (void __user *)arg, sizeof(RTVencFixQP))) {
|
|
RT_LOGE("IOCTL_SET_FIX_QP copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_FIX_QP, (void *)&fix_qp);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_FIX_QP failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_H264_VIDEO_TIMING: {
|
|
RTVencH264VideoTiming st_h264_video_timing;
|
|
|
|
if (copy_from_user(&st_h264_video_timing, (void __user *)arg, sizeof(RTVencH264VideoTiming))) {
|
|
RT_LOGE("IOCTL_SET_H264_VIDEO_TIMING copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_H264_TIMING, (void *)&st_h264_video_timing);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_H264_VIDEO_TIMING failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_H265_VIDEO_TIMING: {
|
|
RTVencH265TimingS st_h265_video_timing;
|
|
|
|
if (copy_from_user(&st_h265_video_timing, (void __user *)arg, sizeof(RTVencH265TimingS))) {
|
|
RT_LOGE("IOCTL_SET_H265_VIDEO_TIMING copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_H265_TIMING, (void *)&st_h265_video_timing);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_H265_VIDEO_TIMING failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_GET_TDM_BUF: {
|
|
struct vin_isp_tdm_event_status tdm_status;
|
|
|
|
if (copy_from_user(&tdm_status, (void __user *)arg, sizeof(struct vin_isp_tdm_event_status))) {
|
|
RT_LOGE("IOCTL_GET_TDM_BUF copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
rt_tdm_get_buf(&tdm_status);
|
|
|
|
if (copy_to_user((void *)arg, &tdm_status, sizeof(struct vin_isp_tdm_event_status))) {
|
|
RT_LOGE("IOCTL_GET_TDM_BUF copy_to_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case IOCTL_RETURN_TDM_BUF: {
|
|
struct vin_isp_tdm_event_status tdm_status;
|
|
|
|
if (copy_from_user(&tdm_status, (void __user *)arg, sizeof(struct vin_isp_tdm_event_status))) {
|
|
RT_LOGE("IOCTL_RETURN_TDM_BUF copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
vin_return_tdmbuffer_special(recoder->config.channelId, &tdm_status);
|
|
break;
|
|
}
|
|
case IOCTL_GET_TDM_DATA: {
|
|
struct vin_isp_tdm_data st_tdm_data;
|
|
|
|
if (copy_from_user(&st_tdm_data, (void __user *)arg, sizeof(struct vin_isp_tdm_data))) {
|
|
RT_LOGE("IOCTL_GET_TDM_DATA copy_from_user fail");
|
|
return -EFAULT;
|
|
}
|
|
|
|
vin_get_tdm_data_special(recoder->config.channelId, &st_tdm_data);
|
|
|
|
if (copy_to_user((void *)arg, &st_tdm_data, sizeof(struct vin_isp_tdm_data))) {
|
|
RT_LOGE("IOCTL_GET_TDM_DATA copy_to_user fail");
|
|
return -EFAULT;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case IOCTL_SET_QP_RANGE: {
|
|
video_qp_range qp_range;
|
|
|
|
if (copy_from_user(&qp_range, (void __user *)arg, sizeof(video_qp_range))) {
|
|
RT_LOGE("IOCTL_SET_QP_RANGE copy_from_user fail");
|
|
return -EFAULT;
|
|
}
|
|
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_Dynamic_SET_QP_RANGE, (void *)&qp_range);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_QP_RANGE failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_MB_RC_MOVE_STATUS: {
|
|
int nMoveStatus = (int)arg;
|
|
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_MB_MOVE_STATUS, &nMoveStatus);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_MB_RC_MOVE_STATUS failed, ret = %d, nMoveStatus = %d", ret, nMoveStatus);
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_JPEG_QUALITY: {
|
|
int nQuality = (int)arg;
|
|
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_JPG_QUALITY, (void *)nQuality);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_JPEG_QUALITY failed, ret = %d, bitrate = %d", ret, nQuality);
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_BITRATE: {
|
|
int bitrate = ((int)arg) * 1024;
|
|
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_Dynamic_SET_BITRATE, (void *)bitrate);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_BITRATE failed, ret = %d, bitrate = %d", ret, bitrate);
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_FPS: {
|
|
int fps = ((int)arg);
|
|
|
|
if (fps <= 0 || fps > recoder->max_fps) {
|
|
RT_LOGW("IOCTL_SET_FPS: invalid fps[%d], setup to max_fps[%d]", fps, recoder->max_fps);
|
|
fps = recoder->max_fps;
|
|
}
|
|
|
|
RT_LOGI("IOCTL_SET_FPS: fps = %d, max_fps = %d, vi_comp = %p, venc_comp = %p",
|
|
fps, recoder->max_fps, recoder->vi_comp, recoder->venc_comp);
|
|
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_SET_FPS, (void *)fps);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_FPS failed, ret = %d, fps = %d", ret, fps);
|
|
return -EFAULT;
|
|
}
|
|
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_Dynamic_SET_FPS, (void *)fps);
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_SET_FPS failed, ret = %d, fps = %d", ret, fps);
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_VBR_PARAM: {
|
|
RTVencVbrParam rt_vbr_param;
|
|
|
|
memset(&rt_vbr_param, 0, sizeof(RTVencVbrParam));
|
|
|
|
if (copy_from_user(&rt_vbr_param, (void __user *)arg, sizeof(RTVencVbrParam))) {
|
|
RT_LOGE("IOCTL_SET_VBR_PARAM copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_Dynamic_SET_VBR_PARAM, (void *)&rt_vbr_param);
|
|
if (ret != 0) {
|
|
RT_LOGE("VENC SET_VBR_PARAM fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case IOCTL_GET_SUM_MB_INFO: {
|
|
RTVencMBSumInfo rt_mb_sum;
|
|
|
|
memset(&rt_mb_sum, 0, sizeof(RTVencMBSumInfo));
|
|
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_Dynamic_GET_SUM_MB_INFO, (void *)&rt_mb_sum);
|
|
if (ret != 0) {
|
|
RT_LOGE("VENC GET_SUM_MB_INFO fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (copy_to_user((void *)arg, &rt_mb_sum, sizeof(RTVencMBSumInfo))) {
|
|
RT_LOGE("IOCTL_REQUEST_ENC_YUV_FRAME copy_to_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case IOCTL_SET_ENC_MOTION_SEARCH_PARAM: {
|
|
VencMotionSearchParam *pmotion_search_param = &recoder->motion_search_param;
|
|
int total_region_num;
|
|
|
|
if (copy_from_user(pmotion_search_param, (void __user *)arg, sizeof(RTVencMotionSearchParam))) {
|
|
RT_LOGE("IOCTL_SET_ENC_MOTION_SEARCH_PARAM copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
RT_LOGD("motion_search_param hor_region_num %d, ver_region_num %d", recoder->motion_search_param.hor_region_num, recoder->motion_search_param.ver_region_num);
|
|
|
|
if (0 == recoder->motion_search_param.en_motion_search) {
|
|
if (recoder->motion_region) {
|
|
kfree(recoder->motion_region);
|
|
recoder->motion_region = NULL;
|
|
recoder->motion_region_len = 0;
|
|
}
|
|
} else {
|
|
if (0 == recoder->motion_search_param.dis_default_para) {
|
|
total_region_num = MOTION_TOTAL_REGION_NUM_DEFAULT;
|
|
} else {
|
|
if ((0 == recoder->motion_search_param.hor_region_num) || (0 == recoder->motion_search_param.ver_region_num)) {
|
|
RT_LOGE("IOCTL_SET_ENC_MOTION_SEARCH_PARAM invalid params, %d %d\n", recoder->motion_search_param.hor_region_num,
|
|
recoder->motion_search_param.ver_region_num);
|
|
return -EFAULT;
|
|
} else {
|
|
total_region_num = recoder->motion_search_param.hor_region_num * recoder->motion_search_param.ver_region_num;
|
|
}
|
|
}
|
|
|
|
recoder->motion_region_len = total_region_num * sizeof(VencMotionSearchRegion);
|
|
RT_LOGI("total_region_num %d, motion_region_len %d", total_region_num, recoder->motion_region_len);
|
|
|
|
// free motion_region when disable motion_search or ioctl_destroy
|
|
recoder->motion_region = kmalloc(recoder->motion_region_len, GFP_KERNEL);
|
|
if (recoder->motion_region == NULL) {
|
|
RT_LOGE("IOCTL_SET_ENC_MOTION_SEARCH_PARAM: kmalloc fail\n");
|
|
return -EFAULT;
|
|
}
|
|
memset(recoder->motion_region, 0, recoder->motion_region_len);
|
|
}
|
|
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_MOTION_SEARCH_PARAM, (void *)pmotion_search_param);
|
|
if (ret != 0) {
|
|
RT_LOGE("VENC COMP_INDEX_VENC_CONFIG_SET_MOTION_SEARCH_PARAM fail\n");
|
|
if (recoder->motion_region) {
|
|
kfree(recoder->motion_region);
|
|
recoder->motion_region = NULL;
|
|
recoder->motion_region_len = 0;
|
|
}
|
|
return -EFAULT;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case IOCTL_GET_ENC_MOTION_SEARCH_RESULT: {
|
|
VencMotionSearchResult motion_result;
|
|
VencMotionSearchResult motion_result_from_user;
|
|
|
|
if (recoder->config.encodeType == 1) {
|
|
RT_LOGW("not support jpg, return\n");
|
|
return -1;
|
|
}
|
|
|
|
if (recoder->motion_region == NULL || 0 == recoder->motion_region_len) {
|
|
RT_LOGE("IOCTL_GET_ENC_MOTION_SEARCH_RESULT: invalid motion_region\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
memset(&motion_result_from_user, 0, sizeof(VencMotionSearchResult));
|
|
if (copy_from_user(&motion_result_from_user, (void __user *)arg, sizeof(VencMotionSearchResult))) {
|
|
RT_LOGE("motion_result_from_user copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
memset(&motion_result, 0, sizeof(VencMotionSearchResult));
|
|
motion_result.region = recoder->motion_region;
|
|
|
|
ret = comp_get_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_Dynamic_GET_MOTION_SEARCH_RESULT, (void *)&motion_result);
|
|
if (ret != 0) {
|
|
RT_LOGE("VENC COMP_INDEX_VENC_CONFIG_Dynamic_GET_MOTION_SEARCH_RESULT fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (copy_to_user((void *)motion_result_from_user.region, motion_result.region, recoder->motion_region_len)) {
|
|
RT_LOGE("region copy_to_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
motion_result.region = motion_result_from_user.region;
|
|
if (copy_to_user((void *)arg, &motion_result, sizeof(VencMotionSearchResult))) {
|
|
RT_LOGE("motion_result copy_to_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_VENC_SUPER_FRAME_PARAM: {
|
|
VencSuperFrameConfig super_frame_config;
|
|
|
|
memset(&super_frame_config, 0, sizeof(VencSuperFrameConfig));
|
|
|
|
if (copy_from_user(&super_frame_config, (void __user *)arg, sizeof(VencSuperFrameConfig))) {
|
|
RT_LOGE("IOCTL_SET_VENC_SUPER_FRAME_PARAM copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_Dynamic_SET_SUPER_FRAME_PARAM, (void *)&super_frame_config);
|
|
if (ret != 0) {
|
|
RT_LOGE("VENC SET_SUPER_FRAME_PARAM fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case IOCTL_SET_SHARP: {
|
|
int bSharp = (int)arg;
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_SHARP, (void *)&bSharp);
|
|
if (ret != 0) {
|
|
RT_LOGE("VENC COMP_INDEX_VENC_CONFIG_SET_SHARP fail\n");
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_GET_CSI_STATUS: {
|
|
//not buildin mode, such ko mode, this is invalid
|
|
int i = 0;
|
|
for (; i < VIDEO_INPUT_CHANNEL_NUM; i++) {
|
|
#if defined CONFIG_VIDEO_RT_MEDIA//build in mode
|
|
if (g_csi_status_pair[i].bset) {
|
|
rt_media_devp->bcsi_status_set[i] = g_csi_status_pair[i].status;
|
|
}
|
|
#else//not for real value, only compatibility
|
|
rt_media_devp->bcsi_status_set[i] = 1;
|
|
#endif
|
|
}
|
|
if (copy_to_user((void *)arg, rt_media_devp->bcsi_status_set, sizeof(int) * VIDEO_INPUT_CHANNEL_NUM)) {
|
|
RT_LOGE("IOCTL_GET_CSI_STATUS copy_to_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_ROI: {
|
|
VencROIConfig sRoiConfig[MAX_ROI_AREA];
|
|
|
|
memset(sRoiConfig, 0, sizeof(VencROIConfig) * MAX_ROI_AREA);
|
|
|
|
if (copy_from_user(sRoiConfig, (void __user *)arg, sizeof(VencROIConfig) * MAX_ROI_AREA)) {
|
|
RT_LOGE("IOCTL_SET_ROI copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
if (recoder->venc_comp) {
|
|
for (i = 0; i < MAX_ROI_AREA; i++) {
|
|
comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_ROI, &sRoiConfig[i]);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_GDC: {
|
|
sGdcParam sGdcConfig;
|
|
|
|
memset(&sGdcConfig, 0, sizeof(sGdcParam));
|
|
|
|
if (copy_from_user(&sGdcConfig, (void __user *)arg, sizeof(sGdcParam))) {
|
|
RT_LOGE("IOCTL_SET_GDC copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
RT_LOGD("eMountMode %d peak_weights_strength %d peak_m %d %d", sGdcConfig.eMountMode, sGdcConfig.peak_weights_strength, sGdcConfig.peak_m, sGdcConfig.th_strong_edge);
|
|
if (recoder->venc_comp)
|
|
comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_GDC, &sGdcConfig);
|
|
break;
|
|
}
|
|
case IOCTL_SET_ROTATE: {
|
|
unsigned int rotate_angle = (unsigned int)arg;
|
|
|
|
if (recoder->venc_comp)
|
|
comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_ROTATE, &rotate_angle);
|
|
break;
|
|
}
|
|
case IOCTL_SET_REC_REF_LBC_MODE: {
|
|
eVeLbcMode rec_lbc_mode = (eVeLbcMode)arg;
|
|
RT_LOGD("rec_lbc_mode %d\n", rec_lbc_mode);
|
|
|
|
if (recoder->config.encodeType == 1) {
|
|
RT_LOGW("not support jpg, return\n");
|
|
return -1;
|
|
}
|
|
|
|
if (recoder->venc_comp)
|
|
comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_REC_REF_LBC_MODE, &rec_lbc_mode);
|
|
break;
|
|
}
|
|
case IOCTL_SET_WEAK_TEXT_TH: {
|
|
RTVenWeakTextTh WeakTextTh;
|
|
|
|
memset(&WeakTextTh, 0, sizeof(RTVenWeakTextTh));
|
|
|
|
if (copy_from_user(&WeakTextTh, (void __user *)arg, sizeof(RTVenWeakTextTh))) {
|
|
RT_LOGE("IOCTL_SET_WEAK_TEXT_TH copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (recoder->config.encodeType == 1) {
|
|
RT_LOGW("not support jpg, return\n");
|
|
return -1;
|
|
}
|
|
|
|
RT_LOGD("en_weak_text_th:%d, weak_text_th:%d%%", WeakTextTh.en_weak_text_th, (int)WeakTextTh.weak_text_th);
|
|
|
|
if (recoder->venc_comp && WeakTextTh.en_weak_text_th) {
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_WEAK_TEXT_TH, (void *)&WeakTextTh.weak_text_th);
|
|
if (ret != 0) {
|
|
RT_LOGE("COMP_INDEX_VENC_CONFIG_SET_WEAK_TEXT_TH fail\n");
|
|
return -EFAULT;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case IOCTL_SET_REGION_D3D_PARAM: {
|
|
VencRegionD3DParam *pregion_d3d_param = &recoder->region_d3d_param;
|
|
int total_region_num;
|
|
|
|
if (recoder->config.encodeType == 1) {
|
|
RT_LOGW("not support jpg, return\n");
|
|
return -1;
|
|
}
|
|
|
|
if (copy_from_user(pregion_d3d_param, (void __user *)arg, sizeof(VencRegionD3DParam))) {
|
|
RT_LOGE("IOCTL_SET_REGION_D3D_PARAM copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
RT_LOGD("RegionD3D result_num:%d, Region:%dx%d, Expand:%dx%d, Coef:%d,{%d,%d,%d},{%d,%d,%d,%d}, Th:{%d%%,%d%%,%d%%}\n",
|
|
pregion_d3d_param->result_num,
|
|
pregion_d3d_param->hor_region_num,
|
|
pregion_d3d_param->ver_region_num,
|
|
pregion_d3d_param->hor_expand_num,
|
|
pregion_d3d_param->ver_expand_num,
|
|
pregion_d3d_param->chroma_offset,
|
|
pregion_d3d_param->static_coef[0],
|
|
pregion_d3d_param->static_coef[1],
|
|
pregion_d3d_param->static_coef[2],
|
|
pregion_d3d_param->motion_coef[0],
|
|
pregion_d3d_param->motion_coef[1],
|
|
pregion_d3d_param->motion_coef[2],
|
|
pregion_d3d_param->motion_coef[3],
|
|
(int)pregion_d3d_param->zero_mv_rate_th[0],
|
|
(int)pregion_d3d_param->zero_mv_rate_th[1],
|
|
(int)pregion_d3d_param->zero_mv_rate_th[2]);
|
|
|
|
if (recoder->region_d3d_param.en_region_d3d == 0) {
|
|
if (recoder->region_d3d_region) {
|
|
kfree(recoder->region_d3d_region);
|
|
recoder->region_d3d_region = NULL;
|
|
recoder->region_d3d_region_len = 0;
|
|
}
|
|
} else {
|
|
if (recoder->region_d3d_param.dis_default_para == 0) {
|
|
total_region_num = REGION_D3D_TOTAL_REGION_NUM_DEFAULT;
|
|
} else {
|
|
if ((recoder->region_d3d_param.hor_region_num == 0) || (recoder->region_d3d_param.ver_region_num == 0)) {
|
|
RT_LOGE("IOCTL_SET_REGION_D3D_PARAM invalid params, %d %d\n", recoder->region_d3d_param.hor_region_num,
|
|
recoder->region_d3d_param.ver_region_num);
|
|
return -EFAULT;
|
|
} else {
|
|
total_region_num = recoder->region_d3d_param.hor_region_num * recoder->region_d3d_param.ver_region_num;
|
|
}
|
|
}
|
|
|
|
recoder->region_d3d_region_len = total_region_num * sizeof(VencRegionD3DRegion);
|
|
RT_LOGI("total_region_num %d, region_d3d_region_len %d", total_region_num, recoder->region_d3d_region_len);
|
|
|
|
// free region_d3d_region when disable region_d3d or ioctl_destroy
|
|
recoder->region_d3d_region = kmalloc(recoder->region_d3d_region_len, GFP_KERNEL);
|
|
if (recoder->region_d3d_region == NULL) {
|
|
RT_LOGE("IOCTL_SET_REGION_D3D_PARAM: kmalloc fail\n");
|
|
return -EFAULT;
|
|
}
|
|
memset(recoder->region_d3d_region, 0, recoder->region_d3d_region_len);
|
|
}
|
|
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_REGION_D3D_PARAM, (void *)pregion_d3d_param);
|
|
if (ret != 0) {
|
|
RT_LOGE("VENC COMP_INDEX_VENC_CONFIG_SET_REGION_D3D_PARAM fail\n");
|
|
if (recoder->region_d3d_region) {
|
|
kfree(recoder->region_d3d_region);
|
|
recoder->region_d3d_region = NULL;
|
|
recoder->region_d3d_region_len = 0;
|
|
}
|
|
return -EFAULT;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case IOCTL_GET_REGION_D3D_RESULT: {
|
|
VencRegionD3DResult region_d3d_result;
|
|
VencRegionD3DResult region_d3d_result_from_user;
|
|
|
|
if (recoder->config.encodeType == 1) {
|
|
RT_LOGW("not support jpg, return\n");
|
|
return -1;
|
|
}
|
|
|
|
if (recoder->region_d3d_region == NULL || 0 == recoder->region_d3d_region_len) {
|
|
RT_LOGE("IOCTL_GET_REGION_D3D_RESULT: invalid region_d3d_region\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
memset(®ion_d3d_result_from_user, 0, sizeof(VencRegionD3DResult));
|
|
if (copy_from_user(®ion_d3d_result_from_user, (void __user *)arg, sizeof(VencRegionD3DResult))) {
|
|
RT_LOGE("region_d3d_result_from_user copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
memset(®ion_d3d_result, 0, sizeof(VencRegionD3DResult));
|
|
region_d3d_result.region = recoder->region_d3d_region;
|
|
|
|
ret = comp_get_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_Dynamic_GET_REGION_D3D_RESULT, (void *)®ion_d3d_result);
|
|
if (ret != 0) {
|
|
RT_LOGE("VENC COMP_INDEX_VENC_CONFIG_Dynamic_GET_REGION_D3D_RESULT fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (copy_to_user((void *)region_d3d_result_from_user.region, region_d3d_result.region, recoder->region_d3d_region_len)) {
|
|
RT_LOGE("region copy_to_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
region_d3d_result.region = region_d3d_result_from_user.region;
|
|
if (copy_to_user((void *)arg, ®ion_d3d_result, sizeof(VencRegionD3DResult))) {
|
|
RT_LOGE("region_d3d_result copy_to_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_CHROMA_QP_OFFSET: {
|
|
int nChromaQPOffset = (int)arg;
|
|
|
|
if (recoder->config.encodeType == 1) {
|
|
RT_LOGW("not support jpg, return\n");
|
|
return -1;
|
|
}
|
|
RT_LOGD("nChromaQPOffset %d\n", nChromaQPOffset);
|
|
|
|
if (recoder->venc_comp)
|
|
comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_CHROMA_QP_OFFSET, &nChromaQPOffset);
|
|
break;
|
|
}
|
|
case IOCTL_SET_ENC_AND_DEC_CASE: {
|
|
int bEncAndDecCase = (int)arg;
|
|
|
|
if (recoder->venc_comp)
|
|
comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_ENC_AND_DEC_CASE, &bEncAndDecCase);
|
|
break;
|
|
}
|
|
case IOCTL_SET_H264_CONSTRAINT_FLAG: {
|
|
VencH264ConstraintFlag ConstraintFlag;
|
|
|
|
if (recoder->config.encodeType != 0) {
|
|
RT_LOGW("only support h.264, return\n");
|
|
return -1;
|
|
}
|
|
|
|
memset(&ConstraintFlag, 0, sizeof(VencH264ConstraintFlag));
|
|
|
|
if (copy_from_user(&ConstraintFlag, (void __user *)arg, sizeof(VencH264ConstraintFlag))) {
|
|
RT_LOGE("IOCTL_SET_H264_CONSTRAINT_FLAG copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
RT_LOGD("constraint:%d %d %d %d %d %d", ConstraintFlag.constraint_0, ConstraintFlag.constraint_1,
|
|
ConstraintFlag.constraint_2, ConstraintFlag.constraint_3, ConstraintFlag.constraint_4, ConstraintFlag.constraint_5);
|
|
|
|
if (recoder->venc_comp) {
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_H264_CONSTRAINT_FLAG, (void *)&ConstraintFlag);
|
|
if (ret != 0) {
|
|
RT_LOGE("COMP_INDEX_VENC_CONFIG_SET_H264_CONSTRAINT_FLAG fail\n");
|
|
return -EFAULT;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case IOCTL_SET_VE2ISP_D2D_LIMIT: {
|
|
VencVe2IspD2DLimit D2DLimit;
|
|
|
|
if (recoder->config.encodeType == 1) {
|
|
RT_LOGW("not support jpg, return\n");
|
|
return -1;
|
|
}
|
|
|
|
memset(&D2DLimit, 0, sizeof(VencVe2IspD2DLimit));
|
|
|
|
if (copy_from_user(&D2DLimit, (void __user *)arg, sizeof(VencVe2IspD2DLimit))) {
|
|
RT_LOGE("IOCTL_SET_VE2ISP_D2D_LIMIT copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
RT_LOGD("en_d2d_limit:%d, d2d_level:%d %d %d %d %d %d", D2DLimit.en_d2d_limit,
|
|
D2DLimit.d2d_level[0], D2DLimit.d2d_level[1], D2DLimit.d2d_level[2],
|
|
D2DLimit.d2d_level[3], D2DLimit.d2d_level[4], D2DLimit.d2d_level[5]);
|
|
|
|
if (recoder->venc_comp) {
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_VE2ISP_D2D_LIMIT, (void *)&D2DLimit);
|
|
if (ret != 0) {
|
|
RT_LOGE("COMP_INDEX_VENC_CONFIG_SET_VE2ISP_D2D_LIMIT fail\n");
|
|
return -EFAULT;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case IOCTL_SET_EN_SMALL_SEARCH_RANGE: {
|
|
int nEnSmallSearchRange = (int)arg;
|
|
|
|
if (recoder->config.encodeType == 1) {
|
|
RT_LOGW("not support jpg, return\n");
|
|
return -1;
|
|
}
|
|
|
|
RT_LOGD("nEnSmallSearchRange:%d\n", nEnSmallSearchRange);
|
|
|
|
if (recoder->venc_comp) {
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_EN_SMALL_SEARCH_RANGE, (void *)&nEnSmallSearchRange);
|
|
if (ret != 0) {
|
|
RT_LOGE("COMP_INDEX_VENC_CONFIG_SET_EN_SMALL_SEARCH_RANGE fail\n");
|
|
return -EFAULT;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case IOCTL_SET_FORCE_CONF_WIN: {
|
|
VencForceConfWin ConfWin;
|
|
|
|
if (recoder->config.encodeType == 1) {
|
|
RT_LOGW("not support jpg, return\n");
|
|
return -1;
|
|
}
|
|
|
|
memset(&ConfWin, 0, sizeof(VencForceConfWin));
|
|
|
|
if (copy_from_user(&ConfWin, (void __user *)arg, sizeof(VencForceConfWin))) {
|
|
RT_LOGE("IOCTL_SET_FORCE_CONF_WIN copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
RT_LOGD("en_force_conf:%d, %d %d, %d %d\n", ConfWin.en_force_conf,
|
|
ConfWin.top_offset, ConfWin.bottom_offset, ConfWin.left_offset, ConfWin.right_offset);
|
|
|
|
if (recoder->venc_comp) {
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_FORCE_CONF_WIN, (void *)&ConfWin);
|
|
if (ret != 0) {
|
|
RT_LOGE("COMP_INDEX_VENC_CONFIG_SET_FORCE_CONF_WIN fail\n");
|
|
return -EFAULT;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case IOCTL_SET_ROT_VE2ISP: {
|
|
VencRotVe2Isp RotVe2Isp;
|
|
|
|
if (recoder->config.encodeType == 1) {
|
|
RT_LOGW("not support jpg, return\n");
|
|
return -1;
|
|
}
|
|
|
|
memset(&RotVe2Isp, 0, sizeof(VencRotVe2Isp));
|
|
|
|
if (copy_from_user(&RotVe2Isp, (void __user *)arg, sizeof(VencRotVe2Isp))) {
|
|
RT_LOGE("IOCTL_SET_ROT_VE2ISP copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
RT_LOGD("d2d %d lv_th[%d,%d] lv_level[%d,%d], d3d %d lv_th[%d,%d] lv_level[%d,%d]\n",
|
|
RotVe2Isp.dis_default_d2d, RotVe2Isp.d2d_min_lv_th, RotVe2Isp.d2d_max_lv_th, RotVe2Isp.d2d_min_lv_level, RotVe2Isp.d2d_max_lv_level,
|
|
RotVe2Isp.dis_default_d3d, RotVe2Isp.d3d_min_lv_th, RotVe2Isp.d3d_max_lv_th, RotVe2Isp.d3d_min_lv_level, RotVe2Isp.d3d_max_lv_level);
|
|
|
|
if (recoder->venc_comp) {
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_ROT_VE2ISP, (void *)&RotVe2Isp);
|
|
if (ret != 0) {
|
|
RT_LOGE("COMP_INDEX_VENC_CONFIG_SET_ROT_VE2ISP fail\n");
|
|
return -EFAULT;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case IOCTL_SET_INSERT_DATA: {
|
|
RTVencInsertData InsertData;
|
|
unsigned int insert_data_buf_len = 0;
|
|
|
|
if (recoder->config.encodeType != 1) {
|
|
RT_LOGW("only support jpg, type %d return\n", recoder->config.encodeType);
|
|
return -1;
|
|
}
|
|
|
|
memset(&InsertData, 0, sizeof(RTVencInsertData));
|
|
|
|
if (copy_from_user(&InsertData, (void __user *)arg, sizeof(RTVencInsertData))) {
|
|
RT_LOGE("IOCTL_SET_INSERT_DATA copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
RT_LOGD("set InsertData status:%d, buf:%p, data_len:%d, framerate:%d\n", InsertData.eStatus,
|
|
InsertData.pBuffer, InsertData.nDataLen, InsertData.nFrameRate);
|
|
|
|
if (NULL == InsertData.pBuffer || 0 == InsertData.nDataLen) {
|
|
RT_LOGE("invalid input params! %p,%d\n", InsertData.pBuffer, InsertData.nDataLen);
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (0 < InsertData.nBufLen) {
|
|
insert_data_buf_len = InsertData.nBufLen;
|
|
} else {
|
|
insert_data_buf_len = RT_MAX_INSERT_FRAME_LEN;
|
|
}
|
|
|
|
if (insert_data_buf_len < InsertData.nDataLen) {
|
|
RT_LOGE("invalid input params! data_len %d > %d\n", InsertData.nDataLen, insert_data_buf_len);
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (NULL == recoder->insert_data.pBuffer) {
|
|
recoder->insert_data.pBuffer = kmalloc(insert_data_buf_len, GFP_KERNEL);
|
|
if (NULL == recoder->insert_data.pBuffer) {
|
|
RT_LOGE("kmalloc failed! size=%d\n", InsertData.nDataLen);
|
|
return -EFAULT;
|
|
}
|
|
memset(recoder->insert_data.pBuffer, 0, insert_data_buf_len);
|
|
}
|
|
if (copy_from_user(recoder->insert_data.pBuffer, (void __user *)InsertData.pBuffer, InsertData.nDataLen)) {
|
|
RT_LOGE("IOCTL_SET_INSERT_DATA copy_from_user fail\n");
|
|
if (recoder->insert_data.pBuffer) {
|
|
kfree(recoder->insert_data.pBuffer);
|
|
recoder->insert_data.pBuffer = NULL;
|
|
recoder->insert_data.nDataLen = 0;
|
|
recoder->insert_data.nBufLen = 0;
|
|
}
|
|
return -EFAULT;
|
|
}
|
|
recoder->insert_data.nBufLen = insert_data_buf_len;
|
|
recoder->insert_data.nDataLen = InsertData.nDataLen;
|
|
recoder->insert_data.eStatus = InsertData.eStatus;
|
|
recoder->insert_data.nFrameRate = InsertData.nFrameRate;
|
|
|
|
if (recoder->venc_comp) {
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_INSERT_DATA, (void *)&recoder->insert_data);
|
|
if (ret != 0) {
|
|
RT_LOGE("COMP_INDEX_VENC_CONFIG_SET_INSERT_DATA fail\n");
|
|
if (recoder->insert_data.pBuffer) {
|
|
kfree(recoder->insert_data.pBuffer);
|
|
recoder->insert_data.pBuffer = NULL;
|
|
recoder->insert_data.nDataLen = 0;
|
|
recoder->insert_data.nBufLen = 0;
|
|
}
|
|
return -EFAULT;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case IOCTL_GET_INSERT_DATA_BUF_STATUS: {
|
|
RT_VENC_BUF_STATUS eStatus;
|
|
|
|
if (recoder->config.encodeType != 1) {
|
|
RT_LOGW("only support jpg, type %d return\n", recoder->config.encodeType);
|
|
return -1;
|
|
}
|
|
|
|
ret = comp_get_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_GET_INSERT_DATA_BUF_STATUS, (void *)&eStatus);
|
|
if (ret != 0) {
|
|
RT_LOGE("VENC COMP_INDEX_VENC_CONFIG_GET_INSERT_DATA_BUF_STATUS fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (copy_to_user((void *)arg, &eStatus, sizeof(RT_VENC_BUF_STATUS))) {
|
|
RT_LOGE("IOCTL_GET_INSERT_DATA_BUF_STATUS copy_to_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_GRAY: {
|
|
unsigned int enable_gray = (unsigned int)arg;
|
|
|
|
if (recoder->venc_comp)
|
|
comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_GRAY, &enable_gray);
|
|
break;
|
|
}
|
|
case IOCTL_SET_WB_YUV: {
|
|
RTsWbYuvParam sWbyuvConfig;
|
|
|
|
memset(&sWbyuvConfig, 0, sizeof(RTsWbYuvParam));
|
|
|
|
if (copy_from_user(&sWbyuvConfig, (void __user *)arg, sizeof(RTsWbYuvParam))) {
|
|
RT_LOGE("IOCTL_SET_WB_YUV copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
if (recoder->venc_comp)
|
|
comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_WBYUV, &sWbyuvConfig);
|
|
RT_LOGD("bEnableWbYuv %d bEnableCrop %d scalerRatio %d", sWbyuvConfig.bEnableWbYuv, sWbyuvConfig.bEnableCrop, sWbyuvConfig.scalerRatio);
|
|
break;
|
|
}
|
|
case IOCTL_GET_WB_YUV: {
|
|
RTVencThumbInfo s_wbyuv_info;
|
|
|
|
memset(&s_wbyuv_info, 0, sizeof(RTVencThumbInfo));
|
|
|
|
if (copy_from_user(&s_wbyuv_info, (void __user *)arg, sizeof(RTVencThumbInfo))) {
|
|
RT_LOGE("IOCTL_GET_WB_YUV copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
RT_LOGD("nThumbSize %d %p", s_wbyuv_info.nThumbSize, s_wbyuv_info.pThumbBuf);
|
|
if (recoder->venc_comp) {
|
|
if (comp_get_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_GET_WBYUV, &s_wbyuv_info))
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_2DNR: {
|
|
RTs2DfilterParam s_2dnr_param;
|
|
|
|
memset(&s_2dnr_param, 0, sizeof(RTs2DfilterParam));
|
|
|
|
if (copy_from_user(&s_2dnr_param, (void __user *)arg, sizeof(RTs2DfilterParam))) {
|
|
RT_LOGE("IOCTL_SET_2DNR copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
if (recoder->venc_comp)
|
|
comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_2DNR, &s_2dnr_param);
|
|
break;
|
|
}
|
|
case IOCTL_SET_3DNR: {
|
|
RTs3DfilterParam s_3dnr_param;
|
|
|
|
memset(&s_3dnr_param, 0, sizeof(RTs3DfilterParam));
|
|
|
|
if (copy_from_user(&s_3dnr_param, (void __user *)arg, sizeof(RTs3DfilterParam))) {
|
|
RT_LOGE("IOCTL_SET_3DNR copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
if (recoder->venc_comp)
|
|
comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_3DNR, &s_3dnr_param);
|
|
break;
|
|
}
|
|
case IOCTL_SET_CYCLIC_INTRA_REFRESH: {
|
|
RTVencCyclicIntraRefresh s_intra_refresh;
|
|
|
|
memset(&s_intra_refresh, 0, sizeof(RTVencCyclicIntraRefresh));
|
|
|
|
if (copy_from_user(&s_intra_refresh, (void __user *)arg, sizeof(RTVencCyclicIntraRefresh))) {
|
|
RT_LOGE("IOCTL_SET_CYCLIC_INTRA_REFRESH copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
if (recoder->venc_comp)
|
|
comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_CYCLE_INTRA_REFRESH, &s_intra_refresh);
|
|
break;
|
|
}
|
|
case IOCTL_SET_P_FRAME_INTRA: {
|
|
unsigned int enable_p_intra = (unsigned int)arg;
|
|
|
|
if (recoder->venc_comp)
|
|
comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_P_FRAME_INTRA, &enable_p_intra);
|
|
break;
|
|
}
|
|
case IOCTL_RESET_IN_OUT_BUFFER: {
|
|
comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_FLUSH_IN_BUFFER, NULL);
|
|
flush_stream_buff(recoder);
|
|
if (recoder->venc_comp)
|
|
comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_RESET_VE_INOUT_BUFFER, NULL);
|
|
break;
|
|
}
|
|
case IOCTL_GET_SENSOR_RESERVE_ADDR: {
|
|
SENSOR_ISP_CONFIG_S sensor_isp_config;
|
|
memset(&sensor_isp_config, 0, sizeof(SENSOR_ISP_CONFIG_S));
|
|
if (recoder->vi_comp)
|
|
comp_get_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_GET_SENSOR_RESERVE_ADDR, &sensor_isp_config);
|
|
if (copy_to_user((void *)arg, &sensor_isp_config, sizeof(SENSOR_ISP_CONFIG_S))) {
|
|
RT_LOGE("IOCTL_GET_SENSOR_RESERVE_ADDR copy_to_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_DROP_FRAME: {
|
|
int nDropNum = (int)arg;
|
|
if (recoder->venc_comp) {
|
|
comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_DROP_FRAME, &nDropNum);
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_CAMERA_MOVE_STATUS: {
|
|
RT_VENC_CAMERA_MOVE_STATUS camera_move_status = (RT_VENC_CAMERA_MOVE_STATUS)arg;
|
|
if (recoder->venc_comp) {
|
|
comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_CAMERA_MOVE_STATUS, &camera_move_status);
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_SET_CROP: {
|
|
RTCropInfo s_crop_info;
|
|
|
|
memset(&s_crop_info, 0, sizeof(RTCropInfo));
|
|
|
|
if (copy_from_user(&s_crop_info, (void __user *)arg, sizeof(RTCropInfo))) {
|
|
RT_LOGE("IOCTL_SET_CROP copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
if (recoder->venc_comp)
|
|
comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_SET_CROP, &s_crop_info);
|
|
break;
|
|
}
|
|
case IOCTL_SET_VENC_TARTGET_BITS_CLIP_PARAM: {
|
|
RT_VENC_TARGET_BITS_CLIP_PARAM rt_venc_target_bits_clip_param;
|
|
if (recoder->config.encodeType == 1) {
|
|
RT_LOGW("not support jpg, return\n");
|
|
return -1;
|
|
}
|
|
memset(&rt_venc_target_bits_clip_param, 0, sizeof(RT_VENC_TARGET_BITS_CLIP_PARAM));
|
|
if (copy_from_user(&rt_venc_target_bits_clip_param, (void __user *)arg, sizeof(RT_VENC_TARGET_BITS_CLIP_PARAM))) {
|
|
RT_LOGE("venc_target_bits_clip_param copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
if (recoder->venc_comp) {
|
|
ret = comp_set_config(recoder->venc_comp, COMP_INDEX_VENC_CONFIG_TARGET_BITS_CLIP_PARAM, (void *)&rt_venc_target_bits_clip_param);
|
|
if (ret != 0) {
|
|
RT_LOGE("VENC COMP_INDEX_VENC_CONFIG_TARGET_BITS_CLIP_PARAM fail\n");
|
|
return -EFAULT;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_GET_ISP_REG: {
|
|
//Copy VIN_ISP_REG_GET_CFG struct param from user space
|
|
VIN_ISP_REG_GET_CFG isp_reg_get_cfg;
|
|
memset(&isp_reg_get_cfg, 0, sizeof(isp_reg_get_cfg));
|
|
if (copy_from_user(&isp_reg_get_cfg, (void __user *)arg, sizeof(isp_reg_get_cfg))) {
|
|
RT_LOGE("IOCTL_GET_ISP_REG copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (isp_reg_get_cfg.flag == 0) {
|
|
//Call VI component interface to get isp reg
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_GET_ISP_REG_CONFIG, (void *)&isp_reg_get_cfg);
|
|
} else if (isp_reg_get_cfg.flag == 1) {
|
|
//Copy isp reg save file path from user space
|
|
char save_file_path[isp_reg_get_cfg.len + 1];
|
|
memset(save_file_path, 0, sizeof(save_file_path));
|
|
if (copy_from_user(save_file_path, (void __user *)isp_reg_get_cfg.path, isp_reg_get_cfg.len)) {
|
|
RT_LOGE("IOCTL_GET_ISP_REG isp reg save file path copy_from_user fail\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
//Call VI component interface to get isp reg
|
|
isp_reg_get_cfg.path = save_file_path;
|
|
ret = comp_set_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_GET_ISP_REG_CONFIG, (void *)&isp_reg_get_cfg);
|
|
}
|
|
|
|
//ioctl error
|
|
if (ret < 0) {
|
|
RT_LOGE("IOCTL_GET_ISP_REG failed, ret = %d", ret);
|
|
return -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
RT_LOGE("not support cmd: %d", cmd);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct file_operations rt_media_fops = {
|
|
.owner = THIS_MODULE,
|
|
.mmap = fops_mmap,
|
|
.open = fops_open,
|
|
.release = fops_release,
|
|
.llseek = no_llseek,
|
|
.unlocked_ioctl = fops_ioctl,
|
|
#ifdef CONFIG_COMPAT
|
|
.compat_ioctl = fops_ioctl,
|
|
#endif
|
|
};
|
|
|
|
#if defined(CONFIG_OF)
|
|
static struct of_device_id rt_media_match[] = {
|
|
{
|
|
.compatible = "allwinner,rt-media",
|
|
},
|
|
{}
|
|
};
|
|
MODULE_DEVICE_TABLE(of, rt_media_match);
|
|
#endif
|
|
|
|
#ifdef CONFIG_PM
|
|
static int rt_media_suspend(struct platform_device *pdev, pm_message_t state)
|
|
{
|
|
/* todo */
|
|
RT_LOGD("[cedar] standby suspend\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int rt_media_resume(struct platform_device *pdev)
|
|
{
|
|
/* todo */
|
|
RT_LOGD("[cedar] standby resume\n");
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
static int rt_is_sensor_0(int vipp_num)
|
|
{
|
|
if (vipp_num == CSI_SENSOR_0_VIPP_0
|
|
|| vipp_num == CSI_SENSOR_0_VIPP_1
|
|
|| vipp_num == CSI_SENSOR_0_VIPP_2
|
|
|| vipp_num == CSI_SENSOR_0_VIPP_3
|
|
)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int rt_is_sensor_1(int vipp_num)
|
|
{
|
|
if (vipp_num == CSI_SENSOR_1_VIPP_0
|
|
|| vipp_num == CSI_SENSOR_1_VIPP_1
|
|
|| vipp_num == CSI_SENSOR_1_VIPP_2
|
|
|| vipp_num == CSI_SENSOR_1_VIPP_3
|
|
)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int rt_is_sensor_2(int vipp_num)
|
|
{
|
|
if (vipp_num == CSI_SENSOR_2_VIPP_0
|
|
|| vipp_num == CSI_SENSOR_2_VIPP_1
|
|
|| vipp_num == CSI_SENSOR_2_VIPP_2
|
|
|| vipp_num == CSI_SENSOR_2_VIPP_3
|
|
)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int rt_which_sensor(int vipp_num)
|
|
{
|
|
switch (vipp_num) {
|
|
case CSI_SENSOR_0_VIPP_0:
|
|
case CSI_SENSOR_0_VIPP_1:
|
|
case CSI_SENSOR_0_VIPP_2:
|
|
case CSI_SENSOR_0_VIPP_3:
|
|
return 0;
|
|
case CSI_SENSOR_1_VIPP_0:
|
|
case CSI_SENSOR_1_VIPP_1:
|
|
case CSI_SENSOR_1_VIPP_2:
|
|
case CSI_SENSOR_1_VIPP_3:
|
|
return 1;
|
|
case CSI_SENSOR_2_VIPP_0:
|
|
case CSI_SENSOR_2_VIPP_1:
|
|
case CSI_SENSOR_2_VIPP_2:
|
|
case CSI_SENSOR_2_VIPP_3:
|
|
return 2;
|
|
default:
|
|
return 0;//default sensor 0
|
|
}
|
|
|
|
return 0;//default sensor 0
|
|
}
|
|
|
|
static int setup_recoder_config(int channel_id)
|
|
{
|
|
int ret = 0;
|
|
video_recoder *recoder = &rt_media_devp->recoder[channel_id];
|
|
rt_media_config_s config;
|
|
struct vi_part_cfg vi_part_cfg;
|
|
encode_config *venc_cfg = &rt_media_devp->enc_conf[rt_which_sensor(channel_id)];
|
|
|
|
memset(&config, 0, sizeof(rt_media_config_s));
|
|
config.channelId = channel_id;
|
|
config.encodeType = venc_cfg->codec_type;
|
|
config.width = venc_cfg->res_w;
|
|
config.height = venc_cfg->res_h;
|
|
config.fps = venc_cfg->fps;
|
|
config.bitrate = venc_cfg->bit_rate;
|
|
config.gop = venc_cfg->gop;
|
|
config.vbr = venc_cfg->vbr;
|
|
config.product_mode = venc_cfg->product_mode;
|
|
config.qp_range.i_init_qp = venc_cfg->qp_range.i_init_qp;
|
|
config.qp_range.i_min_qp = venc_cfg->qp_range.i_min_qp;
|
|
config.qp_range.i_max_qp = venc_cfg->qp_range.i_max_qp;
|
|
config.qp_range.p_min_qp = venc_cfg->qp_range.p_min_qp;
|
|
config.qp_range.p_max_qp = venc_cfg->qp_range.p_max_qp;
|
|
config.qp_range.enable_mb_qp_limit = venc_cfg->qp_range.enable_mb_qp_limit;
|
|
config.vbr_param.nMovingTh = venc_cfg->vbr_param.nMovingTh;
|
|
config.vbr_param.nQuality = venc_cfg->vbr_param.nQuality;
|
|
config.vbr_param.nIFrmBitsCoef = venc_cfg->vbr_param.nIFrmBitsCoef;
|
|
config.vbr_param.nPFrmBitsCoef = venc_cfg->vbr_param.nPFrmBitsCoef;
|
|
ret = wdr_get_from_partition(&vi_part_cfg, rt_which_sensor(channel_id));
|
|
if (!ret) {
|
|
RT_LOGW("get info fram part: w&h = %d, %d, venc_format = %d, wdr = %d, flicker = %d",
|
|
vi_part_cfg.width, vi_part_cfg.height, vi_part_cfg.venc_format,
|
|
vi_part_cfg.wdr, vi_part_cfg.flicker_mode);
|
|
|
|
if (vi_part_cfg.width && vi_part_cfg.height) {
|
|
config.width = vi_part_cfg.width;
|
|
config.height = vi_part_cfg.height;
|
|
}
|
|
|
|
if (vi_part_cfg.venc_format == 2)
|
|
config.encodeType = 2;
|
|
else if (vi_part_cfg.venc_format == 1)
|
|
config.encodeType = 0;
|
|
|
|
//if (vi_part_cfg.flicker_mode == 1)
|
|
// config.fps = 16;
|
|
config.fps = vi_part_cfg.fps;
|
|
config.enable_wdr = vi_part_cfg.wdr;
|
|
}
|
|
config.profile = AW_Video_H264ProfileMain;
|
|
config.level = AW_Video_H264Level51;
|
|
config.drop_frame_num = 0;
|
|
config.output_mode = venc_cfg->out_mode;
|
|
config.pixelformat = venc_cfg->pix_fmt;
|
|
|
|
config.venc_video_signal.video_format = DEFAULT;
|
|
config.venc_video_signal.full_range_flag = 1;
|
|
config.venc_video_signal.src_colour_primaries = VENC_BT709;
|
|
config.venc_video_signal.dst_colour_primaries = VENC_BT709;
|
|
config.breduce_refrecmem = venc_cfg->reduce_refrec_mem;
|
|
config.enable_sharp = venc_cfg->enable_sharp;
|
|
config.tdm_rxbuf_cnt = venc_cfg->tdm_rxbuf_cnt;
|
|
config.enable_aiisp = venc_cfg->aiisp_en;
|
|
|
|
ret = ioctl_config(recoder, &config);
|
|
if (ret != 0) {
|
|
RT_LOGE("config err ret %d", ret);
|
|
ioctl_destroy(recoder);
|
|
return -1;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
static int setup_recoder(void)
|
|
{
|
|
#if defined CONFIG_RT_MEDIA_SINGEL_SENSOR || defined CONFIG_RT_MEDIA_DUAL_SENSOR || defined CONFIG_RT_MEDIA_THREE_SENSOR
|
|
int single_channel_id = CSI_SENSOR_0_VIPP_0;
|
|
video_recoder *recoder_single = &rt_media_devp->recoder[single_channel_id];
|
|
#endif
|
|
#if defined CONFIG_RT_MEDIA_DUAL_SENSOR || defined CONFIG_RT_MEDIA_THREE_SENSOR
|
|
int dual_channel_id = CSI_SENSOR_1_VIPP_0;
|
|
video_recoder *recoder_dual = &rt_media_devp->recoder[dual_channel_id];
|
|
#endif
|
|
#if defined CONFIG_RT_MEDIA_THREE_SENSOR
|
|
int three_channel_id = CSI_SENSOR_2_VIPP_0;
|
|
video_recoder *recoder_three = &rt_media_devp->recoder[three_channel_id];
|
|
#endif
|
|
|
|
RT_LOGW("* start setup_recoder");
|
|
|
|
#if defined CONFIG_RT_MEDIA_SINGEL_SENSOR || defined CONFIG_RT_MEDIA_DUAL_SENSOR || defined CONFIG_RT_MEDIA_THREE_SENSOR
|
|
setup_recoder_config(single_channel_id);
|
|
if (recoder_single->bvin_is_ready || bvin_is_ready_rt_not_probe[single_channel_id]) {
|
|
rt_media_devp->bcsi_status_set[single_channel_id] = 1;
|
|
ioctl_start(recoder_single);
|
|
} else {
|
|
recoder_single->bsetup_recorder_finish = 1;
|
|
}
|
|
#endif
|
|
|
|
#if defined CONFIG_RT_MEDIA_DUAL_SENSOR || defined CONFIG_RT_MEDIA_THREE_SENSOR
|
|
setup_recoder_config(dual_channel_id);
|
|
if (recoder_dual->bvin_is_ready || bvin_is_ready_rt_not_probe[dual_channel_id]) {
|
|
rt_media_devp->bcsi_status_set[dual_channel_id] = 1;
|
|
ioctl_start(recoder_dual);
|
|
} else {
|
|
recoder_dual->bsetup_recorder_finish = 1;
|
|
}
|
|
#endif
|
|
|
|
#if defined CONFIG_RT_MEDIA_THREE_SENSOR
|
|
setup_recoder_config(three_channel_id);
|
|
if (recoder_three->bvin_is_ready || bvin_is_ready_rt_not_probe[three_channel_id]) {
|
|
rt_media_devp->bcsi_status_set[three_channel_id] = 1;
|
|
ioctl_start(recoder_three);
|
|
} else {
|
|
recoder_three->bsetup_recorder_finish = 1;
|
|
}
|
|
#endif
|
|
RT_LOGW("finish");
|
|
return 0;
|
|
}
|
|
|
|
int rt_vin_is_ready(int channel_id)
|
|
{
|
|
int ret = 0;
|
|
RT_LOGD("rt_vin_is_ready vinc%d", channel_id);
|
|
if (rt_media_devp) {
|
|
video_recoder *recoder = &rt_media_devp->recoder[channel_id];
|
|
rt_media_devp->bcsi_status_set[channel_id] = 1;
|
|
if (recoder->bsetup_recorder_finish) {
|
|
ioctl_start(recoder);
|
|
} else {
|
|
RT_LOGW("%d rt_media thread not ready", channel_id);
|
|
recoder->bvin_is_ready = 1;
|
|
}
|
|
} else {
|
|
RT_LOGW("%d rt_media not probe yet", channel_id);
|
|
bvin_is_ready_rt_not_probe[channel_id] = 1;
|
|
g_csi_status_pair[channel_id].bset = 1;
|
|
g_csi_status_pair[channel_id].status = 1;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(rt_vin_is_ready);
|
|
|
|
int rt_vin_buf_info_get(int channel_id, int *buf_num, int *buf_size)
|
|
{
|
|
int ret = 0;
|
|
RT_LOGD("rt_vin_buf_info_get vinc%d", channel_id);
|
|
if (rt_media_devp) {
|
|
video_recoder *recoder = &rt_media_devp->recoder[channel_id];
|
|
if (recoder->vi_comp) {
|
|
vi_bkbuf_info bkbuf_info;
|
|
memset(&bkbuf_info, 0, sizeof(vi_bkbuf_info));
|
|
comp_get_config(recoder->vi_comp, COMP_INDEX_VI_CONFIG_Dynamic_GET_BKBUF_INFO, (void *)&bkbuf_info);
|
|
*buf_num = bkbuf_info.buf_num;
|
|
*buf_size = bkbuf_info.buf_size;
|
|
} else {
|
|
RT_LOGD("%d rt vi_comp is NULL", channel_id);
|
|
*buf_num = 0;
|
|
*buf_size = 0;
|
|
}
|
|
} else {
|
|
RT_LOGD("%d rt_media not probe yet", channel_id);
|
|
*buf_num = 0;
|
|
*buf_size = 0;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(rt_vin_buf_info_get);
|
|
|
|
static int thread_setup(void *param)
|
|
{
|
|
setup_recoder();
|
|
RT_LOGW("finish");
|
|
return 0;
|
|
}
|
|
|
|
static int rt_get_venc_config(struct device_node *node, encode_config *config)
|
|
{
|
|
int i = 0;
|
|
struct device_node *child;
|
|
|
|
for_each_available_child_of_node(node, child) {
|
|
config->name = of_get_property(child, "name", NULL);
|
|
// if (config->name)
|
|
// RT_LOGW("%d Found child node: %s\n", i, config->name);
|
|
config->b_get_from_dts = 1;
|
|
of_property_read_u32(child, "ch_id", &config->ch_id);
|
|
of_property_read_u32(child, "codec_type", &config->codec_type);
|
|
of_property_read_u32(child, "res_w", &config->res_w);
|
|
of_property_read_u32(child, "res_h", &config->res_h);
|
|
of_property_read_u32(child, "fps", &config->fps);
|
|
of_property_read_u32(child, "bit_rate", &config->bit_rate);
|
|
of_property_read_u32(child, "gop", &config->gop);
|
|
of_property_read_u32(child, "enable_sharp", &config->enable_sharp);
|
|
of_property_read_u32(child, "product_mode", &config->product_mode);
|
|
of_property_read_u32(child, "vbr", &config->vbr);
|
|
of_property_read_u32(child, "init_qp", &config->qp_range.i_init_qp);
|
|
of_property_read_u32(child, "i_min_qp", &config->qp_range.i_min_qp);
|
|
of_property_read_u32(child, "i_max_qp", &config->qp_range.i_max_qp);
|
|
of_property_read_u32(child, "p_min_qp", &config->qp_range.p_min_qp);
|
|
of_property_read_u32(child, "p_max_qp", &config->qp_range.p_max_qp);
|
|
of_property_read_u32(child, "enable_mb_qp_limit", &config->qp_range.enable_mb_qp_limit);
|
|
of_property_read_u32(child, "moving_th", &config->vbr_param.nMovingTh);
|
|
of_property_read_u32(child, "quality", &config->vbr_param.nQuality);
|
|
of_property_read_u32(child, "i_frm_bits_coef", &config->vbr_param.nIFrmBitsCoef);
|
|
of_property_read_u32(child, "p_frm_bits_coef", &config->vbr_param.nPFrmBitsCoef);
|
|
of_property_read_u32(child, "out_mode", &config->out_mode);
|
|
of_property_read_u32(child, "pix_fmt", &config->pix_fmt);
|
|
of_property_read_u32(child, "reduce_refrec_mem", &config->reduce_refrec_mem);
|
|
of_property_read_u32(child, "aiisp_en", &config->aiisp_en);
|
|
of_property_read_u32(child, "tdm_rxbuf_cnt", &config->tdm_rxbuf_cnt);
|
|
i++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#if defined CONFIG_VIN_INIT_MELIS
|
|
static int rt_media_csi_err(void *dev, void *data, int len)
|
|
{
|
|
RT_LOGE("melis rpmsg notify csi is err");
|
|
rt_media_devp->bcsi_err = 1;
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
static int rt_media_probe(struct platform_device *pdev)
|
|
{
|
|
int i = 0;
|
|
int ret = 0;
|
|
int devno;
|
|
struct sched_param param = {.sched_priority = 1 };
|
|
|
|
#if defined(CONFIG_OF)
|
|
struct device_node *node;
|
|
#endif
|
|
dev_t dev;
|
|
|
|
dev = 0;
|
|
|
|
RT_LOGW("rt_media install start!!!\n");
|
|
|
|
#if defined(CONFIG_OF)
|
|
node = pdev->dev.of_node;
|
|
#endif
|
|
/*register or alloc the device number.*/
|
|
if (g_rt_media_dev_major) {
|
|
dev = MKDEV(g_rt_media_dev_major, g_rt_media_dev_minor);
|
|
ret = register_chrdev_region(dev, 1, "rt-media");
|
|
} else {
|
|
ret = alloc_chrdev_region(&dev, g_rt_media_dev_minor, 1, "rt-media");
|
|
g_rt_media_dev_major = MAJOR(dev);
|
|
g_rt_media_dev_minor = MINOR(dev);
|
|
}
|
|
|
|
if (ret < 0) {
|
|
RT_LOGW("rt_media_dev: can't get major %d\n", g_rt_media_dev_major);
|
|
return ret;
|
|
}
|
|
|
|
rt_media_devp = kmalloc(sizeof(struct rt_media_dev), GFP_KERNEL);
|
|
if (rt_media_devp == NULL) {
|
|
RT_LOGW("malloc mem for cedar device err\n");
|
|
return -ENOMEM;
|
|
}
|
|
memset(rt_media_devp, 0, sizeof(struct rt_media_dev));
|
|
rt_media_devp->platform_dev = &pdev->dev;
|
|
|
|
for (i = 0; i < VIDEO_INPUT_CHANNEL_NUM; i++) {
|
|
rt_media_devp->recoder[i].state = RT_MEDIA_STATE_IDLE;
|
|
#if !defined CONFIG_VIN_INIT_MELIS
|
|
//if e907 not enable, default vin is ready.
|
|
rt_media_devp->bcsi_status_set[i] = 1;
|
|
rt_media_devp->recoder[i].bvin_is_ready = 1;
|
|
#endif
|
|
}
|
|
|
|
#if defined CONFIG_VIN_INIT_MELIS
|
|
rpmsg_notify_add("e907_rproc@0", "rt-media", rt_media_csi_err, rt_media_devp);
|
|
#endif
|
|
|
|
struct device_node *child;
|
|
int ii = 0;
|
|
for_each_available_child_of_node(node, child) {
|
|
const char *name = of_get_property(child, "name", NULL);
|
|
// if (name)
|
|
// RT_LOGW("%d Found child node: %s\n", ii, name);
|
|
if (MAX_SENSOR_NUM > ii)
|
|
rt_get_venc_config(child, &rt_media_devp->enc_conf[ii]);
|
|
ii++;
|
|
}
|
|
#if 0//for debug
|
|
for (ii = 0; ii < MAX_SENSOR_NUM; ii++) {
|
|
if (rt_media_devp->enc_conf[ii].b_get_from_dts) {
|
|
encode_config *venc_conf = &rt_media_devp->enc_conf[ii];
|
|
if (venc_conf->name)
|
|
RT_LOGW("%s: ", venc_conf->name);
|
|
if (venc_conf->res_w == 0 || venc_conf->res_h == 0)
|
|
RT_LOGW("res_w res_h is 0, will use default param");
|
|
else {
|
|
RT_LOGW("ch_id %d codec_type %d res_wh %dx%d fps %d bitrate %d gop %d enable_sharp %d",\
|
|
venc_conf->ch_id, venc_conf->codec_type, venc_conf->res_w, venc_conf->res_h, \
|
|
venc_conf->fps, venc_conf->bit_rate, venc_conf->gop, venc_conf->enable_sharp);
|
|
RT_LOGW("ch_id %d out_mode %d pixfmt %d reduce_refrec_mem %d aiisp_en %d tdm_rxbuf_cnt %d",\
|
|
venc_conf->ch_id, venc_conf->out_mode, venc_conf->pix_fmt, venc_conf->reduce_refrec_mem, \
|
|
venc_conf->aiisp_en, venc_conf->tdm_rxbuf_cnt);
|
|
RT_LOGW("ch_id %d vbr %d product_mode %d init_qp %d i_min_qp %d i_max_qp %d p_min_qp %d p_max_qp %d",\
|
|
venc_conf->ch_id, venc_conf->vbr, venc_conf->product_mode, \
|
|
venc_conf->qp_range.i_init_qp, venc_conf->qp_range.i_min_qp, \
|
|
venc_conf->qp_range.i_max_qp, venc_conf->qp_range.p_min_qp, venc_conf->qp_range.p_max_qp);
|
|
RT_LOGW("ch_id %d moving_th %d quality %d i_frm_bits_coef %d p_frm_bits_coef %d\n",\
|
|
venc_conf->ch_id, venc_conf->vbr_param.nMovingTh, \
|
|
venc_conf->vbr_param.nQuality, venc_conf->vbr_param.nIFrmBitsCoef, venc_conf->vbr_param.nPFrmBitsCoef);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
/* Create char device */
|
|
devno = MKDEV(g_rt_media_dev_major, g_rt_media_dev_minor);
|
|
cdev_init(&rt_media_devp->cdev, &rt_media_fops);
|
|
rt_media_devp->cdev.owner = THIS_MODULE;
|
|
/* rt_media_devp->cdev.ops = &rt_media_fops; */
|
|
ret = cdev_add(&rt_media_devp->cdev, devno, 1);
|
|
if (ret)
|
|
RT_LOGW("Err:%d add cedardev", ret);
|
|
rt_media_devp->class = class_create(THIS_MODULE, "rt-media");
|
|
rt_media_devp->dev = device_create(rt_media_devp->class, NULL, devno, NULL, "rt-media");
|
|
|
|
RT_LOGW("rt_media install end!!!\n");
|
|
RT_LOGD("rt_media_devp %d vi%p ven%p", rt_media_devp->recoder[0].activate_vi_flag, rt_media_devp->recoder[0].vi_comp, rt_media_devp->recoder[0].venc_comp);
|
|
#if defined CONFIG_RT_MEDIA_SETUP_RECORDER_IN_KERNEL && defined CONFIG_VIDEO_RT_MEDIA
|
|
if (!rt_media_devp->bcsi_err) {
|
|
rt_media_devp->setup_thread = kthread_create(thread_setup, rt_media_devp, "rt_media thread");
|
|
sched_setscheduler(rt_media_devp->setup_thread, SCHED_FIFO, ¶m);
|
|
wake_up_process(rt_media_devp->setup_thread);
|
|
}
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
static int rt_media_remove(struct platform_device *pdev)
|
|
{
|
|
dev_t dev;
|
|
|
|
dev = MKDEV(g_rt_media_dev_major, g_rt_media_dev_minor);
|
|
|
|
/* Destroy char device */
|
|
if (rt_media_devp) {
|
|
if (rt_media_devp->setup_thread)
|
|
kthread_stop(rt_media_devp->setup_thread);
|
|
|
|
if (rt_media_devp->reset_high_fps_thread)
|
|
kthread_stop(rt_media_devp->reset_high_fps_thread);
|
|
|
|
cdev_del(&rt_media_devp->cdev);
|
|
device_destroy(rt_media_devp->class, dev);
|
|
class_destroy(rt_media_devp->class);
|
|
}
|
|
|
|
unregister_chrdev_region(dev, 1);
|
|
|
|
kfree(rt_media_devp);
|
|
return 0;
|
|
}
|
|
|
|
static struct platform_driver rt_media_driver = {
|
|
.probe = rt_media_probe,
|
|
.remove = rt_media_remove,
|
|
#if defined(CONFIG_PM)
|
|
.suspend = rt_media_suspend,
|
|
.resume = rt_media_resume,
|
|
#endif
|
|
.driver = {
|
|
.name = "rt-media",
|
|
.owner = THIS_MODULE,
|
|
|
|
#if defined(CONFIG_OF)
|
|
.of_match_table = rt_media_match,
|
|
#endif
|
|
},
|
|
};
|
|
|
|
static int __init rt_media_module_init(void)
|
|
{
|
|
rt_media_genetlink_init();
|
|
/*need not to register device here,because the device is registered by device tree */
|
|
/*platform_device_register(&sunxi_device_cedar);*/
|
|
RT_LOGD("rt_media version 0.1\n");
|
|
return platform_driver_register(&rt_media_driver);
|
|
}
|
|
|
|
static void __exit rt_media_module_exit(void)
|
|
{
|
|
rt_media_genetlink_exit();
|
|
platform_driver_unregister(&rt_media_driver);
|
|
}
|
|
|
|
fs_initcall(rt_media_module_init);
|
|
//late_initcall(rt_media_module_init);
|
|
|
|
module_exit(rt_media_module_exit);
|
|
|
|
MODULE_AUTHOR("Soft-wxw");
|
|
MODULE_DESCRIPTION("User rt-media interface");
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_VERSION("rt-v1.0");
|
|
MODULE_ALIAS("platform:rt-media");
|
|
|
|
//* todo
|