• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > 记一次Android系统下解决音频UnderRun问题的过程

记一次Android系统下解决音频UnderRun问题的过程

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了android underrun,underrun,underrun occurred,android 播放音频,android 音频开发等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

记一次Android系统下解决音频UnderRun问题的过程


【前言】

因为这几天在为设备从Android M升级到Android N的bringup做准备,所以一直没写博客。趁现在刚刚把Kernel部分的移植做完,忙里偷闲把2周前解决的一个音频UnderRun问题记录一下,留作以后参考。

问题现象是:使用腾讯视频APP播放视频,一段时间后会出现pop-click噪音,听起来类似“哒哒”一样的声音。


【排查问题】

看到这个问题的现象后,我的第一猜测就是设备出现了UnderRun。

大胆假设后还需小心求证。于是我在代码中开启Verbose Log打印并重新编译系统镜像烧写到设备上。然后复现问题,并查看出现问题的时间点附近的Log消息。日志文件中出现了大量如下记录:

12-08 10:09:15.565  2825  3426 V AudioFlinger: track(0xea5dda80) underrun,  framesReady(1024) < framesDesired(1026)12-08 10:09:15.599  2825  3426 V AudioFlinger: mixer(0xeb440000) throttle begin: ret(4096) deltaMs(0) requires sleep 10 ms12-08 10:09:15.625  2825  3426 D AudioFlinger: mixer(0xeb440000) throttle end: throttle time(20)

果然这是个UnderRun问题,Log中的信息证实了猜想:音频播放需要1026帧数据,但APP只准备好了1024帧。但我们也知道,Android系统对于underrun出现后是有一套默认的处理流程来消除问题的,也就是紧接着的2条和throttle相关的Log所对应的操作。

简单介绍一下Android系统默认处理underrun问题的流程:当检测到当前写入音频数据的时间与上次出现警告的时间间隔大于预定的最大时间间隔(5纳秒)后,系统将判定音频播放过程出现了underrun。然后系统会调用usleep()函数对当前PlaybackThread进行短时间阻塞,这样上层APP就能为PlaybackThread准备好更多音频数据。这个usleep()的时长是根据相邻2次写入音频数据的时间间隔实时计算出的。

相应的代码可以在 frameworks/av/sevices/audioflinger/Threads.cpp 中的AudioFlinger::PlaybackThread::threadLoop()函数中找到:

  1. bool AudioFlinger::PlaybackThread::threadLoop()
  2. {
  3. ......
  4. if (mType == MIXER && !mStandby) {
  5. // write blocked detection
  6. nsecs_t now = systemTime();
  7. nsecs_t delta = now - mLastWriteTime; // 相邻 2 次写入音频数据操作的时间间隔
  8. if (delta > maxPeriod) {
  9. mNumDelayedWrites++;
  10. if ((now - lastWarning) > kWarningThrottleNs) { // 如果本次写入数据时间与上次警告出现时间间隔大于kWarningThrottleNs(5纳秒)则判断出现underrun
  11. ATRACE_NAME("underrun");
  12. ALOGW("write blocked for %llu msecs, %d delayed writes, thread %p",
  13. ns2ms(delta), mNumDelayedWrites, this);
  14. lastWarning = now;
  15. }
  16. }

  17. if (mThreadThrottle
  18. && mMixerStatus == MIXER_TRACKS_READY // we are mixing (active tracks)
  19. && ret > 0) { // we wrote something

  20. // The throttle smooths out sudden large data drains from the device,
  21. // e.g. when it comes out of standby, which often causes problems with
  22. // (1) mixer threads without a fast mixer (which has its own warm-up)
  23. // (2) minimum buffer sized tracks (even if the track is full,
  24. // the app won't fill fast enough to handle the sudden draw).

  25. const int32_t deltaMs = delta / 1000000;
  26. const int32_t throttleMs = mHalfBufferMs - deltaMs;
  27. if ((signed)mHalfBufferMs >= throttleMs && throttleMs > 0) {
  28. //usleep(throttleMs * 1000); // 通过usleep()短时间阻塞当前PlaybackThread,让app可以准备更多的数据
  29. usleep((throttleMs + 3) * 1000); /* 增加 3ms 的延时时间
  30. * 修复腾讯视频APP播放视频有噪声的问题 20161216
  31. */
  32. // notify of throttle start on verbose log
  33. ALOGV_IF(mThreadThrottleEndMs == mThreadThrottleTimeMs,
  34. "mixer(%p) throttle begin:"
  35. " ret(%zd) deltaMs(%d) requires sleep %d ms",
  36. this, ret, deltaMs, throttleMs);
  37. mThreadThrottleTimeMs += throttleMs;
  38. } else {
  39. uint32_t diff = mThreadThrottleTimeMs - mThreadThrottleEndMs;
  40. if (diff > 0) {
  41. // notify of throttle end on debug log
  42. ALOGD("mixer(%p) throttle end: throttle time(%u)", this, diff);
  43. mThreadThrottleEndMs = mThreadThrottleTimeMs;
  44. }
  45. }
  46. }
  47. }
  48. ......
  49. }


【解决问题】

前文贴出的Log表明,Android系统已经检测到了UnderRun问题并进行了延时处理来让APP准备更多的音频数据。可是我们在使用腾讯视频APP时依然会继续发生UnderRun的问题,原因在于代码中计算出的延时时间对腾讯视频APP来说还是太短。在Log中我们可以看到需要的数据量为1026帧但实际准备好的数据为1024帧,所以我们可以稍微增加usleep()的延时时间来为PlaybackThread准备足够的数据。经过试验,我决定在原有延时时间上增加3毫秒。

重编系统镜像后烧入设备进行验证,问题得到解决。


【扩展阅读】

[1]《音频出现Xrun(underrun或overrun)的原因与解决办法》


分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 记一次Android系统下解决音频UnderRun问题的过程

相关文章

  • 2017-05-26android开发之——获取相册图片和路径,
  • 2017-05-26android开发之路03,android之路03
  • 2017-05-223.4 TouchListener PK OnTouchEvent + 多点触碰
  • 2017-05-26如何写一个简易的文件系统(4):umount
  • 2017-05-26Android的消息机制,Android消息机制
  • 2017-05-26Android中View的滑动冲突——Android开发艺术探索笔记
  • 2017-05-26Android API Guides---App Widget Host
  • 2017-05-26Android 手机卫士--导航界面3、4和功能列表界面跳转逻辑处理,android4和
  • 2017-05-26Android开发2:事件处理及实现简单的对话框,android开发
  • 2017-05-26Android安全攻防战,反编译与混淆技术完全解析(下)

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 大神都是有个起点的,大神都是起点
    • Android--根据子控件的大小自动换行的ViewGroup,android--viewgroup
    • Android--split()分割字符串特殊用法,csplit字符串分割
    • Android 如何本地加载pdf文件,android加载pdf
    • 谷歌IAP:skusBundle array associated with key ITEM_ID_LIST cannot contain more than 20 items.,jsarraycontain
    • ViewPager实现滑动翻页效果,viewpager滑动翻页
    • 添加页面切换动画, 避免冷启动
    • Weex 环境搭建(win7),weex环境搭建win7
    • Android框架设计模式(五)——Singleton Method
    • andriod 读取网络图片,

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有