Android N Audio: AudioTrack 向上通知的路径

在前面介绍创建AudioTrack的native实例后,会调用set,这里就在搭建进行native AudioTrack和java层进行通信的桥梁audioCallback,

android_media_AudioTrack.cpp

 

        lpTrack = new AudioTrack();

 

        case MODE_STREAM:

 

            status = lpTrack->set(

                    AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)

                    sampleRateInHertz,

                    format,// word length, PCM

                    nativeChannelMask,

                    frameCount,

                    AUDIO_OUTPUT_FLAG_NONE,

                    audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)

                    0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack

                    0,// shared mem

                    true,// thread can call Java

                    sessionId,// audio session ID

                    AudioTrack::TRANSFER_SYNC,

                    NULL,                         // default offloadInfo

                    -1, -1,                       // default uid, pid values

                    paa);

 

 

 

1)先向下看

在AudioTrack里,cb被赋值给mCbf,并在set里根据cbf创建了一个AudioTrackThread线程,

status_t AudioTrack::set(

        audio_stream_type_t streamType,

        uint32_t sampleRate,

        audio_format_t format,

        audio_channel_mask_t channelMask,

        size_t frameCount,

        audio_output_flags_t flags,

        callback_t cbf,

        void* user,

{

    mCbf = cbf;

 

    if (cbf != NULL) {

        mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava);

        mAudioTrackThread->run("AudioTrack", ANDROID_PRIORITY_AUDIO, 0 /*stack*/);

        // thread begins in paused state, and will not reference us until start()

}

}

 

 

AudioTrackThread线程的threadLoop的调用AudioTrack自身处理音频缓冲,

AudioTrack::AudioTrackThread::AudioTrackThread(AudioTrack& receiver, bool bCanCallJava)

    : Thread(bCanCallJava), mReceiver(receiver), mPaused(true), mPausedInt(false), mPausedNs(0LL),

      mIgnoreNextPausedInt(false)

{

}

 

bool AudioTrack::AudioTrackThread::threadLoop()

{

nsecs_t ns = mReceiver.processAudioBuffer();

}

 

 

mCbf即audioCallback被调用,开始向上传递事件和数据,

nsecs_t AudioTrack::processAudioBuffer()

{

                mCbf(EVENT_STREAM_END, mUserData, NULL);

}

 

 

2)再向上看,

 

android_media_AudioTrack.cpp里,通过虚拟机调用和javaAudioTrackFields.postNativeEventInJava对应的java层函数,

static void audioCallback(int event, void* user, void *info) {

 

    case AudioTrack::EVENT_NEW_POS: {

        JNIEnv *env = AndroidRuntime::getJNIEnv();

        if (user != NULL && env != NULL) {

            env->CallStaticVoidMethod(

                callbackInfo->audioTrack_class,

                javaAudioTrackFields.postNativeEventInJava,

                callbackInfo->audioTrack_ref, event, 0,0, NULL);

            if (env->ExceptionCheck()) {

                env->ExceptionDescribe();

                env->ExceptionClear();

            }

        }

        } break;

    }

 

 

javaAudioTrackFields.postNativeEventInJava初始的地方如下,即对应java的postEventFromNative,

#define JAVA_POSTEVENT_CALLBACK_NAME                    "postEventFromNative"

 

int register_android_media_AudioTrack(JNIEnv *env)

{

 

    javaAudioTrackFields.postNativeEventInJava = NULL;

 

    // Get the AudioTrack class

    jclass audioTrackClass = FindClassOrDie(env, kClassPathName);

 

    // Get the postEvent method

    javaAudioTrackFields.postNativeEventInJava = GetStaticMethodIDOrDie(env,

            audioTrackClass, JAVA_POSTEVENT_CALLBACK_NAME,

            "(Ljava/lang/Object;IIILjava/lang/Object;)V");

    }

 

 

在java层,通过handler转发事件,将事件通知给应用。 这其中又涉及到应用向java层注册监听器等操作,这个过程比较简单易懂,贴上代码示例。

    private static void postEventFromNative(Object audiotrack_ref,

            int what, int arg1, int arg2, Object obj) {

        //logd("Event posted from the native side: event="+ what + " args="+ arg1+" "+arg2);

        AudioTrack track = (AudioTrack)((WeakReference)audiotrack_ref).get();

        if (track == null) {

            return;

        }

 

        if (what == AudioSystem.NATIVE_EVENT_ROUTING_CHANGE) {

            track.broadcastRoutingChange();

            return;

        }

        NativePositionEventHandlerDelegate delegate = track.mEventHandlerDelegate;

        if (delegate != null) {

            Handler handler = delegate.getHandler();

            if (handler != null) {

                Message m = handler.obtainMessage(what, arg1, arg2, obj);

                handler.sendMessage(m);

            }

        }

    }

 

 

    private class NativePositionEventHandlerDelegate {

        private final Handler mHandler;

 

        NativePositionEventHandlerDelegate(final AudioTrack track,

                                   final OnPlaybackPositionUpdateListener listener,

                                   Handler handler) {

                mHandler = new Handler(looper) {

                    @Override

                    public void handleMessage(Message msg) {

                        if (track == null) {

                            return;

                        }

                        switch(msg.what) {

                        case NATIVE_EVENT_MARKER:

                            if (listener != null) {

                                listener.onMarkerReached(track);

                            }

                            break;

                        case NATIVE_EVENT_NEW_POS:

                            if (listener != null) {

                                listener.onPeriodicNotification(track);

                            }

                            break;

    }

 

 

    public void setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener listener,

                                                    Handler handler) {

        if (listener != null) {

            mEventHandlerDelegate = new NativePositionEventHandlerDelegate(this, listener, handler);

        } else {

            mEventHandlerDelegate = null;

        }

    }

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值