rtmp 看一篇就够了

目录

1 Rtmp 定义

2 Rtmp 基础
3 协议组成
4 Rtmp 消息流程
5 实例分析:项目使用librtmp接口
6 主要Rtmp函数源码分析
7 QA

正文

相关系列文章

H264解析:H264解析_fdsafwagdagadg6576的专栏-CSDN博客_rtp帧格式
Flv 格式分析参见:https://www.jianshu.com/p/27d506edd4e4
ngnix-rtmp :Ngnix Rtmp_fdsafwagdagadg6576的专栏-CSDN博客

在这里插入图片描述

1 Rtmp定义

定义:Rtmp是一种音视频数据在网络上传输的网络协议.类似Http是一种网页文本数据在网络上传输的网络协议.音视频传输协议还有HLS,RTSP等.

原理

Rtmp作用:rtmp是传输flv的流媒体协议.也就是将音视频包封装成flv tag发送.
Rtmp特点是chunk,将flv数据放入一个个小的chunk中传输.
Rtmp基于Tcp协议. Port is 1935.
Librtmp/Rtmpdump 是一个用来处理 RTMP 流媒体的工具包.
Rtmp使用请参考:FFMpeg处理RTMP流的总结_北雨南萍-CSDN博客

2 基础

H264->FLV封装->rtmp 封装

h264=nalu1+nalu2+...;
nalu加上变成了flv tag header变成flv tag. flv = flv tag1+flv tag2+....
flv tag放入chunk data中. rtmp消息=rtmp header + chunk data.

3 协议组成

3.1 rtmp协议:消息格式+流程

1 ) rtmp 消息格式:

image
image
  • 整体结构

Rtmp msg= Rtmp header + chunk data;
Rtmp header= Basice header + Chunk msg header + Ext Timestamp;
Chunk msg header = Flv tag header=Timestamp+body size+ TypeID+StreamID;

  • 各个域介绍
image
Rtmp struct ://12bytes
        packet.m_headerType    = RTMP_PACKET_SIZE_LARGE; //0x00
        packet.m_packetType    = RTMP_PACKET_TYPE_AUDIO;  //type is 0x08 or 09
        packet.m_nChannel      = RTMP_AUDIO_CHANNEL;   //0x04,channel is chunk msg id,it headerType 后6bit,对于a/v data是固定数据04
        packet.m_nTimeStamp    = item->m_dwTimeStamp;   //timestamp
        packet.m_nInfoField2   = m_pub_rtmp.m_stream_id ;//chunk stream id,it is always 0
        packet.m_nBodySize     = item->m_dwSize + RTMP_AUIDO_FRAME_SIZE ;

2 ) chunk msg header

i) basic header and chunk msg header长度
basic header和chunk msg header是变长的.basic header 1-3个字节. chunk msg header 0,3,7,11字节.
basic header的前两个2bit决定了,chunk msg header的字节长度是11 bytes,7 bytes,3 bytes还是0 bytes.
basic header的chunk stream id的大小,决定basic header是1 bytes,2 bytes or 3 bytes。如何区分参见:librtmp协议分析---RTMP_SendPacket函数_终究还是能力达不到预期的目标-CSDN博客.
ii ) chunk msg header结构
注意chunk msg header就是flv tag header.分成script(0x12),video(0x9),audio(0x08) 3种.
下面的消息图以basic header 1 bytes 为例。basic header 与 4种chunk msg header 的关系.
其中第一个字节是basic header,其他字节是chunk msg header.
chunk msg header作用:它 决定了一个msg 放入一个chunk data ,还是放入多个chunk data.

image

image.png

image.png

image.png

上述图片参见:RTMP Chunk Header - 里面还有抓包分析

3 ) 4种chunk msg 应用场景

上面的4副图表示msg0-3 4中消息类型.
msg0 带有绝对时间,用于发送metadata, 发送第一次 video,audio.
msg3 只有basic header,没有chunk msg header,直接加上chunk data。
用于一个msg被分成多个chunk,第一个chunk 是msg0,后面的chunk 采用msg3的格式。

4 ) basic header和 chunk msg header 关系导图

image

image

参见:librtmp协议分析---RTMP_SendPacket函数_终究还是能力达不到预期的目标-CSDN博客
5 ) 抓包分析

image

第一个字节headerType is 0x03, 后6 bit 是11,即channelid=chunk msg id=0x03.
查表得出是invoke消息(connect or publish).
00 00 00 is 时间戳Timer=0.
00 01 02 is AMFSize=18.
14 查表表示AMFType=invoke.
00 00 00 00 表示streamid总是0.

上面是12字节的rtmp协议头,下面是amf语法
02 is string, 0007 is string len is 7.
63 6F 6E 6E 65 63 74 is string ascii value "connect".
00 is double.
3F F0 00 00 00 00 00 00 is double value 0.0
08 is map begin

参考查表:https://wenku.baidu.com/view/cdc944114afe04a1b171de86.html

6 ) 实例分析

 a. 发送aac音频包:

编码器的打包大小为320字节,时间间隔为40ms,假设块大小设定为1000,几个音频包的时间戳依次为1000、1040、1080、1120.....,则可能的发送格式如下所示:

| rtmp packet | format | timestamp | message length | packet size |
| #1 | fmt0 | 1000 | 320 | 320+1+11 |
| #2 | fmt2 | 40 | x | 320+1+3 |
| #3 | fmt3 | x | x | 320+1 |
| #4 | fmt3 | x | x | 320+1 |

注:上例我们也可以每个包都用fmt0来发送,这样的话,每个包都要指定准确的时间戳和长度。

 b. 发送视频包:

时间间隔为40ms,假设块大小设定为1000,几个视频包的时间戳依次为1000、1040.....,大小依次为2500,1600,....则可能的发送格式如下所示: (一个msg分包实例,第一个包是fmt0,第二个以后是fmt3)

| rtmp packet | format | timestamp | message length | packet size |
| #1 | fmt0 | 1000 | 2500 | 1000+1+11 |
| #2 | fmt3 | x | x | 1000+1 |
| #3 | fmt3 | x | x | 500+1 |
| #4 | fmt0 | 1040 | 1500 | 1000+1+11 |
| #5 | fmt3 | x | x | 600+1 |

      注:上例中如果每帧的音频间隔是相等,第二帧的第一个包(#4),我们也可以用fmt1来发送,将消息头中的timestamp指定为时间差。并指定帧长。

4 Rtmp 消息流程

协议流程:RTMP流媒体播放过程:握手(handshake),建立连接,建立流,播放.
Librtmp封装了上述流程. Ngx-rtmp 实现协议,请参见:Ngnix Rtmp_fdsafwagdagadg6576的专栏-CSDN博客

image

相关源码参考:【原】librtmp源码详解 - 尚码园.
上述源码分析通常用不到,仅仅适合调试备用.

整体流程

 基本的播放流程:收到连接请求-》应答连接成功-》收到播放请求-》检测点播的流是否存在-》发送stream begin消息-》发送paly.start消息—-》连续发送音视数据-》...-》直接收到关闭连接请求或播放到文件末尾. 
image

参考:https://my.oschina.net/u/1983790/blog/686521

5 实例分析:项目使用librtmp接口

rtmp封装h264流程:nalu 第一层添加video tag data header,第二层添加video.
Tag header,第三层添加rtmp header.
然后将msg分包成多个chunk. 参见RTMP_SendPacket
引用参考:流媒体之RTMP——librtmp推流测试_一步的专栏-CSDN博客_librtmp推流

6 主要Rtmp函数源码分析

RTMP_ReadPacket 源码看是实现组合chunk为一个msg。
librtmp 源码分析笔记 RTMP_ReadPacket_lucyTheSlayer的博客-CSDN博客_rtmp_readpacket
RTMP_ClientPacket 是case 不同消息类型,0x12 metadata,0x09 video,0x08 audio
librtmp协议分析---RTMP_ConnectStream函数_终究还是能力达不到预期的目标-CSDN博客
librtmp协议分析---RTMP_SendPacket函数:将一个msg分成多个chunk data发送
https://blog.csdn.net/xwjazjx1314/article/details/54863428

7 QA: Rtmp 和flv什么关系?

Rtmp是流媒体传输协议,可以传输h264和flv格式的数据.
Flv的Metadata 是怎么通过rtmp传输的呢?Metadata属于script tag,是按照script tag的方式传输的,即header tag is 0x12.
Flv和h264什么关系?
Flv是文件格式,其中的video数据,通常用h264格式(也可以是h265,v8等).
Flv 的本质是flv tag,将每帧封装到一个tag中,而且每个tag都有时间戳,这样也支持点播了.

image

你可能感兴趣的:(rtmp 看一篇就够了)