当前位置:操作系统 > 安卓/Android >>

Android Audio代码分析5 - 函数getAudioSessionId

 

在我们学习AudioTrack对象的创建过程时,了解到,创建一个AudioTrack对象,必须指定一个SessionId,并与其他使用该SessionId的AudioTrack和MediaPlayer共享AudioEffect。

如果不指定SessionId,将会自动生成一个SessionId,AudioEffect会将该SessionId与新创建的AudioTrack对象关联起来。

别人可以通过getAudioSessionId函数取得该SessionId。

今天我们就看看getAudioSessionId函数。

 

在frameworks的代码中搜了一下,发现有两个地方实现了该函数,分别来说一下。

 

先说说在类MediaPlayer中的实现。

*****************************************源码*************************************************

int MediaPlayer::getAudioSessionId()

{

    Mutex::Autolock _l(mLock);

    return mAudioSessionId;

}

**********************************************************************************************

源码路径:

frameworks\base\media\libmedia\mediaplayer.cpp

 

###########################################说明################################################

代码很简单,只是将成员变量返回,没啥好说的。

那我们看看该成员变量是何时被赋值的。

 

找了下代码,发现有两个地方对该成员变量进行了赋值。

 

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

一个在构造函数中。

MediaPlayer::MediaPlayer()

{

    LOGV("constructor");

    mListener = NULL;

    mCookie = NULL;

    mDuration = -1;

    mStreamType = AudioSystem::MUSIC;

    mCurrentPosition = -1;

    mSeekPosition = -1;

    mCurrentState = MEDIA_PLAYER_IDLE;

    mPrepareSync = false;

    mPrepareStatus = NO_ERROR;

    mLoop = false;

    mLeftVolume = mRightVolume = 1.0;

    mVideoWidth = mVideoHeight = 0;

    mLockThreadId = 0;

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

int AudioSystem::newAudioSessionId() {

    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();

    if (af == 0) return 0;

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

int AudioFlinger::newAudioSessionId()

{

// 看到了函数nextUniqueId,我们感觉到有点熟悉。

// 不错,在我们看函数AudioSystem::getOutputSamplingRate的时候,看到,在函数AudioFlinger::openOutput中有调过函数nextUniqueId

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

int AudioFlinger::nextUniqueId()

{

// 这是一个自增的操作

// 可见,SessionId最终是在AudioFlinger中维护的。

// 关于函数android_atomic_inc,可参考以下链接:

// http://www.zzzyk.com/kf/201110/106982.html

    return android_atomic_inc(&mNextUniqueId);

}

----------------------------------------------------------------

    return nextUniqueId();

}

----------------------------------------------------------------

    return af->newAudioSessionId();

}

----------------------------------------------------------------

    mAudioSessionId = AudioSystem::newAudioSessionId();

    mSendLevel = 0;

}

----------------------------------------------------------------

 

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

另一个给成员变量mAudioSessionId赋值的地方是在函数MediaPlayer::setAudioSessionId中。

status_t MediaPlayer::setAudioSessionId(int sessionId)

{

    LOGV("MediaPlayer::setAudioSessionId(%d)", sessionId);

    Mutex::Autolock _l(mLock);

    if (!(mCurrentState & MEDIA_PLAYER_IDLE)) {

        LOGE("setAudioSessionId called in state %d", mCurrentState);

        return INVALID_OPERATION;

    }

    if (sessionId < 0) {

        return BAD_VALUE;

    }

    mAudioSessionId = sessionId;

    return NO_ERROR;

}

 

函数MediaPlayer::setAudioSessionId在函数android_media_MediaPlayer_set_audio_session_id中被调用。

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

static void android_media_MediaPlayer_set_audio_session_id(JNIEnv *env,  jobject thiz, jint sessionId) {

    LOGV("set_session_id(): %d", sessionId);

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

static sp<MediaPlayer> getMediaPlayer(JNIEnv* env, jobject thiz)

{

    Mutex::Autolock l(sLock);

    MediaPlayer* const p = (MediaPlayer*)env->GetIntField(thiz, fields.context);

    return sp<MediaPlayer>(p);

}

以前见到过类似的函数,肯定有某个地方把它set进去。

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

static sp<MediaPlayer> setMediaPlayer(JNIEnv* env, jobject thiz, const sp<MediaPlayer>& player)

{

    Mutex::Autolock l(sLock);

    sp<MediaPlayer> old = (MediaPlayer*)env->GetIntField(thiz, fields.context);

    if (player.get()) {

        player->incStrong(thiz);

    }

    if (old != 0) {

        old->decStrong(thiz);

    }

    env->SetIntField(thiz, fields.context, (int)player.get());

    return old;

}

函数setMediaPlayer在函数android_media_MediaPlayer_native_setup中被调用。

函数android_media_MediaPlayer_native_setup也是供java调用的。

对应的接口,在下面的一个列表中可以看到。

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

static void

android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)

{

    LOGV("native_setup");

 // 在上面的代码中,SessionId的一个赋值的地方就是MediaPlayer的构造函数中。

 // MediaPlayer对象就是在这儿被构造的。

    sp<MediaPlayer> mp = new MediaPlayer();

    if (mp == NULL) {

        jniThrowException(env, "java/lang/RuntimeException", "Out of memory");

        return;

    }

 

    // create new listener and give it to MediaPlayer

 // JNIMediaPlayerListener是一个代码量不多的类,其声明和实现如下:

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// ref-counted object for callbacks

class JNIMediaPlayerListener: public MediaPlayerListener

{

public:

    JNIMediaPlayerListener(JNIEnv* env, jobject thiz, jobject weak_thiz);

    ~JNIMediaPlayerListener();

    void notify(int msg, int

补充:移动开发 , Android ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,