前言

我们继续介绍MediaPlayer源码,继《MediaPlayer源码介绍2》和《mediaserver的启动》后,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源码介绍3

接上回。这里简单回顾一下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,先是简单的回顾一下哈(具体看《MediaPlayer源码介绍2》)。

//其实就是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之前在《mediaserver的启动》中有介绍过),按照之前介绍的,播放类就三种

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都稍微介绍过,具体看《mediaserver的启动》。

//获取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); }

上面很长,但我们只关注以下几点。

  1. mPlayer的创建

  2. mLooper初始化和启动

  3. 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> &notify, 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));

主要做了如下事情:

  1. 根据p->setDataSource()返回状态进行处理

  2. 把p(也就是NuPlayerDriver对象)赋值给mPlayer(这样不需要重复创建)

参考文章

部分链接丢失

  1. MediaPlayer源码介绍2

  2. mediaserver的启动

  3. Android MediaPlayer整体架构源码分析 -【MediaPlayer多种类型播放器注册和获取创建流程】

  4. Android多媒体框架:GenericSource搭建过程

暂无评论

评论审核已启用。您的评论可能需要一段时间后才能被显示。

none
暂无评论...