RTMP协议详解

目录

概述:

rtmp播放流程

代码示例:


概述:

RTMP协议是Real Time Message Protocol(实时信息传输协议)的缩写,它是由Adobe公司提出的一种应用层的协议,用来解决多媒体数据传输流的多路复用(Multiplexing)和分包(packetizing)的问题。

RTMP协议是应用层协议,是要靠底层可靠的传输层协议(通常是TCP)来保证信息传输的可靠性的。在基于传输层协议的链接建立完成后,RTMP协议也要客户端和服务器通过“握手”来建立基于传输层链接之上的RTMP Connection链接。

RTMP一般在一个TCP通道上传输flv,f4v格式流和命令。

RTSP传输一般需要 2-3 个通道,命令和数据通道分离;TS和MP4。

概念

有效负载:包含在每一个包中的数据,就像音视频样本或压缩后的视频数据。

包: 一个数据包是由固定的包头和有效的负载数据来组成的。

端口:rtmp协议默认使用的是1935端口。

消息流:一个通信的逻辑通道,让消息流通

消息流id:每个消息拥有一个分配的id,标识消息流。

消息块:消息的一个片段,一个完整的消息会被分割成小的片段,每个片段都是一个消息块。

消息块流:一个通信的逻辑通道,允许消息块在一个特定方向流通,例如:从客户端到服务器。

消息块流id:每个消息块有一个分配的id用于识别跟随消息块流。

复合技术:把分开的音视频数据组合成一条音视频流的过程。

逆复合技术:复合的反向过程,交叉存取组装的音视频数据,是他们成为最初的音视频数据。

时间戳:在rtmp消息块中的时间戳使用整数来表示,但是为毫秒。时间戳必须是线性增加的,允许引用程序处理异步传输,带宽度量,检测,流控制。

RTMP协议详解_第1张图片

                                                      图1 RTMP协议流程

bilibili pc端直播(libobs26.1.1推流,rtmp)wireshark截取摘要如下:(192.168.1.5本机IP)

122775    2233.876959    192.168.1.5    111.62.90.116    RTMP    1591    Handshake C0+C1

122783    2233.890926    192.168.1.5    111.62.90.116    RTMP    1590    Handshake C2

122784    2233.902499    111.62.90.116    192.168.1.5    RTMP    138    Handshake C2

122787    2233.903620    192.168.1.5    111.62.90.116    RTMP    283    Set Chunk Size 4096|connect('live-bvc')

122790    2233.916266    111.62.90.116    192.168.1.5    RTMP    70    Window Acknowledgement Size 5000000

122794    2233.975749    111.62.90.116    192.168.1.5    RTMP    333    Set Peer Bandwidth 5000000,Dynamic|Set Chunk Size 4096|_result('NetConnection.Connect.Success')

122795    2233.976037    192.168.1.5    111.62.90.116    RTMP    186    releaseStream('?streamname=live_2039896039_16392939&key=519686c99f3b1a4200eab44d83621b9d&schedule=rtmp&pflag=2')

122798    2233.988083    192.168.1.5    111.62.90.116    RTMP    215    FCPublish('?streamname=live_2039896039_16392939&key=519686c99f3b1a4200eab44d83621b9d&schedule=rtmp&pflag=2')|createStream()

122800    2234.000070    111.62.90.116    192.168.1.5    RTMP    95    _result()

122801    2234.000192    192.168.1.5    111.62.90.116    RTMP    191    publish('?streamname=live_2039896039_16392939&key=519686c99f3b1a4200eab44d83621b9d&schedule=rtmp&pflag=2')

122804    2234.067911    111.62.90.116    192.168.1.5    RTMP    171    onStatus('NetStream.Publish.Start')

122805    2234.068238    192.168.1.5    111.62.90.116    RTMP    467    @setDataFrame()音视频编码信息

122819    2234.386047    192.168.1.5    111.62.90.116    RTMP    73    Audio Data

122820    2234.386204    192.168.1.5    111.62.90.116    RTMP    4232    Video Data

122821    2234.386240    192.168.1.5    111.62.90.116    RTMP    4151    Video Data

122822    2234.386264    192.168.1.5    111.62.90.116    RTMP    4151    Video Data

122823    2234.386290    192.168.1.5    111.62.90.116    RTMP    4151    Unknown (0x0)

122824    2234.386322    192.168.1.5    111.62.90.116    RTMP    1506    Unknown (0x0)

122825    2234.398021    111.62.90.116    192.168.1.5    TCP    60    1935 → 59645 [ACK] Seq=3527 Ack=4165 Win=42496 Len=0

122835    2234.398316    192.168.1.5    111.62.90.116    RTMP    24738    Unknown (0x0)

122854    2234.418696    192.168.1.5    111.62.90.116    RTMP    2335    Video Data

122876    2234.452212    192.168.1.5    111.62.90.116    RTMP    4102    Video Data

122880    2234.485544    192.168.1.5    111.62.90.116    RTMP    623    Audio Data

122882    2234.497523    192.168.1.5    111.62.90.116    RTMP    638    Audio Data

523792    2681.306871    192.168.1.5    111.62.90.116    RTMP    4151    Abort Message -684195369|Unknown (0x0)关闭直播

RTMP协议详解_第2张图片

rtmp播放流程

RTMP协议规定,播放一个流媒体有两个前提步骤:第一步,建立一个网络连接(NetConnection);第二步,建立一个网络流(NetStream)。其中,网络连接代表服务器端应用程序和客户端之间基础的连通关系。网络流代表了发送多媒体数据的通道。服务器和客户端之间只能建立一个网络连接,但是基于该连接可以创建很多网络流。播放一个RTMP协议的流媒体需要经过以下几个步骤:握手,建立连接,建立流,播放。RTMP连接都是以握手作为开始的。建立连接阶段用于建立客户端与服务器之间的“网络连接”;建立流阶段用于建立客户端与服务器之间的“网络流”;播放阶段用于传输视音频数据。

RTMP协议详解_第3张图片

                                                          图2  RTMP使用流程

InitSockets():初始化Socket
RTMP_Alloc():为结构体“RTMP”分配内存。
RTMP_Init():初始化结构体“RTMP”中的成员变量。
RTMP_SetupURL():设置输入的RTMP连接的URL。
RTMP_Connect():建立RTMP连接,创建一个RTMP协议规范中的NetConnection。
RTMP_ConnectStream():创建一个RTMP协议规范中的NetStream。
RTMP_Read():从服务器读取数据。
RTMP_Close():关闭RTMP连接。
RTMP_Free():释放结构体“RTMP”。

CleanupSockets():关闭Socket。

RTMP协议详解_第4张图片

                                                           图3  建立网络连接

RTMP协议详解_第5张图片

                                                           图4  建立网络流播放

代码示例:

#include     
#include "librtmp/rtmp_sys.h"    
#include "librtmp/log.h"    

int InitSockets()
{
	WORD version;
	WSADATA wsaData;
	version = MAKEWORD(1, 1);
	return (WSAStartup(version, &wsaData) == 0);
}

void CleanupSockets()
{
	WSACleanup();
}

int main(int argc, char* argv[])
{
	InitSockets();

	double duration = -1;
	int nRead;
	//is live stream ?    
	bool bLiveStream = true;


	int bufsize = 1024 * 1024 * 10;
	char *buf = (char*)malloc(bufsize);
	memset(buf, 0, bufsize);
	long countbufsize = 0;

	FILE *fp = fopen("receive.flv", "wb");
	if (!fp){
		RTMP_LogPrintf("Open File Error.\n");
		CleanupSockets();
		return -1;
	}

	/* set log level */
	//RTMP_LogLevel loglvl=RTMP_LOGDEBUG;    
	//RTMP_LogSetLevel(loglvl);    

	RTMP *rtmp = RTMP_Alloc();
	RTMP_Init(rtmp);
	//set connection timeout,default 30s    
	rtmp->Link.timeout = 10;
	// HKS's live URL    
	if (!RTMP_SetupURL(rtmp, "rtmp://live.hkstv.hk.lxdns.com/live/hks"))
	{
		RTMP_Log(RTMP_LOGERROR, "SetupURL Err\n");
		RTMP_Free(rtmp);
		CleanupSockets();
		return -1;
	}
	if (bLiveStream){
		rtmp->Link.lFlags |= RTMP_LF_LIVE;
	}

	//1hour    
	RTMP_SetBufferMS(rtmp, 3600 * 1000);

	if (!RTMP_Connect(rtmp, NULL)){
		RTMP_Log(RTMP_LOGERROR, "Connect Err\n");
		RTMP_Free(rtmp);
		CleanupSockets();
		return -1;
	}

	if (!RTMP_ConnectStream(rtmp, 0)){
		RTMP_Log(RTMP_LOGERROR, "ConnectStream Err\n");
		RTMP_Close(rtmp);
		RTMP_Free(rtmp);
		CleanupSockets();
		return -1;
	}

	while (nRead = RTMP_Read(rtmp, buf, bufsize)){
		fwrite(buf, 1, nRead, fp);

		countbufsize += nRead;
		RTMP_LogPrintf("Receive: %5dByte, Total: %5.2fkB\n", nRead, countbufsize*1.0 / 1024);
	}

	if (fp)
		fclose(fp);

	if (buf){
		free(buf);
	}

	if (rtmp){
		RTMP_Close(rtmp);
		RTMP_Free(rtmp);
		CleanupSockets();
		rtmp = NULL;
	}
	return 0;
}

流测试:

rtmp://live.hkstv.hk.lxdns.com/live/hks

​​​​​​​https://www.w3school.com.cn/i/movie.mp4

你可能感兴趣的:(网络,网络)