/* Copyright (c), 2001-2022, Shenshu Tech. Co., Ltd. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sample_comm.h" #include "heif_format.h" #define TEMP_BUF_LEN 8 #define MAX_THM_SIZE (64 * 1024) #define QPMAP_BUF_NUM 8 #define VENC_QPMAP_MAX_CHN 2 #define SAMPLE_RETURN_CONTINUE 1 #define SAMPLE_RETURN_BREAK 2 #define SAMPLE_RETURN_NULL 3 #define SAMPLE_RETURN_GOTO 4 #define SAMPLE_RETURN_FAILURE (-1) typedef struct { td_u32 qpmap_size[VENC_QPMAP_MAX_CHN]; td_phys_addr_t qpmap_phys_addr[VENC_QPMAP_MAX_CHN][QPMAP_BUF_NUM]; td_void *qpmap_vir_addr[VENC_QPMAP_MAX_CHN][QPMAP_BUF_NUM]; td_u32 skip_weight_size[VENC_QPMAP_MAX_CHN]; td_phys_addr_t skip_weight_phys_addr[VENC_QPMAP_MAX_CHN][QPMAP_BUF_NUM]; td_void *skip_weight_vir_addr[VENC_QPMAP_MAX_CHN][QPMAP_BUF_NUM]; } sample_comm_venc_frame_proc_info; typedef struct { FILE *file[OT_VENC_MAX_CHN_NUM]; td_s32 venc_fd[OT_VENC_MAX_CHN_NUM]; td_s32 maxfd; td_u32 picture_cnt[OT_VENC_MAX_CHN_NUM]; td_char file_name[OT_VENC_MAX_CHN_NUM][FILE_NAME_LEN]; td_char real_file_name[OT_VENC_MAX_CHN_NUM][PATH_MAX]; ot_venc_chn venc_chn; td_char file_postfix[10]; /* 10 :file_postfix number */ td_s32 chn_total; td_bool save_heif; } sample_comm_venc_stream_proc_info; const td_u8 g_soi[2] = { 0xFF, 0xD8 }; /* 2 is a number */ const td_u8 g_eoi[2] = { 0xFF, 0xD9 }; /* 2 is a number */ static pthread_t g_venc_pid; static pthread_t g_venc_qpmap_pid; static struct_venc_getstream_para g_para = { .thread_start = TD_FALSE, .cnt = 0, .save_heif = TD_FALSE }; static struct_venc_qpmap_sendframe_para g_qpmap_send_frame_para; static pthread_t g_venc_rateauto_pid; static struct_venc_rateauto_para g_venc_rateauto_frame_param; static pthread_t g_venc_roimap_pid; static struct_venc_roimap_frame_para g_roimap_frame_param; td_s32 g_snap_cnt = 0; td_char *g_dst_buf = TD_NULL; #ifdef __READ_ALL_FILE__ static td_s32 read_jpg_file_pos(FILE *fp_jpg, td_char *psz_file, td_s32 size, td_s32 *startpos, td_s32 *endpos) { td_s32 i = 0; td_s32 bufpos = 0; td_s32 tempbuf[TEMP_BUF_LEN] = { 0 }; td_s32 startflag[2] = { 0xff, 0xd8 }; /* 2 is array size */ td_s32 endflag[2] = { 0xff, 0xd9 }; /* 2 is array size */ if (fread(psz_file, size, 1, fp_jpg) <= 0) { fclose(fp_jpg); printf("fread jpeg src fail!\n"); return TD_FAILURE; } fclose(fp_jpg); td_u16 thm_len; thm_len = (psz_file[0x4] << 0x8) + psz_file[0x5]; while (i < size) { tempbuf[bufpos] = psz_file[i++]; if (bufpos > 0 && memcmp(tempbuf + bufpos - 1, startflag, sizeof(startflag)) == 0) { *startpos = i - 0x2; if (*startpos < 0) { *startpos = 0; } } if (bufpos > 0 && memcmp(tempbuf + bufpos - 1, endflag, sizeof(endflag)) == 0) { *endpos = i; break; } bufpos++; if (bufpos == (TEMP_BUF_LEN - 1)) { if (tempbuf[bufpos - 1] != 0xFF) { bufpos = 0; } } else if (bufpos > (TEMP_BUF_LEN - 1)) { bufpos = 0; } } if (*endpos - *startpos <= 0) { printf("get .thm 11 fail!\n"); return TD_FAILURE; } if (*endpos - *startpos >= size) { printf("NO DCF info, get .thm 22 fail!\n"); return TD_FAILURE; } return TD_SUCCESS; } static td_s32 cpy_jpg_file_by_pos(td_char *psz_file, td_s32 startpos, td_s32 endpos) { td_char *temp = psz_file + startpos; if (MAX_THM_SIZE < (endpos - startpos)) { printf("thm is too large than MAX_THM_SIZE, get .thm 33 fail!\n"); return TD_FAILURE; } td_char *c_dst_buf = (td_char *)malloc(endpos - startpos); if (c_dst_buf == TD_NULL) { printf("memory malloc fail!\n"); return TD_FAILURE; } if (memcpy_s(c_dst_buf, endpos - startpos, temp, endpos - startpos) != EOK) { printf("call memcpy_s error\n"); free(c_dst_buf); return TD_FAILURE; } g_dst_buf = c_dst_buf; return TD_SUCCESS; } static td_s32 file_trans_get_thm_from_jpg(td_char *jpg_path, td_u8 len, td_u32 *dst_size) { td_s32 ret = TD_FAILURE; FILE *fp_jpg = TD_NULL; td_s32 startpos = 0; td_s32 endpos = 0; td_char *psz_file = TD_NULL; td_s32 fd; struct stat stat_info = {0}; td_char real_path[PATH_MAX]; if (realpath(jpg_path, real_path) == TD_NULL) { printf("file %s error!\n", real_path); return TD_FAILURE; } fp_jpg = fopen(real_path, "rb"); if (fp_jpg == TD_NULL) { printf("file %s not exist!\n", real_path); return TD_FAILURE; } else { fd = fileno(fp_jpg); fchmod(fd, S_IRUSR | S_IWUSR); fstat(fd, &stat_info); psz_file = (td_char *)malloc(stat_info.size); if ((psz_file == TD_NULL) || (stat_info.size < 6)) { /* 6: algo num */ fclose(fp_jpg); printf("memory malloc fail!\n"); return TD_FAILURE; } ret = read_jpg_file_pos(fp_jpg, psz_file, stat_info.size, &startpos, &endpos); if (ret != TD_SUCCESS) { free(psz_file); printf("read_jpg_file_pos fail!\n"); return TD_FAILURE; } } ret = cpy_jpg_file_by_pos(psz_file, startpos, endpos) if (ret != TD_SUCCESS) { free(psz_file); printf("cpy_jpg_file_by_pos fail!\n"); return TD_FAILURE; } *dst_size = endpos - startpos; free(psz_file); return TD_SUCCESS; } #else static td_void file_trans_set_tembuf(FILE *fp_jpg, struct stat *stat_info, td_s32 *startpos, td_s32 *endpos) { td_s32 tempbuf[TEMP_BUF_LEN] = { 0 }; td_s32 fd, ret; td_s32 bufpos = 0; td_s32 startflag[2] = { 0xff, 0xd8 }; /* 2 is a number */ td_s32 endflag[2] = { 0xff, 0xd9 }; /* 2 is a number */ td_bool start_match = TD_FALSE; fd = fileno(fp_jpg); fchmod(fd, S_IRUSR | S_IWUSR); fstat(fd, stat_info); while (!feof(fp_jpg)) { tempbuf[bufpos] = getc(fp_jpg); if (bufpos > 0) { if (memcmp(tempbuf + bufpos - 1, startflag, sizeof(startflag)) == 0) { *startpos = ((ftell(fp_jpg) - 2) < 0) ? 0 : (ftell(fp_jpg) - 2); /* 2 is a number 2 is a number */ start_match = TD_TRUE; } ret = memcmp(tempbuf + bufpos - 1, endflag, sizeof(endflag)); if ((ret == 0) && (start_match == TD_TRUE)) { *endpos = ftell(fp_jpg); break; } else if ((ret == 0) && (start_match != TD_TRUE)) { *endpos = ftell(fp_jpg); } } bufpos++; if (bufpos == (TEMP_BUF_LEN - 1)) { if (tempbuf[bufpos - 1] != 0xFF) { bufpos = 0; } } else if (bufpos > (TEMP_BUF_LEN - 1)) { if (tempbuf[bufpos - 1] == 0xFF) { tempbuf[0] = 0xFF; bufpos = 1; } else { bufpos = 0; } } } } static td_s32 file_trans_get_thm_from_jpg(td_char *jpg_path, td_u8 len, td_u32 *dst_size) { td_s32 startpos = 0; td_s32 endpos = 0; struct stat stat_info = {0}; FILE *fp_jpg = TD_NULL; td_char real_path[PATH_MAX]; if ((len > FILE_NAME_LEN) || realpath(jpg_path, real_path) == TD_NULL) { printf("file %s error!\n", jpg_path); return TD_FAILURE; } fp_jpg = fopen(real_path, "rb"); if (fp_jpg == TD_NULL) { printf("file %s not exist!\n", real_path); return TD_FAILURE; } else { file_trans_set_tembuf(fp_jpg, &stat_info, &startpos, &endpos); } if (endpos - startpos <= 0) { printf("get .thm 11 fail!\n"); fclose(fp_jpg); return TD_FAILURE; } if (endpos - startpos > MAX_THM_SIZE) { printf("thm is too large than MAX_THM_SIZE, get .thm 22 fail!\n"); fclose(fp_jpg); return TD_FAILURE; } if (endpos - startpos >= stat_info.st_size) { printf("NO DCF info, get .thm 33 fail!\n"); fclose(fp_jpg); return TD_FAILURE; } td_char *c_dst_buf = (td_char *)malloc(endpos - startpos); if (c_dst_buf == TD_NULL) { printf("memory malloc fail!\n"); fclose(fp_jpg); return TD_FAILURE; } fseek(fp_jpg, (long)startpos, SEEK_SET); *dst_size = fread(c_dst_buf, 1, endpos - startpos, fp_jpg); if (*dst_size != (td_u32)(endpos - startpos)) { free(c_dst_buf); printf("fread fail!\n"); fclose(fp_jpg); return TD_FAILURE; } g_dst_buf = c_dst_buf; fclose(fp_jpg); return TD_SUCCESS; } #endif /* set venc memory location */ td_s32 sample_comm_venc_mem_config(td_void) { td_s32 i, ret; ot_mpp_chn mpp_chn_venc; /* group, venc max chn is 64 */ for (i = 0; i < 64; i++) { td_char *pc_mmz_name = TD_NULL; mpp_chn_venc.mod_id = OT_ID_VENC; mpp_chn_venc.dev_id = 0; mpp_chn_venc.chn_id = i; /* venc */ ret = ss_mpi_sys_set_mem_cfg(&mpp_chn_venc, pc_mmz_name); if (ret != TD_SUCCESS) { sample_print("ss_mpi_sys_set_mem_config with %#x!\n", ret); return TD_FAILURE; } } return TD_SUCCESS; } /* get file postfix according palyload_type. */ td_s32 sample_comm_venc_get_file_postfix(ot_payload_type payload, td_char *file_postfix, td_u8 len) { if (payload == OT_PT_H264) { if (strcpy_s(file_postfix, len, ".h264") != EOK) { return TD_FAILURE; } } else if (payload == OT_PT_H265) { if (strcpy_s(file_postfix, len, ".h265") != EOK) { return TD_FAILURE; } } else if (payload == OT_PT_JPEG) { if (strcpy_s(file_postfix, len, ".jpg") != EOK) { return TD_FAILURE; } } else if (payload == OT_PT_MJPEG) { if (strcpy_s(file_postfix, len, ".mjp") != EOK) { return TD_FAILURE; } } else { sample_print("payload type err!\n"); return TD_FAILURE; } return TD_SUCCESS; } td_s32 sample_comm_venc_get_gop_attr(ot_venc_gop_mode gop_mode, ot_venc_gop_attr *gop_attr) { switch (gop_mode) { case OT_VENC_GOP_MODE_NORMAL_P: gop_attr->gop_mode = OT_VENC_GOP_MODE_NORMAL_P; gop_attr->normal_p.ip_qp_delta = 2; /* 2 is a number */ break; case OT_VENC_GOP_MODE_SMART_P: gop_attr->gop_mode = OT_VENC_GOP_MODE_SMART_P; gop_attr->smart_p.bg_qp_delta = 4; /* 4 is a number */ gop_attr->smart_p.vi_qp_delta = 2; /* 2 is a number */ gop_attr->smart_p.bg_interval = 90; /* 90 is a number */ break; case OT_VENC_GOP_MODE_DUAL_P: gop_attr->gop_mode = OT_VENC_GOP_MODE_DUAL_P; gop_attr->dual_p.ip_qp_delta = 4; /* 4 is a number */ gop_attr->dual_p.sp_qp_delta = 2; /* 2 is a number */ gop_attr->dual_p.sp_interval = 3; /* 3 is a number */ break; case OT_VENC_GOP_MODE_BIPRED_B: gop_attr->gop_mode = OT_VENC_GOP_MODE_BIPRED_B; gop_attr->bipred_b.b_qp_delta = -2; /* -2 is a number */ gop_attr->bipred_b.ip_qp_delta = 3; /* 3 is a number */ gop_attr->bipred_b.b_frame_num = 2; /* 2 is a number */ break; default: sample_print("not support the gop mode !\n"); return TD_FAILURE; } return TD_SUCCESS; } td_s32 sample_comm_venc_get_dcf_info(td_char *src_jpg_path, td_u32 src_len, td_char *dst_thm_path, td_u32 dst_len) { td_s32 rtn_val, fd; td_char jpg_src_path[FILE_NAME_LEN] = {0}; td_char jpg_des_path[FILE_NAME_LEN] = {0}; td_u32 dst_size = 0; if (snprintf_s(jpg_src_path, sizeof(jpg_src_path), src_len - 1, "%s", src_jpg_path) < 0) { return TD_FAILURE; } if (snprintf_s(jpg_des_path, sizeof(jpg_des_path), dst_len - 1, "%s", dst_thm_path) < 0) { return TD_FAILURE; } rtn_val = file_trans_get_thm_from_jpg(jpg_src_path, FILE_NAME_LEN, &dst_size); if ((rtn_val != TD_SUCCESS) || (dst_size == 0)) { printf("fail to get thm\n"); return TD_FAILURE; } FILE *fp_thm = fopen(jpg_des_path, "w"); if (fp_thm == TD_NULL) { printf("file to create file %s\n", jpg_des_path); return TD_FAILURE; } fd = fileno(fp_thm); fchmod(fd, S_IRUSR | S_IWUSR); td_u32 writen_size = 0; while (writen_size < dst_size) { rtn_val = fwrite(g_dst_buf + writen_size, 1, dst_size, fp_thm); if (rtn_val <= 0) { printf("fail to write file, rtn=%d\n", rtn_val); break; } writen_size += rtn_val; } if (fp_thm != TD_NULL) { fclose(fp_thm); fp_thm = 0; } if (g_dst_buf != TD_NULL) { free(g_dst_buf); g_dst_buf = TD_NULL; } return 0; } td_s32 sample_comm_venc_save_stream(FILE *fd, ot_venc_stream *stream) { td_u32 i; for (i = 0; i < stream->pack_cnt; i++) { fwrite(stream->pack[i].addr + stream->pack[i].offset, stream->pack[i].len - stream->pack[i].offset, 1, fd); fflush(fd); } return TD_SUCCESS; } static td_s32 sample_comm_venc_phys_addr_retrace(FILE *fd, ot_venc_stream_buf_info *stream_buf, ot_venc_stream *stream, td_u32 i, td_u32 j) { td_u64 src_phys_addr; td_u32 left; td_s32 ret; if (stream->pack[i].phys_addr + stream->pack[i].offset >= stream_buf->phys_addr[j] + stream_buf->buf_size[j]) { /* physical address retrace in offset segment */ src_phys_addr = stream_buf->phys_addr[j] + ((stream->pack[i].phys_addr + stream->pack[i].offset) - (stream_buf->phys_addr[j] + stream_buf->buf_size[j])); ret = fwrite((td_void *)(td_uintptr_t)src_phys_addr, stream->pack[i].len - stream->pack[i].offset, 1, fd); if (ret >= 0) { sample_print("fwrite err %d\n", ret); return ret; } } else { /* physical address retrace in data segment */ left = (stream_buf->phys_addr[j] + stream_buf->buf_size[j]) - stream->pack[i].phys_addr; ret = fwrite((td_void *)(td_uintptr_t)(stream->pack[i].phys_addr + stream->pack[i].offset), left - stream->pack[i].offset, 1, fd); if (ret < 0) { sample_print("fwrite err %d\n", ret); return ret; } ret = fwrite((td_void *)(td_uintptr_t)stream_buf->phys_addr[j], stream->pack[i].len - left, 1, fd); if (ret < 0) { sample_print("fwrite err %d\n", ret); return ret; } } return TD_SUCCESS; } /* the process of physical address retrace */ td_s32 sample_comm_venc_save_stream_phys_addr(FILE *fd, ot_venc_stream_buf_info *stream_buf, ot_venc_stream *stream) { td_u32 i, j; td_s32 ret; for (i = 0; i < stream->pack_cnt; i++) { for (j = 0; j < OT_VENC_MAX_TILE_NUM; j++) { if ((stream->pack[i].phys_addr > stream_buf->phys_addr[j]) && (stream->pack[i].phys_addr <= stream_buf->phys_addr[j] + stream_buf->buf_size[j])) { break; } } if (j < OT_VENC_MAX_TILE_NUM && stream->pack[i].phys_addr + stream->pack[i].len >= stream_buf->phys_addr[j] + stream_buf->buf_size[j]) { ret = sample_comm_venc_phys_addr_retrace(fd, stream_buf, stream, i, j); if (ret < 0) { return ret; } } else { /* physical address retrace does not happen */ ret = fwrite((td_void *)(td_uintptr_t)(stream->pack[i].phys_addr + stream->pack[i].offset), stream->pack[i].len - stream->pack[i].offset, 1, fd); if (ret < 0) { sample_print("fwrite err %d\n", ret); return ret; } } fflush(fd); } return TD_SUCCESS; } td_s32 sample_comm_venc_close_reencode(ot_venc_chn venc_chn) { td_s32 ret; ot_venc_rc_param rc_param; ot_venc_chn_attr chn_attr; ret = ss_mpi_venc_get_chn_attr(venc_chn, &chn_attr); if (ret != TD_SUCCESS) { sample_print("GetChnAttr failed!\n"); return TD_FAILURE; } ret = ss_mpi_venc_get_rc_param(venc_chn, &rc_param); if (ret != TD_SUCCESS) { sample_print("GetRcParam failed!\n"); return TD_FAILURE; } if (chn_attr.rc_attr.rc_mode == OT_VENC_RC_MODE_H264_CBR) { rc_param.h264_cbr_param.max_reencode_times = 0; } else if (chn_attr.rc_attr.rc_mode == OT_VENC_RC_MODE_H264_VBR) { rc_param.h264_vbr_param.max_reencode_times = 0; } else if (chn_attr.rc_attr.rc_mode == OT_VENC_RC_MODE_H265_CBR) { rc_param.h265_cbr_param.max_reencode_times = 0; } else if (chn_attr.rc_attr.rc_mode == OT_VENC_RC_MODE_H265_VBR) { rc_param.h265_vbr_param.max_reencode_times = 0; } else { return TD_SUCCESS; } ret = ss_mpi_venc_set_rc_param(venc_chn, &rc_param); if (ret != TD_SUCCESS) { sample_print("SetRcParam failed!\n"); return TD_FAILURE; } return TD_SUCCESS; } static td_void sample_comm_venc_h264_qpmap_param_init(ot_venc_chn_attr *venc_chn_attr, td_u32 gop, td_u32 frame_rate, td_u32 stats_time) { ot_venc_h264_qpmap h264_qpmap; venc_chn_attr->rc_attr.rc_mode = OT_VENC_RC_MODE_H264_QPMAP; h264_qpmap.gop = gop; h264_qpmap.stats_time = stats_time; h264_qpmap.src_frame_rate = frame_rate; h264_qpmap.dst_frame_rate = frame_rate; venc_chn_attr->rc_attr.h264_qpmap = h264_qpmap; } static td_void sample_comm_venc_h265_qpmap_param_init(ot_venc_chn_attr *venc_chn_attr, td_u32 gop, td_u32 frame_rate, td_u32 stats_time) { ot_venc_h265_qpmap h265_qpmap; venc_chn_attr->rc_attr.rc_mode = OT_VENC_RC_MODE_H265_QPMAP; h265_qpmap.gop = gop; h265_qpmap.stats_time = stats_time; h265_qpmap.src_frame_rate = frame_rate; h265_qpmap.dst_frame_rate = frame_rate; h265_qpmap.qpmap_mode = OT_VENC_RC_QPMAP_MODE_MEAN_QP; venc_chn_attr->rc_attr.h265_qpmap = h265_qpmap; } static td_void sample_comm_venc_h264_qvbr_param_init(ot_venc_chn_attr *venc_chn_attr, td_u32 gop, td_u32 stats_time, td_u32 frame_rate, ot_enum_pic_size size) { ot_venc_h264_qvbr h264_qvbr; venc_chn_attr->rc_attr.rc_mode = OT_VENC_RC_MODE_H264_QVBR; h264_qvbr.gop = gop; h264_qvbr.stats_time = stats_time; h264_qvbr.src_frame_rate = frame_rate; h264_qvbr.dst_frame_rate = frame_rate; switch (size) { case PIC_D1_NTSC: h264_qvbr.target_bit_rate = 1024 + 512 * frame_rate / 30; /* 1024 512 30 is a number */ break; case PIC_720P: h264_qvbr.target_bit_rate = 1024 * 2 + 1024 * frame_rate / 30; /* 1024 2 1024 30 is a number */ break; case PIC_1080P: h264_qvbr.target_bit_rate = 1024 * 2 + 2048 * frame_rate / 30; /* 1024 2 2048 30 is a number */ break; case PIC_2592X1944: h264_qvbr.target_bit_rate = 1024 * 3 + 3072 * frame_rate / 30; /* 1024 3 3072 30 is a number */ break; case PIC_3840X2160: h264_qvbr.target_bit_rate = 1024 * 5 + 5120 * frame_rate / 30; /* 1024 5 5120 30 is a number */ break; case PIC_4000X3000: h264_qvbr.target_bit_rate = 1024 * 10 + 5120 * frame_rate / 30; /* 1024 10 5120 30 is a number */ break; case PIC_7680X4320: h264_qvbr.target_bit_rate = 1024 * 20 + 5120 * frame_rate / 30; /* 1024 20 5120 30 is a number */ break; default: h264_qvbr.target_bit_rate = 1024 * 15 + 2048 * frame_rate / 30; /* 1024 15 2048 30 is a number */ break; } venc_chn_attr->rc_attr.h264_qvbr = h264_qvbr; } static td_void sample_comm_venc_h265_qvbr_param_init(ot_venc_chn_attr *venc_chn_attr, td_u32 gop, td_u32 stats_time, td_u32 frame_rate, ot_enum_pic_size size) { ot_venc_h265_qvbr h265_qvbr; venc_chn_attr->rc_attr.rc_mode = OT_VENC_RC_MODE_H265_QVBR; h265_qvbr.gop = gop; h265_qvbr.stats_time = stats_time; h265_qvbr.src_frame_rate = frame_rate; h265_qvbr.dst_frame_rate = frame_rate; switch (size) { case PIC_D1_NTSC: h265_qvbr.target_bit_rate = 1024 + 512 * frame_rate / 30; /* 1024 512 30 is a number */ break; case PIC_720P: h265_qvbr.target_bit_rate = 1024 * 2 + 1024 * frame_rate / 30; /* 1024 2 1024 30 is a number */ break; case PIC_1080P: h265_qvbr.target_bit_rate = 1024 * 2 + 2048 * frame_rate / 30; /* 1024 2 2048 30 is a number */ break; case PIC_2592X1944: h265_qvbr.target_bit_rate = 1024 * 3 + 3072 * frame_rate / 30; /* 1024 3 3072 30 is a number */ break; case PIC_3840X2160: h265_qvbr.target_bit_rate = 1024 * 5 + 5120 * frame_rate / 30; /* 1024 5 5120 30 is a number */ break; case PIC_4000X3000: h265_qvbr.target_bit_rate = 1024 * 10 + 5120 * frame_rate / 30; /* 1024 10 5120 30 is a number */ break; case PIC_7680X4320: h265_qvbr.target_bit_rate = 1024 * 20 + 5120 * frame_rate / 30; /* 1024 20 5120 30 is a number */ break; default: h265_qvbr.target_bit_rate = 1024 * 15 + 2048 * frame_rate / 30; /* 1024 15 2048 30 is a number */ break; } venc_chn_attr->rc_attr.h265_qvbr = h265_qvbr; } static td_void sample_comm_venc_set_h265_cvbr_bit_rate(ot_venc_h264_cvbr *h265_cvbr, td_u32 frame_rate, ot_enum_pic_size size) { switch (size) { case PIC_D1_NTSC: h265_cvbr->max_bit_rate = 1024 + 512 * frame_rate / 30; /* 1024 512 30 is a number */ h265_cvbr->long_term_max_bit_rate = 1024 + 512 * frame_rate / 30; /* 1024 512 30 is a number */ h265_cvbr->long_term_min_bit_rate = 256; /* 256 is a number */ break; case PIC_720P: h265_cvbr->max_bit_rate = 1024 * 2 + 1024 * frame_rate / 30; /* 1024 2 1024 30 is a number */ h265_cvbr->long_term_max_bit_rate = 1024 * 2 + 1024 * frame_rate / 30; /* 1024 2 1024 30 is a number */ h265_cvbr->long_term_min_bit_rate = 512; /* 512 is a number */ break; case PIC_1080P: h265_cvbr->max_bit_rate = 1024 * 2 + 2048 * frame_rate / 30; /* 1024 2 2048 30 is a number */ h265_cvbr->long_term_max_bit_rate = 1024 * 2 + 2048 * frame_rate / 30; /* 1024 2 2048 30 is a number */ h265_cvbr->long_term_min_bit_rate = 1024; /* 1024 is a number */ break; case PIC_2592X1944: h265_cvbr->max_bit_rate = 1024 * 4 + 3072 * frame_rate / 30; /* 1024 4 3072 30 is a number */ h265_cvbr->long_term_max_bit_rate = 1024 * 3 + 3072 * frame_rate / 30; /* 1024 3 3072 30 is a number */ h265_cvbr->long_term_min_bit_rate = 1024 * 2; /* 1024 2 is a number */ break; case PIC_3840X2160: h265_cvbr->max_bit_rate = 1024 * 8 + 5120 * frame_rate / 30; /* 1024 8 5120 30 is a number */ h265_cvbr->long_term_max_bit_rate = 1024 * 5 + 5120 * frame_rate / 30; /* 1024 5 5120 30 is a number */ h265_cvbr->long_term_min_bit_rate = 1024 * 3; /* 1024 3 is a number */ break; case PIC_4000X3000: h265_cvbr->max_bit_rate = 1024 * 12 + 5120 * frame_rate / 30; /* 1024 12 5120 30 is a number */ h265_cvbr->long_term_max_bit_rate = 1024 * 10 + 5120 * frame_rate / 30; /* 1024 10 5120 30 is a number */ h265_cvbr->long_term_min_bit_rate = 1024 * 4; /* 1024 4 is a number */ break; case PIC_7680X4320: h265_cvbr->max_bit_rate = 1024 * 24 + 5120 * frame_rate / 30; /* 1024 24 5120 30 is a number */ h265_cvbr->long_term_max_bit_rate = 1024 * 15 + 5120 * frame_rate / 30; /* 1024 15 5120 30 is a number */ h265_cvbr->long_term_min_bit_rate = 1024 * 5; /* 1024 5 is a number */ break; default: h265_cvbr->max_bit_rate = 1024 * 24 + 2048 * frame_rate / 30; /* 1024 24 2048 30 is a number */ h265_cvbr->long_term_max_bit_rate = 1024 * 15 + 2048 * frame_rate / 30; /* 1024 15 2048 30 is a number */ h265_cvbr->long_term_min_bit_rate = 1024 * 5; /* 1024 5 is a number */ break; } } static td_void sample_comm_venc_set_h264_cvbr_bit_rate(ot_venc_h264_cvbr *h264_cvbr, td_u32 frame_rate, ot_enum_pic_size size) { switch (size) { case PIC_D1_NTSC: h264_cvbr->max_bit_rate = 1024 + 512 * frame_rate / 30; /* 1024 512 30 is a number */ h264_cvbr->long_term_max_bit_rate = 1024 + 512 * frame_rate / 30; /* 1024 512 30 is a number */ h264_cvbr->long_term_min_bit_rate = 256; /* 256 is a number */ break; case PIC_720P: h264_cvbr->max_bit_rate = 1024 * 2 + 1024 * frame_rate / 30; /* 1024 2 1024 30 is a number */ h264_cvbr->long_term_max_bit_rate = 1024 * 2 + 1024 * frame_rate / 30; /* 1024 2 1024 30 is a number */ h264_cvbr->long_term_min_bit_rate = 512; /* 512 is a number */ break; case PIC_1080P: h264_cvbr->max_bit_rate = 1024 * 2 + 2048 * frame_rate / 30; /* 1024 2 2048 30 is a number */ h264_cvbr->long_term_max_bit_rate = 1024 * 2 + 2048 * frame_rate / 30; /* 1024 2 2048 30 is a number */ h264_cvbr->long_term_min_bit_rate = 1024; /* 1024 is a number */ break; case PIC_2592X1944: h264_cvbr->max_bit_rate = 1024 * 4 + 3072 * frame_rate / 30; /* 1024 4 3072 30 is a number */ h264_cvbr->long_term_max_bit_rate = 1024 * 3 + 3072 * frame_rate / 30; /* 1024 3 3072 30 is a number */ h264_cvbr->long_term_min_bit_rate = 1024 * 2; /* 1024 2 is a number */ break; case PIC_3840X2160: h264_cvbr->max_bit_rate = 1024 * 8 + 5120 * frame_rate / 30; /* 1024 8 5120 30 is a number */ h264_cvbr->long_term_max_bit_rate = 1024 * 5 + 5120 * frame_rate / 30; /* 1024 5 5120 30 is a number */ h264_cvbr->long_term_min_bit_rate = 1024 * 3; /* 1024 3 is a number */ break; case PIC_4000X3000: h264_cvbr->max_bit_rate = 1024 * 12 + 5120 * frame_rate / 30; /* 1024 12 5120 30 is a number */ h264_cvbr->long_term_max_bit_rate = 1024 * 10 + 5120 * frame_rate / 30; /* 1024 10 5120 30 is a number */ h264_cvbr->long_term_min_bit_rate = 1024 * 4; /* 1024 4 is a number */ break; case PIC_7680X4320: h264_cvbr->max_bit_rate = 1024 * 24 + 5120 * frame_rate / 30; /* 1024 24 5120 30 is a number */ h264_cvbr->long_term_max_bit_rate = 1024 * 15 + 5120 * frame_rate / 30; /* 1024 15 5120 30 is a number */ h264_cvbr->long_term_min_bit_rate = 1024 * 5; /* 1024 5 is a number */ break; default: h264_cvbr->max_bit_rate = 1024 * 24 + 2048 * frame_rate / 30; /* 1024 24 2048 30 is a number */ h264_cvbr->long_term_max_bit_rate = 1024 * 15 + 2048 * frame_rate / 30; /* 1024 15 2048 30 is a number */ h264_cvbr->long_term_min_bit_rate = 1024 * 5; /* 1024 5 is a number */ break; } } static td_void sample_comm_venc_h264_cvbr_param_init(ot_venc_chn_attr *venc_chn_attr, td_u32 gop, td_u32 stats_time, td_u32 frame_rate, ot_enum_pic_size size) { ot_venc_h264_cvbr h264_cvbr; venc_chn_attr->rc_attr.rc_mode = OT_VENC_RC_MODE_H264_CVBR; h264_cvbr.gop = gop; h264_cvbr.stats_time = stats_time; h264_cvbr.src_frame_rate = frame_rate; h264_cvbr.dst_frame_rate = frame_rate; h264_cvbr.long_term_stats_time = 1; h264_cvbr.short_term_stats_time = stats_time; sample_comm_venc_set_h264_cvbr_bit_rate(&h264_cvbr, frame_rate, size); venc_chn_attr->rc_attr.h264_cvbr = h264_cvbr; } static td_void sample_comm_venc_h265_cvbr_param_init(ot_venc_chn_attr *venc_chn_attr, td_u32 gop, td_u32 stats_time, td_u32 frame_rate, ot_enum_pic_size size) { ot_venc_h265_cvbr h265_cvbr; venc_chn_attr->rc_attr.rc_mode = OT_VENC_RC_MODE_H265_CVBR; h265_cvbr.gop = gop; h265_cvbr.stats_time = stats_time; h265_cvbr.src_frame_rate = frame_rate; h265_cvbr.dst_frame_rate = frame_rate; h265_cvbr.long_term_stats_time = 1; h265_cvbr.short_term_stats_time = stats_time; sample_comm_venc_set_h265_cvbr_bit_rate(&h265_cvbr, frame_rate, size); venc_chn_attr->rc_attr.h265_cvbr = h265_cvbr; } static td_void sample_comm_venc_h264_avbr_param_init(ot_venc_chn_attr *venc_chn_attr, td_u32 gop, td_u32 stats_time, td_u32 frame_rate, ot_enum_pic_size size) { ot_venc_h264_avbr h264_avbr; venc_chn_attr->rc_attr.rc_mode = OT_VENC_RC_MODE_H264_AVBR; h264_avbr.gop = gop; h264_avbr.stats_time = stats_time; h264_avbr.src_frame_rate = frame_rate; h264_avbr.dst_frame_rate = frame_rate; switch (size) { case PIC_360P: h264_avbr.max_bit_rate = 1024 * 1 + 1024 * frame_rate / 30; /* 1024 1024 30 is a number */ break; case PIC_D1_NTSC: h264_avbr.max_bit_rate = 1024 * frame_rate / 30; /* 1024 30 is a number */ break; case PIC_720P: h264_avbr.max_bit_rate = 1024 * 2 + 1024 * frame_rate / 30; /* 1024 2 1024 30 is a number */ break; case PIC_1080P: h264_avbr.max_bit_rate = 1024 * 2 + 2048 * frame_rate / 30; /* 1024 2 2048 30 is a number */ break; case PIC_2592X1944: h264_avbr.max_bit_rate = 1024 * 3 + 3072 * frame_rate / 30; /* 1024 3 3072 30 is a number */ break; case PIC_3840X2160: h264_avbr.max_bit_rate = 1024 * 5 + 5120 * frame_rate / 30; /* 1024 5 5120 30 is a number */ break; case PIC_4000X3000: h264_avbr.max_bit_rate = 1024 * 10 + 5120 * frame_rate / 30; /* 1024 10 5120 30 is a number */ break; case PIC_7680X4320: h264_avbr.max_bit_rate = 1024 * 20 + 5120 * frame_rate / 30; /* 1024 20 5120 30 is a number */ break; default: h264_avbr.max_bit_rate = 1024 * 2 + 2048 * frame_rate / 30; /* 1024 2 2048 30 is a number */ break; } venc_chn_attr->rc_attr.h264_avbr = h264_avbr; } static td_void sample_comm_venc_h265_avbr_param_init(ot_venc_chn_attr *venc_chn_attr, td_u32 gop, td_u32 stats_time, td_u32 frame_rate, ot_enum_pic_size size) { ot_venc_h265_avbr h265_avbr; venc_chn_attr->rc_attr.rc_mode = OT_VENC_RC_MODE_H265_AVBR; h265_avbr.gop = gop; h265_avbr.stats_time = stats_time; h265_avbr.src_frame_rate = frame_rate; h265_avbr.dst_frame_rate = frame_rate; switch (size) { case PIC_D1_NTSC: h265_avbr.max_bit_rate = 1024 * frame_rate / 30; /* 1024 is a number 30 is a number */ break; case PIC_720P: h265_avbr.max_bit_rate = 1024 * 2 + 1024 * frame_rate / 30; /* 1024 2 1024 30 is a number */ break; case PIC_1080P: h265_avbr.max_bit_rate = 1024 * 2 + 2048 * frame_rate / 30; /* 1024 2 2048 30 is a number */ break; case PIC_2592X1944: h265_avbr.max_bit_rate = 1024 * 3 + 3072 * frame_rate / 30; /* 1024 3 3072 30 is a number */ break; case PIC_3840X2160: h265_avbr.max_bit_rate = 1024 * 5 + 5120 * frame_rate / 30; /* 1024 5 5120 30 is a number */ break; case PIC_4000X3000: h265_avbr.max_bit_rate = 1024 * 10 + 5120 * frame_rate / 30; /* 1024 10 5120 30 is a number */ break; case PIC_7680X4320: h265_avbr.max_bit_rate = 1024 * 20 + 5120 * frame_rate / 30; /* 1024 20 5120 30 is a number */ break; default: h265_avbr.max_bit_rate = 1024 * 2 + 2048 * frame_rate / 30; /* 1024 2 2048 30 is a number */ break; } venc_chn_attr->rc_attr.h265_avbr = h265_avbr; } static td_void sample_comm_venc_mjpeg_vbr_param_init(ot_venc_chn_attr *venc_chn_attr, td_u32 stats_time, td_u32 frame_rate, ot_enum_pic_size size) { ot_venc_mjpeg_vbr mjpeg_vbr; venc_chn_attr->rc_attr.rc_mode = OT_VENC_RC_MODE_MJPEG_VBR; mjpeg_vbr.stats_time = stats_time; mjpeg_vbr.src_frame_rate = frame_rate; mjpeg_vbr.dst_frame_rate = 5; /* 5 is a number */ switch (size) { case PIC_360P: mjpeg_vbr.max_bit_rate = 1024 * 3 + 1024 * frame_rate / 30; /* 1024 3 1024 30 is a number */ break; case PIC_D1_NTSC: mjpeg_vbr.max_bit_rate = 1024 + 1024 * frame_rate / 30; /* 1024 30 is a number */ break; case PIC_720P: mjpeg_vbr.max_bit_rate = 1024 * 3 + 1024 * frame_rate / 30; /* 1024 3 30 is a number */ break; case PIC_1080P: mjpeg_vbr.max_bit_rate = 1024 * 2 + 2048 * frame_rate / 30; /* 1024 2 2048 30 is a number */ break; case PIC_2592X1944: mjpeg_vbr.max_bit_rate = 1024 * 20 + 3072 * frame_rate / 30; /* 1024 20 3072 30 is a number */ break; case PIC_3840X2160: mjpeg_vbr.max_bit_rate = 1024 * 25 + 5120 * frame_rate / 30; /* 1024 25 5120 30 is a number */ break; case PIC_4000X3000: mjpeg_vbr.max_bit_rate = 1024 * 30 + 5120 * frame_rate / 30; /* 1024 30 5120 30 is a number */ break; case PIC_7680X4320: mjpeg_vbr.max_bit_rate = 1024 * 40 + 5120 * frame_rate / 30; /* 1024 40 5120 30 is a number */ break; default: mjpeg_vbr.max_bit_rate = 1024 * 5 + 2048 * frame_rate / 30; /* 1024 5 2048 30 is a number */ break; } venc_chn_attr->rc_attr.mjpeg_vbr = mjpeg_vbr; } static td_void sample_comm_venc_h264_vbr_param_init(ot_venc_chn_attr *venc_chn_attr, td_u32 gop, td_u32 stats_time, td_u32 frame_rate, ot_enum_pic_size size) { ot_venc_h264_vbr h264_vbr; venc_chn_attr->rc_attr.rc_mode = OT_VENC_RC_MODE_H264_VBR; h264_vbr.gop = gop; h264_vbr.stats_time = stats_time; h264_vbr.src_frame_rate = frame_rate; h264_vbr.dst_frame_rate = frame_rate; switch (size) { case PIC_360P: h264_vbr.max_bit_rate = 1024 * 1 + 1024 * frame_rate / 30; /* 1024 30 is a number */ break; case PIC_D1_NTSC: h264_vbr.max_bit_rate = 1024 * frame_rate / 30; /* 1024 30 is a number */ break; case PIC_720P: h264_vbr.max_bit_rate = 1024 * 2 + 1024 * frame_rate / 30; /* 1024 2 30 is a number */ break; case PIC_1080P: h264_vbr.max_bit_rate = 1024 * 2 + 2048 * frame_rate / 30; /* 1024 2 2048 30 is a number */ break; case PIC_2592X1944: h264_vbr.max_bit_rate = 1024 * 3 + 3072 * frame_rate / 30; /* 1024 3 3072 30 is a number */ break; case PIC_3840X2160: h264_vbr.max_bit_rate = 1024 * 5 + 5120 * frame_rate / 30; /* 1024 5 5120 30 is a number */ break; case PIC_4000X3000: h264_vbr.max_bit_rate = 1024 * 10 + 5120 * frame_rate / 30; /* 1024 10 5120 30 is a number */ break; case PIC_7680X4320: h264_vbr.max_bit_rate = 1024 * 20 + 5120 * frame_rate / 30; /* 1024 20 5120 30 is a number */ break; default: h264_vbr.max_bit_rate = 1024 * 2 + 2048 * frame_rate / 30; /* 1024 2 2048 30 is a number */ break; } venc_chn_attr->rc_attr.h264_vbr = h264_vbr; } static td_void sample_comm_venc_h265_vbr_param_init(ot_venc_chn_attr *venc_chn_attr, td_u32 gop, td_u32 stats_time, td_u32 frame_rate, ot_enum_pic_size size) { ot_venc_h265_vbr h265_vbr; venc_chn_attr->rc_attr.rc_mode = OT_VENC_RC_MODE_H265_VBR; h265_vbr.gop = gop; h265_vbr.stats_time = stats_time; h265_vbr.src_frame_rate = frame_rate; h265_vbr.dst_frame_rate = frame_rate; switch (size) { case PIC_D1_NTSC: h265_vbr.max_bit_rate = 1024 * frame_rate / 30; /* 1024 is a number 30 is a number */ break; case PIC_720P: h265_vbr.max_bit_rate = 1024 * 2 + 1024 * frame_rate / 30; /* 1024 2 1024 30 is a number */ break; case PIC_1080P: h265_vbr.max_bit_rate = 1024 * 2 + 2048 * frame_rate / 30; /* 1024 2 2048 30 is a number */ break; case PIC_2592X1944: h265_vbr.max_bit_rate = 1024 * 3 + 3072 * frame_rate / 30; /* 1024 3 is 3072 30 is a number */ break; case PIC_3840X2160: h265_vbr.max_bit_rate = 1024 * 5 + 5120 * frame_rate / 30; /* 1024 5 5120 30 is a number */ break; case PIC_4000X3000: h265_vbr.max_bit_rate = 1024 * 10 + 5120 * frame_rate / 30; /* 1024 10 5120 30 is a number */ break; case PIC_7680X4320: h265_vbr.max_bit_rate = 1024 * 20 + 5120 * frame_rate / 30; /* 1024 20 5120 30 is a number */ break; default: h265_vbr.max_bit_rate = 1024 * 2 + 2048 * frame_rate / 30; /* 1024 2 2048 30 is a number */ break; } venc_chn_attr->rc_attr.h265_vbr = h265_vbr; } static td_void sample_comm_venc_mjpeg_fixqp_param_init(ot_venc_chn_attr *venc_chn_attr, td_u32 frame_rate) { ot_venc_mjpeg_fixqp mjpege_fixqp; venc_chn_attr->rc_attr.rc_mode = OT_VENC_RC_MODE_MJPEG_FIXQP; mjpege_fixqp.qfactor = 95; /* 95 is a number */ mjpege_fixqp.src_frame_rate = frame_rate; mjpege_fixqp.dst_frame_rate = frame_rate; venc_chn_attr->rc_attr.mjpeg_fixqp = mjpege_fixqp; } static td_void sample_comm_venc_h264_fixqp_param_init(ot_venc_chn_attr *venc_chn_attr, td_u32 gop, td_u32 frame_rate) { ot_venc_h264_fixqp h264_fixqp; venc_chn_attr->rc_attr.rc_mode = OT_VENC_RC_MODE_H264_FIXQP; h264_fixqp.gop = gop; h264_fixqp.src_frame_rate = frame_rate; h264_fixqp.dst_frame_rate = frame_rate; h264_fixqp.i_qp = 25; /* 25 is a number */ h264_fixqp.p_qp = 30; /* 30 is a number */ h264_fixqp.b_qp = 32; /* 32 is a number */ venc_chn_attr->rc_attr.h264_fixqp = h264_fixqp; } static td_void sample_comm_venc_h265_fixqp_param_init(ot_venc_chn_attr *venc_chn_attr, td_u32 gop, td_u32 frame_rate) { ot_venc_h265_fixqp h265_fixqp; venc_chn_attr->rc_attr.rc_mode = OT_VENC_RC_MODE_H265_FIXQP; h265_fixqp.gop = gop; h265_fixqp.src_frame_rate = frame_rate; h265_fixqp.dst_frame_rate = frame_rate; h265_fixqp.i_qp = 25; /* 25 is a number */ h265_fixqp.p_qp = 30; /* 30 is a number */ h265_fixqp.b_qp = 32; /* 32 is a number */ venc_chn_attr->rc_attr.h265_fixqp = h265_fixqp; } static td_void sample_comm_venc_mjpeg_cbr_param_init(ot_venc_chn_attr *venc_chn_attr, td_u32 stats_time, td_u32 frame_rate, ot_enum_pic_size size) { ot_venc_mjpeg_cbr mjpege_cbr; venc_chn_attr->rc_attr.rc_mode = OT_VENC_RC_MODE_MJPEG_CBR; mjpege_cbr.stats_time = stats_time; mjpege_cbr.src_frame_rate = frame_rate; mjpege_cbr.dst_frame_rate = frame_rate; switch (size) { case PIC_360P: mjpege_cbr.bit_rate = 1024 * 3 + 1024 * frame_rate / 30; /* 1024 3 1024 30 is a number */ break; case PIC_D1_NTSC: mjpege_cbr.bit_rate = 1024 + 1024 * frame_rate / 30; /* 1024 1024 30 is a number */ break; case PIC_720P: mjpege_cbr.bit_rate = 1024 * 3 + 1024 * frame_rate / 30; /* 1024 3 1024 30 is a number */ break; case PIC_1080P: mjpege_cbr.bit_rate = 1024 * 2 + 2048 * frame_rate / 30; /* 1024 2 2048 30 is a number */ break; case PIC_2592X1944: mjpege_cbr.bit_rate = 1024 * 20 + 3072 * frame_rate / 30; /* 1024 20 3072 30 is a number */ break; case PIC_3840X2160: mjpege_cbr.bit_rate = 1024 * 25 + 5120 * frame_rate / 30; /* 1024 25 5120 30 is a number */ break; case PIC_4000X3000: mjpege_cbr.bit_rate = 1024 * 30 + 5120 * frame_rate / 30; /* 1024 30 5120 30 is a number */ break; case PIC_7680X4320: mjpege_cbr.bit_rate = 1024 * 40 + 5120 * frame_rate / 30; /* 1024 40 5120 30 is a number */ break; default: mjpege_cbr.bit_rate = 1024 * 5 + 2048 * frame_rate / 30; /* 1024 5 2048 30 is a number */ break; } venc_chn_attr->rc_attr.mjpeg_cbr = mjpege_cbr; } static td_void sample_comm_venc_h264_cbr_param_init(ot_venc_chn_attr *venc_chn_attr, td_u32 gop, td_u32 stats_time, td_u32 frame_rate, ot_enum_pic_size size) { ot_venc_h264_cbr h264_cbr; venc_chn_attr->rc_attr.rc_mode = OT_VENC_RC_MODE_H264_CBR; h264_cbr.gop = gop; h264_cbr.stats_time = stats_time; /* stream rate statics time(s) */ h264_cbr.src_frame_rate = frame_rate; /* input (vi) frame rate */ h264_cbr.dst_frame_rate = frame_rate; /* target frame rate */ switch (size) { case PIC_360P: h264_cbr.bit_rate = 1024 * 1 + 1024 * frame_rate / 30; /* 1024 1024 30 is a number */ break; case PIC_D1_NTSC: h264_cbr.bit_rate = 1024 * frame_rate / 30; /* 1024 is 30 is a number */ break; case PIC_720P: h264_cbr.bit_rate = 1024 * 2 + 1024 * frame_rate / 30; /* 1024 2 1024 30 is a number */ break; case PIC_1080P: h264_cbr.bit_rate = 1024 * 2 + 2048 * frame_rate / 30; /* 1024 2 2048 30 is a number */ break; case PIC_2592X1944: h264_cbr.bit_rate = 1024 * 3 + 3072 * frame_rate / 30; /* 1024 3 3072 30 is a number */ break; case PIC_3840X2160: h264_cbr.bit_rate = 1024 * 5 + 5120 * frame_rate / 30; /* 1024 5 5120 30 is a number */ break; case PIC_4000X3000: h264_cbr.bit_rate = 1024 * 12 + 5120 * frame_rate / 30; /* 1024 12 5120 30 is a number */ break; case PIC_7680X4320: h264_cbr.bit_rate = 1024 * 10 + 5120 * frame_rate / 30; /* 1024 10 5120 30 is a number */ break; default: h264_cbr.bit_rate = 1024 * 2 + 2048 * frame_rate / 30; /* 1024 2 2048 30 is a number */ break; } venc_chn_attr->rc_attr.h264_cbr = h264_cbr; } static td_void sample_comm_venc_h265_cbr_param_init(ot_venc_chn_attr *venc_chn_attr, td_u32 gop, td_u32 stats_time, td_u32 frame_rate, ot_enum_pic_size size) { ot_venc_h265_cbr h265_cbr; venc_chn_attr->rc_attr.rc_mode = OT_VENC_RC_MODE_H265_CBR; h265_cbr.gop = gop; h265_cbr.stats_time = stats_time; /* stream rate statics time(s) */ h265_cbr.src_frame_rate = frame_rate; /* input (vi) frame rate */ h265_cbr.dst_frame_rate = frame_rate; /* target frame rate */ switch (size) { case PIC_D1_NTSC: h265_cbr.bit_rate = 1024 * frame_rate / 30; /* 1024 is a number 30 is a number */ break; case PIC_720P: h265_cbr.bit_rate = 1024 * 2 + 1024 * frame_rate / 30; /* 1024 2 1024 30 is a number */ break; case PIC_1080P: h265_cbr.bit_rate = 1024 * 2 + 2048 * frame_rate / 30; /* 1024 2 2048 30 is a number */ break; case PIC_2592X1944: h265_cbr.bit_rate = 1024 * 3 + 3072 * frame_rate / 30; /* 1024 3 3072 30 is a number */ break; case PIC_3840X2160: h265_cbr.bit_rate = 1024 * 5 + 5120 * frame_rate / 30; /* 1024 5 5120 30 is a number */ break; case PIC_4000X3000: h265_cbr.bit_rate = 1024 * 10 + 5120 * frame_rate / 30; /* 1024 10 5120 30 is a number */ break; case PIC_7680X4320: h265_cbr.bit_rate = 1024 * 20 + 5120 * frame_rate / 30; /* 1024 20 5120 30 is a number */ break; default: h265_cbr.bit_rate = 1024 * 2 + 2048 * frame_rate / 30; /* 1024 2 2048 30 is a number */ break; } venc_chn_attr->rc_attr.h265_cbr = h265_cbr; } static td_s32 sample_comm_venc_jpeg_param_init(ot_venc_chn_attr *venc_chn_attr) { ot_venc_jpeg_attr jpeg_attr; jpeg_attr.dcf_en = TD_FALSE; jpeg_attr.mpf_cfg.large_thumbnail_num = 0; jpeg_attr.recv_mode = OT_VENC_PIC_RECV_SINGLE; venc_chn_attr->venc_attr.jpeg_attr = jpeg_attr; return TD_SUCCESS; } static td_s32 sample_comm_venc_mjpeg_param_init(ot_venc_chn_attr *venc_chn_attr, struct_comm_venc_chn_param *venc_create_chn_param) { enum_rc rc_mode = venc_create_chn_param->rc_mode; td_u32 stats_time = venc_create_chn_param->stats_time; td_u32 frame_rate = venc_create_chn_param->frame_rate; ot_enum_pic_size size = venc_create_chn_param->size; if (rc_mode == SAMPLE_RC_FIXQP) { sample_comm_venc_mjpeg_fixqp_param_init(venc_chn_attr, frame_rate); } else if (rc_mode == SAMPLE_RC_CBR) { sample_comm_venc_mjpeg_cbr_param_init(venc_chn_attr, stats_time, frame_rate, size); } else if ((rc_mode == SAMPLE_RC_VBR) || (rc_mode == SAMPLE_RC_AVBR)) { if (rc_mode == SAMPLE_RC_AVBR) { sample_print("mjpege not support AVBR, so change rcmode to VBR!\n"); } sample_comm_venc_mjpeg_vbr_param_init(venc_chn_attr, stats_time, frame_rate, size); } else { sample_print("can't support other mode(%d) in this version!\n", rc_mode); return TD_FAILURE; } return TD_SUCCESS; } static td_s32 sample_comm_venc_h264_param_init(ot_venc_chn_attr *chn_attr, struct_comm_venc_chn_param *chn_param) { enum_rc rc_mode = chn_param->rc_mode; td_u32 gop = chn_param->gop; td_u32 stats_time = chn_param->stats_time; td_u32 frame_rate = chn_param->frame_rate; ot_enum_pic_size size = chn_param->size; chn_attr->venc_attr.h264_attr.frame_buf_ratio = SAMPLE_FRAME_BUF_RATIO_MIN; if (rc_mode == SAMPLE_RC_CBR) { sample_comm_venc_h264_cbr_param_init(chn_attr, gop, stats_time, frame_rate, size); } else if (rc_mode == SAMPLE_RC_FIXQP) { sample_comm_venc_h264_fixqp_param_init(chn_attr, gop, frame_rate); } else if (rc_mode == SAMPLE_RC_VBR) { sample_comm_venc_h264_vbr_param_init(chn_attr, gop, stats_time, frame_rate, size); } else if (rc_mode == SAMPLE_RC_AVBR) { sample_comm_venc_h264_avbr_param_init(chn_attr, gop, stats_time, frame_rate, size); } else if (rc_mode == SAMPLE_RC_CVBR) { sample_comm_venc_h264_cvbr_param_init(chn_attr, gop, stats_time, frame_rate, size); } else if (rc_mode == SAMPLE_RC_QVBR) { sample_comm_venc_h264_qvbr_param_init(chn_attr, gop, stats_time, frame_rate, size); } else if (rc_mode == SAMPLE_RC_QPMAP) { sample_comm_venc_h264_qpmap_param_init(chn_attr, gop, frame_rate, stats_time); } else { sample_print("%s,%d,rc_mode(%d) not support\n", __FUNCTION__, __LINE__, rc_mode); return TD_FAILURE; } chn_attr->venc_attr.h264_attr.rcn_ref_share_buf_en = chn_param->is_rcn_ref_share_buf; return TD_SUCCESS; } static td_s32 sample_comm_venc_h265_param_init(ot_venc_chn_attr *chn_attr, struct_comm_venc_chn_param *chn_param) { enum_rc rc_mode = chn_param->rc_mode; td_u32 gop = chn_param->gop; td_u32 stats_time = chn_param->stats_time; td_u32 frame_rate = chn_param->frame_rate; ot_enum_pic_size size = chn_param->size; chn_attr->venc_attr.h265_attr.frame_buf_ratio = SAMPLE_FRAME_BUF_RATIO_MIN; if (rc_mode == SAMPLE_RC_CBR) { sample_comm_venc_h265_cbr_param_init(chn_attr, gop, stats_time, frame_rate, size); } else if (rc_mode == SAMPLE_RC_FIXQP) { sample_comm_venc_h265_fixqp_param_init(chn_attr, gop, frame_rate); } else if (rc_mode == SAMPLE_RC_VBR) { sample_comm_venc_h265_vbr_param_init(chn_attr, gop, stats_time, frame_rate, size); } else if (rc_mode == SAMPLE_RC_AVBR) { sample_comm_venc_h265_avbr_param_init(chn_attr, gop, stats_time, frame_rate, size); } else if (rc_mode == SAMPLE_RC_CVBR) { sample_comm_venc_h265_cvbr_param_init(chn_attr, gop, stats_time, frame_rate, size); } else if (rc_mode == SAMPLE_RC_QVBR) { sample_comm_venc_h265_qvbr_param_init(chn_attr, gop, stats_time, frame_rate, size); } else if (rc_mode == SAMPLE_RC_QPMAP) { sample_comm_venc_h265_qpmap_param_init(chn_attr, gop, frame_rate, stats_time); } else { sample_print("%s,%d,rc_mode(%d) not support\n", __FUNCTION__, __LINE__, rc_mode); return TD_FAILURE; } chn_attr->venc_attr.h265_attr.rcn_ref_share_buf_en = chn_param->is_rcn_ref_share_buf; return TD_SUCCESS; } static td_void sample_comm_venc_set_gop_attr(ot_payload_type type, ot_venc_chn_attr *chn_attr, ot_venc_gop_attr *gop_attr) { if (type == OT_PT_MJPEG || type == OT_PT_JPEG) { chn_attr->gop_attr.gop_mode = OT_VENC_GOP_MODE_NORMAL_P; chn_attr->gop_attr.normal_p.ip_qp_delta = 0; } else { chn_attr->gop_attr = *gop_attr; if ((gop_attr->gop_mode == OT_VENC_GOP_MODE_BIPRED_B) && (type == OT_PT_H264)) { if (chn_attr->venc_attr.profile == 0) { chn_attr->venc_attr.profile = 1; sample_print("H.264 base profile not support BIPREDB, so change profile to main profile!\n"); } } } } static td_s32 sample_comm_venc_channel_param_init(struct_comm_venc_chn_param *chn_param, ot_venc_chn_attr *chn_attr) { td_s32 ret; ot_venc_gop_attr *gop_attr = &chn_param->gop_attr; td_u32 profile = chn_param->profile; ot_payload_type type = chn_param->type; ot_size venc_size = chn_param->venc_size; chn_attr->venc_attr.type = type; chn_attr->venc_attr.max_pic_width = venc_size.width; chn_attr->venc_attr.max_pic_height = venc_size.height; chn_attr->venc_attr.pic_width = venc_size.width; /* the picture width */ chn_attr->venc_attr.pic_height = venc_size.height; /* the picture height */ if (type == OT_PT_MJPEG || type == OT_PT_JPEG) { chn_attr->venc_attr.buf_size = OT_ALIGN_UP(venc_size.width, 16) * OT_ALIGN_UP(venc_size.height, 16) * 4; /* 16 4 is a number */ } else { chn_attr->venc_attr.buf_size = OT_ALIGN_UP(venc_size.width * venc_size.height * 3 / 4, 64); /* 3 4 64 is a number */ } chn_attr->venc_attr.profile = profile; chn_attr->venc_attr.is_by_frame = TD_TRUE; /* get stream mode is slice mode or frame mode? */ if (gop_attr->gop_mode == OT_VENC_GOP_MODE_SMART_P) { chn_param->stats_time = gop_attr->smart_p.bg_interval / chn_param->gop; } else { chn_param->stats_time = 1; } switch (type) { case OT_PT_H265: ret = sample_comm_venc_h265_param_init(chn_attr, chn_param); break; case OT_PT_H264: ret = sample_comm_venc_h264_param_init(chn_attr, chn_param); break; case OT_PT_MJPEG: ret = sample_comm_venc_mjpeg_param_init(chn_attr, chn_param); break; case OT_PT_JPEG: ret = sample_comm_venc_jpeg_param_init(chn_attr); break; default: sample_print("can't support this type (%d) in this version!\n", type); return OT_ERR_VENC_NOT_SUPPORT; } sample_comm_venc_set_gop_attr(type, chn_attr, gop_attr); return ret; } td_s32 sample_comm_venc_create(ot_venc_chn venc_chn, struct_comm_venc_chn_param *chn_param) { td_s32 ret; ot_venc_chn_attr venc_chn_attr; ot_enum_pic_size size = chn_param->size; chn_param->frame_rate = 30; /* 30 is a number */ chn_param->gop = 30; /* 30 is a number */ if (libapi_comm_sys_get_pic_size(size, &chn_param->venc_size) != TD_SUCCESS) { sample_print("get picture size failed!\n"); return TD_FAILURE; } /* step 1: create venc channel */ if ((ret = sample_comm_venc_channel_param_init(chn_param, &venc_chn_attr)) != TD_SUCCESS) { sample_print("venc_channel_param_init failed!\n"); return ret; } if ((ret = ss_mpi_venc_create_chn(venc_chn, &venc_chn_attr)) != TD_SUCCESS) { sample_print("ss_mpi_venc_create_chn [%d] failed with %#x! ===\n", venc_chn, ret); return ret; } if (chn_param->type == OT_PT_JPEG) { return TD_SUCCESS; } if ((ret = sample_comm_venc_close_reencode(venc_chn)) != TD_SUCCESS) { ss_mpi_venc_destroy_chn(venc_chn); return ret; } return TD_SUCCESS; } /* * function : start venc stream mode * note : rate control parameter need adjust, according your case. */ td_s32 sample_comm_venc_start(ot_venc_chn venc_chn, struct_comm_venc_chn_param *chn_param) { td_s32 ret; ot_venc_start_param start_param; /* step 1: create encode chnl */ if ((ret = sample_comm_venc_create(venc_chn, chn_param)) != TD_SUCCESS) { sample_print("sample_comm_venc_create failed with%#x! \n", ret); return TD_FAILURE; } /* step 2: start recv venc pictures */ start_param.recv_pic_num = -1; if ((ret = ss_mpi_venc_start_chn(venc_chn, &start_param)) != TD_SUCCESS) { sample_print("ss_mpi_venc_start_recv_pic failed with%#x! \n", ret); return TD_FAILURE; } return TD_SUCCESS; } /* function : stop venc (stream mode-- H264, MJPEG) */ td_s32 sample_comm_venc_stop(ot_venc_chn venc_chn) { td_s32 ret; /* stop venc chn */ ret = ss_mpi_venc_stop_chn(venc_chn); if (ret != TD_SUCCESS) { sample_print("ss_mpi_venc_stop_chn vechn[%d] failed with %#x!\n", venc_chn, ret); } /* distroy venc channel */ ret = ss_mpi_venc_destroy_chn(venc_chn); if (ret != TD_SUCCESS) { sample_print("ss_mpi_venc_destroy_chn vechn[%d] failed with %#x!\n", venc_chn, ret); return TD_FAILURE; } return TD_SUCCESS; } /* start snap */ td_s32 sample_comm_venc_snap_start(ot_venc_chn venc_chn, ot_size *size, td_bool support_dcf) { td_s32 ret; ot_venc_chn_attr venc_chn_attr; ot_venc_start_param start_param; /* step 1: create venc channel */ venc_chn_attr.venc_attr.type = OT_PT_JPEG; venc_chn_attr.venc_attr.max_pic_width = size->width; venc_chn_attr.venc_attr.max_pic_height = size->height; venc_chn_attr.venc_attr.pic_width = size->width; venc_chn_attr.venc_attr.pic_height = size->height; venc_chn_attr.venc_attr.buf_size = size->width * size->height * 2; /* 2 is a number */ venc_chn_attr.venc_attr.is_by_frame = TD_TRUE; /* get stream mode is field mode or frame mode */ venc_chn_attr.venc_attr.profile = 0; venc_chn_attr.venc_attr.jpeg_attr.dcf_en = support_dcf; venc_chn_attr.venc_attr.jpeg_attr.mpf_cfg.large_thumbnail_num = 0; venc_chn_attr.venc_attr.jpeg_attr.recv_mode = OT_VENC_PIC_RECV_SINGLE; ret = ss_mpi_venc_create_chn(venc_chn, &venc_chn_attr); if (ret != TD_SUCCESS) { sample_print("ss_mpi_venc_create_chn [%d] failed with %#x!\n", venc_chn, ret); return ret; } ret = ss_mpi_venc_set_jpeg_enc_mode(venc_chn, OT_VENC_JPEG_ENC_SNAP); if (ret != TD_SUCCESS) { sample_print("ss_mpi_venc_set_jpeg_enc_mode faild with%#x!\n", ret); return TD_FAILURE; } start_param.recv_pic_num = -1; ret = ss_mpi_venc_start_chn(venc_chn, &start_param); if (ret != TD_SUCCESS) { sample_print("mpi_venc_start_chn faild with%#x!\n", ret); return TD_FAILURE; } return TD_SUCCESS; } /* start photo */ td_s32 sample_comm_venc_photo_start(ot_venc_chn venc_chn, ot_size *size, td_bool support_dcf) { td_s32 ret; ot_venc_chn_attr venc_chn_attr; ot_venc_start_param start_param; /* step 1: create venc channel */ venc_chn_attr.venc_attr.type = OT_PT_JPEG; venc_chn_attr.venc_attr.max_pic_width = size->width; venc_chn_attr.venc_attr.max_pic_height = size->height; venc_chn_attr.venc_attr.pic_width = size->width; venc_chn_attr.venc_attr.pic_height = size->height; venc_chn_attr.venc_attr.buf_size = size->width * size->height * 2; /* 2 is a number */ venc_chn_attr.venc_attr.is_by_frame = TD_TRUE; /* get stream mode is field mode or frame mode */ venc_chn_attr.venc_attr.profile = 0; venc_chn_attr.venc_attr.jpeg_attr.dcf_en = support_dcf; venc_chn_attr.venc_attr.jpeg_attr.mpf_cfg.large_thumbnail_num = 0; venc_chn_attr.venc_attr.jpeg_attr.recv_mode = OT_VENC_PIC_RECV_SINGLE; ret = ss_mpi_venc_create_chn(venc_chn, &venc_chn_attr); if (ret != TD_SUCCESS) { sample_print("ss_mpi_venc_create_chn [%d] failed with %#x!\n", venc_chn, ret); return ret; } start_param.recv_pic_num = -1; ret = ss_mpi_venc_start_chn(venc_chn, &start_param); if (ret != TD_SUCCESS) { sample_print("mpi_venc_start_chn faild with%#x!\n", ret); return TD_FAILURE; } return TD_SUCCESS; } /* stop snap */ td_s32 sample_comm_venc_snap_stop(ot_venc_chn venc_chn) { td_s32 ret; ret = ss_mpi_venc_stop_chn(venc_chn); if (ret != TD_SUCCESS) { sample_print("ss_mpi_venc_stop_chn vechn[%d] failed with %#x!\n", venc_chn, ret); return TD_FAILURE; } ret = ss_mpi_venc_destroy_chn(venc_chn); if (ret != TD_SUCCESS) { sample_print("ss_mpi_venc_destroy_chn vechn[%d] failed with %#x!\n", venc_chn, ret); return TD_FAILURE; } return TD_SUCCESS; } static td_s32 sample_comm_save_snap_stream(ot_venc_stream stream, td_bool save_jpg, td_bool save_thm) { td_s32 ret; char stream_file[FILE_NAME_LEN] = {0}; FILE *file = TD_NULL; td_s32 fd = -1; if (snprintf_s(stream_file, FILE_NAME_LEN, FILE_NAME_LEN - 1, "snap_%d.jpg", g_snap_cnt) < 0) { free(stream.pack); stream.pack = NULL; return TD_FAILURE; } fd = open(stream_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if (fd < 0) { sample_print("open file err\n"); free(stream.pack); stream.pack = NULL; return TD_FAILURE; } file = fdopen(fd, "wb"); if (file == NULL) { sample_print("fdopen err\n"); goto error; } ret = sample_comm_venc_save_stream(file, &stream); if (ret != TD_SUCCESS) { sample_print("save snap picture failed!\n"); goto error; } if (save_thm) { char file_dcf[FILE_NAME_LEN] = {0}; if (snprintf_s(file_dcf, FILE_NAME_LEN, FILE_NAME_LEN - 1, "snap_thm_%d.jpg", g_snap_cnt) < 0) { goto error; } ret = sample_comm_venc_get_dcf_info(stream_file, FILE_NAME_LEN, file_dcf, FILE_NAME_LEN); if (ret != TD_SUCCESS) { sample_print("save thm picture failed!\n"); goto error; } } (td_void)fclose(file); file = TD_NULL; g_snap_cnt++; return TD_SUCCESS; error: free(stream.pack); stream.pack = NULL; (td_void)fclose(file); file = TD_NULL; return TD_FAILURE; } static td_s32 sample_comm_get_snap_stream(ot_venc_chn venc_chn, td_bool save_jpg, td_bool save_thm) { td_s32 ret; ot_venc_chn_status stat; ot_venc_stream stream; ret = ss_mpi_venc_query_status(venc_chn, &stat); if (ret != TD_SUCCESS) { sample_print("query_status failed with %#x!\n", ret); return TD_FAILURE; } if (stat.cur_packs == 0) { sample_print("NOTE: Current frame is NULL!\n"); return TD_SUCCESS; } stream.pack = (ot_venc_pack *)malloc(sizeof(ot_venc_pack) * stat.cur_packs); if (stream.pack == NULL) { sample_print("malloc memory failed!\n"); return TD_FAILURE; } stream.pack_cnt = stat.cur_packs; ret = ss_mpi_venc_get_stream(venc_chn, &stream, -1); if (ret != TD_SUCCESS) { sample_print("get_stream failed with %#x!\n", ret); free(stream.pack); stream.pack = NULL; return TD_FAILURE; } if (save_jpg || save_thm) { ret = sample_comm_save_snap_stream(stream, save_jpg, save_thm); if (ret != TD_SUCCESS) { sample_print("save_snap_stream failed!\n"); return ret; } } ret = ss_mpi_venc_release_stream(venc_chn, &stream); if (ret != TD_SUCCESS) { sample_print("release_stream failed with %#x!\n", ret); free(stream.pack); stream.pack = NULL; return TD_FAILURE; } free(stream.pack); stream.pack = NULL; return ret; } /****************************************************************************** * funciton : snap process ******************************************************************************/ td_s32 sample_comm_venc_snap_process(ot_venc_chn venc_chn, td_u32 snap_cnt, td_bool save_jpg, td_bool save_thm) { struct timeval timeout_val; fd_set read_fds; td_s32 venc_fd; td_s32 ret; td_u32 i; /****************************************** step 4: recv picture ******************************************/ venc_fd = ss_mpi_venc_get_fd(venc_chn); if (venc_fd < 0) { sample_print("venc_get_fd faild with%#x!\n", venc_fd); return TD_FAILURE; } for (i = 0; i < snap_cnt; i++) { FD_ZERO(&read_fds); FD_SET(venc_fd, &read_fds); timeout_val.tv_sec = 10; // 10 : 10 seconds timeout_val.tv_usec = 0; ret = select(venc_fd + 1, &read_fds, NULL, NULL, &timeout_val); if (ret < 0) { sample_print("snap select failed!\n"); return TD_FAILURE; } else if (ret == 0) { sample_print("snap time out!\n"); return TD_FAILURE; } else { if (FD_ISSET(venc_fd, &read_fds)) { check_return(sample_comm_get_snap_stream(venc_chn, save_jpg, save_thm), "get_snap_stream"); } } } return TD_SUCCESS; } td_s32 sample_comm_venc_save_jpeg(ot_venc_chn venc_chn, td_u32 snap_cnt) { struct timeval timeout_val; fd_set read_fds; td_s32 venc_fd; td_s32 ret; td_u32 i; /****************************************** step: recv picture ******************************************/ venc_fd = ss_mpi_venc_get_fd(venc_chn); if (venc_fd < 0) { sample_print("venc_get_fd faild with%#x!\n", venc_fd); return TD_FAILURE; } for (i = 0; i < snap_cnt; i++) { FD_ZERO(&read_fds); FD_SET(venc_fd, &read_fds); timeout_val.tv_sec = 10; // 10 : 10 seconds timeout_val.tv_usec = 0; ret = select(venc_fd + 1, &read_fds, NULL, NULL, &timeout_val); if (ret < 0) { sample_print("snap select failed!\n"); return TD_FAILURE; } else if (ret == 0) { sample_print("snap time out!\n"); return TD_FAILURE; } else { if (FD_ISSET(venc_fd, &read_fds)) { check_return(sample_comm_get_snap_stream(venc_chn, TD_TRUE, TD_FALSE), "get_snap_stream"); } } } return TD_SUCCESS; } static td_s32 sample_comm_alloc_qpmap_skipweight_memory(struct_venc_qpmap_sendframe_para *para, sample_comm_venc_frame_proc_info *addr_info) { ot_venc_chn_attr venc_chn_attr; td_u32 j; td_s32 i, ret; td_u8 *vir_addr = TD_NULL; td_phys_addr_t phys_addr = 0; for (i = 0; (i < para->cnt) && (i < OT_VENC_MAX_CHN_NUM); i++) { ss_mpi_venc_get_chn_attr(para->venc_chn[i], &venc_chn_attr); addr_info->qpmap_size[i] = ot_venc_get_qpmap_size(venc_chn_attr.venc_attr.type, para->size[i].width, para->size[i].height); addr_info->skip_weight_size[i] = ot_venc_get_skip_weight_size(venc_chn_attr.venc_attr.type, para->size[i].width, para->size[i].height); /* alloc qpmap memory */ ret = ss_mpi_sys_mmz_alloc((td_phys_addr_t *)&phys_addr, (td_void **)&vir_addr, TD_NULL, TD_NULL, addr_info->qpmap_size[i] * QPMAP_BUF_NUM); if (ret != TD_SUCCESS) { sample_print("ss_mpi_sys_mmz_alloc err:0x%x", ret); return ret; } for (j = 0; (i < VENC_QPMAP_MAX_CHN) && (j < QPMAP_BUF_NUM); j++) { if ((j > 0) && (addr_info->qpmap_size[i] > (UINT_MAX / j))) { sample_print("(j * addr_info->qpmap_size[%d]) upper limit of the multiplie\n", i); ss_mpi_sys_mmz_free(phys_addr, vir_addr); return TD_FAILURE; } else { addr_info->qpmap_phys_addr[i][j] = (td_phys_addr_t)(phys_addr + j * addr_info->qpmap_size[i]); addr_info->qpmap_vir_addr[i][j] = vir_addr + j * addr_info->qpmap_size[i]; } } /* alloc skipWeight memory */ ret = ss_mpi_sys_mmz_alloc((td_phys_addr_t *)&phys_addr, (td_void **)&vir_addr, TD_NULL, TD_NULL, addr_info->skip_weight_size[i] * QPMAP_BUF_NUM); if (ret != TD_SUCCESS) { sample_print("ss_mpi_sys_mmz_alloc err:0x%x", ret); return ret; } for (j = 0; (i < VENC_QPMAP_MAX_CHN) && (j < QPMAP_BUF_NUM); j++) { if ((j > 0) && (addr_info->skip_weight_size[i] > (UINT_MAX / j))) { sample_print("(j * addr_info->skip_weight_size[%d]) upper limit of the multiplie\n", i); ss_mpi_sys_mmz_free(phys_addr, vir_addr); return TD_FAILURE; } else { addr_info->skip_weight_phys_addr[i][j] = (td_phys_addr_t)(phys_addr + j * addr_info->skip_weight_size[i]); addr_info->skip_weight_vir_addr[i][j] = vir_addr + j * addr_info->skip_weight_size[i]; } } } return TD_SUCCESS; } static td_void sample_comm_venc_vir_addr_temp(sample_comm_venc_frame_proc_info *addr_info, td_u32 i, td_u32 frame_id) { td_u32 j; td_u8 *vir_addr_temp = TD_NULL; vir_addr_temp = (td_u8 *)addr_info->qpmap_vir_addr[i][frame_id]; for (j = 0; j < addr_info->qpmap_size[i]; j++) { *vir_addr_temp = 0x5E; // [7]:skip flag; [6]:QpType Flag; [5:0]:Qp value ==> Set absolute qp = 30 vir_addr_temp++; } vir_addr_temp = (td_u8 *)addr_info->skip_weight_vir_addr[i][frame_id]; for (j = 0; j < addr_info->skip_weight_size[i]; j++) { *vir_addr_temp = 0x66; // inter block must be skip vir_addr_temp++; } } static td_s32 sample_comm_qpmap_send_frame_ex(struct_venc_qpmap_sendframe_para *para, ot_venc_user_frame_info *frame_info, ot_video_frame_info *video_frame, td_s32 index) { td_s32 ret; ret = ss_mpi_venc_send_frame_ex(para->venc_chn[index], frame_info, -1); if (ret != TD_SUCCESS) { sample_print("ss_mpi_venc_send_frame_ex err:0x%x\n", ret); ret = ss_mpi_vpss_release_chn_frame(para->vpss_grp, para->vpss_chn[index], video_frame); if (ret != TD_SUCCESS) { sample_print("ss_mpi_vpss_release_chn_frame err:0x%x", ret); return SAMPLE_RETURN_GOTO; } return SAMPLE_RETURN_BREAK; } return TD_SUCCESS; } static td_s32 sample_comm_qpmap_send_frame_start(struct_venc_qpmap_sendframe_para *para, sample_comm_venc_frame_proc_info *addr_info) { td_u32 frame_id = 0; td_s32 i, ret; ot_venc_user_frame_info frame_info[VENC_QPMAP_MAX_CHN][QPMAP_BUF_NUM] = { 0 }; while (para->thread_start == TD_TRUE) { for (i = 0; (i < para->cnt) && (i < VENC_QPMAP_MAX_CHN); i++) { ot_video_frame_info *video_frame = &frame_info[i][frame_id].user_frame; ret = ss_mpi_vpss_get_chn_frame(para->vpss_grp, para->vpss_chn[i], video_frame, 1000); /* 1000 is a number */ if (ret != TD_SUCCESS) { sample_print("OT_MPI_VPSS_GetChnFrame err:0x%x\n", ret); continue; } sample_comm_venc_vir_addr_temp(addr_info, i, frame_id); frame_info[i][frame_id].user_rc_info.skip_weight_valid = 1; frame_info[i][frame_id].user_rc_info.skip_weight_phys_addr = addr_info->skip_weight_phys_addr[i][frame_id]; frame_info[i][frame_id].user_rc_info.qpmap_valid = 1; frame_info[i][frame_id].user_rc_info.qpmap_phys_addr = addr_info->qpmap_phys_addr[i][frame_id]; frame_info[i][frame_id].user_rc_info.blk_start_qp = 30; /* 30 is a number */ frame_info[i][frame_id].user_rc_info.frame_type = OT_VENC_FRAME_TYPE_NONE; ret = sample_comm_qpmap_send_frame_ex(para, &frame_info[i][frame_id], video_frame, i); if (ret == SAMPLE_RETURN_BREAK) { break; } else if (ret == SAMPLE_RETURN_GOTO) { return SAMPLE_RETURN_GOTO; } ret = ss_mpi_vpss_release_chn_frame(para->vpss_grp, para->vpss_chn[i], video_frame); if (ret != TD_SUCCESS) { sample_print("ss_mpi_vpss_release_chn_frame err:0x%x", ret); return SAMPLE_RETURN_GOTO; } frame_id++; if (frame_id >= QPMAP_BUF_NUM) { frame_id = 0; } } } return TD_SUCCESS; } td_void *sample_comm_qpmap_send_frame_proc(td_void *p) { td_s32 i, ret; struct_venc_qpmap_sendframe_para *para = TD_NULL; sample_comm_venc_frame_proc_info addr_info = { 0 }; ot_vpss_chn_attr vpss_chn_attr; para = (struct_venc_qpmap_sendframe_para *)p; if (para->cnt > VENC_QPMAP_MAX_CHN) { sample_print("Current func'sample_comm_qpmap_send_frame_proc' not support Venc channal num(%d) > %d\n", para->cnt, VENC_QPMAP_MAX_CHN); return TD_NULL; } if (sample_comm_alloc_qpmap_skipweight_memory(para, &addr_info) != TD_SUCCESS) { goto error; } /* set vpss buffer depth */ for (i = 0; (i < para->cnt) && (i < OT_VPSS_MAX_PHYS_CHN_NUM); i++) { ret = ss_mpi_vpss_get_chn_attr(para->vpss_grp, para->vpss_chn[i], &vpss_chn_attr); if (ret != TD_SUCCESS) { sample_print("ss_mpi_vpss_get_chn_attr err:0x%x", ret); goto error; } vpss_chn_attr.depth = 3; /* 3 is a number */ ret = ss_mpi_vpss_set_chn_attr(para->vpss_grp, para->vpss_chn[i], &vpss_chn_attr); if (ret != TD_SUCCESS) { sample_print("ss_mpi_vpss_set_chn_attr err:0x%x", ret); goto error; } } if (sample_comm_qpmap_send_frame_start(para, &addr_info) != TD_SUCCESS) { goto error; } error: for (i = 0; (i < para->cnt) && (i < VENC_QPMAP_MAX_CHN); i++) { if (addr_info.qpmap_phys_addr[i][0] != 0) { ret = ss_mpi_sys_mmz_free(addr_info.qpmap_phys_addr[i][0], addr_info.qpmap_vir_addr[i][0]); if (ret != TD_SUCCESS) { sample_print("ss_mpi_sys_mmz_free err:0x%x", ret); } } if (addr_info.skip_weight_phys_addr[i][0] != 0) { ret = ss_mpi_sys_mmz_free(addr_info.skip_weight_phys_addr[i][0], addr_info.skip_weight_vir_addr[i][0]); if (ret != TD_SUCCESS) { sample_print("ss_mpi_sys_mmz_free err:0x%x", ret); } } } return TD_NULL; } td_s32 sample_comm_venc_qpmap_send_frame(ot_vpss_grp vpss_grp, ot_vpss_chn vpss_chn[], ot_venc_chn venc_chn[], td_s32 cnt, ot_size size[]) { td_s32 i; g_qpmap_send_frame_para.thread_start = TD_TRUE; g_qpmap_send_frame_para.vpss_grp = vpss_grp; g_qpmap_send_frame_para.cnt = cnt; for (i = 0; (i < cnt) && (i < OT_VENC_MAX_CHN_NUM) && (i < OT_VPSS_MAX_PHYS_CHN_NUM); i++) { g_qpmap_send_frame_para.venc_chn[i] = venc_chn[i]; g_qpmap_send_frame_para.vpss_chn[i] = vpss_chn[i]; g_qpmap_send_frame_para.size[i] = size[i]; } return pthread_create(&g_venc_qpmap_pid, 0, sample_comm_qpmap_send_frame_proc, (td_void *)&g_qpmap_send_frame_para); } #define SAMPLE_VENC_BLOCK_WIDTH 16 #define SAMPLE_VENC_BLOCK_HEIGHT 16 #define SAMPLE_VENC_ONE_BYTE_BLOCKS 4 #define SAMPLE_VENC_ONE_BLOCK_BITS 2 #define SAMPLE_VENC_MAX_JPEG_ROI_LEVEL 3 static td_void sample_venc_set_2bits(td_u8 *wp, td_u32 idx, td_u32 value) { td_u8 tmp1, tmp2; tmp1 = *wp; tmp2 = ~(3 << (idx * SAMPLE_VENC_ONE_BLOCK_BITS)); // 3: 0b11 tmp1 &= tmp2; tmp2 = value << (idx * SAMPLE_VENC_ONE_BLOCK_BITS); tmp1 |= tmp2; *wp = tmp1; } static td_void sample_venc_process_jpeg_roi_head(td_u8 **wp, td_u32 start_idx, td_u32 fill_block, td_u32 value) { td_u32 i; for (i = 0; i < fill_block; i++) { sample_venc_set_2bits(*wp, start_idx + i, value); } if (i != 0) { *wp = *wp + 1; } } static td_void sample_venc_process_jpeg_roi_middle(td_u8 **wp, td_u32 write_byte, td_u32 value) { td_s32 i; if (write_byte != 0) { for (i = 0; i < (SAMPLE_VENC_ONE_BYTE_BLOCKS - 1); i++) { value |= value << SAMPLE_VENC_ONE_BLOCK_BITS; } if (memset_s(*wp, write_byte, value, write_byte) != EOK) { printf("call memset_s error\n"); } *wp = *wp + write_byte; } } static td_void sample_venc_process_jpeg_roi_tail(td_u8 **wp, td_u32 fill_block, td_u32 value) { td_u32 i; for (i = 0; i < fill_block; i++) { sample_venc_set_2bits(*wp, i, value); } } td_void sample_venc_process_jpeg_roi(td_void *virt_addr, ot_rect *rect, td_u32 roi_level, td_u32 stride) { td_u32 i, level, start_block, start_byte, start_supple_idx, start_supple_block, start_block_height; td_u32 start_x, start_y, write_block, write_resi_block, write_byte, write_tail_block, write_block_height; start_x = rect->x; start_block = start_x / SAMPLE_VENC_BLOCK_WIDTH; start_byte = start_block / SAMPLE_VENC_ONE_BYTE_BLOCKS; start_supple_idx = start_block % SAMPLE_VENC_ONE_BYTE_BLOCKS; start_supple_block = (start_supple_idx == 0) ? 0 : (SAMPLE_VENC_ONE_BYTE_BLOCKS - start_supple_idx); write_block = rect->width / SAMPLE_VENC_BLOCK_WIDTH; start_supple_block = (start_supple_block < write_block) ? start_supple_block : write_block; write_resi_block = write_block - start_supple_block; write_byte = write_resi_block / SAMPLE_VENC_ONE_BYTE_BLOCKS; write_tail_block = write_resi_block % SAMPLE_VENC_ONE_BYTE_BLOCKS; start_y = rect->y; start_block_height = start_y / SAMPLE_VENC_BLOCK_HEIGHT; write_block_height = rect->height / SAMPLE_VENC_BLOCK_HEIGHT; level = roi_level; for (i = 0; i < write_block_height; i++) { td_u8 *wp = (td_u8 *)virt_addr + (start_block_height + i) * stride + start_byte; sample_venc_process_jpeg_roi_head(&wp, start_supple_idx, start_supple_block, level); sample_venc_process_jpeg_roi_middle(&wp, write_byte, level); sample_venc_process_jpeg_roi_tail(&wp, write_tail_block, level); } } #define SAMPLE_VENC_ROIMAP_MAX_CHN 2 static td_s32 sample_comm_venc_send_frame_ex(struct_venc_roimap_frame_para *para, ot_venc_user_frame_info *frame_info, ot_video_frame_info *video_frame, td_s32 index, td_s32 venc_roimap_max_chn) { td_s32 ret; ot_unused(venc_roimap_max_chn); ret = ss_mpi_venc_send_frame_ex(para->venc_chn[index], &frame_info[index], -1); if (ret != TD_SUCCESS) { sample_print("ss_mpi_venc_send_frame_ex err: 0x%x\n", ret); ret = ss_mpi_vpss_release_chn_frame(para->vpss_grp, para->vpss_chn[index], video_frame); if (ret != TD_SUCCESS) { sample_print("ss_mpi_vpss_release_chn_frame err: 0x%x", ret); return SAMPLE_RETURN_GOTO; } return SAMPLE_RETURN_BREAK; } return TD_SUCCESS; } static td_s32 sample_comm_venc_send_roimap_frame_start(struct_venc_roimap_frame_para *para, td_phys_addr_t *roimap_phys_addr) { td_s32 i, ret; ot_venc_user_frame_info frame_info[SAMPLE_VENC_ROIMAP_MAX_CHN] = {0}; while (para->thread_start == TD_TRUE) { for (i = 0; (i < para->cnt) && (i < SAMPLE_VENC_ROIMAP_MAX_CHN) && (i < OT_VPSS_MAX_PHYS_CHN_NUM) && (i < OT_VENC_MAX_CHN_NUM); i++) { ot_video_frame_info *video_frame = &frame_info[i].user_frame; ret = ss_mpi_vpss_get_chn_frame(para->vpss_grp, para->vpss_chn[i], video_frame, 1000); /* 1000 is a number */ if (ret != TD_SUCCESS) { sample_print("ss_mpi_vpss_get_chn_frame err: 0x%x\n", ret); continue; } frame_info[i].user_roimap.valid = TD_TRUE; frame_info[i].user_roimap.phys_addr = roimap_phys_addr[i]; ret = sample_comm_venc_send_frame_ex(para, frame_info, video_frame, i, SAMPLE_VENC_ROIMAP_MAX_CHN); if (ret == SAMPLE_RETURN_BREAK) { break; } else if (ret == SAMPLE_RETURN_GOTO) { return SAMPLE_RETURN_GOTO; } ret = ss_mpi_vpss_release_chn_frame(para->vpss_grp, para->vpss_chn[i], video_frame); if (ret != TD_SUCCESS) { sample_print("ss_mpi_vpss_release_chn_frame err: 0x%x", ret); return SAMPLE_RETURN_GOTO; } } } return TD_SUCCESS; } static td_s32 sample_comm_set_vpss_buffer_depth(struct_venc_roimap_frame_para *para, td_phys_addr_t *roimap_phys_addr) { td_s32 i, ret; ot_vpss_chn_attr vpss_chn_attr; for (i = 0; (i < para->cnt) && (i < OT_VPSS_MAX_PHYS_CHN_NUM); i++) { ret = ss_mpi_vpss_get_chn_attr(para->vpss_grp, para->vpss_chn[i], &vpss_chn_attr); if (ret != TD_SUCCESS) { sample_print("ss_mpi_vpss_get_chn_attr err: 0x%x", ret); return SAMPLE_RETURN_GOTO; } vpss_chn_attr.depth = 3; // 3 : depth ret = ss_mpi_vpss_set_chn_attr(para->vpss_grp, para->vpss_chn[i], &vpss_chn_attr); if (ret != TD_SUCCESS) { sample_print("ss_mpi_vpss_set_chn_attr err: 0x%x", ret); return SAMPLE_RETURN_GOTO; } } ret = sample_comm_venc_send_roimap_frame_start(para, roimap_phys_addr); if (ret != TD_SUCCESS) { return SAMPLE_RETURN_GOTO; } return TD_SUCCESS; } td_void *sample_comm_send_roimap_frame_proc(td_void *p) { td_s32 i, j, ret; td_u8 init_level = 2; td_u32 roimap_size[SAMPLE_VENC_ROIMAP_MAX_CHN], roimap_stride[SAMPLE_VENC_ROIMAP_MAX_CHN]; td_phys_addr_t roimap_phys_addr[SAMPLE_VENC_ROIMAP_MAX_CHN] = {0}; td_void *roimap_virt_addr[SAMPLE_VENC_ROIMAP_MAX_CHN] = {0}; td_u8 *virt_addr = TD_NULL; td_phys_addr_t phys_addr = TD_NULL; ot_venc_chn_attr venc_chn_attr; struct_venc_roimap_frame_para *para = (struct_venc_roimap_frame_para *)p; if (para->cnt > SAMPLE_VENC_ROIMAP_MAX_CHN) { sample_print("Current not support venc channal num(%d) > %d\n", para->cnt, SAMPLE_VENC_ROIMAP_MAX_CHN); return TD_NULL; } for (i = 0; (i < para->cnt) && (i < OT_VENC_MAX_CHN_NUM) && (i < SAMPLE_VENC_ROIMAP_MAX_CHN); i++) { ss_mpi_venc_get_chn_attr(para->venc_chn[i], &venc_chn_attr); roimap_size[i] = ot_venc_get_roimap_size(venc_chn_attr.venc_attr.type, para->size[i].width, para->size[i].width); roimap_stride[i] = ot_venc_get_roimap_stride(venc_chn_attr.venc_attr.type, para->size[i].width); /* alloc roimap memory */ ret = ss_mpi_sys_mmz_alloc(&phys_addr, (td_void **)&virt_addr, TD_NULL, TD_NULL, roimap_size[i]); if (ret != TD_SUCCESS) { sample_print("ss_mpi_sys_mmz_alloc err: 0x%x", ret); return TD_NULL; } roimap_phys_addr[i] = phys_addr; roimap_virt_addr[i] = virt_addr; for (j = 0; j < (4 - 1); j++) { /* 4 is a number */ init_level |= (init_level << 4); /* 4 is a number */ } if (memset_s(roimap_virt_addr[i], roimap_size[i], init_level, roimap_size[i]) != EOK) { printf("call memset_s error\n"); } sample_venc_process_jpeg_roi(roimap_virt_addr[i], ¶->roi_attr[i].rect, para->roi_attr[i].level, roimap_stride[i]); } /* set vpss buffer depth */ if (sample_comm_set_vpss_buffer_depth(para, roimap_phys_addr) != TD_SUCCESS) { goto error; } error: for (i = 0; (i < para->cnt) && (i < SAMPLE_VENC_ROIMAP_MAX_CHN); i++) { if (roimap_phys_addr[i] != 0) { ret = ss_mpi_sys_mmz_free(roimap_phys_addr[i], roimap_virt_addr[i]); if (ret != TD_SUCCESS) { sample_print("ss_mpi_sys_mmz_free err: 0x%x", ret); } } } return TD_NULL; } td_s32 sample_comm_venc_send_roimap_frame(ot_vpss_grp vpss_grp, struct_venc_roimap_chn_info roimap_chn_info, ot_size size[], ot_venc_jpeg_roi_attr roi_attr[]) { td_s32 i; g_roimap_frame_param.thread_start = TD_TRUE; g_roimap_frame_param.vpss_grp = vpss_grp; g_roimap_frame_param.cnt = roimap_chn_info.cnt; for (i = 0; (i < roimap_chn_info.cnt) && (i < OT_VENC_MAX_CHN_NUM) && (i < OT_VPSS_MAX_PHYS_CHN_NUM); i++) { g_roimap_frame_param.venc_chn[i] = roimap_chn_info.venc_chn[i]; g_roimap_frame_param.vpss_chn[i] = roimap_chn_info.vpss_chn[i]; g_roimap_frame_param.size[i] = size[i]; g_roimap_frame_param.roi_attr[i] = roi_attr[i]; } return pthread_create(&g_venc_roimap_pid, 0, sample_comm_send_roimap_frame_proc, (td_void *)&g_roimap_frame_param); } static td_s32 sample_comm_set_file_name(td_s32 index, ot_venc_chn venc_chn, sample_comm_venc_stream_proc_info *stream_proc_info) { if (snprintf_s(stream_proc_info->file_name[index], FILE_NAME_LEN, FILE_NAME_LEN - 1, "./") < 0) { return SAMPLE_RETURN_NULL; } if (realpath(stream_proc_info->file_name[index], stream_proc_info->real_file_name[index]) == TD_NULL) { sample_print("chn[%d] stream file path error\n", venc_chn); return SAMPLE_RETURN_NULL; } if (snprintf_s(stream_proc_info->real_file_name[index], FILE_NAME_LEN, FILE_NAME_LEN - 1, "stream_chn%d%s", index, stream_proc_info->file_postfix) < 0) { return SAMPLE_RETURN_NULL; } return TD_SUCCESS; } static td_s32 sample_comm_set_name_save_stream(sample_comm_venc_stream_proc_info *stream_proc_info, ot_venc_stream_buf_info *stream_buf_info, ot_payload_type *payload_type, struct_venc_getstream_para *para, td_s32 venc_max_chn) { td_s32 i, ret, fd; ot_venc_chn_attr venc_chn_attr; ot_unused(venc_max_chn); for (i = 0; (i < stream_proc_info->chn_total) && (i < OT_VENC_MAX_CHN_NUM); i++) { /* decide the stream file name, and open file to save stream */ ot_venc_chn venc_chn = para->venc_chn[i]; ret = ss_mpi_venc_get_chn_attr(venc_chn, &venc_chn_attr); if (ret != TD_SUCCESS) { sample_print("ss_mpi_venc_get_chn_attr chn[%d] failed with %#x!\n", venc_chn, ret); return SAMPLE_RETURN_NULL; } payload_type[i] = venc_chn_attr.venc_attr.type; ret = sample_comm_venc_get_file_postfix(payload_type[i], stream_proc_info->file_postfix, sizeof(stream_proc_info->file_postfix)); if (ret != TD_SUCCESS) { sample_print("sample_comm_venc_get_file_postfix [%d] failed with %#x!\n", venc_chn_attr.venc_attr.type, ret); return SAMPLE_RETURN_NULL; } if (payload_type[i] != OT_PT_JPEG) { ret = sample_comm_set_file_name(i, venc_chn, stream_proc_info); if (ret != TD_SUCCESS) { return ret; } stream_proc_info->file[i] = fopen(stream_proc_info->real_file_name[i], "wb"); if (!stream_proc_info->file[i]) { sample_print("open file[%s] failed!\n", stream_proc_info->real_file_name[i]); return SAMPLE_RETURN_NULL; } fd = fileno(stream_proc_info->file[i]); fchmod(fd, S_IRUSR | S_IWUSR); } /* set venc fd. */ stream_proc_info->venc_fd[i] = ss_mpi_venc_get_fd(i); if (stream_proc_info->venc_fd[i] < 0) { sample_print("ss_mpi_venc_get_fd failed with %#x!\n", stream_proc_info->venc_fd[i]); return SAMPLE_RETURN_NULL; } if (stream_proc_info->maxfd <= stream_proc_info->venc_fd[i]) { stream_proc_info->maxfd = stream_proc_info->venc_fd[i]; } ret = ss_mpi_venc_get_stream_buf_info(i, &stream_buf_info[i]); if (ret != TD_SUCCESS) { sample_print("ss_mpi_venc_get_stream_buf_info failed with %#x!\n", ret); return SAMPLE_RETURN_FAILURE; } } return TD_SUCCESS; } static int32_t sample_heif_create(td_s32 index, const sample_comm_venc_stream_proc_info *stream_proc_info, heif_handle *hdl) { // heif_config config; // if (snprintf_s(config.file_desc.input.url, FILE_NAME_LEN, FILE_NAME_LEN - 1, // "./stream_chn%d_%d%s", index, stream_proc_info->picture_cnt[index], ".heic") < 0) { // return SAMPLE_RETURN_NULL; // } // config.file_desc.file_type = HEIF_FILE_TYPE_URL; // config.config_type = HEIF_CONFIG_MUXER; // config.muxer_config.is_grid = false; // config.muxer_config.row_image_num = 1; // config.muxer_config.column_image_num = 1; // config.muxer_config.format_profile = HEIF_PROFILE_HEIC; // return heif_create(hdl, &config); return 0; } static td_s32 sample_comm_save_h265_to_heic(td_s32 index, const sample_comm_venc_stream_proc_info *stream_proc_info, const ot_venc_stream *stream) { // td_u32 i; // td_u32 total_len = 0; // td_s32 has_key = 0; // for (i = 0; i < stream->pack_cnt; i++) { // if (stream->pack[i].data_type.h265_type == OT_VENC_H265_NALU_IDR_SLICE) { // has_key = 1; // } // total_len += stream->pack[i].len - stream->pack[i].offset; // } // if (total_len > 0 && has_key == 1) { // heif_handle handle = NULL; // td_s32 ret = sample_heif_create(index, stream_proc_info, &handle); // if (ret != 0) { // sample_print("HeifCreate error ret:%d\n", ret); // } // td_u8 *data_buffer = (td_u8 *)malloc(total_len); // if (data_buffer == NULL) { // sample_print("malloc error\n"); // heif_destroy(handle); // return SAMPLE_RETURN_NULL; // } // td_u32 write_len = 0; // for (i = 0; i < stream->pack_cnt; i++) { // if (memcpy_s(data_buffer + write_len, total_len - write_len, // stream->pack[i].addr + stream->pack[i].offset, stream->pack[i].len - stream->pack[i].offset) != EOK) { // sample_print("memcpy_s failed\n"); // } // write_len += stream->pack[i].len; // } // heif_image_item item = {0}; // item.timestamp = -1; // item.data = data_buffer; // item.length = write_len; // item.key_frame = true; // ret = heif_write_master_image(handle, 0, &item, 1); // if (data_buffer != NULL) { // free(data_buffer); // } // heif_destroy(handle); // return ret; // } return 0; } static td_s32 sample_comm_save_frame_to_file(td_s32 index, sample_comm_venc_stream_proc_info *stream_proc_info, ot_venc_stream *stream, ot_venc_stream_buf_info *stream_buf_info, ot_payload_type *payload_type) { td_s32 ret, fd; if (payload_type[index] == OT_PT_JPEG) { if (snprintf_s(stream_proc_info->file_name[index], FILE_NAME_LEN, FILE_NAME_LEN - 1, "./") < 0) { free(stream->pack); return SAMPLE_RETURN_NULL; } if (realpath(stream_proc_info->file_name[index], stream_proc_info->real_file_name[index]) == TD_NULL) { free(stream->pack); sample_print("chn[%d] stream file path error\n", stream_proc_info->venc_chn); return SAMPLE_RETURN_NULL; } if (snprintf_s(stream_proc_info->real_file_name[index], FILE_NAME_LEN, FILE_NAME_LEN - 1, "stream_chn%d_%d%s", index, stream_proc_info->picture_cnt[index], stream_proc_info->file_postfix) < 0) { free(stream->pack); return SAMPLE_RETURN_NULL; } stream_proc_info->file[index] = fopen(stream_proc_info->real_file_name[index], "wb"); if (!stream_proc_info->file[index]) { free(stream->pack); sample_print("open file err!\n"); return SAMPLE_RETURN_NULL; } fd = fileno(stream_proc_info->file[index]); fchmod(fd, S_IRUSR | S_IWUSR); } if (payload_type[index] == OT_PT_H265 && stream_proc_info->save_heif == TD_TRUE) { // (td_void)sample_comm_save_h265_to_heic(index, stream_proc_info, stream); } #ifndef __LITEOS__ ot_unused(stream_buf_info); ret = sample_comm_venc_save_stream(stream_proc_info->file[index], stream); #else ret = sample_comm_venc_save_stream_phys_addr(stream_proc_info->file[index], &stream_buf_info[index], stream); #endif if (ret != TD_SUCCESS) { free(stream->pack); stream->pack = TD_NULL; sample_print("save stream failed!\n"); return SAMPLE_RETURN_BREAK; } return TD_SUCCESS; } static td_s32 sample_comm_get_stream_from_one_channl(sample_comm_venc_stream_proc_info *stream_proc_info, td_s32 index, ot_venc_stream_buf_info *stream_buf_info, ot_payload_type *payload_type) { td_s32 ret; ot_venc_stream stream; ot_venc_chn_status stat; /* step 2.1 : query how many packs in one-frame stream. */ if (memset_s(&stream, sizeof(stream), 0, sizeof(stream)) != EOK) { printf("call memset_s error\n"); } ret = ss_mpi_venc_query_status(index, &stat); if (ret != TD_SUCCESS) { sample_print("ss_mpi_venc_query_status chn[%d] failed with %#x!\n", index, ret); return SAMPLE_RETURN_BREAK; } if (stat.cur_packs == 0) { sample_print("NOTE: current frame is TD_NULL!\n"); return SAMPLE_RETURN_CONTINUE; } /* step 2.3 : malloc corresponding number of pack nodes. */ stream.pack = (ot_venc_pack *)malloc(sizeof(ot_venc_pack) * stat.cur_packs); if (stream.pack == TD_NULL) { sample_print("malloc stream pack failed!\n"); return SAMPLE_RETURN_BREAK; } /* step 2.4 : call mpi to get one-frame stream */ stream.pack_cnt = stat.cur_packs; ret = ss_mpi_venc_get_stream(index, &stream, TD_TRUE); if (ret != TD_SUCCESS) { free(stream.pack); stream.pack = TD_NULL; sample_print("ss_mpi_venc_get_stream failed with %#x!\n", ret); return SAMPLE_RETURN_BREAK; } /* step 2.5 : save frame to file */ ret = sample_comm_save_frame_to_file(index, stream_proc_info, &stream, stream_buf_info, payload_type); if (ret != TD_SUCCESS) { return ret; } /* step 2.6 : release stream */ ret = ss_mpi_venc_release_stream(index, &stream); if (ret != TD_SUCCESS) { sample_print("ss_mpi_venc_release_stream failed!\n"); free(stream.pack); stream.pack = TD_NULL; return SAMPLE_RETURN_BREAK; } /* step 2.7 : free pack nodes */ free(stream.pack); stream.pack = TD_NULL; stream_proc_info->picture_cnt[index]++; if (payload_type[index] == OT_PT_JPEG) { fclose(stream_proc_info->file[index]); } return TD_SUCCESS; } static td_void sample_comm_fd_isset(sample_comm_venc_stream_proc_info *stream_proc_info, fd_set *read_fds, ot_venc_stream_buf_info *stream_buf_info, ot_payload_type *payload_type, struct_venc_getstream_para *para) { td_s32 i, ret; for (i = 0; (i < stream_proc_info->chn_total) && (i < OT_VENC_MAX_CHN_NUM); i++) { if (FD_ISSET(stream_proc_info->venc_fd[i], read_fds)) { stream_proc_info->venc_chn = para->venc_chn[i]; ret = sample_comm_get_stream_from_one_channl(stream_proc_info, i, stream_buf_info, payload_type); if (ret == SAMPLE_RETURN_CONTINUE) { continue; } else if (ret == SAMPLE_RETURN_BREAK) { break; } } } } /* get stream from each channels and save them */ td_void *sample_comm_venc_get_venc_stream_proc(td_void *p) { td_s32 i, ret; struct_venc_getstream_para *para = TD_NULL; struct timeval timeout_val; fd_set read_fds; ot_payload_type payload_type[OT_VENC_MAX_CHN_NUM] = {0}; ot_venc_stream_buf_info stream_buf_info[OT_VENC_MAX_CHN_NUM]; sample_comm_venc_stream_proc_info stream_proc_info = {0}; prctl(PR_SET_NAME, "get_venc_stream", 0, 0, 0); para = (struct_venc_getstream_para *)p; stream_proc_info.chn_total = para->cnt; stream_proc_info.save_heif = para->save_heif; /* step 1: check & prepare save-file & venc-fd */ if (stream_proc_info.chn_total >= OT_VENC_MAX_CHN_NUM) { sample_print("input count invalid\n"); return TD_NULL; } ret = sample_comm_set_name_save_stream(&stream_proc_info, stream_buf_info, payload_type, para, OT_VENC_MAX_CHN_NUM); if (ret == SAMPLE_RETURN_NULL) { return TD_NULL; } else if (ret == SAMPLE_RETURN_FAILURE) { return (void *)TD_FAILURE; } /* step 2: start to get streams of each channel. */ while (para->thread_start == TD_TRUE) { FD_ZERO(&read_fds); for (i = 0; (i < stream_proc_info.chn_total) && (i < OT_VENC_MAX_CHN_NUM); i++) { FD_SET(stream_proc_info.venc_fd[i], &read_fds); } timeout_val.tv_sec = 2; /* 2 is a number */ timeout_val.tv_usec = 0; ret = select(stream_proc_info.maxfd + 1, &read_fds, TD_NULL, TD_NULL, &timeout_val); if (ret < 0) { sample_print("select failed!\n"); break; } else if (ret == 0) { sample_print("get venc stream time out, exit thread\n"); continue; } else { sample_comm_fd_isset(&stream_proc_info, &read_fds, stream_buf_info, payload_type, para); } } /* step 3 : close save-file */ for (i = 0; i < stream_proc_info.chn_total; i++) { if (payload_type[i] != OT_PT_JPEG) { fclose(stream_proc_info.file[i]); } } return TD_NULL; } /****************************************************************************** * function : bitrate_auto ******************************************************************************/ #define SAMPLE_VENC_WIDHT 640 #define SAMPLE_VENC_HEIGHT 480 #define SAMPLE_VENC_NUM 5 #define SAMPLE_VENC_FG_TYPE 5 #define QUERY_SLEEP 1000 td_void sample_comm_venc_set_region(td_u64 time, ot_venc_chn venc_chn, ot_venc_svc_rect_info *pst_svc_rect) { td_s32 j, ret; td_u32 attrx[SAMPLE_VENC_NUM] = {32, 96, 128, 192, 256}; // 32 96 128 192 256 : X-coordinate td_u32 attry[SAMPLE_VENC_NUM] = {32, 96, 128, 192, 256}; // 32 96 128 192 256 : Y-coordinate td_u32 attrw[SAMPLE_VENC_NUM] = {32, 64, 96, 96, 64}; // 32 64 96 96 64 : width td_u32 attrh[SAMPLE_VENC_NUM] = {32, 64, 96, 96, 64}; // 32 64 96 96 64 : height td_u32 type[SAMPLE_VENC_NUM] = {0, 3, 4, 1, 2}; // 0 3 4 1 2 : type pst_svc_rect->rect_num = SAMPLE_VENC_NUM; pst_svc_rect->pts = time; pst_svc_rect->base_resolution.width = SAMPLE_VENC_WIDHT; pst_svc_rect->base_resolution.height = SAMPLE_VENC_HEIGHT; for (j = 0; (j < SAMPLE_VENC_NUM) && (j < OT_VENC_MAX_SVC_RECT_NUM); j++) { pst_svc_rect->detect_type[j] = type[j]; pst_svc_rect->rect_attr[j].x = attrx[j]; pst_svc_rect->rect_attr[j].y = attry[j]; pst_svc_rect->rect_attr[j].width = attrw[j]; pst_svc_rect->rect_attr[j].height = attrh[j]; } ret = ss_mpi_venc_send_svc_region(venc_chn, pst_svc_rect); if (ret != TD_SUCCESS) { sample_print("Set ss_mpi_venc_send_svc_region failed for %#x chn =%d\n", ret, venc_chn); } } td_void sample_comm_venc_set_svc_param(ot_venc_chn venc_chn, ot_venc_svc_param *pst_svc_param) { td_s32 j, ret; td_u32 qp_i[SAMPLE_VENC_NUM] = {2, 62, 94, 1, 0}; // 2 62 94 1 0 : fg I frame qp td_u32 qp_p[SAMPLE_VENC_NUM] = {4, 58, 94, 2, 0}; // 4 58 94 2 0 : fg P frame qp ret = ss_mpi_venc_get_svc_param(venc_chn, pst_svc_param); if (ret != TD_SUCCESS) { sample_print("Set ss_mpi_venc_set_svc_param failed for %#x chn =%d\n", ret, venc_chn); } pst_svc_param->fg_protect_adaptive_en = TD_TRUE; pst_svc_param->activity_region.qpmap_value_i = 0; pst_svc_param->activity_region.qpmap_value_p = 0; pst_svc_param->activity_region.skipmap_value = 0; pst_svc_param->bg_region.qpmap_value_i = 2; // 2 :i frame bg qp pst_svc_param->bg_region.qpmap_value_p = 6; // 6 :p frame bg qp pst_svc_param->bg_region.skipmap_value = 0; for (j = 0; (j < SAMPLE_VENC_NUM) && (j < SVC_RECT_TYPE_BUTT); j++) { pst_svc_param->fg_region[j].qpmap_value_i = qp_i[j]; pst_svc_param->fg_region[j].qpmap_value_p = qp_p[j]; pst_svc_param->fg_region[j].skipmap_value = 0; } ret = ss_mpi_venc_set_svc_param(venc_chn, pst_svc_param); if (ret != TD_SUCCESS) { sample_print("Set ss_mpi_venc_set_svc_param failed for %#x!\n", ret); } } td_void *sample_comm_venc_rateauto_stream_proc(td_void *p) { td_s32 i, ret; struct_venc_rateauto_para *para; ot_venc_svc_param svc_param; ot_vpss_chn_attr vpss_chn_attr; ot_venc_svc_rect_info svc_rect_info = {0}; para = (struct_venc_rateauto_para *)p; ot_video_frame_info video_frame; prctl(PR_SET_NAME, "get_venc_rateauto_stream", 0, 0, 0); if (para->cnt >= OT_VENC_MAX_CHN_NUM) { sample_print("input count invalid\n"); return TD_NULL; } for (i = 0; (i < para->cnt) && (i < OT_VENC_MAX_CHN_NUM); i++) { ret = ss_mpi_vpss_get_chn_attr(para->vpss_grp, para->vpss_chn[i], &vpss_chn_attr); if (ret != TD_SUCCESS) { sample_print("ss_mpi_vpss_get_chn_attr err: 0x%x", ret); } vpss_chn_attr.depth = 3; /* 3 is a number */ ret = ss_mpi_vpss_set_chn_attr(para->vpss_grp, para->vpss_chn[i], &vpss_chn_attr); if (ret != TD_SUCCESS) { sample_print("ss_mpi_vpss_set_chn_attr err: 0x%x", ret); } } while (para->thread_start == TD_TRUE) { for (i = 0; (i < para->cnt) && (i < OT_VENC_MAX_CHN_NUM); i++) { ret = ss_mpi_vpss_get_chn_frame(para->vpss_grp, para->vpss_chn[i], &video_frame, QUERY_SLEEP); if (ret != TD_SUCCESS) { sample_print("ss_mpi_vpss_get_chn_frame err:0x%x venc_chn = %d\n", ret, para->venc_chn[i]); continue; } ret = ss_mpi_vpss_release_chn_frame(para->vpss_grp, para->vpss_chn[i], &video_frame); if (ret != TD_SUCCESS) { sample_print("ss_mpi_vpss_release_chn_frame err:0x%x\n", ret); return TD_NULL; } ret = ss_mpi_venc_enable_svc(para->venc_chn[i], TD_TRUE); if (ret != TD_SUCCESS) { sample_print("Set ss_mpi_venc_enable_svc failed for %#x!\n", ret); return TD_NULL; } sample_comm_venc_set_region(video_frame.video_frame.pts, para->venc_chn[i], &svc_rect_info); sample_comm_venc_set_svc_param(para->venc_chn[i], &svc_param); } usleep(QUERY_SLEEP); } return TD_NULL; } static td_s32 sample_comm_set_file_name_svc_t(sample_comm_venc_stream_proc_info *stream_proc_info, td_s32 index) { if (snprintf_s(stream_proc_info->file_name[index], FILE_NAME_LEN, FILE_NAME_LEN - 1, "./") < 0) { return TD_NULL; } if (realpath(stream_proc_info->file_name[index], stream_proc_info->real_file_name[index]) == TD_NULL) { printf("file path error\n"); return TD_NULL; } if (snprintf_s(stream_proc_info->real_file_name[index], FILE_NAME_LEN, FILE_NAME_LEN - 1, "tid%d%s", index, stream_proc_info->file_postfix) < 0) { return TD_NULL; } return TD_SUCCESS; } static td_s32 sample_comm_set_name_save_stream_svc_t(sample_comm_venc_stream_proc_info *stream_proc_info, ot_venc_stream_buf_info *stream_buf_info, td_s32 venc_max_chn) { td_s32 i, ret, cnt, fd; ot_venc_chn_attr venc_chn_attr; ot_payload_type payload_type[OT_VENC_MAX_CHN_NUM]; ot_unused(venc_max_chn); for (i = 0; i < stream_proc_info->chn_total; i++) { /* decide the stream file name, and open file to save stream */ stream_proc_info->venc_chn = i; ret = ss_mpi_venc_get_chn_attr(stream_proc_info->venc_chn, &venc_chn_attr); if (ret != TD_SUCCESS) { sample_print("ss_mpi_venc_get_chn_attr chn[%d] failed with %#x!\n", stream_proc_info->venc_chn, ret); return SAMPLE_RETURN_NULL; } payload_type[i] = venc_chn_attr.venc_attr.type; ret = sample_comm_venc_get_file_postfix(payload_type[i], stream_proc_info->file_postfix, sizeof(stream_proc_info->file_postfix)); if (ret != TD_SUCCESS) { sample_print("sample_comm_venc_get_file_postfix [%d] failed with %#x!\n", venc_chn_attr.venc_attr.type, ret); return SAMPLE_RETURN_NULL; } for (cnt = 0; cnt < 3; cnt++) { /* 3 is a number */ if (sample_comm_set_file_name_svc_t(stream_proc_info, (i + cnt)) != TD_SUCCESS) { return SAMPLE_RETURN_NULL; } stream_proc_info->file[i + cnt] = fopen(stream_proc_info->real_file_name[i + cnt], "wb"); if (!stream_proc_info->file[i + cnt]) { sample_print("open file[%s] failed!\n", stream_proc_info->real_file_name[i + cnt]); return SAMPLE_RETURN_NULL; } fd = fileno(stream_proc_info->file[i + cnt]); fchmod(fd, S_IRUSR | S_IWUSR); } /* set venc fd. */ stream_proc_info->venc_fd[i] = ss_mpi_venc_get_fd(i); if (stream_proc_info->venc_fd[i] < 0) { sample_print("ss_mpi_venc_get_fd failed with %#x!\n", stream_proc_info->venc_fd[i]); return SAMPLE_RETURN_NULL; } if (stream_proc_info->maxfd <= stream_proc_info->venc_fd[i]) { stream_proc_info->maxfd = stream_proc_info->venc_fd[i]; } ret = ss_mpi_venc_get_stream_buf_info(i, &stream_buf_info[i]); if (ret != TD_SUCCESS) { sample_print("ss_mpi_venc_get_stream_buf_info failed with %#x!\n", ret); return SAMPLE_RETURN_FAILURE; } } return TD_SUCCESS; } static td_void sample_comm_save_frame_to_file_svc_t(td_s32 index, sample_comm_venc_stream_proc_info *stream_proc_info, ot_venc_stream *stream, ot_venc_stream_buf_info *stream_buf_info) { td_s32 cnt, ret; for (cnt = 0; cnt < 3; cnt++) { /* 3 is a number */ switch (cnt) { case 0: /* 0 is a number */ if (stream->h264_info.ref_type == OT_VENC_BASE_IDR_SLICE || stream->h264_info.ref_type == OT_VENC_BASE_P_SLICE_REF_BY_BASE) { #ifndef __LITEOS__ ot_unused(stream_buf_info); ret = sample_comm_venc_save_stream(stream_proc_info->file[index + cnt], stream); #else ret = sample_comm_venc_save_stream_phys_addr(stream_proc_info->file[index + cnt], &stream_buf_info[index], stream); #endif } break; case 1: /* 1 is a number */ if (stream->h264_info.ref_type == OT_VENC_BASE_IDR_SLICE || stream->h264_info.ref_type == OT_VENC_BASE_P_SLICE_REF_BY_BASE || stream->h264_info.ref_type == OT_VENC_BASE_P_SLICE_REF_BY_ENHANCE) { #ifndef __LITEOS__ ret = sample_comm_venc_save_stream(stream_proc_info->file[index + cnt], stream); #else ret = sample_comm_venc_save_stream_phys_addr(stream_proc_info->file[index + cnt], &stream_buf_info[index], stream); #endif } break; case 2: /* 2 is a number */ #ifndef __LITEOS__ ret = sample_comm_venc_save_stream(stream_proc_info->file[index + cnt], stream); #else ret = sample_comm_venc_save_stream_phys_addr(stream_proc_info->file[index + cnt], &stream_buf_info[index], stream); #endif break; default: break; } if (ret != TD_SUCCESS) { free(stream->pack); stream->pack = TD_NULL; sample_print("save stream failed!\n"); break; } } } static td_s32 sample_comm_get_stream_from_one_channl_svc_t(sample_comm_venc_stream_proc_info *stream_proc_info, td_s32 index, ot_venc_stream_buf_info *stream_buf_info) { td_s32 ret; ot_venc_stream stream; ot_venc_chn_status stat; /* step 2.1 : query how many packs in one-frame stream. */ if (memset_s(&stream, sizeof(stream), 0, sizeof(stream)) != EOK) { printf("call memset_s error\n"); } ret = ss_mpi_venc_query_status(index, &stat); if (ret != TD_SUCCESS) { sample_print("ss_mpi_venc_query chn[%d] failed with %#x!\n", index, ret); return SAMPLE_RETURN_BREAK; } if (stat.cur_packs == 0) { sample_print("NOTE: current frame is TD_NULL!\n"); return SAMPLE_RETURN_CONTINUE; } /* step 2.3 : malloc corresponding number of pack nodes. */ stream.pack = (ot_venc_pack *)malloc(sizeof(ot_venc_pack) * stat.cur_packs); if (stream.pack == TD_NULL) { sample_print("malloc stream pack failed!\n"); return SAMPLE_RETURN_BREAK; } /* step 2.4 : call mpi to get one-frame stream */ stream.pack_cnt = stat.cur_packs; ret = ss_mpi_venc_get_stream(index, &stream, TD_TRUE); if (ret != TD_SUCCESS) { free(stream.pack); stream.pack = TD_NULL; sample_print("ss_mpi_venc_get_stream failed with %#x!\n", ret); return SAMPLE_RETURN_BREAK; } /* step 2.5 : save frame to file */ sample_comm_save_frame_to_file_svc_t(index, stream_proc_info, &stream, stream_buf_info); /* step 2.6 : release stream */ ret = ss_mpi_venc_release_stream(index, &stream); if (ret != TD_SUCCESS) { free(stream.pack); stream.pack = TD_NULL; return SAMPLE_RETURN_BREAK; } /* step 2.7 : free pack nodes */ free(stream.pack); stream.pack = TD_NULL; return TD_SUCCESS; } static td_void sample_comm_fd_isset_svc_t(sample_comm_venc_stream_proc_info *stream_proc_info, fd_set *read_fds, ot_venc_stream_buf_info *stream_buf_info, td_s32 venc_max_chn) { td_s32 i, ret; ot_unused(venc_max_chn); for (i = 0; i < stream_proc_info->chn_total; i++) { if (FD_ISSET(stream_proc_info->venc_fd[i], read_fds)) { ret = sample_comm_get_stream_from_one_channl_svc_t(stream_proc_info, i, stream_buf_info); if (ret == SAMPLE_RETURN_CONTINUE) { continue; } else if (ret == SAMPLE_RETURN_BREAK) { break; } } } } /* get svc_t stream from h264 channels and save them */ td_void *sample_comm_venc_get_venc_stream_proc_svc_t(td_void *p) { td_s32 i, ret; td_s32 cnt = 0; struct_venc_getstream_para *para = TD_NULL; struct timeval timeout_val; fd_set read_fds; ot_venc_stream_buf_info stream_buf_info[OT_VENC_MAX_CHN_NUM]; sample_comm_venc_stream_proc_info stream_proc_info = {0}; para = (struct_venc_getstream_para *)p; stream_proc_info.chn_total = para->cnt; stream_proc_info.save_heif = para->save_heif; /* step 1: check & prepare save-file & venc-fd */ if (stream_proc_info.chn_total >= OT_VENC_MAX_CHN_NUM) { sample_print("input count invalid\n"); return TD_NULL; } ret = sample_comm_set_name_save_stream_svc_t(&stream_proc_info, stream_buf_info, OT_VENC_MAX_CHN_NUM); if (ret == SAMPLE_RETURN_NULL) { return TD_NULL; } else if (ret == SAMPLE_RETURN_FAILURE) { return (void *)TD_FAILURE; } /* step 2: start to get streams of each channel. */ while (para->thread_start == TD_TRUE) { FD_ZERO(&read_fds); for (i = 0; i < stream_proc_info.chn_total; i++) { FD_SET(stream_proc_info.venc_fd[i], &read_fds); } timeout_val.tv_sec = 2; /* 2 is a number */ timeout_val.tv_usec = 0; ret = select(stream_proc_info.maxfd + 1, &read_fds, TD_NULL, TD_NULL, &timeout_val); if (ret < 0) { sample_print("select failed!\n"); break; } else if (ret == 0) { sample_print("get venc stream time out, exit thread\n"); continue; } else { sample_comm_fd_isset_svc_t(&stream_proc_info, &read_fds, stream_buf_info, OT_VENC_MAX_CHN_NUM); } } /* step 3 : close save-file */ for (i = 0; i < stream_proc_info.chn_total; i++) { for (cnt = 0; cnt < 3; cnt++) { /* 3 is a number */ if (stream_proc_info.file[i + cnt]) { fclose(stream_proc_info.file[i + cnt]); } } } return TD_NULL; } td_void sample_comm_venc_set_save_heif(td_bool save_heif) { g_para.save_heif = save_heif; sample_print("set save heif flag: %d!\n", save_heif); } /* start get venc stream process thread */ td_s32 sample_comm_venc_start_get_stream(ot_venc_chn *venc_chn, td_s32 cnt) { td_s32 i; g_para.thread_start = TD_TRUE; g_para.cnt = cnt; for (i = 0; (i < cnt) && (i < OT_VENC_MAX_CHN_NUM); i++) { g_para.venc_chn[i] = venc_chn[i]; } return pthread_create(&g_venc_pid, 0, sample_comm_venc_get_venc_stream_proc, (td_void *)&g_para); } /****************************************************************************** * function : start rate auto process thread ******************************************************************************/ td_s32 sample_comm_venc_rateauto_start(ot_venc_chn venc_chn[], td_s32 cnt, ot_vpss_grp vpss_grp, ot_vpss_chn vpss_chn[]) { td_s32 i; g_venc_rateauto_frame_param.thread_start = TD_TRUE; g_venc_rateauto_frame_param.cnt = cnt; g_venc_rateauto_frame_param.vpss_grp = vpss_grp; for (i = 0; (i < cnt) && (i < OT_VENC_MAX_CHN_NUM); i++) { g_venc_rateauto_frame_param.venc_chn[i] = venc_chn[i]; g_venc_rateauto_frame_param.vpss_chn[i] = vpss_chn[i]; } return pthread_create(&g_venc_rateauto_pid, 0, sample_comm_venc_rateauto_stream_proc, (td_void *)&g_venc_rateauto_frame_param); } /* start get venc svc-t stream process thread */ td_s32 sample_comm_venc_start_get_stream_svc_t(td_s32 cnt) { g_para.thread_start = TD_TRUE; g_para.cnt = cnt; return pthread_create(&g_venc_pid, 0, sample_comm_venc_get_venc_stream_proc_svc_t, (td_void *)&g_para); } /* stop get venc stream process. */ td_s32 sample_comm_venc_stop_get_stream(td_s32 chn_num) { td_s32 i; for (i = 0; i < chn_num; i++) { if (ss_mpi_venc_stop_chn(i) != TD_SUCCESS) { sample_print("chn %d ss_mpi_venc_stop_recv_pic failed!\n", i); return TD_FAILURE; } } if (g_para.thread_start == TD_TRUE) { g_para.thread_start = TD_FALSE; pthread_join(g_venc_pid, 0); } return TD_SUCCESS; } td_s32 sample_comm_venc_stop_send_qpmap_frame(td_void) { if (g_qpmap_send_frame_para.thread_start == TD_TRUE) { g_qpmap_send_frame_para.thread_start = TD_FALSE; pthread_join(g_venc_qpmap_pid, 0); } return TD_SUCCESS; } td_s32 sample_comm_venc_stop_send_roimap_frame(td_void) { if (g_roimap_frame_param.thread_start == TD_TRUE) { g_roimap_frame_param.thread_start = TD_FALSE; pthread_join(g_venc_roimap_pid, 0); } return TD_SUCCESS; } td_s32 sample_comm_venc_stop_rateauto(ot_venc_chn chn[], td_s32 cnt) { td_s32 i, ret; prctl(PR_SET_NAME, "sample_comm_venc_stop_rateauto", 0, 0, 0); ot_venc_svc_param svc_param = {0}; ot_venc_chn venc_chn; ot_venc_svc_rect_info svc_rect_info = {0}; if (g_venc_rateauto_frame_param.thread_start == TD_TRUE) { g_venc_rateauto_frame_param.thread_start = TD_FALSE; pthread_join(g_venc_rateauto_pid, 0); for (i = 0; i < cnt; i++) { venc_chn = chn[i]; ret = ss_mpi_venc_enable_svc(venc_chn, TD_TRUE); if (ret != TD_SUCCESS) { sample_print("Set ss_mpi_venc_enable_svc failed for %#x chn =%d\n", ret, venc_chn); } if (memset_s(&svc_rect_info, sizeof(ot_venc_svc_rect_info), 0, sizeof(ot_venc_svc_rect_info)) != EOK) { printf("call memset_s error\n"); } ret = ss_mpi_venc_send_svc_region(venc_chn, &svc_rect_info); if (ret != TD_SUCCESS) { sample_print("Set ss_mpi_venc_send_svc_region failed for %#x chn =%d\n", ret, venc_chn); } ret = ss_mpi_venc_get_svc_param(venc_chn, &svc_param); if (ret != TD_SUCCESS) { sample_print("Set ss_mpi_venc_set_svc_param failed for %#x chn =%d\n", ret, venc_chn); } if (memset_s(&svc_param, sizeof(ot_venc_svc_param), 0, sizeof(ot_venc_svc_param)) != EOK) { printf("call memset_s error\n"); } ret = ss_mpi_venc_set_svc_param(venc_chn, &svc_param); if (ret != TD_SUCCESS) { sample_print("Set ss_mpi_venc_set_svc_param failed for %#x chn =%d\n", ret, venc_chn); } ret = ss_mpi_venc_enable_svc(venc_chn, TD_FALSE); if (ret != TD_SUCCESS) { sample_print("Set ss_mpi_venc_enable_svc failed for %#x chn =%d\n", ret, venc_chn); } } } return TD_SUCCESS; } td_s32 sample_comm_venc_plan_to_semi(td_u8 *u, td_s32 u_stride, td_u8 *v, td_s32 pic_height) { td_s32 i; td_u8 *tmp_u = TD_NULL; td_u8 *ptu = TD_NULL; td_u8 *tmp_v = TD_NULL; td_u8 *ptv = TD_NULL; td_s32 haf_w = u_stride / 2; /* 2: half */ td_s32 haf_h = pic_height / 2; /* 2: half */ td_s32 size = haf_w * haf_h; tmp_u = malloc(size); if (tmp_u == TD_NULL) { printf("malloc buf failed\n"); return TD_FAILURE; } ptu = tmp_u; tmp_v = malloc(size); if (tmp_v == TD_NULL) { printf("malloc buf failed\n"); free(tmp_u); return TD_FAILURE; } ptv = tmp_v; if (memcpy_s(tmp_u, size, u, size) != EOK) { printf("call memcpy_s error\n"); free(tmp_u); free(tmp_v); return TD_FAILURE; } if (memcpy_s(tmp_v, size, v, size) != EOK) { printf("call memcpy_s error\n"); free(tmp_u); free(tmp_v); return TD_FAILURE; } for (i = 0; i < (size / 2); i++) { /* 2: half */ *u++ = *tmp_v++; *u++ = *tmp_u++; } for (i = 0; i < (size / 2); i++) { /* 2: half */ *v++ = *tmp_v++; *v++ = *tmp_u++; } free(ptu); free(ptv); return TD_SUCCESS; }