#include "sys_config.h" #include "tx_platform.h" #include "list.h" #include "dev.h" #include "typesdef.h" #include "lib/video/dvp/cmos_sensor/csi.h" #include "lib/video/h264/h264_drv.h" #include "devid.h" #include "osal/irq.h" #include "osal/string.h" #include "lib/video/dvp/jpeg/jpg.h" #include "hal/h264.h" #include "dev/scale/hgscale.h" #include "dev/h264/hg264.h" #include "osal/semaphore.h" #include "openDML.h" #include "osal/mutex.h" #include "lib/heap/av_heap.h" #include "lib/heap/av_psram_heap.h" #include "gen420_hardware_msi.h" #include "lib/video/vpp/vpp_dev.h" #include "lib/multimedia/msi.h" //workqueue #include "user_work/user_work.h" struct timeLapse_work_t { struct os_work wk; uint32_t timer; uint32_t last_kick_time; }; static struct timeLapse_work_t *timeLapse_wk; #define H264_MALLOC av_psram_malloc #define H264_FREE av_psram_free #define H264_ZALLOC av_psram_zalloc #define H264_LIB_MALLOC av_malloc #define H264_LIB_FREE av_free #define H264_LIB_ZALLOC av_zalloc #ifndef H264_HARDWARE_CLK #define H264_HARDWARE_CLK H264_MODULE_CLK_480M #endif #ifndef H264_I_ONLY #define H264_I_ONLY 0 #endif void h264_sema_up(); volatile uint32_t h264_dev_num = 1; volatile struct h264_cfg_t enc_cfg; volatile struct h264_ctl_t enc_ctl; volatile struct h264_rc_ctl_t rc_ctl; volatile struct h264_cfg_t enc_2_cfg; volatile struct h264_ctl_t enc_2_ctl; volatile struct h264_rc_ctl_t rc_2_ctl; volatile struct h264_cfg_t *penc_cfg; volatile struct h264_ctl_t *penc_ctl; volatile struct h264_rc_ctl_t *prc_ctl; uint8_t *h264_ref_lu_base_psram = NULL; uint8_t *h264_ref_ch_base_psram = NULL; uint8_t *h264_ref_lu_base_psram2 = NULL; uint8_t *h264_ref_ch_base_psram2 = NULL; uint8_t *h264_room_psram = NULL; uint8_t *h264_ref_memory_base[10]; __psram_data uint8_t h264_room[H264_NODE_NUM*H264_NODE_LEN] __aligned(1024); volatile h264_frame h264_frame_point[H264_FRAME_NUM]; volatile struct list_head *h264_module_p; //264模块的节点指针 volatile struct list_head *h264_app_p; //应用的节点指针 volatile struct list_head* h264_f_p; //当前264所使用的frame volatile h264_node h264_node_src[H264_NODE_NUM]; volatile struct list_head h264_free_tab; //空闲列表,存放空间节点 volatile uint8 h264_error = 0; volatile uint8 frame_done = 0; static struct os_semaphore h264_sem = {0,NULL}; volatile struct list_head h264_queue_head; static struct os_semaphore h264wq_sem = {0,NULL}; void h264wq_sema_init() { os_sema_init(&h264wq_sem,0); } void h264wq_sema_down(int32 tmo_ms) { os_sema_down(&h264wq_sem,tmo_ms); } void h264wq_sema_up() { os_sema_up(&h264wq_sem); } /**@brief * 将传入的frame根节点下的buf池都送回空间池(free_tab)中 */ static bool free_get_node_list(volatile struct list_head *head,volatile struct list_head *free){ bool ret = 1; uint32_t flags = disable_irq(); if(list_empty((struct list_head *)head)){ ret = 0; goto free_get_node_list_end; } list_splice_init((struct list_head *)head,(struct list_head *)free); free_get_node_list_end: enable_irq(flags); return ret; } /**@brief * 从初始化的frame根节点中抽取其中一个空闲的根节点进行使用,并标记frame的使用状态为正在使用 * @param 是否开启抢占模式,如果开启,则将上一帧已完成的帧节点删掉,并返回 */ volatile struct list_head* get_h264_new_frame_head(int grab,uint8_t devid,uint8_t is_iframe){ uint8 frame_num = 0; for(frame_num = 0;frame_num < H264_FRAME_NUM;frame_num++){ if(h264_frame_point[frame_num].usable == 0){ h264_frame_point[frame_num].usable = 1; if(is_iframe){ h264_frame_point[frame_num].h264_type = 1; }else{ h264_frame_point[frame_num].h264_type = 2; } h264_frame_point[frame_num].h264_dev_id = devid; return &h264_frame_point[frame_num].list; } } if(grab) //是否开启抢占模式,开启抢占后,肯定有frame返回,上一帧没使用的frame肯定usable为2 { for(frame_num = 0;frame_num < H264_FRAME_NUM;frame_num++){ if(h264_frame_point[frame_num].usable == 2){ h264_frame_point[frame_num].usable = 1; if(is_iframe){ h264_frame_point[frame_num].h264_type = 1; }else{ h264_frame_point[frame_num].h264_type = 2; } h264_frame_point[frame_num].h264_dev_id = devid; free_get_node_list(&h264_frame_point[frame_num].list,&h264_free_tab); return &h264_frame_point[frame_num].list; } } } return 0; } /**@brief * 初始化free_tab池,将mjpeg_node的节点都放到空闲池中,供frame后面提取使用 * @param ftb 空闲池头指针 * @param jpn mjpeg_node节点源 * @param use_num mjpeg_node的数量,即多少个mjpeg_node放到空闲池 * @param addr mjpeg_node的总buf起始地址 * @param buf_len 每个mjpeg_node所关联到的数据量 */ void h264_free_table_init(volatile struct list_head *ftb, volatile h264_node* h264n,int use_num,uint32 addr,uint32 buf_len){ int itk; for(itk = 0;itk < use_num;itk++){ h264n->buf_addr = (uint8*)(addr + itk*buf_len); list_add_tail((struct list_head *)&h264n->list,(struct list_head *)ftb); h264n++; } } static void set_frame_ready(h264_frame *hf){ hf->timestamp = os_jiffies(); hf->usable = 2; } /**@brief * 从空间池中提取一个节点,放到队列中,并将此节点作为返回值返回 */ static struct list_head *get_node(volatile struct list_head *head,volatile struct list_head *del){ struct list_head *ret = NULL; uint32_t flags = disable_irq(); if(list_empty((struct list_head *)del)){ goto get_node_end; } list_move((struct list_head *)del->next,(struct list_head *)head); ret = head->next; get_node_end: enable_irq(flags); return ret; //返回最新的位置 } /**@brief * 从当前使用的节点回放到消息池中 */ static bool put_node(volatile struct list_head *head,volatile struct list_head *del){ bool ret = 1; uint32_t flags = disable_irq(); if(list_empty((struct list_head *)del)){ ret = 0; goto put_node_end; } list_move(del->next,(struct list_head *)head); put_node_end: enable_irq(flags); return ret; } /**@brief * 获取当前jpeg节点buf地址进行返回 */ static uint32 get_addr(volatile struct list_head *list){ h264_node* h264n; h264n = list_entry((struct list_head *)list,h264_node,list); return (uint32)h264n->buf_addr; } /**@brief * 将传入的frame根节点状态调整为空闲,以供下次重新获取 */ void del_264_frame(volatile struct list_head* frame_list) { h264_frame* fl; uint32_t flags; flags = disable_irq(); if(list_empty((struct list_head *)frame_list) != TRUE){ free_get_node_list(frame_list,&h264_free_tab); fl = list_entry((struct list_head *)frame_list,h264_frame,list); fl->usable = 0; goto del_264_frame_end; }else{ fl = list_entry((struct list_head *)frame_list,h264_frame,list); fl->usable = 0; goto del_264_frame_end; } del_264_frame_end: enable_irq(flags); } uint32 get_h264_node_len_new(void *get_f) { return H264_NODE_LEN; } void del_h264_frame(void *d) { h264_frame* get_f = (h264_frame*)d; del_264_frame((struct list_head*)get_f); } struct list_head* get_h264_frame() { uint8 frame_num = 0; for(frame_num = 0;frame_num < H264_FRAME_NUM;frame_num++){ if(h264_frame_point[frame_num].usable == 2){ h264_frame_point[frame_num].usable = 1; return (struct list_head *)&h264_frame_point[frame_num].list; } } return NULL; } uint32 get_h264_timestamp(void *d) { struct list_head* get_f = (struct list_head*)d; h264_frame* hf; hf = list_entry(get_f,h264_frame,list); return hf->timestamp; } uint32 get_h264_which(void *d) { struct list_head* get_f = (struct list_head*)d; h264_frame* hf; hf = list_entry(get_f,h264_frame,list); return hf->which; } uint32 get_h264_srcID(void *d) { struct list_head* get_f = (struct list_head*)d; h264_frame* hf; hf = list_entry(get_f,h264_frame,list); return hf->srcID; } uint32 get_h264_len(void *d) { uint32 flen; struct list_head* get_f = (struct list_head*)d; h264_frame* hf; hf = list_entry(get_f,h264_frame,list); flen = hf->frame_len; return flen; } uint8 get_h264_type(void *d) { uint8 type; struct list_head* get_f = (struct list_head*)d; h264_frame* hf; hf = list_entry(get_f,h264_frame,list); type = hf->h264_type; return type; } uint8 get_h264_loop_num(void *d) { uint8 num; struct list_head* get_f = (struct list_head*)d; h264_frame* hf; hf = list_entry(get_f,h264_frame,list); num = hf->h264_num; return num; } void *get_h264_first_buf(void *d) { struct list_head* get_f = (struct list_head*)d; h264_node* hn; hn = list_entry(get_f->next,h264_node,list); if(hn) { return hn->buf_addr; } return NULL; } int del_h264_first_node(void *d) { h264_frame* get_f = (h264_frame*)d; uint8_t *h264_buf = get_h264_first_buf(get_f); uint32_t h264_buf_node_len = get_h264_node_len_new((void *)get_f); sys_dcache_invalid_range((uint32_t *)h264_buf, h264_buf_node_len); put_node(&h264_free_tab,(struct list_head*)get_f); return 0; } void *get_h264_node_buf(void *d) { struct list_head* get_f = (struct list_head*)d; h264_node* hn; hn = list_entry(get_f,h264_node,list); if(hn) { return hn->buf_addr; } return NULL; } //删除节点,是实际节点 void del_h264_node(void *d) { uint32_t flags; struct list_head* get_f = (struct list_head *)d; flags = disable_irq(); list_add_tail(get_f,(struct list_head*)&h264_free_tab); enable_irq(flags); } uint32 get_h264_w_h(void *d,uint16_t *w,uint16_t *h) { h264_frame* get_f = (h264_frame*)d; if(w) { *w = get_f->w; } if(h) { *h = get_f->h; } return 0; } void h264_room_init(){ uint8_t i; for(i = 0;i < H264_FRAME_NUM;i++){ INIT_LIST_HEAD((struct list_head *)&h264_frame_point[i].list); } INIT_LIST_HEAD((struct list_head *)&h264_free_tab); uint32_t h264_rom_addr = ((uint32_t)h264_room_psram + 0x3ff)&(~0x3ff); h264_free_table_init(&h264_free_tab,(h264_node*)&h264_node_src,H264_NODE_NUM,(uint32)h264_rom_addr,H264_NODE_LEN); for(i = 0;i < H264_FRAME_NUM;i++){ h264_frame_point[i].usable = 0; h264_frame_point[i].h264_num = 0; h264_frame_point[i].h264_dev_id = 0; } } void h264_3dnr_ini(struct h264_device *p_h264,struct h264_cfg_t *enc_cfg) { uint8_t h264_noise_level = enc_cfg->flt_noise_lev; uint16_t i; uint32_t wdata ; uint8_t d0, d1, d2, d3; uint32_t NoiseLevel = 8 ; // range:0 ~ 15 uint32_t BackGroundNoiseLevel = 8 ; // range:0 ~ 15 uint32_t LightFlowLevel = 8 ; // range:0 ~ 15 uint32_t MV_Threshold = 3 ; // 0~15, 3 bits, 0: disable mv_threshold_check, user modify uint32_t MV_Trust_Cut = 3840 ; // if max_mcoststilltomove == 0){ if(enc_cfg->enc_bps != recfg_h264_mbps[dev_num-1]){ enc_cfg->enc_bps = recfg_h264_mbps[dev_num-1]; result = 1; } }else{ if(enc_cfg->move_enc_bps != recfg_h264_mbps[dev_num-1]){ enc_cfg->move_enc_bps = recfg_h264_mbps[dev_num-1]; result = 1; } if(enc_cfg->still_enc_bps != recfg_h264_sbps[dev_num-1]){ enc_cfg->still_enc_bps = recfg_h264_sbps[dev_num-1]; result = 1; } } if(enc_cfg->frm_rate != recfg_h264_rate[dev_num-1]){ enc_cfg->frm_rate = recfg_h264_rate[dev_num-1]; result = 1; } if(enc_cfg->frm_gop != recfg_h264_gop[dev_num-1]){ enc_cfg->frm_gop = recfg_h264_gop[dev_num-1]; result = 1; } if(enc_cfg->ini_qp != recfg_h264_ini_qp[dev_num-1]){ enc_cfg->ini_qp = recfg_h264_ini_qp[dev_num-1]; result = 1; } return result; } void h264_ini_recfg(struct h264_cfg_t *enc_cfg, struct h264_ctl_t *enc_ctl, struct h264_rc_ctl_t *rc_ctl){ enc_ctl->frm_qp = enc_cfg->ini_qp; enc_ctl->target_gop = ( ((uint32_t)enc_cfg->enc_bps * 1000 * (uint32_t)enc_cfg->frm_gop) / enc_cfg->frm_rate ) >> 3; //byte target rc_ctl->i_qp = enc_cfg->ini_qp; rc_ctl->p_qp = enc_cfg->ini_qp; //--- cal I frame target byte rc_ctl->i_byte = (enc_ctl->target_gop * enc_cfg->frm_ip_rate) / (enc_cfg->frm_gop - 1 + enc_cfg->frm_ip_rate); rc_ctl->i_frm_max = (enc_ctl->target_gop * enc_cfg->frm_ip_rate_max) / (enc_cfg->frm_gop - 1 + enc_cfg->frm_ip_rate_max); rc_ctl->i_frm_min = (enc_ctl->target_gop * enc_cfg->frm_ip_rate_min) / (enc_cfg->frm_gop - 1 + enc_cfg->frm_ip_rate_min); } void h264_ini_seting_cfg(struct h264_device *p_h264,struct h264_cfg_t *enc_cfg, struct h264_ctl_t *enc_ctl, struct h264_rc_ctl_t *rc_ctl,uint8_t dev_num) { h264_reflash_new_gop(dev_num,0); h264_recfg_bsp(dev_num,enc_cfg->move_enc_bps,enc_cfg->move_enc_bps); h264_recfg_rate(dev_num,enc_cfg->frm_rate); h264_recfg_frm_gop(dev_num,enc_cfg->frm_gop); h264_recfg_ini_qp(dev_num,enc_cfg->ini_qp); enc_ctl->enc_mode = enc_cfg->enc_mode; enc_ctl->frm_qp = enc_cfg->ini_qp; enc_ctl->frm_width = ((enc_cfg->frm_width + 15) >> 4) << 4; //16 pixel align enc_ctl->frm_height= ((enc_cfg->frm_height + 15) >> 4) << 4; //16 pixel align enc_ctl->frm_luma_size = enc_ctl->frm_width * enc_ctl->frm_height; enc_ctl->frm_mblines= enc_ctl->frm_height >> 4; enc_ctl->timeout_limit = (enc_ctl->frm_luma_size << 10) >> 17;//18 enc_ctl->bs_byte_limit = H264_BS_SIZE-4; enc_ctl->frm_cnt = 0; enc_ctl->gop_frm_cnt= 0; enc_ctl->idrid = 0; enc_ctl->target_gop = ( ((uint32_t)enc_cfg->enc_bps * 1000 * (uint32_t)enc_cfg->frm_gop) / enc_cfg->frm_rate ) >> 3; //byte target //_os_printf("frm_luma_size:%d frm_width:%d\r\n",enc_ctl->frm_luma_size,enc_ctl->frm_width); if(dev_num == 1){ //申请空间多申请了4K,主要是为了对齐使用 enc_ctl->ref_lu_base= ((uint32_t)h264_ref_lu_base_psram + 0xfff) & (~0xfff); //must be 4KB aligned enc_ctl->ref_lu_end = ((enc_ctl->ref_lu_base + enc_ctl->frm_luma_size + (48*enc_ctl->frm_width) + 4095) >> 12) << 12; //4KB align enc_ctl->ref_ch_base= ((uint32_t)h264_ref_ch_base_psram + 0xfff)& (~0xfff);//enc_ctl->ref_lu_end; enc_ctl->ref_ch_end = ((enc_ctl->ref_ch_base + (enc_ctl->frm_luma_size >>1) + (24*enc_ctl->frm_width) + 4095) >> 12) << 12; //4KB align }else if(dev_num == 2){ enc_ctl->ref_lu_base= ((uint32_t)h264_ref_lu_base_psram2 + 0xfff) & (~0xfff); //must be 4KB aligned enc_ctl->ref_lu_end = ((enc_ctl->ref_lu_base + enc_ctl->frm_luma_size + (48*enc_ctl->frm_width) + 4095) >> 12) << 12; //4KB align enc_ctl->ref_ch_base= ((uint32_t)h264_ref_ch_base_psram2 + 0xfff)& (~0xfff);//enc_ctl->ref_lu_end; enc_ctl->ref_ch_end = ((enc_ctl->ref_ch_base + (enc_ctl->frm_luma_size >>1) + (24*enc_ctl->frm_width) + 4095) >> 12) << 12; //4KB align } enc_ctl->last_lpf_lu_base = enc_ctl->ref_lu_base; enc_ctl->last_lpf_ch_base = enc_ctl->ref_ch_base; // enc_ctl->bs_base0 = (uint32_t)h264_dat_buf[0];//h264_dat_buf + (1<<20) - 1024; // enc_ctl->bs_base1 = (uint32_t)h264_dat_buf[1];//enc_ctl->bs_base0 + 16*1024; enc_ctl->enc_first_frm=1; rc_ctl->frm_rdcost= (enc_ctl->frm_luma_size >> 8) * (256*48 >> 4);//not critial initial value rc_ctl->i_qp = enc_cfg->ini_qp; rc_ctl->p_qp = enc_cfg->ini_qp; //--- cal I frame target byte rc_ctl->i_byte = (enc_ctl->target_gop * enc_cfg->frm_ip_rate) / (enc_cfg->frm_gop - 1 + enc_cfg->frm_ip_rate); rc_ctl->i_frm_max = (enc_ctl->target_gop * enc_cfg->frm_ip_rate_max) / (enc_cfg->frm_gop - 1 + enc_cfg->frm_ip_rate_max); rc_ctl->i_frm_min = (enc_ctl->target_gop * enc_cfg->frm_ip_rate_min) / (enc_cfg->frm_gop - 1 + enc_cfg->frm_ip_rate_min); } void h264_enc_eof_update(struct h264_cfg_t *enc_cfg, struct h264_ctl_t *enc_ctl, struct h264_rc_ctl_t *rc_ctl) { uint8 rc_p_qp; uint8 i_qp; uint32 frm_target_step; uint32 i_byte; enc_ctl->frm_cnt ++; enc_ctl->gop_frm_cnt ++; enc_ctl->enc_first_frm = 0; if(enc_ctl->gop_frm_cnt == enc_cfg->frm_gop) { enc_ctl->gop_frm_cnt = 0; enc_ctl->idrid = (enc_ctl->idrid + 1) & 0x07; if(enc_cfg->rc_en) { //--- I frame target byte update rc_p_qp= (rc_ctl->p_qp_acc + (rc_ctl->p_acc_num >> 1)) / rc_ctl->p_acc_num; frm_target_step = (rc_ctl->i_byte >> 4) + (rc_ctl->i_byte >> 5); //about 10% i_qp = rc_ctl->i_qp; i_byte= rc_ctl->i_byte; if(i_qp > rc_p_qp) { //need add more byte to I frame if(i_qp >= (rc_p_qp + 3)) i_byte += 2*frm_target_step; else if(i_qp > (rc_p_qp + 1)) i_byte += frm_target_step; } else if(i_qp < rc_p_qp) { //need add more byte to P frame if(i_qp <= (rc_p_qp - 3)) i_byte -= 2*frm_target_step; else if(i_qp < (rc_p_qp - 1)) i_byte -= frm_target_step; } //clip if(i_byte > rc_ctl->i_frm_max) i_byte = rc_ctl->i_frm_max; else if(i_byte < rc_ctl->i_frm_min) i_byte = rc_ctl->i_frm_min; rc_ctl->i_byte = i_byte; } } } void h264_rc_tune_eof(struct h264_device*p_h264,struct h264_cfg_t *enc_cfg, struct h264_ctl_t *enc_ctl, struct h264_rc_ctl_t *rc_ctl) { uint32 rdata; uint32 bs_len = enc_ctl->enc_bs_byte; uint32 frm_target = enc_ctl->frm_target; uint32 frm_target_step = (enc_ctl->frm_target >> 4) + (enc_ctl->frm_target >> 5); //about 10% rc_ctl->gop_remain_byte -= enc_ctl->enc_bs_byte; if(rc_ctl->gop_remain_byte <=0) rc_ctl->gop_remain_byte = 1; //--- just accumulate the average QP for last 4 P frame within a GOP if((rc_ctl->gop_remain_frame <= 3) && (enc_ctl->frm_type == 0)) { rc_ctl->p_qp_acc += enc_ctl->hw_cal_qp; rc_ctl->p_acc_num++; } //--- next frame QP modify for I/P frames if(enc_ctl->frm_type == 2) { rc_ctl->i_qp = enc_ctl->hw_cal_qp; //must within [16, 50] range, no need clip } else { uint8 hw_cal_qp = enc_ctl->hw_cal_qp; if(enc_cfg->cc_corect) { //high effort if(bs_len > (frm_target + 1*frm_target_step)) { //real > target if(bs_len > (frm_target + 4*frm_target_step)) //>= 1.4*target hw_cal_qp += 3; else if(bs_len > (frm_target + 3*frm_target_step)) //>= 1.3*target hw_cal_qp += 3; else if(bs_len > (frm_target + 2*frm_target_step)) //>= 1.2*target hw_cal_qp += 2; else if(bs_len >= (frm_target + 1*frm_target_step)) //>= 1.1*target hw_cal_qp += 1; } else if(bs_len < (frm_target - 1*frm_target_step)) {//real < target if(bs_len <= (frm_target - 5*frm_target_step)) //<= 0.5*target hw_cal_qp -= 4; else if(bs_len <= (frm_target - 3*frm_target_step)) //<= 0.7*target hw_cal_qp -= 2; else if(bs_len < (frm_target - 1*frm_target_step)) //<= 0.9*target hw_cal_qp -= 1; } } else { //low or relax mode //start QP change between each P frame is [-2, 3] if((hw_cal_qp >= (rc_ctl->p_qp + 3))) { hw_cal_qp = rc_ctl->p_qp + 3; } else if((hw_cal_qp <= (rc_ctl->p_qp - 3))) { hw_cal_qp = rc_ctl->p_qp - 2; } } //clip to [16, 50] if(hw_cal_qp > 50) hw_cal_qp = 50; else if(hw_cal_qp < 16) hw_cal_qp = 16; rc_ctl->p_qp = hw_cal_qp; } if(enc_cfg->rc_effort == 2) { rdata = h264_get_enc_frame_rdcost(p_h264); rc_ctl->frm_rdcost = (rdata * enc_cfg->rc_grp + (enc_ctl->frm_mblines >> 1)) / ((uint32)enc_ctl->frm_mblines); } } void h264_read_bs(struct str_info *str) { uint8_t bs ; uint8_t sf_bit ; //make sure this is str->bit_len >=25 while(str->bit_len <= 24) { bs = *(str->ptr); str->ptr += 1; sf_bit = 24 - str->bit_len; str->stream = str->stream | (((uint32_t) bs) << sf_bit); str->bit_len+= 8; } } void h264_byte_align(struct str_info *str) { uint8_t sf_bit ; sf_bit = str->bit_len & 0x07; if(sf_bit != 0) { str->stream = str->stream << sf_bit; str->bit_len -= sf_bit; str->used_bits += sf_bit; h264_read_bs(str); } } uint32_t dec_fix(struct str_info *str, uint8_t bit_num) { uint32_t val ; uint8_t sf_bit ; if(bit_num > 25) { //print("dec_fix error, bit_num is too big.\n\r"); } sf_bit= 32 - bit_num; val = str->stream >> sf_bit; str->stream = str->stream << bit_num; str->bit_len -= bit_num; str->used_bits += bit_num; h264_read_bs(str); return(val); } int32_t dec_glb(struct str_info *str, uint8_t mode) { uint8_t leading_0 = 0; uint16_t tmp_val = 0; uint16_t tail_val ; int32_t syn ; //-- find leading zero while (((str->stream >> 31) & 0x01) == 0x0) { str->stream = str->stream << 1; str->bit_len -= 1; str->used_bits += 1; leading_0++; } //--- shift 1 str->stream = str->stream << 1; str->bit_len -= 1; str->used_bits += 1; h264_read_bs(str); //--- get tail if(leading_0 == 0) tail_val = 0; else tail_val = (uint16_t) (str->stream >> (32 - leading_0)); str->stream = str->stream << leading_0; str->bit_len -= leading_0; str->used_bits += leading_0; tmp_val = (1 << leading_0) - 1 + tail_val; h264_read_bs(str); if(mode == 0) syn = tmp_val; else { if(tmp_val == 0) syn = 0; else if(tmp_val & 0x01) syn = (tmp_val + 1) >> 1; else syn = 0 - (tmp_val >> 1); } return(syn); } void dec_pic(struct str_info *str, struct h264_header *head) { uint32_t syn_unsign; int32_t syn_sign; uint8_t slice_type; uint8_t ref_pic_list_modification_flag_l0; uint8_t modify_of_pic_muns_idc; int16_t qp_delta; syn_sign = dec_glb(str, 0); //first_mb_in_slice syn_sign = dec_glb(str, 0); //slice_type //slice_type = syn_sign; slice_type = syn_sign % 5; head->pic_slice_type = slice_type; syn_sign = dec_glb(str, 0); //pps_id syn_unsign = dec_fix(str, (head->sps_log2_max_fnum_minus4 + 4)); //frame_num if(head->idr_flag) { syn_sign = dec_glb(str, 0); //idr_pic_id } syn_unsign = dec_fix(str, (head->sps_log2_max_poc_lsb_minus4 + 4)); //pic_order_cnt_lsb if(slice_type == 0) { syn_unsign = dec_fix(str, 1); //num_ref_idx_active_override_flag } if(slice_type == 0) { syn_unsign = dec_fix(str, 1); //ref_pic_list_modification_flag_l0 ref_pic_list_modification_flag_l0 = syn_unsign; } else { ref_pic_list_modification_flag_l0 = 0; } if(ref_pic_list_modification_flag_l0) { modify_of_pic_muns_idc = 0; while(modify_of_pic_muns_idc != 3) { syn_sign = dec_glb(str, 0); //modify_of_pic_nums_idc modify_of_pic_muns_idc = syn_sign; if(modify_of_pic_muns_idc == 0 || modify_of_pic_muns_idc == 1) { syn_sign = dec_glb(str, 0); //abs_diff_pic_num_minus1 } } } if(head->idr_flag) { syn_unsign = dec_fix(str, 1); //no_output_of_prior_pics_flag syn_unsign = dec_fix(str, 1); //long_term_reference_flag } else { syn_unsign = dec_fix(str, 1); //adaptive_ref_pic_marking_mode_flag } if((head->pps_cavlc_mode == 0) && (head->idr_flag == 0)) { syn_unsign = dec_glb(str, 0); //cabac_init_idc } syn_sign = dec_glb(str, 1); //slice_qp_delta qp_delta = syn_sign; head->pic_qp= (uint8_t) ((int8_t)head->pps_qp_ini + qp_delta); if(head->pps_cavlc_mode == 0) { //cabac mode, align to 8bit str->used_bits = ((str->used_bits + 7) >> 3) << 3; } } void dec_sps(struct str_info *str, struct h264_header *head) { uint32_t syn_unsign; int32_t syn_sign; syn_unsign = dec_fix(str, 8); //profile_idc syn_unsign = dec_fix(str, 8); // syn_unsign = dec_fix(str, 8); //level_idc syn_sign = dec_glb(str, 0); //sps_id syn_sign = dec_glb(str, 0); //log2_max_frame_num_minus4 head->sps_log2_max_fnum_minus4 = syn_sign; syn_sign = dec_glb(str, 0); //pic_order_cnt_type syn_sign = dec_glb(str, 0); //log2_max_pic_order_cnt_lsb_minus4 head->sps_log2_max_poc_lsb_minus4 = syn_sign; syn_sign = dec_glb(str, 0); //max_mun_ref_frames syn_unsign = dec_fix(str, 1); //gaps_in_frame_num_value_allowed_flag syn_sign = dec_glb(str, 0); //pic_width_in_mbs_minus1 head->sps_pic_width = (syn_sign + 1) * 16; syn_sign = dec_glb(str, 0); //pic_height_in_map_units_minus1 head->sps_pic_height= (syn_sign + 1) * 16; h264_byte_align(str); } void dec_pps(struct str_info *str, struct h264_header *head) { uint32_t syn_unsign; int32_t syn_sign; syn_sign = dec_glb(str, 0); //pps_id syn_sign = dec_glb(str, 0); //sps_id syn_unsign = dec_fix(str, 1); //entropy_coding_mode_flag head->pps_cavlc_mode = (syn_unsign == 0)? 1 : 0; syn_unsign = dec_fix(str, 1); //bottom_filed_pic_order_in_frame... syn_sign = dec_glb(str, 0); //num_slice_groups_minus1 syn_sign = dec_glb(str, 0); //num_ref_idx_l0_default_active_minus1 syn_sign = dec_glb(str, 0); //num_ref_idx_l1_default_active_minus1 syn_unsign = dec_fix(str, 1); //weighted_pred_flag syn_unsign = dec_fix(str, 2); //weighted_bipred_idc syn_sign = dec_glb(str, 1); //pic_init_qp_minus26 head->pps_qp_ini = syn_sign + 26; syn_sign = dec_glb(str, 1); //pic_init_qs_minus26 syn_sign = dec_glb(str, 1); //chroma_qp_index_offset head->pps_chrom_qp_offset = syn_sign; h264_byte_align(str); } uint8_t nal_parse(struct str_info *str, struct h264_header *head) { uint32_t syn_unsign; uint8_t nal_type; //initial read in 4 byte str->used_bits = 0; str->bit_len = 0; str->stream =0; h264_read_bs(str); //--- find the 0x00000001 nal start code while( str->stream != 0x00000001) { str->stream = str->stream << 8; str->bit_len -= 8; str->used_bits += 8; h264_read_bs(str); } //discard 0x00000001 start code str->bit_len = 0; str->used_bits += 32; str->stream = 0; h264_read_bs(str); syn_unsign = dec_fix(str, 3); syn_unsign = dec_fix(str, 5); nal_type = syn_unsign; h264_read_bs(str); if(nal_type == pic_idr) { head->idr_flag = 1; dec_pic(str, head); } else if(nal_type == pic_data) { head->idr_flag = 0; dec_pic(str, head); } else if(nal_type == sps) { dec_sps(str, head); } else if(nal_type == pps) { dec_pps(str, head); } else { _os_printf("Unsupported NAL Unit type.\n\r"); } return(nal_type); } void h264_dec_flag_chk(uint32_t flags) { if((flags & 0x10) != 0) { //check dec_err_flag _os_printf("decoder syntax error.\n\r"); } if((flags & 0x100) != 0) {//check bitstream read length error flag _os_printf("decoder stream length error.\n\r"); } } //return ptr point to byte location after 0x00000001 uint8_t* find_start_code(uint8_t* ptr) { struct str_info str ; str.ptr= ptr; str.bit_len=0; str.used_bits=0; str.stream=0; //initial with 32bit h264_read_bs(&str); //--- find the 0x00000001 nal start code while(str.stream != 0x00000001) { str.stream = str.stream << 8; str.bit_len -= 8; str.used_bits += 8; h264_read_bs(&str); //debug only //if((uint32_t)str.ptr >= (H264_FILE_BS_BASE + bs_size)) { // print("Start code not find.\n\r"); //} } return(str.ptr); } void h264_enc_flag_chk(uint32 flags) { } void h264_clr_intr(struct h264_device *p_h264) { h264_set_sta(p_h264,0); } void h264_cfg_srcdat(struct h264_device *p_h264,uint8_t mode){ h264_set_src_from(p_h264,mode); } void h264_get_intr_status(struct h264_device *p_h264,struct h264_cfg_t *enc_cfg, struct h264_ctl_t *enc_ctl, struct h264_rc_ctl_t *rc_ctl) { uint32 rdata ; rdata = h264_get_sta(p_h264); enc_ctl->enc_end_flags= rdata; if(enc_cfg->rc_en) { //rate control info rdata = h264_get_rate_ctl(p_h264); rdata = rdata >> 16; enc_ctl->hw_cal_qp = (rdata + (enc_ctl->frm_mblines >> 1)) / (enc_ctl->frm_mblines); } } uint32 h264_cal_ref_base(uint32 buf_base, uint32 buf_end, uint32 last_base, uint32 last_offset) { uint32 addr ; addr = ((last_base + last_offset + 4095) >> 12) << 12; //4KB align //ring-buffer if(addr >= buf_end) { addr = addr - buf_end; addr = buf_base + addr; } return(addr); } //--- cal RC MB Line target byte for IPPPPPPP.... GOP mode //--- target bitrate is traced through a GOP uint32 h264_rc_cal(struct h264_cfg_t *enc_cfg, struct h264_ctl_t *enc_ctl, struct h264_rc_ctl_t *rc_ctl) { uint32 grp_byte ; //target byte number of a RC MB line group uint32 frm_byte ; //target byte number of a frame if(enc_ctl->frm_type == 2) { //I frame, first Intra frame in a GOP rc_ctl->gop_remain_frame = enc_cfg->frm_gop; rc_ctl->p_qp_acc = 0; rc_ctl->p_acc_num = 0; rc_ctl->p_avg = (rc_ctl->gop_remain_byte - rc_ctl->i_byte) / (enc_cfg->frm_gop - 1); rc_ctl->p_frm_max = rc_ctl->p_avg + (rc_ctl->p_avg >>3); //+0.125 times variation within a GOP rc_ctl->p_frm_min = rc_ctl->p_avg - (rc_ctl->p_avg >>3); //-0.125 times variation within a GOP frm_byte = rc_ctl->i_byte; } else { //other P frame in a GOP frm_byte = rc_ctl->gop_remain_byte / rc_ctl->gop_remain_frame; if(frm_byte > rc_ctl->p_frm_max) frm_byte = rc_ctl->p_frm_max; else if(frm_byte < rc_ctl->p_frm_min) frm_byte = rc_ctl->p_frm_min; } if(enc_cfg->rc_effort != 2) //low/high-effort frm_byte += (frm_byte >> 4); //add 6% more to compensate the HW inaccurate enc_ctl->frm_target = frm_byte; grp_byte = (frm_byte*enc_cfg->rc_grp + (enc_ctl->frm_mblines >> 1)) / enc_ctl->frm_mblines; rc_ctl->gop_remain_frame --; return (grp_byte); } extern volatile uint32_t vpp_md_cnt; void h264_start_enc_frm(struct h264_device *p_h264,struct h264_cfg_t *penc_cfg, struct h264_ctl_t *enc_ctl, struct h264_rc_ctl_t *rc_ctl) { uint32 rc_grp_byte ; //uint32 frm_target_step ; uint32 lpf_lu_base ; uint32 lpf_ch_base ; uint32 wdata ; uint32 rdata ; uint32 con ; // static uint8_t frm_num = 2; h264_frame* hf; uint32 addr; h264_error = 0; if(enc_ctl->gop_frm_cnt == 0) { if(penc_cfg->auto_ctl_3dnr == 1){ if(penc_cfg->md_3dnr_timer == 0){ if(penc_cfg->last_vpp_md != vpp_md_cnt){ if(penc_cfg->md_set_3dnr == 0){ penc_cfg->md_3dnr_en = penc_cfg->flt3d_en; penc_cfg->md_set_3dnr = 1; } penc_cfg->flt3d_en = 0; //发现有在动,3d降噪先关闭 penc_cfg->md_3dnr_timer = 3; }else{ penc_cfg->md_set_3dnr = 0; penc_cfg->flt3d_en = penc_cfg->md_3dnr_en; } penc_cfg->last_vpp_md = vpp_md_cnt; }else{ penc_cfg->md_3dnr_timer--; } } if(penc_cfg->flt3d_en){ if(penc_cfg->run_gop_3dnr == 0){ enc_ctl->enc_first_frm = 1; penc_cfg->run_gop_3dnr = penc_cfg->gop_rst_3dnr; } else penc_cfg->run_gop_3dnr--; } if(penc_cfg->stilltomove != 0){ if(penc_cfg->move_remain_gop){ penc_cfg->move_remain_gop--; penc_cfg->enc_bps = penc_cfg->move_enc_bps; }else{ penc_cfg->enc_bps = penc_cfg->still_enc_bps; } enc_ctl->target_gop = ( ((uint32_t)penc_cfg->enc_bps * 1000 * (uint32_t)penc_cfg->frm_gop) / penc_cfg->frm_rate ) >> 3; } enc_ctl->frm_type = 2; rc_ctl->gop_remain_byte = enc_ctl->target_gop; enc_ctl->frm_qp = rc_ctl->i_qp; } else { enc_ctl->frm_type = 0; enc_ctl->frm_qp = rc_ctl->p_qp; } // --- ISP denoise turning --- if(penc_cfg->md_3dnr_timer == 0 && penc_cfg->last_vpp_md == vpp_md_cnt){ if ((penc_cfg->flt_noise_lev != penc_cfg->flt_noise_lev_last) || (penc_cfg->flt3d_en != penc_cfg->flt3d_en_last)) { h264_3dnr_ini(p_h264, penc_cfg); enc_ctl->enc_first_frm = 1; penc_cfg->flt_noise_lev_last = penc_cfg->flt_noise_lev; penc_cfg->flt3d_en = penc_cfg->flt3d_en_last; //_os_printf("h264 nr: %d %d\r\n", penc_cfg->flt3d_en, penc_cfg->flt_noise_lev); } } //--- write cfg regs wdata = enc_ctl->frm_type | (1 << 3) | (enc_ctl->enc_mode << 4) | (penc_cfg->enc_bs_buf_size << 16); con = wdata; h264_set_frame_base_cfg(p_h264,enc_ctl->frm_type,enc_ctl->enc_mode,penc_cfg->enc_bs_buf_size,1); h264_set_phy_img_size(p_h264,enc_ctl->frm_width,enc_ctl->frm_height); if(penc_cfg->rc_en){ h264_set_frame_qp(p_h264,enc_ctl->frm_qp); } else{ h264_set_frame_qp(p_h264,penc_cfg->ini_qp); } //--- cfg reg not change(if frame x/y size change, may need change) h264_set_timeout_limit(p_h264,enc_ctl->timeout_limit); h264_set_len_limit(p_h264,enc_ctl->bs_byte_limit); #if H264_I_ONLY h264_set_ref_lu_addr(p_h264,0X40000000,0X40000000); h264_set_ref_chro_addr(p_h264,0X40000000,0X40000000); //h264_set_ref_lu_addr(p_h264,enc_ctl->ref_lu_base,enc_ctl->ref_lu_base+(IMAGE_W_H264*(IMAGE_H_H264+48))/2); //h264_set_ref_chro_addr(p_h264,enc_ctl->ref_lu_base,enc_ctl->ref_lu_base+(IMAGE_W_H264*(IMAGE_H_H264+48))/2); #else h264_set_ref_lu_addr(p_h264,enc_ctl->ref_lu_base,enc_ctl->ref_lu_end); h264_set_ref_chro_addr(p_h264,enc_ctl->ref_ch_base,enc_ctl->ref_ch_end); #endif h264_set_frame_num(p_h264,enc_ctl->gop_frm_cnt); h264_set_enc_cnt(p_h264,enc_ctl->gop_frm_cnt); h264_set_enc_frame_id(p_h264,enc_ctl->idrid); h264_f_p = get_h264_new_frame_head(1,H264_DEV_0_ID,con&BIT(1)); //预先分配第一frame,待帧结束的时候再分配下一frame h264_module_p = h264_f_p; h264_module_p = get_node(h264_module_p,&h264_free_tab); if(h264_module_p == NULL){ _os_printf("need more node for new h264 frame start1\r\n"); while(1); } addr = get_addr(h264_module_p); h264_set_buf_addr(p_h264,addr); h264_module_p = get_node(h264_module_p,&h264_free_tab); if(h264_module_p == NULL){ _os_printf("need more node for new h264 frame start2\r\n"); while(1); } addr = get_addr(h264_module_p); h264_set_buf_addr(p_h264,addr); hf = list_entry((struct list_head *)h264_f_p,h264_frame,list); //hf->h264_num = frm_num; hf->h264_num = penc_cfg->count; penc_cfg->count++; //Xil_Out32((H264_REG_BASE + 12*4), (enc_ctl->frm_luma_size) >> 8); //MB number of a frame //p_h264->FRM_MB_NUM = (enc_ctl->frm_luma_size) >> 8; h264_set_frame_mb_num(p_h264,enc_ctl->frm_luma_size); //--- ref/lpf buf base //--- cal lpf write base lpf_lu_base = h264_cal_ref_base(enc_ctl->ref_lu_base, enc_ctl->ref_lu_end, enc_ctl->last_lpf_lu_base, enc_ctl->frm_luma_size); lpf_ch_base = h264_cal_ref_base(enc_ctl->ref_ch_base, enc_ctl->ref_ch_end, enc_ctl->last_lpf_ch_base, (enc_ctl->frm_luma_size >> 1)); #if H264_I_ONLY h264_set_ref_wb_addr(p_h264,0X40000000,0X40000000); h264_set_ref_rb_addr(p_h264,0X40000000,0X40000000); //h264_set_ref_wb_addr(p_h264,enc_ctl->ref_lu_base,enc_ctl->ref_lu_base); //h264_set_ref_rb_addr(p_h264,enc_ctl->ref_lu_base,enc_ctl->ref_lu_base); #else h264_set_ref_wb_addr(p_h264,lpf_lu_base,lpf_ch_base); h264_set_ref_rb_addr(p_h264,enc_ctl->last_lpf_lu_base,enc_ctl->last_lpf_ch_base); #endif enc_ctl->last_lpf_lu_base = lpf_lu_base; enc_ctl->last_lpf_ch_base = lpf_ch_base; //--- rate contrl wdata = ((penc_cfg->rc_grp - 1)<<0) | (penc_cfg->rc_effort << 4) | (penc_cfg->rc_en <<7); //Xil_Out32((H264_REG_BASE + 16*4), wdata); //p_h264->RC_CTL = wdata; h264_set_frame_rate_ctl(p_h264,penc_cfg->rc_grp,penc_cfg->rc_effort,penc_cfg->rc_en); if(penc_cfg->rc_en) { rc_grp_byte = h264_rc_cal(penc_cfg, enc_ctl, rc_ctl); //p_h264->RC_BYTE = rc_grp_byte; h264_set_rate_ctl_byte(p_h264,rc_grp_byte); if(penc_cfg->rc_effort == 2) { //p_h264->RC_RDCOST = rc_ctl->frm_rdcost; h264_set_rate_ctl_rdcost(p_h264,rc_ctl->frm_rdcost); } } //--- 3DNR if(penc_cfg->flt3d_en) { rdata = h264_get_flt_3dnr(p_h264); //获取上一帧结果 wdata = rdata & 0x0fffffff; if(h264_dev_num == 2){ if(penc_cfg == &enc_cfg){ //当前是主镜头,那表示上次获取到的是副镜头 enc_2_cfg.r3dnr = wdata; //os_printf("Y0:%08x cont:%d r:%d\r\n",wdata,penc_cfg->count,penc_cfg->run_gop_3dnr); penc_cfg->r3dnr = enc_cfg.r3dnr; //拿回主镜头的参数 }else{ //当前是副镜头,那表示上次获取到的是主镜头 enc_cfg.r3dnr = wdata; //os_printf("Y1:%08x cont:%d r:%d\r\n",wdata,penc_cfg->count,penc_cfg->run_gop_3dnr); penc_cfg->r3dnr = enc_2_cfg.r3dnr; //拿回副镜头的参数 } }else{ penc_cfg->r3dnr = wdata; } if(enc_ctl->enc_first_frm == 1){ penc_cfg->r3dnr = penc_cfg->r3dnr; //disable 3DNR for first frame } else{ penc_cfg->r3dnr = penc_cfg->r3dnr | (3 << 28);//enable 3DNR //结果保存下来 } h264_set_flt_3dnr(p_h264,penc_cfg->r3dnr); }else{ penc_cfg->r3dnr = penc_cfg->r3dnr & 0x0fffffff; h264_set_flt_3dnr(p_h264,penc_cfg->r3dnr); } //configure mb_pipe_cnt if((penc_cfg->flt3d_en == 0) && (enc_ctl->frm_type == 2)) //I frame and 3DNR disable wdata = ((460-2) << 16) | 460; else wdata = ((502-2) << 16) | 502; //crop_en if((penc_cfg->frm_height != penc_cfg->wrap_height)){ //p_h264->Y_CROP = BIT(31)|4; h264_set_y_crop(p_h264,1,penc_cfg->frm_height - penc_cfg->wrap_height); } else { h264_set_y_crop(p_h264,0,8); } penc_cfg->enc_runing = 1; //p_h264->MB_PIPE = wdata; h264_set_mb_pipe(p_h264,wdata); //configure ROI window //p_h264->WRAP_CON |= BIT(7); h264_set_sw_ready(p_h264); // if(con&BIT(1)){ // _os_printf("is iframe \r\n"); // }else{ // _os_printf("is pframe \r\n"); // } // ll_gpio_bit_set(GPIOD,BIT(9)); // ll_gpio_bit_reset(GPIOD,BIT(9)); // _os_printf(" [CON:%x ] ",con); //--- start encode a frame //enc_ctl->bs_buf_id = 0; } void h264_frame_done_isr(uint32 irq_flags, uint32 irq_data, uint32 param){ h264_frame* hf; uint32 rdata; uint16 imb_mov_num; uint8_t drop = 0; uint8_t new_gop = 0; //为了缩时录影,强行需要I帧 //uint32 dat_ofs=0; uint32 bw_cnt_wr,bw_cnt_rd,enc_cnt_cyc; struct h264_device *p_h264 = (struct h264_device *)irq_data; bw_cnt_wr = h264_get_bandwidth_wr(p_h264); bw_cnt_rd = h264_get_bandwidth_rd(p_h264); enc_cnt_cyc = h264_get_cyc_done_num(p_h264); rdata = h264_get_frame_len(p_h264); //如果超过某个size,就认为图片太大,就重新生成吧 if(rdata*3/2 > (H264_NODE_LEN*H264_NODE_NUM)) { h264_set_err(p_h264,1); os_printf(KERN_ERR"h264 size over:%d\n",rdata); } // dat_ofs = rdata%(16*1024); // if(dat_atbuf == 0) // { //ll_m2m_memcpy(M2M_DMA0,frame_cache+frame_offset,h264_dat_buf[0],dat_ofs,0); // }else{ //ll_m2m_memcpy(M2M_DMA0,frame_cache+frame_offset,h264_dat_buf[1],dat_ofs,0); // } //帧OK if(penc_ctl->gop_frm_cnt != 0){ if(penc_cfg->stilltomove == 0){ penc_cfg->still_enc_bps = penc_cfg->enc_bps; penc_cfg->move_enc_bps = penc_cfg->enc_bps; }else{ imb_mov_num = h264_get_imb_num(p_h264); if(((imb_mov_num*1000)/((penc_cfg->frm_width * penc_cfg->frm_height)/256)) > penc_cfg->stilltomove){ //_os_printf("dev running ,cfg move enc_fps(%d)",h264_get_imb_num(p_h264)); penc_cfg->move_remain_gop = penc_cfg->move_keep_gop; } } } hf = list_entry((struct list_head *)h264_f_p,h264_frame,list); hf->frame_len = rdata; hf->which = penc_cfg->src_from; hf->srcID = video_msg.video_type_cur + FRAMEBUFF_SOURCE_CAMERA0; //因为有预分配机制,所以要先去掉最后一个节点 //_os_printf("bw_rd:%d bw_wr:%d\r\n",h264_get_bandwidth_rd(p_h264),h264_get_bandwidth_wr(p_h264)); //os_printf("---H(%d %d)",h264_dev_num,penc_cfg->src_from); if(h264_module_p) { put_node(&h264_free_tab,h264_module_p->prev); } if(h264_is_running(p_h264) == 1){ hf->w = penc_cfg->wrap_width; hf->h = penc_cfg->wrap_height; set_frame_ready(hf); } penc_ctl->enc_bs_byte = rdata; h264_get_intr_status(p_h264,(struct h264_cfg_t*)penc_cfg, (struct h264_ctl_t*)penc_ctl, (struct h264_rc_ctl_t *)prc_ctl); h264_clr_intr(p_h264); //--- user add function to check the flags h264_enc_flag_chk(penc_ctl->enc_end_flags); if(penc_cfg->rc_en) h264_rc_tune_eof(p_h264,(struct h264_cfg_t *)penc_cfg, (struct h264_ctl_t *)penc_ctl, (struct h264_rc_ctl_t *)prc_ctl); h264_enc_eof_update((struct h264_cfg_t *)penc_cfg, (struct h264_ctl_t *)penc_ctl, (struct h264_rc_ctl_t *)prc_ctl); if(h264_is_running(p_h264) == 0){ del_264_frame(h264_f_p); return; } if(param || h264_is_err(p_h264)){ os_printf("isp ov,h264 frame drop\r\n"); drop = 1; h264_set_err(p_h264,0); del_264_frame(h264_f_p); if(h264_dev_num == 2){ if(penc_ctl == &enc_ctl){ recfg_h264_new_grop[0] = 1; }else{ recfg_h264_new_grop[1] = 1; } }else{ recfg_h264_new_grop[0] = 1; //重新配置成I帧 } os_printf("grop[0]:%d\tgrop[1]:%d\tfrom:%d\n",recfg_h264_new_grop[0],recfg_h264_new_grop[1],penc_cfg->src_from); } /////////////////////////////////////////////////////// //p_h264->WRAP_CON |= 0x01|0x10; /////////////////////////////////////////////////////// if(h264_dev_num == 2){ //只有不丢帧的情况才能切换到副码流,仅仅适用主码流(vpp)+镜头副码流情况(不适合从外部其他来源gen420编码) if(penc_ctl == &enc_ctl && drop == 0 ){ penc_ctl = &enc_2_ctl; penc_cfg = &enc_2_cfg; prc_ctl = &rc_2_ctl; if(recfg_h264_new_grop[1] == 1){ recfg_h264_new_grop[1] = 0; penc_ctl->gop_frm_cnt = 0; } if(penc_ctl->gop_frm_cnt == 0){ //I帧再做调整,保证上个gop完成 if(h264_cfg_modify((struct h264_cfg_t *)penc_cfg,2)){ h264_ini_recfg((struct h264_cfg_t *)penc_cfg,(struct h264_ctl_t *)penc_ctl,(struct h264_rc_ctl_t *)prc_ctl); } } }else{ penc_ctl = &enc_ctl; penc_cfg = &enc_cfg; prc_ctl = &rc_ctl; if(recfg_h264_new_grop[0] == 1){ recfg_h264_new_grop[0] = 0; penc_ctl->gop_frm_cnt = 0; } if(penc_ctl->gop_frm_cnt == 0){ if(h264_cfg_modify((struct h264_cfg_t *)penc_cfg,1)){ h264_ini_recfg((struct h264_cfg_t *)penc_cfg,(struct h264_ctl_t *)penc_ctl,(struct h264_rc_ctl_t *)prc_ctl); } } } }else{ if(recfg_h264_new_grop[0] == 1){ recfg_h264_new_grop[0] = 0; penc_ctl->gop_frm_cnt = 0; new_gop = 1; } if(penc_ctl->gop_frm_cnt == 0){ if(h264_cfg_modify((struct h264_cfg_t *)penc_cfg,1)){ h264_ini_recfg((struct h264_cfg_t *)penc_cfg,(struct h264_ctl_t *)penc_ctl,(struct h264_rc_ctl_t *)prc_ctl); } } } h264_set_wrap_img_size(p_h264,penc_cfg->wrap_width,penc_cfg->wrap_height); penc_ctl->bs_buf_id = 0; if(penc_cfg->src_from == GEN420_DATA) { //唤醒任务去kick gen420 extern void *get_vpp_psram_buf(); wake_up_gen420_queue(1,get_vpp_psram_buf()); }else{ if(!penc_cfg->timeLapse_en) { h264_cfg_srcdat(p_h264,penc_cfg->src_from); h264_start_enc_frm(p_h264,(struct h264_cfg_t *)penc_cfg, (struct h264_ctl_t *)penc_ctl, (struct h264_rc_ctl_t *)prc_ctl); } else { if(timeLapse_wk) { if(new_gop) { h264_cfg_srcdat(p_h264,penc_cfg->src_from); h264_start_enc_frm(p_h264,(struct h264_cfg_t *)penc_cfg, (struct h264_ctl_t *)penc_ctl, (struct h264_rc_ctl_t *)prc_ctl); } else { h264_cfg_srcdat(p_h264,SOFT_DATA); penc_cfg->timeLapse_ready_kick = 1; timeLapse_wk->last_kick_time += timeLapse_wk->timer; //设置下一次kick的时间 os_run_work(&timeLapse_wk->wk); } } } } _os_printf(KERN_DEBUG"Z%d",penc_cfg->src_from); } void h264_frame_done_norekick_isr(uint32 irq_flags, uint32 irq_data, uint32 param){ h264_frame* hf; uint32 rdata; uint16 imb_mov_num; //uint32 dat_ofs=0; uint32 bw_cnt_wr,bw_cnt_rd,enc_cnt_cyc; struct h264_device *p_h264 = (struct h264_device *)irq_data; bw_cnt_wr = h264_get_bandwidth_wr(p_h264); bw_cnt_rd = h264_get_bandwidth_rd(p_h264); enc_cnt_cyc = h264_get_cyc_done_num(p_h264); rdata = h264_get_frame_len(p_h264); // dat_ofs = rdata%(16*1024); // if(dat_atbuf == 0) // { //ll_m2m_memcpy(M2M_DMA0,frame_cache+frame_offset,h264_dat_buf[0],dat_ofs,0); // }else{ //ll_m2m_memcpy(M2M_DMA0,frame_cache+frame_offset,h264_dat_buf[1],dat_ofs,0); // } //帧OK if(penc_ctl->gop_frm_cnt != 0){ if(penc_cfg->stilltomove == 0){ penc_cfg->still_enc_bps = penc_cfg->enc_bps; penc_cfg->move_enc_bps = penc_cfg->enc_bps; }else{ imb_mov_num = h264_get_imb_num(p_h264); if(((imb_mov_num*1000)/((penc_cfg->frm_width * penc_cfg->frm_height)/256)) > penc_cfg->stilltomove){ //_os_printf("dev running ,cfg move enc_fps(%d)",h264_get_imb_num(p_h264)); penc_cfg->move_remain_gop = penc_cfg->move_keep_gop; } } } hf = list_entry((struct list_head *)h264_f_p,h264_frame,list); hf->frame_len = rdata; hf->which = penc_cfg->src_from; hf->srcID = video_msg.video_type_cur + FRAMEBUFF_SOURCE_CAMERA0; //因为有预分配机制,所以要先去掉最后一个节点 //_os_printf("bw_rd:%d bw_wr:%d\r\n",h264_get_bandwidth_rd(p_h264),h264_get_bandwidth_wr(p_h264)); //os_printf("---H(%d %d)",h264_dev_num,penc_cfg->src_from); put_node(&h264_free_tab,h264_module_p->prev); if(h264_is_running(p_h264) == 1){ set_frame_ready(hf); } enc_ctl.enc_bs_byte = rdata; h264_get_intr_status(p_h264,(struct h264_cfg_t*)penc_cfg, (struct h264_ctl_t*)penc_ctl, (struct h264_rc_ctl_t *)prc_ctl); h264_clr_intr(p_h264); //--- user add function to check the flags h264_enc_flag_chk(penc_ctl->enc_end_flags); if(penc_cfg->rc_en) h264_rc_tune_eof(p_h264,(struct h264_cfg_t *)penc_cfg, (struct h264_ctl_t *)penc_ctl, (struct h264_rc_ctl_t *)prc_ctl); h264_enc_eof_update((struct h264_cfg_t *)penc_cfg, (struct h264_ctl_t *)penc_ctl, (struct h264_rc_ctl_t *)prc_ctl); if(h264_is_running(p_h264) == 0){ del_264_frame(h264_f_p); h264_sema_up(); return; } if(param){ os_printf("isp ov,h264 frame drop\r\n"); del_264_frame(h264_f_p); if(h264_dev_num == 2){ if(penc_ctl == &enc_ctl){ recfg_h264_new_grop[1] = 1; }else{ recfg_h264_new_grop[0] = 1; } }else{ recfg_h264_new_grop[0] = 1; //重新配置成I帧 } } if(recfg_h264_new_grop[0] == 1){ recfg_h264_new_grop[0] = 0; penc_ctl->gop_frm_cnt = 0; } penc_cfg->enc_runing = 0; os_printf(KERN_DEBUG"Z%d",penc_cfg->src_from); h264_sema_up(); } void h264_sema_init() { if(h264_sem.magic == 0){ os_sema_init(&h264_sem,0); } } int32 h264_sema_down(int32 tmo_ms) { int32 ret; ret = os_sema_down(&h264_sem,tmo_ms); return ret; } void h264_sema_up() { os_sema_up(&h264_sem); } void h264_drv_init(){ struct h264_device *p_h264; p_h264 = (struct h264_device *)dev_get(HG_H264_DEVID); h264_sema_init(); h264_init(p_h264,H264_HARDWARE_CLK); } void h264_frame_dec_done_isr(uint32 irq_flags, uint32 irq_data, uint32 param){ //struct h264_device *p_h264 = (struct h264_device *)irq_data; //frame_done = 1; h264_sema_up(); //_os_printf("h264 dec end\r\n"); } void h264_buf0_done_isr(uint32 irq_flags, uint32 irq_data, uint32 param){ struct h264_device *p_h264 = (struct h264_device *)irq_data; uint32 addr; //_os_printf("B0"); h264_module_p = get_node(h264_module_p,&h264_free_tab); if(h264_module_p == NULL){ _os_printf("need more node for new h264 frame start\r\n"); h264_set_err(p_h264,1); return ; } addr = get_addr(h264_module_p); h264_set_buf_addr(p_h264,addr); //_os_printf("B0"); enc_ctl.bs_buf_id = (penc_ctl->bs_buf_id + 1) & 0x01; } void h264_buf1_done_isr(uint32 irq_flags, uint32 irq_data, uint32 param){ struct h264_device *p_h264 = (struct h264_device *)irq_data; uint32 addr; //_os_printf("B1"); h264_module_p = get_node(h264_module_p,&h264_free_tab); if(h264_module_p == NULL){ _os_printf("need more node for new h264 frame start\r\n"); h264_set_err(p_h264,1); return ; } addr = get_addr(h264_module_p); h264_set_buf_addr(p_h264,addr); //_os_printf("B1"); enc_ctl.bs_buf_id = (penc_ctl->bs_buf_id + 1) & 0x01; } void h264_frame_fast_isr(uint32 irq_flags, uint32 irq_data, uint32 param){ //struct h264_device *p_h264 = (struct h264_device *)irq_data; //_os_printf("********************************%s %d\r\n",__func__,__LINE__); _os_printf(KERN_INFO"(F)"); } void h264_pixel_fast_isr(uint32 irq_flags, uint32 irq_data, uint32 param){ // struct h264_device *p_h264 = (struct h264_device *)irq_data; printf(KERN_INFO"(P)"); // printf("******************************** %s %d\r\n",__func__,__LINE__); // h264_error = 1; } void h264_soft_slow_isr(uint32 irq_flags, uint32 irq_data, uint32 param){ //struct h264_device *p_h264 = (struct h264_device *)irq_data; _os_printf(KERN_INFO"******************************** %s %d\r\n",__func__,__LINE__); } void h264_pixel_done_isr(uint32 irq_flags, uint32 irq_data, uint32 param){ //struct h264_device *p_h264 = (struct h264_device *)irq_data; //_os_printf("mbl_calc:%d mb_calc_max:%d\r\n",h264_get_mbl_calc(p_h264),h264_get_mbl_calc_max(p_h264)); } void h264_enc_timeout_isr(uint32 irq_flags, uint32 irq_data, uint32 param){ //struct h264_device *p_h264 = (struct h264_device *)irq_data; //_os_printf("(ENC TIMOUT)"); //_os_printf("mbl_calc:%d mb_calc_max:%d\r\n",h264_get_mbl_calc(p_h264),h264_get_mbl_calc_max(p_h264)); } void h264_isr_init(struct h264_device *p_h264){ h264_request_irq(p_h264,H264_FRAME_DONE,(h264_irq_hdl )&h264_frame_done_isr,(uint32)p_h264); h264_request_irq(p_h264,H264_BUF0_FULL ,(h264_irq_hdl )&h264_buf0_done_isr,(uint32)p_h264); h264_request_irq(p_h264,H264_BUF1_FULL ,(h264_irq_hdl )&h264_buf1_done_isr,(uint32)p_h264); h264_request_irq(p_h264,H264_SOFT_SLOW ,(h264_irq_hdl )&h264_soft_slow_isr,(uint32)p_h264); h264_request_irq(p_h264,H264_FRAME_FAST,(h264_irq_hdl )&h264_frame_fast_isr,(uint32)p_h264); h264_request_irq(p_h264,H264_PIXEL_FAST,(h264_irq_hdl )&h264_pixel_fast_isr,(uint32)p_h264); h264_request_irq(p_h264,H264_PIXEL_DONE,(h264_irq_hdl )&h264_pixel_done_isr,(uint32)p_h264); h264_request_irq(p_h264,H264_ENC_TIME_OUT,(h264_irq_hdl )&h264_enc_timeout_isr,(uint32)p_h264); } #ifdef SYS_APP_WALKIE_TALKIE void h264_main_sensor_cfg(struct h264_device *p_h264,uint32_t w,uint32_t h,uint8_t src_from){ enc_cfg.enc_mode = 1; //0:dec, 1:enc enc_cfg.enc_bs_buf_size = 4; //0:1KB; 1:2KB; 2:4KB; 3:8KB; 4:16KB enc_cfg.frm_width = (w+0xf)&(~0xf); enc_cfg.frm_height = (h+0xf)&(~0xf); enc_cfg.wrap_width = w; enc_cfg.wrap_height = h; enc_cfg.src_from = src_from; enc_cfg.enc_bps = 200; //Kbit pre second enc_cfg.still_enc_bps = 100; //Kbit pre second enc_cfg.move_enc_bps = 200; //Kbit pre second enc_cfg.stilltomove = 100; //permil for judgmemnt is move or still enc_cfg.move_keep_gop = 5; enc_cfg.frm_rate = 25; //fps #if H264_I_ONLY enc_cfg.frm_gop = 1; //IPPPP frame number of a gop enc_cfg.rc_en = 0; //enc rate control enable #else enc_cfg.frm_gop = 25; //IPPPP frame number of a gop enc_cfg.rc_en = 1; //enc rate control enable #endif enc_cfg.rc_grp = 2; //mb line number when RC change qp enc_cfg.rc_effort = 2; //0:low; 1: high; 2:relax; //still video: bigger frm_ip_rate; moving video: smaller frm_ip_rate; enc_cfg.frm_ip_rate = 10; //initial (Intra MB line)/(Inter MB line) target bit rate times; not critical parameter. enc_cfg.frm_ip_rate_max = 15; enc_cfg.frm_ip_rate_min = 5; enc_cfg.flt3d_en = 0; //3D filter enable 对讲机一定要关掉 enc_cfg.flt3d_en_last = 1; //3D filter enable enc_cfg.flt_noise_lev = 2; //0: very low nosie; 1: low; 2: medium; 3: high; 4: very high; naomal usage is: 2 enc_cfg.flt_noise_lev_last = enc_cfg.flt_noise_lev; enc_cfg.ini_qp = 26; //initial QP for this sequence, not critical enc_cfg.roi_qp = 22; //QP used in ROI windows enc_cfg.gop_rst_3dnr = 10; //10个ip gop后,重新使能一下3dnr enc_cfg.auto_ctl_3dnr = 0; //需要打开vpp移动帧测,否则无效 enc_cfg.run_gop_3dnr = enc_cfg.gop_rst_3dnr; h264_ini_seting_cfg(p_h264,(struct h264_cfg_t *)&enc_cfg, (struct h264_ctl_t *)&enc_ctl, (struct h264_rc_ctl_t *)&rc_ctl,1); if(enc_cfg.flt3d_en) { enc_cfg.r3dnr = h264_get_flt_3dnr(p_h264); enc_cfg.r3dnr = enc_cfg.r3dnr & 0x0fffffff; h264_3dnr_ini(p_h264,(struct h264_cfg_t *)&enc_cfg); // os_printf("Z:%08x\r\n",enc_cfg.r3dnr); } } #else void h264_main_sensor_cfg(struct h264_device *p_h264,uint32_t w,uint32_t h,uint8_t src_from){ enc_cfg.enc_mode = 1; //0:dec, 1:enc enc_cfg.enc_bs_buf_size = 4; //0:1KB; 1:2KB; 2:4KB; 3:8KB; 4:16KB enc_cfg.frm_width = (w+0xf)&(~0xf); enc_cfg.frm_height = (h+0xf)&(~0xf); enc_cfg.wrap_width = w; enc_cfg.wrap_height = h; enc_cfg.src_from = src_from; enc_cfg.enc_bps = 4000; //Kbit pre second enc_cfg.still_enc_bps = 600; //Kbit pre second enc_cfg.move_enc_bps = 4000; //Kbit pre second enc_cfg.stilltomove = 0; //permil for judgmemnt is move or still enc_cfg.move_keep_gop = 5; enc_cfg.frm_rate = 25; //fps #if H264_I_ONLY enc_cfg.frm_gop = 1; //IPPPP frame number of a gop enc_cfg.rc_en = 0; //enc rate control enable #else enc_cfg.frm_gop = 25; //IPPPP frame number of a gop enc_cfg.rc_en = 1; //enc rate control enable #endif enc_cfg.rc_grp = 2; //mb line number when RC change qp enc_cfg.cc_corect = 0; //0: no corection; 1: corection enc_cfg.rc_effort = 2; //0:low; 1: high; 2:relax; //still video: bigger frm_ip_rate; moving video: smaller frm_ip_rate; enc_cfg.frm_ip_rate = 10; //initial (Intra MB line)/(Inter MB line) target bit rate times; not critical parameter. enc_cfg.frm_ip_rate_max = 15; enc_cfg.frm_ip_rate_min = 5; enc_cfg.flt3d_en = 1; //3D filter enable 对讲机一定要关掉 enc_cfg.flt3d_en_last = 1; //3D filter enable enc_cfg.flt_noise_lev = 2; //0: very low nosie; 1: low; 2: medium; 3: high; 4: very high; naomal usage is: 2 enc_cfg.flt_noise_lev_last = enc_cfg.flt_noise_lev; enc_cfg.ini_qp = 26; //initial QP for this sequence, not critical enc_cfg.roi_qp = 22; //QP used in ROI windows enc_cfg.gop_rst_3dnr = 10; //10个ip gop后,重新使能一下3dnr enc_cfg.auto_ctl_3dnr = 1; //需要打开vpp移动帧测,否则无效 enc_cfg.run_gop_3dnr = enc_cfg.gop_rst_3dnr; h264_ini_seting_cfg(p_h264,(struct h264_cfg_t *)&enc_cfg, (struct h264_ctl_t *)&enc_ctl, (struct h264_rc_ctl_t *)&rc_ctl,1); if(enc_cfg.flt3d_en) { enc_cfg.r3dnr = h264_get_flt_3dnr(p_h264); enc_cfg.r3dnr = enc_cfg.r3dnr & 0x0fffffff; h264_3dnr_ini(p_h264,(struct h264_cfg_t *)&enc_cfg); // os_printf("Z:%08x\r\n",enc_cfg.r3dnr); } } #endif void h264_second_sensor_cfg(struct h264_device *p_h264,uint32_t w,uint32_t h,uint8_t src_from){ enc_2_cfg.enc_mode = 1; //0:dec, 1:enc enc_2_cfg.enc_bs_buf_size = 4; //0:1KB; 1:2KB; 2:4KB; 3:8KB; 4:16KB enc_2_cfg.frm_width = (w+0xf)&(~0xf);//w;// enc_2_cfg.frm_height = (h+0xf)&(~0xf);//h;// enc_2_cfg.wrap_width = w; enc_2_cfg.wrap_height = h; enc_2_cfg.src_from = src_from; enc_2_cfg.enc_bps = 1000; //Kbit pre second enc_2_cfg.still_enc_bps = 300; //Kbit pre second enc_2_cfg.move_enc_bps = 1000; //Kbit pre second enc_2_cfg.stilltomove = 0; //permil for judgmemnt is move or still enc_2_cfg.move_keep_gop = 5; enc_2_cfg.frm_rate = 25; //fps #if H264_I_ONLY enc_2_cfg.frm_gop = 1; //IPPPP frame number of a gop enc_2_cfg.rc_en = 0; //enc rate control enable #else enc_2_cfg.frm_gop = 25; //IPPPP frame number of a gop enc_2_cfg.rc_en = 1; //enc rate control enable #endif enc_2_cfg.rc_grp = 2; //mb line number when RC change qp enc_2_cfg.cc_corect = 0; //0: no corection; 1: corection enc_2_cfg.rc_effort = 2; //0:low; 1: high; 2:relax; //still video: bigger frm_ip_rate; moving video: smaller frm_ip_rate; enc_2_cfg.frm_ip_rate = 10; //initial (Intra MB line)/(Inter MB line) target bit rate times; not critical parameter. enc_2_cfg.frm_ip_rate_max = 15; enc_2_cfg.frm_ip_rate_min = 5; enc_2_cfg.flt3d_en = 1; //3D filter enable enc_2_cfg.flt3d_en_last = 1; enc_2_cfg.flt_noise_lev = 2; //0: very low nosie; 1: low; 2: medium; 3: high; 4: very high; naomal usage is: 2 enc_2_cfg.flt_noise_lev_last = enc_2_cfg.flt_noise_lev; enc_2_cfg.ini_qp = 26; //initial QP for this sequence, not critical enc_2_cfg.roi_qp = 22; //QP used in ROI windows enc_2_cfg.gop_rst_3dnr = 10; //10个ip gop后,重新使能一下3dnr enc_2_cfg.auto_ctl_3dnr = 1; enc_2_cfg.run_gop_3dnr = enc_2_cfg.gop_rst_3dnr; h264_ini_seting_cfg(p_h264,(struct h264_cfg_t *)&enc_2_cfg, (struct h264_ctl_t *)&enc_2_ctl, (struct h264_rc_ctl_t *)&rc_2_ctl,2); if(enc_2_cfg.flt3d_en) { enc_2_cfg.r3dnr = h264_get_flt_3dnr(p_h264); enc_2_cfg.r3dnr = enc_cfg.r3dnr & 0x0fffffff; h264_3dnr_ini(p_h264,(struct h264_cfg_t *)&enc_2_cfg); // os_printf("N:%08x\r\n",enc_2_cfg.r3dnr); } } //init就初始化,需要申请释放配合使用,否则内存泄漏 //暂时没有返回值 //申请空间需要16对齐 int h264_mem_init(uint8_t init,uint32_t drv1_w,uint32_t drv1_h,uint32_t drv2_w,uint32_t drv2_h) { uint8_t err = 0; uint32_t lu_base_buf_size,ch_base_size,h264_room_size; if(init) { if(drv1_w && drv1_h) { drv1_w = (drv1_w+0xf)&(~0xf); drv1_h = (drv1_h+0xf)&(~0xf); #if H264_I_ONLY lu_base_buf_size = 4096 + 4096; ch_base_size = 4096 + 4096; #else lu_base_buf_size = (drv1_w*(drv1_h+48)) + 4096 + 4096; ch_base_size = (drv1_w*(drv1_h+48))/2 + 4096 + 4096; #endif h264_ref_lu_base_psram = H264_MALLOC(lu_base_buf_size); h264_ref_ch_base_psram = H264_MALLOC(ch_base_size); if(!h264_ref_lu_base_psram || !h264_ref_ch_base_psram) { err = 1; goto h264_mem_init_end; } else { sys_dcache_invalid_range((uint32_t *) h264_ref_lu_base_psram, lu_base_buf_size); sys_dcache_invalid_range((uint32_t *) h264_ref_ch_base_psram, ch_base_size); } } if(drv2_w && drv2_h) { drv2_w = (drv2_w+0xf)&(~0xf); drv2_h = (drv2_h+0xf)&(~0xf); #if H264_I_ONLY lu_base_buf_size = 4096 + 4096; ch_base_size = 4096 + 4096; #else lu_base_buf_size = (drv2_w*(drv2_h+48)) + 4096 + 4096; ch_base_size = (drv2_w*(drv2_h+48))/2 + 4096 + 4096; #endif h264_ref_lu_base_psram2 = H264_MALLOC(lu_base_buf_size); h264_ref_ch_base_psram2 = H264_MALLOC(ch_base_size); if(!h264_ref_lu_base_psram2 || !h264_ref_ch_base_psram2) { err = 1; goto h264_mem_init_end; } else { sys_dcache_invalid_range((uint32_t *) h264_ref_lu_base_psram2, lu_base_buf_size); sys_dcache_invalid_range((uint32_t *) h264_ref_ch_base_psram2, ch_base_size); } } h264_room_size = H264_NODE_NUM*H264_NODE_LEN + 1024; h264_room_psram = H264_MALLOC(h264_room_size);; if(!h264_room_psram) { err = 1; goto h264_mem_init_end; } else { sys_dcache_invalid_range((uint32_t *) h264_room_psram, h264_room_size); } } else { err = 2; } h264_mem_init_end: if(err) { if(timeLapse_wk) { os_work_cancle2(&timeLapse_wk->wk, 1); H264_LIB_FREE(timeLapse_wk); timeLapse_wk = NULL; } if(h264_ref_lu_base_psram) { H264_FREE(h264_ref_lu_base_psram); h264_ref_lu_base_psram = NULL; } if(h264_ref_ch_base_psram) { H264_FREE(h264_ref_ch_base_psram); h264_ref_ch_base_psram = NULL; } if(h264_ref_lu_base_psram2) { H264_FREE(h264_ref_lu_base_psram2); h264_ref_lu_base_psram2 = NULL; } if(h264_ref_ch_base_psram2) { H264_FREE(h264_ref_ch_base_psram2); h264_ref_ch_base_psram2 = NULL; } if(h264_room_psram) { H264_FREE(h264_room_psram); h264_room_psram = NULL; } } return err; } int h264_enc(uint32_t drv1_from,uint32_t drv1_w,uint32_t drv1_h,uint32_t drv2_from,uint32_t drv2_w,uint32_t drv2_h){ // uint32_t cnt=0; // uint32 start_time; // uint32_t dat_ofs=0; // uint32_t yuv_offset=0; // uint32_t bs_offset=0; //BS file offset // uint32_t x, y; //uint32_t dma_cmd_base = DMA_CMD_BASE; // uint32_t null_dma_da = 0xffff0000; //no use, write to h264 core directly //--- h264 working mode config //struct h264_cfg_t enc_cfg; // uint32_t rdata; // uint32_t room_ofset[2]; // uint32_t bs_size; // uint32_t w_size = 0; // uint8_t frame_end; // uint32_t temp; // uint32_t w_dat = 0; struct h264_device *h264_dev; h264_dev = (struct h264_device *)dev_get(HG_H264_DEVID); _os_printf("%s %d drv2_w:%d\r\n",__func__,__LINE__,drv2_w); if(drv2_w != 0){ h264_dev_num = 2; } else{ h264_dev_num = 1; } uint8_t err = h264_mem_init(1,drv1_w,drv1_h,drv2_w,drv2_h); if(err) { return err; } h264_room_init(); h264_drv_init(h264_dev); h264_main_sensor_cfg(h264_dev,drv1_w,drv1_h,drv1_from); if(h264_dev_num == 2) h264_second_sensor_cfg(h264_dev,drv2_w,drv2_h,drv2_from); h264_isr_init(h264_dev); //h264_wrap_init penc_ctl = &enc_ctl; penc_cfg = &enc_cfg; prc_ctl = &rc_ctl; penc_cfg->timeLapse_en = 0; penc_ctl->bs_buf_id = 0; #if 0 if(penc_cfg->frm_height == 1088){ h264_set_wrap_img_size(h264_dev,penc_cfg->frm_width,(penc_cfg->frm_height-8)); }else{ h264_set_wrap_img_size(h264_dev,penc_cfg->frm_width,penc_cfg->frm_height); } #else h264_set_wrap_img_size(h264_dev,penc_cfg->wrap_width,penc_cfg->wrap_height); #endif h264_cfg_srcdat(h264_dev,penc_cfg->src_from); //p_h264->WRAP_CON |= 0x01|0x10|0x100; h264_set_vpp_vsync_delay(h264_dev,1); h264_set_hw_open(h264_dev,1); //h264_open(h264_dev); h264_start_enc_frm(h264_dev,(struct h264_cfg_t *)penc_cfg, (struct h264_ctl_t *)penc_ctl, (struct h264_rc_ctl_t *)prc_ctl); #if 0 h264_open(h264_dev); os_sleep_ms(10000); h264_close(h264_dev); os_sleep_ms(10000); h264_open(h264_dev); os_sleep_ms(10000); #endif return 0; } //缩时录影外部调用kick接口(不能随时调用,需要结合模式去调用) //没有考虑临界,比如外部要注意不要close又继续重新kick int32_t h264_extern_kick() { if(penc_cfg->timeLapse_en && penc_cfg->timeLapse_ready_kick) { //去启动kick struct h264_device *h264_dev; h264_dev = (struct h264_device *)dev_get(HG_H264_DEVID); extern void h264_cfg_srcdat(struct h264_device *p_h264,uint8_t mode); h264_cfg_srcdat(h264_dev,penc_cfg->src_from); penc_cfg->timeLapse_ready_kick = 0; h264_start_enc_frm(h264_dev,(struct h264_cfg_t *)penc_cfg, (struct h264_ctl_t *)penc_ctl, (struct h264_rc_ctl_t *)prc_ctl); return 0; } return 1; } static int32 h264_timeLapse(struct os_work *work) { struct timeLapse_work_t *timeLapse_wk = (struct timeLapse_work_t *)work; //如果计算时间大于0,代表还没有到kick的时间 //如果小于0,则已经错过了,立刻去kick int32_t err_time = timeLapse_wk->last_kick_time - os_jiffies(); if(err_time > 0 ) { os_run_work_delay(&timeLapse_wk->wk,err_time); } else { h264_extern_kick(); } return 0; } //h264,并且启动缩时录影功能,主要与原来模式不能共存,timer是定时的时间 int h264_enc_with_timeLapse(uint32_t drv1_from,uint32_t drv1_w,uint32_t drv1_h,uint32_t timer) { struct h264_device *h264_dev; h264_dev = (struct h264_device *)dev_get(HG_H264_DEVID); h264_dev_num = 1; uint8_t err = 0; //创建workqueue timeLapse_wk = (struct timeLapse_work_t *)H264_LIB_MALLOC(sizeof(struct timeLapse_work_t)); if(!timeLapse_wk) { err = -1; goto h264_enc_with_timeLapse_end; } timeLapse_wk->timer = timer; err = h264_mem_init(1,drv1_w,drv1_h,0,0); if(err) { goto h264_enc_with_timeLapse_end; } timeLapse_wk->last_kick_time = os_jiffies(); OS_WORK_INIT(&timeLapse_wk->wk, h264_timeLapse, 0); h264_room_init(); h264_drv_init(h264_dev); h264_main_sensor_cfg(h264_dev,drv1_w,drv1_h,drv1_from); h264_isr_init(h264_dev); //h264_wrap_init penc_ctl = &enc_ctl; penc_cfg = &enc_cfg; prc_ctl = &rc_ctl; penc_ctl->bs_buf_id = 0; //启动缩时录影的模式 penc_cfg->timeLapse_en = 1; h264_set_wrap_img_size(h264_dev,penc_cfg->wrap_width,penc_cfg->wrap_height); h264_cfg_srcdat(h264_dev,penc_cfg->src_from); h264_set_vpp_vsync_delay(h264_dev,1); h264_set_hw_open(h264_dev,1); h264_start_enc_frm(h264_dev,(struct h264_cfg_t *)penc_cfg, (struct h264_ctl_t *)penc_ctl, (struct h264_rc_ctl_t *)prc_ctl); h264_enc_with_timeLapse_end: if(err && timeLapse_wk) { H264_LIB_FREE(timeLapse_wk); timeLapse_wk = NULL; } return err; } void h264_dec_intr_status(struct h264_device *p_h264,struct h264_ctl_t *dec_ctl) { uint32_t rdata ; uint32_t hw_byte ; //decoder used bitstream length check hw_byte = h264_get_frame_len(p_h264); hw_byte += h264_get_dec_del(p_h264); if((hw_byte < (dec_ctl->bs_byte_limit - 0x10)) || (hw_byte > dec_ctl->bs_byte_limit)) { _os_printf("decoder stream length error.:%d %d\n\r",hw_byte,dec_ctl->bs_byte_limit); } rdata = h264_get_sta(p_h264); dec_ctl->enc_end_flags= rdata; } void h264_dec_clr_enc_funcs(struct h264_device *p_h264) { h264_set_enc_frame_rdcost(p_h264); } void h264_dec_refbuf_set(struct h264_device *p_h264,uint32_t buf_base, struct h264_cfg_t *dec_cfg, struct h264_ctl_t *dec_ctl) { uint32_t max_luma_size; max_luma_size = dec_cfg->frm_width * dec_cfg->frm_height; dec_ctl->ref_lu_base= buf_base; //must be 4KB aligned dec_ctl->ref_lu_end = ((buf_base + max_luma_size + (48*dec_cfg->frm_width) + 4095) >> 12) << 12; //4KB align dec_ctl->ref_ch_base= dec_ctl->ref_lu_end; dec_ctl->ref_ch_end = ((dec_ctl->ref_ch_base + (max_luma_size>>1) + (24*dec_cfg->frm_width) + 4095) >> 12) << 12; //4KB align dec_ctl->last_lpf_lu_base = dec_ctl->ref_lu_base; dec_ctl->last_lpf_ch_base = dec_ctl->ref_ch_base; //p_h264->REF_LU_ST_ADDR = dec_ctl->ref_lu_base >> 12; //p_h264->REF_LU_ED_ADDR = dec_ctl->ref_lu_end >> 12; //p_h264->REF_CHRO_ST_ADDR = dec_ctl->ref_ch_base >> 12; //p_h264->REF_CHRO_ED_ADDR = dec_ctl->ref_ch_end >> 12; // h264_set_ref_lu_addr(p_h264,dec_ctl->ref_lu_base,dec_ctl->ref_lu_end); // h264_set_ref_chro_addr(p_h264,dec_ctl->ref_ch_base,dec_ctl->ref_ch_end); } void h264_dec_src_room_set(struct h264_device *p_h264,uint32_t buf_base, struct h264_cfg_t *dec_cfg,struct h264_ctl_t *dec_ctl){ uint32_t max_luma_size; max_luma_size = dec_cfg->frm_width * dec_cfg->frm_height; dec_ctl->ref_lu_base= buf_base; //must be 4KB aligned dec_ctl->ref_lu_end = ((buf_base + max_luma_size + (48*dec_cfg->frm_width) + 4095) >> 12) << 12; //4KB align dec_ctl->ref_ch_base= dec_ctl->ref_lu_end; dec_ctl->ref_ch_end = ((dec_ctl->ref_ch_base + (max_luma_size>>1) + (24*dec_cfg->frm_width) + 4095) >> 12) << 12; //4KB align // _os_printf("[%08x]h264_lu:%08x-%08x ch:%08x-%08x\r\n",dec_cfg,dec_ctl->ref_lu_base,dec_ctl->ref_lu_end,dec_ctl->ref_ch_base,dec_ctl->ref_ch_end); h264_set_ref_lu_addr(p_h264,dec_ctl->ref_lu_base,dec_ctl->ref_lu_end); h264_set_ref_chro_addr(p_h264,dec_ctl->ref_ch_base,dec_ctl->ref_ch_end); } void h264_dec_a_frame(struct h264_device *p_h264,uint32_t nal_length, struct h264_ctl_t *dec_ctl, struct h264_header *head, struct str_info *str,uint32 dataroom) { uint32_t wdata; uint32_t base_tmp; uint32_t base_tmp2; wdata = dec_ctl->frm_type | (0 << 4); //p_h264->CON = wdata; h264_set_frame_base_cfg(p_h264,dec_ctl->frm_type,0,0,0); //p_h264->IMG_WIDTH = dec_ctl->frm_width; //p_h264->IMG_HEIGH = dec_ctl->frm_height; h264_set_phy_img_size(p_h264,dec_ctl->frm_width,dec_ctl->frm_height); //p_h264->FRM_QP = head->pic_qp; h264_set_frame_qp(p_h264,head->pic_qp); //ref read base // p_h264->REF_LU_RB_ADDR = dec_ctl->last_lpf_lu_base >> 12; // p_h264->REF_CHRO_RB_ADDR = dec_ctl->last_lpf_ch_base >> 12; h264_set_ref_rb_addr(p_h264,dec_ctl->last_lpf_lu_base,dec_ctl->last_lpf_ch_base); //lpf write base //lpf luma base base_tmp = h264_cal_ref_base(dec_ctl->ref_lu_base, dec_ctl->ref_lu_end, dec_ctl->last_lpf_lu_base, dec_ctl->frm_luma_size); //Xil_Out32((H264_REG_BASE + 84*4), base_tmp >> 12); //p_h264->REF_LU_WB_ADDR = base_tmp >> 12; dec_ctl->last_lpf_lu_base = base_tmp; //lpf chroma base base_tmp2 = h264_cal_ref_base(dec_ctl->ref_ch_base, dec_ctl->ref_ch_end, dec_ctl->last_lpf_ch_base, (dec_ctl->frm_luma_size >> 1)); //Xil_Out32((H264_REG_BASE + 85*4), base_tmp >> 12); //p_h264->REF_CHRO_WB_ADDR = base_tmp2 >> 12; dec_ctl->last_lpf_ch_base = base_tmp2; h264_set_ref_wb_addr(p_h264,base_tmp,base_tmp2); // p_h264->LEN_LIMIT = (nal_length+4); h264_set_len_limit(p_h264,nal_length+4); dec_ctl->bs_byte_limit = nal_length+4; //p_h264->DMA_BS_ADDR0 = ((uint32_t)&frame_cache>>10); h264_set_buf_addr(p_h264,dataroom); //p_h264->FRM_MB_NUM = (dec_ctl->frm_luma_size >> 8); h264_set_frame_mb_num(p_h264,dec_ctl->frm_luma_size); //p_h264->DEC_HEADB_NUM = str->used_bits; h264_set_dec_headb_num(p_h264,str->used_bits); } struct str_info h264_str[3]; struct h264_header h264_head[3]; struct h264_cfg_t dec_cfg[3]; struct h264_ctl_t dec_ctl[3]; //__psram_data uint8_t h264_1_room[100*1024] __aligned(4096); uint8_t *h264_1_room; void h264_dec_room_init(uint8_t devnum,uint16_t drv2_w,uint16_t drv2_h){ uint8_t i = 0; for(i = 0;i < devnum;i++){ h264_ref_memory_base[i] = H264_MALLOC((drv2_w*(drv2_h+48))+(drv2_w*(drv2_h+48))/2 + 3*4096); h264_ref_memory_base[i] = (uint8_t*)(((uint32_t)h264_ref_memory_base[i] + 0xfff) & (~0xfff)); //h264_ref_memory_base[i] = 0X40000000; } } void get_h264_stream_w_h(uint16_t* w,uint16_t* h,uint8_t *h264data){ struct str_info h264_str; struct h264_header h264_head; h264_str.ptr = (uint8_t *)h264data; nal_parse(&h264_str, &h264_head); *w = h264_head.sps_pic_width; *h = h264_head.sps_pic_height; return; } extern uint8_t h264_dec_sps_src_param(uint32 w, uint32 h, uint8_t *buf); void h264_dec_src_264(uint8 *src_file,uint32 file_size,uint32 w,uint32 h,uint32_t devid){ //--- platform initial #if VIDEO_YUV_RANGE_TYPE uint8_t spsbuf[20]; uint8_t spslen; #endif uint8_t onlysps = 0; int32 ret; uint8_t *psram_room; uint8_t* mbs_ptr; //main bs ptr struct h264_device *p_h264; p_h264 = (struct h264_device *)dev_get(HG_H264_DEVID); //file_size = file_size-4; //_os_printf("fs(%d)",file_size); mbs_ptr = src_file; //文件地址 //decoder reference frame addr setting dec_cfg[devid].enc_mode = 0; //0:dec, 1:enc dec_cfg[devid].frm_width = w; //maximal support x-pixel dec_cfg[devid].frm_height= h; //maximal support y-pixel if(src_file[4] == 0x67){ if(file_size > 50){ //单sps不可能大于50字节的,此时肯定是带上sps+pps+I帧的数据帧 onlysps = 0; }else{ onlysps = 1; } } psram_room = (uint8_t*)H264_MALLOC(file_size + 4096); h264_1_room = (uint8_t*)(((uint32_t)psram_room + 0xfff) & (~0xfff)); h264_request_irq(p_h264,H264_FRAME_DONE,(h264_irq_hdl )&h264_frame_dec_done_isr,(uint32)p_h264); while(1){ uint8_t nal_type ; uint32_t nal_start ; //nal bitstream start addr uint32_t nal_length ; //nal byte length if(onlysps == 0){ if((mbs_ptr[4] == 0x67) ||(mbs_ptr[4] == 0x68)){ //SPS mbs_ptr = find_start_code(mbs_ptr); //find first 0x0000_0001 nal_start = (uint32_t) mbs_ptr - 4; //return the 4byte "00000001" mbs_ptr = find_start_code(mbs_ptr); //find second 0x0000_0001 mbs_ptr -= 4; nal_length = (uint32_t) mbs_ptr - nal_start; //file_size = file_size-nal_length; }else{ mbs_ptr = find_start_code(mbs_ptr); nal_start = (uint32_t) mbs_ptr - 4; nal_length = file_size; } }else{ nal_start = (uint32_t)src_file; nal_length = file_size; } // if((mbs_ptr - src_file) > file_size-30000){ // break; // } //--- copy bitstream to BS buffer for decode //_os_printf("%08x %08x %d\r\n",h264_1_room,nal_start,nal_length); hw_memcpy((void*) h264_1_room,(const void*) nal_start,nal_length); sys_dcache_clean_range((uint32_t*)h264_1_room,nal_length); #if VIDEO_YUV_RANGE_TYPE if(h264_1_room[4] == 0x67){ spslen = h264_dec_sps_src_param( w, h,(uint8_t*)spsbuf); memcpy((void*) h264_1_room,(const void*)spsbuf,spslen); } #endif h264_str[devid].ptr = (uint8_t *)h264_1_room; //decoder nal header nal_type = nal_parse(&h264_str[devid], &h264_head[devid]); if(nal_type == sps) { //frame size check if((h264_head[devid].sps_pic_width > dec_cfg[devid].frm_width) || (h264_head[devid].sps_pic_height > dec_cfg[devid].frm_height)) { _os_printf("frame x/y pixel size is too big.(%d %d === > %d %d)\n\r",h264_head[devid].sps_pic_width,h264_head[devid].sps_pic_height,dec_cfg[devid].frm_width,dec_cfg[devid].frm_height); return ; } dec_ctl[devid].frm_width = h264_head[devid].sps_pic_width; //should be 16*N dec_ctl[devid].frm_height= h264_head[devid].sps_pic_height; //should be 16*N dec_ctl[devid].frm_luma_size = dec_ctl[devid].frm_width * dec_ctl[devid].frm_height; dec_ctl[devid].timeout_limit = (dec_ctl[devid].frm_luma_size >> 8) * 512 * 2; //_os_printf("h264_ref:%08x\r\n",h264_ref_memory_base[devid]); h264_dec_refbuf_set(p_h264,((uint32_t)h264_ref_memory_base[devid] + 0xfff) & (~0xfff), (struct h264_cfg_t *)&dec_cfg[devid], (struct h264_ctl_t *)&dec_ctl[devid]); h264_dec_clr_enc_funcs(p_h264); h264_set_mb_pipe(p_h264,((502-2) << 16) | 502); h264_set_timeout_limit(p_h264,(dec_ctl[devid].timeout_limit) >> 10); } else if(nal_type == pps) { } else if(nal_type == pic_idr) { } h264_dec_src_room_set(p_h264,((uint32_t)h264_ref_memory_base[devid] + 0xfff) & (~0xfff), (struct h264_cfg_t *)&dec_cfg[devid], (struct h264_ctl_t *)&dec_ctl[devid]); //there is a frame need decode if((nal_type == pic_idr) || (nal_type == pic_data)) { //decode a picture if(nal_type == pic_idr) dec_ctl[devid].frm_type = 2; else dec_ctl[devid].frm_type = 0; h264_dec_a_frame(p_h264,nal_length, &dec_ctl[devid], &h264_head[devid], &h264_str[devid],(uint32_t)h264_1_room); h264_decode_start(p_h264); ret = h264_sema_down(100); h264_dec_intr_status(p_h264,&dec_ctl[devid]); //-- clear the frm end flag h264_clr_intr(p_h264); h264_dec_flag_chk(dec_ctl[devid].enc_end_flags); } file_size -= nal_length; if(file_size == 0) //sps+pps { H264_FREE(psram_room); return; } } } void h264_dec_nal_264(uint8 *src_file,uint32 file_size,uint32 w,uint32 h,uint32_t devid){ struct h264_device *p_h264; p_h264 = (struct h264_device *)dev_get(HG_H264_DEVID); dec_cfg[devid].enc_mode = 0; //0:dec, 1:enc dec_cfg[devid].frm_width = w; //maximal support x-pixel dec_cfg[devid].frm_height= h; //maximal support y-pixel } void h264_frame_gen420_kick_run(struct h264_device *p_h264,uint32 addr,uint16_t w,uint16_t h){ if(recfg_h264_new_grop[0] == 1){ recfg_h264_new_grop[0] = 0; penc_ctl->gop_frm_cnt = 0; } //os_printf("w:%d h:%d\r\n",w,h); penc_cfg->wrap_width = w; penc_cfg->wrap_height = h; penc_cfg->frm_width = (w+0xf)&(~0xf); penc_cfg->frm_height = (h+0xf)&(~0xf); h264_init(p_h264,H264_HARDWARE_CLK); if(penc_ctl->gop_frm_cnt == 0){ if(h264_cfg_modify((struct h264_cfg_t *)penc_cfg,1)){ h264_ini_recfg((struct h264_cfg_t *)penc_cfg,(struct h264_ctl_t *)penc_ctl,(struct h264_rc_ctl_t *)prc_ctl); h264_ini_seting_cfg(p_h264,(struct h264_cfg_t *)penc_cfg, (struct h264_ctl_t *)penc_ctl, (struct h264_rc_ctl_t *)prc_ctl,1); } } h264_request_irq(p_h264,H264_FRAME_DONE, (h264_irq_hdl )&h264_frame_done_norekick_isr,(uint32)p_h264); h264_request_irq(p_h264,H264_BUF0_FULL , (h264_irq_hdl )&h264_buf0_done_isr,(uint32)p_h264); h264_request_irq(p_h264,H264_BUF1_FULL , (h264_irq_hdl )&h264_buf1_done_isr,(uint32)p_h264); h264_request_irq(p_h264,H264_SOFT_SLOW , (h264_irq_hdl )&h264_soft_slow_isr,(uint32)p_h264); h264_request_irq(p_h264,H264_FRAME_FAST, (h264_irq_hdl )&h264_frame_fast_isr,(uint32)p_h264); h264_request_irq(p_h264,H264_PIXEL_FAST, (h264_irq_hdl )&h264_pixel_fast_isr,(uint32)p_h264); h264_request_irq(p_h264,H264_PIXEL_DONE, (h264_irq_hdl )&h264_pixel_done_isr,(uint32)p_h264); h264_request_irq(p_h264,H264_ENC_TIME_OUT,(h264_irq_hdl )&h264_enc_timeout_isr,(uint32)p_h264); h264_set_oe_select(p_h264, 0, 0); h264_set_wrap_img_size(p_h264,penc_cfg->wrap_width,penc_cfg->wrap_height); h264_cfg_srcdat(p_h264,penc_cfg->src_from); h264_set_vpp_vsync_delay(p_h264,1); h264_set_hw_open(p_h264,1); //h264_start_enc_frm(p_h264,(struct h264_cfg_t *)penc_cfg, (struct h264_ctl_t *)penc_ctl, (struct h264_rc_ctl_t *)prc_ctl); enc_ctl.bs_buf_id = 0; h264_open(p_h264); wake_up_gen420_queue(1,(uint8_t*)addr); } struct h264_hardware_s { struct msi *msi; struct h264_device *h264_dev; os_msgqueue_t msgq; struct os_event evt; struct os_task task; }; //一个回调函数,私有结构,以及一些固定参数 struct h264_msg_s { struct list_head list; //h264 queue hand void *fn_data; //函数的私有结构 uint8_t type; //0: h264 enc 1:h264 dec uint32_t data; uint32_t len; uint16_t w; uint16_t h; uint8_t sta; //0:idle 1:data ready }; int put_h264msg_to_queue(uint8_t type,uint32_t w,uint32_t h,uint32 data,uint32 len){ struct h264_msg_s *wq; uint32_t flags; wq = malloc(sizeof(struct h264_msg_s)); wq->type = type; wq->w = w; wq->h = h; wq->sta = 0; wq->data = data; wq->len = len; flags = disable_irq(); INIT_LIST_HEAD(&wq->list); list_add_tail(&wq->list,(struct list_head*)&h264_queue_head); enable_irq(flags); h264wq_sema_up(); return (int)&wq->list; } uint8_t h264msg_queue_done(uint32 list){ struct list_head *dlist; uint32_t flags; flags = disable_irq(); dlist = (struct list_head *)&h264_queue_head; while(dlist->next != &h264_queue_head){ if(dlist->next == (struct list_head *)list){ enable_irq(flags); return 0; } dlist = dlist->next; } enable_irq(flags); return 1; } extern int scale2_cfg_run(uint8_t streamfrom,uint8_t id); extern volatile uint8_t scaler2_dev_id; void h264_wq_thread(){ int32 ret; uint32_t flags; struct list_head *dlist; struct h264_msg_s* h264dev; struct h264_device *p_h264; p_h264 = (struct h264_device *)dev_get(HG_H264_DEVID); while(1){ h264wq_sema_down(-1); flags = disable_irq(); if(list_empty((struct list_head *)&h264_queue_head) != TRUE){ enable_irq(flags); do{ flags = disable_irq(); dlist = (struct list_head *)&h264_queue_head; dlist = dlist->next; if(dlist == &h264_queue_head){ enable_irq(flags); break; //return -1; }else{ h264dev = list_entry((struct list_head *)dlist,struct h264_msg_s,list); enable_irq(flags); if(h264dev->type == 0){ //h264 enc h264_frame_gen420_kick_run(p_h264,h264dev->data,h264dev->w,h264dev->h); ret = h264_sema_down(100); if(ret == 0){ os_printf("enc error..\r\n"); } }else{ //_os_printf("%s %d\r\n",__func__,__LINE__); int32 ret = scale2_cfg_run(H264_DEC,scaler2_dev_id); if(ret == 0) { h264_dec_src_264((uint8_t*)h264dev->data,h264dev->len,h264dev->w,16*((h264dev->h + 15)/16) ,0); } //scale2_cfg_run(MJPEG_DEC,scaler2_dev_id); //void jpg_decode_run(uint32_t addr); //jpg_decode_run(h264_1_room); } flags = disable_irq(); list_del(&h264dev->list); enable_irq(flags); free(h264dev); } }while(1); }else{ enable_irq(flags); } } } extern struct msi *h264_msi_init_with_mode_for_264wq(uint32_t drv1_from, uint16_t drv1_w, uint16_t drv1_h); void h264wq_queue_init(uint16_t w,uint16_t h){ //h264_drv_init(); h264wq_sema_init(); INIT_LIST_HEAD((struct list_head *)&h264_queue_head); h264_msi_init_with_mode_for_264wq(GEN420_DATA,w,h); h264_dec_room_init(1,w,16*((h+15)/16)); os_task_create("h264_thread", h264_wq_thread, NULL, OS_TASK_PRIORITY_HIGH, 0, NULL, 1024); } //gen420编码的接口 int32_t h264_gen420_kick() { struct h264_device *h264_dev; h264_dev = (struct h264_device *)dev_get(HG_H264_DEVID); extern void h264_cfg_srcdat(struct h264_device *p_h264,uint8_t mode); h264_cfg_srcdat(h264_dev,GEN420_DATA); h264_start_enc_frm(h264_dev,(struct h264_cfg_t *)penc_cfg, (struct h264_ctl_t *)penc_ctl, (struct h264_rc_ctl_t *)prc_ctl); return 0; } //解码封装的接口 void sps_setting(struct str_info *str, struct h264_header *head, uint32_t w, uint32_t h) { uint8_t spsbuf[20]; uint8_t spslen; spslen = h264_dec_sps_src_param(w, h, spsbuf); str->ptr = spsbuf; nal_parse(str, head); } void pps_setting(struct str_info *str, struct h264_header *head, uint8_t *pps, uint8_t len) { uint8_t ppsbuf[20]; ppsbuf[0] = 0x00; ppsbuf[1] = 0x00; ppsbuf[2] = 0x00; ppsbuf[3] = 0x01; memcpy((void *) ppsbuf + 4, (const void *) pps, len); str->ptr = ppsbuf; nal_parse(str, head); } void cfg_setting(struct h264_device *p_h264, struct h264_header *head, struct h264_cfg_t *cfg, struct h264_ctl_t *ctl) { if ((head->sps_pic_width > cfg->frm_width) || (head->sps_pic_height > cfg->frm_height)) { _os_printf("frame x/y pixel size is too big.(%d %d === > %d %d)\n\r", head->sps_pic_width, head->sps_pic_height, cfg->frm_width, cfg->frm_height); } ctl->frm_width = head->sps_pic_width; // should be 16*N ctl->frm_height = head->sps_pic_height; // should be 16*N ctl->frm_luma_size = ctl->frm_width * ctl->frm_height; ctl->timeout_limit = (ctl->frm_luma_size >> 8) * 512 * 2; h264_dec_clr_enc_funcs(p_h264); h264_set_mb_pipe(p_h264, ((502 - 2) << 16) | 502); h264_set_timeout_limit(p_h264, (ctl->timeout_limit) >> 10); } void h264_decode_I_P_setting(struct str_info *str, struct h264_header *head, uint8_t *rom_ptr) { str->ptr = rom_ptr; nal_parse(str, head); } void h264_rom_memcpy(uint8_t *rom_ptr, uint8_t *data, uint32_t len) { rom_ptr[0] = 0x00; rom_ptr[1] = 0x00; rom_ptr[2] = 0x00; rom_ptr[3] = 0x01; hw_memcpy((void *) rom_ptr + 4, (const void *) data, len); sys_dcache_clean_range((uint32_t *) rom_ptr, len + 4); }