Chinaunix首页 | 论坛 | 博客
  • 博客访问: 342370
  • 博文数量: 41
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 476
  • 用 户 组: 普通用户
  • 注册时间: 2016-09-01 19:08
个人简介

Android/Linux/音频/驱动

文章分类

全部博文(41)

文章存档

2017年(21)

2016年(20)

我的朋友

分类: Android平台

2016-12-07 14:00:31

【背景介绍】 

  前 2 天收到个音频子系统的 bug 反馈,测试组说设备在使用某视频 app 播放视频时不定期会出现“嗒嗒”的噪声。因为检查上层 Log 和底层寄存器配置后发现都正常,所以我怀疑是功放芯片硬件的问题,但硬件开发的同事需要我提供 SoC 送到 Codec 芯片之前的原始 PCM 音频数据帮助分析。以前我也没这么做过,研究了一下午终于把这个问题搞定了,在这里记录一下。

  实际上 Google 在实现 Android 系统的 Framework 层时,就已经很有先见之明地开发了这个功能,官方称呼是 TeeSink。顾名思义,它可以为音频流开启一个 T 型的数据管道,在将音频流输出到扬声器这样的音频设备(或者录音)的同时,还可以把这些原始的 PCM 音频数据保存到 .wav 文件中。其官方说明如下:

The "tee sink" is an AudioFlinger debugging feature, available in custom builds only, for retaining a short fragment of recent audio for later analysis. This permits comparison between what was actually played or recorded vs. what was expected.

For privacy the tee sink is disabled by default, at both compile-time and run-time. To use the tee sink, you will need to enable it by re-compiling, and also by setting a property. Be sure to disable this feature after you are done debugging; the tee sink should not be left enabled in production builds.

    这段话的大意是 TeeSink 是 AudioFlinger 的一个调试功能,可以用来保存被播放音频的片段,但这个功能默认是关闭的,我们需要修改代码并重新编译系统才能使用。


【开启功能】

    正如上文所讲,这个功能默认是关闭的,我们需要在 frameworks/av/services/audioflinger/configuration.h 文件中开启它。很简单,如下将 TEE_SINK 宏解除注释就可以了:

    

    如果足够细心,我们应该会发现这个文件中除了可以开启 TEE_SINK 功能外,还可以开闭其它的调试功能,诸如 AUDIO_WATCHDOG、CPU_FREQUENCY_STATISTICS 等。处处留心皆学问,多看看这些注释,说不定以后碰到什么问题就会从这里获得灵感。

    然后我们需要重新编译 libaudioflinger.so 库文件,并用这个库文件把设备上 /system/lib 路径下的同名库文件替换掉,然后重启设备。

    或者也可以采取另一个偷懒的办法,直接重新编译整个系统镜像,然后烧写镜像到设备上。(会花费较多的时间,可以下楼吃个便当或者关东煮再回来。不然怎么叫偷懒呢)

    接下来,我们需要检查系统的 ro.debuggable 属性,确保属性值是 1:

    

    然后检查 /data/misc/media 目录的属性,确保它显示的信息是类似下方这样的:

    

    如果 media 目录不存在,那么我们使用下方的命令来创建它:

    $  mkdir  /data/misc/media

    $  chown  media:media  /data/misc/media

    最后还要在 /data 目录下创建一个文件 local.prop 并在这个文件中写入你想要截取的音频流类型。因为我是要截取视频中的原始音频,所以我需要写入的类型为 4:

    $  echo  af.tee=4 > /data/local.prop

    $  chmod  644  /data/local.prop

    到这里,我们重启设备之后就可以使用 TeeSink 来保存原始的 PCM 音频数据了

    关于 af.tee 的取值,其范围可以是 0~7(实际上就是个 4-bit 长度的变量),简单说明一下:

    1 = 音频输入的数据

    2 = FastMixer音频输出数据(一般是在低延迟播放的场合才会使用这个)

    4 = 所有录音/播放时的音频数据

    可以在 AudioFlinger.cpp 文件的  AudioFlinger() 构造函数中找到相关代码:

    


【保存音频】

    保存音频的操作很简单。先播放会造成问题的音频,然后在出现问题的时候执行下面的命令进行保存即可:

    $  dumpsys  media.audio_flinger

    各个音轨的原始 PCM 音频数据都会被保存在 /data/misc/media/xxxx.wav 文件中,如下图:

    


【注意事项】

    1、在使用 TeeSink 调试完后,一定要将该功能关闭。因为它使用的 local.prop 文件可以被利用进行本地提权,这会带来安全风险。

    2、在 Android 7.x 系统中,/data/misc/media 目录的名字被修改为了 /data/misc/audioserver。


【参考资料】

    [1] 《Audio Debugging》(需要翻墙)


阅读(3947) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~