2361 lines
70 KiB
C
2361 lines
70 KiB
C
|
|
#include <linux/sched.h>
|
|
#include <linux/kthread.h>
|
|
#include <linux/wait.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/module.h>
|
|
#include <linux/fs.h>
|
|
#define LOG_TAG "rt_vi_comp"
|
|
|
|
#include "rt_common.h"
|
|
#include "rt_vi_component.h"
|
|
#include "rt_message.h"
|
|
#include "vin_video_api.h"
|
|
|
|
#include "mem_interface.h"
|
|
|
|
|
|
#define RT_VI_SHOW_TIME_COST (0)
|
|
|
|
#define CLEAR(x) (memset(&(x), 0, sizeof(x)))
|
|
|
|
struct vi_comp_ctx *g_vi_comp[VIDEO_INPUT_CHANNEL_NUM];
|
|
|
|
static int64_t time_vi_start;
|
|
static int64_t time_first_cb;
|
|
|
|
static int callback_count;
|
|
|
|
typedef struct vi_comp_ctx {
|
|
comp_state_type state;
|
|
struct task_struct *vi_thread;
|
|
message_queue_t msg_queue;
|
|
comp_callback_type *callback;
|
|
void *callback_data;
|
|
rt_component_type *self_comp;
|
|
wait_queue_head_t wait_reply[WAIT_REPLY_NUM];
|
|
unsigned int wait_reply_condition[WAIT_REPLY_NUM];
|
|
vi_outbuf_manager out_buf_manager;
|
|
comp_tunnel_info in_port_tunnel_info;
|
|
comp_tunnel_info out_port_tunnel_info;
|
|
vi_comp_base_config base_config;
|
|
vi_comp_normal_config normal_config;
|
|
config_yuv_buf_info yuv_buf_info;
|
|
int config_yuv_buf_flag;
|
|
int align_width;
|
|
int align_height;
|
|
int buf_size;
|
|
int buf_num;
|
|
struct vin_buffer *vin_buf;
|
|
int vipp_id;
|
|
struct mem_interface *memops;
|
|
|
|
spinlock_t vi_spin_lock;
|
|
wait_queue_head_t wait_in_buf;
|
|
unsigned int wait_in_buf_condition;
|
|
int catch_jpeg_flag;
|
|
int max_fps;
|
|
|
|
vi_lbc_fill_param s_vi_lbc_fill_param;
|
|
rt_yuv_info s_yuv_info[CONFIG_YUV_BUF_NUM];
|
|
} vi_comp_ctx;
|
|
|
|
static int thread_process_vi(void *param);
|
|
|
|
static int config_videostream_by_vinbuf(void *vi_comp, video_frame_s *pvideo_stream,
|
|
struct vin_buffer *pvin_buf)
|
|
{
|
|
vi_comp_ctx *pvi_comp = (vi_comp_ctx *)vi_comp;
|
|
int y_size = pvi_comp->align_width * pvi_comp->align_height;
|
|
unsigned char *phy_addr = pvin_buf->paddr;
|
|
unsigned char *vir_addr = cdc_mem_get_vir(pvi_comp->memops, (unsigned long)phy_addr);
|
|
|
|
pvideo_stream->pts = (uint64_t)(pvin_buf->vb.vb2_buf.timestamp/1000);
|
|
pvideo_stream->phy_addr[0] = (unsigned int)phy_addr;
|
|
pvideo_stream->phy_addr[1] = (unsigned int)(phy_addr + y_size);
|
|
pvideo_stream->vir_addr[0] = (void *)vir_addr;
|
|
pvideo_stream->vir_addr[1] = (void *)(vir_addr + y_size);
|
|
pvideo_stream->private = (void *)pvin_buf;
|
|
pvideo_stream->buf_size = pvi_comp->buf_size;
|
|
if (pvi_comp->vipp_id == 0)
|
|
RT_LOGI("boot id = %d, video pts = %llu us, cur_time = %llu us,",
|
|
pvi_comp->vipp_id, pvideo_stream->pts, ktime_get_ns() / 1000);
|
|
return 0;
|
|
}
|
|
|
|
static int rt_is_lbc_format(vi_comp_ctx *vi_comp)
|
|
{
|
|
if (vi_comp->base_config.pixelformat == RT_PIXEL_LBC_25X
|
|
|| vi_comp->base_config.pixelformat == RT_PIXEL_LBC_2X)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
static int rt_need_fill_data(vi_comp_ctx *vi_comp)
|
|
{
|
|
int vipp_id = vi_comp->base_config.channel_id;
|
|
int en_encpp = 0;
|
|
|
|
vin_get_encpp_cfg(vipp_id, RT_CTRL_ENCPP_EN, &en_encpp);
|
|
|
|
if (en_encpp && vi_comp->base_config.en_16_align_fill_data
|
|
&& vi_comp->base_config.height != vi_comp->align_height) {
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
void vin_buffer_callback(int id)
|
|
{
|
|
vi_comp_ctx *vi_comp = g_vi_comp[id];
|
|
|
|
RT_LOGI("callback, id = %d", id);
|
|
|
|
time_first_cb = get_cur_time();
|
|
callback_count++;
|
|
|
|
if (callback_count == 1)
|
|
RT_LOGW("callback, time = %lld", time_first_cb - time_vi_start);
|
|
|
|
vi_comp->wait_in_buf_condition = 1;
|
|
wake_up(&vi_comp->wait_in_buf);
|
|
|
|
return;
|
|
}
|
|
|
|
#if 1//lbc fill data function.
|
|
static void lbcLine_StmWrBit(VI_DMA_LBC_BS_S *bs, unsigned int word, unsigned int len)
|
|
{
|
|
if (NULL == bs) {
|
|
return;
|
|
}
|
|
bs->cnt++;
|
|
bs->sum = bs->sum + len;
|
|
|
|
while (len > 0) {
|
|
if (len < 32) {
|
|
word = word & ((1 << len) - 1);
|
|
}
|
|
|
|
if (bs->left_bits > len) {
|
|
*bs->cur_buf_ptr = *bs->cur_buf_ptr | (word << (8 - bs->left_bits));
|
|
bs->left_bits = bs->left_bits - len;
|
|
break;
|
|
} else {
|
|
*bs->cur_buf_ptr = *bs->cur_buf_ptr | (word << (8 - bs->left_bits));
|
|
len = len - bs->left_bits;
|
|
word = word >> bs->left_bits;
|
|
bs->left_bits = 8;
|
|
bs->cur_buf_ptr++;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void lbcLine_StmInit(VI_DMA_LBC_BS_S *bs, unsigned char *bs_buf_ptr)
|
|
{
|
|
if (NULL == bs || NULL == bs_buf_ptr) {
|
|
return;
|
|
}
|
|
bs->cur_buf_ptr = bs_buf_ptr;
|
|
bs->left_bits = 8;
|
|
bs->cnt = 0;
|
|
bs->sum = 0;
|
|
}
|
|
|
|
static void lbcLine_ParaInit(VI_DMA_LBC_PARAM_S *para, VI_DMA_LBC_CFG_S *cfg)
|
|
{
|
|
if (NULL == para || NULL == cfg) {
|
|
return;
|
|
}
|
|
para->mb_wth = 16;
|
|
para->frm_wth = (cfg->frm_wth + 31) / 32 * 32;
|
|
para->frm_hgt = cfg->frm_hgt;
|
|
para->line_tar_bits[0] = cfg->line_tar_bits[0];
|
|
para->line_tar_bits[1] = cfg->line_tar_bits[1];
|
|
para->frm_bits = 0;
|
|
}
|
|
|
|
static void lbcLine_Align(VI_DMA_LBC_PARAM_S *para, VI_DMA_LBC_BS_S *bs)
|
|
{
|
|
unsigned int align_bit = 0;
|
|
unsigned int align_bit_1 = 0;
|
|
unsigned int align_bit_2 = 0;
|
|
unsigned int i = 0;
|
|
|
|
if (NULL == para || NULL == bs) {
|
|
return;
|
|
}
|
|
|
|
align_bit = para->line_tar_bits[para->frm_y % 2] - para->line_bits;
|
|
align_bit_1 = align_bit / 1024;
|
|
align_bit_2 = align_bit % 1024;
|
|
|
|
for (i = 0; i < align_bit_1; i++) {
|
|
lbcLine_StmWrBit(bs, 0, 1024);
|
|
}
|
|
lbcLine_StmWrBit(bs, 0, align_bit_2);
|
|
para->frm_bits += para->line_tar_bits[para->frm_y % 2];
|
|
}
|
|
|
|
static void lbcLine_Enc(VI_DMA_LBC_PARAM_S *para, VI_DMA_LBC_BS_S *bs, unsigned int frm_x)
|
|
{
|
|
unsigned int i = 0;
|
|
unsigned int bits = 0;
|
|
|
|
if (NULL == para || NULL == bs) {
|
|
return;
|
|
}
|
|
|
|
if (para->frm_y % 2 == 0) {
|
|
lbcLine_StmWrBit(bs, 1, 2); //mode-dts
|
|
if (para->frm_x == 0) { //qp_code
|
|
lbcLine_StmWrBit(bs, 0, 3);
|
|
bits = 3;
|
|
} else {
|
|
lbcLine_StmWrBit(bs, 1, 1);
|
|
bits = 1;
|
|
}
|
|
lbcLine_StmWrBit(bs, 0, 3);
|
|
para->line_bits += bits + 5;
|
|
} else {
|
|
for (i = 0; i < 2; i++) {
|
|
lbcLine_StmWrBit(bs, 1, 2); //mode-dts
|
|
if (i == 1) { //qp_code
|
|
lbcLine_StmWrBit(bs, 0, 1);
|
|
bits = 1;
|
|
} else {
|
|
if (para->frm_x == 0) { //qp_code
|
|
lbcLine_StmWrBit(bs, 0, 3);
|
|
bits = 3;
|
|
} else {
|
|
lbcLine_StmWrBit(bs, 1, 1);
|
|
bits = 1;;
|
|
}
|
|
}
|
|
lbcLine_StmWrBit(bs, 0, 3);
|
|
para->line_bits += bits + 5;
|
|
}
|
|
}
|
|
}
|
|
|
|
static unsigned int lbcLine_Cmp(VI_DMA_LBC_CFG_S *cfg, VI_DMA_LBC_STM_S *stm)
|
|
{
|
|
VI_DMA_LBC_PARAM_S stLbcPara;
|
|
VI_DMA_LBC_BS_S stLbcBs;
|
|
unsigned int frm_x = 0;
|
|
unsigned int frm_bits = 0;
|
|
|
|
if (NULL == cfg || NULL == stm) {
|
|
RT_LOGE("fatal error! null pointer");
|
|
return 0;
|
|
}
|
|
|
|
memset(&stLbcPara, 0, sizeof(VI_DMA_LBC_PARAM_S));
|
|
memset(&stLbcBs, 0, sizeof(VI_DMA_LBC_BS_S));
|
|
|
|
lbcLine_ParaInit(&stLbcPara, cfg);
|
|
lbcLine_StmInit(&stLbcBs, stm->bs);
|
|
|
|
for (stLbcPara.frm_y = 0; stLbcPara.frm_y < stLbcPara.frm_hgt; stLbcPara.frm_y = stLbcPara.frm_y + 1) {
|
|
stLbcPara.line_bits = 0;
|
|
for (stLbcPara.frm_x = 0; stLbcPara.frm_x < stLbcPara.frm_wth; stLbcPara.frm_x = stLbcPara.frm_x + stLbcPara.mb_wth) {
|
|
lbcLine_Enc(&stLbcPara, &stLbcBs, stLbcPara.frm_x);
|
|
}
|
|
lbcLine_Align(&stLbcPara, &stLbcBs);
|
|
}
|
|
frm_bits = (stLbcPara.frm_bits + 7) / 8;
|
|
|
|
return frm_bits;
|
|
}
|
|
#endif
|
|
|
|
#if ENABLE_SAVE_VIN_OUT_DATA
|
|
void vi_comp_save_outdata(struct vi_comp_ctx *pvi_comp, video_frame_s *pvideo_frame)
|
|
{
|
|
struct mem_interface *_memops = pvi_comp->memops;
|
|
int nSaveLen = pvideo_frame->buf_size;
|
|
unsigned char *pVirBuf = pvideo_frame->vir_addr[0];
|
|
int width = pvi_comp->align_width;
|
|
int height = pvi_comp->align_height;
|
|
int ret = 0;
|
|
mm_segment_t old_fs;
|
|
char name[128];
|
|
struct file *fp;
|
|
static int count;
|
|
if (pvi_comp->base_config.pixelformat == RT_PIXEL_LBC_25X
|
|
|| pvi_comp->base_config.pixelformat == RT_PIXEL_LBC_2X) {
|
|
sprintf(name, "/mnt/extsd/lbc_%d_%d_%d.bin", width, height, count++);
|
|
} else {
|
|
sprintf(name, "/mnt/extsd/yuv_%d_%d_%d.yuv", width, height, count++);
|
|
}
|
|
if (count > 5)
|
|
count = 0;
|
|
|
|
old_fs = get_fs();
|
|
set_fs(KERNEL_DS);
|
|
fp = filp_open(name, O_CREAT|O_RDWR, 0600);
|
|
if (IS_ERR(fp)) {
|
|
RT_LOGE("open file failed");
|
|
set_fs(old_fs);
|
|
return ;
|
|
}
|
|
RT_LOGW("file name = %s, nSaveLen = %d, fp = %p, id = %d pVirBuf %p",
|
|
name, nSaveLen, fp, pvideo_frame->id, pVirBuf);
|
|
|
|
cdc_mem_flush_cache(_memops, pVirBuf, nSaveLen);
|
|
ret = vfs_write(fp, (char __user *)pVirBuf, nSaveLen, &fp->f_pos);
|
|
RT_LOGW("vfs_write ret: %d", ret);
|
|
filp_close(fp, NULL);
|
|
set_fs(old_fs);
|
|
return ;
|
|
}
|
|
#endif
|
|
|
|
static int vi_comp_fill_buffer_to_16_align(struct vi_comp_ctx *vi_comp, video_frame_s *src_frame)
|
|
{
|
|
void *src_vir_addr = src_frame->vir_addr[0];
|
|
unsigned int width = vi_comp->base_config.width;
|
|
unsigned int width_align = vi_comp->align_width;
|
|
unsigned int height = vi_comp->base_config.height;
|
|
unsigned int height_align = vi_comp->align_height;
|
|
unsigned int height_diff = height_align - height;
|
|
unsigned int offset_src = width_align*height - (width_align*1);
|
|
unsigned int offset_dst = 0;
|
|
int i = 0;
|
|
|
|
RT_LOGD("width %dx%d align %dx%d height_diff %d", width, height, width_align, height_align, height_diff);
|
|
if (rt_is_lbc_format(vi_comp)) {
|
|
unsigned char *mLbcFillDataAddr = vi_comp->s_vi_lbc_fill_param.mLbcFillDataAddr;
|
|
unsigned int mLbcFillDataLen = vi_comp->s_vi_lbc_fill_param.mLbcFillDataLen;
|
|
unsigned int line_bits_sum = (vi_comp->s_vi_lbc_fill_param.line_tar_bits[0] + vi_comp->s_vi_lbc_fill_param.line_tar_bits[1]) / 8;
|
|
unsigned int offset_dst = line_bits_sum/2*height;
|
|
|
|
RT_LOGD("ViCh:%d, LBC pix:0x%x, src_vir_addr:0x%p, dst:%d, src:%p, len:%d, %d", vi_comp->base_config.channel_id, vi_comp->base_config.pixelformat,
|
|
src_vir_addr, offset_dst, mLbcFillDataAddr, mLbcFillDataLen, src_frame->buf_size);
|
|
if (!mLbcFillDataAddr) {
|
|
RT_LOGE("mLbcFillDataAddr is null!");
|
|
return -1;
|
|
}
|
|
unsigned int mDataLen = line_bits_sum*height_diff/2;
|
|
if (mLbcFillDataLen != mDataLen) {
|
|
RT_LOGW("error! wrong data len %d != %d", mLbcFillDataLen, mDataLen);
|
|
}
|
|
memcpy(src_vir_addr + offset_dst, mLbcFillDataAddr, mLbcFillDataLen);
|
|
cdc_mem_flush_cache(vi_comp->memops, src_vir_addr + offset_dst, mLbcFillDataLen);
|
|
} else {
|
|
for (i = 0; i < height_diff; i++) {
|
|
offset_dst = width_align*height + (width_align*i);
|
|
memcpy(src_vir_addr + offset_dst, src_vir_addr + offset_src, width_align);
|
|
}
|
|
cdc_mem_flush_cache(vi_comp->memops, src_vir_addr + width_align*height, width_align*height_diff);
|
|
|
|
char *tmp = (char *)src_vir_addr;
|
|
|
|
int ySize = width_align * height_align;
|
|
if (RT_PIXEL_YUV420SP == vi_comp->base_config.pixelformat || RT_PIXEL_YVU420SP == vi_comp->base_config.pixelformat) {
|
|
// fill UV
|
|
int uvData = width_align * height / 2;
|
|
offset_src = ySize + uvData - (width_align*1);
|
|
for (i = 0; i < height_diff/2; i++) {
|
|
offset_dst = ySize + uvData + (width_align*i);
|
|
RT_LOGI("i:%d, src_vir_addr:0x%x, offset_src:%d, offset_dst:%d, width_align:%d", i, src_vir_addr, offset_src, offset_dst, width_align);
|
|
memcpy(src_vir_addr + offset_dst, src_vir_addr + offset_src, width_align);
|
|
}
|
|
cdc_mem_flush_cache(vi_comp->memops, src_vir_addr + ySize + uvData, width_align*height_diff/2);
|
|
} else if (RT_PIXEL_YUV420P == vi_comp->base_config.pixelformat || RT_PIXEL_YVU420P == vi_comp->base_config.pixelformat) {
|
|
// fill U
|
|
int uData = width_align * height / 4;
|
|
offset_src = ySize + uData - (width_align/4 * 1);
|
|
for (i = 0; i < height_diff; i++) {
|
|
offset_dst = ySize + uData + (width_align/4 * i);
|
|
memcpy(src_vir_addr + offset_dst, src_vir_addr + offset_src, width_align/4);
|
|
}
|
|
cdc_mem_flush_cache(vi_comp->memops, src_vir_addr + ySize + uData, width_align/4*height_diff);
|
|
// fill V
|
|
int uvData = width_align * height / 2;
|
|
offset_src = ySize + uvData - (width_align/4 * 1);
|
|
for (i = 0; i < height_diff; i++) {
|
|
offset_dst = ySize + uvData + (width_align/4 * i);
|
|
memcpy(src_vir_addr + offset_dst, src_vir_addr + offset_src, width_align/4);
|
|
}
|
|
cdc_mem_flush_cache(vi_comp->memops, src_vir_addr + ySize + uvData, width_align/4*height_diff);
|
|
} else {
|
|
RT_LOGW("pixel format 0x%x is not support!", vi_comp->base_config.pixelformat);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* empty_list --> valid_list */
|
|
static int vi_fill_out_buffer_done(struct vi_comp_ctx *vi_comp, struct vin_buffer *vin_buf)
|
|
{
|
|
video_frame_node *first_node = NULL;
|
|
comp_buffer_header_type buffer_header;
|
|
video_frame_s mvideo_frame;
|
|
|
|
memset(&mvideo_frame, 0, sizeof(video_frame_s));
|
|
memset(&buffer_header, 0, sizeof(comp_buffer_header_type));
|
|
config_videostream_by_vinbuf(vi_comp, &mvideo_frame, vin_buf);
|
|
mutex_lock(&vi_comp->out_buf_manager.mutex);
|
|
if (list_empty(&vi_comp->out_buf_manager.empty_frame_list)) {
|
|
RT_LOGE("error: empty_frame_list is empty");
|
|
mutex_unlock(&vi_comp->out_buf_manager.mutex);
|
|
vin_qbuffer_special(vi_comp->vipp_id, vin_buf);
|
|
return -1;
|
|
}
|
|
|
|
first_node = list_first_entry(&vi_comp->out_buf_manager.empty_frame_list, video_frame_node, mList);
|
|
memcpy(&first_node->video_frame, &mvideo_frame, sizeof(video_frame_s));
|
|
|
|
vi_comp->out_buf_manager.empty_num--;
|
|
list_move_tail(&first_node->mList, &vi_comp->out_buf_manager.valid_frame_list);
|
|
|
|
mutex_unlock(&vi_comp->out_buf_manager.mutex);
|
|
|
|
buffer_header.private = &mvideo_frame;
|
|
|
|
#if ENABLE_SAVE_VIN_OUT_DATA
|
|
vi_comp_save_outdata(vi_comp, &mvideo_frame);
|
|
#endif
|
|
|
|
if (rt_need_fill_data(vi_comp))
|
|
vi_comp_fill_buffer_to_16_align(vi_comp, &mvideo_frame);
|
|
|
|
if (vi_comp->out_port_tunnel_info.valid_flag == 1 && vi_comp->out_port_tunnel_info.tunnel_comp != NULL) {
|
|
comp_empty_this_in_buffer(vi_comp->out_port_tunnel_info.tunnel_comp, &buffer_header);
|
|
} else {
|
|
RT_LOGE("tunnel_comp is null: %d, %p, return to isp", vi_comp->out_port_tunnel_info.valid_flag,
|
|
vi_comp->out_port_tunnel_info.tunnel_comp);
|
|
vin_qbuffer_special(vi_comp->vipp_id, vin_buf);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int check_adt_fps_reduce_frame(vi_comp_ctx *vi_comp, uint64_t pts)
|
|
{
|
|
adapter_venc_fps_info *venc_fps_info = &vi_comp->base_config.st_adapter_venc_fps;
|
|
uint64_t videoFramerate = (uint64_t)venc_fps_info->dst_fps;
|
|
|
|
RT_LOGI("all frame, pts %lld %lld", pts, venc_fps_info->cur_wanted_pts);
|
|
|
|
if (videoFramerate == 0) {
|
|
RT_LOGE("err, dst_fps is 0!");
|
|
return 0;
|
|
}
|
|
if (-1 == venc_fps_info->frame_cnt) {
|
|
venc_fps_info->base_pts = pts;
|
|
venc_fps_info->cur_wanted_pts = venc_fps_info->base_pts;
|
|
venc_fps_info->frame_cnt = 0;
|
|
}
|
|
if (pts >= venc_fps_info->cur_wanted_pts) {
|
|
venc_fps_info->frame_cnt++;
|
|
venc_fps_info->cur_wanted_pts = venc_fps_info->base_pts + venc_fps_info->frame_cnt * (1000 * 1000) * 1000 / videoFramerate;
|
|
RT_LOGI("cur_wanted_pts %lld cnt %d", venc_fps_info->cur_wanted_pts, venc_fps_info->frame_cnt);
|
|
} else {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int dequeue_count;
|
|
|
|
int dequeue_buffer(vi_comp_ctx *vi_comp)
|
|
{
|
|
struct vin_buffer *vin_buf = NULL;
|
|
int ret = 0;
|
|
|
|
if (vi_comp->base_config.bonline_channel) {
|
|
RT_LOGD(" chanel_id %d online mode not need this", vi_comp->base_config.channel_id);
|
|
return -1;
|
|
}
|
|
|
|
ret = vin_dqbuffer_special(vi_comp->vipp_id, &vin_buf);
|
|
|
|
RT_LOGI("ch %d dequeue buf, ret = %d", vi_comp->base_config.channel_id, ret);
|
|
|
|
if (ret != 0)
|
|
return -1;
|
|
|
|
dequeue_count++;
|
|
RT_LOGI("ch %d dqbuffer succes dequeue_count %d", vi_comp->base_config.channel_id, dequeue_count);
|
|
if (dequeue_count == 1) {
|
|
int64_t time_cur = get_cur_time();
|
|
RT_LOGW("wait first dequeue time = %lld", time_cur - time_first_cb);
|
|
}
|
|
|
|
/* just queue back buf if output mode is yuv */
|
|
if (vi_comp->base_config.output_mode == OUTPUT_MODE_YUV) {
|
|
if (vi_comp->catch_jpeg_flag == 1) {
|
|
vi_comp->catch_jpeg_flag = 0;
|
|
vi_fill_out_buffer_done(vi_comp, vin_buf);
|
|
} else {
|
|
vin_qbuffer_special(vi_comp->vipp_id, vin_buf);
|
|
}
|
|
} else {
|
|
if (vi_comp->base_config.drop_frame_num > 0) {
|
|
RT_LOGI("drop_frame_num = %d", vi_comp->base_config.drop_frame_num);
|
|
vi_comp->base_config.drop_frame_num--;
|
|
vin_qbuffer_special(vi_comp->vipp_id, vin_buf);
|
|
} else {
|
|
int badt_fps_drop_flag = 0;
|
|
if (vi_comp->base_config.st_adapter_venc_fps.enable)
|
|
badt_fps_drop_flag = check_adt_fps_reduce_frame(vi_comp, vin_buf->vb.vb2_buf.timestamp);
|
|
|
|
if (badt_fps_drop_flag)
|
|
vin_qbuffer_special(vi_comp->vipp_id, vin_buf);
|
|
else
|
|
vi_fill_out_buffer_done(vi_comp, vin_buf);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int vipp_create(vi_comp_ctx *vi_comp)
|
|
{
|
|
RT_LOGI("vipp create not support");
|
|
|
|
return -1;
|
|
}
|
|
|
|
static int lbc_cal_fill_16_align_data(vi_comp_ctx *vi_comp)
|
|
{
|
|
unsigned int width = vi_comp->base_config.width;
|
|
unsigned int width_32_align = RT_ALIGN(vi_comp->base_config.width, 32);
|
|
unsigned int height = vi_comp->base_config.height;
|
|
unsigned int height_16_align = RT_ALIGN(vi_comp->base_config.height, 16);
|
|
|
|
if (vi_comp->base_config.pixelformat == RT_PIXEL_LBC_25X) {
|
|
vi_comp->s_vi_lbc_fill_param.line_tar_bits[0] = RT_ALIGN(LBC_2_5X_COM_RATIO_EVEN * width_32_align * LBC_BIT_DEPTH/1000, 512);
|
|
vi_comp->s_vi_lbc_fill_param.line_tar_bits[1] = RT_ALIGN(LBC_2_5X_COM_RATIO_ODD * width_32_align * LBC_BIT_DEPTH/500, 512);
|
|
} else if (vi_comp->base_config.pixelformat == RT_PIXEL_LBC_2X) {
|
|
vi_comp->s_vi_lbc_fill_param.line_tar_bits[0] = RT_ALIGN(LBC_2X_COM_RATIO_EVEN * width_32_align * LBC_BIT_DEPTH/1000, 512);
|
|
vi_comp->s_vi_lbc_fill_param.line_tar_bits[1] = RT_ALIGN(LBC_2X_COM_RATIO_ODD * width_32_align * LBC_BIT_DEPTH/500, 512);
|
|
} else {
|
|
RT_LOGW("rt_media now only support LBC_25X/2X.");
|
|
}
|
|
|
|
VI_DMA_LBC_CFG_S stLbcCfg;
|
|
VI_DMA_LBC_STM_S stLbcStm;
|
|
memset(&stLbcCfg, 0, sizeof(VI_DMA_LBC_CFG_S));
|
|
stLbcCfg.frm_wth = width;
|
|
stLbcCfg.frm_hgt = height_16_align - height;
|
|
stLbcCfg.line_tar_bits[0] = vi_comp->s_vi_lbc_fill_param.line_tar_bits[0];
|
|
stLbcCfg.line_tar_bits[1] = vi_comp->s_vi_lbc_fill_param.line_tar_bits[1];
|
|
|
|
memset(&stLbcStm, 0, sizeof(VI_DMA_LBC_STM_S));
|
|
unsigned int bs_len = stLbcCfg.frm_wth * stLbcCfg.frm_hgt * 4;
|
|
stLbcStm.bs = (unsigned char *)kmalloc(bs_len, GFP_KERNEL);
|
|
if (NULL == stLbcStm.bs) {
|
|
RT_LOGE("fatal error! malloc stLbcStm.bs failed! size=%d", bs_len);
|
|
return -1;
|
|
}
|
|
memset(stLbcStm.bs, 0, bs_len);
|
|
|
|
unsigned int frm_bit = lbcLine_Cmp(&stLbcCfg, &stLbcStm);
|
|
if (frm_bit > bs_len) {
|
|
RT_LOGE("fatal error! wrong frm_bit:%d > bs_len:%d", frm_bit, bs_len);
|
|
if (stLbcStm.bs) {
|
|
kfree(stLbcStm.bs);
|
|
stLbcStm.bs = NULL;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
if (vi_comp->s_vi_lbc_fill_param.mLbcFillDataAddr) {
|
|
RT_LOGW("LbcFillDataAddr %p is not NULL! free it before malloc.", vi_comp->s_vi_lbc_fill_param.mLbcFillDataAddr);
|
|
kfree(vi_comp->s_vi_lbc_fill_param.mLbcFillDataAddr);
|
|
vi_comp->s_vi_lbc_fill_param.mLbcFillDataAddr = NULL;
|
|
}
|
|
|
|
vi_comp->s_vi_lbc_fill_param.mLbcFillDataLen = frm_bit;
|
|
vi_comp->s_vi_lbc_fill_param.mLbcFillDataAddr = (unsigned char *)kmalloc(vi_comp->s_vi_lbc_fill_param.mLbcFillDataLen, GFP_KERNEL);
|
|
if (NULL == vi_comp->s_vi_lbc_fill_param.mLbcFillDataAddr) {
|
|
RT_LOGE("fatal error! malloc LbcFillDataAddr failed! size=%d", vi_comp->s_vi_lbc_fill_param.mLbcFillDataLen);
|
|
if (stLbcStm.bs) {
|
|
kfree(stLbcStm.bs);
|
|
stLbcStm.bs = NULL;
|
|
}
|
|
return -1;
|
|
}
|
|
memcpy(vi_comp->s_vi_lbc_fill_param.mLbcFillDataAddr, stLbcStm.bs, vi_comp->s_vi_lbc_fill_param.mLbcFillDataLen);
|
|
|
|
if (stLbcStm.bs) {
|
|
kfree(stLbcStm.bs);
|
|
stLbcStm.bs = NULL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int alloc_vin_buf(vi_comp_ctx *vi_comp)
|
|
{
|
|
struct mem_param param;
|
|
int i = 0;
|
|
|
|
int buf_size = vi_comp->align_width * vi_comp->align_height * 3 / 2;
|
|
unsigned int lbc_ext_size = 0;
|
|
|
|
if (vi_comp->base_config.pixelformat == RT_PIXEL_LBC_25X || vi_comp->base_config.pixelformat == RT_PIXEL_LBC_2X) {
|
|
int y_stride = 0;
|
|
int yc_stride = 0;
|
|
int bit_depth = 8;
|
|
int com_ratio_even = 0;
|
|
int com_ratio_odd = 0;
|
|
int pic_width_32align = (vi_comp->base_config.width + 31) & ~31;
|
|
int pic_height_16align = (vi_comp->base_config.height + 15) & ~15;
|
|
int bLbcLossyComEnFlag2x = 0;
|
|
int bLbcLossyComEnFlag2_5x = 0;
|
|
|
|
if (vi_comp->base_config.pixelformat == RT_PIXEL_LBC_25X) {
|
|
bLbcLossyComEnFlag2_5x = 1;
|
|
} else if (vi_comp->base_config.pixelformat == RT_PIXEL_LBC_2X) {
|
|
bLbcLossyComEnFlag2x = 1;
|
|
}
|
|
|
|
if (rt_need_fill_data(vi_comp) && rt_is_lbc_format(vi_comp)) {
|
|
lbc_cal_fill_16_align_data(vi_comp);
|
|
}
|
|
|
|
RT_LOGD("bLbcLossyComEnFlag2x %d bLbcLossyComEnFlag2_5x %d", bLbcLossyComEnFlag2x, bLbcLossyComEnFlag2_5x);
|
|
if (bLbcLossyComEnFlag2x == 1) {
|
|
com_ratio_even = LBC_2X_COM_RATIO_EVEN;
|
|
com_ratio_odd = LBC_2X_COM_RATIO_ODD;
|
|
y_stride = ((com_ratio_even * pic_width_32align * bit_depth / 1000 + 511) & (~511)) >> 3;
|
|
yc_stride = ((com_ratio_odd * pic_width_32align * bit_depth / 500 + 511) & (~511)) >> 3;
|
|
} else if (bLbcLossyComEnFlag2_5x == 1) {
|
|
com_ratio_even = LBC_2_5X_COM_RATIO_EVEN;
|
|
com_ratio_odd = LBC_2_5X_COM_RATIO_ODD;
|
|
y_stride = ((com_ratio_even * pic_width_32align * bit_depth / 1000 + 511) & (~511)) >> 3;
|
|
yc_stride = ((com_ratio_odd * pic_width_32align * bit_depth / 500 + 511) & (~511)) >> 3;
|
|
} else {
|
|
y_stride = ((pic_width_32align * bit_depth + pic_width_32align / 16 * 2 + 511) & (~511)) >> 3;
|
|
yc_stride = ((pic_width_32align * bit_depth * 2 + pic_width_32align / 16 * 4 + 511) & (~511)) >> 3;
|
|
}
|
|
|
|
buf_size = (y_stride + yc_stride) * pic_height_16align / 2;
|
|
|
|
//* add more 1KB to fix ve-lbc-error
|
|
lbc_ext_size = LBC_EXT_SIZE;
|
|
buf_size += lbc_ext_size;
|
|
|
|
RT_LOGW("LBC in buf:com_ratio: %d, %d, w32alin = %d, h16alin = %d, y_s = %d, yc_s = %d, total_len = %d,\n",
|
|
com_ratio_even, com_ratio_odd,
|
|
pic_width_32align, pic_height_16align,
|
|
y_stride, yc_stride, buf_size);
|
|
} else if (rt_is_format422(vi_comp->base_config.pixelformat)) {
|
|
buf_size = vi_comp->align_width * vi_comp->align_height * 2;
|
|
if (vi_comp->align_width % 64 != 0)
|
|
buf_size += 64;
|
|
} else {//default as yuv420, add other format please additionally add
|
|
buf_size = vi_comp->align_width * vi_comp->align_height * 3 / 2;
|
|
if (vi_comp->align_width % 64 != 0)
|
|
buf_size += 64;
|
|
}
|
|
|
|
vi_comp->buf_size = buf_size - lbc_ext_size;
|
|
RT_LOGW("buf_size = %d, align_w = %d, align_h = %d", buf_size,
|
|
vi_comp->align_width, vi_comp->align_height);
|
|
if (vi_comp->memops == NULL) {
|
|
vi_comp->memops = mem_create(MEM_TYPE_ION, param);
|
|
if (vi_comp->memops == NULL) {
|
|
RT_LOGE("mem_create failed\n");
|
|
return -1;
|
|
}
|
|
}
|
|
#if 0//yuv mem have change to kernel palloc.
|
|
if (vi_comp->base_config.output_mode == OUTPUT_MODE_YUV) {
|
|
RT_LOGW("vi_comp->vipp_id %d config yuv buf, size = %d, %d, num = %d", vi_comp->vipp_id,
|
|
buf_size, vi_comp->yuv_buf_info.buf_size,
|
|
vi_comp->yuv_buf_info.buf_num);
|
|
if (vi_comp->yuv_buf_info.buf_num != vi_comp->base_config.vin_buf_num) {
|
|
RT_LOGE("yuv_buf_info.buf_num is not match: %d, %d",
|
|
vi_comp->yuv_buf_info.buf_num, vi_comp->base_config.vin_buf_num);
|
|
return -1;
|
|
}
|
|
for (i = 0; i < vi_comp->yuv_buf_info.buf_num; i++) {
|
|
vi_comp->vin_buf[i].paddr = vi_comp->yuv_buf_info.phy_addr[i];
|
|
vin_qbuffer_special(vi_comp->vipp_id, &vi_comp->vin_buf[i]);
|
|
}
|
|
vi_comp->config_yuv_buf_flag = 1;
|
|
} else
|
|
#endif
|
|
{
|
|
RT_LOGD("channel %d vin_buf_num %d", vi_comp->base_config.channel_id, vi_comp->base_config.vin_buf_num);
|
|
int buf_num = vi_comp->base_config.vin_buf_num;
|
|
|
|
if (vi_comp->base_config.bonline_channel)
|
|
buf_num = vi_comp->base_config.share_buf_num;
|
|
|
|
if (vi_comp->base_config.output_mode == OUTPUT_MODE_YUV)
|
|
buf_num = CONFIG_YUV_BUF_NUM;
|
|
|
|
vi_comp->buf_num = buf_num;
|
|
for (i = 0; i < buf_num; i++) {
|
|
unsigned char *vir_addr = cdc_mem_palloc(vi_comp->memops, buf_size);
|
|
cdc_mem_flush_cache(vi_comp->memops, vir_addr, buf_size);
|
|
if (vir_addr == NULL) {
|
|
RT_LOGE("cdc_mem_palloc failed, size = %d", buf_size);
|
|
return -1;
|
|
}
|
|
vi_comp->vin_buf[i].vir_addr = vir_addr;
|
|
vi_comp->vin_buf[i].paddr = (void *)cdc_mem_get_phy(vi_comp->memops, vir_addr);
|
|
|
|
if (vi_comp->base_config.output_mode == OUTPUT_MODE_YUV)
|
|
vi_comp->s_yuv_info[i].phy_addr = vi_comp->vin_buf[i].paddr;
|
|
|
|
RT_LOGW("palloc vin buf: vir = %p, phy = %p, buf_size = %d, i = %d", vir_addr, vi_comp->vin_buf[i].paddr, buf_size, i);
|
|
vin_qbuffer_special(vi_comp->vipp_id, &vi_comp->vin_buf[i]);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#if 0
|
|
static int vipp_init(vi_comp_ctx *vi_comp)
|
|
{
|
|
int ret = 0;
|
|
int id = vi_comp->base_config.channel_id;
|
|
struct v4l2_streamparm parms;
|
|
int mode = 4; /* NV12 */
|
|
struct v4l2_format fmt;
|
|
int wdr_param = 0;
|
|
|
|
//if(vi_comp->base_config.width >= 1280)
|
|
if (vi_comp->base_config.pixelformat == RT_PIXEL_YUV420SP)
|
|
mode = 4; /* NV12 */
|
|
else if (vi_comp->base_config.pixelformat == RT_PIXELFORMAT_NV21)
|
|
mode = 8; /* NV21 */
|
|
else if (vi_comp->base_config.pixelformat == RT_PIXELFORMAT_YV12)
|
|
mode = 2; /* YV12 */
|
|
else if (vi_comp->base_config.pixelformat == RT_PIXELFORMAT_YV21)
|
|
mode = 9; /* YV21 */
|
|
else if (vi_comp->base_config.pixelformat == RT_PIXEL_LBC_25X)
|
|
mode = 7; /* LBC2.5 */
|
|
|
|
RT_LOGW("vipp init: widht = %d, height = %d, fps = %d, id = %d, mode = %d, format = %d",
|
|
vi_comp->base_config.width, vi_comp->base_config.height,
|
|
vi_comp->base_config.frame_rate, id, mode,
|
|
vi_comp->base_config.pixelformat);
|
|
|
|
callback_count = 0;
|
|
dequeue_count = 0;
|
|
time_vi_start = 0;
|
|
time_first_cb = 0;
|
|
|
|
ret = vin_open_special(id);
|
|
RT_LOGI("vin open, ret = %d, id = %d", ret, id);
|
|
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time3_start = get_cur_time();
|
|
#endif
|
|
|
|
ret = vin_s_input_special(id, 0);
|
|
RT_LOGI("vin s input, ret = %d, id = %d", ret, id);
|
|
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time3_end = get_cur_time();
|
|
RT_LOGE("time of s input: %lld", (time3_end - time3_start));
|
|
#endif
|
|
|
|
if (vi_comp->base_config.enable_wdr == 1)
|
|
wdr_param = 1;
|
|
else
|
|
wdr_param = 2;
|
|
RT_LOGI("wdr_param = %d, enable_wdr = %d", wdr_param, vi_comp->base_config.enable_wdr);
|
|
|
|
/* set paramter */
|
|
CLEAR(parms);
|
|
parms.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
|
parms.parm.capture.timeperframe.numerator = 1;
|
|
parms.parm.capture.timeperframe.denominator = vi_comp->base_config.frame_rate;
|
|
parms.parm.capture.capturemode = V4L2_MODE_VIDEO;
|
|
/* parms.parm.capture.capturemode = V4L2_MODE_IMAGE; */
|
|
/*when different video have the same sensor source, 1:use sensor current win, 0:find the nearest win*/
|
|
parms.parm.capture.reserved[0] = 0;
|
|
parms.parm.capture.reserved[1] = wdr_param;/*2:command, 1: wdr, 0: normal*/
|
|
|
|
|
|
ret = vin_s_parm_special(id, NULL, &parms);
|
|
RT_LOGI("vin s parm, ret = %d, id = %d", ret, id);
|
|
|
|
/* set format */
|
|
CLEAR(fmt);
|
|
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
|
fmt.fmt.pix_mp.width = vi_comp->base_config.width;
|
|
fmt.fmt.pix_mp.height = vi_comp->base_config.height;
|
|
switch (mode) {
|
|
case 0:
|
|
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_SBGGR8;
|
|
break;
|
|
case 1:
|
|
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420M;
|
|
break;
|
|
case 2:
|
|
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420;
|
|
break;
|
|
case 3:
|
|
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M;
|
|
break;
|
|
case 4:
|
|
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12;
|
|
break;
|
|
case 5:
|
|
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_SBGGR10;
|
|
break;
|
|
case 6:
|
|
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_SBGGR12;
|
|
break;
|
|
case 7:
|
|
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_LBC_2_5X;
|
|
break;
|
|
case 8:
|
|
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV21;
|
|
break;
|
|
case 9:
|
|
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YVU420;
|
|
break;
|
|
default:
|
|
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420M;
|
|
break;
|
|
}
|
|
fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
|
|
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time2_start = get_cur_time();
|
|
#endif
|
|
|
|
ret = vin_s_fmt_special(id, &fmt);
|
|
RT_LOGI("vin s fmt, ret = %d, id = %d", ret, id);
|
|
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time2_end = get_cur_time();
|
|
RT_LOGE("time of s fmt: %lld", (time2_end - time2_start));
|
|
#endif
|
|
|
|
ret = vin_g_fmt_special(id, &fmt);
|
|
RT_LOGI("vin g fmt, ret = %d, id = %d", ret, id);
|
|
|
|
RT_LOGD("resolution got from sensor = %d*%d num_planes = %d\n",
|
|
fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
|
|
fmt.fmt.pix_mp.num_planes);
|
|
|
|
/* queue buffer */
|
|
vi_comp->vipp_id = id;
|
|
g_vi_comp[id] = vi_comp;
|
|
|
|
vin_register_buffer_done_callback(id, vin_buffer_callback);
|
|
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time_start = get_cur_time();
|
|
#endif
|
|
|
|
alloc_vin_buf(vi_comp);
|
|
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time_end = get_cur_time();
|
|
RT_LOGE("time of alloc buf: %lld", (time_end - time_start));
|
|
#endif
|
|
|
|
/* stream on */
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time1_start = get_cur_time();
|
|
#endif
|
|
|
|
ret = vin_streamon_special(vi_comp->vipp_id, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
|
|
RT_LOGI("vin streamon, ret = %d, id = %d", ret, id);
|
|
|
|
time_vi_start = get_cur_time();
|
|
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time1_end = get_cur_time();
|
|
RT_LOGE("time of stream on: %lld", (time1_end - time1_start));
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
static void highframe_callback(int id)
|
|
{
|
|
vi_comp_ctx *vi_comp = g_vi_comp[id];
|
|
message_t cmd_msg;
|
|
|
|
RT_LOGW("%s:change to low frame, id = %d", __func__, id);
|
|
|
|
memset(&cmd_msg, 0, sizeof(message_t));
|
|
cmd_msg.command = COMP_COMMAND_RESET_HIGH_FPS;
|
|
|
|
put_message(&vi_comp->msg_queue, &cmd_msg);
|
|
return;
|
|
}
|
|
|
|
static int highframe_alloc_vin_buf(vi_comp_ctx *vi_comp, int width, int height)
|
|
{
|
|
struct mem_param param;
|
|
int i = 0;
|
|
|
|
int buf_size = width * height * 3 / 2;
|
|
|
|
vi_comp->buf_size = buf_size;
|
|
RT_LOGW("%s: buf_size = %d, align_w = %d, align_h = %d", __func__, buf_size,
|
|
width, height);
|
|
|
|
if (vi_comp->memops == NULL) {
|
|
vi_comp->memops = mem_create(MEM_TYPE_ION, param);
|
|
if (vi_comp->memops == NULL) {
|
|
RT_LOGE("mem_create failed\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < vi_comp->base_config.vin_buf_num; i++) {
|
|
unsigned char *vir_addr = cdc_mem_palloc(vi_comp->memops, buf_size);
|
|
|
|
if (vir_addr == NULL) {
|
|
RT_LOGE("cdc_mem_palloc failed, size = %d", buf_size);
|
|
return -1;
|
|
}
|
|
vi_comp->vin_buf[i].paddr = (void *)cdc_mem_get_phy(vi_comp->memops, vir_addr);
|
|
|
|
RT_LOGI("palloc vin buf: vir = %p, phy = %p, i = %d", vir_addr, vi_comp->vin_buf[i].paddr, i);
|
|
vin_qbuffer_special(vi_comp->vipp_id, &vi_comp->vin_buf[i]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void highframe_free_vin_buf(vi_comp_ctx *vi_comp)
|
|
{
|
|
int i = 0;
|
|
|
|
RT_LOGW("%s:free vin buffer\n", __func__);
|
|
|
|
for (i = 0; i < vi_comp->base_config.vin_buf_num; i++) {
|
|
if (vi_comp->vin_buf[i].paddr) {
|
|
unsigned char *virAddr = (unsigned char *)cdc_mem_get_vir(vi_comp->memops,
|
|
(unsigned long)vi_comp->vin_buf[i].paddr);
|
|
cdc_mem_pfree(vi_comp->memops, virAddr);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int highframe_vipp_init(vi_comp_ctx *vi_comp)
|
|
{
|
|
int ret = 0;
|
|
int id = vi_comp->base_config.channel_id;
|
|
struct v4l2_streamparm parms;
|
|
int mode = 4; /* NV12 */
|
|
struct v4l2_format fmt;
|
|
int wdr_param, frame_rate, isp_drop_frame;
|
|
int width, height;
|
|
|
|
callback_count = 0;
|
|
dequeue_count = 0;
|
|
time_vi_start = 0;
|
|
time_first_cb = 0;
|
|
|
|
ret = vin_open_special(id);
|
|
RT_LOGI("vin open, ret = %d, id = %d", ret, id);
|
|
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time3_start = get_cur_time();
|
|
#endif
|
|
|
|
ret = vin_s_input_special(id, 0);
|
|
RT_LOGI("vin s input, ret = %d, id = %d", ret, id);
|
|
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time3_end = get_cur_time();
|
|
RT_LOGE("time of s input: %lld", (time3_end - time3_start));
|
|
#endif
|
|
|
|
wdr_param = 2;
|
|
frame_rate = 120;
|
|
isp_drop_frame = 7;
|
|
/* set paramter */
|
|
CLEAR(parms);
|
|
parms.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
|
parms.parm.capture.timeperframe.numerator = 1;
|
|
parms.parm.capture.timeperframe.denominator = frame_rate;
|
|
parms.parm.capture.capturemode = V4L2_MODE_VIDEO;
|
|
/* parms.parm.capture.capturemode = V4L2_MODE_IMAGE; */
|
|
/*when different video have the same sensor source, 1:use sensor current win, 0:find the nearest win*/
|
|
parms.parm.capture.reserved[0] = 0;
|
|
parms.parm.capture.reserved[1] = wdr_param; /*2:command, 1: wdr, 0: normal*/
|
|
parms.parm.capture.reserved[3] = isp_drop_frame;
|
|
|
|
ret = vin_s_parm_special(id, NULL, &parms);
|
|
RT_LOGI("vin s parm, ret = %d, id = %d", ret, id);
|
|
|
|
/* set format */
|
|
width = 1280;
|
|
height = 720;
|
|
CLEAR(fmt);
|
|
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
|
fmt.fmt.pix_mp.width = width;
|
|
fmt.fmt.pix_mp.height = height;
|
|
switch (mode) {
|
|
case 0:
|
|
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_SBGGR8;
|
|
break;
|
|
case 1:
|
|
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420M;
|
|
break;
|
|
case 2:
|
|
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420;
|
|
break;
|
|
case 3:
|
|
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M;
|
|
break;
|
|
case 4:
|
|
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12;
|
|
break;
|
|
case 5:
|
|
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_SBGGR10;
|
|
break;
|
|
case 6:
|
|
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_SBGGR12;
|
|
break;
|
|
case 7:
|
|
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_LBC_2_5X;
|
|
break;
|
|
case 8:
|
|
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV21;
|
|
break;
|
|
case 9:
|
|
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YVU420;
|
|
break;
|
|
default:
|
|
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420M;
|
|
break;
|
|
}
|
|
fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
|
|
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time2_start = get_cur_time();
|
|
#endif
|
|
|
|
ret = vin_s_fmt_special(id, &fmt);
|
|
RT_LOGI("vin s fmt, ret = %d, id = %d", ret, id);
|
|
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time2_end = get_cur_time();
|
|
RT_LOGE("time of s fmt: %lld", (time2_end - time2_start));
|
|
#endif
|
|
|
|
ret = vin_g_fmt_special(id, &fmt);
|
|
RT_LOGI("vin g fmt, ret = %d, id = %d", ret, id);
|
|
|
|
RT_LOGD("resolution got from sensor = %d*%d num_planes = %d\n",
|
|
fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
|
|
fmt.fmt.pix_mp.num_planes);
|
|
|
|
/* queue buffer */
|
|
vi_comp->vipp_id = id;
|
|
g_vi_comp[id] = vi_comp;
|
|
|
|
vin_register_buffer_done_callback(id, highframe_callback);
|
|
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time_start = get_cur_time();
|
|
#endif
|
|
|
|
highframe_alloc_vin_buf(vi_comp, width, height);
|
|
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time_end = get_cur_time();
|
|
RT_LOGE("time of alloc buf: %lld", (time_end - time_start));
|
|
#endif
|
|
|
|
/* stream on */
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time1_start = get_cur_time();
|
|
#endif
|
|
|
|
RT_LOGW("highframe vipp init: %d*%d@%dfps, drop frame %d", width, height, frame_rate, isp_drop_frame);
|
|
|
|
ret = vin_streamon_special(vi_comp->vipp_id, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
|
|
RT_LOGI("vin streamon, ret = %d, id = %d", ret, id);
|
|
|
|
time_vi_start = get_cur_time();
|
|
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time1_end = get_cur_time();
|
|
RT_LOGE("time of stream on: %lld", (time1_end - time1_start));
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int convert_to_v4l2_color_space(VencH264VideoSignal *venc_video_signal)
|
|
{
|
|
if (venc_video_signal->src_colour_primaries == VENC_BT709) {
|
|
if (venc_video_signal->full_range_flag)
|
|
return V4L2_COLORSPACE_REC709;
|
|
else
|
|
return V4L2_COLORSPACE_REC709_PART_RANGE;
|
|
}
|
|
|
|
if (VENC_YCC == venc_video_signal->src_colour_primaries)
|
|
return V4L2_COLORSPACE_JPEG;
|
|
|
|
RT_LOGW("not support color space %d set default to V4L2_COLORSPACE_REC709", venc_video_signal->src_colour_primaries);
|
|
return V4L2_COLORSPACE_REC709;
|
|
}
|
|
|
|
int rt_is_format422(rt_pixelformat_type pixelformat)
|
|
{
|
|
if (pixelformat >= RT_PIXEL_YUV422SP && pixelformat <= RT_PIXEL_VYUY422)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
static __u32 vi_change_pixelformat_2_vin(rt_pixelformat_type pixelformat)
|
|
{
|
|
__u32 v4l2_pix_fmt = 0;
|
|
|
|
switch (pixelformat) {
|
|
case RT_PIXEL_YUV420SP:
|
|
v4l2_pix_fmt = V4L2_PIX_FMT_NV12;
|
|
break;
|
|
case RT_PIXEL_YVU420SP:
|
|
v4l2_pix_fmt = V4L2_PIX_FMT_NV21;
|
|
break;
|
|
case RT_PIXEL_YUV420P:
|
|
v4l2_pix_fmt = V4L2_PIX_FMT_YUV420;
|
|
break;
|
|
case RT_PIXEL_YVU420P:
|
|
v4l2_pix_fmt = V4L2_PIX_FMT_YVU420;
|
|
break;
|
|
case RT_PIXEL_LBC_25X:
|
|
v4l2_pix_fmt = V4L2_PIX_FMT_LBC_2_5X;
|
|
break;
|
|
case RT_PIXEL_LBC_2X:
|
|
v4l2_pix_fmt = V4L2_PIX_FMT_LBC_2_0X;
|
|
break;
|
|
case RT_PIXEL_YUV422SP:
|
|
v4l2_pix_fmt = V4L2_PIX_FMT_NV16;
|
|
break;
|
|
case RT_PIXEL_YVU422SP:
|
|
v4l2_pix_fmt = V4L2_PIX_FMT_NV61;
|
|
break;
|
|
//blow 422 format csi not support, reserve.
|
|
case RT_PIXEL_YUV422P:
|
|
v4l2_pix_fmt = V4L2_PIX_FMT_YUV422P;
|
|
break;
|
|
case RT_PIXEL_YVU422P:
|
|
v4l2_pix_fmt = V4L2_PIX_FMT_YYUV;
|
|
break;
|
|
|
|
case RT_PIXEL_YUYV422:
|
|
v4l2_pix_fmt = V4L2_PIX_FMT_YUYV;
|
|
break;
|
|
case RT_PIXEL_UYVY422:
|
|
v4l2_pix_fmt = V4L2_PIX_FMT_UYVY;
|
|
break;
|
|
case RT_PIXEL_YVYU422:
|
|
v4l2_pix_fmt = V4L2_PIX_FMT_YVYU;
|
|
break;
|
|
case RT_PIXEL_VYUY422:
|
|
v4l2_pix_fmt = V4L2_PIX_FMT_VYUY;
|
|
break;
|
|
default:
|
|
v4l2_pix_fmt = V4L2_PIX_FMT_YUV420M;
|
|
break;
|
|
}
|
|
return v4l2_pix_fmt;
|
|
}
|
|
|
|
static int vipp_init(vi_comp_ctx *vi_comp)
|
|
{
|
|
int ret = 0;
|
|
int id = vi_comp->base_config.channel_id;
|
|
struct v4l2_streamparm parms;
|
|
struct v4l2_format fmt;
|
|
int wdr_param = 0;
|
|
struct csi_ve_online_cfg online_cfg;
|
|
|
|
memset(&online_cfg, 0, sizeof(struct csi_ve_online_cfg));
|
|
|
|
RT_LOGW("vipp init: widht = %d, height = %d, fps = %d, id = %d, format = %d",
|
|
vi_comp->base_config.width, vi_comp->base_config.height,
|
|
vi_comp->base_config.frame_rate, id, vi_comp->base_config.pixelformat);
|
|
|
|
callback_count = 0;
|
|
dequeue_count = 0;
|
|
time_vi_start = 0;
|
|
time_first_cb = 0;
|
|
|
|
if (vi_comp->base_config.enable_high_fps_transfor == 0)
|
|
ret = vin_open_special(id);
|
|
RT_LOGI("vin open, ret = %d, id = %d", ret, id);
|
|
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time3_start = get_cur_time();
|
|
#endif
|
|
|
|
if (vi_comp->base_config.enable_high_fps_transfor == 0)
|
|
ret = vin_s_input_special(id, 0);
|
|
RT_LOGI("vin s input, ret = %d, id = %d", ret, id);
|
|
|
|
if (vi_comp->base_config.enable_aiisp && vi_comp->base_config.tdm_rxbuf_cnt)
|
|
vin_set_tdm_rxbuf_cnt_special(vi_comp->base_config.channel_id, &vi_comp->base_config.tdm_rxbuf_cnt);
|
|
|
|
if (vi_comp->base_config.width == 0 || vi_comp->base_config.height == 0) {
|
|
struct sensor_resolution Sensor_resolution;
|
|
memset(&Sensor_resolution, 0, sizeof(struct sensor_resolution));
|
|
|
|
vin_get_sensor_resolution_special(id, (void *)&Sensor_resolution);
|
|
if (Sensor_resolution.width_max && Sensor_resolution.height_max) {
|
|
if (Sensor_resolution.width_max > 1920) {
|
|
vi_comp->base_config.width = 1920;
|
|
vi_comp->base_config.height = 1088;
|
|
} else {
|
|
vi_comp->base_config.width = Sensor_resolution.width_max;
|
|
vi_comp->base_config.height = Sensor_resolution.height_max;
|
|
}
|
|
} else {
|
|
vi_comp->base_config.width = 640;
|
|
vi_comp->base_config.height = 480;
|
|
}
|
|
}
|
|
|
|
online_cfg.ve_online_en = vi_comp->base_config.bonline_channel;
|
|
online_cfg.dma_buf_num = vi_comp->base_config.share_buf_num;
|
|
ret = vin_set_ve_online_cfg_special(id, &online_cfg);
|
|
RT_LOGI("vin_set_ve_online_cfg_special, ret = %d, id = %d", ret, id);
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time3_end = get_cur_time();
|
|
RT_LOGE("time of s input: %lld", (time3_end - time3_start));
|
|
#endif
|
|
|
|
if (vi_comp->base_config.enable_wdr == 1)
|
|
wdr_param = 1;
|
|
else
|
|
wdr_param = 0;
|
|
RT_LOGI("wdr_param = %d, enable_wdr = %d", wdr_param, vi_comp->base_config.enable_wdr);
|
|
|
|
/* set parameter */
|
|
CLEAR(parms);
|
|
parms.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
|
parms.parm.capture.timeperframe.numerator = 1;
|
|
parms.parm.capture.timeperframe.denominator = vi_comp->base_config.frame_rate;
|
|
parms.parm.capture.capturemode = V4L2_MODE_VIDEO;
|
|
/* parms.parm.capture.capturemode = V4L2_MODE_IMAGE; */
|
|
/*when different video have the same sensor source, 1:use sensor current win, 0:find the nearest win*/
|
|
parms.parm.capture.reserved[0] = 0;
|
|
parms.parm.capture.reserved[1] = wdr_param; /*2:command, 1: wdr, 0: normal*/
|
|
|
|
ret = vin_s_parm_special(id, NULL, &parms);
|
|
RT_LOGI("vin s parm, ret = %d, id = %d", ret, id);
|
|
|
|
/* set format */
|
|
CLEAR(fmt);
|
|
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
|
fmt.fmt.pix_mp.width = vi_comp->base_config.width;
|
|
fmt.fmt.pix_mp.height = vi_comp->base_config.height;
|
|
fmt.fmt.pix_mp.colorspace =
|
|
convert_to_v4l2_color_space(&vi_comp->base_config.venc_video_signal);
|
|
RT_LOGI("fmt.fmt.pix_mp.colorspace %d %d", fmt.fmt.pix_mp.colorspace, V4L2_COLORSPACE_REC709);
|
|
fmt.fmt.pix_mp.pixelformat = vi_change_pixelformat_2_vin(vi_comp->base_config.pixelformat);
|
|
fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
|
|
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time2_start = get_cur_time();
|
|
#endif
|
|
|
|
ret = vin_s_fmt_special(id, &fmt);
|
|
RT_LOGI("vin s fmt, ret = %d, id = %d", ret, id);
|
|
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time2_end = get_cur_time();
|
|
RT_LOGE("time of s fmt: %lld", (time2_end - time2_start));
|
|
#endif
|
|
|
|
vin_g_fmt_special(id, &fmt);
|
|
RT_LOGI("vin g fmt, ret = %d, id = %d", ret, id);
|
|
|
|
RT_LOGD("resolution got from sensor = %d*%d num_planes = %d\n",
|
|
fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
|
|
fmt.fmt.pix_mp.num_planes);
|
|
|
|
/* queue buffer */
|
|
vi_comp->vipp_id = id;
|
|
g_vi_comp[id] = vi_comp;
|
|
|
|
vin_register_buffer_done_callback(id, vin_buffer_callback);
|
|
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time_start = get_cur_time();
|
|
#endif
|
|
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time_end = get_cur_time();
|
|
RT_LOGE("time of alloc buf: %lld", (time_end - time_start));
|
|
#endif
|
|
|
|
/* stream on */
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time1_start = get_cur_time();
|
|
#endif
|
|
|
|
time_vi_start = get_cur_time();
|
|
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time1_end = get_cur_time();
|
|
|
|
RT_LOGE("time of stream on: %lld", (time1_end - time1_start));
|
|
#endif
|
|
RT_LOGD("ret %d", ret);
|
|
return ret;
|
|
}
|
|
|
|
static int reset_high_fps(vi_comp_ctx *vi_comp)
|
|
{
|
|
vin_streamoff_special(vi_comp->vipp_id, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
|
|
|
|
RT_LOGW("vin streamoff\n");
|
|
|
|
highframe_free_vin_buf(vi_comp);
|
|
|
|
vipp_init(vi_comp);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int request_yuv_frame(struct vi_comp_ctx *vi_comp, rt_yuv_info *p_yuv_info)
|
|
{
|
|
unsigned long flags;
|
|
int ret = -1;
|
|
struct vin_buffer *vin_buf = NULL;
|
|
int data_size = vi_comp->align_width * vi_comp->base_config.height * 3 / 2;
|
|
int loop_cnt = 0;
|
|
int max_cnt = 50;
|
|
int i = 0;
|
|
|
|
if (vi_comp->base_config.pixelformat == RT_PIXEL_LBC_25X || vi_comp->base_config.pixelformat == RT_PIXEL_LBC_2X)
|
|
data_size = vi_comp->buf_size;
|
|
|
|
while (ret != 0) {
|
|
ret = vin_dqbuffer_special(vi_comp->vipp_id, &vin_buf);
|
|
|
|
if (ret != 0) {
|
|
spin_lock_irqsave(&vi_comp->vi_spin_lock, flags);
|
|
vi_comp->wait_in_buf_condition = 0;
|
|
spin_unlock_irqrestore(&vi_comp->vi_spin_lock, flags);
|
|
/* timeout is 10 ms: HZ is 100, HZ == 1s, so 1 jiffies is 10 ms */
|
|
wait_event_timeout(vi_comp->wait_in_buf, vi_comp->wait_in_buf_condition, 10);
|
|
}
|
|
loop_cnt++;
|
|
if (loop_cnt > max_cnt) {
|
|
RT_LOGE("loop timeout: loop_cnt = %d\n", loop_cnt);
|
|
break;
|
|
}
|
|
}
|
|
|
|
RT_LOGI("ret = %d, loop_cnt = %d, data_size = %d\n", ret, loop_cnt, data_size);
|
|
|
|
if (ret != 0) {
|
|
RT_LOGE(" dequeue buf failed\n");
|
|
return ret;
|
|
}
|
|
RT_LOGI("success, ret = %d, loop_cnt = %d, data_size = %d\n", ret, loop_cnt, data_size);
|
|
p_yuv_info->phy_addr = (unsigned char *)vin_buf->paddr;
|
|
|
|
for (i = 0; i < CONFIG_YUV_BUF_NUM; i++) {
|
|
if (p_yuv_info->phy_addr == vi_comp->s_yuv_info[i].phy_addr) {
|
|
if (vi_comp->s_yuv_info[i].bset)
|
|
p_yuv_info->fd = vi_comp->s_yuv_info[i].fd;
|
|
else {
|
|
vi_comp->s_yuv_info[i].fd = cdc_mem_share_fd(vi_comp->memops, vin_buf->vir_addr);
|
|
p_yuv_info->fd = vi_comp->s_yuv_info[i].fd;
|
|
vi_comp->s_yuv_info[i].bset = 1;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (i >= CONFIG_YUV_BUF_NUM)
|
|
RT_LOGE("get yuv mem fd err.");
|
|
return data_size;
|
|
}
|
|
|
|
static int return_yuv_frame(struct vi_comp_ctx *vi_comp, unsigned char *phy_addr)
|
|
{
|
|
int i = 0;
|
|
for (i = 0; i < vi_comp->base_config.vin_buf_num; i++) {
|
|
if (vi_comp->vin_buf[i].paddr == phy_addr) {
|
|
vin_qbuffer_special(vi_comp->vipp_id, &vi_comp->vin_buf[i]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i >= vi_comp->base_config.vin_buf_num) {
|
|
RT_LOGE("can not match phy_addr: %p", phy_addr);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int commond_process_vi(struct vi_comp_ctx *vi_comp, message_t *msg)
|
|
{
|
|
int ret = 0;
|
|
int cmd_error = 0;
|
|
int cmd = msg->command;
|
|
wait_queue_head_t *wait_reply = (wait_queue_head_t *)msg->wait_queue;
|
|
unsigned int *wait_condition = (unsigned int *)msg->wait_condition;
|
|
|
|
RT_LOGD("cmd process: cmd = %d, state = %d, wait_reply = %p, wait_condition = %p",
|
|
cmd, vi_comp->state, wait_reply, wait_condition);
|
|
|
|
if (cmd == COMP_COMMAND_INIT) {
|
|
if (vi_comp->state != COMP_STATE_IDLE) {
|
|
cmd_error = 1;
|
|
} else {
|
|
vi_comp->state = COMP_STATE_INITIALIZED;
|
|
}
|
|
|
|
} else if (cmd == COMP_COMMAND_START) {
|
|
if (vi_comp->state != COMP_STATE_INITIALIZED && vi_comp->state != COMP_STATE_PAUSE) {
|
|
cmd_error = 1;
|
|
} else {
|
|
if (vi_comp->state == COMP_STATE_INITIALIZED) {
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time_start = get_cur_time();
|
|
#endif
|
|
if (vi_comp->base_config.enable_high_fps_transfor == 1) {
|
|
highframe_vipp_init(vi_comp);
|
|
} else {
|
|
alloc_vin_buf(vi_comp);
|
|
ret = vin_streamon_special(vi_comp->base_config.channel_id, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
|
|
RT_LOGW("vin streamon, ret = %d, id = %d", ret, vi_comp->base_config.channel_id);
|
|
}
|
|
|
|
#if RT_VI_SHOW_TIME_COST
|
|
int64_t time_end = get_cur_time();
|
|
RT_LOGW("time of vipp_init: %lld time: %lld", (time_end - time_start), time_end);
|
|
#endif
|
|
}
|
|
|
|
vi_comp->state = COMP_STATE_EXECUTING;
|
|
}
|
|
|
|
} else if (cmd == COMP_COMMAND_PAUSE) {
|
|
if (vi_comp->state != COMP_STATE_EXECUTING) {
|
|
cmd_error = 1;
|
|
} else {
|
|
vi_comp->state = COMP_STATE_PAUSE;
|
|
}
|
|
} else if (cmd == COMP_COMMAND_STOP) {
|
|
vin_streamoff_special(vi_comp->vipp_id, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
|
|
vi_comp->state = COMP_STATE_IDLE;
|
|
} else if (cmd == COMP_COMMAND_RESET_HIGH_FPS) {
|
|
RT_LOGW("*** process COMP_COMMAND_RESET_HIGH_FPS ***");
|
|
vi_comp->callback->EventHandler(
|
|
vi_comp->self_comp,
|
|
vi_comp->callback_data,
|
|
COMP_EVENT_CMD_RESET_ISP_HIGH_FPS,
|
|
0,
|
|
0,
|
|
NULL);
|
|
} else if (cmd == COMP_COMMAND_EXIT) {
|
|
if (vi_comp->state != COMP_STATE_IDLE) {
|
|
cmd_error = 1;
|
|
} else {
|
|
vi_comp->state = COMP_STATE_EXIT;
|
|
}
|
|
}
|
|
|
|
if (cmd_error == 1) {
|
|
vi_comp->callback->EventHandler(
|
|
vi_comp->self_comp,
|
|
vi_comp->callback_data,
|
|
COMP_EVENT_CMD_ERROR,
|
|
COMP_COMMAND_INIT,
|
|
0,
|
|
NULL);
|
|
} else {
|
|
vi_comp->callback->EventHandler(
|
|
vi_comp->self_comp,
|
|
vi_comp->callback_data,
|
|
COMP_EVENT_CMD_COMPLETE,
|
|
cmd,
|
|
0,
|
|
NULL);
|
|
}
|
|
|
|
if (wait_reply) {
|
|
RT_LOGD("wait up: cmd = %d", cmd);
|
|
*wait_condition = 1;
|
|
wake_up(wait_reply);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static error_type config_dynamic_param(
|
|
vi_comp_ctx *vi_comp,
|
|
comp_index_type index,
|
|
void *param_data)
|
|
{
|
|
error_type error = ERROR_TYPE_OK;
|
|
|
|
RT_LOGW("not support config dynamic param yet");
|
|
|
|
return error;
|
|
}
|
|
|
|
static int post_msg_and_wait(vi_comp_ctx *vi_comp, int cmd_id, int msg_param)
|
|
{
|
|
message_t cmd_msg;
|
|
memset(&cmd_msg, 0, sizeof(message_t));
|
|
cmd_msg.command = cmd_id;
|
|
cmd_msg.para0 = msg_param;
|
|
cmd_msg.wait_queue = (char *)&vi_comp->wait_reply[cmd_id];
|
|
cmd_msg.wait_condition = (char *)&vi_comp->wait_reply_condition[cmd_id];
|
|
|
|
vi_comp->wait_reply_condition[cmd_id] = 0;
|
|
|
|
put_message(&vi_comp->msg_queue, &cmd_msg);
|
|
|
|
RT_LOGD("wait for : cmd[%d], start", cmd_id);
|
|
wait_event(vi_comp->wait_reply[cmd_id],
|
|
vi_comp->wait_reply_condition[cmd_id]);
|
|
RT_LOGD("wait for : cmd[%d], finish", cmd_id);
|
|
|
|
return 0;
|
|
}
|
|
|
|
error_type vi_comp_init(
|
|
PARAM_IN comp_handle component)
|
|
{
|
|
error_type error = ERROR_TYPE_OK;
|
|
int ret = 0;
|
|
rt_component_type *rt_component = (rt_component_type *)component;
|
|
struct vi_comp_ctx *vi_comp = (struct vi_comp_ctx *)rt_component->component_private;
|
|
|
|
if (rt_component == NULL || vi_comp == NULL) {
|
|
RT_LOGE("venc_comp_init: param error");
|
|
return ERROR_TYPE_ILLEGAL_PARAM;
|
|
}
|
|
|
|
vi_comp->vin_buf = kzalloc(sizeof(struct vin_buffer) * vi_comp->base_config.vin_buf_num, GFP_KERNEL);
|
|
|
|
vipp_create(vi_comp);
|
|
ret = vipp_init(vi_comp);
|
|
if (ret != 0) {
|
|
RT_LOGE("vipp_init error ret %d", ret);
|
|
return ERROR_TYPE_VIN_ERR;
|
|
}
|
|
post_msg_and_wait(vi_comp, COMP_COMMAND_INIT, 0);
|
|
return error;
|
|
}
|
|
|
|
error_type vi_comp_start(
|
|
PARAM_IN comp_handle component)
|
|
{
|
|
error_type error = ERROR_TYPE_OK;
|
|
rt_component_type *rt_component = (rt_component_type *)component;
|
|
struct vi_comp_ctx *vi_comp = (struct vi_comp_ctx *)rt_component->component_private;
|
|
|
|
if (rt_component == NULL || vi_comp == NULL) {
|
|
RT_LOGE("venc_comp_start: param error");
|
|
return ERROR_TYPE_ILLEGAL_PARAM;
|
|
}
|
|
|
|
post_msg_and_wait(vi_comp, COMP_COMMAND_START, 0);
|
|
return error;
|
|
}
|
|
|
|
error_type vi_comp_pause(
|
|
PARAM_IN comp_handle component)
|
|
{
|
|
error_type error = ERROR_TYPE_OK;
|
|
|
|
rt_component_type *rt_component = (rt_component_type *)component;
|
|
struct vi_comp_ctx *vi_comp = (struct vi_comp_ctx *)rt_component->component_private;
|
|
|
|
if (rt_component == NULL || vi_comp == NULL) {
|
|
RT_LOGE("venc_comp_start: param error");
|
|
return ERROR_TYPE_ILLEGAL_PARAM;
|
|
}
|
|
|
|
post_msg_and_wait(vi_comp, COMP_COMMAND_PAUSE, 0);
|
|
return error;
|
|
}
|
|
|
|
error_type vi_comp_stop(
|
|
PARAM_IN comp_handle component)
|
|
{
|
|
error_type error = ERROR_TYPE_OK;
|
|
|
|
rt_component_type *rt_component = (rt_component_type *)component;
|
|
struct vi_comp_ctx *vi_comp = (struct vi_comp_ctx *)rt_component->component_private;
|
|
|
|
if (rt_component == NULL || vi_comp == NULL) {
|
|
RT_LOGE("venc_comp_stop: param error");
|
|
return ERROR_TYPE_ILLEGAL_PARAM;
|
|
}
|
|
|
|
post_msg_and_wait(vi_comp, COMP_COMMAND_STOP, 0);
|
|
return error;
|
|
}
|
|
|
|
error_type vi_comp_destroy(PARAM_IN comp_handle component)
|
|
{
|
|
int i = 0;
|
|
error_type error = ERROR_TYPE_OK;
|
|
rt_component_type *rt_component = (rt_component_type *)component;
|
|
struct vi_comp_ctx *vi_comp = (struct vi_comp_ctx *)rt_component->component_private;
|
|
video_frame_node *frame_node = NULL;
|
|
int free_frame_cout = 0;
|
|
|
|
if (rt_component == NULL || vi_comp == NULL) {
|
|
RT_LOGE("venc_comp_destroy: param error");
|
|
return ERROR_TYPE_ILLEGAL_PARAM;
|
|
}
|
|
|
|
vin_close_special(vi_comp->vipp_id);
|
|
/*should make sure the thread do nothing importent */
|
|
if (vi_comp->vi_thread)
|
|
post_msg_and_wait(vi_comp, COMP_COMMAND_EXIT, 0);
|
|
//kthread_stop(vi_comp->vi_thread);
|
|
message_destroy(&vi_comp->msg_queue);
|
|
|
|
while ((!list_empty(&vi_comp->out_buf_manager.empty_frame_list))) {
|
|
frame_node = list_first_entry(&vi_comp->out_buf_manager.empty_frame_list, video_frame_node, mList);
|
|
if (frame_node) {
|
|
free_frame_cout++;
|
|
list_del(&frame_node->mList);
|
|
kfree(frame_node);
|
|
}
|
|
}
|
|
|
|
while ((!list_empty(&vi_comp->out_buf_manager.valid_frame_list))) {
|
|
frame_node = list_first_entry(&vi_comp->out_buf_manager.valid_frame_list, video_frame_node, mList);
|
|
if (frame_node) {
|
|
free_frame_cout++;
|
|
list_del(&frame_node->mList);
|
|
kfree(frame_node);
|
|
}
|
|
}
|
|
RT_LOGD("free_frame_cout = %d", free_frame_cout);
|
|
if (free_frame_cout != vi_comp->base_config.vin_buf_num)
|
|
RT_LOGE("free num of frame node is not match: %d, %d", free_frame_cout, vi_comp->base_config.vin_buf_num);
|
|
|
|
if (vi_comp->config_yuv_buf_flag == 0) {
|
|
for (i = 0; i < vi_comp->base_config.vin_buf_num; i++) {
|
|
if (vi_comp->vin_buf[i].paddr) {
|
|
unsigned char *virAddr = (unsigned char *)cdc_mem_get_vir(vi_comp->memops,
|
|
(unsigned long)vi_comp->vin_buf[i].paddr);
|
|
cdc_mem_pfree(vi_comp->memops, virAddr);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (vi_comp->vin_buf != NULL) {
|
|
kfree(vi_comp->vin_buf);
|
|
vi_comp->vin_buf = NULL;
|
|
}
|
|
|
|
if (vi_comp->memops)
|
|
mem_destory(MEM_TYPE_ION, vi_comp->memops);
|
|
|
|
kfree(vi_comp);
|
|
|
|
return error;
|
|
}
|
|
|
|
error_type vi_comp_get_config(
|
|
PARAM_IN comp_handle component,
|
|
PARAM_IN comp_index_type index,
|
|
PARAM_INOUT void *param_data)
|
|
{
|
|
error_type error = ERROR_TYPE_OK;
|
|
rt_component_type *rt_component = (rt_component_type *)component;
|
|
struct vi_comp_ctx *vi_comp = (struct vi_comp_ctx *)rt_component->component_private;
|
|
|
|
if (rt_component == NULL || vi_comp == NULL) {
|
|
RT_LOGE("vi_comp_get_config: param error");
|
|
return ERROR_TYPE_ILLEGAL_PARAM;
|
|
}
|
|
|
|
switch (index) {
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_GET_ISP_ARRT_CFG: {
|
|
RTIspCtrlAttr *ctrlattr = (RTIspCtrlAttr *)param_data;
|
|
|
|
vin_get_isp_attr_cfg_special(vi_comp->vipp_id, &(ctrlattr->isp_attr_cfg));
|
|
|
|
RT_LOGD("set isp attr cfg");
|
|
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_GET_SENSOR_NAME: {
|
|
char *sensor_name = (char *)param_data;
|
|
|
|
vin_get_sensor_name_special(vi_comp->vipp_id, &sensor_name[0]);
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_GET_SENSOR_RESOLUTION: {
|
|
RTSensorResolution *sensor_resolution = (RTSensorResolution *)param_data;
|
|
|
|
vin_get_sensor_resolution_special(vi_comp->vipp_id, (void *)sensor_resolution);
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_GET_TUNNING_CTL_DATA: {
|
|
RTTunningCtlData *TunningCtlData = (RTTunningCtlData *)param_data;
|
|
|
|
vin_tunning_ctrl_special(vi_comp->vipp_id, (void *)TunningCtlData);
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_GET_BASE_CONFIG: {
|
|
vi_comp_base_config *base_config = (vi_comp_base_config *)param_data;
|
|
memcpy(base_config, &vi_comp->base_config, sizeof(vi_comp_base_config));
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_GET_BKBUF_INFO: {
|
|
vi_bkbuf_info *bkbuf_info = (vi_bkbuf_info *)param_data;
|
|
if (vi_comp->base_config.pixelformat == RT_PIXEL_LBC_25X || vi_comp->base_config.pixelformat == RT_PIXEL_LBC_2X) {
|
|
bkbuf_info->buf_size = vi_comp->buf_size + LBC_EXT_SIZE;
|
|
} else {
|
|
bkbuf_info->buf_size = vi_comp->buf_size;
|
|
}
|
|
bkbuf_info->buf_num = vi_comp->buf_num;
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_GET_SENSOR_RESERVE_ADDR: {
|
|
SENSOR_ISP_CONFIG_S *sensor_isp_cfg = (SENSOR_ISP_CONFIG_S *)param_data;
|
|
vin_get_sensor_reserve_addr(vi_comp->vipp_id, sensor_isp_cfg);
|
|
break;
|
|
}
|
|
default: {
|
|
error = config_dynamic_param(vi_comp, index, param_data);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
error_type vi_comp_set_config(
|
|
PARAM_IN comp_handle component,
|
|
PARAM_IN comp_index_type index,
|
|
PARAM_IN void *param_data)
|
|
{
|
|
error_type error = ERROR_TYPE_OK;
|
|
rt_component_type *rt_component = (rt_component_type *)component;
|
|
struct vi_comp_ctx *vi_comp = (struct vi_comp_ctx *)rt_component->component_private;
|
|
|
|
if (rt_component == NULL || vi_comp == NULL) {
|
|
RT_LOGE("venc_comp_set_config: param error");
|
|
return ERROR_TYPE_ILLEGAL_PARAM;
|
|
}
|
|
|
|
switch (index) {
|
|
case COMP_INDEX_VI_CONFIG_Base: {
|
|
vi_comp_base_config *base_config = (vi_comp_base_config *)param_data;
|
|
memcpy(&vi_comp->base_config, base_config, sizeof(vi_comp_base_config));
|
|
vi_comp->align_width = RT_ALIGN(vi_comp->base_config.width, 16);
|
|
vi_comp->align_height = RT_ALIGN(vi_comp->base_config.height, 16);
|
|
vi_comp->max_fps = base_config->frame_rate;
|
|
|
|
if (vi_comp->max_fps <= 0)
|
|
vi_comp->max_fps = 15;
|
|
|
|
#ifdef CONFIG_FRAMEDONE_TWO_BUFFER
|
|
if ((0 == vi_comp->base_config.bonline_channel) && (0 == vi_comp->base_config.enable_high_fps_transfor)) {
|
|
vi_comp->base_config.vin_buf_num = 2;
|
|
RT_LOGW("channel %d update vin_buf_num %d", vi_comp->base_config.channel_id, vi_comp->base_config.vin_buf_num);
|
|
}
|
|
#endif
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Normal: {
|
|
vi_comp_normal_config *normal_config = (vi_comp_normal_config *)param_data;
|
|
memcpy(&vi_comp->normal_config, normal_config, sizeof(vi_comp_normal_config));
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_SET_YUV_BUF_INFO: {
|
|
memcpy(&vi_comp->yuv_buf_info, (config_yuv_buf_info *)param_data, sizeof(config_yuv_buf_info));
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_REQUEST_YUV_FRAME: {
|
|
if (vi_comp->state != COMP_STATE_EXECUTING) {
|
|
RT_LOGW("the state is not executing when request yuv frame: %d", vi_comp->state);
|
|
break;
|
|
}
|
|
|
|
post_msg_and_wait(vi_comp, COMP_COMMAND_PAUSE, 0);
|
|
rt_yuv_info *p_yuv_info = (rt_yuv_info *)param_data;
|
|
|
|
error = request_yuv_frame(vi_comp, p_yuv_info);
|
|
RT_LOGI("request yuv frame, ret = %d, fd = %d phy_addr %p\n", error, p_yuv_info->fd, p_yuv_info->phy_addr);
|
|
|
|
post_msg_and_wait(vi_comp, COMP_COMMAND_START, 0);
|
|
|
|
if (error < 0)
|
|
error = ERROR_TYPE_ERROR;
|
|
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_RETURN_YUV_FRAME: {
|
|
if (vi_comp->state != COMP_STATE_EXECUTING) {
|
|
RT_LOGW("the state is not executing when request yuv frame: %d", vi_comp->state);
|
|
break;
|
|
}
|
|
|
|
error = return_yuv_frame(vi_comp, (unsigned char *)param_data);
|
|
RT_LOGI("return yuv frame, ret = %d, phy_addr = %p\n", error, param_data);
|
|
|
|
if (error < 0)
|
|
error = ERROR_TYPE_ERROR;
|
|
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_GET_LV: {
|
|
int lv = 0;
|
|
|
|
if (vi_comp->state != COMP_STATE_EXECUTING) {
|
|
RT_LOGW("the state is not executing when get lv: %d", vi_comp->state);
|
|
break;
|
|
}
|
|
|
|
//lv = vin_isp_get_lv_special(vi_comp->vipp_id, 0);
|
|
RT_LOGI("get lv = %d\n", lv);
|
|
|
|
return lv;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_SET_IR_PARAM: {
|
|
RTIrParam *ir_param = (RTIrParam *)param_data;
|
|
int mode_flag = 0;
|
|
|
|
if (vi_comp->state != COMP_STATE_EXECUTING) {
|
|
RT_LOGW("the state is not executing when get lv: %d", vi_comp->state);
|
|
break;
|
|
}
|
|
|
|
/* ir_mode of user -- 0 :color, 1: grey */
|
|
if (ir_param->grey == 1)
|
|
mode_flag = 2;
|
|
else
|
|
mode_flag = 0;
|
|
|
|
RT_LOGI("set ir param: mode_flag = %d, ir_on = %d, ir_flash_on = %d",
|
|
mode_flag, ir_param->ir_on, ir_param->ir_flash_on);
|
|
|
|
/* ir_mode of isp -- 2: grey, other: color */
|
|
vin_server_reset_special(vi_comp->vipp_id, mode_flag, ir_param->ir_on, ir_param->ir_flash_on);
|
|
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_SET_H_FLIP: {
|
|
int bhflip = (int)param_data;
|
|
unsigned int ctrl_id = V4L2_CID_HFLIP;
|
|
int val = bhflip;
|
|
|
|
RT_LOGI("set h flip: %d", bhflip);
|
|
|
|
vin_s_ctrl_special(vi_comp->vipp_id, ctrl_id, val);
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_SET_V_FLIP: {
|
|
int bvflip = (int)param_data;
|
|
unsigned int ctrl_id = V4L2_CID_VFLIP;
|
|
int val = bvflip;
|
|
|
|
RT_LOGI("set v flip: %d", bvflip);
|
|
|
|
vin_s_ctrl_special(vi_comp->vipp_id, ctrl_id, val);
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_CATCH_JPEG: {
|
|
vi_comp->catch_jpeg_flag = (int)param_data;
|
|
RT_LOGI("vi_comp->catch_jpeg_flag = %d", vi_comp->catch_jpeg_flag);
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_SET_POWER_LINE_FREQ: {
|
|
enum RT_POWER_LINE_FREQUENCY ePower_line = (enum RT_POWER_LINE_FREQUENCY)param_data;
|
|
unsigned int ctrl_id = V4L2_CID_POWER_LINE_FREQUENCY;
|
|
|
|
RT_LOGI("ePower_line_freq = %d", ePower_line);
|
|
|
|
vin_s_ctrl_special(vi_comp->vipp_id, ctrl_id, ePower_line);
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_SET_BRIGHTNESS: {
|
|
int brightness_level = (int)param_data;
|
|
unsigned int ctrl_id = V4L2_CID_BRIGHTNESS;
|
|
|
|
RT_LOGI("brightness_level = %d", brightness_level);
|
|
|
|
vin_s_ctrl_special(vi_comp->vipp_id, ctrl_id, brightness_level);
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_SET_CONTRAST: {
|
|
int contrast_level = (int)param_data;
|
|
unsigned int ctrl_id = V4L2_CID_CONTRAST;
|
|
|
|
RT_LOGI("contrast_level = %d", contrast_level);
|
|
|
|
vin_s_ctrl_special(vi_comp->vipp_id, ctrl_id, contrast_level);
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_SET_SATURATION: {
|
|
int saturation_level = (int)param_data;
|
|
unsigned int ctrl_id = V4L2_CID_SATURATION;
|
|
|
|
RT_LOGI("saturation_level = %d", saturation_level);
|
|
|
|
vin_s_ctrl_special(vi_comp->vipp_id, ctrl_id, saturation_level);
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_SET_HUE: {
|
|
int hue_level = (int)param_data;
|
|
unsigned int ctrl_id = V4L2_CID_HUE;
|
|
|
|
RT_LOGI("hue_level = %d", hue_level);
|
|
|
|
vin_s_ctrl_special(vi_comp->vipp_id, ctrl_id, hue_level);
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_SET_SHARPNESS: {
|
|
int sharpness_level = (int)param_data;
|
|
unsigned int ctrl_id = V4L2_CID_SHARPNESS;
|
|
|
|
RT_LOGI("sharpness_level = %d", sharpness_level);
|
|
|
|
vin_s_ctrl_special(vi_comp->vipp_id, ctrl_id, sharpness_level);
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_SET_AE_METERING_MODE: {
|
|
enum RT_AE_METERING_MODE ae_metering_mode = (enum RT_AE_METERING_MODE)param_data;
|
|
unsigned int ctrl_id = V4L2_CID_EXPOSURE_METERING;
|
|
|
|
RT_LOGI("ae_metering_mode = %d", ae_metering_mode);
|
|
|
|
vin_s_ctrl_special(vi_comp->vipp_id, ctrl_id, ae_metering_mode);
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_SET_AE_MODE: {
|
|
int ae_mode = (int)param_data;
|
|
unsigned int ctrl_id;
|
|
unsigned int ctrl_value;
|
|
|
|
ctrl_id = V4L2_CID_EXPOSURE_AUTO;
|
|
ctrl_value = ae_mode;
|
|
vin_s_ctrl_special(vi_comp->vipp_id, ctrl_id, ctrl_value);
|
|
ctrl_id = V4L2_CID_AUTOGAIN;
|
|
if (!ae_mode) {
|
|
/* auto ae */
|
|
ctrl_value = 1;
|
|
} else {
|
|
/* manual ae */
|
|
ctrl_value = 0;
|
|
}
|
|
vin_s_ctrl_special(vi_comp->vipp_id, ctrl_id, ctrl_value);
|
|
|
|
RT_LOGI("ae_mode = %d", ae_mode);
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_SET_EXP: {
|
|
int exp_time = (int)param_data;
|
|
unsigned int ctrl_id = V4L2_CID_EXPOSURE_ABSOLUTE;
|
|
|
|
vin_s_ctrl_special(vi_comp->vipp_id, ctrl_id, exp_time);
|
|
|
|
RT_LOGI("exp_time = %d", exp_time);
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_SET_GAIN: {
|
|
int sensor_gain = (int)param_data;
|
|
unsigned int ctrl_id = V4L2_CID_GAIN;
|
|
|
|
vin_s_ctrl_special(vi_comp->vipp_id, ctrl_id, sensor_gain);
|
|
|
|
RT_LOGI("sensor_gain = %d", sensor_gain);
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_GET_EXP_GAIN: {
|
|
RTIspExpGain *exp_gain = (RTIspExpGain *)param_data;
|
|
|
|
vin_isp_get_exp_gain_special(vi_comp->vipp_id, (struct sensor_exp_gain *)exp_gain);
|
|
|
|
RT_LOGI("get exp&gain = %d/%d/%d/%d", exp_gain->exp_val, exp_gain->gain_val,
|
|
exp_gain->r_gain, exp_gain->b_gain);
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_GET_HIST: {
|
|
unsigned int *hist = (unsigned int *)param_data;
|
|
|
|
vin_isp_get_hist_special(vi_comp->vipp_id, hist);
|
|
|
|
RT_LOGI("get hist");
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_SET_ORL: {
|
|
int i;
|
|
struct v4l2_format fmt;
|
|
RTIspOrl *isp_orl = (RTIspOrl *)param_data;
|
|
struct v4l2_clip clips[isp_orl->orl_cnt * 2];
|
|
|
|
for (i = 0; i < isp_orl->orl_cnt; i++) {
|
|
clips[i].c.height = isp_orl->orl_win[i].height;
|
|
clips[i].c.width = isp_orl->orl_win[i].width;
|
|
clips[i].c.left = isp_orl->orl_win[i].left;
|
|
clips[i].c.top = isp_orl->orl_win[i].top;
|
|
|
|
clips[isp_orl->orl_cnt + i].c.top = isp_orl->orl_win[i].rgb_orl;
|
|
}
|
|
clips[isp_orl->orl_cnt].c.width = isp_orl->orl_width;
|
|
|
|
CLEAR(fmt);
|
|
fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
|
|
fmt.fmt.win.clips = &clips[0];
|
|
fmt.fmt.win.clipcount = isp_orl->orl_cnt;
|
|
fmt.fmt.win.bitmap = NULL;
|
|
fmt.fmt.win.field = V4L2_FIELD_NONE;
|
|
vin_s_fmt_overlay_special(vi_comp->vipp_id, &fmt);
|
|
|
|
vin_overlay_special(vi_comp->vipp_id, isp_orl->on);
|
|
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_SET_ISP_ARRT_CFG: {
|
|
RTIspCtrlAttr *ctrlattr = (RTIspCtrlAttr *)param_data;
|
|
|
|
vin_set_isp_attr_cfg_special(vi_comp->vipp_id, &(ctrlattr->isp_attr_cfg));
|
|
|
|
RT_LOGD("set isp attr cfg");
|
|
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_SET_RESET_HIGH_FPS: {
|
|
if (vi_comp->state != COMP_STATE_PAUSE)
|
|
RT_LOGE("the state is not pause when reset-high-fps");
|
|
|
|
reset_high_fps(vi_comp);
|
|
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_ENABLE_HIGH_FPS: {
|
|
vi_comp->base_config.enable_high_fps_transfor = 1;
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_Dynamic_SET_FPS: {
|
|
int fps = (int)param_data;
|
|
|
|
if (fps < vi_comp->max_fps) {
|
|
vi_comp->base_config.st_adapter_venc_fps.enable = 1;
|
|
vi_comp->base_config.st_adapter_venc_fps.frame_cnt = -1;
|
|
vi_comp->base_config.st_adapter_venc_fps.dst_fps = fps;
|
|
} else if (fps > vi_comp->max_fps) {
|
|
RT_LOGW("Notice fps[%d] > max_fps[%d]", fps, vi_comp->max_fps);
|
|
}
|
|
|
|
RT_LOGW("set fps = %d, max_fps = %d, bEnable_reduce_fps = %d",
|
|
fps, vi_comp->max_fps, vi_comp->base_config.st_adapter_venc_fps.enable);
|
|
break;
|
|
}
|
|
case COMP_INDEX_VI_CONFIG_GET_ISP_REG_CONFIG: {
|
|
VIN_ISP_REG_GET_CFG *isp_reg_get_cfg_ptr = (VIN_ISP_REG_GET_CFG *)param_data;
|
|
vin_get_isp_reg(vi_comp->vipp_id, isp_reg_get_cfg_ptr->flag, isp_reg_get_cfg_ptr->path);
|
|
break;
|
|
}
|
|
default: {
|
|
error = config_dynamic_param(vi_comp, index, param_data);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
error_type vi_comp_get_state(
|
|
PARAM_IN comp_handle component,
|
|
PARAM_OUT comp_state_type *pState)
|
|
{
|
|
error_type error = ERROR_TYPE_OK;
|
|
rt_component_type *rt_component = (rt_component_type *)component;
|
|
struct vi_comp_ctx *vi_comp = (struct vi_comp_ctx *)rt_component->component_private;
|
|
|
|
if (rt_component == NULL || vi_comp == NULL) {
|
|
RT_LOGE("venc_comp_get_state: param error");
|
|
return ERROR_TYPE_ILLEGAL_PARAM;
|
|
}
|
|
|
|
*pState = vi_comp->state;
|
|
return error;
|
|
}
|
|
|
|
/* valid_list --> empty_list */
|
|
error_type vi_comp_fill_this_out_buffer(
|
|
PARAM_IN comp_handle component,
|
|
PARAM_IN comp_buffer_header_type *pBuffer)
|
|
{
|
|
error_type error = ERROR_TYPE_OK;
|
|
rt_component_type *rt_component = (rt_component_type *)component;
|
|
struct vi_comp_ctx *vi_comp = (struct vi_comp_ctx *)rt_component->component_private;
|
|
video_frame_s *src_stream = NULL;
|
|
video_frame_node *frame_node = NULL;
|
|
struct vin_buffer *vin_buf = NULL;
|
|
|
|
if (rt_component == NULL || vi_comp == NULL) {
|
|
RT_LOGE("venc_comp_fill_this_out_buffer: param error");
|
|
return ERROR_TYPE_ILLEGAL_PARAM;
|
|
}
|
|
|
|
src_stream = (video_frame_s *)pBuffer->private;
|
|
|
|
/* get the ready frame */
|
|
mutex_lock(&vi_comp->out_buf_manager.mutex);
|
|
|
|
if (list_empty(&vi_comp->out_buf_manager.valid_frame_list)) {
|
|
RT_LOGE("error: valid_frame_list is null");
|
|
mutex_unlock(&vi_comp->out_buf_manager.mutex);
|
|
return ERROR_TYPE_ERROR;
|
|
}
|
|
frame_node = list_first_entry(&vi_comp->out_buf_manager.valid_frame_list, video_frame_node, mList);
|
|
memcpy(&frame_node->video_frame, src_stream, sizeof(video_frame_s));
|
|
|
|
RT_LOGD("src_stream->id %d frame_node->video_frame.id %d", src_stream->id, frame_node->video_frame.id);
|
|
|
|
if (src_stream->id != frame_node->video_frame.id) {
|
|
RT_LOGE("id not match, src_stream->id %d frame_node->video_frame.id %d", src_stream->id, frame_node->video_frame.id);
|
|
}
|
|
|
|
list_move_tail(&frame_node->mList, &vi_comp->out_buf_manager.empty_frame_list);
|
|
|
|
mutex_unlock(&vi_comp->out_buf_manager.mutex);
|
|
|
|
vin_buf = src_stream->private;
|
|
|
|
RT_LOGI("vin_buf = %p", vin_buf);
|
|
|
|
if (vin_buf == NULL)
|
|
RT_LOGE("error: vin_buf is null");
|
|
else
|
|
vin_qbuffer_special(vi_comp->vipp_id, vin_buf);
|
|
|
|
return error;
|
|
}
|
|
|
|
error_type vi_comp_set_callbacks(
|
|
PARAM_IN comp_handle component,
|
|
PARAM_IN comp_callback_type *callback,
|
|
PARAM_IN void *callback_data)
|
|
{
|
|
error_type error = ERROR_TYPE_OK;
|
|
rt_component_type *rt_component = (rt_component_type *)component;
|
|
struct vi_comp_ctx *vi_comp = (struct vi_comp_ctx *)rt_component->component_private;
|
|
|
|
if (rt_component == NULL || vi_comp == NULL) {
|
|
RT_LOGE("venc_comp_set_callbacks: param error");
|
|
return ERROR_TYPE_ILLEGAL_PARAM;
|
|
}
|
|
|
|
vi_comp->callback = callback;
|
|
vi_comp->callback_data = callback_data;
|
|
return error;
|
|
}
|
|
|
|
error_type vi_comp_setup_tunnel(
|
|
PARAM_IN comp_handle component,
|
|
PARAM_IN comp_port_type port_type,
|
|
PARAM_IN comp_handle tunnel_comp,
|
|
PARAM_IN int connect_flag)
|
|
{
|
|
error_type error = ERROR_TYPE_OK;
|
|
rt_component_type *rt_component = (rt_component_type *)component;
|
|
struct vi_comp_ctx *vi_comp = (struct vi_comp_ctx *)rt_component->component_private;
|
|
|
|
if (rt_component == NULL || vi_comp == NULL || tunnel_comp == NULL) {
|
|
RT_LOGE("venc_comp_set_callbacks, param error: %p, %p, %p",
|
|
rt_component, vi_comp, tunnel_comp);
|
|
error = ERROR_TYPE_ILLEGAL_PARAM;
|
|
goto setup_tunnel_exit;
|
|
}
|
|
|
|
if (port_type == COMP_INPUT_PORT) {
|
|
if (connect_flag == 1) {
|
|
if (vi_comp->in_port_tunnel_info.valid_flag == 1) {
|
|
RT_LOGE("in port tunnel had setuped !!");
|
|
error = ERROR_TYPE_ERROR;
|
|
goto setup_tunnel_exit;
|
|
} else {
|
|
vi_comp->in_port_tunnel_info.valid_flag = 1;
|
|
vi_comp->in_port_tunnel_info.tunnel_comp = tunnel_comp;
|
|
}
|
|
} else {
|
|
if (vi_comp->in_port_tunnel_info.valid_flag == 1 && vi_comp->in_port_tunnel_info.tunnel_comp == tunnel_comp) {
|
|
vi_comp->in_port_tunnel_info.valid_flag = 0;
|
|
vi_comp->in_port_tunnel_info.tunnel_comp = NULL;
|
|
} else {
|
|
RT_LOGE("disconnect in tunnel failed: valid_flag = %d, tunnel_comp = %p, %p",
|
|
vi_comp->in_port_tunnel_info.valid_flag,
|
|
vi_comp->in_port_tunnel_info.tunnel_comp, tunnel_comp);
|
|
error = ERROR_TYPE_ERROR;
|
|
}
|
|
}
|
|
} else if (port_type == COMP_OUTPUT_PORT) {
|
|
if (connect_flag == 1) {
|
|
if (vi_comp->out_port_tunnel_info.valid_flag == 1) {
|
|
RT_LOGE("out port tunnel had setuped !!");
|
|
error = ERROR_TYPE_ERROR;
|
|
goto setup_tunnel_exit;
|
|
} else {
|
|
vi_comp->out_port_tunnel_info.valid_flag = 1;
|
|
vi_comp->out_port_tunnel_info.tunnel_comp = tunnel_comp;
|
|
}
|
|
} else {
|
|
if (vi_comp->out_port_tunnel_info.valid_flag == 1 && vi_comp->out_port_tunnel_info.tunnel_comp == tunnel_comp) {
|
|
vi_comp->out_port_tunnel_info.valid_flag = 0;
|
|
vi_comp->out_port_tunnel_info.tunnel_comp = NULL;
|
|
} else {
|
|
RT_LOGE("disconnect out tunnel failed: valid = %d, tunnel_comp = %p, %p",
|
|
vi_comp->out_port_tunnel_info.valid_flag,
|
|
vi_comp->out_port_tunnel_info.tunnel_comp, tunnel_comp);
|
|
error = ERROR_TYPE_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
setup_tunnel_exit:
|
|
|
|
return error;
|
|
}
|
|
|
|
error_type vi_comp_component_init(PARAM_IN comp_handle component, const rt_media_config_s *pmedia_config)
|
|
{
|
|
int i = 0;
|
|
int ret = 0;
|
|
error_type error = ERROR_TYPE_OK;
|
|
rt_component_type *rt_component = (rt_component_type *)component;
|
|
struct vi_comp_ctx *vi_comp = NULL;
|
|
struct sched_param param = {.sched_priority = 1 };
|
|
|
|
vi_comp = kmalloc(sizeof(struct vi_comp_ctx), GFP_KERNEL);
|
|
if (vi_comp == NULL) {
|
|
RT_LOGE("kmalloc for vi_comp failed");
|
|
error = ERROR_TYPE_NOMEM;
|
|
goto EXIT;
|
|
}
|
|
memset(vi_comp, 0, sizeof(struct vi_comp_ctx));
|
|
|
|
ret = message_create(&vi_comp->msg_queue);
|
|
if (ret < 0) {
|
|
RT_LOGE("message create failed");
|
|
error = ERROR_TYPE_ERROR;
|
|
goto EXIT;
|
|
}
|
|
|
|
rt_component->component_private = vi_comp;
|
|
rt_component->init = vi_comp_init;
|
|
rt_component->start = vi_comp_start;
|
|
rt_component->pause = vi_comp_pause;
|
|
rt_component->stop = vi_comp_stop;
|
|
rt_component->destroy = vi_comp_destroy;
|
|
rt_component->get_config = vi_comp_get_config;
|
|
rt_component->set_config = vi_comp_set_config;
|
|
rt_component->get_state = vi_comp_get_state;
|
|
rt_component->fill_this_out_buffer = vi_comp_fill_this_out_buffer;
|
|
rt_component->set_callbacks = vi_comp_set_callbacks;
|
|
rt_component->setup_tunnel = vi_comp_setup_tunnel;
|
|
|
|
vi_comp->self_comp = rt_component;
|
|
vi_comp->state = COMP_STATE_IDLE;
|
|
vi_comp->base_config.channel_id = pmedia_config->channelId;
|
|
|
|
init_waitqueue_head(&vi_comp->wait_in_buf);
|
|
for (i = 0; i < WAIT_REPLY_NUM; i++) {
|
|
init_waitqueue_head(&vi_comp->wait_reply[i]);
|
|
}
|
|
|
|
/* init out buf manager*/
|
|
mutex_init(&vi_comp->out_buf_manager.mutex);
|
|
RT_LOGD("channel %d vin_buf_num %d", pmedia_config->channelId, pmedia_config->vin_buf_num);
|
|
vi_comp->out_buf_manager.empty_num = pmedia_config->vin_buf_num;
|
|
INIT_LIST_HEAD(&vi_comp->out_buf_manager.empty_frame_list);
|
|
INIT_LIST_HEAD(&vi_comp->out_buf_manager.valid_frame_list);
|
|
for (i = 0; i < pmedia_config->vin_buf_num; i++) {
|
|
video_frame_node *pNode = kmalloc(sizeof(video_frame_node), GFP_KERNEL);
|
|
if (NULL == pNode) {
|
|
RT_LOGE("fatal error! kmalloc fail!");
|
|
error = ERROR_TYPE_NOMEM;
|
|
goto EXIT;
|
|
}
|
|
memset(pNode, 0, sizeof(video_frame_node));
|
|
list_add_tail(&pNode->mList, &vi_comp->out_buf_manager.empty_frame_list);
|
|
}
|
|
|
|
spin_lock_init(&vi_comp->vi_spin_lock);
|
|
|
|
vi_comp->vi_thread = kthread_create(thread_process_vi,
|
|
vi_comp, "vi comp thread");
|
|
sched_setscheduler(vi_comp->vi_thread, SCHED_FIFO, ¶m);
|
|
wake_up_process(vi_comp->vi_thread);
|
|
|
|
EXIT:
|
|
|
|
return error;
|
|
}
|
|
|
|
static int thread_process_vi(void *param)
|
|
{
|
|
struct vi_comp_ctx *vi_comp = (struct vi_comp_ctx *)param;
|
|
message_t cmd_msg;
|
|
unsigned long flags;
|
|
|
|
RT_LOGD("thread_process_vi start !");
|
|
while (1) {
|
|
if (kthread_should_stop())
|
|
break;
|
|
|
|
if (get_message(&vi_comp->msg_queue, &cmd_msg) == 0) {
|
|
/* todo */
|
|
commond_process_vi(vi_comp, &cmd_msg);
|
|
/* continue process message */
|
|
continue;
|
|
}
|
|
|
|
if (vi_comp->state == COMP_STATE_EXECUTING) {
|
|
/* get out buffer */
|
|
#if DEBUG_SHOW_ENCODE_TIME
|
|
static int cnt_1 = 1;
|
|
if (cnt_1 && vi_comp->base_config.channel_id == 0) {
|
|
cnt_1 = 0;
|
|
RT_LOGW("channel %d vin comp first time EXECUTING state, time: %lld",
|
|
vi_comp->base_config.channel_id, get_cur_time());
|
|
}
|
|
static int cnt_11 = 1;
|
|
if (cnt_11 && vi_comp->base_config.channel_id == 1) {
|
|
cnt_11 = 0;
|
|
RT_LOGW("channel %d vin comp first time EXECUTING state, time: %lld",
|
|
vi_comp->base_config.channel_id, get_cur_time());
|
|
}
|
|
#endif
|
|
if (dequeue_buffer(vi_comp) != 0) {
|
|
spin_lock_irqsave(&vi_comp->vi_spin_lock, flags);
|
|
vi_comp->wait_in_buf_condition = 0;
|
|
spin_unlock_irqrestore(&vi_comp->vi_spin_lock, flags);
|
|
/* timeout is 10 ms: HZ is 100, HZ == 1s, so 1 jiffies is 10 ms */
|
|
wait_event_timeout(vi_comp->wait_in_buf, vi_comp->wait_in_buf_condition, 10);
|
|
continue;
|
|
}
|
|
} else if (vi_comp->state == COMP_STATE_EXIT) {
|
|
RT_LOGW("COMP_STATE_EXIT vi_comp->state %d", vi_comp->state);
|
|
break;
|
|
} else {
|
|
TMessage_WaitQueueNotEmpty(&vi_comp->msg_queue, 1000);
|
|
}
|
|
}
|
|
|
|
RT_LOGD("thread_process_vi finish !");
|
|
return 0;
|
|
}
|