安卓音效AudioEffect源码剖析1——构造流程
来源:互联网 发布:到香港去网络要关闭吗 编辑:程序博客网 时间:2024/05/02 12:31
PresetReverb pReverb = new PresetReverb(100, 0);
让我们看看安卓做了什么?
Java层到audioflinger的调用流程:
audioflinger service到库的创建流程:
- 【Java层】调用了PresetReverb的构造函数。
- 【Java层】PresetReverb把构造功能甩给了基类AudioEffect——frameworks/base/media/java/android/media/audiofx/PresetReverb.java
- 【Java层】AudioEffect使用了JNI,并把构造工作抛给了native层的native_setup。——frameworks/base/media/java/android/media/audiofx/AudioEffect.java。
- 【JNI层】native_setup(android_media_AudioEffect_native_setup)中调用了AudioEffect(C++)的构造代码。——framework/base/media/jni/audioeffect/android_media_AudioEffect.cpp
- 【native层】AudioEffect(C++)的构造代码调用了set(),set()中进一步调用了audioFlinger->createEffect()来创建音效。——frameworks/av/media/libmedia/AudioEffect.cpp
- 【native层】audioFlinger的客户端服务端通信略。
- 【native层】audioFlinger service端调用thread->createEffect_l在对应的音频线程创建音效。——frameworks\av\services\audioflinger\AudioFlinger.cpp
- 【native层】createEffect_l中创建了效果链,并把new EffectModule(this, chain, desc, id, sessionId)加入效果链。——frameworks/av/services/audioflinger/Threads.cpp
- 【native层】EffectModule的构造函数中调用了EffectFactory的EffectCreate方法来创建音效实例。——frameworks/av/services/audioflinger/Effects.cpp
- 【native层】EffectCreate中枚举并创建了具体的效果类。
(2)【Java层】PresetReverb把构造功能甩给了基类AudioEffect——frameworks/base/media/java/android/media/audiofx/PresetReverb.java
PresetReverb.java的构造函数如下:public PresetReverb(int priority, int audioSession) throws IllegalArgumentException, UnsupportedOperationException, RuntimeException { super(EFFECT_TYPE_PRESET_REVERB, EFFECT_TYPE_NULL, priority, audioSession); }
public static final UUID EFFECT_TYPE_PRESET_REVERB = UUID .fromString("47382d60-ddd8-11db-bf3a-0002a5d5c51b");public static final UUID EFFECT_TYPE_NULL = UUID .fromString("ec7178ec-e5e1-4432-a3f4-4657e6795210");
(3)【Java层】AudioEffect使用了JNI,并把构造工作抛给了native层的native_setup。——frameworks/base/media/java/android/media/audiofx/AudioEffect.java。
public class AudioEffect { static { System.loadLibrary("audioeffect_jni"); native_init(); }…… public AudioEffect(UUID type, UUID uuid, int priority, int audioSession) throws IllegalArgumentException, UnsupportedOperationException, RuntimeException { int[] id = new int[1]; Descriptor[] desc = new Descriptor[1]; // native initialization int initResult = native_setup(new WeakReference<AudioEffect>(this), type.toString(), uuid.toString(), priority, audioSession, id, desc); ……
(4)【JNI层】native_setup(android_media_AudioEffect_native_setup)中调用了AudioEffect(C++)的构造代码。——framework/base/media/jni/audioeffect/android_media_AudioEffect.cpp
static jintandroid_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_this, jstring type, jstring uuid, jint priority, jint sessionId, jintArray jId, jobjectArray javadesc){ …… // create the native AudioEffect object lpAudioEffect = new AudioEffect(typeStr, uuidStr, priority, effectCallback, &lpJniStorage->mCallbackData, sessionId, 0);
(5)【native层】AudioEffect(C++)的构造代码调用了set(),set()中进一步调用了audioFlinger->createEffect()来创建音效。——frameworks/av/media/libmedia/AudioEffect.cpp
AudioEffect::AudioEffect(const effect_uuid_t *type, const effect_uuid_t *uuid, int32_t priority, effect_callback_t cbf, void* user, int sessionId, audio_io_handle_t io ) : mStatus(NO_INIT){ mStatus = set(type, uuid, priority, cbf, user, sessionId, io);}status_t AudioEffect::set(const effect_uuid_t *type, const effect_uuid_t *uuid, int32_t priority, effect_callback_t cbf, void* user, int sessionId, audio_io_handle_t io){ sp<IEffect> iEffect; sp<IMemory> cblk; int enabled; …… const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger(); if (audioFlinger == 0) { ALOGE("set(): Could not get audioflinger"); return NO_INIT; } if (type == NULL && uuid == NULL) { ALOGW("Must specify at least type or uuid"); return BAD_VALUE; } mPriority = priority; mCbf = cbf; mUserData = user; mSessionId = sessionId; memset(&mDescriptor, 0, sizeof(effect_descriptor_t)); mDescriptor.type = *(type != NULL ? type : EFFECT_UUID_NULL); mDescriptor.uuid = *(uuid != NULL ? uuid : EFFECT_UUID_NULL); mIEffectClient = new EffectClient(this); //利用audioFlinger创建音效 iEffect = audioFlinger->createEffect((effect_descriptor_t *)&mDescriptor, mIEffectClient, priority, io, mSessionId, &mStatus, &mId, &enabled); ……}
流程正式和AudioFlinger挂钩,并将创建特效的职责转给AudioFlinger,应用层作为一个客户端(Binder)。
Binder通信相关的流程略。
(7)【native层】audioFlinger service端调用thread->createEffect_l在对应的音频线程创建音效。——frameworks\av\services\audioflinger\AudioFlinger.cpp
sp<IEffect> AudioFlinger::createEffect( effect_descriptor_t *pDesc, const sp<IEffectClient>& effectClient, int32_t priority, audio_io_handle_t io, int sessionId, status_t *status, int *id, int *enabled){ status_t lStatus = NO_ERROR; sp<EffectHandle> handle; effect_descriptor_t desc; …… ThreadBase *thread = checkRecordThread_l(io); if (thread == NULL) { thread = checkPlaybackThread_l(io); if (thread == NULL) { ALOGE("createEffect() unknown output thread"); lStatus = BAD_VALUE; goto Exit; } } sp<Client> client = registerPid_l(pid); // create effect on selected output thread(音效是在线程上的) handle = thread->createEffect_l(client, effectClient, priority, sessionId, &desc, enabled, &lStatus); if (handle != 0 && id != NULL) { *id = handle->id(); } }……}
(8)【native层】createEffect_l中创建了效果链,并把new EffectModule(this,chain, desc, id, sessionId)加入效果链。——frameworks/av/services/audioflinger/Threads.cpp
sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l( const sp<AudioFlinger::Client>& client, const sp<IEffectClient>& effectClient, int32_t priority, int sessionId, effect_descriptor_t *desc, int *enabled, status_t *status ){ sp<EffectModule> effect; sp<EffectHandle> handle; status_t lStatus; sp<EffectChain> chain; bool chainCreated = false; bool effectCreated = false; bool effectRegistered = false; …… { // scope for mLock Mutex::Autolock _l(mLock); // 获取效果链 // check for existing effect chain with the requested audio session chain = getEffectChain_l(sessionId); if (chain == 0) { // create a new chain for this session ALOGV("createEffect_l() new effect chain for session %d", sessionId); chain = new EffectChain(this, sessionId); addEffectChain_l(chain); chain->setStrategy(getStrategyForSession_l(sessionId)); chainCreated = true; } else { effect = chain->getEffectFromDesc_l(desc); } if (effect == 0) { int id = mAudioFlinger->nextUniqueId(); // Check CPU and memory usage lStatus = AudioSystem::registerEffect(desc, mId, chain->strategy(), sessionId, id); if (lStatus != NO_ERROR) { goto Exit; } effectRegistered = true; // 创建效果模块 // create a new effect module if none present in the chain effect = new EffectModule(this, chain, desc, id, sessionId); lStatus = effect->status(); if (lStatus != NO_ERROR) { goto Exit; } effect->setOffloaded(mType == OFFLOAD, mId); lStatus = chain->addEffect_l(effect); if (lStatus != NO_ERROR) { goto Exit; } effectCreated = true; effect->setDevice(mOutDevice); effect->setDevice(mInDevice); effect->setMode(mAudioFlinger->getMode()); effect->setAudioSource(mAudioSource); } // create effect handle and connect it to effect module handle = new EffectHandle(effect, client, effectClient, priority); lStatus = effect->addHandle(handle.get()); if (enabled != NULL) { *enabled = (int)effect->isEnabled(); } }……}
(9)【native层】EffectModule的构造函数中调用了EffectFactory的EffectCreate方法来创建音效实例。——frameworks/av/services/audioflinger/Effects.cpp
AudioFlinger::EffectModule::EffectModule(ThreadBase *thread, const wp<AudioFlinger::EffectChain>& chain, effect_descriptor_t *desc, int id, int sessionId) : mPinned(sessionId > AUDIO_SESSION_OUTPUT_MIX), mThread(thread), mChain(chain), mId(id), mSessionId(sessionId), mDescriptor(*desc), // mConfig is set by configure() and not used before then mEffectInterface(NULL), mStatus(NO_INIT), mState(IDLE), // mMaxDisableWaitCnt is set by configure() and not used before then // mDisableWaitCnt is set by process() and updateState() and not used before then mSuspended(false){ ALOGV("Constructor %p", this); int lStatus; // create effect engine from effect factory mStatus = EffectCreate(&desc->uuid, sessionId, thread->id(), &mEffectInterface); ……}
看到使用特效工厂创建,已经很近了。
(10)【native层】EffectCreate中枚举并创建了具体的效果类。
int EffectCreate(const effect_uuid_t *uuid, int32_t sessionId, int32_t ioId, effect_handle_t *pHandle){ list_elem_t *e = gLibraryList; lib_entry_t *l = NULL; effect_descriptor_t *d = NULL; effect_handle_t itfe; effect_entry_t *fx; int found = 0; int ret;…… ret = init(); if (ret < 0) { ALOGW("EffectCreate() init error: %d", ret); return ret; } pthread_mutex_lock(&gLibLock); ret = findEffect(NULL, uuid, &l, &d); if (ret < 0){ // Sub effects are not associated with the library->effects, // so, findEffect will fail. Search for the effect in gSubEffectList. ret = findSubEffect(uuid, &l, &d); if (ret < 0 ) { goto exit; } } // create effect in library ret = l->desc->create_effect(uuid, sessionId, ioId, &itfe); if (ret != 0) { ALOGW("EffectCreate() library %s: could not create fx %s, error %d", l->name, d->name, ret); goto exit; } ……}
init()从/system/etc/audio_effects.conf配置文件中初始化特效。
audio_effects.conf的结构如下:
libraries {
...
downmix {
path /system/lib/soundfx/libdownmix.so
}
}
effects {
...
downmix {
library downmix
uuid 93f04452-e4fe-41cc-91f9-e475b6d1d69f
}
}
libraries指明了库的加载路径,默认是在/system/lib/soundfx/目录下。
effects包含了该系统支持的所有音效,音效所使用的库,以及音效的uuid。
有了这些信息,就可以创建音效实例了。
创建方法为ret =l->desc->create_effect(uuid, sessionId, ioId, &itfe);
注意:此处的itfe就是创造出来的音效实例。
- 安卓音效AudioEffect源码剖析1——构造流程
- 安卓音效AudioEffect源码剖析2——音效库接口
- AudioEffect构造流程跟踪 & 音效库实现(native侧)
- 源码篇——安卓启动流程
- 下载安卓源码流程
- Android源码分析:AudioEffect
- AudioEffect源码解析
- Android源码分析:AudioEffect
- Android源码分析:AudioEffect
- Android源码分析:AudioEffect
- 【安卓笔记】HandlerThread源码剖析
- 【安卓笔记】IntentService源码剖析
- 【安卓笔记】AsyncQueryHandler源码剖析
- 【安卓笔记】AsyncTask源码剖析
- 【安卓笔记】IntentService源码剖析
- Camera安卓源码剖析-源码中的设计模式实例
- Camera安卓源码剖析-源码中的线程沟通实例
- 安卓View的加载流程详细剖析
- Server.Transfer和Response.Redirect
- (小笔记)(sql)left join
- <s:date>使用nice 属性 实现 ‘XX分钟前’ 日期显示
- 我想要你为我披上白色的婚纱
- Information About OSPF Incremental SPF
- 安卓音效AudioEffect源码剖析1——构造流程
- 淘宝接口基础调用方法-查询商品-php
- 利用ant将Web项目部署至远程Tomcat
- 赴美参加学术会议办理签证流程
- Androi之Canvas drawText
- [2012-05-10 09:52:11 - xxx] Failed to install xxx.apk on device '100046a35a59': timeout
- SQL 嵌套查询 ---比较 很有用
- POJ 1511 Invitation Cards
- C++中数组的声明与赋值