前言
从本章开始我们将要学习嵌入式音视频的学习了 ,使用的瑞芯微的开发板
🎬 个人主页:@ChenPi
🐻推荐专栏1: 《C++_@ChenPi的博客-CSDN博客》✨✨✨
🔥 推荐专栏2: 《Linux C应用编程(概念类)_@ChenPi的博客-CSDN博客》✨✨✨
🛸推荐专栏3:《嵌入式音视频_@ChenPi的博客-CSDN博客》
🌺本篇简介 :本章主要讲解VI VENC模块和AI AENC模块的初始化及具体函数详解
01 main函数
构造一个项目,我们需要先将大概的框架给理解清楚,这样对写代码提供很多帮助
首先,我们看一下主函数
我们的主函数我们就写成这样,把功能和任务都分模块写,这样看代码和移植到方便一些
我们可以看到主函数接收参数的
我们要接收三个参数
- 参数1为可执行文件名
- 参数2为复合流格式
- 参数3为将要推流到的流媒体的地址
第三个红框就是初始化一些参数了
我们重点最后一个红框
这里面的内容是项目跑起来的关键
02 模块参数初始化及模块配置
2.1 VI模块初始化
//1 VI设备参数初始化
int rkmedia_VI_Init()
{RV1126_VI_CONFIG vi_Config; //VI模块配置信息结构体memset(&vi_Config, 0, sizeof(vi_Config)); vi_Config.id = 0; vi_Config.attr.pcVideoNode = VI_4K_NodeName; //设备节点vi_Config.attr.u32Height = 1080; //视频输入的宽度,一般和CMOS摄像头或者外设的宽度一致vi_Config.attr.u32Width = 1920; //视频输入的高度,一般和CMOS摄像头或者外设的高度一致vi_Config.attr.u32BufCnt = 3; //缓冲区计数,一般默认为3vi_Config.attr.enWorkMode = VI_WORK_MODE_NORMAL; //vi工作模式 VI_WORK_MODE_NORMAL正常模式 VI_WORK_MODE_LUMA_ONLY 亮度模式vi_Config.attr.enPixFmt = IMAGE_TYPE_NV12; //图像格式vi_Config.attr.enBufType = VI_CHN_BUF_TYPE_MMAP; //vi关于视频的方式DMA和MMAP两种方式int ret = rkmedia_VI_Module_Init(&vi_Config);if(0 == ret){RV1126_VI_CONTAINTER venc_container; //保存通道号的结构体venc_container.index = 0; //第几组编号venc_container.Vi_Channel_ID = vi_Config.id; //通道号IDset_vi_container(0,&venc_container); //将通道号保存进去puts("container creat succeeded"); }else{puts("container creat failed");}return 0;
}
首先我们来看一下VI模块的初始化
RV1126_VI_CONFIG这个结构体实际上就是对VI_CHN_ATTR_S结构做了一个封装
多了一个变量ID,这个的作用是什么呢?这个是为了后期如果需要多路编码留下拓展空间
再看一下这行代码
int ret = rkmedia_VI_Module_Init(&vi_Config);
这个代码的实际是将VI和VENC模块的绑定操作进行了一个封装
2.2 VENC模块初始化
//初始化VENC模块
int rkmedia_VENC_Init()
{RV1126_VENC_CONFIG vencconfig; //保存VENC模块配置信息结构体memset(&vencconfig, 0, sizeof(vencconfig)); vencconfig.id = 0;//1编码器基础属性结构体vencconfig.attr.stVencAttr.enType = RK_CODEC_TYPE_H264; //编码器协议类型vencconfig.attr.stVencAttr.imageType = IMAGE_TYPE_NV12; //输入图像类型vencconfig.attr.stVencAttr.u32PicWidth = 1920; //编码图像宽度 vencconfig.attr.stVencAttr.u32PicHeight = 1080; //编码图像高度vencconfig.attr.stVencAttr.u32VirWidth = 1920; //编码图像虚宽度,一般来说u32VirWidth和u32PicWidth是一致的vencconfig.attr.stVencAttr.u32VirHeight = 1080; // vencconfig.attr.stVencAttr.u32Profile = 77; //编码等级 有66 77 100 越高画质越好,但网络传输需要的带宽就越大//2编码码率控制属性结构体vencconfig.attr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR; //编码器码率控制模式vencconfig.attr.stRcAttr.stH264Cbr.u32Gop = 30; // h264cbr 关键帧间隔vencconfig.attr.stRcAttr.stH264Cbr.u32BitRate = 1920*1080*3; //编码码率/*原始帧和目标帧的分子分母*/vencconfig.attr.stRcAttr.stH264Cbr.fr32DstFrameRateNum =25; //目标帧vencconfig.attr.stRcAttr.stH264Cbr.fr32DstFrameRateDen = 1;vencconfig.attr.stRcAttr.stH264Cbr.u32SrcFrameRateNum = 25; //原始帧vencconfig.attr.stRcAttr.stH264Cbr.u32SrcFrameRateDen = 1;//3编码器GOP属性结构体int ret = rkmedia_VENC_Module_Init(&vencconfig);if(0 == ret){RV1126_VENC_CONTAINER venc_container;venc_container.index = 0;venc_container.VENC_Channel_ID = vencconfig.id;set_venc_container(0, &venc_container);}else{}return 0;
}
这个的做法和VI模块配置是相似的
需要注意的几个点
- 需要理解VENC_CHN_ATTR_S这个结构体,这个结构体中还包括了三个结构体,每个结构体功能不一样
- 需要按要求选择编码等级,不然选择了最高的编码等级但网络不好容易黑屏
- 编码器的选择需要看仔细
- 目标帧和原始帧最好选择和摄像头硬件匹配的,不然会有音频被加速的感觉。我的硬件25合适
2.3 AI模块初始化
int rkmedia_AI_Init()
{RV1126_AI_CONFIG ai_Config;memset(&ai_Config, 0, sizeof(ai_Config));ai_Config.id = 0;ai_Config.attr.pcAudioNode = "default"; //音频节点路径ai_Config.attr.enSampleFormat = RK_SAMPLE_FMT_S16; //采样格式ai_Config.attr.u32SampleRate = 48000; //采样率ai_Config.attr.u32Channels = 2; //通道数ai_Config.attr.u32NbSamples = 1024; //每帧采样数ai_Config.attr.enAiLayout = AI_LAYOUT_NORMAL; //音频布局 int ret = rkmedia_AI_Module_Init(&ai_Config);if(0 == ret){RV1126_AI_CONTAINTER ai_container;ai_container.index = 0;ai_container.Ai_Channel_ID = ai_Config.id;set_ai_container(0,&ai_container);}else{puts("AI Init Failed");}return 0;
}
这个是音频的AI模块的初始化
注意点:
采样率:96000, 88200, 64000, 48000, 44100, 32000,采样率的选择很多,但一般48000就可以
通道数:单声道,双声道,四声道等等,一般2声道即可
采样个数:1024
2.4 AENC模块初始化
int rkmedia_AENC_Init()
{RV1126_AENC_CONFIG rkmedia_aenc_config; rkmedia_aenc_config.id = 0;rkmedia_aenc_config.attr.enCodecType = RK_CODEC_TYPE_AAC; //AENC的编码类型rkmedia_aenc_config.attr.u32Bitrate = 153600; //AENC的音频码率rkmedia_aenc_config.attr.u32Quality = 1; //AENC编码质量rkmedia_aenc_config.attr.stAencAAC.u32Channels = 2; //AENC编码通道rkmedia_aenc_config.attr.stAencAAC.u32SampleRate = 48000; //AENC编码采样率int ret = rkmedia_AENC_Module_Init(&rkmedia_aenc_config);if(0 == ret){RV1126_AENC_CONTAINER aenc_container;aenc_container.index = 0;aenc_container.AENC_Channel_ID = rkmedia_aenc_config.id;set_aenc_container(0, &aenc_container);puts("AENC Container Success!");}else{}return 0;
}
注意:AENC的配置参数要和AI的参数对应上,声道数,采样率等等