没有合适的资源?快使用搜索试试~ 我知道了~
首页android Audio ALSA框架分析
从框图中可以看出 android 对于 java 层一共提供 3 个接口,分别 MedialPlayer、MediaREcorder 以及 AudioServier,通过 JNI 则调用到 AudioTrack(放 AudioRecord(录音)以及(AudioSystem)主要音频参数设定。通过 Android Binder 机 AudioFlinger 层相同步,之后调用到 AudioHardware ,其中提供的接口主要 AudioStreamOut以及AudioStreamin。最终将进入Linux内核调用到ALSA。
资源详情
资源评论
资源推荐

Android Audio
框架分析
Android Audio
框架分析
.................................................................................................................1
Andrioid
系统框架图
..........................................................................................................................2
Audio JNI
层接口
...............................................................................................................................2
Media
库中的
Audio
框架部分
..........................................................................................................4
AudioFlinger
层
...................................................................................................................................7
AudioFlinger
的启动
..................................................................................................................8
1
、
AudioFlinger
的初始化过程
................................................................................................8
2
、
createTrack
函数
...................................................................................................................9
openRecord
函数
.......................................................................................................................10
AudioFlinger
对放音的管理
...................................................................................................12
3
、
AudioFlinger
对录音的管理
..............................................................................................14
AudioFlinger
以及
Media
层放音录音小结
............................................................................18
Audio
硬件抽象层实现
....................................................................................................................22
Linux
内核
ALSA
模块分析
............................................................................................................24
STE
声卡驱动底层相关操作
...........................................................................................................41

Andrioid
系统框架图
从 框 图 中 可 以 看 出
android
对 于
java
层 一 共 提 供
3
个 接 口 , 分 别 是
MedialPlayer
、
MediaREcorder
以及
AudioServier
,通过
JNI
则调用到
AudioTrack
(放音),
AudioRecord(
录音
)
以及(
AudioSystem
)主要音频参数设定。通过
Android Binder
机制与
AudioFlinger
层 相 同 步 , 之 后 调 用 到
AudioHardware
, 其 中 提 供 的 接 口 主 要 是
AudioStreamOut
以及
AudioStreamin
。最终将进入
Linux
内核调用到
ALSA
。
Audio JNI
层接口
Audio
在
JNI
层 的 接 口 主 要 有
AudioTrack
,
AudioRecorder
,
AudioSystem
来 提 供 ,
AudioTrack
主要实现声音的播放功能,
AudioRecorder
主要实现录音功能,
AudioSystem
主
要为声音系统提供必要的支持函数。所以首先先分析下以
AudioTrack
为例子,分析
Audio
对
jni
所提供的接口。通过
JNI
,可以调用到
AuidoTrack
所提供的函数,例如,当上层调用
native_start
的时候,便会调用函数
android_media_AudioTrack_start,其中的函数 start()
函数在 AudioTrack 中实现,所以通过 android_media_AudioTrack.cpp,jni 的 start 调用
将进入 AudioTrack 中,通过 start()函数的分析,可知,jni 调用的其他函数的传递方式和其
类似,所以不再分析。
static void

android_media_AudioTrack_start(JNIEnv *env, jobject thiz)
{
AudioTrack *lpTrack = (AudioTrack *)env->GetIntField(
thiz, javaAudioTrackFields.nativeTrackInJavaObj);
if (lpTrack == NULL ) {
jniThrowException(env, "java/lang/IllegalStateException",
"Unable to retrieve AudioTrack pointer for start()");
}
lpTrack->start();
}
文件的
android_media_AudioTrack_native_setup
函数中,有对声音系统的一系列初始化
操作,例如设定采样率、格式,通道数等等,在设定好这些数据后,调用
lpTrack = new
AudioTrack()
完成
AudioTrack
实例化,紧接着调用
lpTrack->set()
“完成刚才一系列参数的 写
”入 工作。
AudioTrack* lpTrack = new AudioTrack();
if (lpTrack == NULL) {
LOGE("Error creating uninitialized AudioTrack");
goto native_track_failure;
}
// initialize the native AudioTrack object
if (memoryMode == javaAudioTrackFields.MODE_STREAM) {
lpTrack->set(
atStreamType,// stream type
sampleRateInHertz,
format,// word length, PCM
nbChannels,
frameCount,
0,// flags
audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data
(user)
0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed th
e AudioTrack
0,// shared mem
true);// thread can call Java
}

Media
库中的
Audio
框架部分
AudioTrack.cpp
中的代码主要是给
jni
层
android_media_AudioTrack
提供接口。在该文
件中有
AudioTrack
类中函数的实现方法。其中某些函数将会调用
AudioSystem
中的部分函
数。在
AudioTrack.cpp
与
AudioRecord.cpp
文件中,最关键的是
write
函数和
read
函数,因
为 这 是 录 音 和 放 音 的 数 据 传 递 函 数 , 因 为 和
AudioFlinger
层 关 系 密 切 , 所 以 放 在
AudioFlinger
的录音管理和放音管理中详细描述。
AudioTrack
类的构造函数只实现一个功能,便是设定声音系统的各种参数,这些参数
是由
set()
来设定的,该调用时在
jni
层完成的。下面就首先分析
set()
函数。
首先我们要确定
AudioTrack
类中的
mAudioTrack
没有被使用。否则的话将出错。然后
通过
AudioSystem
中的
get_audio_flinger
函数获得。通过这个函数就可以获得
IAudioflinger
实例化的对象。这个
IAudioFlinger
就是一个
binder
的代理接口。至于
binder
的实现,不再
Audio
的讨论范围。接下来是一系列参数的设定。首先根据传递进来的
streamType
来获得
当前的部分参数,然后根据条件进行部分参数的设定。例如如果
sampleRate
没有设定,则
—设定采样率为当前值。当这些临时变量设定好后,到了最关键的部分
createtrack()
通过这
个函数的返回,获得了一个
IAudioTrack
对象,这个对象控制着整个音频系统的录音功能。
整个
AudioTrack
的音频控制功能都是通过它完成的。这里可以把
IaudioTrack
理解成是一个
接口类,所有的工作都是通过它来和
binder
来完成通信。在初始化的最后完成
AudioTrack
内其他成员函数的初始化。
status_t AudioTrack::set(
void* user,
int notificationFrames,
const sp<IMemory>& sharedBuffer,
bool threadCanCallJava)
{
if (mAudioTrack != 0) {
LOGE("Track already in use");
return INVALID_OPERATION;
}
const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flin
ger();
int afSampleRate;
if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_E
RROR) {
return NO_INIT;
}
if (channelCount == 0) {
channelCount = 2;
}
status_t status;
sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),

streamType, sampleRate, format, channelCount, frameCount, fl
ags, sharedBuffer, &status);
sp<IMemory> cblk = track->getCblk();
if (cblk == 0) {
LOGE("Could not get control block");
return NO_INIT;
}
mAudioTrack = 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 AudioFlinger during track cre
ation
mFrameCount = mCblk->frameCount;
mCblk->volume[0] = mCblk->volume[1] = 0x1000;
mVolume[LEFT] = 1.0f;
return NO_ERROR;
}
Start
函数是
jni
层将要调用的函数,这个函数实际上是一个开关 会通过
IaudioTrack
将当
前
Track
纳入
AudioFlinger
管理,其中的
mAudioTrackThread
是由构造函数构造时获得的,
mAudioTrackThread
的作用是用来获得
Audio
的
event
的数据的。其中还包含了一些线程的控
制参数。最终通过
mAudioTrack->start()
将
track
纳入
audioflinger
管理。
void AudioTrack::start()
{
sp<AudioTrackThread> t = mAudioTrackThread;
LOGV("start %p", this);
if (t != 0) {
if (t->exitPending()) {
if (t->requestExitAndWait() == WOULD_BLOCK) {
LOGE("AudioTrack::start called from thread");
return;
}
}
t->mLock.lock();
}
if (android_atomic_or(1, &mActive) == 0) {
mNewPosition = mCblk->server + mUpdatePeriod;
mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
mCblk->waitTimeMs = 0;
if (t != 0) {
t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT);
} else {
setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
}
剩余43页未读,继续阅读





安全验证
文档复制为VIP权益,开通VIP直接复制

评论13