流媒体协议

三个名词系列

  • 名词系列一:AVI、MPEG、RMVB、MP4、MOV、FLV、WebM、WMV、ASF、MKV。例如 RMVB 和 MP4,看着是不是很熟悉?
  • 名词系列二:H.261、 H.262、H.263、H.264、H.265。这个是不是就没怎么听过了?别着急,你先 记住,要重点关注 H.264。
  • 名词系列三:MPEG-1、MPEG-2、MPEG-4、MPEG-7。MPEG 好像听说过,但是后面的数字是怎 么回事?是不是又熟悉又陌生?

视频是什么?快速播放一连串连续的图片。
每一张图片,我们称为一帧,只要每秒帧的数据足够多,也即播放得足够快,比如每秒30帧,以人的眼睛的敏感程度,是看不出这是一张张独立的图片的,这就是我们常说的帧率。
每一张图片都是由像素组成,假设为1024768。每个像素由RGB组成,每个8位,共24位。
每秒钟视频大小:30帧
102476824=566,231,040Bits=70,778,880Bytes
一分钟呢?大概4个多G了。
这样传输的话,数据量太大,根本没办法存储和传输。人们用编码来解决。尽量用少的Bit数保存视频,使播放的时候画面看起来仍然很精美。编码是一个压缩的过程。

视频和图片的压缩过程有什么特点

  1. 空间冗余。图像的相邻像素之间有较强的相关性,一张图片相邻像素往往是渐变的,不是突变的,没必要为每个像素都完整的保存,可以隔几个保存一个,中间的用算法计算出来。
  2. 时间冗余。视频序列的相邻图片之间内容相似。一个视频中连续出现的图片也不是突变的,可根据已有的图片进行预测和推断。
  3. 视觉冗余。人的视觉系统对某些细节不敏感,因此不会每一个细节都注意到,可以允许丢失一些数据。
  4. 编码冗余。不同像素值出现的概率不同。概率高的用的字节少,概率低的用的字节多,类似霍夫曼编码的思路。
    编码的算法很多,但是编码的过程都是类似的。
    在这里插入图片描述

视频编码的两大流派

  • 流派一:ITU的VECG
  • 流派二:ISO的MPEG
    经过编码之后,生活活泼的一帧一帧的图像,就变成了一串串让人看不懂的二进制,这个二进制可以放在一个文件里面,按照一定的格式保存起来

如何在直播里看到帅哥美女

当然,这个二进制也可以通过某种网络协议进行封装,放在互联网上传输,这个时候就可以进行网络直播了。
网络协议将编码好的视频流,从主播端推送到服务器,在服务器上有个运行了同样协议的服务端来接收这些网络包,从而得到里面的视频流,这个过程称为接流。
服务端接到视频流之后,可以对视频流进行一定的处理,例如转码,也即从一个编码格式,转成另一种格式。因为观众使用的客户端千差万别,要保证他们都能看到直播。
流处理完毕之后,就可以等待观众来请求这些视频流。观众的客户端请求的过程称为拉流。如果有非常多的观众,同时看一个视频直播,那都从一个服务器上拉流,压力太大了,因而需要一个视频分发网络,将视频预先加载到就近的边缘节点,这样大部分观众看得视频,是从边缘节点拉取得,就能降低服务器的压力。
当观众的客户端将视频流拉下来之后,就需要进行解码,也即通过上述过程的逆过程,将一串串看不懂的二进制,再转变成一帧帧生动的图片,在客户端播放出来,这样你就能看到帅哥美女了。整个直播过程如下
在这里插入图片描述

编码:如何将丰富多彩的图片变成二进制流

如果视频是一张张图片的序列,但是如果每张图片都完整,就太大了,因而会将视频序列分成三种帧。

  • I 帧,也称关键帧。里面是完整的图片,只需要本帧数据,就可以完成解码。
  • P帧,前向预测编码帧。P帧表示的是这一帧和之前一个关键帧的差别,解码时需要用之前缓存画面,还要解码之后的画面,通过前后画面的数据与本帧数据的叠加,取得最终的画面。
  • B帧,双向预测内插编码帧。B帧记录的是本帧与前后帧的差别,要解码B帧,不但要取得之前的缓存画面,还要解码之后的画面,通过前后画面的数据与本帧数的叠加,取得最终的画面。
    可以看出,I帧最完整,B帧压缩率最高,而压缩后帧的序列,应该是在IBBP的间隔出现的。这就是通过时序进行编码。
    在这里插入图片描述
    在一个帧中,分成多个片,每个片中分成多个宏块,每个宏块分成多个子块,这样将一张大的图分解成一个个小块,可以方便进行空间上的编码。
    尽管时空非常立体的组成了一个序列,但是总归还是要压缩成一个二进制流。这个流是有结构的,是一个个网络提取层单元(NALU)。变成这种格式就是为了传输,因为网络上的传输,默认的是一个个的包,因而这里也就分成了一个个的单元。
    在这里插入图片描述
    每一个NALU首先是一个起始标识符,用于标识NALU之间的间隔;然后是NALU的头,里面主要配置了NALU的类型;最终Payload里面是NALU承载的数据。
    在NALU头里面,主要的内容是类型NAL Type。
  • 0x07表示SPS,是序列参数集,包括一个图像序列的所有信息,如图像尺寸,视频格式等。
  • 0x08表示PPS ,是图像参数集,包括一个图像的所有分片的所有相关信息,包括图像类型、序列号等。
    在传递视频流之前,必须要传递这两类参数,不然无法解码。为了保证容错性,没一个I帧前面,都会传一遍这两个参数集合。
    如果NALU Header 里面表示类型是SPS或者PPS,则Payload 就是真正的参数集的内容。
    如果类型是帧,则Payload中才是真正的视频数据。当然也是一帧一帧存放的,前面说了,一帧的内容还挺多的,因而每一个NALU里面保存的是一片。对于每一片,到底是I帧,还是P帧,还是B帧,在片结构里面也有个Header,这里面有个类型,然后是片的内容。
    整个格式是:一个视频,可以拆分成一系列的帧,每一帧拆分成一系列的片,每一片都放在一个NALU里面,NALU之间都是通过特殊的起始标识符分割,在每一个I帧的第一片前面,要单独插入SPS和PPS的NALU,最终形成一个长长的NALU序列。

推流 如何把数据流打包传输到对端

需要将这个二进制的流打包成网络包进行发送,这里我们使用RTMP协议。这就进入了第二个过程,推流。
RTMP是基于TCP的,因而肯定需要双方建立一个TCP的连接,在有TCP连接的基础上,还要建立一个RTMP的连接,也即在程序里面,你需要调用RTMP类库的Connect函数,显示创建一个连接。
RTMP为什么需要建立一个单独的连接呢?
因为它们需要商量一些事情,保证以后的传输能正常进行。主要就是两个事情,一个是版本号,如果客户端、服务器的版本号不一致,则不能工作。另一个就是时间戳,视频播放中,时间是很重要的,后面的数据流互通的时候,经常需要带上时间戳的差值,因而一开始双方就知道对方的时间戳。
未来要沟通的这些事情,需要发送六条消息:客户端发送C0,C1,C2,服务器发送S0,S1,S2。
首先,客户端发送C0表示自己的版本号,不必等对方的回复,然后发送C1表示自己的时间戳。
服务器只有在收到C0的时候才返回S0,表示自己的版本号,如果版本号不对,断开连接
服务器发送完S0后,也不用等什么,就直接发送自己的时间戳S1,客户端收到S1的时候,发一个知道了对方时间戳的ACK C2。同理服务器收到C1的时候,发一个知道了对方时间戳的ACK S2。于是,服务器握手完成。
在这里插入图片描述
握手之后,双方需要互相传递一些控制信息,例如Chunk块的大小,窗口大小等。
真正需要传递数据的时候,还是需要创建一个流Stream,然后通过这个Stream 来推流publish。推流的过程,就是讲NALU放在Message里面发送,这个也称为RTMP Packet包。Message格式如下
在这里插入图片描述
发送的时候,去掉NALU的起始标识符。因为这部分对于RTMP协议来讲没有用。接下来,将SPS和PPS参数集封装成一个RTMP包发送,然后发送一个个片的NALU。
RTMP在首发数据的时候并不是以Message为单位的,而是把Message拆分成Chunk都带有Message ID,表示属于哪个Message,接收端也会按照这个ID将Chunk组装成Message。
前面连接的时候,设置的Chunk块大小就是指这个Chunk。将大的消息变为小的块再发送,可以在低带宽的情况下,减少网络拥塞。
这有一个分块的例子。
假设一个视频消息的长度为307,但是Chunk大小约定为128,于是会拆分为三个Chunk。
第一个Chunk的Type=0,表示Chunk头是完整的;头里面Timestamp为1000,总长度为307,类型为9,是个视频,Stream ID为12346,正文部分承担了128个字节的 DATA。
第二个Chunk也要发送128个字节,Chunk头由于和第一个Chunk头一样,因此采用Chunk Type=3, 表示头一样就不再发送了。
第三个Chunk要发送的Data的长度为307-128-128个字节,还是采用Type=3。
在这里插入图片描述
就这样数据就源源不断到达流媒体服务器,整个过程就像这样。
在这里插入图片描述
这个时候,大量观看直播的观众就可以通过RTMP协议从流媒体服务器拉取,但是这么多的用户量,都去同一个地方拉取,服务器压力会比较大,而且用户分布在全国,乃至全球,如果都去统一的一个地方下载,也会时延比较长,需要有分发网络。
分发网络分为中心和边缘两层。边缘层服务器部署在全国各地及横跨各大运营商里,和用户距离近。中心层是流媒体服务集群,负载内容的转发。只能负载均衡系统,根据用户的地理位置信息,就近选择边缘服务器,为用户提供推、拉流服务。中心层也负责转码服务,例如把RTMP协议的码流转换为HLS码流。
在这里插入图片描述
这套机制在后面的DNS、HTTPDNS、CDN章节会有更详细的描述

拉流:观众的客户端如何看到视频

在这里插入图片描述
先读到的是H.264的解码参数,例如SPS和PPS,然后对收到的NALU组成的一个个帧,进行解码,交给播放器播放,一个绚丽多彩的视频画面就出来了。
小结:

  • 视频名词比较多,编码两大流派达成了一致,都是通过时间和空间各种弄算法来压缩数据。
  • 压缩好的数据,为了传输组成一系列的NALU,按照帧和片依次排列。
  • 排列好的NALU,在网络传输的时候,按照RTMP包的格式进行包装,RTMP包会拆分成Chunk进行传输;
  • 推送到流媒体集群的视频经过转码和分发,可以被客户端通过RTMP协议拉取,然后组合为NALU,解码成视频格式进行播放。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值