RTSP服务器:RTP over TCP

点击 RTSP实时监控项目:项目索引,回到目录。
image-20210625175348651

协议回顾

RTP协议负责实际数据的传输。通常使用UDP来传送数据,但RTP也可以在TCP或ATM等其他协议之上工作。

基于UDP的RTP和基于TCP的RTP各有千秋。如果需要低延时,可容忍部分数据丢失,选用UDP;如果需要可靠性高,对实时性要求不高,选用TCP。这里只简单地说明两者的优缺点,在具体项目中需要考虑的细节可能远不止上面几点。


RTP/AVP & RTP/AVP/TCP

推荐阅读:https://www.jianshu.com/p/7b9793eb2f4e

RTSP流(传输RTP包)的传输方式有两种:RTP/AVP/UDP(即RTP/AVP)和 RTP/AVP/TCP

1)采用那种方式传输是由客户端决定的

VLC客户端中设置RTP over TCP:
工具->偏好设置->输入/编解码器->RTP over RTSP(TCP)
image-20210624230517177


2)客户端在RTSP的SETUP命令中需要明确使用TCP传输还是使用UDP传输

① RTP/AVP

---------------C->S--------------
SETUP rtsp://192.168.1.168:1935/live/track1 RTSP/1.0
CSeq: 5
Transport: RTP/AVP;unicast;client_port=51950-51951
Session: 00148940

---------------S->C--------------
RTSP/1.0 200 OK
CSeq: 5
Transport: RTP/AVP;unicast;client_port=51950-51951;server_port=12344-12345
Session: 00148940

② RTP/AVP/TCP

---------------C->S--------------178
SETUP rtsp://192.168.174.3:1935/live/track0 RTSP/1.0
CSeq: 4
User-Agent: LibVLC/3.0.14 (LIVE555 Streaming Media v2016.11.28)
Transport: RTP/AVP/TCP;unicast;interleaved=0-1

---------------S->C--------------
RTSP/1.0 200 OK
CSeq: 4
Transport: RTP/AVP/TCP;unicast;interleaved=0-1
Session: 66334873

3)RTP over TCP,不需要额外的RTP端口和RTCP端口,直接使用原先RTSP与VLC连接的TCP socket传输数据。

因为RTSP、RTP、RTCP都使用同一个socket通道,所以我们需要对不同协议的封包进行区分。在RTP层上添加一层,叫做rtsp interleaved frame层。

struct rtp_packet {
    uint8_t interleaved[4]; 	// interleaved层     
    struct rtp_header header;   // 12 Bytes
    uint8_t payload[0];         // 柔性数组
};

interleaved层(4字节)

第一个字节为'$',用于区分RTP/RTCP包和RTSP包;

第二个字节为channel,用于区分RTP包和RTCP包

interleaved=rtp_channel-rtcp_channel

interleaved=0-1,表示视频流;

interleaved=2-3,表示音频流;
rtp_channel一般为偶数,rtcp_channel一般为奇数。

第三字节和第四字节表示RTP层(rtp_header+rtp_payload)的长度。


完整代码就不贴出来了,大概展示几点与RTP/AVP不同的地方。

① rtp_send_packet

int rtp_send_packet(int sockfd, uint8_t rtpchannel, struct rtp_packet *packet, int datalen) {
    packet->prev[0] = '$';  // 与rtsp区分
    packet->prev[1] = rtpchannel;    // 区分rtp和rtcp。0-1
    packet->prev[2] = ((datalen+RTP_HEADER_SIZE) & 0xff00)>>8;
    packet->prev[3] = (datalen+RTP_HEADER_SIZE) & 0xff;

    packet->header.seq = htons(packet->header.seq); 
    packet->header.timestamp = htonl(packet->header.timestamp);
    packet->header.ssrc = htonl(packet->header.ssrc);
    
    int ret = send(sockfd, (void *)packet, 4+RTP_HEADER_SIZE+datalen, 0);

    packet->header.seq = ntohs(packet->header.seq); 
    packet->header.timestamp = ntohl(packet->header.timestamp);
    packet->header.ssrc = ntohl(packet->header.ssrc);
    return ret;
}

②解析SETUP请求

if (!strcmp(method, "SETUP")) {
	while(1) {
		bufPtr = getLineFromBuf(bufPtr, line);
		if (!strncmp(line, "Transport:", strlen("Transport:"))) {
			sscanf(line, "Transport: RTP/AVP/TCP;unicast;interleaved:%hhu-%hhu\r\n",
					&rtp_channel, &rtcp_channel);
			break;
		}
	}
}

③ rtp_play_h264

/* 
 * @func : RTP打包传输H264码流
 * @param: 
 *      sockfd --- TCP socket 
 *      path   --- H264 file 
 */
int rtp_play_h264(int sockfd, uint8_t rtpchannel, const char *path);

完整项目地址:https://gitee.com/zhoujiabo/audio-and-video-development/tree/master/rtsp_prj/rtsp_tcp_server

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值