概述
1.音频硬件设备
也称为module,定义在services/audiopolicy/config/audio_policy_configuration.xml:
分别有primary,a2dp,usb,r_submix;
配置文件中的每一个module都被描述为HwModule,保存在mHwModules中;
2.output
可以理解成是输出端设备,常用的输出端设备有:
prmary_out,low_latency,deep_buffer,compress_offload,mutil_channel等;
定义在services/audiopolicy/config/audio_policy_configuration.xml;
每个输出设备上都有声卡,蓝牙设备,HDMI接口等;
声卡上面有一个喇叭,也就是speaker,以及一个耳机/麦克插孔用来连接耳机;
蓝牙设备用来连接蓝牙耳机;
把一个设备上具有相同参数的一组device称为output:
①output是多个device的组合;
②这些devcie属于同一硬件上的不同端口;
③这些device支持相同的参数,如:采样率,通道等;
也就是说,output是具有相同特性的device的组合;
配置文件中的每一个output都被描述为OutputProfile,保存在module->mOutputProfiles中;
3.SwAudioOutputDescriptor
Output的描述符,真正的output对象,以output为句柄,保存在AudioPolicyManager的mOutputs中;
可以通过flag,device,stream去获取;
4.PlaybackThread
回放线程。
output在创建同时,会创建一个与之一一对应的PlaybackThread,句柄为output,保存在AudioFlinger的mPlaybackThreads中;
PlaybackThread的类型与配置文件中output的flag有关。
PlaybackThread与output一一对应,一旦确定了output,也就确定了PlaybackThread;
5.AudioPolicyManager中的mpClientInterface
其实是AudioPolicyClientInterface *mpClientInterface,
定义在frameworksavservicesaudiopolicyserviceaudioPolicyClientImpl.cpp中;
6.stream与stage
流类型很多,需要为将他们分类,将具有相同行为的stream分成一组,它们共用一个Strategy:
具有相同行为的Stream:播放的设备一样,device相同,播放优先级相同。
7.stream,strategy,device,output,flag以及playbackthread之间的关系?
①解析配置文件时:
创建output
-->根据flag创建playbackthread
-->以output为句柄保存playbackthread;
②播放声音时:
app指定声音类型stream type
-->将stream进行分类,属于哪一strategy
-->根据strategy确定播放的设备device
-->根据device,flag确定output
-->根据output确定playbackthread
-->把声音数据传给这个thread
8.AudioPolicyService启动过程
①读取解析配置文件
②根据配置文件调用AudioFlinger的服务,打开output,创建线程;
void AudioPolicyService::onFirstRef()
// start tone playback thread
mTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this);
// start audio commands thread
mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
// start output activity command thread
mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);
/*
AudioPolicyService要使用AudioFlinger提供的服务,mAudioPolicyClient 就是AudioFlinger的客户 端,可以通过AudioPolicyClient使用AudioFlinger提供的服务访问硬件。
AudioPolicyClient是在AudioPolicyClientImpl.cpp文件中实现的
*/
mAudioPolicyClient = new AudioPolicyClient(this);
mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);
createAudioPolicyManager(mAudioPolicyClient)主要就是构建AudioPolicyManager,在AudioPolicyManager里面解析配置文件。
AudioPolicyService启动过程分析:
a. 对于配置文件里的每一个module项, new HwModule(name), 放入mHwModules数组;
对于module里的每一个output, new IOProfile, 放入module的mOutputProfiles;
对于module里的每一个input, new IOProfile, 放入module的mInputProfiles;
b. 根据module的name加载厂家提供的so文件 (通过AudioFlinger来加载)
c. 打开对应的output (通过AudioFlinger来open output)
9.AudioTrack的创建过程:
①使用AudioTrack的属性, 根据AudioPolicy找到对应的output、playbackThread
②在playbackThread中创建对应的track
③APP的AudioTrack 和 playbackThread的mTracks中的track之间建立共享内存
10.output选择的优先级:
output的选择发生在AudioTrack.set()中,最终会走到AudioPolicyManager::getOutputForDevice()中;
选择output的逻辑优先级是:
flags > Format > primary > outputs[0](即outputs中的第一个output)。
11.应用程序的AudioTrack与播放线程之中的Track之间是怎么传递数据的?
应用的AudioTrack提供数据有两种方式:
①MODE_STATIC:一次性提供,比如简单的提示音,可以把所有的数据一次性提供给播放线程;
②MODE_STREAM:边播边提供,比如播放音乐;
在每个playbackThread中,有一个mTracks数组,其中肯定有一项,与我们的应用程序的AudioTrack对应起来,应用程序往track中写入数据时,playbackThread就能从对应的track中取出数据,然后混音播放。
所以APP与PlaybackThread声音数据的传递是使用共享内存(即APP与PlaybackThread可以访问同一块内存)。
共享内存是由谁来创建的,是由APP还是由PlaybackThread呢?
①如果APP提供AudioTrack的数据是一次性提供(MODE_STATIC:一次性,提前提供数据),那么显然这个buffer当然是由应用程序提供。因为应用程序才知道这个buffer有多大。
②如果应用程序是一边播放,一边提供数据(MODE_STREAM),那么就由PlaybackThread创建共享内存,因为这样省事(为了简单应用程序的编程)。
应用程序APP与PlaybackThread如何同步数据呢?
①如果APP提供AudioTrack的数据是一次性提供(MODE_STATIC:一次性,提前提供数据),APP先构造,PlaybackThread再消费,则无需进行同步。
②如果应用程序,是一边播放一边提供数据(MODE_STREAM),使用环形缓冲区进行同步。
AudioFlinger::PlaybackThread::Track::Track(
if (sharedBuffer == 0) {
//如果应用程序没有创建sharedBuffer,那么气会创建一个AudioTrackServerProxy用来管理Buffer
mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
mFrameSize, !isExternalTrack(), sampleRate);
} else {
//如果提供了sharedBuffer,则会创建StaticAudioTrackServerProxy,用来管理者一个buffer
mAudioTrackServerProxy = new StaticAudioTrackServerProxy(mCblk, mBuffer, frameCount,
mFrameSize);
}
mServerProxy = mAudioTrackServerProxy;
status_t AudioTrack::set(
status_t status = createTrack_l();
/*使用audioFlinger的服务创建Track,会导致播放线程中创建Track*/
sp<IAudioTrack> track = audioFlinger->createTrack()
/*如果没有提供buffer,指向PlaybackThread提供的buffer*/
if (mSharedBuffer == 0) {
buffers = cblk + 1;
} else {
/*否则指向自己提供的buffer*/
buffers = mSharedBuffer->pointer();
if (buffers == NULL) {
ALOGE("Could not get buffer pointer");
return NO_INIT;
}
}
/*管理共享内存*/
// update proxy
if (mSharedBuffer == 0) {
//如果应用程序没有创建sharedBuffer,那么气会创建一个AudioTrackClientProxy用来管理Buffer
mStaticProxy.clear();
mProxy = new AudioTrackClientProxy(cblk, buffers, frameCount, mFrameSize);
} else {
//如果提供了sharedBuffer,则会创建StaticAudioTrackClientProxy用来管理一个buffer
mStaticProxy = new StaticAudioTrackClientProxy(cblk, buffers, frameCount, mFrameSize);
mProxy = mStaticProxy;
}
AudioTrackClientProxy对应AudioTrackServerProxy,StaticAudioTrackClientProxy对应StaticAudioTrackServerProxy,都是对buffer以及共享内存的管理。
最后
以上就是粗暴荷花为你收集整理的音频相关概念的全部内容,希望文章能够帮你解决音频相关概念所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复