本篇是分析Android设备系统用MediaPlayer类播放视频过程中各个类或函数相互调用的过程,只分析主干过程,不死磕细枝末节, 且着墨于Native层C++的实现,本人资历学识浅薄,忘各位批评指正,多加交流!
既然要分析视频播放时的函数调用过程,必然要有一个主干流程可抓,下面就是一个典型的播放序列——一小段Java应用程序,我们以此为主干流程加以分析:
A块代码如下:
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource("/sdcard/The Human.wav");
mediaPlayer.prepare();
mediaPlayer.start();
mediaPlayer.stop();
首先,A块第一行代码: MediaPlayer mediaPlayer = new MediaPlayer(); //新建MediaPlayer对象
其构造函数在Native层的源码如下:(表述似乎有些别扭,我想表达的时应用层Java程序->JNI->Native的C++)
MediaPlayer::MediaPlayer()
{
ALOGV("constructor");
mListener = NULL;
mCookie = NULL;
mStreamType = AUDIO_STREAM_MUSIC;
mCurrentPosition = -1;
mSeekPosition = -1;
mCurrentState = MEDIA_PLAYER_IDLE;
mPrepareSync = false;
mPrepareStatus = NO_ERROR;
mLoop = false;
mLeftVolume = mRightVolume = 1.0;
mVideoWidth = mVideoHeight = 0;
mLockThreadId = 0;
mAudioSessionId = AudioSystem::newAudioSessionId();
AudioSystem::acquireAudioSessionId(mAudioSessionId);
mSendLevel = 0;
mRetransmitEndpointValid = false;
}
这里只是一些类中变量的初始化,与流程关系不大,我们继续往下分析A块代码第二行:
mediaPlayer.setDataSource("/sdcard/The Human.wav");
这个函数可以说是本篇最重要的函数,看完本文,你会发现整篇都是分析它!!!!其在Native层的代码对应如下:
B块代码如下:
status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
{
ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
status_t err = UNKNOWN_ERROR;
const sp<IMediaPlayerService>& service(getMediaPlayerService());
if (service != 0) {
sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId));
if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
(NO_ERROR != player->setDataSource(fd, offset, length))) {
player.clear();
}
err = attachNewPlayer(player);
}
return err;
}
这里我们重点分析B块代码的第五行、第七行、第九行,第十二行
先简略分析下各行的作用
B.5(B块代码第五行),const sp<IMediaPlayerService>& service(getMediaPlayerService()),获得MediaPlayerService;
B.7, sp<IMediaPlayer> player(service->create(this ,mAudiaSessionId)),返回MediaPlayerService的Client对象Player,后续使用该Client将向MediaPlayer提供服务,因此每一个MediaPlayer都对应一个Client
B.9, player->setDataSource("sdcard/The Human.wav"), 选择正确的播放器,并设置播放器的数据源
B.12, attachNewPlayer(player);保存最新的Client对象,断开之前的Client对象
将B.5行代码getMediaPlayerService()展开,得到:
C块代码如下:
// establish binder interface to MediaPlayerService
/*static*/const sp<IMediaPlayerService>&
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;
}
上面C块代码,是通过Binder通信,最终达到获得MediaPlayerService的目的,不在此次分析的重点,并将其值赋给Service
setDataSource的操作就转成通过与mediaplayerservice的交互来完成了
将B.7行代码service->create(this ,mAudiaSessionId)打开,得到:
D块代码如下:
sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client,
int audioSessionId)
{
int32_t connId = android_atomic_inc(&mNextConnId);
sp<Client> c = new Client(
this, pid, connId, client, audioSessionId,
IPCThreadState::self()->getCallingUid());
ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid,
IPCThreadState::self()->getCallingUid());
wp<Client> w = c;
{
Mutex::Autolock lock(mLock);
mClients.add(w);
}
return c;
}
Client类的继承关系为:Client->BnMediaPlayer->IMediaPlayer分析上面代码,可以看出create方法,是构造了一个Client对象,并且将此client对象添加到mediapalyerservice类的全局列表中:mClient
所以在Server端,我们新建的对象是Client,是MediaPlayerService的内部类。这个Client执行了MediaPlayerService的绝大部分操作。同样我们将来传输过来的数据也都是会交给内部类Client进行处理的。到这里,在Server端的对象就创建完成了,所以上面才说每一个MediaPlayer都对应着一个Client
回到之前B块代码,将B.9行代码player->setDataSource("sdcard/The Human.wav"),展开:
得到E块代码如下:
E块代码
status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
{
ALOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length);
struct stat sb;
int ret = fstat(fd, &sb);
if (ret != 0) {
ALOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
return UNKNOWN_ERROR;
}
ALOGV("st_dev = %llu", sb.st_dev);
ALOGV("st_mode = %u", sb.st_mode);
ALOGV("st_uid = %lu", sb.st_uid);
ALOGV("st_gid = %lu", sb.st_gid);
ALOGV("st_size = %llu", sb.st_size);
if (offset >= sb.st_size) {
ALOGE("offset error");
::close(fd);
return UNKNOWN_ERROR;
}
if (offset + length > sb.st_size) {
length = sb.st_size - offset;
ALOGV("calculated length = %lld", length);
}
player_type playerType = MediaPlayerFactory::getPlayerType(this,
fd,
offset,
length);
sp<MediaPlayerBase> p = setDataSource_pre(playerType);
if (p == NULL) {
return NO_INIT;
}
// now set data source
setDataSource_post(p, p->setDataSource(fd, offset, length));
return mStatus;
}
E块代码重点分析E.27, E.31, E.37,(注意虽然与其那面相比都是setDataSource函数,但是,一开始的是MediaPlayer的函数,现在变成了MediaPlayerService的函数,说明最终实现实在MediaPlayerService中),
将E.27代码getPlayerType(.......)展开得到:
代码:setDataSource_post(p, p->setDataSource(fd, offset, length));我们重点看一下这个函数的第二个参数setDataSource(fd, offset, length),展开如下:
player_type MediaPlayerFactory::getPlayerType(constsp<IMediaPlayer>& client,
intfd,
int64_t offset,
int64_t length) {
GET_PLAYER_TYPE_IMPL(client, fd, offset, length);
}
=继续将宏GET_PLAYER_TYPE_IMPL(client, fd, offset, length);展开得到:
F块代码
#define GET_PLAYER_TYPE_IMPL(a...) \
Mutex::Autolock lock_(&sLock); \
\
player_type ret = STAGEFRIGHT_PLAYER; \
float bestScore =0.0; \
\
for(size_t i = 0; i < sFactoryMap.size(); ++i) { \
\
IFactory* v = sFactoryMap.valueAt(i); \
float thisScore; \
CHECK(v != NULL); \
thisScore = v->scoreFactory(a, bestScore); \
if(thisScore > bestScore) { \
ret = sFactoryMap.keyAt(i); \
bestScore = thisScore; \
} \
} \
\
if(0.0 == bestScore) { \
bestScore = getDefaultPlayerType(); \
} \
\
returnret;
我们只看v->scoreFactory(a, bestScore);这句代码,这就要用到安卓系统的工厂模式与打分机制了,这个目前只了解一点点,这里就是在注册的几种播放器中选择得分最高的播放器来进行接下来的处理,若所有的播放器都不合适,则会选择默认播放器来进行操作,
接下来继续展开E.31行代码setDataSource_pre(playerType),得到:
G块代码
sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre(
player_type playerType)
{
ALOGV("player type = %d", playerType);
// create the right type of player
sp<MediaPlayerBase> p = createPlayer(playerType);
if (p == NULL) {
return p;
}
if (!p->hardwareOutput()) {
mAudioOutput = new AudioOutput(mAudioSessionId);
static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
}
return p;
}
继续展开上面第七行的createPlayer(playerType)得到如下代码:
sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)
{
// determine if we have the right player type
sp<MediaPlayerBase> p = mPlayer;
if ((p != NULL) && (p->playerType() != playerType)) {
ALOGV("delete player");
p.clear();
}
if (p == NULL) {
p = MediaPlayerFactory::createPlayer(playerType, this, notify);
}
if (p != NULL) {
p->setUID(mUID);
}
return p;
}
继续展开上面第10行,这里用了Factory设计模式,其源码在/frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp中,展开MediaPlayerFactory::createPlayer(playerType, this, notify);,如下:
sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
player_type playerType,
void* cookie,
notify_callback_f notifyFunc) {
sp<MediaPlayerBase> p;
IFactory* factory;
status_t init_result;
Mutex::Autolock lock_(&sLock);
if (sFactoryMap.indexOfKey(playerType) < 0) {
ALOGE("Failed to create player object of type %d, no registered"
" factory", playerType);
return p;
}
factory = sFactoryMap.valueFor(playerType);
CHECK(NULL != factory);
p = factory->createPlayer();
if (p == NULL) {
ALOGE("Failed to create player object of type %d, create failed",
playerType);
return p;
}
init_result = p->initCheck();
if (init_result == NO_ERROR) {
p->setNotifyCallback(cookie, notifyFunc);
} else {
ALOGE("Failed to create player object of type %d, initCheck failed"
" (res = %d)", playerType, init_result);
p.clear();
}
return p;
}
分析上面代码第18行,其Factory代表前面打分模式中获取最高分的那个播放器工厂的类,比如
class OMXPlayerFactory : public MediaPlayerFactory::IFactory
class StagefrightPlayerFactory : public MediaPlayerFactory::IFactory
class NuPlayerFactory : public MediaPlayerFactory::IFactory
工厂类原型如下:
class IFactory {
public:
virtual ~IFactory() { }
virtual float scoreFactory(const sp<IMediaPlayer>& client,
const char* url,
float curScore,
const KeyedVector<String8, String8> *headers = NULL) { return 0.0; }
virtual float scoreFactory(const sp<IMediaPlayer>& client,
int fd,
int64_t offset,
int64_t length,
float curScore) { return 0.0; }
virtual float scoreFactory(const sp<IMediaPlayer>& client,
const sp<IStreamSource> &source,
float curScore) { return 0.0; }
virtual sp<MediaPlayerBase> createPlayer() = 0;
};
假设怎们的勤勉打分机制选中的是StagefrightPlayerFactory,继续展开第18行的factory->createPlayer()的代码,得到如下代码:
virtual sp<MediaPlayerBase> createPlayer() {
ALOGV(" create StagefrightPlayer");
return new StagefrightPlayer();
}
查看StagefrightPlayer类构造函数
StagefrightPlayer::StagefrightPlayer()
: mPlayer(new AwesomePlayer) {
ALOGV("StagefrightPlayer");
mPlayer->setListener(this);
}
现在看来真正干活的人出现了是AwesomePlayer,要干活的播放器也终于创建完成了
咱们这才是分析了E.31的代码sp<MediaPlayerBase> p = setDataSource_pre(playerType);,怎么样是不是走的太远忘记了来时的分叉口,就让我们继续分析E.37行的代码吧 ;setDataSource_post(p, p->setDataSource(fd, offset, length));主要是分析其第二个参数p->setDataSource(fd, offset, length),这里也只是运用要干活的播放器设置了一些属性,调用的时候,执行了实际播放器的setDataSource方法,而实际的setDataSource_post 仅仅是将播放器保存在本地成员mPlayer中,代码如下:
void MediaPlayerService::Client::setDataSource_post(
constsp<MediaPlayerBase>& p,
status_t status)
{
ALOGV(" setDataSource");
mStatus = status;
if(mStatus != OK) {
ALOGE(" error: %d", mStatus);
return;
}
// Set the re-transmission endpoint if one was chosen.
if(mRetransmitEndpointValid) {
mStatus = p->setRetransmitEndpoint(&mRetransmitEndpoint);
if(mStatus != NO_ERROR) {
ALOGE("setRetransmitEndpoint error: %d", mStatus);
}
}
if(mStatus == OK) {
mPlayer = p;
}
}
到这里我们的分析调用过程也告一段落了继续往下分析就是StagefrightPlaye的具体实现了,等过一段时间弄明白了其具体实现再来发布关于stagefrightPlayer实现的博文!
欢迎评论,欢迎交流,本人会及时回复,互相进步.......