视频开发基础知识

本文主要介绍在用FFmpeg进行视频相关开发时涉及到的一些视频基本概念。

一、视频帧

在H264协议里,图像以组(GOP,也就是一个序列)为单位进行组织,一个组是一段图像编码后的数据流,以I帧开始,到下一个I帧结束。一个组就是一段内容差异不太大的图像编码后生成的一串数据流。当运动变化比较少时,一个组可以很长,因为运动变化少就代表图像画面的内容变动很小,所以就可以编一个I帧,然后一直P帧、B帧了。当运动变化多时,可能一个序列就比较短了,比如就包含一个I帧和3、4个P帧。

1.I帧

I帧是帧组的第一帧,在一组中只有一个I帧。I帧是帧内编码帧,是一种自带全部信息的独立帧,无需参考其他图像便可独立进行解码,可以简单理解为一张静态画面。如果传输过程中I真丢失,画面最直接的影响就是会卡顿,因为后面的帧都无法正确解码,只能等待下一个GOP。

2.P帧

P帧是帧间预测编码帧,需要参考其前面的I帧或P帧才能进行编码。P帧没有完整的画面数据,只有与其前一参考帧的画面差别的数据。与I帧相比,P帧通常占用更少的数据位,但不足是,由于P帧对前面的P和I参考帧有着复杂的依耐性,因此对传输错误非常敏感,所以如果P帧丢失,画面会出现马赛克现象,因为前向参考帧错误,补齐的并不是真正运动变化后的数据。

3.B帧

B帧是双向预测编码帧,也就是B帧记录的是本帧与前后帧的差别。也就是说要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,但解码时很耗CPU资源。(B帧以前面的I或P帧和后面的P帧为参考帧,B帧不是参考帧,不会造成解码错误的扩散。)


一般来说,I帧的压缩率是7(跟JPG差不多),P帧是20,B帧可以达到50。虽然B帧压缩率高,但是在直播系统中很少使用B帧,一是因为解码很耗CPU,再就是B帧解码需要等待下一个P帧数据,这就会造成解码延时,而直播系统对延时要求很高,所以一般不用B帧。但对于点播系统就不会有这个问题。

二、PTS和DTS

PTS(Presentation TimeStamp)是渲染用的时间戳,也就是说,我们的视频帧是按照 PTS 的时间戳来展示的。DTS(Decoding TimeStamp)解码时间戳,是用于视频解码的。
为什么会有2个不同的时间戳呢?这和I帧、P帧和B帧有关,我们分2中情况来看:

1.视频中只有I帧和P帧

如下所示,第1帧是I帧,2-8帧是P帧,展示的顺序是12345678。解码时先解码第1帧,第2帧参考第1帧解码,第3帧参考第2帧解码……也就是解码顺序也是12345678。这种情况下PTS和DTS是一样的,所以此时是没有必要区分2个不同的时间戳的。

1 2 3 4 5 6 7 8
I P P P P P P P

2.视频中有I帧、P帧和B帧时

如下所示,第1帧是I帧,第4、8帧是P帧,其余是B帧,展示顺序是12345678。解码时先解第1帧,第2帧是B帧,由于它后面的帧还没解码,所以它也没法解码,第3帧也是一样,所以第二解码是第4号的P帧,然后2号B帧参考其前面的第1帧和其后面的第4帧进行解码,然后再是3号B帧解码,然后567号B帧要等到8号的P帧解码后才能解码。所以解码的顺序是14238567,这种情况下展示顺序和解码顺序就不一样,所以就有了PTS和DTS的区分。

1 2 3 4 5 6 7 8
I B B P B B B P

三、时间基

1.时间基的概念

FFmpeg中用AVPacket结构体来描述解码前或编码后的压缩包,用AVFrame结构体来描述解码后或编码前的信号帧。对于视频来说,AVFrame就是视频的一帧图像。这帧图像什么时候显示给用户,就取决于它的PTS。DTS是AVPacket里的一个成员,表示这个压缩包应该什么时候被解码。那么PTS和DTS的单位是什么呢?
要回答这个问题,我们先引入FFmpeg中时间基的概念,也就是time_base,它是一个AVRational结构体,其定义如下:

typedef struct AVRational{
    int num; ///< 分子
    int den; ///< 分母
} AVRational;

time_base是用来度量时间的,比如time_base = {1,25},它的意思是将1秒分成25段,那么每段就是1/25秒,在FFmpeg中函数av_q2d(time_base)就是用来计算一段的时间的,计算结果就是1/25秒。PTS和DTS的单位就是段,比如一个视频中某一帧的pts是800,也就是说有800段,那么它表示多少秒呢,ptsav_q2d(time_base)=800(1/25)=32s,也就是说要在第32秒的时候播放这一帧。

2.时间基的转换

为什么要有时间基转换呢?首先,不同的封装格式时间基是不一样的。其次,在编码前和编码后的时间基也不一致。拿mpegts封装格式25fps来说,非压缩时候的数据(YUV),在ffmpeg中对应的结构体为AVFrame,它的时间基为AVCodecContext 的time_base ,AVRational{1,25}。 压缩后的数据(对应的结构体为AVPacket)对应的时间基为AVStream的time_base,AVRational{1,90000}。
因此数据状态不同,时间基不一样,所以我们必须转换,这就是pts的转换。FFmpeg中有个函数用于时间基的转换,比如time_base1 = {1,25}的时间基下pts1 = 100,那么在time_base2 = {1,90000}的时间基下pts2是多少呢?pts2 = av_rescale_q(pts1,time_base1,time_base2);
在FFmpeg内部还有一个比较常见的时间基,其定义如下:

#define         AV_TIME_BASE   1000000
#define         AV_TIME_BASE_Q   (AVRational){1, AV_TIME_BASE}

另外还有个和pts类似的参数duration,它的单位和pts一样,表示两帧直接的间隔,也就是说一帧持续多少个时间刻度。

3.计算音频的pts

以AAC音频为例,一个AAC原始帧包含一段时间内1024个采样及相关数据,也就是说一帧有1024个样本,如果采样率为44.1kHz(1秒采集44100个样本),所以aac音频1秒有44100/1024帧,每一帧的持续时间是1024/44100秒,由此可以计算出每一帧的pts。(不同的封装格式一帧的样本数是不一样的。)

四、NALU、SPS和PPS

NALU(NALU详解)

我们平时的一帧数据就是一个NALU,它包含一个字节的头信息和帧的视频数据内容。
MALU头信息中第1个bit是forbidden_zero_bit,在 H.264 规范中规定了这一位必须为 0。
第2、3位是nal_ref_idc,指示了这个NALU的重要性,值越大表示越重要,比如为0时NALU解码器可以丢弃它而不影响图像的回放。如果是参考帧的话这个值必须大于0。
第4-8位是nal_unit_type,表这个NALU单元类型,2表示B帧或P帧,5表示I帧,7表示SPS帧,8表示PPS帧。
每个NALU前会添加一个4字节的起始码,每当解码器遇到起始码就表示当前帧结束下一帧开始。

SPS和PPS(SPS PPS详解)

SPS(Sequence Paramater Set),也就是序列参数集,里面保存了一组编码视频序列(也叫组)的全局参数(比如分辨率、码流等参数)。
PPS(Picture Paramater Set),也就是图像参数集,每一帧的编码后数据所依赖的参数保存于图像参数集中。
H264中SPS和PPS分别保存在2个NALU中,SPS的nal_unit_type值是7,PPS的nal_unit_type值是。在封装格式中,PPS通常与SPS一起,保存在视频文件的文件头中,后面的解码都需要用到SPS和PPS中的参数,SPS和PPS丢失会导致无法解码。如果在播放途中切换分辨率,SPS和PPS信息都会发生改变,所以每次切换时都需要把新的SPS和PPS传过来。对于需要从中间开始解码的情况,中间也需要传SPS和PPS过来,否则后面无法解码。

五、H264压缩简介

1.分组:把几帧图像分为一组(GOP,也就是一个序列),每组的帧数不是固定的,运动变化少时一组的帧数就较多,运动变化多时一组帧数就少。
2.定义帧:将每组内各帧图像定义为三种类型,即I帧、B帧和P帧;
3.预测帧:以I帧做为基础帧,以I帧预测P帧,再由I帧和P帧预测B帧;
4.数据传输:最后将I帧数据与预测的差值信息进行存储和传输。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容

  • ### YUV颜色空间 视频是由一帧一帧的数据连接而成,而一帧视频数据其实就是一张图片。 yuv是一种图片储存格式...
    天使君阅读 3,174评论 0 4
  • 音视频入门前,需要了解下一些基础概念,不必死记硬背,可之后再补再翻阅。 一. 颜色模式 RGB[https://z...
    Benhero阅读 15,869评论 0 25
  • 一、软编与硬编概念 1、软编码:使用CPU进行编码。 实现直接、简单,参数调整方便,升级易,但CPU负载重,性能较...
    Evans_Xiao阅读 4,599评论 0 6
  • 做这个东西很久了,从去年十二月份开始的,快5个月了。。。期间因为工作一直断断续续,直到最近才有了些进展,也就到此为...
    0_0啊阅读 12,177评论 1 13