1、RTMP简介 RTMP(RealTimeMessagingProtocol)是一个应用层协议,主要用于在Flashplayer和服务器之间传输视频、音频、控制命令等内容。该协议的突出优点是:低延时。 RTMP基于TCP,默认使用端口1935。2、RTMP名词解析 Payload(有效载荷):包含于一个数据包中的数据,例如音频采样或者压缩的视频数据。 Packet(数据包):一个数据包由一个固定头和有效载荷数据构成。一些底层层协议可能会要求对数据包定封装。 Port(端口):传输协议用以区分开指定一台主机的不同目的地的一个抽象。TCPIP使用小的正整数对端口进行标识。OSI传输层使用的运输选择器(TSEL)相当于端口。 Transportaddress(传输地址):用以识别传输层端点的网络地址和端口的组合,例如一个IP地址和一个TCP端口。数据包由一个源传输地址传送到一个目的传输地址。 Messagestream(消息流):通信中消息流通的一个逻辑通道。 MessagestreamID(消息流ID):每个消息有一个关联的ID,使用ID可以识别出流通中的消息流。 Chunk(块):消息的一段。消息在网络发送之前被拆分成很多小的部分。块可以确保端到端交付所有消息有序timestamp,即使有很多不同的流。 Chunkstream(块流):通信中允许块流向一个特定方向的逻辑通道。块流可以从客户端流向服务器,也可以从服务器流向客户端。 ChunkstreamID(块流ID):每个块有一个关联的ID,使用ID可以识别出流通中的块流。 Multiplexing(合成):将独立的音频视频数据合成为一个连续的音频视频流的加工,这样可以同时发送几个视频和音频。 DeMultiplexing(分解):Multiplexing的逆向处理,将交叉的音频和视频数据还原成原始音频和视频数据的格式。 RemoteProcedureCall(RPC远程方法调用):允许客户端或服务器调用对端的一个子程序或者程序的请求。 Metadata(元数据):关于数据的一个描述。一个电影的metadata包括电影标题、持续时间、创建时间等等。 ApplicationInstance(应用实例):服务器上应用的实例,客户端可以连接这个实例并发送连接请求。 ActionMessageFormat(AMF动作消息格式协议):一个用于序列化ActionScript对象图的紧凑的二进制格式。AMF有两个版本:AMFO〔AMFO〕和AMF3〔AMF3〕。3、RTMP推流拉流3。1FFMPEG推流FFPLAY播放推流:ffmpegreimnthgfslinuxvod35。mp4ccopyfflvrtmp:192。168。100。41live35拉流:ffplayrtmp:192。168。100。41live353。2FFPLAY播放拉流:ffplayrtmp:202。69。69。180:443webcastbshdlivepc4、RTMP播放基本流程 4。1推流流程 4。2播流流程 4。3Step1:TCP三次握手修高速公路 RTMP是基于TCP的应用层协议。通过TCP三次握手,可实现RTMP客户端与RTMP服务器的指定端口(默认端口为1935)建立一个可靠的网络连接。这里的网络连接才是真正的物理连接。完成了三次握手,客户端和服务器端就可以开始传送数据。 〔图片上传失败。。。(image46c1481681736408459)〕 image。png 经过三次握手,客户端与服务器端1935端口建立了TCPConnection。 C音视频学习资料免费获取方法:关注音视频开发T哥,点击链接即可免费获取2023年最新C音视频开发进阶独家免费学习大礼包! 4。4Step2:RTMP握手安检 与其叫RTMP握手,其实实质上起到的是验证的作用。 RTMP握手的基本流程: RTMP握手主要分为:简单握手和复杂握手。4。5Step3:RTMP握手简单握手 协议版本号(8bit)C0:客户端版本S0:服务器版本目前版本为3,(0,1,2已经废弃)C1和S1数据包的长度都是1536字节 03(C0)00(C1开始)00000009007c02f778551eceab8eS1片段:009065300d0e0a0d64841cad1e7f0cC2和S2数据包长度都是1536字节,基本就是S1和C1的副本。 S2片段 4。6Step4:RTMP握手复杂握手 相对于简单握手,复杂握手主要是增加了更严格的验证。主要是将简单握手中1528Bytes随机数的部分平均分成两部分,一部分764Bytes存储publickey(公共密钥),另一部分764Bytes存储digest(密文,32字节)。 另外,复杂握手还有一个明显的特征就是:Version部分不为0,服务器端可根据这个来判断是否简单握手或复杂握手。 4。7Step5:connect(连接) 这里也叫连接,连接的是什么呢?这里必须明白RTMP中一个很重要的概念:ApplicationInstance。 不同的ApplicationInstance可根据功能等进行区分,比如直播可以用live来表示,点播回放可以用vod来表示。 rtmp:192。168。100。41live36其中live就是ApplicationInstance(sport,music)播放该流时,connect的地址就是rtmp:192。168。100。41live36 4。8Step6:createStream(创建流)创建逻辑通道 createStream命令用于创建逻辑通道,该通道用于传输视频、音频、metadata。 在服务器的响应报文中会返回,用于唯一的标示该Stream。 注:MessageID和StreamID的区别 Thecommandstructurefromtheclienttotheserverisasfollows: Thecommandstructurefromservertoclientisasfollows: 4。9Step7:play(播放) 客户端发送play命令来播放指定流。开始传输音视频数据。如果发送play命令后想要立即播放,需要清空play队列中的其它流,并将reset置为true。4。10Step8:deleteStream(删除流) Thecommandstructurefromtheclienttotheserverisasfollows: 删除指定StreamID的流。服务器不用对这条命令发送响应报文。5、RTMP层次 RTMP层次(数据发送角度)RTMP层次(数据接收角度)RTMP层次(协议角度)5。1RTMP层次(数据角度)5。1。1RTMP层次(数据发送角度) 5。1。2RTMP层次(数据接收角度) 6、RTMP关键结构 MessageChunk MessageRTMP中一个重要的概念就是消息。 6。1消息分类MessageType 消息主要分为三类:协议控制消息、数据消息、命令消息等。 协议控制消息 MessageTypeID12356和MessageTypeID4两大类,主要用于协议内的控制,此部分后续将详细分析。 数据消息 MessageTypeID89188:Audio音频数据9:Video视频数据18:Metadata包括音视频编码、视频宽高等信息。 命令消息CommandMessage(20,17) 此类型消息主要有NetConnection和NetStream两个类,两个类分别有多个函数,该消息的调用,可理解为远程函数调用。 消息分类StreamID MessageStreamID是音视频流的唯一ID,一路流如果既有音频包又有视频包,那么这路流音频包的StreamID和他视频包的StreamID相同。6。2MessageChunk Chunk网络中实际发送的内容。 image。png6。2。1ChunkStreamID EachchunkthatiscreatedhasauniqueIDassociatedwithitcalledchunkstreamID。(5。3。Chunking) 问题:因为一个流当中可以交错传输多种消息类型的Chunk,那么多个Chunk怎么标记同属于同一类Message的呢? 答案:是通过ChunkStreamID区分的,同一个ChunkStreamID必然属于同一个Message RTMP流中视频和音频拥有单独的ChunkStreamID比如音频的csid20,视频的csid21。接收端接收到Chunk之后,根据csid分别将音频和视频拼成消息。6。3MessageChunk Message被切割成一个或多个Chunk,然后在网络上进行发送。 当发送时,一个chunk发送完毕后才可以发送下一个chunk。 拆分的时候,默认的ChunkSize是128字节,以Message大小为300字节举例,进行拆分。30012812844 7、RTMP实质发送端首先将数据加工成消息(中间物),然后再将消息分割成Chunk(加上ChunkHeader),然后将Chunk通过网络发送出去。接收端接收端将接收到的Chunk组装成消息。 7。1RTMP层次(协议角度) 7。2RTMPChunkHeader RTMPChunkHeader的长度不是固定的,分为:12Bytes、8Bytes、4Bytes、1Byte四种,由RTMPChunkHeader前2位决定。 chunktype与chunkheaderlength的对应关系 7。34种type对比 7。4RTMPChunkHeader 7。5RTMPChunkHeader为什么存在不同长度? 一般情况下,msgstreamid是不会变的,所以针对视频或音频,除了第一个RTMPChunkHeader是12Bytes的,后续即可采用8Bytes的。(5。3。Chunking) 如果消息的长度(messagelength)和类型(msgtypeid,如视频为9或音频为8)又相同,即可将这两部分也省去,RTMPChunkHeader采用4Bytes类型的。 如果当前Chunk与之前的Chunk相比,msgstreamid相同,msgtypeid相同,messagelength相同,而且都属于同一个消息(由同一个Message切割成),这类Chunk的时间戳(timestamp)也是相同的,故后续的也可以省去,RTMPChunkHeader采用1Byte类型的。 当ChunkSize足够大时(一般不这么干),此时所有的Message都只能相应切割成一个Chunk,该Chunk仅msgstreamid相同。此时基本上除了第一个Chunk的Header是12Bytes外,其它所有Chunk的Header都是8Bytes。7。6RTMPChunkHeader举例(12Bytes) RTMPHeader(12Bytes) 一般只有rtmp流刚开始的metadata、绝对时间戳的视频或音频是12Bytes。 有些控制消息也是12Bytes,比如connect。 7。7RTMPChunkHeader举例(8Bytes) 7。8RTMPChunkHeader举例(4Bytes) 7。9RTMPChunkHeader举例(1Byte) 8、RTMP传输基本流程 发送端Step1:把数据封装成消息(Message)。Step2:把消息分割成消息块(Chunk,网络中实际传输的内容)。Step3:将分割后的消息块(Chunk)通过TCP协议发送出去。接收端:Step1:在通过TCP协议收到数据后,先将消息块重新组合成消息(Message)。Step2:通过对消息进行解封装处理就可以恢复出数据。8。1RTMP为什么要将Message划分Chunk? 在互联网中传输数据时,消息(Message)会被拆分成更小的单元,称为消息块(Chunk)。 大的Message被切割成利于在网络上传输的小Chunk 切成小块,可防止大的数据块(如视频数据)阻塞小的数据块(如音频数据或控制信息)。 如果一帧1080PI帧数据量为244KBytes,假设带宽为10Mbits,传输一帧的耗时为:24410248(1010241024)0。190625秒190毫秒 假如要实时传输25帧的I帧文件,即允许每帧传输最大耗时为40毫秒,需要带宽47。65625Mbit,这还没包括传输中的ACK数据。8。2RTMP消息优先级 在RTMP中,消息(Message)主要分为两大类:控制消息和数据消息。 数据消息中由包括Video消息和Audio消息等。 消息都是怎么进行管理的? 通路只有一条(RTMP是单通路),到底谁先走呢,谁后走呢? 答案是:分优先级,优先级高的先行。优先级低的不能阻塞优先级高的。 RTMPChunkStream层级没有优先级的划分,而是在高层次Messagestream提供优先级的划分。 不同类型的消息会被分配不同的优先级,当网络传输能力受限时,优先级用来控制消息在网络底层的排队顺序。 比如当客户端网络不佳时,流媒体服务器可能会选择丢弃视频消息,以保证音频消息可及时送达客户端。 注:5。RTMPChunkStream RTMPChunkStream层级允许在Messagestream层次,将大消息切割成小消息,这样可以避免大的低优先级的消息(如视频消息)阻塞小的高优先级的消息(如音频消息或控制消息)。 注:5。3。Chunking 8。2。1RTMP消息优先级协议控制消息 ProtocolControlMessages属于RTMPChunkStream层级的控制消息,用于该协议的内部控制。8。2。2RTMP消息优先级用户控制消息 ProtocolControlMessages属于RTMPChunkStream层级的控制消息,用于该协议的内部控制。 UserControlMessages(4)是RTMPstreaminglayer(即Messagestream层次)的消息。8。3RTMP消息优先级总结协议先行协议控制消息(ProtocolControlMessages)和用户控制消息(UserControlMessages)应该包含消息流ID0(控制流)和块流ID2,并且有最高的发送优先级。数据次之数据消息(音频信息、音频消息)比控制信息的优先级低。另外,一般情况下,音频消息比视频数据优先级高。8。4RTMP协议时间戳 基本介绍 RTMP中时间戳的单位为毫秒(ms)时间戳为相对于某个时间点的相对值时间戳的长度为32bit,不考虑回滚的话,最大可表示49天17小时2分钟47。296秒Timestampdelta单位也是毫秒,为相对于前一个时间戳的一个无符号整数;可能为24bit或32bit Message时间戳 Timestamp:Fourbytefieldthatcontainsatimestampofthemessage。 The4bytesarepackedinthebigendianorder。 RTMPMessage的时间戳4个字节大端存储8。5Chunk时间戳 用wireshark转包分析发现,rtmp流的chunk视频流(或音频流)除第一个视频时间戳为绝对时间戳外,后续的时间戳均为timestampdelta,即当前时间戳与上一个时间戳的差值。 比如帧率为25帧秒的视频流,timestampdelta基本上都为40ms。 通常情况下,Chunk的时间戳(包括绝对时间戳和Timestampdelta)是3个字节。 但时间戳值超过0xFFFFFF时,启用ExtendedTimestamp(4个字节)来表示时间戳。 通常情况下3字节 三字节的timestamp可能为绝对timestamp或timestampdelta。 timestampdelta的值超过16777215(即16进制的0xFFFFFF)时,这时候这三个字节必须被置为:0xFFFFFF,以此来标示Extended Timestamp(4字节)将会存在,由ExtendedTimestamp来表示时间戳。 原文链接:音视频流媒体开发【四十六】RTMP流媒体3直播拉流简书