安卓音效AudioEffect源码剖析1

当我们写下demo代码:

PresetReverb pReverb = new PresetReverb(100, 0);

让我们看看安卓做了什么?

Java层到audioflinger的调用流程:

audioflinger service到库的创建流程:

【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

(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);}

可见子类的构造函数没做什么事情,只是加了子类的UUID后,调用了基类的构造函数。其中EFFECT_TYPE_PRESET_REVERB和EFFECT_TYPE_NULL的定义在frameworks/base/media/java/android/media/audiofx/AudioEffect.java

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");

【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 initializationint initResult = native_setup(new WeakReference<AudioEffect>(this),type.toString(), uuid.toString(), priority, audioSession, id,desc);……

【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 objectlpAudioEffect = new AudioEffect(typeStr,uuidStr,priority,effectCallback,&lpJniStorage->mCallbackData,sessionId,0);

【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通信相关的流程略。

【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();}}……}可以提高你的水平。(戏从对手来。

安卓音效AudioEffect源码剖析1

相关文章:

你感兴趣的文章:

标签云: