切换语言为:繁体

投屏工具scrcpy导致Android设备声音播放问题

  • 爱糖宝
  • 2024-08-01
  • 2179
  • 0
  • 0

一、问题背景:

音乐播放器播放music,发现能够播放但是没有声音,但是用tinyplay播放又有声音。

二、问题分析:

无声是必现的,抓取log分析,发现播放音频时并没有走primary module,而是走的r_submix module,这个无声问题就能解释通了,音频流并没有走到adsp。

07-24 11:59:21.285 1015 1859 I AudioFlinger: openOutput() this 0xb4000077f35ce9c0, module 26 Device AUDIO_DEVICE_OUT_REMOTE_SUBMIX, @:0, SamplingRate 48000, Format 0x000001, Channels 0x3, flags 0

07-24 11:59:21.286 907 930 D r_submix: adev_open_output_stream(address=0)

07-24 11:59:21.287 907 930 I r_submix: adev_open_output_stream(): about to create pipe at index 9, rate 48000, pipe size 4096

07-24 11:59:21.287 907 930 D r_submix: submix_audio_device_create_pipe_l(addr=0, idx=9)

07-24 11:59:21.287 907 930 D r_submix: now using address 0 for route 9

为什么会走到AUDIO_DEVICE_OUT_REMOTE_SUBMIX这个设备出去呢? 从官网上查询到REMOTE_SUBMIX这个音频类型,描述上看就是捕获设备音频流投到远端设备上。

投屏工具scrcpy导致Android设备声音播放问题

参考官网:MediaRecorder.AudioSource  |  Android Developers (google.cn)

从log上看,确实有录音动作,AUDIO_SOURCE_REMOTE_SUBMIX这个就是REMOTE_SUBMIX这个音源类型

7-24 11:59:21.235 1015 1015 V APM_AudioPolicyManager: getInputForAttr() source 8, sampling rate 48000, format 0x1, channel mask 0xc, session 225, flags 0 attributes={ Content type: AUDIO_CONTENT_TYPE_UNKNOWN Usage: AUDIO_USAGE_UNKNOWN Source: AUDIO_SOURCE_REMOTE_SUBMIX Flags: 0x800 Tags: } requested device ID 0

07-24 11:59:21.236 1015 1015 V APM_AudioPolicyManager: getInputForAttr found device type is 0x80000100

07-24 11:59:21.238 907 930 D r_submix: adev_open_input_stream(addr=0)

07-24 11:59:21.239 907 930 I r_submix: adev_open_input_stream(): about to create pipe at index 9, rate 48000, pipe size 4096

07-24 11:59:21.239 907 930 D r_submix: submix_audio_device_create_pipe_l(addr=0, idx=9)

07-24 11:59:21.240 907 930 D r_submix: now using address 0 for route 9

同测试沟通,了解到使用了scrcpy投屏工具,这就对上了

三、scrcpy音频录制分析:

下载scrcpy源码:github.com/Genymobile/…

源码中确实有录音动作,AudioCapture.java中会创建AudioRecord scrcpy/server/src/main/java/com/genymobile/scrcpy/AudioCapture.java

private static AudioRecord createAudioRecord(int audioSource) {
    AudioRecord.Builder builder = new AudioRecord.Builder();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        // On older APIs, Workarounds.fillAppInfo() must be called beforehand
        builder.setContext(FakeContext.get());
    }   
    builder.setAudioSource(audioSource);
    builder.setAudioFormat(createAudioFormat());
    int minBufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE, CHANNEL_CONFIG, ENCODING);
    // This buffer size does not impact latency
    builder.setBufferSizeInBytes(8 * minBufferSize);
    return builder.build();
}


跟踪audioSource来源,发现是MediaRecorder.AudioSource.REMOTE_SUBMIX这个音频源,这个又对上了

Options.java

private AudioSource audioSource = AudioSource.OUTPUT;

AudioSource.java

OUTPUT("output", MediaRecorder.AudioSource.REMOTE_SUBMIX),

scrcpy录制Android设备音频原理:源码中的java代码编译打包到scrcpy-server,然后push到Android设备,执行app_process运行scrcpy-server

四、总结:

scrcpy投屏工具将Android设备音频流录制后投到PC端,PC端插上耳机后能听到Android设备播放的music

0条评论

您的电子邮件等信息不会被公开,以下所有项均必填

OK! You can skip this field.