一、 stagefrightplayer引入:
mediaplayerservice会在MediaPlayerFactory.cpp中根据URL进行打分,选择出最适合的播放器,对于Android原生的播放器,有stagefrightplayer和nuplayerdriver,Stagefrightplayer是对awesomeplayer的封装,nuplayerdriver是对nuplayer的封装,安卓5.1之后,基本弃用前者,所以,代码分析在4.4版本进行。
二、 构造过程:
frameworks\av\media\libmediaplayerservice\MediaPlayerFactory.cpp
frameworks\av\media\libmediaplayerservice\StagefrightPlayer.cpp
frameworks\av\media\libstagefright\AwesomePlayer.cpp
frameworks\av\media\libstagefright\MediaExtractor.cpp
- 实例化stagefrightplayer:
virtual sp<MediaPlayerBase> createPlayer() {
ALOGV(" create StagefrightPlayer");
return new StagefrightPlayer();
}
StagefrightPlayer::StagefrightPlayer()
: mPlayer(new AwesomePlayer) {
ALOGV("StagefrightPlayer");
mPlayer->setListener(this);
}
StagefrightPlayer的实例化其实就是去new一个AwesomePlayer;而mPlayer的类型正是AwesomePlayer*;
- setdatasource(以本地播放为例):
mediaplayer->StagefrightPlayer;
status_t StagefrightPlayer::setDataSource(int fd, int64_t offset, int64_t length) {
ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
return mPlayer->setDataSource(dup(fd), offset, length);
}
调用至awesomeplayer:
status_t AwesomePlayer::setDataSource(
int fd, int64_t offset, int64_t length) {
Mutex::Autolock autoLock(mLock);
/* 1.调用reset_l清除上次播放痕迹 */
reset_l();
sp<DataSource> dataSource = new FileSource(fd, offset, length);
...
/* 2.调用setDataSource_l */
return setDataSource_l(dataSource);
}
继续跟踪setDataSource_l
status_t AwesomePlayer::setDataSource_l(
const sp<DataSource> &dataSource) {
/* 1.创建解析器extractor */
sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
...
/* 2.将解析器传入继续往下调用 */
return setDataSource_l(extractor);
}
status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
...
/* 1.遍历数据内容,获取元数据 */
mExtractor = extractor;
for (size_t i = 0; i < extractor->countTracks(); ++i) {
sp<MetaData> meta = extractor->getTrackMetaData(i);
...
}
...
bool haveAudio = false;
bool haveVideo = false;
for (size_t i = 0; i < extractor->countTracks(); ++i) {
...
/* 2.分离出视频轨道与音频轨道,赋值给mVideoTrack和mAudioTrack */
if (!haveVideo && !strncasecmp(mime.string(), "video/", 6)) {
setVideoSource(extractor->getTrack(i));
...
}
} else if (!haveAudio && !strncasecmp(mime.string(), "audio/", 6)) {
setAudioSource(extractor->getTrack(i));
...
}
...
return OK;
}
代码会根据不同的格式创建对应的解析器,然后直接分离音视频的工作(demux);
三、 总结:
1. 构造顺序:factory->Stagefrightplayer->awesomeplayer;
2. mediaplayer调用setdatasource操作,awesomeplayer执行创建解析器并解复用音视频码流的动作;