对于直播来说,都使用了什么协议了?

无论是直播还是点播,都是基于视频数据的传输,那么如何进行传输视频数据?

我们先提出三种专有的名词,

1.AVI MPEG RMVB MP4 MOV FLV ASF等

2.H.261,H.262,H.263,H.264,H.265

3.MPEG-1,MPEG-2,MPEG-4,MPEG-7

说完这三种专有的名词,不要急,我们首先说一下视频,它的本质,视频的本质就是一组组的图片,在快速的播放从而形成的连续的视频

每一张图片可以说是一帧,只要帧数足够多,播放的足够快,假如每秒30帧就能形成一个30帧的视频,那么这每秒30帧我们称之为30fps,30帧率

那么,每一张的图片都是由像素点组成的,假设为1024*768,每个像素都是由RGB组成,每个8位,一种24位

那么假设30FPS的视频,每秒占用的大小为

30*1024*768*24=566231040Bits = 70778880Bytes

那么,一分钟的传输,就是4个G,这谁扛得住啊

于是.我们必须进行相关的压缩和编码,编码其实就是一个压缩的过程

整体的编码利用了视频的一些特性

1.空间冗余:图像的相邻像素点之间具有一定的关联性,一个图片的相邻像素往往是渐变的,并非突变的,没有必要所有的像素都保存,而是隔几个保存一个,中间的通过算法计算出来

2.时间冗余,视频之中,相邻的图像是具有相似性的,连续的图片也不是突变的,而是可以通过现有的图片进行预测和推断

3.视觉冗余:人的视觉系统对于某些的细节并不敏感,因此丢失了一些细节也没有问题,可以丢失一些数据

4.编码上的冗余,对于不同的像素值,出现的概率也不同,概率高的字节少,概率低的让其字节多,从而类似霍夫曼编码类似

大致的编码过程如下

图片

然后视频编码既然有了思路,为了统一编码,就有了视频编码的格式

主要的流派有两个

流派一:ITU的VCEG,做视频编码出身的,对应的名词系列二

流派二:ISO的MPEG,这个是做视频传输出来的,对应的名词系列三

后来两者统一制定的, H.264/MPEG-4 AVC

经过编码后,生动活泼的一帧帧的图片,变成了一串串的二进制,在这个二进制放在一个文件中,按照一定的格式保存,就是名词系列一

如何进行直播的视频流传输呢?

二进制可以通过某种网络协议进行封装,放在互联网上传输

网络协议将编码好的视频流,从主播端推送到服务器,然后服务器上有个运行了同样网络协议的服务器端来接收网络包,然后得到网络流,这一步的操作称为接流

然后接收到流之后,进行对视频流的处理,称为转码,从一种编码格式转换到另一种编码格式,这一步是因为观众的客户端和客户端的分辨率千差万别,我们要保证统一的推送

流处理完成后,等待观众的客户端来请求这些处理好的视频流,这请求的过程称为拉流,就好比我按照1080*1920 30FPS的格式请求视频流,服务器就是将这一种格式的视频流给我

客户端获取到了视频流,也进行解码,进行处理,将二进制变成了一帧帧的图片,从而从客户端播放出来

图片

然后下一个问题,如何进行编码呢?

首先说编码中的一个重要压缩方式,时间上的预测

我们将视频序列分为了三种帧

I帧:关键帧,里面是完整额图片,只要本帧数据数据,就可以完成解码

P帧:前向预测编码帧,P帧表示这一帧和之前一个I帧或者P帧之间的差别

B帧:双向预测内插编码帧,B帧记录的是本帧和前后帧的差别,要解码B帧,不仅要取出之前的缓存画面,还要解码之后的画面,利用叠加,获取最终的画面

那么I帧最完整,B帧压缩率最高,这就是时间上的编码

然后在一个帧中,分成了多个片,每个片分成了多个宏快,每个宏块分为了多个子快,将一个图片分为了一个个的小块,进行了空间上的编码

图片

然后时空综合,完成了一个二进制的流,这个流是有结构的,是一个个网络提取层单元 NALU,方便传输,因为传输的是一个个的包,于是这就是一个个的单元

图片

在这个NALU的包中,首先是一个NALU的标识,标识了NALU的间隔,然后是NALU的头,说明了NALU的类型,最终是Payload是NALU的数据

NALU的头里面,主要的内容类型是NAL TYPE

0x07标识的SPS,是序列参数集,说明了这个序列中的所有信息,说明了图像的尺寸,视频格式

0x08表示了PPS,是图像参数集,说明了一个图像的所有分片的信息,包含了图像类型和序列号

在传输视频流之前,必须要有这两个参数,不然怎么解码呢?

为了保证不出错,每个I帧都会带着两个参数集合

然后如果是 0x07 或者 0x08,其中的payload就是真正的参数集内容

然后是01-05就是说明是什么类型的帧,每个帧里面payload里面就是片的内容

那么如何推流?

那么这个格式,如何进行网络的传输呢?

肯定是有对应的协议,我们使用了RTMP协议,进行发送包,我们使用了RTMP协议,

RTMP是基于TCP的,肯定需要建立一个TCP连接的基础上,然后建立一个RTMP连接,我们需要在程序中,调用RTMP类库的Connect函数,创建一个连接

RTMP的单独连接,主要是商量了两件事情,一个是版本号,如果是客户端和服务器端的版本号不一样,就没法正常的工作,另一个是时间戳,如果时间戳有差值,就要立刻修正

整体的RTMP的建立如下

图片

首先,客户端发送了C0表示自己的版本号,不用等待回复,直接发送了C1表示了自己的时间戳然后服务器收到了C0,才会发挥S0,表示自己的版本号,版本号不匹配则可能不连接

S0发送完也是不等待,直接发送自己的时间戳S1,客户端收到了S1,发送了一个知道对方时间戳的C2,同理服务器收到了C1,发了一个知道对方时间戳的S2

这样就是握手完成了

然后可能传递Chunk块的大小,窗口的大小的信息,

真正传输数据的时候,需要创建一个stream流,然后进行publish

推流的时候,就是讲NALU放在message中发送,这就是RTMP Packet包

图片

发送的时候,去掉了NALU的其实标识符,然后将SPS和PPS封装为了一个RTMP包发送,然后是一个个片的NALU

RTMP收发数据的时候并不是以Message为单位的,而是把mesage拆分了,拆分成了Chunk发送,这必须在一个Chunk发送完成后,才能发送下一个Chunk

假设一个视频的消息长度是307,Chunk的大小约定为128,于是会拆分为三个Chunk

第一个Chunk的Type=0,表示头是完整的,头里面的TimeStamp为1000,,总长度为Length为307,类型为9.是个视频 stream ID为 123456,正文部分承担128个字节的Data

第二个的Chunk也发送了128个字节,由于和第一个头一样,所以表明自己的Chunk Type为3,表明头一样不就不发送了

图片

这样,数据就源源不断的发送到流媒体的服务器,过程如下

图片 然后观众就可以通过RTMP协议从流媒体上拉取数据,但是这么多的用户,都去一个地方拉取,肯定不合适.于是使用了内容分发网络,内容分发网络分为了中心和边缘两层,边缘层部署在全国各地和各大运营商中,中心层流媒体服务集群,负责内容的转发,只能负载均衡系统,根据用户的地理位置信息,就进选择边缘服务器,将中心层推送过来的流转发给用户

图片

后面说,CDN会说明的

客户端如何看到视频?

图片

首先是H.264的解码参数,例如SPS和PPS,然后对收到的NALU组成的帧,进行解码,并转发给播放器播放

本章小结:

视频的名词比较多,但是大多就是通过时间或者空间的各种算法来压缩数据

压缩好的数据,为了传输组成了一系列的NALU,然后根据帧和片来排列

排列好的NALU,传输的时候,要按照RTMP包的格式来包装,RTMP的包会拆分为Chunk来传递

推送到流媒体集群的视频经过转码和分发,可以被客户端通过RTMP协议拉取,然后组合为NALU,解码成视频格式来播放

课后思考:

1.基于RTMP的视频流传输有什么问题吗?如何优化?

2.下载电影是什么协议呢?

1.因为RTMP基于TCP传输,所以不适合做直播,需要实时的推送,引入UDP试试

2.使用了P2P协议

宏块和子块建立成为了NALU中的payload,在RTMP建立起来后,将NALU放在chuck块中的message进行发送

现在因为RTMP基于TCP做的传输,不如HTTP-FLV,基于HTTP做的封装,更容易进入防火墙内

RTMP建立连接的序列是什么呢>

客户端C0,C1,C2.服务端发送S0,S1,S2

首先,客户端发送C0表明自己的版本号,不必等对方的回复,然后发送C1表明自己的时间戳

服务器只有收到C0的时候,才能发S0,表明自己的版本号,如果版本不匹配,可以断开连接

服务器发送完S0后,会直接发送S1,客户端收到S1的时候,发一个知道了对方时间戳的ACK C2,同理服务器收到C1的时候,发一个知道了对方时间戳ACK S2

发表评论

邮箱地址不会被公开。 必填项已用*标注