extern "C" { #include <libavformat/avformat.h> #include <libavdevice/avdevice.h> #include <libavutil/opt.h> #include <libavcodec/avcodec.h> #include <libswscale/swscale.h> #include "libavutil/imgutils.h" #include "unistd.h" #include <cstdlib> #include <assert.h> #include <errno.h> #include <fcntl.h> #include <getopt.h> #include <pthread.h> #include <signal.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/poll.h> #include <time.h> #include <unistd.h> #include <sys/poll.h> #include <time.h> #include <unistd.h> } #include "sample_comm.h" #include "rtsp_demo.h" #include <vector> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> using namespace std; using namespace cv; #define DISP_WIDTH 1920 #define DISP_HEIGHT 1080 void Init_ISP(void) { RK_BOOL multi_sensor = RK_FALSE; const char *iq_dir = "/etc/iqfiles"; rk_aiq_working_mode_t hdr_mode = RK_AIQ_WORKING_MODE_NORMAL; //hdr_mode = RK_AIQ_WORKING_MODE_ISP_HDR2; SAMPLE_COMM_ISP_Init(0, hdr_mode, multi_sensor, iq_dir); SAMPLE_COMM_ISP_Run(0); } int main(int argc,char * argv[]) { system("RkLunch-stop.sh"); //1:初始化 ISP RK_BOOL multi_sensor = RK_FALSE; const char *iq_dir = "/etc/iqfiles"; rk_aiq_working_mode_t hdr_mode = RK_AIQ_WORKING_MODE_NORMAL; //hdr_mode = RK_AIQ_WORKING_MODE_ISP_HDR2; SAMPLE_COMM_ISP_Init(0, hdr_mode, multi_sensor, iq_dir); SAMPLE_COMM_ISP_Run(0); printf("初始化 ISP 成功!\r\n"); //2:初始化 RKMPI if (RK_MPI_SYS_Init() != RK_SUCCESS) { RK_LOGE("rk mpi sys init fail!"); return -1; } printf("初始化 MPI 系统成功!\r\n"); /////////////////////////// //初始化ai音频 AIO_ATTR_S aiattr = {0}; aiattr.enBitwidth = AUDIO_BIT_WIDTH_16; aiattr.enSamplerate = AUDIO_SAMPLE_RATE_8000; aiattr.enSoundmode = AUDIO_SOUND_MODE_STEREO; aiattr.soundCard.bitWidth = AUDIO_BIT_WIDTH_16; aiattr.soundCard.channels = 2; aiattr.soundCard.sampleRate = 8000; aiattr.u32ChnCnt = 1; aiattr.u32EXFlag = 0; aiattr.u32FrmNum = 8; aiattr.u32PtNumPerFrm = 1024; RK_U8 nam[64] = "hw:0,0"; strcpy((char *)aiattr.u8CardName,(const char *)nam); int ret = RK_MPI_AI_SetPubAttr(0,&aiattr); if (ret) { printf("ERROR: create AI error! ret=%d\n", ret); return ret; } ret = RK_MPI_AI_Enable(0); if (ret) { printf("ERROR: RK_MPI_AI_Enable error! ret=%d\n", ret); return ret; } ret = RK_MPI_AI_EnableChn(0,0); if (ret) { printf("ERROR: RK_MPI_AI_EnableChn error! ret=%d\n", ret); return ret; } AENC_CHN_ATTR_S aencattr; //memset(&aencattr, 0, sizeof(AENC_CHN_ATTR_S)); aencattr.enType = RK_AUDIO_ID_PCM_ALAW; aencattr.stCodecAttr.enBitwidth = AUDIO_BIT_WIDTH_16; aencattr.stCodecAttr.enType = RK_AUDIO_ID_PCM_ALAW;// aencattr.stCodecAttr.u32Bitrate = 64000;// aencattr.stCodecAttr.u32Channels = 2; aencattr.stCodecAttr.u32SampleRate = 8000; aencattr.u32BufCount = 10; //aencattr.stCodecAttr.u32Bitrate = 64000; ret = RK_MPI_AENC_CreateChn(0,&aencattr); if (ret) { printf("ERROR: create AENC error! ret=%d\n", ret); return ret; } // 定义源(VI)和目标(VENC)通道信息 MPP_CHN_S asrc; // 源:AI设备 MPP_CHN_S adst; // 目标:AENC编码器 // 配置源通道(VI设备0的通道0) asrc.enModId = RK_ID_AI; // 模块ID:AI asrc.s32ChnId = 0; // 通道ID asrc.s32DevId = 0; // 设备ID // 配置目标通道(VENC通道0) adst.enModId = RK_ID_AENC; // 模块ID:AENC adst.s32ChnId = 0; // 通道ID adst.s32DevId = 0; // 设备ID // 绑定AI和AENC //RK_MPI_SYS_Bind(&asrc,&adst); // 修复:添加返回值判断 ret = RK_MPI_SYS_Bind(&asrc, &adst); if (ret != RK_SUCCESS) { printf("ERROR: AI与AENC绑定失败!ret=%d\n", ret); return ret; } // rtsp init rtsp_demo_handle g_rtsplive = NULL; rtsp_session_handle g_rtsp_session; g_rtsplive = create_rtsp_demo(554); g_rtsp_session = rtsp_new_session(g_rtsplive, "/live/test"); rtsp_set_audio(g_rtsp_session,RTSP_CODEC_ID_AUDIO_G711A,NULL,0);///加上音频推流初始化 rtsp_sync_audio_ts(g_rtsp_session, rtsp_get_reltime(), rtsp_get_ntptime());///加上音频推流初始化 AUDIO_STREAM_S aencFrame;//音频流 ///////////////////////////////// while(1) { //音频rtsp int s32Ret = RK_MPI_AENC_GetStream(0,&aencFrame,-1); printf("运行到GetStream后这里\n"); if(s32Ret == RK_SUCCESS) { printf("获取音频数据且编码成功 当前帧数据长度==%d 当前帧时间戳==%lld\r\n",aencFrame.u32Len,aencFrame.u64TimeStamp); if(g_rtsplive && g_rtsp_session) { //printf("len = %d PTS = %d \n",stFrame.pstPack->u32Len, stFrame.pstPack->u64PTS); void *paData = RK_MPI_MB_Handle2VirAddr(aencFrame.pMbBlk); rtsp_tx_audio(g_rtsp_session, (uint8_t *)paData, aencFrame.u32Len, aencFrame.u64TimeStamp); rtsp_do_event(g_rtsplive); } } s32Ret = RK_MPI_AENC_ReleaseStream(0, &aencFrame); if (s32Ret != RK_SUCCESS) { RK_LOGE("RK_MPI_AENC_ReleaseStream fail %x", s32Ret); } } return 0; } 这个RV1106G3音频推流问题出在哪,为啥拉流没有声音,杀死进程的一瞬间有一点杂声,用的贴片麦克风
时间: 2025-08-14 12:04:55 AIGC 浏览: 25
<think>我们面对的是一个RV1106G3平台上的音频问题,具体表现为:
1. 使用贴片麦克风进行音频推流时没有声音(推流无声音)
2. 拉流无音频输出
3. 进程终止时有短暂杂音
我们需要逐步排查问题。首先,我们要考虑整个音频通路的各个环节:
### 1. 硬件连接与麦克风
- 确认麦克风硬件连接正确,麦克风本身无故障。
- 确认麦克风的供电(如需要)正常。
- 确认麦克风的极性连接正确(差分麦克风需注意正负极)。
### 2. 音频驱动
- 确认音频驱动已正确加载。
- 使用命令`lsmod`查看已加载的模块,检查音频相关驱动(如`snd_soc_rv1106`,`snd_soc_da7219`等,具体取决于硬件设计)是否加载。
- 检查dmesg日志,查看音频驱动初始化过程中是否有错误:`dmesg | grep -i audio` 或 `dmesg | grep -i snd`。
### 3. 设备节点
- 确认声卡设备节点创建成功。
- 通过`ls /dev/snd`查看设备节点,通常包括`controlC0`, `pcmC0D0c`(录音设备), `pcmC0D0p`(播放设备)等。
- 如果没有,可能是驱动加载失败或设备树配置问题。
### 4. 音频输入配置(ALSA)
- 使用ALSA工具(`arecord`)测试麦克风录音:
```bash
arecord -D hw:0,0 -d 5 -f cd test.wav
```
如果录音没有声音,则问题可能出现在硬件或驱动层。如果录音有声音,则问题可能出现在推流应用层。
### 5. 音频编解码
- 推流应用通常会对音频进行编码(如AAC)。需要确认编码器是否正常工作。
- 检查编码器的参数设置(采样率、声道数、位深)是否与音频采集一致。
- 检查编码器初始化是否成功。
### 6. 推流应用
- 检查推流应用的音频采集配置是否正确(如ALSA设备名、采样率、声道数)。
- 检查推流应用是否成功打开音频设备并读取到数据。
- 使用调试工具(如gdb)或增加日志,查看推流应用读取音频数据是否正常。
### 7. 拉流无音频输出
- 如果推流端没有音频数据,拉流端自然没有声音。
- 如果推流端有音频数据,则检查拉流端:
- 拉流端是否支持该音频编码格式?
- 拉流端是否成功解码音频?
- 拉流端播放设备是否正常?
### 8. 进程终止时的短暂杂音
- 这种现象通常是由于音频设备在关闭时,硬件或驱动没有正确处理导致的。可能的原因包括:
- 音频驱动在关闭时没有平滑地停止DMA传输,导致最后一段数据不完整。
- 硬件断电顺序问题,导致最后几个采样被截断或产生噪声。
- 解决方法:
- 在应用程序中,尝试在关闭音频设备前先静音,或者增加一段延迟。
- 检查驱动中关闭音频设备的代码,确保按照正确的顺序停止各个模块(如先停止DMA,再关闭时钟等)。
### 具体排查步骤
#### 步骤1:检查驱动和硬件
1. 使用`dmesg`检查启动日志,确认音频驱动加载正常,没有错误信息。
2. 使用`cat /proc/asound/cards`查看系统识别的声卡。
#### 步骤2:使用ALSA工具测试录音
```bash
arecord -D hw:0,0 -r 48000 -c 2 -f S16_LE -d 10 test.wav
```
然后使用aplay播放(如果本地有扬声器):
```bash
aplay test.wav
```
或者将文件拷贝到PC上播放。
#### 步骤3:检查应用层
如果ALSA录音正常,则问题在推流应用。需要检查:
- 推流应用是否配置了正确的ALSA设备。
- 推流应用是否以正确的参数(采样率、声道数、格式)打开设备。
- 推流应用是否成功读取到音频数据(可以通过写文件的方式将读取的PCM数据保存下来,然后播放验证)。
#### 步骤4:检查编码和推流
- 检查编码器初始化是否成功。
- 检查编码后的数据是否被正确封装进流媒体协议(如RTMP)。
- 可以在推流端将编码后的音频数据保存为文件(如AAC文件),然后使用PC上的播放器检查是否正常。
#### 步骤5:解决终止杂音
- 在应用程序中,捕获SIGINT(或其它终止信号),在退出前先停止音频采集,然后等待一段时间(例如100ms)再退出。
- 检查驱动中关闭音频设备的代码,确保按照正确的顺序关闭(如先停止ADC,再关闭时钟,最后断电)。
### 其他可能原因
- **设备树配置**:检查设备树中音频相关配置(如麦克风的引脚配置、I2S配置等)是否正确。
- **电源管理**:检查是否有电源管理导致麦克风或音频编解码器提前断电。
### 参考
[^1]: RV1106芯片介绍中提到支持多种图像处理算法,但未提及音频,因此音频问题需从音频驱动和应用入手。
[^2]: 关于RV1106的设置方法,虽然引用的是网络设置,但提醒我们需要检查系统配置,包括内核配置和驱动模块参数。
§§相关问题§§
1. 如何检查RV1106G3的音频设备树配置是否正确?
2. 在RV1106G3平台上,如何调试ALSA驱动?
3. 如何编写一个捕获SIGINT信号并优雅关闭音频的程序?</think>### RV1106G3音频推流问题排查与解决
针对RV1106G3平台音频推流无声音、拉流无输出且进程结束有杂音的问题,请按以下步骤排查:
---
### **1. 基础硬件与驱动检查**
- **麦克风硬件检测**
使用万用表测量麦克风供电电压(通常1.8V-3.3V),确认贴片麦克风焊接无虚焊,差分麦克风需检查正负极连接。
- **驱动加载验证**
```bash
dmesg | grep -i "audio" # 检查音频驱动加载日志
ls /dev/snd # 确认声卡设备节点存在(如pcmC0D0c)
```
若驱动未加载,检查内核配置:`CONFIG_SND_SOC_RV1106=y` 和麦克风编解码器驱动(如`CONFIG_SND_SOC_DA7219`)[^1]。
---
### **2. ALSA层音频通路验证**
- **原始录音测试**
执行ALSA录音命令,验证硬件到内核的通路:
```bash
arecord -D hw:0,0 -f S16_LE -r 16000 -c 2 -d 5 test.wav
aplay test.wav # 播放验证
```
- 若无声音:检查设备树配置(麦克风Pinctrl、I2S时钟配置)
- 若有杂音:检查硬件接地或时钟干扰
---
### **3. 推流应用层排查**
- **GStreamer推流测试(示例)**
```bash
gst-launch-1.0 alsasrc device=hw:0,0 ! audioconvert ! audioresample ! avenc_aac ! rtspclientsink location=rtsp://server/stream
```
- 关键检查点:
- `alsasrc`是否返回错误(`GST_DEBUG=3`查看日志)
- 音频格式匹配:采样率、声道数需与驱动一致
- 使用`! filesink location=test.aac`保存原始AAC文件验证编码
- **进程结束杂音分析**
杂音通常由突然断电导致,解决方案:
```c
// 在应用退出前添加音频淡出
void audio_soft_exit() {
set_volume(100); // 初始音量
for(int vol=100; vol>=0; vol-=10) {
set_volume(vol);
usleep(10000); // 10ms间隔
}
close_audio_device();
}
```
---
### **4. 拉流端问题定位**
- **媒体流分析工具**
```bash
ffprobe rtsp://server/stream # 检查流是否包含音频轨道
ffplay -vn rtsp://server/stream # 强制禁用视频仅播放音频
```
- 若拉流无音频:检查推流端编码器是否成功输出数据包
- 若拉流有杂音:验证音频编码参数(比特率、采样率)是否匹配
---
### **5. 时钟与电源管理**
- **I2S时钟配置**
检查设备树I2S节点:
```dts
i2s0: i2s@ff000000 {
compatible = "rockchip,rv1106-i2s";
clocks = <&cru I2S0_MCLK>, <&cru I2S0_HCLK>;
clock-names = "i2s_clk", "i2s_hclk";
// 确保MCLK频率符合麦克风规格(通常2.4-4.8MHz)
};
```
- **电源域配置**
确认音频相关电源域无提前关闭:
```dts
&power_domains {
pd_audio: PD_AUDIO {
regulator-name = "vcc_1v8_audio";
// 保持供电直至系统休眠
};
};
```
---
### **典型解决方案总结**
| 问题现象 | 可能原因 | 解决措施 |
|------------------------|---------------------------|-----------------------------------|
| 推流无声音 | 麦克风偏置电压异常 | 检查设备树`micbias-voltage`配置 |
| 拉流无音频 | AAC编码器未初始化 | 验证`media-ctl`链路(`media-ctl -p`) |
| 结束杂音 | 电源瞬间跌落 | 添加退出的音频淡出算法 |
| 持续低频噪声 | I2S时钟抖动 | 降低MCLK频率或启用PLL增强模式 |
阅读全文