关于播放模式的选择

https://www.cnblogs.com/wulizhi/p/8183658.html
一。 简介:

我们知道,在Android Audio框架中,主要有四种播放模式: Deep buffer Playback, Low latency Playback, Offload playback和Mutichannel Playback。

Deep buffer Playback:音频文件是在AP侧解码成PCM文件,然后再送到ADSP中处理,音效部分处理的话是在AP侧或者ADSP中进行的。

标志: AUDIO_OUTPUT_FLAG_PRIMARY

支持的声道: 双声道

支持的采样率: 44.1Khz和48Khz

应用场景: 铃声,音视频播放,YouTube等

Low Latency Playback : 和Deep buffer Playback方式类似,但是它所分配的buffer更小些,并且在ADSP侧只做很少或者基本不做处理, 主要是播放一些对延迟要求较高的音频,

比如触碰音和游戏音。

标志:AUDIO_OUTPUT_FLAG_FAST

支持的声道:双声道

支持的采样率:44.1Khz和48Khz

应用场景: 触碰音,游戏音等

Offload Playback: 音频解码部分的工作是在ADSP中完成,AP侧只负责把音频数据送到ADSP中,送出去后,AP侧会进行休眠,ADSP中会分配一块较大的buffer去处理此数据,

在ADSP中进行解码,音效的处理工作,在ADSP解码器处理完数据之前,它会唤醒AP侧去送下一包数据。

支持的格式:MP3, AC3, EAC3, AAC, FLAC, 24bit PCM, 16 bit PCM

标志:AUDIO_OUTPUT_FLAG_DIRECT,AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD,AUDIO_OUTPUT_FLAG_NON_BLOCKING

支持的声道:1, 2, 2,1, 4, 5, 5.1, 6, 7.1

Mutichannel Playback: 和Deep buffer playback类似,但是,它多应用于处理多声道音频数据,采样的解码器是Multichannel Decoder

标志: AUDIO_OUTPUT_FLAG_DIRECT

                                   支持的采样率: 44.1KHZ, 48k

应用场景:播放AAC格式5.1声道音源, 播放杜比AC3/eAC3格式音频

至于每个平台支持哪几种播放模式,以及个播放模式的标志,支持的格式,声道数,输出设备等信息,都是在audio_policy.conf文件里配置的。如下:

复制代码
1 primary {
2 sampling_rates 44100|48000
3 channel_masks AUDIO_CHANNEL_OUT_STEREO
4 formats AUDIO_FORMAT_PCM_16_BIT
5 devices AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_ALL_SCO|AUDIO_DEVICE_OUT_PROXY|AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET|AUDIO_DEVICE_OUT_FM|AUDIO_DEVICE_OUT_FM_TX
6 flags AUDIO_OUTPUT_FLAG_PRIMARY
7 }
8 low_latency {
9 sampling_rates 44100|48000
10 channel_masks AUDIO_CHANNEL_OUT_STEREO
11 formats AUDIO_FORMAT_PCM_16_BIT
12 devices AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_ALL_SCO|AUDIO_DEVICE_OUT_PROXY|AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET|AUDIO_DEVICE_OUT_FM|AUDIO_DEVICE_OUT_FM_TX
13 flags AUDIO_OUTPUT_FLAG_FAST
14 }
15 compress_offload {
16 sampling_rates 8000|11025|16000|22050|32000|44100|48000
17 channel_masks AUDIO_CHANNEL_OUT_MONO|AUDIO_CHANNEL_OUT_STEREO
18 formats AUDIO_FORMAT_MP3|AUDIO_FORMAT_AAC_LC|AUDIO_FORMAT_AAC_HE_V1|AUDIO_FORMAT_AAC_HE_V2
19 devices AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_ALL_SCO|AUDIO_DEVICE_OUT_PROXY|AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET|AUDIO_DEVICE_OUT_FM_TX
20 flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING
21 }
复制代码

二. 播放模式的选择

  1. 在AudioPlayer::start()中会选择一次播放模式:

复制代码
1 status_t AudioPlayer::start(bool sourceAlreadyStarted) {
2 if (mAudioSink.get() != NULL) {
3
4 uint32_t flags = AUDIO_OUTPUT_FLAG_NONE;
5
6 /如果支持DeepBuffer Playback模式,mCreateFlags & ALLOW_DEEP_BUFFERING != 0/
7 if (allowDeepBuffering()) {
8 flags |= AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
9 }
10 /如果支持Offload模式,mCreateFlags & USE_OFFLOAD != 0/
11 if (useOffload()) {
12 flags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
13 }
14 }
15 }
复制代码
mCreateFlags 是在创建AudioPlayer的时候传入的:
复制代码
void AwesomePlayer::createAudioPlayer_l()
{
/如果mOffloadAudio为true,选择OFFLOAD, 否则如果是纯音频,并且播放时长大于5s,就选择deep-buffer模式/
if (mOffloadAudio) {
flags |= AudioPlayer::USE_OFFLOAD;
} else if (mVideoSource == NULL
&& (mDurationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US ||
(getCachedDuration_l(&cachedDurationUs, &eos) &&
cachedDurationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US))) {
flags |= AudioPlayer::ALLOW_DEEP_BUFFERING;
}
}
复制代码
mOffloadAudio的值是在初始化解码器的时候赋值的:
复制代码
1 status_t AwesomePlayer::initAudioDecoder() {
2 /查询是否支持Offload模式播放,/
3 mOffloadAudio = canOffloadStream(meta, (mVideoSource != NULL), vMeta,
4 (isStreamingHTTP() || isWidevineContent()),
5 streamType);
6
7
8 if (!mOffloadAudio && mAudioSource != NULL) {
9 ALOGI(“Could not offload audio decode, try pcm offload”);
10 sp format = mAudioSource->getFormat();
11 if (durationUs >= 0) {
12 format->setInt64(kKeyDuration, durationUs);
13 }
14 / 又查询了一次是否支持Offload模式播放,/
15 mOffloadAudio = canOffloadStream(format, (mVideoSource != NULL), vMeta,
16 (isStreamingHTTP() || isWidevineContent()), streamType);
17 }
18 }
复制代码
canOffloadStream()函数会从音频数据中获取格式,采样率,采样精度,播放时长,声道数,是否有视频源等信息,然后调用AudioSystem::isOffloadSupported()去进行查询,最终的判断是在
AudioPolicyManager中进行的,它主要有以下判断标准:
1). stream type必须是 AUDIO_STREAM_MUSIC
2). 如果音源是PCM格式,audio.offload.pcm.enable 属性必须为true
3). audio.offload.disable 属性必须为false
4). 如果音源是Multichannel类型的,例如声道数大于2,并且是AAC或者FLAC格式的,也不行
5). 如果有视频源,即has_video为true, av.offload.enable属性必须为true, av.streaming.offload.enable也要为true
6). 如果播放的音源格式是MP3, AAC, FLAC或者PCM,长度要大于audio.offload.min.duration.secs配置的值,例如该值被配置成30s,播放音源就得大于30s, 其他格式的,例如杜比AAC/AC3, ARMWB+格  式的没有这个要求。
7). 如果有其他基于PCM进行调试的音效处理的话,也不支持Offload模式
8). 最后一个, offload模式下的参数,采样率,格式,声道,必须要符合audio_policy.conf文件里面的配置

另外,播放时长,是在音视频分离器中计算出来的,例如AMR,是在AMRExtrator.cpp文件中:
复制代码
1 AMRExtractor::AMRExtractor(const sp &source)
2 : mDataSource(source),
3 mInitCheck(NO_INIT),
4 mOffsetTableLength(0) {
5 String8 mimeType;
6 float confidence;
7 /读取文件类型,NB或者WB, 它们的解码方式,采样率都是不一样的/
8 if (!SniffAMR(mDataSource, &mimeType, &confidence, NULL)) {
9 return;
10 }
11
12 mIsWide = (mimeType == MEDIA_MIMETYPE_AUDIO_AMR_WB);
13
14 mMeta = new MetaData;
15 mMeta->setCString(
16 kKeyMIMEType, mIsWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB
17 : MEDIA_MIMETYPE_AUDIO_AMR_NB);
18
19 mMeta->setInt32(kKeyChannelCount, 1);
20 mMeta->setInt32(kKeySampleRate, mIsWide ? 16000 : 8000);
21
22 off64_t offset = mIsWide ? 9 : 6;
23 off64_t streamSize;
24 size_t frameSize, numFrames = 0;
25 int64_t duration = 0;
26
27 if (mDataSource->getSize(&streamSize) == OK) {
28 while (offset < streamSize) {
29 /计算每一frame的数据的大小/
30 if (getFrameSizeByOffset(source, offset, mIsWide, &frameSize) != OK) {
31 return;
32 }
33
34 if ((numFrames % 50 == 0) && (numFrames / 50 < OFFSET_TABLE_LEN)) {
35 CHECK_EQ(mOffsetTableLength, numFrames / 50);
36 mOffsetTable[mOffsetTableLength] = offset - (mIsWide ? 9: 6);
37 mOffsetTableLength ++;
38 }
39
40 offset += frameSize;
41 /每一帧数据播放20ms/
42 duration += 20000; // Each frame is 20ms
43 numFrames ++;
44 }
45
46 mMeta->setInt64(kKeyDuration, duration);
47 }
48
49 mInitCheck = OK;
50 }

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值