音频流分析一

音频流分析一,第1张

目录

1 APP层

2 JAVA框架层

1.计算满足最小要求的缓冲区大小

2. 分析new AudioTrack

3.分析start函数

4.分析write函数

3 Audio本地API--JNI层

4 c/c++框架层

1 APP层

所涉及的代码路径:

录音APK:\packages\apps\SoundRecorder\src\com\android\soundrecorder\*.*

播放APK:\packages\apps\Music\src\com\android\music\*.*

电话APK:\packages\apps\Phone\src\com\android\phone\*.*

所涉及的主要代码:

录音APK:SoundRecorder.java

播放APK:MediaPlaybackService.java

电话APK:PhoneApp.java

APP应用层简略实例一:

        我们使用audiotrack audiorecord 来播放和记录声音。

public class TestAudio extends Activity implements OnClickListener{

    private AudioRecord m_in_rec;
    private AudioTrack m_out_trk;
    protected void onCreate(Bundle savedInstanceState) {
      init();
      record  =  new Thread(new recordSound());
      play    =  new Thread(new playRecord());
      record.start();
      play.start();}
    private void init(){   
  	m_in_buf_size=AudioRecord.getMinBufferSize(
        8000,AudioFormat.CHANNEL_CONFIGURATION_MONO,AudioFormat.ENCODING_PCM_16BIT);
    m_in_rec = new AudioRecord(
        MediaRecorder.AudioSource.MIC,8000,AudioFormat.CHANNEL_CONFIGURATION_MONO,                       
        AudioFormat.ENCODING_PCM_16BIT,m_in_buf_size) ;
   	m_out_buf_size = AudioTrack.getMinBufferSize(
        8000,AudioFormat.CHANNEL_CONFIGURATION_MONO,
        AudioFormat.ENCODING_PCM_16BIT);
	m_out_trk = new AudioTrack(
        AudioManager.STREAM_MUSIC, 8000,AudioFormat.CHANNEL_CONFIGURATION_MONO

}

APP层应用简略实例二:

        应用程序通过调用Audio的JAVA层透露给上层的部分接口:setDataSource(),prepare(),start()等来实现MP3的播放。

public void onStart(Intent intent, int startId) {    
super.onStart(intent, startId);    
             
         // 得到从activity传来的歌曲URI    
         String uri = intent.getStringExtra("data");    
         player = new MediaPlayer();    
         try {    
             player.setDataSource(uri);    
             player.prepare();    
         } catch (IllegalArgumentException e) {    
             // TODO Auto-generated catch block    
             e.printStackTrace();    
         } catch (IllegalStateException e) {    
             // TODO Auto-generated catch block    
             e.printStackTrace();    
         } catch (IOException e) {    
             // TODO Auto-generated catch block    
             e.printStackTrace();    
         }    
         player.start();    
     }
2 JAVA框架层

所涉及的代码路径:

\frameworks\base\media\java\android\media\*.*

所涉及的主要代码:

MediaPlayer.java

MediaRecorder.java

AudioRecord.java

AudioTrack.java

AudioSystem.java

AudioService.java

AudioManager.java

代码路径: \frameworks\base\media\java\android\media

图表 3 Audio JAVA层框架图

与Audio相关的Java包是android.media,主要包含文件:

    AudioManager.java:主要负责Audio系统的管理,向下会调用AudioService.java

    AudioService.java:主要负责Audio系统的相关服务,向下会调用AudioSystem.java

    AudioSystem.java:主要负责Audio系统的总体控制

    AudioTrack.java:主要负责Audio系统的输出环节

    AudioRecord.java:主要负责Audio系统的输入环节

1.计算满足最小要求的缓冲区大小
getMinBufferSize(audiotrack.java)
=>native_get_min_buff_size(audiotrack.java)
    =>android_media_AudioTrack_get_min_buff_size(android_media_audiotrack.cpp)
	    =>getMinFrameCount(audiotrack.cpp)
2. 分析new AudioTrack
AudioTrack(audiotrack.java)
=> native_setup(audiotrack.java)
	=>android_media_AudioTrack_native_setup(android_media_audiotrack.cpp)
		=> new AudioTrack()(android_media_audiotrack.cpp)
			=>set(audiotrack.cpp)
				=>createTrack(audiotrack.cpp)
					=>audioFlinger->createTrack(audiotrack.cpp)
						=> createTrack(audioflinger.cpp)
				=> new AudioTrackThread(audiotrack.cpp)
					=>AudioTrackThread(audiotrack.cpp)
					=>start()(audiotrack.cpp)
					=>threadLoop()(audiotrack.cpp)
						=>processAudioBuffer(audiotrack.cpp)
							=>mCbf(audiotrack.cpp)
								=>audioCallback(android_media_audiotrack.cpp)

3.分析start函数
play(audiotrack.java)
=>native_start(audiotrack.java)
=>android_media_AudioTrack_start(android_media_audiotrack.cpp)
	=>start(audiotrack.cpp)

4.分析write函数
write(audiotrack.java)
=>native_write_short(audiotrack.java)
=>android_media_AudioTrack_native_write_short(android_media_audiotrack.cpp)
	=>android_media_AudioTrack_native_write(android_media_audiotrack.cpp)
	=>writeToTrack(android_media_audiotrack.cpp)
        =>write(audiotrack.cpp)
        =>obtainBuffer(audiotrack.cpp)
        =>releaseBuffer(audiotrack.cpp)

        通过这一次的分析,我自己觉得有AudioTrack的工作原理,尤其是数据的共享内存,进程的同步等,也能解释不少疑惑了。看起来,最重要的工作是在AudioFlinger中做的。通过给后续深入分析AudioFlinger提供了一个切入点流程嘛,再说一次好了,JAVA层就看最前面那个AudioTrack被new出来,然后set了一堆信息,同时会通过Binder机制调用另外一端的AudioFlinger,得到IAudioTrack对象,通过它和AudioFlinger交互。调用start函数后,会启动一个线程专门做回调处理,代码里边也会有那种数据贝的回调,但是JNI层的回调函数实际并没有往里边写数据,大家只要看write就可以了用户一次可想而知,AudioFlinger那一定有一个线程在memcpy数据到音频设备中去。我们拭目以待。

3 Audio本地API--JNI层

所涉及的代码路径:

\frameworks\base\media\jni\*.*

\frameworks\base\core\jni\*.*

所涉及的主要代码:

android_media_MediaPlayer.cpp

android_media_MediaRecorder.cpp

android_media_AudioRecord.cpp

android_media_AudioTrack.cpp

android_media_AudioSystem.cpp

4 c/c++框架层

在文件AudioTrack.java中new AudioTrack()

=>在文件android_media_audioTrack.cpp中调用android_media_AudioTrack_native_setup

=>在文件AudioTrack.cpp中调用set函数中存在mAudioTrackThread = new AudioTrackThread

然后分析如何启动AudioTrackThread线程

=>分析AudioTrack.cpp中的AudioTrack::start()函数会调用mAudioTrack->start()

=>实际上会调用AudioTrack.cpp中AudioFlinger::TrackHandle::start()

=>AudioTrack.cpp中的AudioFlinger::TrackHandle::start()实际上会调用mTrack->start()

=>然后会调用AudioFlinger.cpp中的AudioFlinger::PlaybackThread::Track::start()函数

=>然后分析AudioFlinger::ThreadBase::TrackBase,因为Track继承自TrackBase

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/876755.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存