// PHZ // 2018-9-30 #include "RtpConnection.h" #include "RtspConnection.h" #include "SocketUtil.h" using namespace std; using namespace xop; RtpConnection::RtpConnection(std::weak_ptr rtsp_connection) : rtsp_connection_(rtsp_connection) { std::random_device rd; for(int chn=0; chnGetIp(); rtsp_port_ = conn->GetPort(); } RtpConnection::~RtpConnection() { for(int chn=0; chn 0) { SocketUtil::Close(rtpfd_[chn]); } if(rtcpfd_[chn] > 0) { SocketUtil::Close(rtcpfd_[chn]); } } } int RtpConnection::GetId() const { auto conn = rtsp_connection_.lock(); if (!conn) { return -1; } RtspConnection *rtspConn = (RtspConnection *)conn.get(); return rtspConn->GetId(); } bool RtpConnection::SetupRtpOverTcp(MediaChannelId channel_id, uint16_t rtp_channel, uint16_t rtcp_channel) { auto conn = rtsp_connection_.lock(); if (!conn) { return false; } media_channel_info_[channel_id].rtp_channel = rtp_channel; media_channel_info_[channel_id].rtcp_channel = rtcp_channel; rtpfd_[channel_id] = conn->GetSocket(); rtcpfd_[channel_id] = conn->GetSocket(); media_channel_info_[channel_id].is_setup = true; transport_mode_ = RTP_OVER_TCP; return true; } bool RtpConnection::SetupRtpOverUdp(MediaChannelId channel_id, uint16_t rtp_port, uint16_t rtcp_port) { auto conn = rtsp_connection_.lock(); if (!conn) { return false; } if(SocketUtil::GetPeerAddr(conn->GetSocket(), &peer_addr_) < 0) { return false; } media_channel_info_[channel_id].rtp_port = rtp_port; media_channel_info_[channel_id].rtcp_port = rtcp_port; std::random_device rd; for (int n = 0; n <= 10; n++) { if (n == 10) { return false; } local_rtp_port_[channel_id] = rd() & 0xfffe; local_rtcp_port_[channel_id] =local_rtp_port_[channel_id] + 1; rtpfd_[channel_id] = ::socket(AF_INET, SOCK_DGRAM, 0); if(!SocketUtil::Bind(rtpfd_[channel_id], "0.0.0.0", local_rtp_port_[channel_id])) { SocketUtil::Close(rtpfd_[channel_id]); continue; } rtcpfd_[channel_id] = ::socket(AF_INET, SOCK_DGRAM, 0); if(!SocketUtil::Bind(rtcpfd_[channel_id], "0.0.0.0", local_rtcp_port_[channel_id])) { SocketUtil::Close(rtpfd_[channel_id]); SocketUtil::Close(rtcpfd_[channel_id]); continue; } break; } SocketUtil::SetSendBufSize(rtpfd_[channel_id], 50*1024); peer_rtp_addr_[channel_id].sin_family = AF_INET; peer_rtp_addr_[channel_id].sin_addr.s_addr = peer_addr_.sin_addr.s_addr; peer_rtp_addr_[channel_id].sin_port = htons(media_channel_info_[channel_id].rtp_port); peer_rtcp_sddr_[channel_id].sin_family = AF_INET; peer_rtcp_sddr_[channel_id].sin_addr.s_addr = peer_addr_.sin_addr.s_addr; peer_rtcp_sddr_[channel_id].sin_port = htons(media_channel_info_[channel_id].rtcp_port); media_channel_info_[channel_id].is_setup = true; transport_mode_ = RTP_OVER_UDP; return true; } bool RtpConnection::SetupRtpOverMulticast(MediaChannelId channel_id, std::string ip, uint16_t port) { std::random_device rd; for (int n = 0; n <= 10; n++) { if (n == 10) { return false; } local_rtp_port_[channel_id] = rd() & 0xfffe; rtpfd_[channel_id] = ::socket(AF_INET, SOCK_DGRAM, 0); if (!SocketUtil::Bind(rtpfd_[channel_id], "0.0.0.0", local_rtp_port_[channel_id])) { SocketUtil::Close(rtpfd_[channel_id]); continue; } break; } media_channel_info_[channel_id].rtp_port = port; peer_rtp_addr_[channel_id].sin_family = AF_INET; peer_rtp_addr_[channel_id].sin_addr.s_addr = inet_addr(ip.c_str()); peer_rtp_addr_[channel_id].sin_port = htons(port); media_channel_info_[channel_id].is_setup = true; transport_mode_ = RTP_OVER_MULTICAST; is_multicast_ = true; return true; } void RtpConnection::Play() { for(int chn=0; chn(chrono::steady_clock::now()); auto ts = time_point.time_since_epoch().count(); for (int chn = 0; chntask_scheduler_->AddTriggerEvent([this, channel_id, pkt] { this->SetFrameType(pkt.type); this->SetRtpHeader(channel_id, pkt); if((media_channel_info_[channel_id].is_play || media_channel_info_[channel_id].is_record) && has_key_frame_ ) { if(transport_mode_ == RTP_OVER_TCP) { SendRtpOverTcp(channel_id, pkt); } else { SendRtpOverUdp(channel_id, pkt); } //media_channel_info_[channel_id].octetCount += pkt.size; //media_channel_info_[channel_id].packetCount += 1; } }); return ret ? 0 : -1; } int RtpConnection::SendRtpOverTcp(MediaChannelId channel_id, RtpPacket pkt) { auto conn = rtsp_connection_.lock(); if (!conn) { return -1; } uint8_t* rtpPktPtr = pkt.data.get(); rtpPktPtr[0] = '$'; rtpPktPtr[1] = (char)media_channel_info_[channel_id].rtp_channel; rtpPktPtr[2] = (char)(((pkt.size-4)&0xFF00)>>8); rtpPktPtr[3] = (char)((pkt.size -4)&0xFF); conn->Send((char*)rtpPktPtr, pkt.size); return pkt.size; } int RtpConnection::SendRtpOverUdp(MediaChannelId channel_id, RtpPacket pkt) { int ret = sendto(rtpfd_[channel_id], (const char*)pkt.data.get()+4, pkt.size-4, 0, (struct sockaddr *)&(peer_rtp_addr_[channel_id]), sizeof(struct sockaddr_in)); if(ret < 0) { Teardown(); return -1; } return ret; }