IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> android MediaPlayer 源码分析 1 -> 正文阅读

[移动开发]android MediaPlayer 源码分析 1

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如何解复用,解码,渲染,已经其中涉及到的音视频数据流转,控制,驱动线程模型,不涉及。大图:


?

?上图的文字模式:

mediaplayer
|------MediaPlayer.java 
|    \base\media\java\android\media
|        |--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 
|    \base\media\jni
|        |--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?? 
|      \av\media\libmedia
|        |--MediaPlayer()
|        |--setDataSource()
|        |    |--sp<IMediaPlayer> player(service->create(this, mAudioSessionId)
|        |    |--attachNewPlayer() 
|        |    | sp<IMediaPlayer>? mPlayer
|        |    |--player->setDataSource
|        |--prepare()
|        |    |--prepareAsync_l()
|        |    |    |--mPlayer->setParameter
|        |    |    |--mPlayer->prepareAsync()
|------IMediaPlayerService.cpp 
|      \av\media\libmedia
|        |--BpMediaPlayerService
|        |    |--create()
|        |--BnMediaPlayerService::onTransact()
|------MediaPlayerService.cpp 
    \av\media\libmediaplayerservice
        |--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?? \base\media\java\android\media java的class
? ? ------android_media_MediaPlayer.cpp??\base\media\jni? ?java 对应的jni转
? ??------mediaplayer.cpp??\av\media\libmedia? 没什么实在作用,一层包装
? ? ------IMediaPlayerService.cpp? \av\media\libmedia android典型的 binder 实现的服务,Bp+Bn,跨进程的方法调用,弱化进程概念,代之以组件的思想?
? ? ------MediaPlayerService.cpp???\av\media\libmediaplayerservice Bn,真正的MediaPlayer工作的地方
? ? ------main_mediaserver.cpp??av\media\mediaserver? 这里有main入口函数,这个会生成可执行程序mediaserver,列在系统的启动脚本.rc文件中,系统启动的时候会调用该可执行程序,把mediaPlayerserver服务启动起来。
? ?

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-17 15:30:31  更:2021-08-17 15:30:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 10:15:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码