Android多媒体浅析

时间:2021-05-30 20:35:55

一个月没写博客了 说好的一周一篇泡汤了 不过想想也是了 有时候周六加班 周日不想动 平常下班晚上9点 11点多又要睡觉 木有太多时间 但还是要写 毕竟再慢也要往前走 牢骚发到这吧。

今天讲的是Android的多媒体,感觉这块知识和第一年工作的项目以及现在公司的项目是一一相关的,后面也会举出两个测试遇到的bug例子来总结。


先说说这篇文章的结构:

调用关系-->MediaPlayer和MediaRecorder的状态控制图-->surface简单介绍-->基本实现方法-->测试中的bug例子


调用原理:

   (图片是sundy提高教程多媒体的原理截图 本人膜拜的大神之一)                                         

Android多媒体浅析



例子:播放一个mp3文件

MediaPlayer装载文件之后,调用native层的MediaPlayer,然后通过binder机制调用MediaPlayerService服务,由于音频文件是经过压缩的,所以MediaPlayerService服务调用OpenCV库把mp3文件编码成原始音频流,然后返回给AudioTrack,接着进一步给AudioFlinger处理,比如AudioResample重新编码成码率相同的音频流,最后通过HAL层调用底层硬件播放出去。

例子:播放一个avi文件

和mp3文件大体相同,不同的是经过OpenCV解码后的原始视频流是直接给UI播放的,并不需要像音频的繁杂处理。

例子:录音

MediaRecorder同样走到MediaPlayerService中,经过编码直接保存到文件里面了。

其他:

AudioMixer是合成音频用的,比如多重音效混合

ToneGenerator是系统的一些音效(没用过)

AudioTrack为了减少音频播放的步骤而定义的类

(谢谢sundy讲解的多媒体原理 对于一个测试来说够用了^.^)


MediaPlayer控制流程:

Android多媒体浅析

有点多,直接挑主线。

new一个MediaPlayer之后是Idle状态,reset()方法之后也是Idle状态;setDataResource之后是Initialized状态,此时可以prepare或者prepareAsync;

因为prepare会堵塞主线程,所以建议使用prepareAsync,并监听prepareListener方法,准备完成后才start方法。

播放完成release,那么就是end状态。

上面就是基本播放流程,然后播放过程有多种状态,需要我们去自己重写回调方法。

OnErrorListener:播放错误需要捕获的方法

OnPrepareListener:异步加载完成后触发的方法

OnBufferingUpdateListener:进度的回调方法

OnCompletionListener:播放完成的方法

...等等

Android多媒体浅析

然后录音的流程控制图:

和播放大体相似,注意的是实现的时候要加上录音权限。


surface和播放视频的关系:

先简单介绍一下surfaceView surface以及surfaceHolder的关系

surface:就是一个视图,在学习window的时候,就说了一个window对应一个surface,显示具体的内容的类,上面自带一个canvas画布,决定显示什么数据

surfaceView:里面装着surface,显示在哪里由这个决定,决定surface显示在哪里

surfaceHolder:一个操作surface的接口,决定surface怎么显示

播放视频的时候surfaceHolder需要添加addCallback方法,重写里面的三个函数

surfaceDestroyed

surfaceCreated

surfaceChanged

注意的是只有surfaceCreated方法被回调的时候surface才会准备好,才可以显示内容


基本实现方法:

播放音频:

1.实例化一个MediaPlayer

2.setDataSource,指定播放来源

3.prepare准备工作,然后start(),如果是create创建的则不要prepare

4.监听一些事件回调

5.最后别忘了release

录音:

1.实例化一个MediaRecorder

2.设置声音来源 比如MIC

3.设置输出格式

4.设置编码方式

5.设置输出目录

6.prepare()之后并start()

视频:

1.布局文件声明SurfaceView

2.getHolder得到SurfaceHolder,并设置相关属性

3.给Holder添加回调方法,只有在surface创建的时候给mediaplayer设置display属性,实现播放视频

4.重写一个回调函数

5.用videoview的最简单实现,但是没有自己定义的*


对一个测试来说:

先补充一个知识:soundPool适用于加载简单音效的控件,会开辟一个新的线程,允许多个音效同时执行,注意不能播放过大的音频

对一个测试人员来说,了解了原理及相关的控制流程之后,可能出现的问题的地方,比如播放完成不release造成的内存泄漏(开发没这么蠢吧),比如用soundPool加载大容量的音频,比如主线程prepare,导致后续版本如果代码量大带来的隐患...再比方说播放器音画不同步,surface没有加载就setDisplay的可能出现的bug...