android 在java api中播放一个音乐文件:
MediaPlayer player = new MediaPlayer();
try {
player.setDataSource("/storage/emulated/0/test.aac");
player.prepare();
} catch (IOException e) {
e.printStackTrace();
}
player.start();
上面调用如此简单,framework层里面可是做了非常多的工作,追一下源码。基于android 10,api-29.本篇仅仅为了分析从MediaPlayer.java 到NuPlayer的关联过程,主要跟踪setDataSource 和prepare两个函数,至于后续NuPlayer如何解复用,解码,渲染,已经其中涉及到的音视频数据流转,控制,驱动线程模型,不涉及。大图:
上图的文字模式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84mediaplayer |------MediaPlayer.java | basemediajavaandroidmedia | |--static { | | System.loadLibrary("media_jni"); | | native_init(); | | } | |--MediaPlyer() | | |--Looper.myLooper()//创建了looper线程 | | | |--new EventHandler(this, looper) | | |--mTimeProvider = new TimeProvider(this); | | |--mOpenSubtitleSources = new Vector<InputStream>(); | | |--native_setup(new WeakReference<MediaPlayer>(this)) | | |--baseRegisterPlayer() | |--setDataSource() | | |--nativeSetDataSource( | | | IBinder httpServiceBinder, String path, String[] keys, String[] values) | | |--native void _setDataSource(FileDescriptor fd, long offset, long length) | |--prepare() |-----android_media_MediaPlayer.cpp | basemediajni | |--android_media_MediaPlayer_native_init() | |--android_media_MediaPlayer_native_setup() | | |--sp<MediaPlayer> mp = new MediaPlayer(); | | |--sp<JNIMediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this); | | |--setMediaPlayer(env, thiz, mp); | |--android_media_MediaPlayer_setDataSourceFD() | | |--mp->setDataSource(fd, offset, length) | |--android_media_MediaPlayer_prepare() | |--mp->prepare() |------mediaplayer.cpp | avmedialibmedia | |--MediaPlayer() | |--setDataSource() | | |--sp<IMediaPlayer> player(service->create(this, mAudioSessionId) | | |--attachNewPlayer() | | | sp<IMediaPlayer> mPlayer | | |--player->setDataSource | |--prepare() | | |--prepareAsync_l() | | | |--mPlayer->setParameter | | | |--mPlayer->prepareAsync() |------IMediaPlayerService.cpp | avmedialibmedia | |--BpMediaPlayerService | | |--create() | |--BnMediaPlayerService::onTransact() |------MediaPlayerService.cpp avmedialibmediaplayerservice |--create() | |--return new Client() | | |--MediaPlayerService::Client | | |--setDataSource | | | |--setDataSource_pre | | | |--MediaPlayerFactory::getPlayerType(this, url); | | | |这里,通过url来匹配合适的player类型 | | | |宏定义:GET_PLAYER_TYPE_IMPL | | | |其原理是 遍历 sFactoryMap ,(MediaPlayerService构造函数中就对其进行了初始,注册了几个内置的Factory到该表中) | | | |调用每一个factory的虚函数scoreFactory(), 表明这个factory对当前url的匹配分数, | | | |选取分数最高的一个factory,也就是最匹配的factory。 | | | |所以这里注册的NuplayerFactory,可以很容易的替换成其他Factory,框架很灵活。 | | | |--setDataSource_pre(player_type playerType) | | | |--mPlayer = createPlayer() | | | |--MediaPlayerFactory::createPlayer(playerType, mListener, mPid); | | | MediaPlayerFactory中的静态方法,创建Plyer, | | | 其内部通过传入的playerType类型,从sFactoryMap表中取对应的factory, | | | 比如之前注册的NuplayerFactory,来创建player | | |--sp<MediaPlayerBase> mPlayer; | | |--sp<MediaPlayerService> mService; | | |--sp<IMediaPlayerClient> mClient; | |--在MediaPlayerService中crate 的实际上是一个client,客户端 并且MediaPlayerService会把这个client加到 | SortedVector< wp<Client> > mClients;有序向量中记录 这个 client 自身就是一个 BnMediaPlayer, | 所以由 mediaplayer.cpp 中的 mPlayer的操作直接调用到这个client里面的实现 |--MediaPlayerService()构造函数 |--MediaPlayerFactory::registerBuiltinFactories(); |注册内置的 player工厂 | new NuPlayerFactory(); | new TestPlayerFactory(); | 这里将这这两个Factory注册进去,加入到对象 MediaPlayerFactory 中的KeyedVector<player_type, IFactory*> sFactoryMap | 我们可以在这里添加自己的Player, 在factory匹配分数的时候对 自定义的类型给出一个高的匹配分数,实现自定义的player, | 用以对某些特定格式使用自定义的player代替默认的Nuplayer |--instantiate() //在av/media/mediaserver/main_mediaserver.cpp 生成可执行文件,被.rc启动脚本记录,系统启动的时候会将这个程序运行,把media.player服务运行起来。 defaultServiceManager()->addService(String16("media.player"), new MediaPlayerService())
T1:player 耦合点 --MediaPlayerFactory::getPlayerType(this, url);
这里,通过url来匹配合适的player类型 宏定义:GET_PLAYER_TYPE_IMPL
其原理是 遍历 sFactoryMap ,(MediaPlayerService构造函数中就对其进行了初始化,注册了几个内置的Factory到该表中,目前只有一个Nuplayer可注册)
调用每一个factory的虚函数scoreFactory(), 表明这个factory对当前url的匹配分数,
选取分数最高的一个factory,也就是最匹配的factory。
所以这里注册的NuplayerFactory,可以很容易的替换成其他Factory,框架很灵活,哪一天google对这个Nuplayer不满意了,可能就再整一个新的player在这里注册进去。
T2:主要文件
------MediaPlayer.java basemediajavaandroidmedia java的class
------android_media_MediaPlayer.cpp basemediajni java 对应的jni转
------mediaplayer.cpp avmedialibmedia 没什么实在作用,一层包装
------IMediaPlayerService.cpp avmedialibmedia android典型的 binder 实现的服务,Bp+Bn,跨进程的方法调用,弱化进程概念,代之以组件的思想
------MediaPlayerService.cpp avmedialibmediaplayerservice Bn,真正的MediaPlayer工作的地方
------main_mediaserver.cpp avmediamediaserver 这里有main入口函数,这个会生成可执行程序mediaserver,列在系统的启动脚本.rc文件中,系统启动的时候会调用该可执行程序,把mediaPlayerserver服务启动起来。
最后
以上就是高贵乌冬面最近收集整理的关于android MediaPlayer 源码分析 1的全部内容,更多相关android内容请搜索靠谱客的其他文章。
发表评论 取消回复