音视频学习(十六)——rtp over tcp简介

rtp over rtsp(tcp)

rtp over udp与rtp over rtsp(tcp)的区别:

  • RTP OVER UDP

    • tcp连接进行rtsp信令交互;
    • 创建新的udp套接字来发送rtp包;
    • 创建新的udp套接字来发送rtcp包;
  • RTP OVER RTSP(TCP)

    • tcp连接进行rtsp信令交互;
    • 复用rtsp的tcp连接发送rtp和rtcp包;

rtsp/rtp/rtcp

rtp/rtcp包,每包前面都加上4个字节。

字节 描述
第一个字节 ‘$’标识符(0x24,固定)
第二个字节 通道(channel)。一般情况下偶数是rtp通道,奇数是rtcp通道
interleaved=0:视频流 RTP;
interleaved=1:视频流 RTCP;
interleaved=2:音频流 RTP;
interleaved=3:音频流 RTCP;
第三个和第四个字节 rtp包的大小
# 说明1
第一个字节‘$’主要用来区分rtsp。

# 说明2
第二个字节主要用来区分rtp和rtcp, 通道是在rtsp的setup过程中, 客户端提供给服务端的。

rtsp中setup信令传输示例:

  • UDP传输
# C->S
SETUP rtsp://192.168.1.100:8554/live/track1 RTSP/1.0
CSeq: 5
Transport: RTP/AVP;unicast;client_port=51950-51951  
Session: xxx

# S->C
RTSP/1.0 200 OK
CSeq: 5
Transport: RTP/AVP;unicast;client_port=51950-51951;server_port=21342-21343
Session: xxx
  • TCP传输
# C->S
SETUP rtsp://192.168.1.100:8554/live/track0 RTSP/1.0
CSeq: 6
User-Agent: LibVLC/3.0.14 
Transport: RTP/AVP/TCP;unicast;interleaved=0-1  # 0: rtp通道 1: rtcp通道
 
# S->C
RTSP/1.0 200 OK
CSeq: 6
Transport: RTP/AVP/TCP;unicast;interleaved=0-1
Session: xxx

补充

关于创建传输端口

开发rtsp服务端时,在处理tcp或udp端口组装时略有不同,如下代码所示:

// 此部分参考ireader库中示例代码
if(RTSP_TRANSPORT_RTP_TCP == transport->transport)  
{
    UINT8 interleaved[2];
    if (transport->interleaved1 == transport->interleaved2)
    {
        interleaved[0] = session->channel++;
        interleaved[1] = session->channel++;
    }
    else
    {
        interleaved[0] = (UINT8)transport->interleaved1;
        interleaved[1] = (UINT8)transport->interleaved2;
    }
    
    // ... 

    snprintf(rtsp_transport, sizeof(rtsp_transport), "RTP/AVP/TCP;interleaved=%d-%d", interleaved[0], interleaved[1]);		
}
else if(transport->multicast)   
{
    unsigned short port[2] = { transport->rtp.u.client_port1, transport->rtp.u.client_port2 };
    char multicast[65] = {0};

    if(transport->destination[0])
    {
        snprintf(multicast, sizeof(multicast), "%s", transport->destination);
        port[0] = transport->rtp.m.port1;
        port[1] = transport->rtp.m.port2;
    }
    else
    {
        snprintf(multicast, sizeof(multicast), "%s", GetCRtspConfig().GetConfigString(RTSP_UDP_MULTICAST_ADDR_PARAM).c_str());
        port[0] = (unsigned short)GetCRtspConfig().GetConfigInt(RTSP_UDP_MULTICAST_PORT_PARAM);
        port[1] = (unsigned short)GetCRtspConfig().GetConfigInt(RTSP_UDP_MULTICAST_PORT_PARAM) + 1;
    }
    
    // ...

    snprintf(rtsp_transport, sizeof(rtsp_transport),
             "RTP/AVP;multicast;destination=%s;port=%hu-%hu;ttl=%d",
             multicast, port[0], port[1], 16);
}
else
{
    unsigned short port[2] = { transport->rtp.u.client_port1, transport->rtp.u.client_port2 };
    
    //...

    snprintf(rtsp_transport, sizeof(rtsp_transport), 
             "RTP/AVP;unicast;client_port=%hu-%hu;server_port=%hu-%hu%s%s", 
             transport->rtp.u.client_port1, transport->rtp.u.client_port2,
             port[0], port[1],
             transport->destination[0] ? ";destination=" : "",
             transport->destination[0] ? transport->destination : "");
}

猜你喜欢

转载自blog.csdn.net/www_dong/article/details/128809040