/** @brief Sample code of video snapshot from proc and encode to bs.\n @file video_snapshot.c @author Jeah Yen @ingroup mhdal @note This file is modified from video_record.c. Copyright Novatek Microelectronics Corp. 2018. All rights reserved. */ #include #include #include #include #include #include "hdal.h" #include "hd_debug.h" // platform dependent #if defined(__LINUX) #include //for pthread API #define MAIN(argc, argv) int main(int argc, char** argv) #define GETCHAR() getchar() #else #include #include //for pthread API #include //for sleep API #define sleep(x) vos_util_delay_ms(1000*(x)) #define msleep(x) vos_util_delay_ms(x) #define usleep(x) vos_util_delay_us(x) #include //for MAIN(), GETCHAR() API #define MAIN(argc, argv) EXAMFUNC_ENTRY(hd_video_snapshot, argc, argv) #define GETCHAR() NVT_EXAMSYS_GETCHAR() #endif #define DEBUG_MENU 1 #define CHKPNT printf("\033[37mCHK: %s, %s: %d\033[0m\r\n",__FILE__,__func__,__LINE__) #define DBGH(x) printf("\033[0;35m%s=0x%08X\033[0m\r\n", #x, x) #define DBGD(x) printf("\033[0;35m%s=%d\033[0m\r\n", #x, x) /////////////////////////////////////////////////////////////////////////////// //header #define DBGINFO_BUFSIZE() (0x200) //RAW #define VDO_RAW_BUFSIZE(w, h, pxlfmt) (ALIGN_CEIL_4((w) * HD_VIDEO_PXLFMT_BPP(pxlfmt) / 8) * (h)) //NRX: RAW compress: Only support 12bit mode #define RAW_COMPRESS_RATIO 59 #define VDO_NRX_BUFSIZE(w, h) (ALIGN_CEIL_4(ALIGN_CEIL_64(w) * 12 / 8 * RAW_COMPRESS_RATIO / 100 * (h))) //CA for AWB #define VDO_CA_BUF_SIZE(win_num_w, win_num_h) ALIGN_CEIL_4((win_num_w * win_num_h << 3) << 1) //LA for AE #define VDO_LA_BUF_SIZE(win_num_w, win_num_h) ALIGN_CEIL_4((win_num_w * win_num_h << 1) << 1) //YUV #define VDO_YUV_BUFSIZE(w, h, pxlfmt) (ALIGN_CEIL_4((w) * HD_VIDEO_PXLFMT_BPP(pxlfmt) / 8) * (h)) //NVX: YUV compress #define YUV_COMPRESS_RATIO 75 #define VDO_NVX_BUFSIZE(w, h, pxlfmt) (VDO_YUV_BUFSIZE(w, h, pxlfmt) * YUV_COMPRESS_RATIO / 100) /////////////////////////////////////////////////////////////////////////////// #define SEN_OUT_FMT HD_VIDEO_PXLFMT_RAW12 #define CAP_OUT_FMT HD_VIDEO_PXLFMT_RAW12 #define CA_WIN_NUM_W 32 #define CA_WIN_NUM_H 32 #define LA_WIN_NUM_W 32 #define LA_WIN_NUM_H 32 #define VA_WIN_NUM_W 16 #define VA_WIN_NUM_H 16 #define YOUT_WIN_NUM_W 128 #define YOUT_WIN_NUM_H 128 #define ETH_8BIT_SEL 0 //0: 2bit out, 1:8 bit out #define ETH_OUT_SEL 1 //0: full, 1: subsample 1/2 #define VDO_SIZE_W 1920 #define VDO_SIZE_H 1080 /////////////////////////////////////////////////////////////////////////////// static HD_RESULT mem_init(void) { HD_RESULT ret; HD_COMMON_MEM_INIT_CONFIG mem_cfg = {0}; // config common pool (cap) mem_cfg.pool_info[0].type = HD_COMMON_MEM_COMMON_POOL; mem_cfg.pool_info[0].blk_size = DBGINFO_BUFSIZE()+VDO_RAW_BUFSIZE(VDO_SIZE_W, VDO_SIZE_H, CAP_OUT_FMT) +VDO_CA_BUF_SIZE(CA_WIN_NUM_W, CA_WIN_NUM_H) +VDO_LA_BUF_SIZE(LA_WIN_NUM_W, LA_WIN_NUM_H); mem_cfg.pool_info[0].blk_cnt = 3; mem_cfg.pool_info[0].ddr_id = DDR_ID0; // config common pool (main) mem_cfg.pool_info[1].type = HD_COMMON_MEM_COMMON_POOL; mem_cfg.pool_info[1].blk_size = DBGINFO_BUFSIZE()+VDO_YUV_BUFSIZE(VDO_SIZE_W, VDO_SIZE_H, HD_VIDEO_PXLFMT_YUV420); mem_cfg.pool_info[1].blk_cnt = 3; mem_cfg.pool_info[1].ddr_id = DDR_ID0; ret = hd_common_mem_init(&mem_cfg); return ret; } static HD_RESULT mem_exit(void) { HD_RESULT ret = HD_OK; hd_common_mem_uninit(); return ret; } /////////////////////////////////////////////////////////////////////////////// static HD_RESULT get_cap_caps(HD_PATH_ID video_cap_ctrl, HD_VIDEOCAP_SYSCAPS *p_video_cap_syscaps) { HD_RESULT ret = HD_OK; hd_videocap_get(video_cap_ctrl, HD_VIDEOCAP_PARAM_SYSCAPS, p_video_cap_syscaps); return ret; } static HD_RESULT set_cap_cfg(HD_PATH_ID *p_video_cap_ctrl) { HD_RESULT ret = HD_OK; HD_VIDEOCAP_DRV_CONFIG cap_cfg = {0}; HD_PATH_ID video_cap_ctrl = 0; HD_VIDEOCAP_CTRL iq_ctl = {0}; char *chip_name = getenv("NVT_CHIP_ID"); snprintf(cap_cfg.sen_cfg.sen_dev.driver_name, HD_VIDEOCAP_SEN_NAME_LEN-1, "nvt_sen_imx290"); cap_cfg.sen_cfg.sen_dev.if_type = HD_COMMON_VIDEO_IN_MIPI_CSI; cap_cfg.sen_cfg.sen_dev.pin_cfg.pinmux.sensor_pinmux = 0x220; //PIN_SENSOR_CFG_MIPI | PIN_SENSOR_CFG_MCLK cap_cfg.sen_cfg.sen_dev.pin_cfg.pinmux.serial_if_pinmux = 0x301;//PIN_MIPI_LVDS_CFG_CLK2 | PIN_MIPI_LVDS_CFG_DAT0|PIN_MIPI_LVDS_CFG_DAT1 | PIN_MIPI_LVDS_CFG_DAT2 | PIN_MIPI_LVDS_CFG_DAT3 if (chip_name != NULL && strcmp(chip_name, "CHIP_NA51089") == 0) { cap_cfg.sen_cfg.sen_dev.pin_cfg.pinmux.cmd_if_pinmux = 0x01;//PIN_I2C_CFG_CH1 } else { cap_cfg.sen_cfg.sen_dev.pin_cfg.pinmux.cmd_if_pinmux = 0x10;//PIN_I2C_CFG_CH2 } cap_cfg.sen_cfg.sen_dev.pin_cfg.clk_lane_sel = HD_VIDEOCAP_SEN_CLANE_SEL_CSI0_USE_C0; cap_cfg.sen_cfg.sen_dev.pin_cfg.sen_2_serial_pin_map[0] = 0; cap_cfg.sen_cfg.sen_dev.pin_cfg.sen_2_serial_pin_map[1] = 1; cap_cfg.sen_cfg.sen_dev.pin_cfg.sen_2_serial_pin_map[2] = HD_VIDEOCAP_SEN_IGNORE; cap_cfg.sen_cfg.sen_dev.pin_cfg.sen_2_serial_pin_map[3] = HD_VIDEOCAP_SEN_IGNORE; cap_cfg.sen_cfg.sen_dev.pin_cfg.sen_2_serial_pin_map[4] = HD_VIDEOCAP_SEN_IGNORE; cap_cfg.sen_cfg.sen_dev.pin_cfg.sen_2_serial_pin_map[5] = HD_VIDEOCAP_SEN_IGNORE; cap_cfg.sen_cfg.sen_dev.pin_cfg.sen_2_serial_pin_map[6] = HD_VIDEOCAP_SEN_IGNORE; cap_cfg.sen_cfg.sen_dev.pin_cfg.sen_2_serial_pin_map[7] = HD_VIDEOCAP_SEN_IGNORE; ret = hd_videocap_open(0, HD_VIDEOCAP_0_CTRL, &video_cap_ctrl); //open this for device control if (ret != HD_OK) { return ret; } ret |= hd_videocap_set(video_cap_ctrl, HD_VIDEOCAP_PARAM_DRV_CONFIG, &cap_cfg); iq_ctl.func = HD_VIDEOCAP_FUNC_AE | HD_VIDEOCAP_FUNC_AWB; ret |= hd_videocap_set(video_cap_ctrl, HD_VIDEOCAP_PARAM_CTRL, &iq_ctl); *p_video_cap_ctrl = video_cap_ctrl; return ret; } static HD_RESULT set_cap_param(HD_PATH_ID video_cap_path, HD_DIM *p_dim) { HD_RESULT ret = HD_OK; {//select sensor mode, manually or automatically HD_VIDEOCAP_IN video_in_param = {0}; video_in_param.sen_mode = HD_VIDEOCAP_SEN_MODE_AUTO; //auto select sensor mode by the parameter of HD_VIDEOCAP_PARAM_OUT video_in_param.frc = HD_VIDEO_FRC_RATIO(30,1); video_in_param.dim.w = p_dim->w; video_in_param.dim.h = p_dim->h; video_in_param.pxlfmt = SEN_OUT_FMT; video_in_param.out_frame_num = HD_VIDEOCAP_SEN_FRAME_NUM_1; ret = hd_videocap_set(video_cap_path, HD_VIDEOCAP_PARAM_IN, &video_in_param); //printf("set_cap_param MODE=%d\r\n", ret); if (ret != HD_OK) { return ret; } } #if 1 //no crop, full frame { HD_VIDEOCAP_CROP video_crop_param = {0}; video_crop_param.mode = HD_CROP_OFF; ret = hd_videocap_set(video_cap_path, HD_VIDEOCAP_PARAM_OUT_CROP, &video_crop_param); //printf("set_cap_param CROP NONE=%d\r\n", ret); } #else //HD_CROP_ON { HD_VIDEOCAP_CROP video_crop_param = {0}; video_crop_param.mode = HD_CROP_ON; video_crop_param.win.rect.x = 0; video_crop_param.win.rect.y = 0; video_crop_param.win.rect.w = 1920/2; video_crop_param.win.rect.h= 1080/2; video_crop_param.align.w = 4; video_crop_param.align.h = 4; ret = hd_videocap_set(video_cap_path, HD_VIDEOCAP_PARAM_OUT_CROP, &video_crop_param); //printf("set_cap_param CROP ON=%d\r\n", ret); } #endif { HD_VIDEOCAP_OUT video_out_param = {0}; //without setting dim for no scaling, using original sensor out size video_out_param.pxlfmt = CAP_OUT_FMT; video_out_param.dir = HD_VIDEO_DIR_NONE; ret = hd_videocap_set(video_cap_path, HD_VIDEOCAP_PARAM_OUT, &video_out_param); //printf("set_cap_param OUT=%d\r\n", ret); } return ret; } /////////////////////////////////////////////////////////////////////////////// static HD_RESULT set_proc_cfg(HD_PATH_ID *p_video_proc_ctrl, HD_DIM* p_max_dim) { HD_RESULT ret = HD_OK; HD_VIDEOPROC_DEV_CONFIG video_cfg_param = {0}; HD_VIDEOPROC_CTRL video_ctrl_param = {0}; HD_PATH_ID video_proc_ctrl = 0; ret = hd_videoproc_open(0, HD_VIDEOPROC_0_CTRL, &video_proc_ctrl); //open this for device control if (ret != HD_OK) return ret; if (p_max_dim != NULL ) { video_cfg_param.pipe = HD_VIDEOPROC_PIPE_RAWALL; video_cfg_param.isp_id = 0; video_cfg_param.ctrl_max.func = 0; video_cfg_param.in_max.func = 0; video_cfg_param.in_max.dim.w = p_max_dim->w; video_cfg_param.in_max.dim.h = p_max_dim->h; video_cfg_param.in_max.pxlfmt = CAP_OUT_FMT; video_cfg_param.in_max.frc = HD_VIDEO_FRC_RATIO(1,1); ret = hd_videoproc_set(video_proc_ctrl, HD_VIDEOPROC_PARAM_DEV_CONFIG, &video_cfg_param); if (ret != HD_OK) { return HD_ERR_NG; } } video_ctrl_param.func = 0; ret = hd_videoproc_set(video_proc_ctrl, HD_VIDEOPROC_PARAM_CTRL, &video_ctrl_param); *p_video_proc_ctrl = video_proc_ctrl; return ret; } static HD_RESULT set_proc_param(HD_PATH_ID video_proc_path, HD_DIM* p_dim) { HD_RESULT ret = HD_OK; if (p_dim != NULL) { //if videoproc is already binding to dest module, not require to setting this! HD_VIDEOPROC_OUT video_out_param = {0}; video_out_param.func = 0; video_out_param.dim.w = p_dim->w; video_out_param.dim.h = p_dim->h; video_out_param.pxlfmt = HD_VIDEO_PXLFMT_YUV420; video_out_param.dir = HD_VIDEO_DIR_NONE; video_out_param.frc = HD_VIDEO_FRC_RATIO(1,1); video_out_param.depth = 1; //set 1 to allow pull ret = hd_videoproc_set(video_proc_path, HD_VIDEOPROC_PARAM_OUT, &video_out_param); } return ret; } /////////////////////////////////////////////////////////////////////////////// static HD_RESULT set_enc_cfg(HD_PATH_ID video_enc_path, HD_DIM *p_max_dim, UINT32 max_bitrate) { HD_RESULT ret = HD_OK; HD_VIDEOENC_PATH_CONFIG video_path_config = {0}; if (p_max_dim != NULL) { //--- HD_VIDEOENC_PARAM_PATH_CONFIG --- video_path_config.max_mem.codec_type = HD_CODEC_TYPE_H264; video_path_config.max_mem.max_dim.w = p_max_dim->w; video_path_config.max_mem.max_dim.h = p_max_dim->h; video_path_config.max_mem.bitrate = max_bitrate; video_path_config.max_mem.enc_buf_ms = 3000; video_path_config.max_mem.svc_layer = HD_SVC_4X; video_path_config.max_mem.ltr = TRUE; video_path_config.max_mem.rotate = FALSE; video_path_config.max_mem.source_output = FALSE; video_path_config.isp_id = 0; ret = hd_videoenc_set(video_enc_path, HD_VIDEOENC_PARAM_PATH_CONFIG, &video_path_config); if (ret != HD_OK) { printf("set_enc_path_config = %d\r\n", ret); return HD_ERR_NG; } } return ret; } static HD_RESULT set_enc_param(HD_PATH_ID video_enc_path, HD_DIM *p_dim, UINT32 enc_type, UINT32 bitrate) { HD_RESULT ret = HD_OK; HD_VIDEOENC_IN video_in_param = {0}; HD_VIDEOENC_OUT video_out_param = {0}; HD_H26XENC_RATE_CONTROL rc_param = {0}; if (p_dim != NULL) { //--- HD_VIDEOENC_PARAM_IN --- video_in_param.dir = HD_VIDEO_DIR_NONE; video_in_param.pxl_fmt = HD_VIDEO_PXLFMT_YUV420; video_in_param.dim.w = p_dim->w; video_in_param.dim.h = p_dim->h; video_in_param.frc = HD_VIDEO_FRC_RATIO(1,1); ret = hd_videoenc_set(video_enc_path, HD_VIDEOENC_PARAM_IN, &video_in_param); if (ret != HD_OK) { printf("set_enc_param_in = %d\r\n", ret); return ret; } printf("enc_type=%d\r\n", enc_type); if (enc_type == 0) { //--- HD_VIDEOENC_PARAM_OUT_ENC_PARAM --- video_out_param.codec_type = HD_CODEC_TYPE_H265; video_out_param.h26x.profile = HD_H265E_MAIN_PROFILE; video_out_param.h26x.level_idc = HD_H265E_LEVEL_5; video_out_param.h26x.gop_num = 15; video_out_param.h26x.ltr_interval = 0; video_out_param.h26x.ltr_pre_ref = 0; video_out_param.h26x.gray_en = 0; video_out_param.h26x.source_output = 0; video_out_param.h26x.svc_layer = HD_SVC_DISABLE; video_out_param.h26x.entropy_mode = HD_H265E_CABAC_CODING; ret = hd_videoenc_set(video_enc_path, HD_VIDEOENC_PARAM_OUT_ENC_PARAM, &video_out_param); if (ret != HD_OK) { printf("set_enc_param_out = %d\r\n", ret); return ret; } //--- HD_VIDEOENC_PARAM_OUT_RATE_CONTROL --- rc_param.rc_mode = HD_RC_MODE_CBR; rc_param.cbr.bitrate = bitrate; rc_param.cbr.frame_rate_base = 30; rc_param.cbr.frame_rate_incr = 1; rc_param.cbr.init_i_qp = 26; rc_param.cbr.min_i_qp = 10; rc_param.cbr.max_i_qp = 45; rc_param.cbr.init_p_qp = 26; rc_param.cbr.min_p_qp = 10; rc_param.cbr.max_p_qp = 45; rc_param.cbr.static_time = 4; rc_param.cbr.ip_weight = 0; ret = hd_videoenc_set(video_enc_path, HD_VIDEOENC_PARAM_OUT_RATE_CONTROL, &rc_param); if (ret != HD_OK) { printf("set_enc_rate_control = %d\r\n", ret); return ret; } } else if (enc_type == 1) { //--- HD_VIDEOENC_PARAM_OUT_ENC_PARAM --- video_out_param.codec_type = HD_CODEC_TYPE_H264; video_out_param.h26x.profile = HD_H264E_HIGH_PROFILE; video_out_param.h26x.level_idc = HD_H264E_LEVEL_5_1; video_out_param.h26x.gop_num = 15; video_out_param.h26x.ltr_interval = 0; video_out_param.h26x.ltr_pre_ref = 0; video_out_param.h26x.gray_en = 0; video_out_param.h26x.source_output = 0; video_out_param.h26x.svc_layer = HD_SVC_DISABLE; video_out_param.h26x.entropy_mode = HD_H264E_CABAC_CODING; ret = hd_videoenc_set(video_enc_path, HD_VIDEOENC_PARAM_OUT_ENC_PARAM, &video_out_param); if (ret != HD_OK) { printf("set_enc_param_out = %d\r\n", ret); return ret; } //--- HD_VIDEOENC_PARAM_OUT_RATE_CONTROL --- rc_param.rc_mode = HD_RC_MODE_CBR; rc_param.cbr.bitrate = bitrate; rc_param.cbr.frame_rate_base = 30; rc_param.cbr.frame_rate_incr = 1; rc_param.cbr.init_i_qp = 26; rc_param.cbr.min_i_qp = 10; rc_param.cbr.max_i_qp = 45; rc_param.cbr.init_p_qp = 26; rc_param.cbr.min_p_qp = 10; rc_param.cbr.max_p_qp = 45; rc_param.cbr.static_time = 4; rc_param.cbr.ip_weight = 0; ret = hd_videoenc_set(video_enc_path, HD_VIDEOENC_PARAM_OUT_RATE_CONTROL, &rc_param); if (ret != HD_OK) { printf("set_enc_rate_control = %d\r\n", ret); return ret; } } else if (enc_type == 2) { //--- HD_VIDEOENC_PARAM_OUT_ENC_PARAM --- video_out_param.codec_type = HD_CODEC_TYPE_JPEG; video_out_param.jpeg.retstart_interval = 0; video_out_param.jpeg.image_quality = 70; ret = hd_videoenc_set(video_enc_path, HD_VIDEOENC_PARAM_OUT_ENC_PARAM, &video_out_param); if (ret != HD_OK) { printf("set_enc_param_out = %d\r\n", ret); return ret; } } else { printf("not support enc_type\r\n"); return HD_ERR_NG; } } return ret; } /////////////////////////////////////////////////////////////////////////////// typedef struct _VIDEO_RECORD { // (1) HD_VIDEOCAP_SYSCAPS cap_syscaps; HD_PATH_ID cap_ctrl; HD_PATH_ID cap_path; HD_DIM cap_dim; HD_DIM proc_max_dim; // (2) HD_VIDEOPROC_SYSCAPS proc_syscaps; HD_PATH_ID proc_ctrl; HD_PATH_ID proc_path; HD_DIM proc_dim; HD_DIM enc_max_dim; HD_DIM enc_dim; // (3) HD_VIDEOENC_SYSCAPS enc_syscaps; HD_PATH_ID enc_path; // (3) user pull and push pthread_t snap_thread_id; UINT32 snap_exit; UINT32 flow_start; UINT32 do_snap; UINT32 shot_count; } VIDEO_RECORD; static HD_RESULT init_module(void) { HD_RESULT ret; if ((ret = hd_videocap_init()) != HD_OK) return ret; if ((ret = hd_videoproc_init()) != HD_OK) return ret; if ((ret = hd_videoenc_init()) != HD_OK) return ret; return HD_OK; } static HD_RESULT open_module(VIDEO_RECORD *p_stream, HD_DIM* p_proc_max_dim) { HD_RESULT ret; // set videocap config ret = set_cap_cfg(&p_stream->cap_ctrl); if (ret != HD_OK) { printf("set cap-cfg fail=%d\n", ret); return HD_ERR_NG; } // set videoproc config ret = set_proc_cfg(&p_stream->proc_ctrl, p_proc_max_dim); if (ret != HD_OK) { printf("set proc-cfg fail=%d\n", ret); return HD_ERR_NG; } if ((ret = hd_videocap_open(HD_VIDEOCAP_0_IN_0, HD_VIDEOCAP_0_OUT_0, &p_stream->cap_path)) != HD_OK) return ret; if ((ret = hd_videoproc_open(HD_VIDEOPROC_0_IN_0, HD_VIDEOPROC_0_OUT_0, &p_stream->proc_path)) != HD_OK) return ret; if ((ret = hd_videoenc_open(HD_VIDEOENC_0_IN_0, HD_VIDEOENC_0_OUT_0, &p_stream->enc_path)) != HD_OK) return ret; return HD_OK; } static HD_RESULT close_module(VIDEO_RECORD *p_stream) { HD_RESULT ret; if ((ret = hd_videocap_close(p_stream->cap_path)) != HD_OK) return ret; if ((ret = hd_videoproc_close(p_stream->proc_path)) != HD_OK) return ret; if ((ret = hd_videoenc_close(p_stream->enc_path)) != HD_OK) return ret; return HD_OK; } static HD_RESULT exit_module(void) { HD_RESULT ret; if ((ret = hd_videocap_uninit()) != HD_OK) return ret; if ((ret = hd_videoproc_uninit()) != HD_OK) return ret; if ((ret = hd_videoenc_uninit()) != HD_OK) return ret; return HD_OK; } static void *snapshot_thread(void *arg) { VIDEO_RECORD* p_stream0 = (VIDEO_RECORD *)arg; HD_RESULT ret = HD_OK; HD_VIDEOENC_BS data_pull; UINT32 j; HD_VIDEO_FRAME video_frame = {0}; UINT32 vir_addr_main; HD_VIDEOENC_BUFINFO phy_buf_main; char file_path_main[32] = {0}; FILE *f_out_main; #define PHY2VIRT_MAIN(pa) (vir_addr_main + (pa - phy_buf_main.buf_info.phy_addr)) //------ wait flow_start ------ while (p_stream0->flow_start == 0) sleep(1); // query physical address of bs buffer ( this can ONLY query after hd_videoenc_start() is called !! ) hd_videoenc_get(p_stream0->enc_path, HD_VIDEOENC_PARAM_BUFINFO, &phy_buf_main); // mmap for bs buffer (just mmap one time only, calculate offset to virtual address later) vir_addr_main = (UINT32)hd_common_mem_mmap(HD_COMMON_MEM_MEM_TYPE_CACHE, phy_buf_main.buf_info.phy_addr, phy_buf_main.buf_info.buf_size); if (vir_addr_main == 0) { printf("mmap error !!\r\n\r\n"); return 0; } printf("\r\nif you want to snapshot, enter \"s\" to trigger !!\r\n"); printf("\r\nif you want to stop, enter \"q\" to exit !!\r\n\r\n"); //--------- pull data test --------- while (p_stream0->snap_exit == 0) { if(p_stream0->do_snap) { p_stream0->do_snap = 0; printf("proc_pull ....\r\n"); ret = hd_videoproc_pull_out_buf(p_stream0->proc_path, &video_frame, 0); // 0 = non-blocking mode if (ret != HD_OK) { printf("proc_pull error=%d !!\r\n\r\n", ret); goto skip; } printf("enc_push ....\r\n"); ret = hd_videoenc_push_in_buf(p_stream0->enc_path, &video_frame, NULL, 0); // only support non-blocking mode now if (ret != HD_OK) { printf("enc_push error=%d !!\r\n\r\n", ret); goto skip; } printf("proc_release ....\r\n"); ret = hd_videoproc_release_out_buf(p_stream0->proc_path, &video_frame); if (ret != HD_OK) { printf("proc_release error=%d !!\r\n\r\n", ret); goto skip; } printf("enc_pull ....\r\n"); ret = hd_videoenc_pull_out_buf(p_stream0->enc_path, &data_pull, -1); // -1 = blocking mode if (ret != HD_OK) { printf("enc_pull error=%d !!\r\n\r\n", ret); goto skip; } snprintf(file_path_main, 32, "/mnt/sd/dump_bs_snap%lu.jpg", p_stream0->shot_count); printf("dump snapshot bitstream to file (%s) ....\r\n", file_path_main); //----- open output files ----- if ((f_out_main = fopen(file_path_main, "wb")) == NULL) { HD_VIDEOENC_ERR("open file (%s) fail....\r\n\r\n", file_path_main); goto skip; } for (j=0; j< data_pull.pack_num; j++) { UINT8 *ptr = (UINT8 *)PHY2VIRT_MAIN(data_pull.video_pack[j].phy_addr); UINT32 len = data_pull.video_pack[j].size; if (f_out_main) fwrite(ptr, 1, len, f_out_main); if (f_out_main) fflush(f_out_main); } printf("enc_release ....\r\n"); ret = hd_videoenc_release_out_buf(p_stream0->enc_path, &data_pull); if (ret != HD_OK) { printf("enc_release error=%d !!\r\n", ret); } // close output file fclose(f_out_main); printf("dump snapshot ok\r\n\r\n"); p_stream0->shot_count ++; } skip: sleep(1); //delay 1 ms } // mummap for bs buffer ret = hd_common_mem_munmap((void *)vir_addr_main, phy_buf_main.buf_info.buf_size); if (ret != HD_OK) { printf("mnumap error !!\r\n\r\n"); } return 0; } MAIN(argc, argv) { HD_RESULT ret; INT key; VIDEO_RECORD stream[1] = {0}; //0: main stream UINT32 enc_type = 0; HD_DIM main_dim; // always encode to JPEG enc_type = 2; // init hdal ret = hd_common_init(0); if (ret != HD_OK) { printf("common fail=%d\n", ret); goto exit; } // init memory ret = mem_init(); if (ret != HD_OK) { printf("mem fail=%d\n", ret); goto exit; } // init all modules ret = init_module(); if (ret != HD_OK) { printf("init fail=%d\n", ret); goto exit; } // open video_record modules (main) stream[0].proc_max_dim.w = VDO_SIZE_W; //assign by user stream[0].proc_max_dim.h = VDO_SIZE_H; //assign by user ret = open_module(&stream[0], &stream[0].proc_max_dim); if (ret != HD_OK) { printf("open fail=%d\n", ret); goto exit; } // get videocap capability ret = get_cap_caps(stream[0].cap_ctrl, &stream[0].cap_syscaps); if (ret != HD_OK) { printf("get cap-caps fail=%d\n", ret); goto exit; } // set videocap parameter stream[0].cap_dim.w = VDO_SIZE_W; //assign by user stream[0].cap_dim.h = VDO_SIZE_H; //assign by user ret = set_cap_param(stream[0].cap_path, &stream[0].cap_dim); if (ret != HD_OK) { printf("set cap fail=%d\n", ret); goto exit; } // assign parameter by program options main_dim.w = VDO_SIZE_W; main_dim.h = VDO_SIZE_H; // set videoproc parameter (main), this sample proc_path is not bind to enc_path, must config proc's out dim stream[0].proc_dim.w = main_dim.w; stream[0].proc_dim.h = main_dim.h; ret = set_proc_param(stream[0].proc_path, &stream[0].proc_dim); if (ret != HD_OK) { printf("set proc fail=%d\n", ret); goto exit; } // set videoenc config (main) stream[0].enc_max_dim.w = main_dim.w; stream[0].enc_max_dim.h = main_dim.h; ret = set_enc_cfg(stream[0].enc_path, &stream[0].enc_max_dim, 2 * 1024 * 1024); if (ret != HD_OK) { printf("set enc-cfg fail=%d\n", ret); goto exit; } // set videoenc parameter (main) stream[0].enc_dim.w = main_dim.w; stream[0].enc_dim.h = main_dim.h; ret = set_enc_param(stream[0].enc_path, &stream[0].enc_dim, enc_type, 2 * 1024 * 1024); if (ret != HD_OK) { printf("set enc fail=%d\n", ret); goto exit; } // bind video_record modules (main) hd_videocap_bind(HD_VIDEOCAP_0_OUT_0, HD_VIDEOPROC_0_IN_0); // create encode_thread (pull_out frame, push_in frame then pull_out bitstream) ret = pthread_create(&stream[0].snap_thread_id, NULL, snapshot_thread, (void *)stream); if (ret < 0) { printf("create encode thread failed"); goto exit; } // start video_record modules (main) hd_videocap_start(stream[0].cap_path); hd_videoproc_start(stream[0].proc_path); // just wait ae/awb stable for auto-test, if don't care, user can remove it sleep(1); hd_videoenc_start(stream[0].enc_path); // let encode_thread start to work stream[0].flow_start = 1; // query user key printf("Enter q to exit\n"); while (1) { key = GETCHAR(); if (key == 's') { stream[0].do_snap = 1; } if (key == 'q' || key == 0x3) { // let encode_thread stop loop and exit stream[0].snap_exit = 1; // quit program break; } #if (DEBUG_MENU == 1) if (key == 'd') { // enter debug menu hd_debug_run_menu(); printf("\r\nEnter q to exit, Enter d to debug\r\n"); } #endif } // stop video_record modules (main) hd_videocap_stop(stream[0].cap_path); hd_videoproc_stop(stream[0].proc_path); hd_videoenc_stop(stream[0].enc_path); // unbind video_record modules (main) hd_videocap_unbind(HD_VIDEOCAP_0_OUT_0); // destroy encode thread pthread_join(stream[0].snap_thread_id, NULL); exit: // close video_record modules (main) ret = close_module(&stream[0]); if (ret != HD_OK) { printf("close fail=%d\n", ret); } // uninit all modules ret = exit_module(); if (ret != HD_OK) { printf("exit fail=%d\n", ret); } // uninit memory ret = mem_exit(); if (ret != HD_OK) { printf("mem fail=%d\n", ret); } // uninit hdal ret = hd_common_uninit(); if (ret != HD_OK) { printf("common fail=%d\n", ret); } return 0; }