在好例子网,分享、交流、成长!
您当前所在位置:首页Others 开发实例一般编程问题 → android Audio ALSA框架分析

android Audio ALSA框架分析

一般编程问题

下载此实例
  • 开发语言:Others
  • 实例大小:0.33M
  • 下载次数:12
  • 浏览次数:123
  • 发布时间:2021-02-04
  • 实例类别:一般编程问题
  • 发 布 人:好学IT男
  • 文件格式:.pdf
  • 所需积分:2
 

实例介绍

【实例简介】
从框图中可以看出 android 对于 java 层一共提供 3 个接口,分别 MedialPlayer、MediaREcorder 以及 AudioServier,通过 JNI 则调用到 AudioTrack(放 AudioRecord(录音)以及(AudioSystem)主要音频参数设定。通过 Android Binder 机 AudioFlinger 层相同步,之后调用到 AudioHardware ,其中提供的接口主要 AudioStreamOut以及AudioStreamin。最终将进入Linux内核调用到ALSA。
android media Audiotrack start(NIEnv *env, jobject thiz AudioTrack lpTrack =(AudioTrack *)eny-> GetInt Field( thiz, javaAudioTrack Fields nativeTrackInJavaobj) if (IpTrack== NULL)t jniThrow Exception(env, java/lang/llegalState Exception Unable to retrieve Audio Track pointer for start()"); IpTrack->start(): 文件的 android media Audio frack_ native setup函数中,有对声音系统的一系列初始化 操作,例如设定采样率、格式,通道数等等,在设定好这些数据后,调用 IpTrack=new Audio Track完成 Audio track实例化,紧接着调用 IpTrack->setO完成刚才一系列参数的“写 入"工作。 Audiotrack*k lpTrack new AudioTrack( if (Iptrack ==NULL)[ LOGE("Error creating uninitialized Audiotrack ) goto native track failure; // initialize the native audio track object if (memory Mode = javaAudioTrack Fields MODE STREAM)I IpTrack->set( atstream Type. / stream ty pe sampleRateInHertz, format, / word length, PCM channels frame Count O,//flags audiocallback, &(lpnistorage->mCallbackData, //callback, callback data user 0, //notification Frames ==0 since not using EVENT MORE DATA to feed th e Audio track 0,// shared mem true); //thread can call Java Media库中的Aud框架部分 AudioTrack. cpp中的代码主要是给j层 android media Audio track提供接口。在该文 件中有 Audiotrack类中函数的实现方法。其中某些函数将会调用 AudioSystem中的部分函 数。在 Audio Track. cpp与 Audiorecord. cpp文件中,最关键的是 write函数和read函数,因 为这是录音和放音的数据传递函数,因为和 Audio Flinger层关系密切,所以放在 AudioFlinger的录音管理和放音管理中详细描述 Audio track类的构造函数只实现一个功能,便是设定声音系统的各种参数,这些参数 是由se0来设定的,该调用时在jn层完成的。下面就首先分析set函数 首先我们要确定 Audiotrack类中的 aUdio track没有被使用。否则的话将出错。然后 通过 Audio System中的 get_audio_ flinger函数获得。通过这个函数就可以获得 IAudioflinger 实例化的对象。这个 IAudioFlinger就是一个 binder的代理接口。至于 binder的实现,不再 audio的讨论范围。接下来是一系列参数的设定。首先根据传递进来的 streamType来获得 当前的部分参数,然后根据条件进行部分参数的设定。例如如果 samplerate没有设定,则 设定采样率为当前值。当这些临时变量设定好后,到了最关键的部分— createtrack通过这 个函数的返回,获得了一个 AUdiotrack对象,这个对象控制着整个音频系统的录音功能。 整个 Audio track的音频控制功能都是通过它完成的。这里可以把 audiotrack理解成是一个 接口类,所有的工作都是通过它来和 binder来完成通信。在初始化的最后完成 Audio track 内其他成员函数的初始化。 status t AudioTrack : set( oid user int notification Frames const sp<MEmory>& sharedBuffer bool thread Can Calllaval if (aUdiotRack!=0)t LOGE(" Track already in use") return INVALID OPEration const sp<lAudioFlinger>& audioFlinger AudioSystem::get audio flin ger(); int afsample Rate if (AudioSystem: getoutputsamplingRate(&afsampleRate, streamType)!= NO E RRORI return No nit if (channelCount ==0)f channelCount= 2: status t status. sp<IAudio Track> track audio Flinger->create Track(getpid(), streamType, sampleRate, format, channelCount, frame Count, fl ags, sharedBuffer, &status); sp<MEmory> cblk= track->getcblk( if (cblk==0)[ LOGE("Could not get control block ) return No iNit aUdiotrack track mCblkMemory = cblk mCblk static cast<audio track cblk t*>(cblk->pointer () mCblk->out =1 //Update buffer size in case it has been limited by Audio Flinger during track cre ation m Frame Count mcblk->frame count: mCb|k-> volume[o」=mCbk-> volume1]=0×1000; vOlume[LEFT]= 1.of return NO error, Sar函数是jni层将要调用的函数,这个函数实际上是一个开关会通过 Audiotrack将当 前Iack纳入 AudioFlinger管理,其中的 mAudio trackThread是由构造函数构造时获得的 mAudio TrackThread的作用是用来获得 Audio的 event的数据的。其中还包含了一些线程的控 制参数。最终通过 m Audiotrack-> start0将 track纳入 audioflinger管理 void Audio Track: start( sp<AudioTrackThread>t= mAudio TrackThread LOGV("start %p",this) if(t!=0){ if(t->exteNding if (t->requestExitAndWait(== WOULD BLOCK)i LOGE("Audiotrack: start called from thread") return t->mLock lock(; if (android atomic or(l, &mActive)==0)f mNew Position mcblk->server mUpdate Period mcblk->bufferTimeoutMs= MAX STARTUP TIMEOUT MS mcblk->waitTimeMs =0 if(t!=0) t->run("AudioTrackThread", THREAD PRIORITY AUDIO CLIENT) f else setpriority (PRIO PROCESS, 0, THREAD PRIORITY AUDIO CLIENT) mAudio Track->start: if(t!=0){ t->mLock unlock(; Audio System. cpp维护着上层音频系统公共部分,比说说录音和放音都是有相同的 streamType设定,都是有相同的模式设定,以及音量设定,以及静音设定。其中最为关键 的是 get_audio_ flingero函数,因为他提供给同一层的 Audio track以及 Audiorecod提供 Iaudio Flinger接口。首先看下 Audiosystem类 在 Audiosystem中可以看到整个音频系统需要使用的参数,包括音频类型,输出模式 音频路由等信息,其中还包含一个私有数据 class audioFlingerClient class Audiosystem public: enum stream type i enum audio in acoustics I // routing helper functions static status t speakerphone(bool state) static status t isspeakerphoneOn(bool* state); static status t bluetooth Sco(bool state static status t is bluetoothscoon(boo* state) static void setErrorcallback(audio error callback cb) // helper function to obtain AudioFlinger service handle static const sp<IAudio Flinger>& get audio flinger( private class audioFlingerclient: public IBinder: Death Recipient, public BnAudioFlingerC lient ublic AudioFlingerclient(t static int getoutput(int stream Type); static sp< AudioFlingerClient> gAudio Flingerclient static sp< lAudioFlinger> gAudio Flinger; static audio error callback gAudioError Callback 再看看 get_audio_ flinger的实现,首先把锁锁上,,然后调用 gAudioflinger. get函数, gAudioFlinger是在 android命名空间中的变量, IaudioFlinger的含义与 audio track意义类 似,通过它可以获得 AudioFlinger的代理接口然后通过 binder机制调用到最后的实现函数 接下来,获得系统默认服务里的 mediaaudio flinger类,之后创建一个 gAudio Flingerclient 对象, interface cast本质上就是返回一个 bpiaudioFlinger。在这个 while循环中可以看出, Audio System会一直通过 binder监听 media audio_ flinger是否已经启动。 sp<lAudioFlinger> AudioSystem: gAudioFlinger; const sp<lAudioFlinger>& AudioSystem: get audio flinger( Mutex: Autolock I(gLock); (g AudioFlinger get()==0)( sp<SErvice Manager> sm= defaultservice Manager() sp<BInder> binder do i binder= sm->getservice(string 16("media audio flinger )) if (binder!= 0) break LOGW(Audio Flinger not published, waiting. " ) usleep(500000);∥0.55 I while(true) if (gAudio FlingerClient = NULL)t gAudio Flingerclient new AudioFlingerclient(; F else i if (gAudioErrorCallback)t gAudio ErrorCallback(NO ERROR) binder->linkToDeath(g Audio FlingerClient); gAudioFlinger interface cast<IAudioFlinger>(binder) gAudioFlinger->registerClient(g Audio FlingerClient return gAudioFlinger: AudioFlinger层 由上面分析可以看出来, media层会通过 AudioSystell中的 get_audio flingerO而调用到 laudioFlinger里的代码, laudioFlinger中的是 Audioflinger的代理接口类,在 laudioFlinger 中有个宏定义 IMPLEMENT META INTERFACE( AudioFlinger,…);由此可以知道, AudioFlinger. cpp是 IAudioFlinger类的实现 AudioFlinger是 Audio系统的中间层,它主要是为 Audio系统提供部分接口的功能,在 系统中起服务的功能。其代码路径在 frameworks,/ase/ libs/audioflinger文件夹下。 Audio Flinger的启动 在 main Mediaserver函数或者 system_init(运行于 Simulator上),会调用 AudioFlinger: instantiate函数以便将 AudioFlinger注册进入默认系统服务中去。在 addservice函数中, new Audioflinger实例化了 AudioFlinger void Audio Flinger: instantiate(i defaultservice Manager()->addservice String 16("media audio flinger ) new Audio Flinger() 1、 AudioFlinger的初始化过程 在开始的地方初始化了 BnAudioFlinger、 mAudiohardWare等参数,创建硬件接口,获 得硬件输岀,紧接着设定硬件输岀,为混音器建立线程,设定输岀路由,设定音量设定諍 音模式,这些设定参数都是 Audiosystem中获得的。在初始化的最后部分创建录音接口。 Audio Flinger: AudioFlinger() BnAudioFlinger (), mAudioHardware(0), mA2dpAudiolnterface(0), mA2dpEnabled(false), mNotify A2dp Change(false), hardware Status AUDIO HW IDLE mAudioHardware AudioHardwarelnterface: : create hArdware Status AUDIO HW INIT. if(mAudioHardware->initcheck(==No error)f / open 16-bit output stream for s/w mixer mhardwarestatUs= AUDIO HW OUTPUT OPEN status t status: Audiostreamout *hwoutput mAudioHardware->openOutputstrea m(Audio System: PCM 16 BIT,0,0, &status); mHardwarestatUs AUDIO HW IDLE. mHardwareMixerThread new MixerThread(this, hwOutput, A udio System: AUDIO OUTPUT_ HARDWARE); setRouting(AudioSystem: MODE NORMAL, AudioSystem: ROUTE SPEAKER, Audio System: ROUTE ALL); setMode(Audiosystem: MODE NORMAL) setMasterVolume(l Of); setMasterMute(false) ∥/ Start record thread mAudioRecord Thread new AudioRecord thread (mAudiohardware this); if(mAudioRecordThread =0)t mAudio Record Thread- >run ("Audio RecordThread", PRIORITY URGENT AUDI O); 1 else t LOGE("Couldn't even initialize the stubbed audio hardware! ") 2、 create Track函数 Media层的 Audio track会调用这里的 create Track函数,下面就分析下 create Track函数 的实现方法。它会创建一个在当前请求 create Track进程关联的 track,之后调用new TrackHandle对rack进行一次封装。将结果返回给调用它的函数( AudioTrack. cpp中) p<lAudiotrack> AudioFlinger: create Track( pid t pid It streamType uint32 t samplerate sp<MixerThread: Track> track sp<TrackHandle> trackHandle Mutex: Autolock I(mLock); client= cLients value For(pid ); *ifdef with a2dp if (isA2dpEnabled(&& AudioSystem: routed ToA2dpOutput(streamType))t track= mA2dpMixerThread->create Track I(client, streamType, sample Rate, format, channel Count, frame count, shared Buffer, &lStatus I else #endif track mHardware MixerThread->create Track I(client, stream Type ample Rate format, channelCount, frame Count, shared Buffer, &lstatus) trackHandle new TrackHandle(track) return trackHandle Audiorecord的实现方式和其类似,通过上述分析可以看出, Audiotrack以及 AudioFlinger都是对 Track实力进行操作, Audio通过 track实例开 start\stop write而 Audio flinger通过 track来实现对不同的 I track管理,并且包括调用混音器来混音。 完成上述操作后, Audio frack就可以对tack进行一系列的操作了。 open Record函数 上面简要分析 createTrack函数的实现,但是对于cblk分配管理没有详细的描述,在这 里将详细介绍这些结构是如何构造出来的,这种创建方法和 create Track是类似的。首先看 下 open Record函数,该函数会在 Audiorecord. cpp中set函数调用 首先检测录音的合法性,之后调用 new MixerThread: RecordTrack实例化一个 recordtrack对象,和 create track类似,最后通过 Recordhandle去为 Record做一次封装。 sp<lAudioRecord> audioFlinger: open Record( uint 32 t flags, status t *status if ( recordingAllowed()t StatUs= PERMISSION DENIED goto Exit recordtrack= new MixerThread:: record track(mHardwareMixerThread, cli ent, inputsource, sampleRate, format, channel Count, frame Count, flags if (record Track->getcblk(==NULL)t record Track. clear(; Status NO MEMorY. goto Exit l/ return to handle to client record Handle= new RecordHandle (record track); Status =NO errOR 可以看出 Mixerthread∷ Record track: Record Track实际上是初始化了 Trackbacks,所以真 正的工作是在 BackBase中完成的 AudioFlinger: MixerThread: Record Track: RecordTrack const sp<MixerThread>& mixerThread const sp<client>& client int inputSource, uint32 t sampleRate, int format int channelcount int frame Count uint32 t flags) 【实例截图】
【核心代码】

标签:

实例下载地址

android Audio ALSA框架分析

不能下载?内容有错? 点击这里报错 + 投诉 + 提问

好例子网口号:伸出你的我的手 — 分享

网友评论

发表评论

(您的评论需要经过审核才能显示)

查看所有0条评论>>

小贴士

感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。

  • 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
  • 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
  • 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
  • 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。

关于好例子网

本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明

;
报警