本文主要介绍通过udp方式实现rtsp拉流。
流程说明:
m_tcpClient = std::make_shared(nullptr, this);
if (!m_tcpClient.get()
|| 0 != m_tcpClient->TcpCreate()
|| 0 != m_tcpClient->TcpConnect(ip.c_str(), port)
|| 0 != m_tcpClient->TcpSetNoBlock(true)
|| 0 != m_tcpClient->TcpRecvTimeout(10))
break;
// 参数1(RTSP_TRANSPORT_RTP_UDP)指明使用udp方式收流
m_command = std::make_shared(RTSP_TRANSPORT_RTP_UDP, m_tcpClient, m_func, m_user);
if (!m_command.get())
break;
// 创建rtsp client
if (!m_command->CreateRtspClient(m_rtspUrl, username, userpasswd))
break;
// 发送describe信令
int ret = m_command->SendDescribe();
if (0 != ret)
break;
int CRtspCmd::HandleRtpPort(int media, const char* source, unsigned short rtp[2], char* ip, int len)
{
int ret = -1;
switch (m_transport)
{
case RTSP_TRANSPORT_RTP_UDP:
ret = sockpair_create("0.0.0.0", m_rtp[media], m_port[media]);
if (0 != ret)
{
return -1;
}
rtp[0] = m_port[media][0];
rtp[1] = m_port[media][1];
break;
default:
assert(0);
return -1;
}
return m_transport;
}
int CRtspUdpData::Start(int count, socket_t rtp[2], const char* peer, int peerport[2], int payload, const char* encoding)
{
// 创建解复用器
const struct rtp_profile_t* profile = rtp_profile_find(payload);
m_demuxer = rtp_demuxer_create(100, profile ? profile->frequency : 90000, payload, encoding, RtpPacketCB, this);
if (!m_demuxer)
return -1;
if (0 != CreatePacker_(payload, encoding))
{
rtp_demuxer_destroy(&m_demuxer);
return -1;
}
m_encoding = encoding;
m_payload = payload;
m_socket[0] = rtp[0];
m_socket[1] = rtp[1];
// 启动数据接收线程
m_thread = std::thread(UdpDataThread, this);
return 0;
}
// 读rtp数据
int CRtspUdpData::RtpRead_(socket_t s)
{
if (!m_demuxer)
return -1;
struct sockaddr_storage ss;
socklen_t len = sizeof(ss);
int dataLen = recvfrom(s, m_rtpBuffer, sizeof(m_rtpBuffer), 0, (struct sockaddr*)&ss, &len);
if (dataLen < 12)
{
return -1;
}
// 视频数据解复用
return rtp_demuxer_input(m_demuxer, m_rtpBuffer, dataLen);
}
// 读rtcp数据
int CRtspUdpData::RtcpRead_(socket_t s)
{
if (!m_demuxer)
return -1;
struct sockaddr_storage ss;
socklen_t len = sizeof(ss);
int dataLen = recvfrom(s, m_rtcpBuffer, sizeof(m_rtcpBuffer), 0, (struct sockaddr*)&ss, &len);
if (dataLen < 12)
{
return -1;
}
return rtp_demuxer_input(m_demuxer, m_rtcpBuffer, dataLen);
}