目录
前言
我们继续介绍MediaPlayer的源码,继《》和《》后,MediaPlayer也进入了MediaPlayerService的接口调用中。
今天我们继续以setDataSource为例,看看其在MediaPlayerService的流程。
frameworks\av\media\libmediaplayerservice\MediaPlayerService.cpp frameworks\av\media\libmediaplayerservice\MediaPlayerFactory.cpp frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayerDriver.cpp frameworks\av\media\libstagefright\foundation\ALooper.cpp frameworks\av\media\libstagefright\foundation\AMessage.cpp frameworks\av\media\libmediaplayerservice\nuplayer\NuPlayer.cpp frameworks\av\media\libmediaplayerservice\nuplayer\GenericSource.cpp
正文
接上回。这里简单回顾一下mediaplayer.cpp的setDataSource()。
// mediaplayer.cpp 中 status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length){ status_t err = UNKNOWN_ERROR; // getMediaPlayerService()获取的是BpMediaPlayerService // BpMediaPlayerService的对象service const sp<IMediaPlayerService> service(getMediaPlayerService()); if (service != 0) { //创建BpMediaPlayer对象player,具体看BpMediaPlayerService中create方法 sp<IMediaPlayer> player(service->create(this, mAudioSessionId)); if ((NO_ERROR != doSetRetransmitEndpoint(player)) || //就是调用BpMediaPlayer->setDataSource(); (NO_ERROR != player->setDataSource(fd, offset, length))) { player.clear(); } //赋值,mPlayer = plyaer; //BpMediaPlayer在IMediaPlayer.cpp err = attachNewPlayer(player); } return err; }
我们知道player是BpMediaPlayer,先是简单的回顾一下哈(具体看《》)。
//其实就是BpMediaPlayer->setDataSource(); player->setDataSource(); //调用的是 remote()->transact(SET_DATA_SOURCE_FD, data, &reply); //通过Binder通信进入了BnMediaPlayer的onTransact() BnMediaPlayer.onTransact(); //调用的是setDataSource(),而BnMediaPlayer没有实现,那就看器子类 reply->writeInt32(setDataSource(fd, offset, length)); //BnMediaPlayer继承BnInterface<IMediaPlayer>没有实现其父类接口 //其子类,MediaPlayerService中Client继承BnMediaPlayer //并实现了setDataSource(),因此进入Client.setDataSource() MediaPlayerService::Client::setDataSource();
接上回分析,我们进入了
//MediaPlayerService.cpp MediaPlayerService::Client::setDataSource();
setDataSource()
status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length){ struct stat sb; //略 //获取播放类型 player_type playerType = MediaPlayerFactory::getPlayerType(this, fd, offset, length); //根据类型创建createPlayer sp<MediaPlayerBase> p = setDataSource_pre(playerType); if (p == NULL) { return NO_INIT; } return mStatus = setDataSource_post(p, p->setDataSource(fd, offset, length)); }
getPlayerType()
player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client, int fd, int64_t offset, int64_t length) { GET_PLAYER_TYPE_IMPL(client, fd, offset, length); }
调用的是GET_PLAYER_TYPE_IMPL()
GET_PLAYER_TYPE_IMPL
其实就是查找sFactoryMap中存储的类型。(这个sFactoryMap之前在《》中有介绍过),按照之前介绍的,播放类就三种
enum player_type { STAGEFRIGHT_PLAYER = 3, NU_PLAYER = 4, TEST_PLAYER = 5, };
而我们之前在registerBuiltinFactories()就注册了NU_PLAYER和TEST_PLAYER。一般用这个NU_PLAYER。
#define GET_PLAYER_TYPE_IMPL(a...) \ Mutex::Autolock lock_(&sLock); \ // 默认为STAGEFRIGHT_PLAYER类型 player_type ret = STAGEFRIGHT_PLAYER; \ //最佳播放器得分 float bestScore = 0.0; \ // 播放器工厂模式实现的缓存注册的已实现的所有播放器集合[sFactoryMap] // 进行循环并查找最佳得分的播放器 for (size_t i = 0; i < sFactoryMap.size(); ++i) { \ // 获取该播放器工厂得分,注意此处的参数a是个可变参数, // 例如上面是文件流时为4个参数,因此传入给scoreFactory方法的参数即可5个参数 // 见下面的具体Factory实现分析中 IFactory* v = sFactoryMap.valueAt(i); \ float thisScore; \ CHECK(v != NULL); \ thisScore = v->scoreFactory(a, bestScore); \ // 若当前播放器工厂得分更高则替换旧值 if (thisScore > bestScore) { \ ret = sFactoryMap.keyAt(i); \ bestScore = thisScore; \ } \ } \ // 若最佳得分为0,则获取默认推荐的播放器类型。 // getDefaultPlayerType()直接返回的是[NU_PLAYER]播放器类型 if (0.0 == bestScore) { \ ret = getDefaultPlayerType(); \ } \ return ret;
setDataSource_pre()
根据playerType,进行获取player
sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre( player_type playerType){ //根据类型进行获取对应的player sp<MediaPlayerBase> p = createPlayer(playerType); if (p == NULL) { return p; } sp<IServiceManager> sm = defaultServiceManager(); //获取媒体解码器 sp<IBinder> binder = sm->getService(String16("media.extractor")); if (binder == NULL) { return NULL; } //解码器死亡监听 sp<ServiceDeathNotifier> extractorDeathListener = new ServiceDeathNotifier(binder, p, MEDIAEXTRACTOR_PROCESS_DEATH); binder->linkToDeath(extractorDeathListener); //获取omx sp<IOmx> omx = IOmx::getService(); if (omx == nullptr) { return NULL; } //omx死亡监听 sp<ServiceDeathNotifier> codecDeathListener = new ServiceDeathNotifier(omx, p, MEDIACODEC_PROCESS_DEATH); omx->linkToDeath(codecDeathListener, 0); Mutex::Autolock lock(mLock); clearDeathNotifiers_l(); mExtractorDeathListener = extractorDeathListener; mCodecDeathListener = codecDeathListener; mAudioDeviceUpdatedListener = new AudioDeviceUpdatedNotifier(p); if (!p->hardwareOutput()) { mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid(), mPid, mAudioAttributes, mAudioDeviceUpdatedListener); static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput); } return p; }
我们这里只关注createPlayer哈,其他的暂时忽略。
createPlayer()
先查询已经有的,如果类型不一样,就清除之前的,重新根据类型进行获取
sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType){ //获取之前使用的player sp<MediaPlayerBase> p = getPlayer(); if ((p != NULL) && (p->playerType() != playerType)) { //如果之前的不为null,且类型不一样,清除 p.clear(); } //重新通过playerType进行创建Player if (p == NULL) { p = MediaPlayerFactory::createPlayer(playerType, mListener, mPid); } if (p != NULL) { p->setUID(mUid); } return p; }
createPlayer()
进入MediaPlayerFactory::createPlayer()。
sp<MediaPlayerBase> MediaPlayerFactory::createPlayer( player_type playerType, const sp<MediaPlayerBase::Listener> &listener, pid_t pid) { sp<MediaPlayerBase> p; IFactory* factory; status_t init_result; Mutex::Autolock lock_(&sLock); if (sFactoryMap.indexOfKey(playerType) < 0) { return p; } //获取NuPlayerFactory factory = sFactoryMap.valueFor(playerType); CHECK(NULL != factory); // p = new NuPlayerDriver(); factory是之前创建的,从sFactoryMap获取 //也就是说真正处理的还是进入了NuPlayerDriver,真绕 p = factory->createPlayer(pid); if (p == NULL) { return p; } init_result = p->initCheck(); if (init_result == NO_ERROR) { //设置监听 p->setNotifyCallback(listener); } else { p.clear(); } return p; }
这里做了三件事(1)从sFactoryMap根据类型获取NuPlayerFactory对象(2)同NuPlayerFactory对象创建NuPlayerDriver(3)对player设置监听。
listener就是赋值的mListener,是MediaPlayerService::Client::Client的变量,这里暂不关心。
从上面的之前sFactoryMap和NuPlayerFactory都稍微介绍过,具体看《》。
//获取NuPlayerFactory factory = sFactoryMap.valueFor(playerType);
//调用NuPlayerFactory.createPlayer() p = factory->createPlayer(pid);
class NuPlayerFactory : public MediaPlayerFactory::IFactory { public: virtual sp<MediaPlayerBase> createPlayer(pid_t pid) { return new NuPlayerDriver(pid); } };
也就是创建的p就是NuPlayerDriver对象。
NuPlayerDriver
接上面NuPlayerFactory.createPlayer()。
class NuPlayerFactory : public MediaPlayerFactory::IFactory { public: virtual sp<MediaPlayerBase> createPlayer(pid_t pid) { return new NuPlayerDriver(pid); } };
NuPlayerDriver在NuPlayerDriver.cpp中。
NuPlayerDriver::NuPlayerDriver(pid_t pid) : mState(STATE_IDLE), mIsAsyncPrepare(false), mAsyncResult(UNKNOWN_ERROR), mSetSurfaceInProgress(false), mDurationUs(-1), mPositionUs(-1), mSeekInProgress(false), mPlayingTimeUs(0), mRebufferingTimeUs(0), mRebufferingEvents(0), mRebufferingAtExit(false), mLooper(new ALooper), mMediaClock(new MediaClock), //初始化了mPlayer,NuPlayer的对象 mPlayer(new NuPlayer(pid, mMediaClock)), mPlayerFlags(0), mAnalyticsItem(NULL), mClientUid(-1), mAtEOS(false), mLooping(false), mAutoLoop(false) { //mLooper设置名字 mLooper->setName("NuPlayerDriver Looper"); mMediaClock->init(); mAnalyticsItem = new MediaAnalyticsItem(kKeyPlayer); //mLooper调用start方法 mLooper->start( false, /* runOnCallingThread */ true, /* canCallJava */ PRIORITY_AUDIO); //关联mPlayer mLooper->registerHandler(mPlayer); //调用mPlayer.init() mPlayer->init(this); }
上面很长,但我们只关注以下几点。
-
mPlayer的创建
-
mLooper初始化和启动
-
mPlayer调用init()
mPlayer初始化
变量初始化时
mPlayer(new NuPlayer(pid, mMediaClock))
这是C++的写法,等于
mPlayer = new NuPlayer(pid, mMediaClock)
也就是mPlayer是NuPlayer的对象。
struct NuPlayer : public AHandler { }
NuPlayer是AHandler的子类。
后面调用了init()。
init()
mPlayer->init(this);
void NuPlayer::init(const wp<NuPlayerDriver> &driver) { //就是NuPlayerDriver mDriver = driver; //这里初始化了AMessage sp<AMessage> notify = new AMessage(kWhatMediaClockNotify, this); mMediaClock->setNotificationMessage(notify); }
mLooper
哈哈看名字是不是很熟悉。没错。就是那个味!
mLooper(new ALooper)
//设置mLooper名字 mLooper->setName("NuPlayerDriver Looper"); //启动looper mLooper->start( false, /* runOnCallingThread */ true, /* canCallJava */ PRIORITY_AUDIO); //关联mPlayer mLooper->registerHandler(mPlayer);
暂时对这块不是很理解,只是知道就是ALooper AHandler AMessager组成一个消息循环的。
这部分后续吧,略过。
NuPlayerDriver小结
从上面NuPlayerDriver构造函数可以看出,NuPlayerDriver也是不干活的,真正干活的是NuPlayer,不过这里有一个消息队列。
p->setDataSource()
我们已经知道p就是NuPlayerDriver的对象,就是
NuPlayerDriver->setDataSource();
status_t NuPlayerDriver::setDataSource(int fd, int64_t offset, int64_t length) { Mutex::Autolock autoLock(mLock); if (mState != STATE_IDLE) { return INVALID_OPERATION; } mState = STATE_SET_DATASOURCE_PENDING; //mPlayer是NuPlayer对象 mPlayer->setDataSourceAsync(fd, offset, length); //这里有个循环,会等待mState的变化 while (mState == STATE_SET_DATASOURCE_PENDING) { //直到mState出现变化,要不然等待 mCondition.wait(mLock); } // 这个值会在notifySetDataSourceCompleted()中更新 return mAsyncResult; }
mState和mAsyncResult是在notifySetDataSourceCompleted()中更新的,后面会有。
干活的是NuPlayer,进入NuPlayer.cpp
setDataSourceAsync
void NuPlayer::setDataSourceAsync(int fd, int64_t offset, int64_t length) { //创建Message,消息类型是kWhatSetDataSource和kWhatSourceNotify sp<AMessage> msg = new AMessage(kWhatSetDataSource, this); sp<AMessage> notify = new AMessage(kWhatSourceNotify, this); //初始化GenericSource, notify是个Message用于消息通知 sp<GenericSource> source = new GenericSource(notify, mUIDValid, mUID, mMediaClock); //通过source进行setDataSource status_t err = source->setDataSource(fd, offset, length); if (err != OK) { source = NULL; } //把创建的source附上 msg->setObject("source", source); //发送Message出去 msg->post(); mDataSourceType = DATA_SOURCE_TYPE_GENERIC_FD; }
这里关注GenericSource,这个才是重点GenericSource继承NuPlayer::Source和MediaBufferObserver。
NuPlayer::GenericSource::GenericSource( const sp<AMessage> ¬ify, bool uidValid, uid_t uid, const sp<MediaClock> &mediaClock) : Source(notify),//Message用于状态通知 mAudioTimeUs(0), mAudioLastDequeueTimeUs(0), mVideoTimeUs(0), mVideoLastDequeueTimeUs(0), mPrevBufferPercentage(-1), mPollBufferingGeneration(0), mSentPauseOnBuffering(false), mAudioDataGeneration(0), mVideoDataGeneration(0), mFetchSubtitleDataGeneration(0), mFetchTimedTextDataGeneration(0), mDurationUs(-1ll), mAudioIsVorbis(false), mIsSecure(false), mIsStreaming(false), mUIDValid(uidValid), mUID(uid), mMediaClock(mediaClock), mFd(-1), //文件描述符索引默认值 mBitrate(-1ll), mPendingReadBufferTypes(0) { CHECK(mediaClock != NULL); mBufferingSettings.mInitialMarkMs = kInitialMarkMs; mBufferingSettings.mResumePlaybackMarkMs = kResumePlaybackMarkMs; //重置变量初始状态 resetDataSource(); }
初始化当前资源进入source,传入了文件描述符索引值和文件长度信息等。
status_t err = source->setDataSource(fd, offset, length);
setDataSource
status_t NuPlayer::GenericSource::setDataSource( int fd, int64_t offset, int64_t length) { Mutex::Autolock _l(mLock); //这里又变量恢复默认状态 resetDataSource(); //保存当前文件相关信息 mFd = dup(fd); mOffset = offset; mLength = length; return OK; }
onMessageReceived()
msg->post();
消息发送了,消息类型是kWhatSetDataSource,进入了onMessageReceived()
void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { switch (msg->what()) { case kWhatSetDataSource:{ CHECK(mSource == NULL); status_t err = OK; sp<RefBase> obj; CHECK(msg->findObject("source", &obj)); if (obj != NULL) { Mutex::Autolock autoLock(mSourceLock); //mSource赋值,上面setDataSourceAsync()初始化并传入的message中的 //这里用了静态类型转换 mSource = static_cast<Source *>(obj.get()); } else { err = UNKNOWN_ERROR; } CHECK(mDriver != NULL); //mDriver是之前传入的NuPlayerDriver对象 sp<NuPlayerDriver> driver = mDriver.promote(); if (driver != NULL) { //这里用于回调状态 driver->notifySetDataSourceCompleted(err); } break; } //略 } }
notifySetDataSourceCompleted
driver->notifySetDataSourceCompleted(err);
就是
# NuPlayerDriver.cpp NuPlayerDriver->notifySetDataSourceCompleted(err);
void NuPlayerDriver::notifySetDataSourceCompleted(status_t err) { Mutex::Autolock autoLock(mLock); CHECK_EQ(mState, STATE_SET_DATASOURCE_PENDING); //更新结果 mAsyncResult = err; //刷新状态 mState = (err == OK) ? STATE_UNPREPARED : STATE_IDLE; //mCondition通知解锁 mCondition.broadcast(); }
到此,setDataSource()就差不多了,然后就等setDataSource_post()进行回调状态了。
setDataSource_post()
这个就是抛出p->setDataSource()状态。
return mStatus = setDataSource_post(p, p->setDataSource(fd, offset, length));
主要做了如下事情:
-
根据p->setDataSource()返回状态进行处理
-
把p(也就是NuPlayerDriver对象)赋值给mPlayer(这样不需要重复创建)
参考文章
部分链接丢失
-
《》
-
《》
-
《》
-
《》