Android 音视频开发之音视频编码原理
Posted 殇神马
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 音视频开发之音视频编码原理相关的知识,希望对你有一定的参考价值。
一、前言
在上一篇Android音视频开发之音视频基础知识文章中,我们学习了播放一个视频的流程:解协议、解封装、解码、音视频同步、音视频数据的渲染;
其中解码是非常关键的一步,那为什么要进行解码,所谓的解码就是音视频编码数据的解码,那为什么视频文件中的音视频数据是编码后的数据,而不是音视频原始数据这是因为音视频原始数据,这是因为音视频原始数据是非常大的,所谓编码,就是对视频的原始图像数据,音频数据进行压缩,压缩之后再按照封装格式规范,封装成一个视频文件,这样可以大大降低视频文件的大小,便于视频的存储以及传输;
二、图像的表示
(1)RGB表示
一个图像可以由RGB三原色组成,比如我们在android中Bitmap的色彩空间模式
有ARGB_8888,ARGB_4444,RGB_565,ALPHA_8;分别就是一个像素是32位(4个字节),16位(2个字节),16位(2个字节),8位(1个字节);
如一张1280720的ARGB_8888图像,大小是1280720*4≈3.5M,这个是一张图片占用的内存大小,所以一张图片的裸数据都是比较大的,直接在网络中传输或者存储到本地不太可能,所以出现了图像的压缩格式,比如PNG、WEBP、JPEG等;但是这种压缩不能直接用于视频压缩,对于视频来说还有时域上的因素要考虑,也就是说不尽要考虑一张图像的编码,还要考虑多帧图像之间的联系,能进一步减少视频;
(2)YUV表示
对于视频帧的裸数据其实更多的是YUV数据格式的表示,YUV主要应用于优化彩色视频信号的传输,且能够兼容黑白电视,与RGB相比,YUV只需占用极少的频宽(RGB需要三个独立的的视频信号同时传输);YUV中的Y代表明亮度,也称灰阶值;U与V表示的则是色度(色调和饱和度),也可记作YCbCr,如果只有Y数据,则表示的图像就是黑白的;
YUV的采样方式有三种:
1.YUV 4:4:4采样,每一个Y对应一组UV分量
2.YUV 4:2:2采样,每两个Y共用一组UV分量
3.YUV 4:2:0采样,每四个Y共用一组UV分量
我们常见的NV21和I420格式都是属于YUV420,但是NV21属于YUV420SP,而I420属于YUV420P;
一帧1280720的视频帧,用YUV420P格式表示,数据大小为1280720*3/2≈1.3M
,如果fps(帧率)是30,按照一般电影90分钟来计算,则一部YUV420P电影,约为208G,所以仅用这种方式来存储电影肯定是不行的,更别说在网络上通过流媒体协议传输播放了,所以需要进行视频编码(视频压缩);
三、视频编码
视频编码就是一种特定的压缩技术,将视频中的图像数据压缩成视频码流,音频数据压缩成音频码流,从而大大降低视频文件的大小;
当然通常我们说视频编码,通常指的是视频中的图像数据的编码,因为一个视频中,图像编码数据占了视频数据的绝大部分,音频数据部分其实占的很少;
视频是连续的图像序列,由连续的帧构成,一帧即一幅图像,由于人眼的视觉暂留效应,当帧序列以一定的速率播放时,我们看到的就是动作连续的视频,一般帧率(FPS)得有二三十,也即一秒有二三十帧,所以一个视频如果不经过编码,数据量是非常巨大的。
原始视频压缩是为了去除冗余信息,同一副图像的临近像素之间有着相关性,相邻图像之间内容也存在相似,所以有大量的数据冗余,包括空间冗余和时间冗余。
预测编码
预测编码的目的就是为了去除空间冗余和时间冗余,同一副图像的像素之间有着空间相关性,相邻图像之间有着很强的时间相关性,针对空间冗余,可以使用帧内预测编码,对于时间冗余有基于运动估计和运动补偿的技术的帧间预测编码;
通过预测可以,可以得到实际实际像素值和预测像素值之间的差值,解码器通过采用与编码器完全相同的预测方法,得到完全相同的预测值,然后用解码出来的预测残差与预测值相加就得到重建图像;
帧内预测(帧内编码)
每一幅图像(YUV数据)被分成很多个宏块,颜色相近的区域,块的大小比较大,颜色差别比较大的区域,块的大小比较小;比如一个宏块的大小是44个像素,这个时候一个宏块就是44=16个像素,帧内编码不是把16个像素全部保留,而是只保留最上面一行,和左边一行,这里就是(4+4-1=7个像素),解码的时候就是根据这7个元素按照一定的算法推出整个宏块内(16个元素)的其他像素,而编码后的数据就少了
16-7=9个像素,对于颜色相近的区域,也即较大的宏块比如16*16=256像素的宏块,帧内编码之后就保存了16+16-1=31个像素,减少了256-31=225个像素,所以帧内编码可以大大减少图像数据大小;
帧间预测(帧间编码)
一个视频相邻的图像之间有着很强的相似性,即时间冗余,比如一分钟的视频,有十几秒画面是不动的,或者有很多一部分图像面积是不动的;所以就有了帧间编码,对于连续的图像,对第一幅图像不做改变,保存原本的像素数据,然后以此图像为基准,对另外的图像使用公式计算来做运动预测,即把第一幅图像的某个像素值,经过公式计算后,预测出第二个图像指定位置的像素值,以此类推,得到一整副图像的像素值;这里要注意的是,其实不是根据公式直接计算出图像数据,因为
没有任何算法能够保证能够保证预测出来的图像的准确性,因此帧间编码不是为了得到预测值,而是得到差值;
因为差值的绝对值都很小,数值小,到编码阶段编码压缩的数据量更小,从而压缩效率更高,这是预测的作用,有了原图,有了特定的预测公式算法,就不需要再去存储第二幅至第N副图像的原始像素值,只需要存储他们的差值就可以了;解码的时候,根据第一幅图像的原始像素值,以及差值,就可以把预测的图像恢复成原图了;之后还需要进行:变换(如DCT离散余弦变换)、量化、熵编码等多个过程。
变换:依据频率和幅度的存储方式,改变像素信息的空间顺序。低频的、重要的信息放在一起,人类不敏感的、高频的数据放在一处。在接下来的量化步骤,就可以滤掉不敏感的数据。
量化:对数据进行有损量化,将不重要的数据归零,通过更粗糙的数据或者去除人眼不敏感的信息来降低编码的数据量;
熵编码:RLE行程编码、Huffman霍夫曼编码、CABAC/CAVLC等,根据待编码数据概率特性降低编码冗
余。
IPB帧
I帧:帧内编码帧;关键帧(I帧是一副完整原图经过压缩之后的产物),可以单独解码出完整原图的;
P帧:前向参考帧,记录了本帧和前一帧(I帧或者P帧)的差别,解码时,就根据差值和前一帧计算出完整的当前帧
B帧:双向参考帧,记录了本帧和前后帧的差别,解码时,需要根据前后帧还原出完整的本帧图像;
PTS与DTS
PTS:Presentation Timestamp 显示时间戳,表示帧的显示顺序
DTS: Decode Timestamp 解码时间戳,表示解码顺序
视频解码的顺序是按照DTS顺序进行解码的,解码顺序肯定是按照编码时的顺序,
肯定是先解码I帧,P帧,B帧,编码顺序也就是码流顺序 (I ,B…B,P, I,B…B,P ),
如果没有B帧,PTS和DTS是一样的,有了B帧,由于B帧必须要先解码后面的P帧
所以B帧打乱了解码和显示的顺序,所以一点有了B帧,PTS和DTS就会不同;
播放的时候是按照PTS顺序进行播放的;
主流视频编码标准:
视频流传输中最重要的编解码标准有国际电联(ITU-T,国际电信联盟)的H.261、H.263、H.264等,运动静止图像专家组(由ISO
国际标准化组织与IEC国际电子委员会于1988年联合成立 )的MPEG系列标准MPEG1、MPEG2、MPEG4 AVC等。
其中ITU-T H.264/MPEG-4 AVC是 ITU-T与ISO/IEC连手合作制订的新标准。ITU-T方面称之为H.264。但ISO/IEC的
则将这个新标准归纳于MPEG系列,称为MPEG-4 AVC。
而H.265则被视为是ITU-T H.264/MPEG-4 AVC标准的继任者,又称为高效率视频编码(High Efficiency Video
Coding,简称HEVC)。
四、音频编码
音频编码就是对音频裸数据(音频采样数据PCM)数据进行压缩,实际上一个视频编码包括了图像数据编码,和音频数据编码,只不过前面我们说过了,一个视频中,图像数据占了整个视频数据的绝大部分,所以一般说视频编码主要是指视频中图像数据的编码,这里我们把音频编码单独拿出来学习;
音频的裸数据就是脉冲编码调制PCM,描述一段PCM数据一般需要量化格式(sampleFormat)、采样率(sampleRate)、声道数(channel)。以CD的音质为例,量化格式(也描述为位深度)位16bit,采样率为44100HZ,声道数为2,对于声音数据的码率计算为:
16441002/1024=1378.125kbps;
如果是1分钟的这类CD音质的数据存储空间为:
16441002*60/8/1024/1024≈10.09MB;
10M大小存在磁盘中,可能还好,但是如果在网络中实时传输,数据量相对还是较大的,因为这还只是1分钟的音频数据,所以要进行压缩编码。对于声音数据而言,不被人耳感知到的信号,包括人耳听觉范围之外的以及掩蔽掉的信号就是冗余
信号。编码实际上就是把这些冗余信号压缩、去除掉。
主流音频编码标准:
常见的音频编码格式有:AAC、MP3、AC3等。
欢迎扫码订阅公众号,公众号主要分享原创或转载移动开发技术文章,和广大移动开发者一起学习成长!
以上是关于Android 音视频开发之音视频编码原理的主要内容,如果未能解决你的问题,请参考以下文章