gst-plugins-rs/net/rtsp/src/rtspsrc/transport.rs
Nirbheek Chauhan 086ffd7aff New RTSP source plugin with live streaming support
GST_PLUGIN_FEATURE_RANK=rtspsrc2:1 gst-play-1.0 [URI]

Features:
* Live streaming N audio and N video
  - With RTCP-based A/V sync
* Lower transports: TCP, UDP, UDP-Multicast
* RTP, RTCP SR, RTCP RR
* OPTIONS DESCRIBE SETUP PLAY TEARDOWN
* Custom UDP socket management, does not use udpsrc/udpsink
* Supports both rtpbin and the rtpbin2 rust rewrite
  - Set USE_RTPBIN2=1 to use rtpbin2 (needs other MRs)
* Properties:
  - protocols selection and priority (NEW!)
  - location supports rtsp[ut]://
  - port-start instead of port-range

Co-Authored-by: Tim-Philipp Müller <tim@centricular.com>
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1425>
2024-02-07 20:29:18 +05:30

106 lines
3.7 KiB
Rust

// GStreamer RTSP Source 2
//
// Copyright (C) 2023-2024 Nirbheek Chauhan <nirbheek centricular com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License, v2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at
// <https://mozilla.org/MPL/2.0/>.
//
// SPDX-License-Identifier: MPL-2.0
//
// https://www.rfc-editor.org/rfc/rfc2326.html
use super::imp::{RtspError, RtspProtocol};
use rtsp_types::headers::{transport::RtpTransport, RtpLowerTransport};
use std::{convert::TryFrom, net::IpAddr};
use tokio::net::UdpSocket;
#[derive(Debug)]
pub enum RtspTransportInfo {
Tcp {
channels: (u8, Option<u8>),
},
Udp {
source: Option<String>,
server_port: (u16, Option<u16>),
client_port: Option<(u16, Option<u16>)>,
sockets: Option<(UdpSocket, Option<UdpSocket>)>,
},
UdpMulticast {
dest: IpAddr,
port: (u16, Option<u16>),
ttl: Option<u8>,
},
}
impl TryFrom<&RtpTransport> for RtspTransportInfo {
type Error = RtspError;
fn try_from(t: &RtpTransport) -> Result<Self, Self::Error> {
match &t.lower_transport {
Some(RtpLowerTransport::Tcp) => match t.params.interleaved {
Some(v) => Ok(RtspTransportInfo::Tcp { channels: v }),
None => Err(RtspError::Fatal(format!(
"Expected interleaved channels: {t:#?}",
))),
},
Some(RtpLowerTransport::Udp) | None => {
if t.params.multicast {
let dest = if let Some(d) = t.params.destination.as_ref() {
match d.parse::<IpAddr>() {
Ok(d) => d,
Err(err) => {
return Err(RtspError::Fatal(format!(
"Failed to parse multicast dest addr: {err:?}"
)));
}
}
} else {
return Err(RtspError::Fatal(format!(
"Need multicast dest addr: {:#?}",
t.params,
)));
};
let Some(port) = t.params.port else {
return Err(RtspError::Fatal(format!(
"Need multicast UDP port(s): {:#?}",
t.params,
)));
};
Ok(RtspTransportInfo::UdpMulticast {
dest,
port,
ttl: t.params.ttl,
})
} else {
let Some(server_port) = t.params.server_port else {
return Err(RtspError::Fatal(format!(
"Need server unicast UDP port(s): {:#?}",
t.params,
)));
};
Ok(RtspTransportInfo::Udp {
source: t.params.source.clone(),
server_port,
client_port: t.params.client_port,
sockets: None,
})
}
}
Some(RtpLowerTransport::Other(token)) => Err(RtspError::Fatal(format!(
"Unsupported RTP lower transport {token:?}"
))),
}
}
}
impl RtspTransportInfo {
pub fn to_protocol(&self) -> RtspProtocol {
match &self {
Self::Tcp { .. } => RtspProtocol::Tcp,
Self::Udp { .. } => RtspProtocol::Udp,
Self::UdpMulticast { .. } => RtspProtocol::UdpMulticast,
}
}
}