本篇是分析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<IMedi