platform:px30(rk平台)

OS:Android8.1

问题描述:在使用系统录音机以及其他录音软件录音时,会出现apk 录制回来的音频会出现部分数据丢失的情况,导致录制的音频会出现节奏跳动等异常现象!

后经过排查,发现是因为audioflinger 获取音频数据时出现了overrun 的情况导致数据丢失!

贴上overrun 报错部分代码(frameworks/av/services/audioflinger/Threads.cpp):

        // Read from HAL to keep up with fastest client if multiple active tracks, not slowest one.// Only the client(s) that are too slow will overrun. But if even the fastest client is too// slow, then this RecordThread will overrun by not calling HAL read often enough.// If destination is non-contiguous, first read past the nominal end of buffer, then// copy to the right place.  Permitted because mRsmpInBuffer was over-allocated.int32_t rear = mRsmpInRear & (mRsmpInFramesP2 - 1);ssize_t framesRead;// If an NBAIO source is present, use it to read the normal capture's dataif (mPipeSource != 0) {size_t framesToRead = mBufferSize / mFrameSize;framesToRead = min(mRsmpInFramesOA - rear, mRsmpInFramesP2 / 2);framesRead = mPipeSource->read((uint8_t*)mRsmpInBuffer + rear * mFrameSize,framesToRead);ALOGW("framesRead :%zd framesToRead :%zd \n",framesRead,framesToRead);// since pipe is non-blocking, simulate blocking input by waiting for 1/2 of// buffer size or at least for 20ms.size_t sleepFrames = max(min(mPipeFramesP2, mRsmpInFramesP2) / 2, FMS_20 * mSampleRate / 1000);if (framesRead <= (ssize_t) sleepFrames) {sleepUs = (sleepFrames * 1000000LL) / mSampleRate;}if (framesRead < 0) {status_t status = (status_t) framesRead;switch (status) {case OVERRUN:ALOGW("overrun on read from pipe");framesRead = 0;break;case NEGOTIATE:ALOGE("re-negotiation is needed");framesRead = -1;  // Will cause an attempt to recover.break;default:ALOGE("unknown error %d on read from pipe", status);break;}}// otherwise use the HAL / AudioStreamIn directly}

通过代码可以看见当framesToRead参数,也就是获取一帧数据的缓冲区大小不够接收由底层获取到的数据时,read 函数就会返回OVERRUN,出现overrun 时,缓冲区就被置0,这一帧的数据也就相对的丢失了。

分析了原因后,现提出解决办法,首先需要确认audio hal 设置的帧数据缓冲区,代码位置hardware/rockchip/audio/tinyalsa_hal/audio_hw.h

struct pcm_config pcm_config_in = {.channels = 4,.rate = 48000,//44100,
#ifdef SPEEX_DENOISE_ENABLE.period_size = 1024,
#else.period_size = 480,//256,
#endif.period_count = 8,.format = PCM_FORMAT_S16_LE,.flag = HW_PARAMS_FLAG_LPCM,
};

period_size 和period_count 这两个参数就是缓冲区大小,这儿我设置的480 和8.

确定了这儿设置的参数,改起来就很简单了,在上面的Threads.cpp中修改:

framesRead = mPipeSource->read((uint8_t*)mRsmpInBuffer + rear * mFrameSize,3840);//framesToRead);

3840是period_size * period_count的大小,在读取音频数据时,hal 传输的数据大小,与audioflinger 获取到的数据大小一致,则能保证缓冲区不会因为数据读取过短,或者hal 层数据传输过快,导致缓冲区溢出。

这顺便分享遇见音频问题的一般调试办法:

录音问题:一般先确定驱动录制的音频没有问题,可以使用Androidsdk 里提供的tinycap 工具录制从硬件mic 直接传输回的数据,tinycap 源码位于/external/tinyalsa/ 下,可以设置多种采样率,采样位数,通道数,录制wav 文件,使用audacity软件分析音频,如音频异常,需要检查音频驱动,平台端和codec 端,问题大多出在clk 不同步。

底层获取到的音频数据没问题时,就往上排查,到audio hal ,hal 是调用/external/tinyalsa/pcm.c 里面的接口获取数据,在hal 层可抓取debug 音频,在audio_hw.c 中添加

#define ALSA_IN_DEBUG
#ifdef ALSA_IN_DEBUG
FILE *in_debug;
#endif#ifdef ALSA_IN_DEBUGin_debug = fopen("/data/debug.pcm","wb");//please touch /data/debug.pcm first
#endif#ifdef ALSA_IN_DEBUGfwrite(buffer,frames_wr * frame_size,1,in_debug);
#endif

这儿给的示例,具体fwrite参数需要根据你自定义的参数写入,不然写入的数据会是一堆乱码,这儿不知道怎么给参数的,欢迎私信!

我这儿排查到audioflinger 的overrun 问题,也是在驱动层和hal层抓取的debug音频文件没问题,才查到audioflinger ,

最后就是排查audioflinger ,这一层涉及到的代码量较大,建议说根据具体的log 报错位置去排查!

Android8.1 audioflinger overrun问题解决相关推荐

  1. Deepin15.7 Android8.1 编译 以及问题解决

    前几天装了deepin15.7美滋滋,然后开始折腾编译.LOS15.1(android8.1),在此记录遇到的问题 1.大天朝下载源码是个问题,换个hosts即可,这里我用的是 https://git ...

  2. Audio中underrun与overrun问题解决(十八)

    简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案.音视频.编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列[原创干货持续更新中--]

  3. android8.1系统连接不上BLE蓝牙设备问题解决

    OS:Android8.1 platform:px30 问题:在更换完wifi-bt模组进行工厂测试时,发现蓝牙可正常扫描连接经典蓝牙(手机等设备),但是扫描出来的BLE蓝牙设备却连接不上. 在与模组 ...

  4. Android8.0 Audio系统之AudioFlinger

    继上一篇AudioTrack的分析,本篇我们来看AudioFlinger,AF主要承担音频混合输出,是Audio系统的核心,从AudioTrack来的数据最终都会在这里处理,并被写入到Audio的HA ...

  5. Rockchip PX30 android8.1双屏显示带宽不足闪屏 问题解决

    瑞芯微 Rockchip PX30平台的主板,接mipi和rgb屏做双屏显示:调试过程中,双屏能够同显,但作为副屏的rgb会闪动,且较为厉害:在启动进入系统过程中和进入系统后的操作,都会出现闪动: 系 ...

  6. 【Android8.1】软键盘和实体键盘冲突(无法同时使用)问题解决

    在Android系统上存在一个机制,即当系统外接实体键盘时候,软键盘则会默认被禁用,要想实现软键盘和实体键盘同时使用,则需要进行如下操作: vi frameworks/base/packages/Se ...

  7. UnderRun和OverRun

    UnderRun pcm播放的场景,alsa中snd_pcm_write()返回–EPIPE,表示alsa取不到足够的数据: AudioTrack 写入数据的速度跟不上 AudioFlinger 读取 ...

  8. Android8.0、9.0安装包解析失败

    根据google官网得知,在8.0以上权限控制的更加严格,应用内安装下载更新的apk都需要申请"安装外面应用"权限才能去安装新应用,如果没有申请否则无法安装. 顺便附上6.0.7. ...

  9. undefined reference to 'pthread_create'问题解决(转)

    undefined reference to 'pthread_create' undefined reference to 'pthread_join' 问题原因:     pthread 库不是 ...

最新文章

  1. 详谈如何定制自己的博客园皮肤
  2. CHIL-ORACLE-主外键约束(primary key / foreign key)
  3. 树莓派智能小车python_人工智能-树莓派小车(1)——DuerOS语音唤醒
  4. mysql客户端程序介绍
  5. messagebox的用法_酝酿已久,MessageBox类实例代码讲解
  6. 智慧能源管理系统解决方案
  7. 整蛊别人的vbs代码刷屏
  8. 十折交叉验证python_Python实现K折交叉验证法的方法步骤
  9. Ros系统配置DNS服务器,ros设置dns服务器
  10. Executing an update/delete query
  11. jndi step by step(2)
  12. 2021年江苏省高考成绩排名查询,2021年江苏高考个人成绩排名查询方法及排名查询系统...
  13. 7和7的倍数游戏答案_团建游戏大全-桌游篇
  14. VSCode 配置使用 PyLint 语法检查器
  15. MFC自制小游戏——躲避球(每日进度)
  16. Centos7- wget未找到命令,there are no enabled repos 解决办法
  17. 【技术认证题库】齐治初级运维安全认证——RIS堡垒机习题
  18. 网络基础之基于距离矢量的动态路由(RIP)
  19. 【论文--文献格式】
  20. Android通过GET方式访问网络页面

热门文章

  1. 【Luat-esp32c3】4.2 文件系统——sdmmc挂载tf卡
  2. C#的TimeSpan介绍
  3. 统计3:样本和统计量
  4. 相似矩阵(Similar Matrixces)
  5. 浅谈Scheduled
  6. 在Android手机上编写并运行Lua脚本
  7. Java基础(Java补码)
  8. GDPU C语言 番外篇
  9. 百度语音合成(TTS) 在Android的使用方法
  10. jacoco代码覆盖率