Android N Audio播放三:prepare大揭秘

本文详细探讨了Android N中音频播放的prepare过程,从Client端到Service端,涉及MediaPlayerService、NuplayerDriver、Nuplayer和GenericSource。重点在于prepare在各个组件中的操作,包括状态管理、数据源构建、Extractor生成以及Flag的更新,为理解音频播放准备阶段的内部机制提供了清晰的路径。
摘要由CSDN通过智能技术生成

  这一节我们来看看在Android N Audio播放一:如何播放一首音乐中介绍的播放音乐的第二步:
  

player.prepare();

  同样,我们在MusicDemo中将start方法注释掉。这样可以看得更清楚。
  

    private void play(){
        try {
            String path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/Music/Test.mp3";
            player.setDataSource(path);
            Log.d("Jaychou","MusicDemo setDataSource");
            player.prepare();
            Log.d("Jaychou","MusicDemo Prepare");
            //player.start();
        } catch (IOException e) {
            e.printStackTrace();
            Log.d("Jaychou","err when play");
        }
    }

1. prepare序列图

  先来一张用UML工具Astah画的prepare的序列图, 让我们对流程有个大致的认识。
  这里写图片描述

  我也不知道为啥每次传上来的流程图看着都不清晰,看不清楚的同学可以下载到本地再放大一点看。

2. prepare都干了些啥

2.1 Client端

  序列图中的MusicDemo, MediaPlayer.java, Mediaplayer.cpp都是属于Client端,他们属于同一个进程。
  

这里写图片描述

一直调到Mediaplayer.cpp的prepare.

./frameworks/av/media/libmedia/Mediaplayer.cpp#prepare

status_t MediaPlayer::prepare()
{
    ALOGV("prepare");
    Mutex::Autolock _l(mLock);
    mLockThreadId = getThreadId();
    if (mPrepareSync) {
        mLockThreadId = 0;
        return -EALREADY;
    }
    mPrepareSync = true;
    status_t ret = prepareAsync_l();
    if (ret != NO_ERROR) {
        mLockThreadId = 0;
        return ret;
    }

    if (mPrepareSync) {
        mSignal.wait(mLock);  // wait for prepare done
        mPrepareSync = false;
    }
    ALOGV("prepare complete - status=%d", mPrepareStatus);
    mLockThreadId = 0;
    return mPrepareStatus;

再到

status_t MediaPlayer::prepareAsync_l()
{
    if ( (mPlayer != 0) && ( mCurrentState & (MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) {
        if (mAudioAttributesParcel != NULL) {
            mPlayer->setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, *mAudioAttributesParcel);
        } else {
            mPlayer->setAudioStreamType(mStreamType);
        }
        mCurrentState = MEDIA_PLAYER_PREPARING;
        return mPlayer->prepareAsync();
    }
    ALOGE("prepareAsync called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
    return INVALID_OPERATION;
}

可以看到,client端主要是调用service端的方法来设置Parameter, AudioStreamType和调用具体播放器(上一节我们知道是Nuplayer)的prepare方法. 还有一个是任务就是设置VideoSurfaceTexture,这个是在JNI层调用下来的,在日志中也可以看到:

02-13 18:57:15.769 V/MediaPlayer( 4477): setVideoSurfaceTexture
02-13 18:57:15.772 V/MediaPlayerService(  616): [4] setVideoSurfaceTexture(0x0)
02-13 18:57:15.774 V/MediaPlayerService(  616): [4] setAudioStreamType(3)

2.2 Service端

序列图中的mediaplayerservice之后的部分都是属于service端,它们是属于另一个进程。

这里写图片描述

2.2.1 MediaPlayerService

./frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp#prepareAsync

status_t MediaPlayerService::Client::prepareAsync()
{
    ALOGV("[%d] prepareAsync", mConnId);
    sp<MediaPlayerBase> p = getPlayer();
    if (p == 0) return UNKNOWN_ERROR;
    status_t ret = p->prepareAsync();
#if CALLBACK_ANTAGONIZER
    ALOGD("start Antagonizer");
    if (ret == NO_ERROR) mAntagonizer->start();
#endif
    return ret;
}

这里主要是调用Nupl

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值