短视频软件开发中 Android音视频编码基础

视频编码基础知识

关于视频常听码率,帧率,分辨率,它们分别是什么呢?

码率:

码率或码流率也就码流(Data Rate)是指视频文件在单位时间内使用的数据流量,通俗一点的理解就是取样率,是视频编码中画面质量控制中最重要的部分,一般用kb/s或者Mb/s表示。同样分辨率下,视频文件的码流越大,压缩比就越小,画面质量就越高。码流越大,说明单位时间内取样率越大,数据流,精度就越高,处理出来的文件就越接近原始文件,图像质量越好,画质越清晰,要求播放设备的解码能力也越高。
码流越大,文件体积也越大,其计算公式是文件体积=时间X码率/8。例如,网络上常见的一部90分钟1Mbps码流的720P RMVB文件,其体积就=5400秒×1Mb/8=675MB。
比特率是指每秒传送的比特(bit)数,单位为bps(Bit Per Second),比特率越高,传送的数据越大,音质越好,在视频领域,比特率常翻译为码率。比特率 =采样率 x 采用位数 x声道数。
  
码率类型,共有两种——动态码率(VBR)和固定码率(CBR)。所谓动态码率是指编码器在对图像进行压缩编码的过程中,根据图像的状况实时调整码率高低的过程,例如当图像中没有物体在移动时,编码器自动将码率调整到一个较低的值。但当图像中开始有物体移动时,编码器又自动将码率调整到一个较高的值,并且实时根据运动的剧烈程度进行调整。这种方式是一种图像质量不变,数据量变化的编码模式。   
固定码率是指编码器在对图像进行编码的过程中,自始至终采用一个固定的码率值,不论图像情况如何变化。这种方式是码率量不变,而图像质量变化的编码模式。在动态码率模式下,我们在硬盘录像机上设置的位率值称为“位率上限”。意思是我们人为设定一个编码码率变化的上限,可以低于,但不能高于。根据这个位率值,我们可以估算出一定时间内的存储容量的上限值。

RMVB视频文件中的VB,指的是VBR,即Variable Bit Rate的缩写,中文含义是可变比特率,它表示RMVB采用的是动态编码的方式,把较高的采样率用于复杂的动态画面(歌舞、飞车、战争、动作等),而把较低的采样率用于静态画面,合理利用资源,达到画质与体积可兼得的效果。

码率和采样率最根本的差别就是码率是针对源文件来讲的。

采样率

采样率(也称为采样速度或者采样频率)定义了每秒从连续信号中提取并组成离散信号的采样个数,它用赫兹(Hz)来表示。采样率是指将模拟信号转换成数字信号时的采样频率,也就是单位时间内采样多少点,一个采样点数据有多少个比特。

采样率类似于动态影像的帧数,比如电影的采样率是24赫兹,PAL制式的采样率是25赫兹,NTSC制式的采样率是30赫兹。当我们把采样到的一个个静止画面再以采样率同样的速度回放时,看到的就是连续的画面。同样的道理,把以44.1kHZ采样率记录的CD以同样的速率播放时,就能听到连续的声音。显然,这个采样率越高,听到的声音和看到的图像就越连贯。当然,人的听觉和视觉器官能分辨的采样率是有限的,基本上高于44.1kHZ采样的声音,绝大部分人已经觉察不到其中的分别了。

**帧率FPS **

FPS指每秒显示的图片数,或者GPU每秒能够更新的次数。帧率越高可以看到更加流畅的画面,同时文件大小会增加。我们人眼在30fps的时候就可以认为很流畅了,60fps可以有很好的体验了,再增大则对人眼来说意义不大。帧率会影响画面流畅度,与画面流畅度成正比:帧率越大,画面越流畅;帧率越小,画面越有跳动感。

GOP(Group of picture) 关键帧的周期

关键帧的周期,也就是两个IDR帧之间的距离,一个帧组的最大帧数,一般而言,每一秒视频至少需要使用 1 个关键帧。增加关键帧个数可改善质量,但是同时增加带宽和网络负载。

需要说明的是,通过提高GOP值来提高图像质量是有限度的,在遇到场景切换的情况时,H.264编码器会自动强制插入一个I帧,此时实际的GOP值被缩短了。另一方面,在一个GOP中,P、B帧是由I帧预测得到的,当I帧的图像质量比较差时,会影响到一个GOP中后续P、B帧的图像质量,直到下一个GOP开始才有可能得以恢复,所以GOP值也不宜设置过大。

同时,由于P、B帧的复杂度大于I帧,所以过多的P、B帧会影响编码效率,使编码效率降低。另外,过长的GOP还会影响Seek操作的响应速度,由于P、B帧是由前面的I或P帧预测得到的,所以Seek操作需要直接定位,解码某一个P或B帧时,需要先解码得到本GOP内的I帧及之前的N个预测帧才可以,GOP值越长,需要解码的预测帧就越多,seek响应的时间也越长。

**视频分辨率 **

视频分辨率指物理显示画面的宽度和高度即视频文件打开的尺寸属性,例如1920X960。分辨率:影响图像大小,与图像大小成正比:分辨率越高,图像越大;分辨率越低,图像越小。
看视频时的标清,高清,720P,这个和实际尺寸有啥关系?好像不同分辨率代表了不同清晰度真的是这样吗?
标清:分辨率在1280X720(720P)以下的视频格式,这个比较以高度720为界限,低于垂直分辨率720的为标清。
高清:垂直分辨率大于等于720,并且宽高比最少为16:9。不能低于1280X720。

分辨率不代表清晰度,它只是尺寸。

清晰度

在码率一定的情况下,分辨率与清晰度成反比关系:分辨率越高,图像越不清晰,分辨率越低,图像越清晰。

在分辨率一定的情况下,码率与清晰度成正比关系,码率越高,图像越清晰;码率越低,图像越不清晰。

在码率一定的情况下,分辨率在一定范围内取值都将是清晰的;同样地,在分辨率一定的情况下,码率在一定范围内取值都将是清晰的。

好的画质是分辨率、帧率和码率三者之间的平衡:

码率不是越大越好

如果不做码率大小上的限制,那么分辨率越高,画质越细腻;帧率越高,视频也越流畅,但相应的码率也会很大,因为每秒钟需要用更多的数据来承载较高的清晰度和流畅度,需要的带宽,费用也越大。

特定码率帧率越高,编码器就必须加大对单帧画面的压缩比,也就是通过降低画质来承载足够多的帧数。如果视频源来自摄像头,24FPS已经是肉眼极限,所以一般20帧的FPS就已经可以达到很好的用户体验了。

3D游戏的帧率越高越流畅,因为游戏追求高帧率的目的是为了尽可能让3D模型渲染出来的运动效果更加接近真实运动轨迹,所以帧率越高越好。但对摄像头而言,它要采集的目标是真实世界的物体,真实世界本来就没有刷新率的说法,所以这个理论不适用。

编码:

既然码本来就是一种数据,为什么还需要编码呢?
从拍照设备采集的原始视频数据量非常大,编码处理之后会显著减小视频的大小,便于传输,所以无论是为了存储或者为了传输,亦或是为了加密,修改都必须对视频进行编码,所以编码相当于对视频进行压缩(对音频,图像等也存在压缩,这里重点说明视频的压缩)。
举个例子:未经压缩的电视品质视讯资料的位元率高达216Mbps,压缩之后可以减小百倍,甚至千倍。
解码,编码之后的视频通过解码还原视频的原貌。解码过程中能够得到码流片段,可以对视频流进行处理。

为什么视频可以压缩:

核心思想就是去除冗余信息,画面中有很多冗余信息。
空间冗余:图像相邻像素之间有较强的相关性
时间冗余:视频序列的相邻图像之间内容相似
编码冗余:不同像素值出现的概率不同
视觉冗余:人的视觉系统对某些细节不敏感
知识冗余:规律性的结构可由先验知识和背景知识得到

帧内压缩和帧间压缩

帧内(Intraframe)压缩也称为空间压缩 (Spatial compression),是最早的一种压缩方式,当压缩一帧图像时,仅考虑本帧的数据而不考虑相邻帧之间的冗余信息,这实际上与静态图像压缩类似。帧内一般采用有损压缩算法,由于帧内压缩时各个帧之间没有相互关系,所以压缩后的视频数据仍可以以帧为单位进行编辑。帧内压缩一般达不到很高的压缩。
帧间(Interframe)压缩是基于许多视频或动画的连续前后两帧具有很大的相关性,或者说前后两帧信息变化很小的特点,也即连续的视频其相邻帧之间具有冗余信息,根据这一特性,压缩相邻帧之间的冗余量就可以进一步提高压缩量,减小压缩比。帧间压缩也称为时间压缩(Temporalcompression),它通过比较时间轴上不同帧之间的数据进行压缩。帧间压缩一般是无损的。帧差值(Frame differencing)算法是一种典型的时间压缩法,它通过比较本帧与相邻帧之间的差异,仅记录本帧与其相邻帧的差值,这样可以大大减少数据量。现在的压缩标砖都是帧间压缩标准。

编解码种类(硬件编码,软件编码):

硬编码:
用设备GPU去实现编解码,这样可以减轻CPU的压力。

软编码:
让CPU来进行编解码,在c层代码来进行编解码,因为c/c++有很多好的编解码库。

软硬编码对比:
硬编的好处主要在于速度快,而且系统自带不需要引入外部的库,但是特性支持有限,而且硬编的压缩率一般偏低,而对于软编码来说,虽然速度较慢,但是压缩率比较高,而且支持的H264特性也会比硬编码多很多,相对来说比较可控。硬编码会受硬件设备支持的影响。

在Android 4.1之前没有提供硬编解码的API,所以基本都是采用开源的那些库,比如著名的FFMpeg实现软编解码。但是通常情况下,同一平台同一硬件环境,硬编码的速度快于软件编码,软编码使用CPU来进行计算,会消耗一些app的运算效率。在Android4.1出来了一个新的API:MediaCodec可以支持硬编解码。MediaCodec可以支持对音频和视频的编解码,我们就要学会使用它来进行音频的编解码操作。

数据编码(压缩)分类:

无损压缩(Lossless)
压缩前解压缩后图像完全一致
压缩比低较小(2:1~3:1)
有损压缩(Lossy)
压缩前解压缩后图像不一致
压缩比较大(10:1~20:1)

有哪些编码的标准:

常见的视频编码标准:
H.264/AVC,HEVC/H.265,VP8,VP9,FFmpeg,MPEG-2,MPEG-4,WMV
常见的音频编码标准
MP3,AAC,WMA,PCM,MPEG标准也可以用于音频编码(aac就用了MPEG标准)。

容器(特定格式视频或音频)

所谓容器就是对视频,音频,字幕,弹幕等其他信息进行封装在一起的标准,简单点说就是平时各种视频格式。视频的常见格式avi,mov, ogg, 3gp, mp4, rm, rmvb, flv, mkv, ts, asf, wmv, mpg, mpeg, dat, vob等。音频也有相应的容器wav,pcm,acc, mp3等。
AVI 格式(后缀为 .avi)
DV-AVI 格式(后缀为 .avi)
QuickTime File Format 格式(后缀为 .mov)
MPEG 格式(文件后缀可以是 .mpg .mpeg .mpe .dat .vob .asf .3gp .mp4等)
WMV 格式(后缀为.wmv .asf)
Real Video 格式(后缀为 .rm .rmvb)
Flash Video 格式(后缀为 .flv)
Matroska 格式(后缀为 .mkv)
MPEG2-TS 格式 (后缀为 .ts)

颜色模型:

颜色模型通常指的是RGB和YUV。
RGB颜色空间:
RGB一般用在电视,显示器等设备上,而非科学研究中,因为三种颜色分量放在一起表示,相互干扰,不便处理,而且会造成存储空间的浪费。
YUV颜色空间:
其中Y代表亮度值,U和V表示色度,代表了颜色的色调Cr和饱和度Cb。
与RGB不同,其优点是亮度Y和色度UV是相互独立的,占用频宽小。如果只有Y信号,就是黑白彩色图像。
YUV的原理是因为人眼对颜色细节的分辨能力远远低于对亮度细节分辨能力,所以可以把几个相邻像素不同颜色值当做相同的颜色值来处理,以减少存储容量,从而压缩数据。按照不同的YCbCr的比率,可以分为YUV420、YUV422、YUV411和YUV444。YUV可以与RGB通过矩阵相互转换。
Android原始视频格式YUV,NV12,NV21,YV12,YU12(I420)

**位深度 **

每一个像素用多少位表示,位数就叫做位深度,数值越大,可用的颜色越多,颜色也越逼真。例如位深度为8则一个像素可用的颜色为256种。

编解码器可以处理的数据类型

编解码器可以处理三种类型的数据:

  • 压缩数据(即为经过H254 ,H265等编码的视频数据或AAC等编码的音频数据)
  • 原始音频数据,
  • 原始视频数据。

三种类型的数据均可以利用ByteBuffers进行处理,但是对于原始视频数据应提供一个Surface以提高编解码器的性能。Surface直接使用本地视频数据缓存(native video buffers),而没有映射或复制数据到ByteBuffers,因此,这种方式会更加高效。在使用Surface的时候,通常不能直接访问原始视频数据,但是可以使用ImageReader类来访问非安全的解码(原始)视频帧。这仍然比使用ByteBuffers更加高效,因为一些本地缓存(native buffer)可以被映射到 direct ByteBuffers。当使用ByteBuffer模式,你可以利用Image类和getInput/OutputImage(int)方法来访问到原始视频数据帧。

压缩缓存

输入缓存(对于解码器)和输出缓存(对于编码器)中包含由多媒体格式类型决定的压缩数据。对于视频类型是单个压缩的视频帧。对于音频数据通常是单个可访问单元(一个编码的音频片段,通常包含几毫秒的遵循特定格式类型的音频数据),但这种要求也不是十分严格,一个缓存内可能包含多个可访问的音频单元。在这两种情况下,缓存不会在任意的字节边界上开始或结束,而是在帧或可访问单元的边界上开始或结束。

原始音频缓存(Raw Audio Buffers)

原始的音频数据缓存包含完整的PCM(脉冲编码调制)音频数据帧,这是每一个通道按照通道顺序的一个样本。每一个样本是一个按照本机字节顺序的16位带符号整数(16-bit signed integer in native byte order)。

原始视频缓存(Raw Video Buffers)

在ByteBuffer模式下,视频缓存(video buffers)根据它们的颜色格式(color format)进行展现。你可以通过调用getCodecInfo().getCapabilitiesForType(…).colorFormats方法获得编解码器支持的颜色格式数组。视频编解码器可以支持三种类型的颜色格式:

本地原始视频格式(native raw video format):这种格式通过COLOR_FormatSurface标记,并可以与输入或输出Surface一起使用。
灵活的YUV缓存(flexible YUV buffers)(例如:COLOR_FormatYUV420Flexible):利用一个输入或输出Surface,或在在ByteBuffer模式下,可以通过调用getInput/OutputImage(int)方法使用这些格式。
其他,特定的格式(other, specific formats):通常只在ByteBuffer模式下被支持。有些颜色格式是特定供应商指定的。其他的一些被定义在 MediaCodecInfo.CodecCapabilities中。这些颜色格式同 flexible format相似,你仍然可以使用 getInput/OutputImage(int)方法。
从Android 5.1(LOLLIPOP_MR1)开始,所有的视频编解码器都支持灵活的YUV420缓存(flexible YUV 420 buffers)。

Android 从API 16提供了Mediacodec类以便开发者更加灵活的处理音视频的编解码,通常与MediaExtractor, MediaSync, MediaMuxer, MediaCrypto, MediaDrm, Image, Surface, 以及AudioTrack一起使用。

猜你喜欢

转载自blog.csdn.net/q3557873521/article/details/107814888