Audio播放流程(一)---MediaPlayer流程
1. 对于APP而言要播放一个MP3很简单,只需要如下几步:
mp3 = MediaPlayer.create(MainActivity.this,R.raw.gem);
mp3.prepare();
mp3.start(); //开始播放
如上即可完成,But,Android系统在后台需要完成哪些更复杂的逻辑呢 ?
2. Android MediaPlayer流程
第一步: MediaPlayer类会先加载"media_jni"的库,然后调用native_init进入native完成初始化
static {System.loadLibrary("media_jni");native_init();}
第二步:创建MediaPlayer的Java端对象
public static MediaPlayer create(Context context, int resid,AudioAttributes audioAttributes, int audioSessionId) {try {AssetFileDescriptor afd = context.getResources().openRawResourceFd(resid);if (afd == null) return null;//先创建一个对象MediaPlayer mp = new MediaPlayer();//设置音频属性,例如:flag,source,formatfinal AudioAttributes aa = audioAttributes != null ? audioAttributes :new AudioAttributes.Builder().build();//为Java端对象设置属性 mp.setAudioAttributes(aa);//为Java端对象设置会话idmp.setAudioSessionId(audioSessionId);//设置需要播放的音频文件大小,偏移等到Native中mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());afd.close();//调用preparemp.prepare();return mp;...}
再看看mediaplayer的构造方法:
public MediaPlayer() {super(new AudioAttributes.Builder().build());Looper looper;//如果调用MediaPlayer构造方法的线程有自己的looper,就用子线程的looper,否则使用主线程的looperif ((looper = Looper.myLooper()) != null) {mEventHandler = new EventHandler(this, looper);} else if ((looper = Looper.getMainLooper()) != null) {mEventHandler = new EventHandler(this, looper);} else {mEventHandler = null;}mTimeProvider = new TimeProvider(this);mOpenSubtitleSources = new Vector<InputStream>();/* Native setup requires a weak reference to our object.* It's easier to create it here than in C++.*/native_setup(new WeakReference<MediaPlayer>(this));}
总结下目前为止,JAVA端下发到JNI的native方法:
来到native看下代码的流程
frameworks\base\media\jni\android_media_MediaPlayer.cpp
native_setup的本地实现
android_media_MediaPlayer_native_setupJNIMediaPlayerFactory *jniMediaPlayerFactory = new JNIMediaPlayerFactory();sp<MediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this);//创建native的MediaPlayer对象mp = new MediaPlayer();//为native的对象设置监听mp->setListener(listener);//将native对象的保存到Java对象的成员mNativeContext中setMediaPlayer(env, thiz, mp);
setDataSource的本地实现
android_media_MediaPlayer_setDataSourceFD//获取native的mediaplayer的对象sp<MediaPlayer> mp = getMediaPlayer(env, thiz);//将java端的文件描述符转化为本地的描述符int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);//这条语句是指,如果mp->setDataSource(fd, offset, length)这个方法执行出粗,将会抛出相应的异常process_media_player_call( env, thiz, mp->setDataSource(fd, offset, length), "java/io/IOException", "setDataSourceFD failed." );
BTW,mp->setDataSource将会调用到mediaplayerservice完成相应的操作
prepare的本地实现
static void
android_media_MediaPlayer_prepare(JNIEnv *env, jobject thiz)
{sp<MediaPlayer> mp = getMediaPlayer(env, thiz);if (mp == NULL ) {jniThrowException(env, "java/lang/IllegalStateException", NULL);return;}// Handle the case where the display surface was set before the mp was// initialized. We try again to make it stick.sp<IGraphicBufferProducer> st = getVideoSurfaceTexture(env, thiz);mp->setVideoSurfaceTexture(st);process_media_player_call( env, thiz, mp->prepare(), "java/io/IOException", "Prepare failed." );
}
这里的mp->prepare()实现如下:
status_t MediaPlayer::prepare()
...
status_t ret = prepareAsync_l();//这里的默认mStreamType是AUDIO_STREAM_MUSIC,当然你可以手动设置改变它---->mPlayer->setAudioStreamType(mStreamType);---->mPlayer->prepareAsync();
...
}
同理这里的prepareAsync_l会调度到mediaplayerservice中去;
然后我们来看最后一个native的方法----start
status_t MediaPlayer::start()
{ALOGV("start");...//这里的mloop默认是false的mPlayer->setLooping(mLoop);mPlayer->setVolume(mLeftVolume, mRightVolume);mPlayer->setAuxEffectSendLevel(mSendLevel);mCurrentState = MEDIA_PLAYER_STARTED;ret = mPlayer->start();...return ret;
}
ok,这里再做一下总结,MediaPlayer发送到MediaPlayerService中去执行的方法如下:
Audio播放流程(一)---MediaPlayer流程相关推荐
- 视频编解码(十二):播放器编解码流程source、demux、decoder、output
一.播放器编解码流程source.demux.decoder.output 说白了播放器大致分为4大部分:source.demux.decoder.output. 1.source: 数据源,数据的来 ...
- Audio播放音频 --- 建立播放通道
Audio播放音频 - 建立播放通道 简介 虽然文章标题是<建立播放通道>,其实播放通道早在AudioPolicyManager解析configuration配置文件时,openoutpu ...
- android播放器:MediaPlayer ExoPlayer ijkplayer
视频播放主要涉及解码流程,主要分为硬解码和软解码.在Android设备硬件支持的情况下优先使用Android设备的硬件解码,减少CPU的占用,更加省电. 软件解码:通过软件让CPU来对视频进行解码处理 ...
- js监听audio播放完毕
js监听audio播放完毕 <!DOCTYPE html> <html> <head><meta charset="UTF-8">& ...
- 【Android 安装包优化】APK 打包流程 ( 文件结构 | 打包流程 | 安装流程 | 安卓虚拟机 )
文章目录 一.APK 文件结构 二.APK 打包流程 三.APK 安装流程 四.安卓虚拟机 一.APK 文件结构 Android 应用的安装包时 以 " .apk " 为后缀的 A ...
- (转)CentOS 7系统详细开机启动流程和关机流程
CentOS 7系统详细开机启动流程和关机流程 原文:http://blog.csdn.net/yuesichiu/article/details/51350654 名称 bootup - 系统启动流 ...
- uboot流程——uboot启动流程
[uboot] (第五章)uboot流程--uboot启动流程 2016年11月07日 20:12:07 阅读数:2230 以下例子都以project X项目tiny210(s5pv210平台,arm ...
- Activiti第二篇【管理流程定义、执行任务和流程实例、流程变量】
tags: Activiti 上篇Activiti只是一个快速入门案例,这篇就讲定义.部署.查看任务等等的一些细节[涉及到的数据库表.对象等等]... 管理流程定义 管理流程定义主要涉及到以下的4张表 ...
- 第5篇:Flowable快速工作流脚手架Jsite_请假实战_部署流程和发起流程
接上一篇:第4篇:Flowable快速工作流脚手架Jsite_启动项目 https://blog.csdn.net/weixin_40816738/article/details/103388465 ...
- java工作流引擎Jflow流程事件和流程节点事件设置
流程实例的引入和设置 关键词: 开源工作流引擎 Java工作流开发 .net开源工作流引擎 流程事件 工作流节点事件 应用场景: 在一些复杂的业务逻辑流程中需要在某个节点或者是流程结束后做一些 ...
最新文章
- Java Radom类的使用方法实例
- 对象并不一定都是在堆上分配内存的
- pytorch实现图像分类代码实例
- 权威指南之脚本化jquery
- 趣图图解 SOLID 软件开发原则
- adobe reader打开pdf闪退或自动关闭
- 似乎可以破解软件代码
- “易班”学生管理平台小项目 万字总结 泪目!!!
- 台式计算机亮度怎么调节快捷键,详解电脑调亮度快捷键如何调整屏幕亮度呢?...
- STM32F103X hal RTThread rtc驱动支持日期保存
- 3d Max人物动画学习笔记(二)蒙皮
- 学习FPGA绝佳网站推荐
- 屏幕适配以及ui切图规范和命名标准
- 一男老师每日百词转载+连载(3)
- 从零开始搭建springboot框架
- 基于springboot的校园二手交易系统-JAVA【毕业设计、论文、源码、开题报告】
- 【智力题】13 个球一个天平,现知道只有一个和其它的重量不同,问怎样称才能用三次就找到那个球?
- OSError: [Errno 28] No space left on device以及查看系统分区情况
- SaaS、PaaS、IaaS、aPaaS、iPaaS、RaaS、RPAaaS,傻傻分不清楚?
- 深入理解android的读后感_《陪孩子长大》读后感