Brillo: brillo-m10-dev @ RPi 3B – Audio模块

RPi 2B/3B与DragonBoard 410c的不同之处在于它有一个耳机接口,你只需要一条耳机线,就可以利用它来播放音乐或者是播放一些提示信息。原以为使RPi 3B在Brillo系统下正常工作是一件很难的事情:由于之前一直在做高通Android的项目,关于Audio的配置非常的复杂,所以对Audio模块有点畏惧。这几天硬着头皮去看了一下Intel Edison/Qualcomm DragonBoard/Rockchip Kylin与Audio HAL层相关的代码,发现基本上大同小异,基本上都是是建立在ALSA架构的基础上。这里,RPi 3B @ brillo-m10-dev也是在复用Rockchhip Kylin上的代码。

  • kernel及audio驱动

从kernel log中,我们可以看到kernel已经识别出来RPi 3B的音频设备,并使用ALSA架构:

01-01 00:00:03.140     0     0 W         : Indeed it is in host mode hprt0 = 00001101
01-01 00:00:03.154     0     0 I netconsole: network logging started
01-01 00:00:03.163     0     0 E         : Starting self testing
01-01 00:00:03.166     0     0 E         : Finished self testing
01-01 00:00:03.170     0     0 I         : ALSA device list:
01-01 00:00:03.173     0     0 I         : #0: Dummy 1
01-01 00:00:03.175     0     0 I         : #1: bcm2835 ALSA
01-01 00:00:03.180     0     0 I         : Freeing unused kernel memory: 1024K (80d00000 - 80e00000)
01-01 00:00:03.189     0     0 I init    : init first stage started!
01-01 00:00:03.202     0     0 D SELinux : 2048 avtab hash slots, 6576 rules.
01-01 00:00:03.210     0     0 D SELinux : 2048 avtab hash slots, 6576 rules.
01-01 00:00:03.210     0     0 D SELinux : 1 users, 2 roles, 661 types, 0 bools, 1 sens, 1024 cats
01-01 00:00:03.210     0     0 D SELinux : 56 classes, 6576 rules

我们可以通过/sys/class/sound目录查看当前系统有几个音频设备:

$ adb shell ls -l /sys/class/sound/
total 0
lrwxrwxrwx 1 root root 0 2016-04-02 10:39 card0 -> ../../devices/platform/snd_dummy.0/sound/card0
lrwxrwxrwx 1 root root 0 2016-04-02 10:39 card1 -> ../../devices/virtual/sound/card1
lrwxrwxrwx 1 root root 0 2016-04-02 10:39 controlC0 -> ../../devices/platform/snd_dummy.0/sound/card0/controlC0
lrwxrwxrwx 1 root root 0 2016-04-02 10:39 controlC1 -> ../../devices/virtual/sound/card1/controlC1
lrwxrwxrwx 1 root root 0 2016-04-02 10:39 pcmC0D0c -> ../../devices/platform/snd_dummy.0/sound/card0/pcmC0D0c
lrwxrwxrwx 1 root root 0 2016-04-02 10:39 pcmC0D0p -> ../../devices/platform/snd_dummy.0/sound/card0/pcmC0D0p
lrwxrwxrwx 1 root root 0 2016-04-02 10:39 pcmC1D0p -> ../../devices/virtual/sound/card1/pcmC1D0p
lrwxrwxrwx 1 root root 0 2016-04-02 10:39 pcmC1D1p -> ../../devices/virtual/sound/card1/pcmC1D1p
lrwxrwxrwx 1 root root 0 2016-04-02 10:39 timer -> ../../devices/virtual/sound/timer

这里,我们可以看到当前有两个音频设备: card0, card1。我们可以通过查看/sys/class/sound/card?/id来确实当音频设备的名称:

$ adb shell cat /sys/class/sound/card0/id
Dummy
$ adb shell cat /sys/class/sound/card1/id
ALSA
  • 相关工具

在Brillo-m10-dev系统中,我们已经将tinycap/tinymix/tinypcminfo/tinyplay这些工具编译进系统了,下面我们看一下这些工具的用法:

1. tinypcminfo – 查看音频设备信息(bcm2835是card1):

# tinypcminfo -D 1                                                                                                                                                                                                
Info for card 1, device 0:

PCM out:
      Access:	0x000009
   Format[0]:	0x000006
   Format[1]:	00000000
 Format Name:	U8, S16_LE
   Subformat:	0x000001
        Rate:	min=8000Hz	max=48000Hz
    Channels:	min=1		max=2
 Sample bits:	min=8		max=16
 Period size:	min=256		max=65536
Period count:	min=1		max=128

PCM in:
cannot open device '/dev/snd/pcmC1D0c'
Device does not exist.

可以看到这个单频设备只支持PCM输入,不支持PCM输入。

2. tinymix – 查看当前音频设备包含哪些widget:

# tinymix -D 1                                                                                                                                                                                                    
Mixer name: 'bcm2835 ALSA'
Number of controls: 6
ctl	type	num	name                                     value
0	INT	1	PCM Playback Volume                      0
1	BOOL	1	PCM Playback Switch                      On
2	INT	1	PCM Playback Route                       0
3	IEC958	1	IEC958 Playback Default                  unknown
4	IEC958	1	IEC958 Playback Con Mask                 unknown
5	IEC958	1	IEC958 Playback PCM Stream               unknown

NOTE: 看来还是得用tinymix来查看音频设备的名称比较好:能够正确显示当前card1对应的名称为bcm2835 ALSA。

3. tinyplay – 播放wav格式的音频文件:

# tinyplay /data/Over_the_Horizon.wav -D 1                                                                                                                                                                        
Playing sample: 2 ch, 44100 hz, 16 bit

NOTE: 播放的时候需要指定音频设备。

4. tinycap – 录音

  • Audio HAL实现

代码直接复用hardware/bsp/rockchip/peripheral/audio/generic的代码并用少量修改:

1. audio_hw.c

diff -r /local/brillo-m10-dev-rpi3b/device/hzak/rpi3b/bsp/audio/audio_hal.c generic/audio_hal.c
50c50
< #define AUDIO_STR "bcm2835"
---
> #define AUDIO_STR "rt5616"
708d707
< 	out->profile->default_config.period_count = 4;
1129c1128
< #if 0 //TARGET_AUDIO_PRIMARY
---
> #if TARGET_AUDIO_PRIMARY
1191c1190
< #if 0 //TARGET_AUDIO_PRIMARY
---
> #if TARGET_AUDIO_PRIMARY
1226c1225
< #if 0 //TARGET_AUDIO_PRIMARY
---
> #if TARGET_AUDIO_PRIMARY

2. audio_policy.conf

global_configuration {
  attached_output_devices AUDIO_DEVICE_OUT_WIRED_HEADPHONE
  default_output_device AUDIO_DEVICE_OUT_WIRED_HEADPHONE
}
audio_hw_modules {
  primary {
    outputs {
      primary {
        sampling_rates 8000|11025|12000|16000|22050|24000|32000|44100|48000
        channel_masks AUDIO_CHANNEL_OUT_STEREO
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_OUT_WIRED_HEADPHONE
        flags AUDIO_OUTPUT_FLAG_PRIMARY
      }
    }
  }
}

3. 加入Audio Effect模块,以便可以对不支持持音频文件进行resample

# Effect libraries
PRODUCT_PACKAGES += \
    libbundlewrapper \
    libreverbwrapper \
    libvisualizer \
    libdownmix \
    libldnhncr

PRODUCT_COPY_FILES += \
    frameworks/av/media/libeffects/data/audio_effects.conf:system/etc/audio_effects.conf
  • 验证

我们可以通过stagefright命令验证Audio HAL模块是否能够正常播放。stagefright没有编译进system image中,可以通过如下命令单独编译stagefright模块:

hzak@B85RPI:/local/brillo-m10-dev-rpi3b$ mmm frameworks/av/cmds/stagefright/:stagefright
$ adb remount
$ adb sync system

使用stagefright播放音频文件:

# stagefright -a -o /data/Over\ the\ Horizon.mp3
  • 调试相关

显示系统服务:

$ adb shell service list
Found 17 services:
0	media.radio: [android.hardware.IRadioService]
1	media.sound_trigger_hw: [android.hardware.ISoundTriggerHwService]
2	media.audio_policy: [android.media.IAudioPolicyService]
3	media.camera: [android.hardware.ICameraService]
4	media.resource_manager: [android.media.IResourceManagerService]
5	media.player: [android.media.IMediaPlayerService]
6	media.audio_flinger: [android.media.IAudioFlinger]
7	bluetooth-service: [bluetooth-service]
8	android.brillo.UpdateEngineService: [android.brillo.IUpdateEngine]
9	sensorservice: [android.gui.SensorServer]
10	weave_service: [android.weave.IWeaveServiceManager]
11	android.brillo.metrics.IMetricsCollectorService: [android.brillo.metrics.IMetricsCollectorService]
12	android.brillo.metrics.IMetricsd: [android.brillo.metrics.IMetricsd]
13	android.security.keystore: [android.security.IKeystoreService]
14	example_led_service: [brillo.examples.ledflasher.ILEDService]
15	android.os.IPeripheralManager: [android.os.IPeripheralManager]
16	power: [android.os.IPowerManager]

dumpsys media.audio_policy:

$ adb shell dumpsys media.audio_policy
AudioPolicyManager: 0x75bc5000
Command Thread: 0x75baaa80
Tones Thread: 0x75baaa20
AudioCommandThread 0x75baaa80 Dump
- Commands:
   Command Time        Wait pParam
  Last Command
   07      000956.109  0    0x7502e400
AudioCommandThread 0x75baaa20 Dump
- Commands:
   Command Time        Wait pParam
  Last Command
     none

AudioPolicyManager Dump: 0x75bc5000
 Primary Output: 2
 Phone state: 0
 Force use for communications 0
 Force use for media 0
 Force use for record 0
 Force use for dock 0
 Force use for system 0
 Force use for hdmi system audio 0
 TTS output not available

 Available output devices:
  Device 1:
  - id:  1
  - type: AUDIO_DEVICE_OUT_WIRED_HEADPHONE                

 Available input devices:

HW Modules dump:
- HW Module 1:
  - name: primary
  - handle: 1
  - version: 2.0
  - outputs:
    output 0:
    - name: primary
    - sampling rates: 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
    - channel masks: 0x0003
    - formats: AUDIO_FORMAT_PCM_16_BIT
    - flags: 0x0002
    - devices:
      Device 1:
      - type: AUDIO_DEVICE_OUT_WIRED_HEADPHONE
...

发表评论

电子邮件地址不会被公开。 必填项已用*标注