若该文为原创文章,转载请注明原文出处。

最近有在了解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下编译例程,后面会独立出来

如有侵权,或需要完整代码,请及时联系博主。

Logo

昇腾计算产业是基于昇腾系列(HUAWEI Ascend)处理器和基础软件构建的全栈 AI计算基础设施、行业应用及服务,https://devpress.csdn.net/organization/setting/general/146749包括昇腾系列处理器、系列硬件、CANN、AI计算框架、应用使能、开发工具链、管理运维工具、行业应用及服务等全产业链

更多推荐