Android音频子系统(六)------拍照音卡顿问题解析

你好!这里是风筝的博客,

欢迎和我一起交流。


自从去年来了手机厂搬砖,就好久没有更新了,实在是太忙了。。。。。。

现在疫情原因,就居家办公了,抽空整理下最近遇到的一些音频问题,供大家学习参考。

测试报了一个拍照音卡顿的问题:
【前提条件】【Prerequistes】暗环境
【操作步骤】【Operation steps】夜景模式点击拍照
【实际结果】【Actual results】拍照声音卡顿

emmm,卡顿问题在音频里面老生常谈了,拿到log之后,打开音频dump文件看了下,主要查看ivdump信号。
ivdump是功放的反馈信号,反馈了功放这边输出的的信号。

打开正常拍照音的ivdump:
normal

可以看出,频谱信号还是比较连贯的,没有卡顿的现象。

打开异常的拍照音ivdump:
在这里插入图片描述

可以看出频谱那里出现了异常,数据断开了,有个26ms左右的空缺,也就是出现了卡顿。
说明PA播放确实出现了卡顿。

但是进一步查看framework里服务层要往HAL写的数据的dump,也就是StreamOut.wav,未发现异常,说明上层服务传下来的音源数据是正常的。
再次查看HAL往kernel写的数据的dump,也就是TaskPlayback_dataout.pcm,居然也是正常的,这就比较奇怪了。

之前文章就说过,如果音源没问题的话,卡顿问题总归就两种情况:
1.overrun:写数据快,播数据慢,导致buffer满了,导致卡顿。
2.underrun:写数据慢,播数据快,导致buffer空了,无数据可播,出现卡顿。

打开kernel log看了下:

  • -(0)[13588:writer]snd_audio_dsp snd_audio_dsp: mtk_dsp_start() task id:10 adsp xrun

简单log里搜了下,确实出现了xrun,不过没标明是overrun还是underrun,而且不像以前接触的芯片通路比较简单,现在高端点的芯片都是带ADSP的,涉及DSP确实不太好搞。
而且手机场景比较多且繁杂,我也不好随意更改buffer size,因为会增大播放时延。

现在一般Kernel和ADSP代码都是由芯片原厂维护,我们厂商音频一般不太好看,所以一般我都是从上层入手分析。

卡顿问题一般都是由性能原因引起的,重新抓了systrace分析。
查看log:

06:07:21.408285 19316 10173 D AudioTrack: start(45): prior state:STATE_STOPPED output 29 stream 1 session 225
06:07:21.408662   935  1227 D APM_AudioPolicyManager: startOutput() output +++ 29, stream 1, session 225

06:07:21 时间Track开始起播,记住这个时间点。

打开perfetto工具网站:https://ui.perfetto.dev/#!/viewer

导入抓到的trace文件,网上有很多教怎么抓trace的文章,我就不累述了。
搜索surfaceflinger ,查看时间点,看到包含06:07:21这个时间点:
time

就说明本次trace有正常抓到出异常那个时间点,上面的nRdy是播放的数据,说明这个点在播放拍照音,OK,log对得上。

之后分别星标nRdy、AudioOut、write这几个线程:
标记
nRdy是服务层传下的要播放的数据,可以看到,再HAL层的write线程,出现了一个橙色的表示,长达27ms,和文章开头的拍照音卡顿的间隔时间差不多一样,就是这里出了问题。
27ms

systrace里一般有四种状态:

  • running(running过长考虑是否线程做事太多
  • runnable(runnable过多考虑是否cpu过忙,无法及时完成调度
  • sleeping(sleeping过多考虑是否被其他线程blocking住
  • uninterruptible sleep(uninterruptible sleep过多可能IO过重

这个橙色是Uninterruptible Sleep状态,看起来是卡IO了,从perfetto看,没有写non-IO或者IO,也不太确定是什么引起的,看唤醒关系的话,往后找running状态,找它是被谁唤醒的:
wake

发现是com.oplus.camera唤醒了HAL里面write线程,所以可能和camera有比较大的关系。

继续看其他几个Uninterruptible Sleep状态,查看他的running,是kworker24035唤醒:
24035

查看kworker24035,前面确实出现一大段时间的Uninterruptible Sleep:
io

看来确实由24035这个线程号引起的!

查看ps文件,查找24035是哪个线程:

root         24035 24035     2       0      0 cmdq_pkt_wait_complete 0 D kworker/u16:3

看起来是cmdq_pkt_wait_complete这个函数,但是看了下也不知道是谁在调用这个API,看起来是公用的,囧。。。

不过按前面分析,camera嫌疑比较大,和camera的同事沟通了下,他们果然给出了方案:
1.音乐播放场景,取消camera调度补偿,播放停止恢复camera调度补偿。
2.提升前台播放app的小线程调度优先级
3.camera 对负载开销优化

camera同事这三把斧下来,问题果然不复现了。

总结下来,虽然问题不是音频这边导致的,但是还要分析是谁导致的问题,真累啊
dog


后记:
用Android自带的perfetto工具也可以抓取trace:
perfetto -o /data/misc/perfetto-traces/trace_file.perfetto-trace -t 30s --buffer 2000mb gfx input view webview wm am sm audio video camera hal res dalvik rs power pm ss database network adb vibrator aidl nnapi rro sched irq i2c freq idle disk mmc sync workq memreclaim regulators binder_driver binder_lock pagecache memory thermal ion bionic perf pdx
这个可以抓取30s的trace

猜你喜欢

转载自blog.csdn.net/Guet_Kite/article/details/123478575
今日推荐