海思开发笔记一:hi3516cv610例程流程
若该文为原创文章,转载请注明原文出处。最近有在了解HI3516CV610的SDK,程序编译有点不一样,原本想把所有程序独立出来使用Makefile来处理,由于时间,没有继续了,这里记录下一些流程。
若该文为原创文章,转载请注明原文出处。
最近有在了解HI3516CV610的SDK,程序编译有点不一样,原本想把所有程序独立出来使用Makefile来处理,由于时间,没有继续了,这里记录下一些流程。
一、VENC正常模式
# VENC 正常模式 H.265e@2560x1440@30fps + h264e@1280x720@30fps
td_s32 main(td_s32 argc, td_char *argv[])
sample_ipc_server_init # IPC 服务初始化
g_msg_proc_func = msg_proc_func;
if (pthread_create(&g_server_msg_thd, NULL, server_msg_handler, NULL) != 0) {
sample_venc_normal # 正常模式
# 步骤0:相关参数已准备就绪
enc_param.venc_chn_num = CHN_NUM_MAX; # 2个通道
# 设置IPC尺寸 [0]通道:SC4336P_MIPI_3M_30FPS_10BIT PIC_2304X1296 [1]通道:720 * 480
sample_venc_set_pic_size_0(sns_type, pic_size);
# 获取编码的长度
sample_venc_get_enc_size
# 设置VPSS 和 VENC 通道
sample_set_venc_vpss_chn
# 步骤1:初始化系统分配公共变量
sample_venc_online_wrap_start_sys_vi_vpss
sample_venc_online_wrap_sys_init
sample_venc_vi_init
sample_venc_online_wrap_start_vpss
sample_comm_vi_bind_vpss
# 启动正常模式编码
sample_venc_normal_start_encode
sample_comm_venc_get_gop_attr
# 设置venc通道参数
sample_venc_set_video_param
sample_comm_venc_mini_buf_en
# 启动编码
sample_comm_venc_start
# 编订venc
sample_comm_vpss_bind_venc
sample_comm_venc_start
sample_comm_vpss_bind_venc
# 获取流
sample_comm_venc_start_get_stream
# 创建获取流线程
ret = pthread_create(&g_venc_pid, 0, sample_comm_venc_get_venc_stream_proc, (td_void *)&g_para);
sample_comm_fd_isset(stream_proc_info, &read_fds, stream_buf_info, payload_type, para);
ret = sample_comm_get_stream_from_one_channl(stream_proc_info, i, stream_buf_info, payload_type);
# 步骤2.1:查询一帧流中包含多少个数据包。
ret = ss_mpi_venc_query_status(index, &stat);
# 步骤2.3:分配相应数量的包节点
stream.pack = (ot_venc_pack *)malloc(sizeof(ot_venc_pack) * stat.cur_packs);
# 步骤2.4:调用MPI获取一帧流
ret = ss_mpi_venc_get_stream(index, &stream, TD_TRUE);
# 步骤2.5:将帧保存到文件
ret = sample_comm_save_frame_to_file(index, stream_proc_info, &stream, stream_buf_info, payload_type);
ret = sample_comm_venc_save_stream(stream_proc_info->file[index], stream);
# 写入文件
for (i = 0; i < stream->pack_cnt; i++) {
(td_void)fwrite(stream->pack[i].addr + stream->pack[i].offset,
stream->pack[i].len - stream->pack[i].offset, 1, fd);
(td_void)fflush(fd);
}
# 步骤2.6:释放流
ret = ss_mpi_venc_release_stream(index, &stream);
# 退出线程
sample_venc_exit_process();
# 解除绑定关系
sample_venc_unbind_vpss_stop(vpss_grp, &venc_vpss_chn);
二、 rtsp流
td_s32 main(td_s32 argc, td_char *argv[]) # 主程序入口
# 信号量
sample_sys_signal(sample_venc_handle_sig);
# 554端口创建rtspserver
g_rtsplive = create_rtsp_demo(554);
# 创建rtsp会话
session= create_rtsp_session(g_rtsplive,"/test.264");
# 正常模式
sample_venc_normal
pic_size[0] = BIG_STREAM_SIZE;
pic_size[1] = SMALL_STREAM_SIZE;
sample_venc_get_enc_size(pic_size, &enc_param);
sample_set_venc_vpss_chn(&venc_vpss_chn, enc_param.venc_chn_num);
sample_venc_online_wrap_start_sys_vi_vpss
sample_venc_online_wrap_sys_init
sample_venc_vi_init
sample_venc_online_wrap_start_vpss
sample_comm_vi_bind_vpss
sample_venc_normal_start_encode
sample_comm_venc_get_gop_attr
sample_venc_set_video_param
sample_comm_venc_mini_buf_en
sample_comm_venc_start
sample_comm_vpss_bind_venc
sample_comm_venc_start
sample_comm_vpss_bind_venc
#获取流
sample_easyvenc_comm_venc_start_get_stream
pthread_create(&g_venc_pid, 0, sample_easyvenc_comm_venc_get_venc_stream_proc, (td_void *)&g_para)
# 设置保存的名称
sample_easyvenc_comm_set_name_save_stream
# 获取流
sample_easyvenc_comm_fd_isset(stream_proc_info, &read_fds, stream_buf_info, payload_type, para);
sample_easyvenc_comm_get_stream_from_one_channl(stream_proc_info, i, stream_buf_info, payload_type);
ret = ss_mpi_venc_query_status(index, &stat);
stream.pack = (ot_venc_pack *)malloc(sizeof(ot_venc_pack) * stat.cur_packs);
ret = ss_mpi_venc_get_stream(index, &stream, TD_TRUE);
ret = sample_easyvenc_comm_save_frame_to_file(index, stream_proc_info, &stream, stream_buf_info, payload_type);
//rtsp发送
td_u8 * pStremData = NULL;int nSize = 0;td_u32 j;
if(index==1){//发送venc通道1
for (j = 0; j < stream->pack_cnt; j++) {
//(td_void)fwrite(stream->pack[j].addr + stream->pack[j].offset, stream->pack[j].len - stream->pack[j].offset, 1, fd);
if(stream->pack[j].data_type.h264_type == OT_VENC_H264_NALU_SEI) continue;//暂时去掉SEI帧
pStremData = stream->pack[j].addr + stream->pack[j].offset;
nSize = stream->pack[j].len - stream->pack[j].offset;
if(g_rtsplive)
{
rtsp_sever_tx_video(g_rtsplive,session,pStremData,nSize,stream->pack[j].pts);
}
}
}
ret = ss_mpi_venc_release_stream(index, &stream);
# 停止获取流
sample_comm_venc_stop_get_stream
sample_venc_unbind_vpss_stop
sample_venc_online_wrap_stop_sys_vi_vpss
三、 rtmp
////////////////////////////swann这里添加rtsp发送//////////////////////////////
//rtsp发送
td_u8 * pStremData = NULL;int nSize = 0;td_u32 j;
if(index==1){//发送venc通道1
for (j = 0; j < stream->pack_cnt; j++) {
//(td_void)fwrite(stream->pack[j].addr + stream->pack[j].offset, stream->pack[j].len - stream->pack[j].offset, 1, fd);
if(stream->pack[j].data_type.h264_type == OT_VENC_H264_NALU_SEI) continue;//暂时去掉SEI帧
pStremData = stream->pack[j].addr + stream->pack[j].offset;
nSize = stream->pack[j].len - stream->pack[j].offset;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////
unsigned char sps_pps_buffer[128]={0};
int spslen=0;
for (j = 0; j < stream->pack_cnt; j++)
{
if(stream->pack[j].data_type.h264_type==OT_VENC_H264_NALU_SPS)
{
memcpy(sps_pps_buffer, stream->pack[j].addr, stream->pack[j].len);
spslen = stream->pack[j].len;
timeCount = RTMP_GetTime();
continue;
}
if(stream->pack[j].data_type.h264_type==OT_VENC_H264_NALU_PPS)
{
memcpy(sps_pps_buffer+spslen, stream->pack[j].addr, stream->pack[j].len);
rtmp_sender_write_video_frame(prtmp, sps_pps_buffer, stream->pack[j].len+spslen,
timeCount, 0,start_time);
timeCount = RTMP_GetTime();
continue;
}
if(stream->pack[j].data_type.h264_type==OT_VENC_H264_NALU_SEI)
{
continue;
}
rtmp_sender_write_video_frame(prtmp, stream->pack[j].addr, stream->pack[j].len,
timeCount, 0,start_time);
timeCount = RTMP_GetTime();
}
//////////////////////////////////////////////////////////////////////////////////////////////////
四、音频
主要功能模块
1. 音频采集与播放(AI to AO)
sample_audio_ai_ao: 实现音频输入(AI)到音频输出(AO)的循环,支持音量控制和淡入淡出效果
sample_audio_ai_to_ao_sys_chn: 将AI通道绑定到系统通道后输出到AO
2. 音频编码与解码
sample_audio_ai_aenc: 音频输入通过编码器(AENC)编码后保存到文件
sample_audio_adec_ao: 从文件读取音频流,通过解码器(ADEC)解码后播放
3. 音频处理与增强
sample_audio_ai_vqe_process_ao: 使用VQE(语音质量增强)处理音频后播放
sample_audio_ai_to_ext_resample: 使用外部重采样器处理音频
usage: ./sample_audio <index> [encoder_type|decoder_type|vqe_type] [decode_file_path]
index:
0: AI到AO循环播放
1: AI采集->AENC编码->保存文件
2: 文件->ADEC解码->AO播放
3: AI采集->VQE处理->AO播放
4: AI到AO系统通道循环
5: AI采集->外部重采样->保存文件
1、 实现音频输入(AI)到音频输出(AO)的循环
s1tatic td_void main_inner(td_u32 index)
sample_audio_ai_ao
# 初始化参数
sample_audio_ai_ao_init_param(&aio_attr, &ai_dev, &ao_dev);
# 设置参数
sample_audio_set_ai_vqe_param(&ai_vqe_param, g_out_sample_rate, g_aio_resample, TD_NULL, 0);
# 启动音频输入(AI)
sample_comm_audio_start_ai(ai_dev, ai_chn_cnt, &aio_attr, &ai_vqe_param, -1);
# 启动音频输出(AO)
sample_comm_audio_start_ao(ao_dev, ao_chn_cnt, &aio_attr, g_in_sample_rate, g_aio_resample);
# 配件内部音频编码器
ret = sample_comm_audio_cfg_acodec(&aio_attr);
# 绑定AI到AO,控制音量等
sample_audio_ai_ao_inner(ai_dev, ai_chn, ao_dev, ao_chn);
sample_comm_audio_create_thread_ao_vol_ctrl(ao_dev);
2、从文件读取音频流,通过解码器(ADEC)解码后播放
sample_audio_adec_ao
sample_audio_adec_ao_init_param(&aio_attr, &ao_dev);
sample_comm_audio_start_adec
ss_mpi_adec_create_chn(ad_chn, &adec_attr);
sample_comm_audio_start_ao
sample_comm_audio_cfg_acodec
sample_audio_adec_ao_inner
sample_comm_audio_ao_bind_adec
sample_audio_open_adec_file
sample_comm_audio_create_thread_file_adec
pthread_create(&adec->ad_pid, 0, sample_comm_audio_adec_proc, adec);
read_len = fread(audio_stream.stream, 1, len, fd);
ss_mpi_adec_send_stream(adec_chn, &audio_stream, TD_TRUE);
3、 AI采集->AENC编码->保存文件
sample_audio_ai_aenc
sample_audio_ai_aenc_init_param(&aio_attr, &ai_dev, &ao_dev);
sample_audio_set_ai_vqe_param(&ai_vqe_param, g_out_sample_rate, g_aio_resample, TD_NULL, 0);
sample_comm_audio_start_ai
sample_comm_audio_cfg_acodec
sample_comm_audio_start_aenc
sample_audio_aenc_bind_ai
sample_audio_ai_aenc_inner
sample_comm_audio_start_adec
sample_comm_audio_start_ao
sample_audio_adec_bind_aenc
sample_audio_open_aenc_file
sample_comm_audio_create_thread_aenc_adec
pthread_create(&aenc->aenc_pid, 0, sample_comm_audio_aenc_proc, aenc);
ret = audio_aenc_get_stream_and_send(aenc_ctl);
ss_mpi_aenc_get_stream(aenc_ctl->ae_chn, &stream, TD_FALSE);
ret = ss_mpi_adec_send_stream(aenc_ctl->ad_chn, &stream, TD_TRUE);
(td_void)fwrite(stream.stream, 1, stream.len, aenc_ctl->fd);
(td_void)fflush(aenc_ctl->fd);
ss_mpi_aenc_release_stream
sample_audio_ao_bind_adec
五、移动侦测
完整的移动侦测示例程序,位于:
AISampleSrc\smp\a7_linux\source\mpp\sample\svp\ive\sample\sample_ive_md.c
int main(int argc, char *argv[])
sample_ive_case_with_one_arg
sample_ive_md
sample_common_svp_start_vi_vpss_venc
sample_comm_sys_get_pic_size
sample_ivs_md_init
pthread_create(&g_md_thread, 0, sample_ivs_md_proc, (td_void *)&g_md_info);
ot_ivs_md_create_chn
ss_mpi_vpss_get_chn_frame
ss_mpi_vpss_get_chn_frame
sample_ivs_md_dma_data
sample_common_ive_dma_image
sample_common_ive_dma_image
ot_ivs_md_proc
sample_ivs_set_src_dst_size
sample_common_ive_blob_to_rect
sample_common_svp_vgs_fill_rect
ss_mpi_venc_send_frame
六、YOLOV8
# yolov8.(VI->VPSS->SVP_NPU->VGS->VENC).
int main(int argc, char *argv[])
td_void sample_svp_npu_acl_e2e_yolo(td_u32 index)
# 初始化ACL
sample_svp_npu_acl_init
# 加载模型
sample_common_svp_npu_load_model
# 获取输入分辨率
sample_common_svp_npu_get_input_resolution
# 启动视频输入、处理和编码
sample_common_svp_npu_start_vi_vpss_venc
# 设置任务配置
sample_svp_npu_acl_set_task_info
# 初始化任务
sample_svp_npu_acl_init_task
# 模型推理
# 模型推理
sample_common_svp_npu_set_threshold
svp_acl_mdl_get_input_index_by_name
svp_acl_mdl_get_dataset_buffer
svp_acl_get_data_buffer_size
svp_acl_get_data_buffer_addr
ret = pthread_create(&g_svp_npu_thread, 0, sample_svp_npu_acl_to_venc, (td_void*)&args);
# 打开指定设备
svp_acl_rt_set_device
#
sample_svp_npu_acl_vb_map
# 获取输入数据缓冲区信息
sample_common_svp_npu_get_input_data_buffer_info
# 处理每一帧并执行推理
sample_svp_npu_acl_frame_proc
# 发送结果到视频编码器
sample_common_svp_venc_send_stream
# 更新输入数据缓冲区
sample_common_svp_npu_update_input_data_buffer_info
记录下hi3516cv610大概流程,不习惯整个SDK下编译例程,后面会独立出来
如有侵权,或需要完整代码,请及时联系博主。
昇腾计算产业是基于昇腾系列(HUAWEI Ascend)处理器和基础软件构建的全栈 AI计算基础设施、行业应用及服务,https://devpress.csdn.net/organization/setting/general/146749包括昇腾系列处理器、系列硬件、CANN、AI计算框架、应用使能、开发工具链、管理运维工具、行业应用及服务等全产业链
更多推荐

所有评论(0)