美文网首页iOS视频开发
音视频流媒体开发【四十七】RTMP流媒体3-直播推流2

音视频流媒体开发【四十七】RTMP流媒体3-直播推流2

作者: AlanGe | 来源:发表于2023-04-17 20:50 被阅读0次

    音视频流媒体开发-目录
    iOS知识点-目录
    Android-目录
    Flutter-目录
    数据结构与算法-目录
    uni-pp-目录

    RTMP流媒体Demo

    RTMP简介

    RTMP(Real Time Messaging Protocol)是一个应用层协议,主要用于 在Flash player和服务器之间传输视频、音频、控制命令等内容。 该协议的突出优点是: 低延时。

    RTMP基于TCP, 默认使用端口1935。

    RTMP 名词解析

    Payload (有效载荷):包含于一个数据包中的数据,例如音频采样或者压缩的视频数据。

    Packet (数据包):一个数据包由一个固定头和有效载荷数据构成。一些底层层协议可能会要求对数据包定Н封装。

    Port (端口):传输协议用以区分开指定一台主机的不同目的地的一个抽象。TCP/IP使用小的正整数对端口进行标识。OSI传输层使用的运输选择器(TSEL)相当于端口。

    Transport address (传输地址):用以识别传输层端点的网络地址和端口的组合,例如一个IP地址和一个TCP端口。数据包由一个源传输地址传送到一个目的传输地址。

    Message stream (消息流):通信中消息流通的一个逻辑通道。

    Message stream ID(消息流ID):每个消息有一个关联的ID,使用ID可以识别出流通中的消息流。

    Chunk (块):消息的一段。消息在网络发送之前被拆分成很多小的部分。块可以确保端到端交付所有消息有序timestamp,即使有很多不同的流。

    Chunk stream(块流):通信中允许块流向一个特定方向的逻辑通道。块流可以从客户端流向服务器,也可以从服务器流向客户端。

    Chunk stream ID(块流ID):每个块有一个关联的ID,使用ID可以识别出流通中的块流。

    Multiplexing(合成):将独立的音频/视频数据合成为一个连续的音频/视频流的加工,这样可以同时发送几个视频和音频。

    DeMultiplexing(分解):Multiplexing 的逆向处理,将交叉的音频和视频数据还原成原始音频和视频数据的格式。

    Remote Procedure Call (RPC远程方法调用):允许客户端或服务器调用对端的一个子程序或者程序的请求。

    Metadata (元数据):关于数据的一个描述。一个电影的 metadata包括电影标题、持续时间、创建时间等等。

    Application Instance (应用实例):服务器上应用的实例,客户端可以连接这个实例并发送连接请求。

    Action Message Format (AMF动作消息格式协议):一个用于序列化 ActionScript对象图的紧凑的二进制格式。AMF有两个版本:AMF O [AMFO]和AMF 3 [AMF3]。

    RTMP推流拉流

    FFMPEG推流+FFPLAY播放
    推流:ffmpeg -re -i /mnt/hgfs/linux/vod/35.mp4 -c copy -f flv rtmp://192.168.100.41/live/35
    拉流:ffplay rtmp://192.168.100.41/live/35
    
    FFPLAY播放
    拉流:ffplay rtmp://202.69.69.180:443/webcast/bshdlive-pc
    

    RTMP播放基本流程

    推流流程

    播流流程

    Step 1: TCP三次握手 - 修高速公路

    RTMP是基于TCP的应用层协议。
    通过TCP三次握手,可实现RTMP客户端与RTMP服务器的指定端口(默 认端口为1935)建立一个可靠的网络连接。
    这里的网络连接才是真正的物理连接。
    完成了三次握手,客户端和服务器端就可以开始传送数据。

    [图片上传失败...(image-46c148-1681736408459)]

    image.png

    经过三次握手,客户端与服务器端1935端口建立了TCP Connection。

    Step 2: RTMP握手 - 安检

    与其叫RTMP握手,其实实质上起到的是验证的作用。

    RTMP握手的基本流程:

    RTMP握手主要分为: 简单握手和复杂握手。

    Step 2: RTMP握手 - 简单握手

    协议版本号(8bit) C0:客户端版本
    S0:服务器版本 目前版本为3,(0,1,2已经废弃)
    C1和S1数据包的长度都是1536字节

    03(C0) 00(C1开始) 00 00 00 09 00 7c 02 f7 78 55 1e ce ab 8e
    S1片段:00 90 65 30 0d 0e 0a 0d 64 84 1c ad 1e 7f 0c
    C2 和 S2 数据包长度都是 1536 字节,基本就是 S1 和 C1 的副本。

    S2片段

    Step 2: RTMP握手 – 复杂握手

    相对于简单握手,复杂握手主要是增加了更严格的验证。 主要是将简单握手中1528Bytes随机数的部分平均分成两部分, 一部分764Bytes存储public key(公共密钥),另一部分 764Bytes存储digest(密文,32字节)。

    另外, 复杂握手还有一个明显的特征就是: Version部分不为0, 服务器端可根据这个来判断是否简单握手或复杂握手。

    Step 3: connect(连接)

    这里也叫连接,连接的是什么呢? 这里必须明白RTMP中一个很重要的概念: Application Instance。

    不同的 Application Instance可根据功能等进行区分,比如直播可以 用live来表示,点播回放可以用vod来表示。

    rtmp://192.168.100.41/live/36
    其中live就是Application Instance(sport, music)
    播放该流时,connect的地址就是 rtmp://192.168.100.41/live/36

    Step 4: createStream(创建流) - 创建逻辑通道

    createStream命令用于创建逻辑通道,该通道用于传输视频、音频、 metadata。

    在服务器的响应报文中会返回 ,用于唯一的标示该 Stream。

    注:Message ID和Stream ID的区别

    The command structure from the client to the server is as follows:

    The command structure from server to client is as follows:

    Step 5: play(播放)

    客户端发送play命令来播放指定流。开始传输音视频数据。 如果发送play命令后想要立即播放,需要清空play队列中的其它 流,并将reset置为true。

    Step 6: deleteStream(删除流)

    The command structure from the client to the server is as follows:

    删除指定Stream ID的流。
    服务器不用对这条命令发送响应报文。

    RTMP层次

    RTMP层次 (数据发送角度)
    RTMP层次 (数据接收角度)
    RTMP层次 (协议角度)

    RTMP层次 (数据角度)

    RTMP层次 (数据发送角度)

    RTMP层次 (数据接收角度)

    RTMP关键结构

    Message & Chunk

    Message RTMP中一个重要的概念就是消息。

    消息分类 – Message Type

    消息主要分为三类: 协议控制消息、数据消息、命令消息等。

    协议控制消息

    Message Type ID = 1 2 3 5 6和Message Type ID = 4两大类,主 要用于协议内的控制,此部分后续将详细分析。

    数据消息

    Message Type ID = 8 9 18
    8: Audio 音频数据
    9: Video 视频数据
    18: Metadata 包括音视频编码、视频宽高等信息。

    命令消息 Command Message (20, 17)

    此类型消息主要有NetConnection和NetStream两个类,两个类分别 有多个函数,该消息的调用,可理解为远程函数调用。

    消息分类 – Stream ID

    Message StreamID是音视频流的唯一ID, 一路流如果既有音频包又 有视频包,那么这路流音频包的StreamID和他视频包的StreamID相 同。

    Message & Chunk

    Chunk 网络中实际发送的内容。

    image.png
    Chunk Stream ID

    Each chunk that is created has a unique ID associated with it called chunk stream ID 。(5.3. Chunking)

    问题:因为一个流当中可以交错传输多种消息类型的Chunk,那 么多个Chunk怎么标记同属于同一类Message的呢?

    答案:是通过Chunk Stream ID区分的,同一个Chunk Stream ID 必然属于同一个Message

    RTMP流中视频和音频拥有单独的Chunk Stream ID
    比如音频的cs id=20,视频的cs id=21。
    接收端接收到Chunk之后,根据cs id分别将音频和视频“拼成消息”。

    Message & Chunk

    Message被切割成一个或多个Chunk,然后在网络上进 行发送。

    当发送时,一个chunk发送完毕后才可以发送下一个 chunk。

    拆分的时候,默认的Chunk Size是128字节,以Message大 小为300字节举例,进行拆分。
    300 = 128 + 128 + 44

    RTMP实质

    • 发送端
      首先将数据加工成消息(中间物),然后再将消息分割成 Chunk(加上Chunk Header),然后将Chunk通过网络发送出去。
    • 接收端
      接收端将接收到的Chunk组装成消息。

    RTMP层次 (协议角度)

    RTMP Chunk Header

    RTMP Chunk Header的长度不是固定的,分为: 12 Bytes、8 Bytes、4 Bytes、1 Byte 四种,由RTMP Chunk Header前2位决定。

    chunk type 与 chunk header length的对应关系

    4种type对比

    RTMP Chunk Header

    RTMP Chunk Header-为什么存在不同长度?

    一般情况下,msg stream id是不会变的,所以针对视频或音频, 除 了第一个RTMP Chunk Header是12Bytes的,后续即可采用8Bytes 的。 (5.3. Chunking)

    如果消息的长度(message length)和类型(msg type id, 如视频为9或音 频为8)又相同,即可将这两部分也省去,RTMP Chunk Header采用 4Bytes类型的。

    如果当前Chunk与之前的Chunk相比, msg stream id相同,msg type id相同,message length相同,而且都属于同一个消息(由同一个 Message切割成),这类Chunk的时间戳(timestamp)也是相同的,故后 续的也可以省去,RTMP Chunk Header采用1 Byte类型的。

    当Chunk Size足够大时(一般不这么干),此时所有的Message都只能 相应切割成一个Chunk,该Chunk仅msg stream id相同。此时基本上 除了第一个Chunk的Header是12Bytes外,其它所有Chunk的Header都 是8Bytes。

    RTMP Chunk Header举例(12 Bytes)

    RTMP Header (12 Bytes)

    一般只有rtmp流刚开始的metadata、绝对时间戳的视频或音频是 12Bytes。

    有些控制消息也是12 Bytes, 比如connect。

    RTMP Chunk Header举例(8 Bytes)

    RTMP Chunk Header举例(4 Bytes)

    RTMP Chunk Header举例 (1 Byte)

    RTMP传输基本流程

    • 发送端
      Step 1:把数据封装成消息(Message)。
      Step 2:把消息分割成消息块(Chunk, 网络中实际传输的内容)。
      Step 3:将分割后的消息块(Chunk)通过TCP协议发送出去。

    • 接收端:
      Step 1:在通过TCP协议收到数据后, 先将消息块重新组合成消息(Message)。
      Step 2: 通过对消息进行解封装处理就可以恢复出数据。

    RTMP为什么要将Message划分Chunk?

    在互联网中传输数据时, 消息(Message)会被拆分成更小的单元, 称为消息块(Chunk).

    大的Message被切割成利于在网 络上传输的小Chunk

    切成小块, 可防止大的数据 块(如视频数据)阻塞小的数 据块(如音频数据或控制信 息)。

    如果一帧1080P I帧数据量为244KBytes,假设带宽为10Mbit/s,传输一帧的 耗时为:
    24410248/(1010241024) = 0.190625秒=190毫秒

    假如要实时传输25帧的I帧文件,即允许每帧传输最大耗时为40毫秒,需要 带宽47.65625Mbit,这还没包括传输中的ACK数据。

    RTMP消息优先级

    在RTMP中,消息(Message)主要分为两大类:控制消息和数据消息。

    数据消息中由包括Video消息和Audio消息等。

    消息都是怎么进行管理的?

    通路只有一条(RTMP是单通路),到底谁先走呢,谁后走呢?

    答案是: 分优先级,优先级高的先行。优先级低的不能阻塞 优先级高的。

    RTMP Chunk Stream层级没有优先级的划分,而是在高层次Message stream提供优先级的划分。

    不同类型的消息会被分配不同的优先级,当网络传输能力受限时,优先级用来控制消息在网络底层的排队顺序。

    比如当客户端网络不佳时,流媒体服务器可能会选择丢弃视频消息,以保证音频消息可及时送达客户端。

    注:5. RTMP Chunk Stream

    RTMP Chunk Stream层级允许在Message stream层次,将大消息 切割成小消息,这样可以避免大的低优先级的消息(如视频消息)阻塞 小的高优先级的消息(如音频消息或控制消息)。

    注:5.3. Chunking

    RTMP消息优先级-协议控制消息

    Protocol Control Messages属于RTMP Chunk Stream层级的控制消 息,用于该协议的内部控制。

    RTMP消息优先级-用户控制消息

    Protocol Control Messages属于RTMP Chunk Stream层级的控制消 息,用于该协议的内部控制。

    User Control Messages (4)是RTMP streaming layer(即Message stream层次)的消息。

    RTMP消息优先级 总结

    • 协议先行
      协议控制消息(Protocol Control Messages)和用户控制消息 (User Control Messages)应该包含消息流ID 0(控制流)和块 流ID 2,并且有最高的发送优先级。

    • 数据次之
      数据消息(音频信息、音频消息)比控制信息的优先级低。 另外,一般情况下,音频消息比视频数据优先级高。

    RTMP协议 - 时间戳

    基本介绍

    •RTMP中时间戳的单位为毫秒(ms)
    •时间戳为相对于某个时间点的相对值
    •时间戳的长度为32bit,不考虑回滚的话,最大可表示49天17小 时2分钟47.296秒
    •Timestamp delta单位也是毫秒,为相对于前一个时间戳的一个 无符号整数; 可能为24bit或32bit

    Message时间戳

    Timestamp: Four-byte field that contains a timestamp of the message.

    The 4 bytes are packed in the big-endian order.

    •RTMP Message的时间戳4个字节
    •大端存储

    Chunk时间戳

    用wireshark转包分析发现,rtmp流的chunk视频流(或音频流)除第 一个视频时间戳为绝对时间戳外,后续的时间戳均为timestamp delta,即当前时间戳与上一个时间戳的差值。

    比如帧率为25帧/秒的视频流,timestamp delta基本上都为40ms。

    通常情况下,Chunk的时间戳(包括绝对时间戳和Timestamp delta) 是3个字节。

    但时间戳值超过0xFFFFFF时,启用Extended Timestamp(4个字节) 来表示时间戳。

    通常情况下 -- 3字节

    三字节的timestamp可能为绝对timestamp或timestamp delta。

    timestamp delta的值超过16777215 (即16进制的0xFFFFFF)时,这 时候这三个字节必须被置为: 0xFFFFFF,以此来标示Extended

    Timestamp(4字节)将会存在,由Extended Timestamp来表示时间戳。

    相关文章

      网友评论

        本文标题:音视频流媒体开发【四十七】RTMP流媒体3-直播推流2

        本文链接:https://www.haomeiwen.com/subject/jmrqjdtx.html