作者|胡锐,单位:中国移动智能家居运营中心实验室指南随着智能手机和5G技术的普及,视频播放需求快速增长,碎片化时间扫一扫小视频,熬夜看电视剧被视频玩一点也不为过。毫不夸张地说,视频一直伴随着你我。我们经常听到一些专业术语,比如MP4、MKV、H264、H265、AAC、1080p、60fps等,它们到底是什么意思呢?视频播放的过程是怎样的?当今市场份额最大的Android平台播放器框架是如何设计的?本文将带你了解这些知识点。Part01常用技术术语我们通常说的MP4、MKV、WMV是一种视频文件格式,业界称之为容器,音视频文件的数据都存储在容器中,每个容器都有固定的格式。其中,MP4是最常见的国际格式,可以在普通的播放软件中使用和播放,应用广泛。安卓手机用相机录制的视频一般都是MP4格式。MKV最大的特点是可以容纳多种不同类型的编码视频、音频和字幕流,俗称通用媒体容器。WMV是微软公司推出的一种流媒体格式,是ASF格式的升级和扩展。在同等视频质量下,WMV格式体积非常小,非常适合在网络上播放和传输。通过工具或命令将WMV文件转换为相同分辨率的MP4文件后,文件体积会变大。下图可以大致表示文件格式和数据的关系。视频原始数据为YUV格式,音频原始数据为PCM格式。这两种格式的数据会占用大量的存储空间。为了解压缩音视频数据占用的存储空间,需要对音视频数据进行压缩,业界称之为编码。播放音视频文件时,需要对压缩后的音视频文件进行解压,也就是解码。编解码是按照一定的规范进行的,不同的规范有不同的名称,如H264、H265、AAC等。也就是说,H264、H265、AAC都是编解码格式。其中H265和H264都是视频编解码格式,都是基于宏块进行编码。其中H264最大支持16*16个宏块,而H265最大支持64*64个宏块,所以H265比H264更详细更清晰。在像素一致的情况下,H265的压缩率会比H264高。因为H265具有更高的压缩比,H265占用的存储空间更少,从而达到节省带宽和流畅播放的目的。这也是目前流行的高清电视剧采用H265编码的原因。我们经常听到的屏幕比例是指视频屏幕宽度与高度的比例。生活中常见的比例是16:9和4:3。我们也经常听到标清、高清、超高清等名词。对应的专业术语是分辨率。720p以下为标清,720p、1080p为高清,4k、8k称为超高清。720p和1080p到底是什么意思?说到这里,首先要说说视频分辨率的概念。分辨率是指视频宽度和高度的像素值,单位为Px。通常视频分辨率的数值纵横比应等于纵横比,否则视频文件会出现黑边。标准的1080p分辨率为1920×1080,即宽1920像素,高1080像素。分辨率越高,视频越清晰。30fps和60fps指的是帧率。视频是由一张一张的图片组成的。视频播放就是将图片以固定的速率一张一张(一张图片也可以简单理解为一帧)展示给观众,比如每秒显示30帧(30fps),或者每秒显示60帧(fps),让观众感觉动作是连续的。因此,帧率就是每秒显示的帧数。帧率越高,视频越流畅。目前主流的视频帧率为60帧。目前主流安卓系统都支持H264和H265硬件编解码,可以很好的满足用户的需求。并且在Android系统上,为开发者预留了方便简单的接口来实现编解码,比如使用MediaRecorder实现视频录制(编码场景),使用MediaPlayer实现播放(解码场景)。MediaRecorder和MediaPlayer之间的接口非常简单易用。并且屏蔽了底层的编解码逻辑,对开发者非常友好。下面简单介绍一下视频播放的过程。Part02视频播放流程播放器播放视频的主要流程如下:1.读取视频文件,解析文件格式,即获取容器格式。Android平台的Media框架的DataSource中有一个sniff函数,会调用每个Extractor函数的sniff,每个Extractor的sniff函数都会返回一个分数,DataSource最终会选择分数最大的Extractor;2.使用对应的容器格式解析器(Android平台名为Extractor)解析视频文件,获取metadata、Audiotrack、videotrackindex和音视频编码格式,如果是MP4文件,会使用Mp4Extractor来解析在Android平台上分析文件;3、调用相应的解码器对音视频数据进行解码,在Android平台上是通过MediaCodec调用OMX或者C2解码器插件进行解码,通过MediaCodec返回解码后的数据;4、对解码后的数据进行音视频同步,必要时进行丢帧处理。一般在做音视频同步的时候,视频是和音频同步的,Android平台也是这样做的。具体方法是将解码后的视频时间戳与音频时间戳进行比较。如果视频时间戳和音频时间戳的差值大于某个设定值比如200ms,则丢弃当前视频帧;5.渲染音视频,Android平台解码器解码后的音频数据会交给SurfaceFlinger进行渲染,解码后的音频数据会经过AudioTrack处理,最终输出到speaker。现在我们对一个视频播放器的主要流程有了一个大致的了解,但是作为一个勤奋的搬砖人,我一直想自己写一个视频播放器,体验一下自己的成就。下面简单介绍一下如何在Android平台上编写一个视频播放器。简单的视频播放器。Part03在Android上实现最简单的播放器其实在Android上写一个视频播放器非常简单。使用Android提供的MediaPlayerJava类可以轻松实现播放器。示例代码:Stringurl=https://www.xxx.com/video/test.mp4MediaPlayerplayer=newMediaPlayer();player.setDataSource(url);player.prepare();player.setDisplay(surfaceView.getHolder());player.start();你没有看错,就是这么简单。作为一个热爱研究技术的小伙伴,一定很好奇,AndroidMediaPlayer内部是如何实现的?Part04AndroidMeiaPlayer播放器架构在Android平台上,Java层的MediaPlayer只提供对外暴露的接口。其实真正的逻辑实现是在NativeMediaSever中。MediaPlayer的setDataSource会触发NativeIPC请求服务端创建播放器实例,prepare会触发服务端寻找合适的容器解析器(MediaExtractor),解析得到需要的解码器信息,所以prepare比较耗时,start会触发服务在最后创建对应的解码器,开始解码,然后同步音视频,最后显示。MediaCodec可以被视为与OMX或C2解码器插件交互的解码器组件。在onInputBufferAvailable回调中给解码器送数据,通过queueInputBuffer给解码器提供数据。在onOutputBufferAvailable回调中处理解码数据,通过releaseOutputBuffer规划输出缓冲区给解码器。在Android平台上,除了MediaPlayer之外,还有很多开源的播放器框架可供我们使用。下面用一个表格来简单介绍一下。Part05常见的开源播放器Part06Android音视频的未来音视频技术在数字时代永远不会过时,需求也会越来越旺盛。我们在工作中参加视频会议,在生活中看小视频,用手机看剧,微信视频通话,进出建筑物人脸识别等等,都与音视频技术息息相关。随着5G技术的发展和普及,视频场景越来越多。同时,随着元宇宙概念的流行,VR和AR被推到了风口浪尖,而VR和AR又与音视频息息相关。目前市面上的VR一体机基本上都是安卓系统。笔者相信,音视频的应用场景将会更多,音视频技术也必将为人类的数字生活增添更多色彩。
