MediaPlayer是Android最基础的播放器,一般播放本地文件就会使用MediaPlayer;
关于MediaPlayer的基础用法的相关文章到处都是,本文就不在详细解说了;
Mediaplayer的使用,主要是记住他的状态机
下面来一起看一下他的内部实现
参考文档:
MediaPlayer框架概述
上面这个网站讲的还是比较清楚的
1.java framwork层的MediaPlayer.java通过JNI调用android_media_mediaplayer.cpp的方法,在native framwork层映射了一个MediaPlayer.cpp,
2.MediaPlayer.cpp 和MediaPlayerService之间一对aidl
3.MediaPlayerService内部实现会交给NuPlayer
4.NuPlayer才是实际去进行视频播放的播放器,NuPlayer会把视频资源分解成AudioTrack和VideoTrack
5.VideoTrack交给SurfaceFlinger去处理
6.AudioTrack交给AudioFlinger去处理;
7.最终形成视频播放;
关键类都在这个下面
NuPlayer源码解析:
参考文档:
NuPlayer源码分析(一)
NuPlayer源码分析(二)
status_t NuPlayer::GenericSource::initFromDataSource() {
...
/* 创建数据提取器 */
extractor = MediaExtractor::Create(mDataSource,
mSniffedMIME.empty() ? NULL: mSniffedMIME.c_str());
...
/* 分离音视频track */
for (size_t i = 0; i < numtracks; ++i) {
sp<MediaSource> track = extractor->getTrack(i);
if (track == NULL) {
continue;
}
sp<MetaData> meta = extractor->getTrackMetaData(i);
const char *mime;
CHECK(meta->findCString(kKeyMIMEType, &mime));
// Do the string compare immediately with "mime",
// we can't assume "mime" would stay valid after another
// extractor operation, some extractors might modify meta
// during getTrack() and make it invalid.
if (!strncasecmp(mime, "audio/", 6)) {
if (mAudioTrack.mSource == NULL) {
mAudioTrack.mIndex = i;
mAudioTrack.mSource = track;
mAudioTrack.mPackets =
new AnotherPacketSource(mAudioTrack.mSource->getFormat());
if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
mAudioIsVorbis = true;
} else {
mAudioIsVorbis = false;
}
}
} else if (!strncasecmp(mime, "video/", 6)) {
if (mVideoTrack.mSource == NULL) {
mVideoTrack.mIndex = i;
mVideoTrack.mSource = track;
mVideoTrack.mPackets =
new AnotherPacketSource(mVideoTrack.mSource->getFormat());
// check if the source requires secure buffers
int32_t secure;
if (meta->findInt32(kKeyRequiresSecureBuffers, &secure)
&& secure) {
mIsSecure = true;
if (mUIDValid) {
extractor->setUID(mUID);
}
}
}
}
...
}
}