文章目录
我们继续介绍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(这样不需要重复创建)
参考文章
部分链接丢失
《》
《》
《》
《》
