流媒体协议是网络对视频的传输协议。
基本概念
视频技术的名词
-
名词系列一:AVI、MPEG、RMVB、MP4、MOV
-
名词系列二:H.261、H.262、H.263、H.264、H.265。重点是H.264
-
名词系列三:MPEG-1、MPEG-2、MPEG-4、MPEG-7。
视频:一连串的图片。
帧:一张图片就是一帧。
帧率:就是每秒由多少张图片
像素:一个像素一个RGB,每个8位。一张图片由好多个像素组成。
每秒种的视频有多大?
30 帧 × 1024 × 768 × 24 = 566,231,040Bits = 70,778,880Bytes
每分钟的视频有多大?4,246,732,800Bytes,已经是 4 个 G 了。
编码:用尽量少的Bit 保存视频,是一个压缩的过程。
利用视频和图片的一些特点进行压缩:空间冗余、时间冗余、视觉冗余、编码冗余。
本质上就是用更少的能量传递更多的信息。这和香农的信息论有些相似。
视频编码的两大流派
-
ITU 的VCEG
-
ISO 的MPEG
-
ITU-T 与 MPEG 联合制定的 H.264/MPEG-4 AVC
经过编码之后,原来的一帧帧图片转为二进制数据,将这些二进制数据放到文件里,按照一定的格式保存起来,就是名词系列一。
接流:服务器从主播客户端的那里接收视频流
转码:从一个编码格式转为另一个编码格式。
拉流:观众客户端从服务器上拉取视频流
解码:观众的客户端将二进制的视频流,转为一帧帧图片,组成视频。
网络直播,数据流的传输过程
我们现在以一个网络直播的例子,来说一下视频是如何从主播的镜头上传到网络上,又是如何从网络上到每个粉丝的电脑屏幕上的。
1、主播的摄像头将视频采集下来,用视频编码协议编码,转成二进制的字节流,通过HTTP协议将它们打包发送出去。
2、服务器这端有同样的视频编码协议,从TCP协议中解析出数据包,做一个缓存或者转码,就是从一个视频编码格式转为另一中格式。因为客户端使用的播放设备千差万别。
3、客户端这边从服务端请求视频流。这个过程很考验服务器,服务器要同时为巨大数量的客户端服务。这时需要一个视频分发的网络,将视频预先加载到里客户端较近的服务器上。
假如全国人都在观看国庆阅兵,辽宁观众看到的视频是从辽宁区域的服务器上拉取的视频流。广州的观众看的是广州区域服务器上的视频流。
4、观众的电脑或显示器从网络上拉取视频流之后,还是二进制的字节,要进行解码才能看。
整个直播的过程像下图这样:
视频分解、传输过程
编码:视频转为二进制的具体操作,为减少视频图像的大小,将视频序列分为三种帧。
-
I 帧,关键帧,是完整图片,需要本帧数据完成解码。
-
P 帧,前向预测编码帧,它表示的是一个差别,这一帧和前一个关键帧的差别。
-
B 帧,双向预测内插编码帧。表示本帧与前后帧的差别。要解码B帧,需要前一帧的画面,和后面一帧的画面,通过前后画面的数据和本帧的叠加,得到最终的画面。
在传输时,为方便空间上的编码,将每帧分为好多片,每片分为好多宏块,每个宏块又分为好多小块。
分成这些小块是不能直接发出去的,不然就乱了,在客户端想复原图片就是不可能的了。那要如何保证这一点呢?
将一个视频分成好多帧,一个帧有好多片,还有宏块,子块。这些子块构成一个序列,这时需要有一个能将这些子块构成序列的办法。保证它们可以通过TCP协议传输到网络另一端,并且能复原成一个视频。这个办法就是包装帧片的 网络提取层单元(NALU)。
每个NALU 由:起始标识符,NALU头,和Payload组成的。
NALU头里面,主要是内容类型NAL Type。
-
SPS,是序列参数集,包括一个图像序列的所有信息,如图像尺寸,视频格式等。
-
PPS,是图像参数集,包括一个图像的所有分片的所有相关信息,包括图像类型、序列号等。
要从视频流中解码出视频,这两个参数是必须的。为保证容错性,每个I 帧前面,都会传一遍这两个参数。
整个视频的格式是这样的。一个视频可以分成好多帧,一个帧可以分成好多片,每一片都放到一个NALU 里面,NALU 之间都是通过特殊的起始标识符分隔,在每个I 帧的第一片前面,要插入单独保存SPS 和PPS 的NALU,最终形成一个长长的NALU 序列。
推流 :把数据流打包传输到对端
如何将二进制的流打包成网络包发送出去,这里需要RTMP 协议。
RTMP 协议是一个实时信息传输协议,Adobe 公司提出,用来解决多媒体数据传输流的多路复用,和分包问题的协议。它建立在TCP协议之上,它主要保证两个事情,一个是版本号,一个是时间戳。
RTMP协议也是需要类似于TCP 一样的连接。就是在接收实时信息时先得了解一下发送和接收方的情况。总不能两眼一抹黑的上来就发消息吧。
要传输实时消息,要事先确定些什么呢?看看RTMP协议是怎么做的,只需要发送六条消息,就搞定了。如下图所示:
1、首先客户端发送 C0,表示自己的版本号,不用等对方回复,直接再发C1,表明自己的时间戳。
2、服务端收到C0 后,才能返回S0,表明自己的版本号,如果不匹配就断开连接。发送完S0 后,服务端继续发S1,表明自己的时间戳。
3、客户端收到S1 后,回送给服务端一个ack,表明自己接收到服务端的时间戳了。
4、同样,服务端收到C1 后,回送给客户端一个ack,表明自己收到客户端的时间戳了。
到此,握手完成!
握手完成只是建立好连接,双方还需要传递一些控制信息,例如Chunk 块的大小,窗口大小等。
真正传输数据时还要创建一个Stream,然后通过这个Stream 来推流(publish),就是将NALU 放在Message里发送,这个Message也称为RTMP Packet 包。Message 的格式像下面这样。
将大的消息变为小的块再发送,可以在低带宽的情况下,减少网络拥塞。
整个数据流的传输过程就像下面这样:
下面是观众客户端的拉流过程:
分发网络
下面说一下服务端的分发网络,它们解决了大量观众给服务器造成压力的问题。
分发网络分为中心和边缘两层。边缘层服务器部署在全国各地,以及横跨各大运营商里,和用户距离很近。中心是流媒体服务集群,负责内容的转发。
智能负载均衡系统,根据用户的地理位置信息,就近选择边缘服务器,为用户提供推/ 拉流服务。
这套机制还会涉及DNS、HTTPDNS、CDN 等等技术。