admin管理员组文章数量:1516870
前言
之前说了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 =newDeathNotifier();}
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这个东西。我觉得还是有必要单独细说一下的。
版权声明:本文标题:一文看懂 Android 10 中的MediaPlayer:音乐播放新体验! 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.betaflare.com/web/1773285605a3277459.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。


发表评论