Android10.0Auidio之MediaPlayer(四)

前言
之前说了MediaPlayer如何从java层到jni,以及jin如何callback回调到java,今天继续看看native层的mediaplayer又做了什么。

正文
先说下路径位于frameworks/av/media/libmedia/mediaplayer.cpp,我们先从mediaplayer的构造跟析构函数说起

MediaPlayer::MediaPlayer()
{
    ALOGV("constructor");
    mListener = NULL;
    mCookie = NULL;
    mStreamType = AUDIO_STREAM_MUSIC;
    mAudioAttributesParcel = NULL;
    mCurrentPosition = -1;
    mCurrentSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
    mSeekPosition = -1;
    mSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
    mCurrentState = MEDIA_PLAYER_IDLE;
    mPrepareSync = false;
    mPrepareStatus = NO_ERROR;
    mLoop = false;
    mLeftVolume = mRightVolume = 1.0;
    mVideoWidth = mVideoHeight = 0;
    mLockThreadId = 0;
    mAudioSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
    AudioSystem::acquireAudioSessionId(mAudioSessionId, -1);
    mSendLevel = 0;
    mRetransmitEndpointValid = false;
}

MediaPlayer::~MediaPlayer()
{
    ALOGV("destructor");
    if (mAudioAttributesParcel != NULL) {
        delete mAudioAttributesParcel;
        mAudioAttributesParcel = NULL;
    }
    AudioSystem::releaseAudioSessionId(mAudioSessionId, -1);
    disconnect();
    IPCThreadState::self()->flushCommands();
}

构造函数初始化了好多参数,等具体使用的时候我们再一一细说,析构呢有一个disconnect(),这是做什么的呢

void MediaPlayer::disconnect()
{
    ALOGV("disconnect");
    sp<IMediaPlayer> p;
    {
        Mutex::Autolock _l(mLock);
        p = mPlayer;
        mPlayer.clear();
    }

    if (p != 0) {
        p->disconnect();
    }
}

mPlayer是啥呢?源码先放在这,后续分析,从mediaplayer的构造函数,我们大体知道貌似初始化了好多参数,但不清楚具体都做了什么。我们记得之前我们在分析jni的时候有个 mp->setListener(listener);这个listener是一个jni的JNIMediaPlayerListener,我们回到jni在看下,原来

JNIMediaPlayerListener: public MediaPlayerListener

继承自MediaPlayerListener,通过jni的头文件#include <media/mediaplayer.h>头文件我们发现MediaPlayerListener定义在mediaplayer.h中,而且mediaplayer中构造函数中mListener就是这个listener

status_t MediaPlayer::setListener(const sp<MediaPlayerListener>& listener)
{
    ALOGV("setListener");
    Mutex::Autolock _l(mLock);
    mListener = listener;
    return NO_ERROR;
}

到此native层如何回调到java层的逻辑就彻底清楚了。java层在创建MediaPlayer的时候,native层同时也会对应创建一个native的medaplayer,并在jni中set一个mediaplayerListener下来,这个listener主要作用回调jave层的postEventFromNative方法最终实现整个cllback的逻辑,具体可参照Android10.0Auidio之MediaPlayer(二)和Android10.0Auidio之MediaPlayer (三)
继续分析,在看下setDataSource吧,由于setDataSource的函数很多,这里只说一个

status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
{
    ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
    status_t err = UNKNOWN_ERROR;
    const sp<IMediaPlayerService> service(getMediaPlayerService());
    if (service != 0) {
        sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
        if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
            (NO_ERROR != player->setDataSource(fd, offset, length))) {
            player.clear();
        }
        err = attachNewPlayer(player);
    }
    return err;
}

这里先来分析下const sp service(getMediaPlayerService());其实大概也可以猜到获取mediaplayer的service嘛,但是具体怎么实现的呢?
我们知道mediaplayer继承自IMediaDeathNotifier,

IMediaDeathNotifier::getMediaPlayerService()
{
    ALOGV("getMediaPlayerService");
    Mutex::Autolock _l(sServiceLock);
    if (sMediaPlayerService == 0) {
        sp<IServiceManager> sm = defaultServiceManager();
        sp<IBinder> binder;
        do {
            binder = sm->getService(String16("media.player"));
            if (binder != 0) {
                break;
            }
            ALOGW("Media player service not published, waiting...");
            usleep(500000); // 0.5 s
        } while (true);

        if (sDeathNotifier == NULL) {
            sDeathNotifier = new DeathNotifier();
        }
        binder->linkToDeath(sDeathNotifier);
        sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
    }
    ALOGE_IF(sMediaPlayerService == 0, "no media player service!?");
    return sMediaPlayerService;
}

简单扫一眼,等说到mediaPlayerService的时候在具体说这块,这里不多说了,大概明白是个binder通信就可以了,拿到了service后先执行了sp player(service->create(this, mAudioSessionId));
很简单主要是拿这个服务的binder对象,然后调用service中的setDataSource(),然后attachNewPlayer(player),最终将结果返给jni,最终回调到java层。
这里先简单说下attachNewPlayer函数

status_t MediaPlayer::attachNewPlayer(const sp<IMediaPlayer>& player)
{
    status_t err = UNKNOWN_ERROR;
    sp<IMediaPlayer> p;
    { // scope for the lock
        Mutex::Autolock _l(mLock);

        if ( !( (mCurrentState & MEDIA_PLAYER_IDLE) ||
                (mCurrentState == MEDIA_PLAYER_STATE_ERROR ) ) ) {
            ALOGE("attachNewPlayer called in state %d", mCurrentState);
            return INVALID_OPERATION;
        }

        clear_l();
        p = mPlayer;
        mPlayer = player;
        if (player != 0) {
            mCurrentState = MEDIA_PLAYER_INITIALIZED;
            err = NO_ERROR;
        } else {
            ALOGE("Unable to create media player");
        }
    }

    if (p != 0) {
        p->disconnect();
    }

    return err;
}

代码不是很复杂,基本就是在client端与service端通信,主要通过这个mPlayer。

总结

今天说的好多都是把前边的串联起来了,native层的mediaplayer构造的时候初始化了mListener主要用作向java层传递callback用,而native层的mediaplayer最终通过binder与mediaPlayerService通信,其实这里有一个参数mAudioSessionId我们在setDataSource和构造函数中都看到了,这里没有具体说抽时间单独聊一下这个,因为不仅mediaplayer,包括audiotrack以及audiopolicy很多地方都用到了mAudioSessionId这个东西。我觉得还是有必要单独细说一下的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值