当前位置:   article > 正文

视频流分析 二_track handle

track handle

目录

5 AudioFlinger和AudioPolicyServer

5 AudioFlinger和AudioPolicyServer

        AudioPolicyService是Android音频系统的两大服务之一,另一个服务是AudioFlinger,这两大服务都在系统启动时有 MediaSever加载,加载的代码位于:frameworks\base\media\mediaserver \main_mediaserver.cpp。AudioFlinger主要负责管理音频数据处理以及和硬件抽象层相关的工作。AudioPolicyService主要完成以下任务:JAVA应用层通过JNI,经由IAudioPolicyService接口,访问AudioPolicyService提供的服务;输入输出设备的连接状态;系统的音频策略(strategy)的切换;音量/音频参数的设置。

1. AudioPolicyService继承了IAudioPolicyService接口,这样AudioPolicyService就可以基于Android的Binder机制,向外部提供服务;

2. AudioPolicyService同时也继承了AudioPolicyClientInterface类,他有一个AudioPolicyInterface类的成员指针mpPolicyManager,实际上就是指向了AudioPolicyManager;

3. AudioPolicyManager类继承了AudioPolicyInterface类以便向AudioPolicyService提供服务,反过来 同时还有一个AudioPolicyClientInterface指针,该指针在构造函数中被初始化,指向了AudioPolicyService,实 际上,AudioPolicyService是通过成员指针mpPolicyManager访问AudioPolicyManager,而 AudioPolicyManager则通过AudioPolicyClientInterface(mpClientInterface)访问 AudioPolicyService;

4. AudioPolicyService有一个内部线程类AudioCommandThread,顾名思义,所有的命令(音量控制,输入、输出的切换等)最终都会在该线程中排队执行;

5.AudioFlinger 类是代表整个AudioFlinger 服务的类,其余所有的工作类都是通过内部类的方式在其中定义的。你把它当做一个壳子也行吧。

class AudioFlinger : public BnAudioFlinger, public IBinder::DeathRecipient

6. Client 是描述C/S结构的C端的代表,也就算是一个AT 在AF 端的对等物吧。不过可不是Binder 机制中的BpXXX 喔。因为AF 是用不到AT 的功能的。

  1. class Client : public RefBase {
  2. public:
  3. Client(const sp<AudioFlinger>& audioFlinger, pid_t pid);
  4. virtual ~Client();
  5. const sp<MemoryDealer>& heap() const;
  6. pid_t pid() const { return mPid; }
  7. sp<AudioFlinger> audioFlinger() { return mAudioFlinger; }
  8. private:
  9. Client(const Client&);
  10. Client& operator = (const Client&);
  11. sp<AudioFlinger> mAudioFlinger;
  12. sp<MemoryDealer> mMemoryDealer;
  13. pid_t mPid;
  14. };

7. Trackhandle 是AT 端调用AF 的CreateTrack 得到的一个基于Binder 机制的Track。这个 TrackHandle 实际上是对真正干活的PlaybackThread::Track 的一个跨进程支持的封装。什么意思?本来PlaybackThread::Track 是真正在AF 中干活的东西,不过为了支持跨进程的话,我们用TrackHandle 对其进行了一下包转。这样在AudioTrack 调用TrackHandle 的功能,实际都由TrackHandle 调用PlaybackThread::Track 来完成了。可以认为是一种Proxy 模式吧。

  1. class TrackHandle : public android::BnAudioTrack {
  2. public:
  3. TrackHandle(const sp<PlaybackThread::Track>& track);
  4. virtual ~TrackHandle();
  5. virtual status_t start();
  6. virtual void stop();
  7. virtual void flush();
  8. virtual void mute(bool);
  9. virtual void pause();
  10. virtual void setVolume(float left, float right);
  11. virtual sp<IMemory> getCblk() const;
  12. virtual status_t attachAuxEffect(int effectId);
  13. virtual status_t onTransact(
  14. uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
  15. private:
  16. sp<PlaybackThread::Track> mTrack;
  17. };

8.线程类

RecordThread : public ThreadBase, public AudioBufferProvider

class PlaybackThread : public ThreadBase

MixerThread : public PlaybackThread

DirectOutputThread : public PlaybackThread

DuplicatingThread : public MixerThread

class Track : public TrackBase                          --PlayingThread 的内部类Track

class TrackBase : public AudioBufferProvider, public RefBase

AudioFlinger功能:

  1. 播放:将应用写入的PCM数据给audio driver播放。
  2. 录音:将从audio driver读取的PCM传输给应用实现录音。
  3. SRC(Sample Rate Converter):根据需要支持采样率的转换功能。
  4. 混音:支持最多32路stream的混音播放
  5. 路径切换:支持多种输入路径,输出路径的选择,切换。
  6. 模式:支持三种不同的模式:normal/ringtone/in-call
  7. 音量控制:根据不同需要支持音量控制。

输出路径管理:

1. 应用层状态发生改变

  因素:1.手机模式发生改变  setMode()     AudioManager.java

        2.stream的状态发生改变

2. 设备状态发生改变

  因素:1.calling:用户默认选择“speaker”

        2.FMRadio:默认选择“headset”

3.应用程序的强制需求

因素:1.插入,拔出耳机

2.连接断开Bluetooth耳机

这个部分的流程与音量调节过程基本相似,重点需要学习的是audioflinger中Track与Record部分。

Record部分:

  1. 1.创建audioflinger
  2. Main(Main_mediaServer.cpp)
  3. =>AudioFlinger::instantiate()(Main_mediaServer.cpp)
  4. =>AudioFlinger()(audioFlinger.cpp)
  5. =>AudioHardwareInterface::create()(audioFlinger.cpp)
  6. =>AudioPolicyService::instantiate()(Main_mediaServer.cpp)
  7. 2.分析createTrack函数
  8. createTrack(audioFlinger.cpp)
  9. => checkPlaybackThread_l(audioFlinger.cpp)—根据output句柄获得线程
  10. =>createTrack_l(audioFlinger.cpp)—从上面返回的线程对象中创建一个track
  11. =>new Track(audioFlinger.cpp)
  12. =>分析Track构造函数(audioFlinger.cpp)
  13. =>再分析TrackBase构造函数(audioFlinger.cpp)
  14. =>new(mCblk) audio_track_cblk_t();
  15. 3.分析output的来源
  16. getOutput(AudioSystem.cpp)
  17. => getOutput(AudioPolicyService.cpp)
  18. => getOutput(AudioPolicyManagerBase.cpp)
  19. =>output = mHardwareOutput(AudioPolicyManagerBase.cpp)
  20. =>分析构造函数AudioPolicyService()并传递this指针AudioPolicyManagerBase
  21. =>分析构造函数AudioPolicyManagerBase()
  22. => openOutput(AudioPolicyManagerBase.cpp)返回mHardwareOutput
  23. => openOutput(AudioPolicyService.cpp)
  24. => openOutput(audioFlinger.cpp)
  25. =>openOutputStream(AudioHardwareALSA.cpp)
  26. =>new AudioStreamOutALSA(AudioHardwareALSA.cpp)
  27. =>new MixerThread()混音线程创建(audioFlinger.cpp)
  28. =>new AudioMixer(audioFlinger.cpp)
  29. =>AudioFlinger::MixerThread::threadLoop(audioFlinger.cpp)
  30. =>prepareTracks_l(audioFlinger.cpp)
  31. =>mAudioMixer->process()(audioFlinger.cpp)

(这是C++语法中的placement new。干啥用的啊?new 后面的括号中是一块buffer,再后面是一个类的构造函数。对了,这个placement new 的意思就是在这块buffer 中构造一个对象。我们之前的普通new 是没法让一个对象在某块指定的内存中创建的。而placement new 却可以。这样不就达到我们的目的了吗?搞一块共享内存,再在这块内存上创建一个对象。这样,这个对象不也就能在两个内存中共享了吗?)

=>new TrackHandle(track) (audioFlinger.cpp)

(Trackhandle 是AT 端调用AF 的CreateTrack 得到的一个基于Binder 机制的Track。这个 TrackHandle 实际上是对真正干活的PlaybackThread::Track 的一个跨进程支持的封装。什么意思?本来PlaybackThread::Track 是真正在AF 中干活的东西,不过为了支持跨进程的话,我们用TrackHandle 对其进行了一下包转。这样在AudioTrack 调用TrackHandle 的功能,实际都由TrackHandle 调用PlaybackThread::Track 来完成了。可以认为是一种Proxy 模式吧。)

在我们再次被绕晕之后,我们回眸看看足迹吧:

1.在 AudioTrack 中,调用set 函数

2.这个函数会通过AudioSystem::getOutput 来得到一个output 的句柄

3.AS 的getOutput 会调用AudioPolicyService 的getOutput

4.然后我们就没继续讲APS 的getOutPut 了,而是去看看APS 创建的东西

5.发现 APS 创建的时候会创建一个AudioManagerBase,这个AMB 的创建又会调用

6.APS 的openOutput。

7.APS 的openOutput 又会调用AudioFlinger 的openOutput

  1. Start(AudioTrack.cpp)
  2. =>mAudioTrack->start()(AudioTrack.cpp)
  3. =>AudioFlinger::TrackHandle::start()(audioFlinger.cpp)
  4. => mTrack->start()(audioFlinger.cpp)
  5. =>AudioFlinger::PlaybackThread::Track::start()(audioFlinger.cpp)
  6. =>playbackThread->addTrack_l(this) (audioFlinger.cpp)
  7. =>mActiveTracks.add(track) (audioFlinger.cpp) —加入到活跃数组
  8. => mWaitWorkCV.broadcast()

(看到这个broadcast,一定要想到:恩,在不远处有那么一个线程正等着这个CV 呢。start 是把某个track 加入到PlayingThread 的活跃Track 队列,然后触发一个信号事件。由于这个事件是PlayingThread 的内部成员变量,而PlayingThread 又创建了一个线程,那么难道是那个线程在等待这个事件吗?这时候有一个活跃track,那个线程应该可以干活了吧?这个线程是MixerThread。我们去看看它的线程函数threadLoop)

  1. => AudioFlinger::MixerThread::threadLoop()(audioFlinger.cpp)
  2. =>prepareTracks_l(audioFlinger.cpp)
  3. =>mAudioMixer->process()(audioFlinger.cpp)
  4. =>AudioMixer(audioFlinger.cpp)
  5. =>mState.hook(&mState, output) (audioFlinger.cpp)
  6. =>AudioMixer(AudioMixer.cpp)
  7. =>mState.hook = process__nop(AudioMixer.cpp)
  8. =>mOutput->write(mMixBuffer, mixBufferSize) (audioFlinger.cpp)

(把缓存的数据写到outPut 中。这个mOutput 是AudioStreamOut,由Audio HAL 的那个对象创建得到)

AudioFlinger层的内容会编译成库libaudioflinger.so。AudioFlinger是Audio系统的中间层,在系统中起服务的作用,向上通过IAudioFlinger接口提供服务,向下访问AudioHardware,实现输出音频数据,控制音频参数。另外,AudioFlinger还为libmedia提供Audio部分接口的实现。AudioPolicyService主要完成以下功能:JAVA应用层通过JNI,经由IAudioPolicyService接口,访问AudioPolicyService提供的服务。输入输出设备的连接状态。系统的音频策略(strategy)的切换。音量/音频参数的设置。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/318879?site
推荐阅读
相关标签
  

闽ICP备14008679号