音视频相关知识记录

最近实现了一款基于FFMpeg的支持多路视频的实时流媒体播放器:https://github.com/huweijian5/RtspPlayer 

有兴趣可以关注下。

 

帧(frame)

一般来说,帧是影像常用的最小单位,简单的说就是组成一段视频的一幅幅图片,是数据传输的基本单位。

帧率(frame-rate)

每秒的帧数。一般来说,我们的眼睛在看到东西时,那些东西的影像会在眼睛中停留大约十六分之一秒,也就是视频中只要每秒超过15帧,人眼就会认为画面是连续不断的。

电影的帧率为24。

常见的帧率有24000/1001=23.976, 30000/1001=29.970, 60000/1001=59.940, 25.000, 50.000等等。这个数字是一秒钟内闪过的图像的数量。比如23.976,就是1001秒内,有24000张图像。视频的帧率是可以是恒定的(cfr, Const Frame-Rate),也可以是变化的(vfr, Variable Frame-Rate).

帧大小

即画面大小或屏幕大小等,是组成视频的每一帧的大小,直观表现为视频的分辨率的大小。

比特率
又叫码率或数据速率,是数据传输时单位时间传送的数据位数,一般我们用的单位是kbps即千位每秒。音视频中的比特率,是指由模拟信号转换为数字信号的采样率;采样率越高,还原后的音质和画质就越好;音视频文件的体积就越大,对系统配置的要求也越高。

视频文件的比特率与帧大小、帧速率直接相关,一般帧越大、速率越高,比特率也就越大。

码率的定义是视频文件体积除以时间。单位一般是Kbps(Kbit/s)或者Mbps(Mbit/s)。注意1B(Byte)=8b(bit)。所以一个24分钟,900MB的视频:
体积:900MB = 900MByte = 7200Mbit
时间:24min = 1440s
码率:7200/1440  = 5000 Kbps = 5Mbps

码率也可以解读为单位时间内,用来记录视频的数据总量。码率越高的视频,意味着用来记录视频的数据量越多,潜在的解读就是视频可以拥有更好的质量。(注意,仅仅是潜在,高码率不一定等于高画质)

采样率

定义了每秒从连续信号中提取并组成离散信号的采样个数,它用赫兹(Hz)来表示。

关键帧

相当于二维动画中的原画,指角色或者物体运动或变化中的关键动作所处的那一帧,它包含了图像的所有信息,后来帧只保留了改变的信息。

关键帧与关键帧之间的动画可以由软件来创建,叫做过渡帧或者中间帧。

I帧 P帧 B帧

I帧特点:
1.它是一个全帧压缩编码帧。它将全帧图像信息进行JPEG压缩编码及传输;
2.解码时仅用I帧的数据就可重构完整图像;
3.I帧描述了图像背景和运动主体的详情;
4.I帧不需要参考其他画面而生成;
5.I帧是P帧和B帧的参考帧(其质量直接影响到同组中以后各帧的质量);
6.I帧是帧组GOP的基础帧(第一帧),在一组中只有一个I帧;
7.I帧不需要考虑运动矢量;
8.I帧所占数据的信息量比较大。


P帧:前向预测编码帧。
P帧的预测与重构:P帧是以I帧为参考帧,在I帧中找出P帧“某点”的预测值和运动矢量,取预测差值和运动矢量一起传送。在接收端根据运动矢量从I帧中找出P帧“某点”的预测值并与差值相加以得到P帧“某点”样值,从而可得到完整的P帧。
P帧特点:
1.P帧是I帧后面相隔1~2帧的编码帧;
2.P帧采用运动补偿的方法传送它与前面的I或P帧的差值及运动矢量(预测误差);
3.解码时必须将I帧中的预测值与预测误差求和后才能重构完整的P帧图像;
4.P帧属于前向预测的帧间编码。它只参考前面最靠近它的I帧或P帧;
5.P帧可以是其后面P帧的参考帧,也可以是其前后的B帧的参考帧;
6.由于P帧是参考帧,它可能造成解码错误的扩散;
7.由于是差值传送,P帧的压缩比较高。


B帧:双向预测内插编码帧。
B帧的预测与重构
B帧以前面的I或P帧和后面的P帧为参考帧,“找出”B帧“某点”的预测值和两个运动矢量,并取预测差值和运动矢量传送。接收端根据运动矢量在两个参考帧中“找出(算出)”预测值并与差值求和,得到B帧“某点”样值,从而可得到完整的B帧。
B帧特点
1.B帧是由前面的I或P帧和后面的P帧来进行预测的;
2.B帧传送的是它与前面的I或P帧和后面的P帧之间的预测误差及运动矢量;
3.B帧是双向预测编码帧;
4.B帧压缩比最高,因为它只反映丙参考帧间运动主体的变化情况,预测比较准确;
5.B帧不是参考帧,不会造成解码错误的扩散。

DTS(Decoding Time Stamp)

解码时间戳

PTS(Presentation Time Stamp)

显示时间戳

FFmpeg中用AVPacket结构体来描述解码前或编码后的压缩包,用AVFrame结构体来描述解码后或编码前的信号帧。 对于视频来说,AVFrame就是视频的一帧图像。这帧图像什么时候显示给用户,就取决于它的PTS。DTS是AVPacket里的一个成员,表示这个压缩包应该什么时候被解码。 如果视频里各帧的编码是按输入顺序(也就是显示顺序)依次进行的,那么解码和显示时间应该是一致的。可事实上,在大多数编解码标准(如H.264或HEVC)中,编码顺序和输入顺序并不一致。 于是才会需要PTS和DTS这两种不同的时间戳。

封装格式(MP4/MKV…)  vs 媒体格式(H.264/FLAC/AAC…)

封装格式是一个容器,类似包裹,里面包含了音视频字幕等信息,每种信息被称为轨道(track)。

常见的类型有音频(audio),视频(video),字幕(subtitles),章节(chapter),每个类型也不一定只有一条轨道,比如经常见到带多音轨的MKV。

每个轨道,都有自己的格式。比如大家常说的,视频是H.264,音频是AAC,这些就是每个轨道的格式。

RGB模型

光的三原色是红(Red)、绿(Green)、蓝(Blue)。现代的显示器技术就是通过组合不同强度的三原色,来达成任何一种可见光的颜色。图像储存中,通过记录每个像素红绿蓝强度,来记录图像的方法,称为RGB模型 (RGB Model)
常见的图片格式中,PNG和BMP这两种就是基于RGB模型的.

 

YUV模型

YUV格式有两大类:planar和packed。
对于planar的YUV格式,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V。
对于packed的YUV格式,每个像素点的Y,U,V是连续交*存储的。
YUV,分为三个分量,“Y”表示明亮度(Luminance或Luma),也就是灰度值;而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。

 

YUV和RGB的转换

Y = 0.299 R + 0.587 G + 0.114 B
U = -0.1687 R - 0.3313 G + 0.5 B + 128
V = 0.5 R - 0.4187 G - 0.0813 B + 128

 R = Y + 1.402 (V-128)
 G= Y - 0.34414 (U-128) - 0.71414 (V-128)
 B= Y + 1.772 (U-128)

 

YCbCr与RGB的相互转换

Y=0.299R+0.587G+0.114B
Cb=0.564(B-Y)
Cr=0.713(R-Y)
 
R=Y+1.402Cr
G=Y-0.344Cb-0.714Cr
B=Y+1.772Cb

 

YUV YCbCr YIQ

yuv色彩模型来源于rgb模型,该模型的特点是将亮度和色度分离开,从而适合于图像处理领域。


YCbCr模型来源于yuv模型,是YUV经过缩放和偏移的翻版.应用于数字视频,ITU-R BT.601 recommendation,

YIQ适用于NTSC彩色电视制式,YUV适用于PAL和SECAM彩色电视制式,而YCrCb适用于计算机用的显示器

YCbCr其中Y是指亮度分量,Cb指蓝色色度分量,而Cr指红色色度分量

一般人们所讲的YUV大多是指YCbCr。YCbCr 有许多取样格式, 如4∶4∶4 , 4∶2∶2 , 4∶1∶1 和4∶2∶0

 

YUV采样方式

主流的采样方式有三种,YUV4:4:4,YUV4:2:2,YUV4:2:0

YUV 4:4:4采样,每一个Y对应一组UV分量。
YUV 4:2:2采样,每两个Y共用一组UV分量。 
YUV 4:2:0采样,每四个Y共用一组UV分量。

YUV4:4:4

YUV三个信道的抽样率相同,因此在生成的图像里,每个象素的三个分量信息完整(每个分量通常8比特),经过8比特量化之后,未经压缩的每个像素占用3个字节。

下面的四个像素为: 
[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
存放的码流为: Y0 U0 V0 Y1 U1 V1 Y2 U2 V2 Y3 U3 V3

 

YUV 4:2:2

每个色差信道的抽样率是亮度信道的一半,所以水平方向的色度抽样率只是4:4:4的一半。对非压缩的8比特量化的图像来说,每个由两个水平方向相邻的像素组成的宏像素需要占用4字节内存。

下面的四个像素为:
[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
存放的码流为:Y0 U0 Y1 V1 Y2 U2 Y3 V3
映射出像素点为:
[Y0 U0 V1] [Y1 U0 V1] [Y2 U2 V3] [Y3 U2 V3]

 

YUV 4:1:1

4:1:1的色度抽样,是在水平方向上对色度进行4:1抽样。对于低端用户和消费类产品这仍然是可以接受的。对非压缩的8比特量化的视频来说,每个由4个水平方向相邻的像素组成的宏像素需要占用6字节内存。

下面的四个像素为: 
[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
存放的码流为: Y0 U0 Y1 Y2 V2 Y3
映射出像素点为:
[Y0 U0 V2] [Y1 U0 V2] [Y2 U0 V2] [Y3 U0 V2]

 

YUV 4:2:0

4:2:0并不意味着只有Y,Cb而没有Cr分量。它指得是对每行扫描线来说,只有一种色度分量以2:1的抽样率存储。相邻的扫描行存储不同的色度分量,也就是说,如果一行是4:2:0的话,下一行就是4:0:2,再下一行是4:2:0...以此类推。对每个色度分量来说,水平方向和竖直方向的抽样率都是2:1,所以可以说色度的抽样率是4:1。对非压缩的8比特量化的视频来说,每个由2x2个2行2列相邻的像素组成的宏像素需要占用6字节内存。

下面八个像素为:[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
[Y5 U5 V5] [Y6 U6 V6] [Y7U7 V7] [Y8 U8 V8]
存放的码流为:Y0 U0 Y1 Y2 U2 Y3
Y5 V5 Y6 Y7 V7 Y8
映射出的像素点为:[Y0 U0 V5] [Y1 U0 V5] [Y2 U2 V7] [Y3 U2 V7]

[Y5 U0 V5] [Y6 U0 V5] [Y7U2 V7] [Y8 U2 V7]

各种YUV格式区别只在于YUV的存储方式上,如下

I420:YYYYYYYY UU VV =>YUV420P

YV12:YYYYYYYY VV UU =>YUV420P

NV12:YYYYYYYY UV UV =>YUV420SP

NV21:YYYYYYYY VU VU =>YUV420SP

YUV420p

YUV420sp

 

YUV的优点

人眼对亮度的敏感度远高于色度,因此人眼看到的有效信息主要来自于亮度。YUV模型可以将绝大多数的有效信息分配到Y通道。UV通道相对记录的信息少的多。相对于RGB模型较为平均的分配,YUV模型将多数有效信息集中在Y通道,不但减少了冗余信息量,还为压缩提供了便利

保持了对黑白显示设备的向下兼容

图像编辑中,调节亮度和颜色饱和度,在YUV模型下更方便。

 

YUV420P

YUV 4:2:0采样,即每4个Y公用一组UV分量。如下(常见的planar格式):

Y1Y2Y3Y4Y5Y6Y7Y8

Y9Y10Y11Y12Y13Y14Y15Y16

 

Y17Y18Y19Y20Y21Y22Y23Y24

Y25Y26Y27Y28Y29Y30Y31Y32

U1U2U3U4U5U6U7U8

V1V2V3V4V5V6V7V8

一个Y分量对应一个像素点,因此若图片的宽为width, 高为height,那么Y的长度就等于(width * height),同理U就等于(Y / 4), V也等于(Y / 4)。

根据这个则可计算YUV图像的长度等于Y+U+V=Y+Y/4+Y/4=Y*3/2=(width*height*3)/2。

在ffmpeg中可以用此函数得出长度:

int numBtyes = avpicture_get_size(AV_PIX_FMT_YUVJ420P, 480, 272);

YUV格式有两大类:planar和packed。
对于packed的YUV格式,每个像素点的Y,U,V是连续交叉存储的。
对于planar的YUV格式,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V。

解码得到YUV数据,经过如下便可得到各个分量的值:

//Read YUV  
FILE *in_file = fopen("cuc_view_480x272.yuv", "rb");  
if( fread(picture_buf, 1, y_size*3/2, in_file) <= 0 )  {  
    printf("Could not read input file.");  
    return -1;  

picture->data[0] = picture_buf;            // Y  
picture->data[1] = picture_buf+ y_size;     // U  
picture->data[2] = picture_buf+ y_size*5/4; // V

其中,y_size即为(width*height)。

 

 

Stride

http://blog.csdn.net/g0ose/article/details/52116453

 

 

SPS PPS IDR

SPS(Sequence Parameter Set):序列参数集,H.264码流第一个 NALU(网络抽象层单元)

PPS(Picture Parameter Set):图像参数集,H.264码流第二个 NALU

IDR:即时解码器刷新,H.264码流第三个 NALU

SPS 包含的是针对一连续编码视频序列的参数,如标识符 seq_parameter_set_id、帧数及 POC 的约束、参考帧数目、解码图像尺寸和帧场编码模式选择标识等等。 
PPS对应的是一个序列中某一幅图像或者某几幅图像,其参数如标识符 pic_parameter_set_id、可选的 seq_parameter_set_id、熵编码模式选择标识、片组数目、初始量化参数和去方块滤波系数调整标识等等

 

H264片段分析

对于H.264而言,每帧的界定符为00 00 00 01 或者00 00 01。
例如下面是一个H264的文件片段
00 00 00 01 67 42 C0 28 DA 01 E0 08 9F 96 10 00
00 03 00 10 00 00 03 01 48 F1 83 2A 00 00 00 01
68 CE 3C 80 00 00 01 06 05 FF FF 5D DC 45 E9 BD
E6 D9 48 B7 96 2C D8 20 D9 23 EE EF …

第一帧是00 00 00 01 67 42 C0 28 DA 01 E0 08 9F 96 10 00 00 03 00 10 00 00 03 01 48 F1 83 2A (67表示是SPS)
第二帧是00 00 00 01 68 CE 3C 80 (68表示是PPS)
第三帧是00 00 01 06 05 FF FF 5D DC 45 E9 BD E6 D9 48 B7 96 2C D8 20 D9 23 EE EF ..

NAL_SLICE = 1 非关键帧
NAL_SLICE_DPA = 2
NAL_SLICE_DPB = 3
NAL_SLICE_DPC =4
NAL_SLICE_IDR =5 关键帧
NAL_SEI = 6
NAL_SPS = 7 SPS帧
NAL_PPS = 8 PPS帧
NAL_AUD = 9
NAL_FILLER = 12

NAL类型计算方法:
67(16)=01100111(2)     
65(16)=01100101(2)
41(16)=01000001(2)

 

常见问题

 

FFMpeg解码后的数据为什么要经过sws_scale()函数处理?
答:解码后YUV格式的视频像素数据保存在AVFrame的data[0]、data[1]、data[2]中。但是这些像素值并不是连续存储的,每行有效像素之后存储 了 一 些 无 效 像 素 。 以 亮 度 Y 数 据 为 例 , data[0] 中 一 共 包 含 了linesize[0]*height个数据。但是出于优化等方面的考虑,linesize[0]实际上并不等于宽度width,而是一个比宽度大一些的值。因此需要使用sws_scale()进行转换。转换后去除了无效数据,width和linesize[0]取值相等。

 

I 帧与IDR帧的区别?

答:举个例子,在一段视频中,
存在以下帧:I P B P B P B B PIP B…
如果这段视频应用了多重参照帧,那么蓝色的P 帧在参照他前面的I 帧(红色)的同时,还可能会参
照I 帧之前的P 帧(绿色),由于I 帧前后的场景可能会有很大的反差甚至根本不同,所以此时P 帧参考I
帧之前的帧不但会没有意义,反而会造成很多问题。
所以一种新型的帧被引入,那就是IDR 帧。如果这段视频应用了多重参考帧的同时采用了IDR 帧,那
么帧的顺序就会变成这样:I P B P B P B B P IDRP B…
由于IDR 帧禁止后面的帧向自己前面的帧参照,所以这回那个蓝色的P 帧就不会参照绿色的P 帧了。

 

参考文章:

http://www.4k123.com/thread-8194-1-1.html

http://blog.csdn.net/leixiaohua1020/article/details/18893769

http://blog.csdn.net/bobsweetie/article/details/50935246

http://blog.csdn.net/u010164190/article/details/52771218

I帧、P帧、B帧,以及PTS、DTS的关系 - 傻眼哥的博客
https://blog.csdn.net/davidsguo008/article/details/72628690

...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值