pub(crate) mod internal;
pub(crate) mod rtcp_parameters;
pub(crate) mod rtp_capabilities;
pub(crate) mod rtp_codec;
pub(crate) mod rtp_codec_parameters;
pub(crate) mod rtp_coding_parameters;
pub(crate) mod rtp_encoding_parameters;
pub(crate) mod rtp_header_extension_capability;
pub(crate) mod rtp_header_extension_parameters;
pub(crate) mod rtp_parameters;
pub(crate) mod rtp_receiver_parameters;
pub(crate) mod rtp_send_parameters;
pub(crate) mod set_parameter_options;
use crate::media_stream::MediaStreamId;
use crate::media_stream::track::MediaStreamTrack;
use crate::peer_connection::RTCPeerConnection;
use crate::peer_connection::message::RTCMessage;
use crate::rtp_transceiver::RTCRtpSenderId;
use interceptor::{Interceptor, NoopInterceptor};
use log::trace;
use sansio::Protocol;
use shared::error::{Error, Result};
pub use rtcp_parameters::{RTCPFeedback, RTCRtcpParameters};
pub use rtcp_parameters::{
TYPE_RTCP_FB_ACK, TYPE_RTCP_FB_CCM, TYPE_RTCP_FB_GOOG_REMB, TYPE_RTCP_FB_NACK,
TYPE_RTCP_FB_TRANSPORT_CC,
};
pub use rtp_capabilities::RTCRtpCapabilities;
pub use rtp_codec::{RTCRtpCodec, RtpCodecKind};
pub use rtp_codec_parameters::RTCRtpCodecParameters;
pub use rtp_coding_parameters::{RTCRtpCodingParameters, RTCRtpFecParameters, RTCRtpRtxParameters};
pub use rtp_encoding_parameters::RTCRtpEncodingParameters;
pub use rtp_header_extension_capability::RTCRtpHeaderExtensionCapability;
pub use rtp_header_extension_parameters::RTCRtpHeaderExtensionParameters;
pub use rtp_parameters::RTCRtpParameters;
pub use rtp_receiver_parameters::RTCRtpReceiveParameters;
pub use rtp_send_parameters::RTCRtpSendParameters;
pub use set_parameter_options::RTCSetParameterOptions;
pub struct RTCRtpSender<'a, I = NoopInterceptor>
where
I: Interceptor,
{
pub(crate) id: RTCRtpSenderId,
pub(crate) peer_connection: &'a mut RTCPeerConnection<I>,
}
impl<I> RTCRtpSender<'_, I>
where
I: Interceptor,
{
pub fn track(&self) -> &MediaStreamTrack {
self.peer_connection.rtp_transceivers[self.id.0]
.sender()
.as_ref()
.unwrap()
.track()
}
pub fn get_capabilities(&self, kind: RtpCodecKind) -> Option<RTCRtpCapabilities> {
self.peer_connection.rtp_transceivers[self.id.0]
.sender()
.as_ref()
.unwrap()
.get_capabilities(kind, &self.peer_connection.media_engine)
}
pub fn set_parameters(
&mut self,
parameters: RTCRtpSendParameters,
set_parameter_options: Option<RTCSetParameterOptions>,
) -> Result<()> {
self.peer_connection.rtp_transceivers[self.id.0]
.sender_mut()
.as_mut()
.unwrap()
.set_parameters(parameters, set_parameter_options)
}
pub fn get_parameters(&mut self) -> &RTCRtpSendParameters {
self.peer_connection.rtp_transceivers[self.id.0]
.sender_mut()
.as_mut()
.unwrap()
.get_parameters(&self.peer_connection.media_engine)
}
pub fn replace_track(&mut self, track: MediaStreamTrack) -> Result<()> {
self.peer_connection.rtp_transceivers[self.id.0]
.sender_mut()
.as_mut()
.unwrap()
.replace_track(track)
}
pub fn set_streams(&mut self, streams: Vec<MediaStreamId>) {
self.peer_connection.rtp_transceivers[self.id.0]
.sender_mut()
.as_mut()
.unwrap()
.set_streams(streams);
}
pub fn write_rtp(&mut self, packet: rtp::Packet) -> Result<()> {
let (sender, media_engine) = (
self.peer_connection.rtp_transceivers[self.id.0]
.sender_mut()
.as_mut()
.unwrap(),
&mut self.peer_connection.media_engine,
);
if !sender
.track()
.ssrcs()
.any(|ssrc| ssrc == packet.header.ssrc)
{
return Err(Error::ErrSenderWithNoSSRCs);
}
let parameters = sender.get_parameters(media_engine);
parameters
.encodings
.iter()
.find(|encoding| {
encoding
.rtp_coding_parameters
.ssrc
.is_some_and(|s| s == packet.header.ssrc)
})
.ok_or(Error::ErrRTPSenderNoBaseEncoding)?;
if !parameters
.rtp_parameters
.codecs
.iter()
.any(|codec| codec.payload_type == packet.header.payload_type)
{
trace!(
"rtp_sender {:?} rejecting RTP ssrc {} pt {}: payload type is not negotiated on this sender leg; sender codecs [{}]",
self.id,
packet.header.ssrc,
packet.header.payload_type,
parameters
.rtp_parameters
.codecs
.iter()
.map(|codec| format!("{}:{}", codec.rtp_codec.mime_type, codec.payload_type))
.collect::<Vec<_>>()
.join(", ")
);
return Err(Error::ErrRTPTransceiverCodecUnsupported);
}
if let Some(ext) = packet.header.extensions.iter().find(|ext| {
!parameters
.rtp_parameters
.header_extensions
.iter()
.any(|negotiated| negotiated.id as u8 == ext.id)
}) {
trace!(
"rtp_sender {:?} rejecting RTP ssrc {} header extension id {}: extension id is not negotiated on this sender leg; sender header extensions [{}]",
self.id,
packet.header.ssrc,
ext.id,
parameters
.rtp_parameters
.header_extensions
.iter()
.map(|he| format!("{}:{}", he.uri, he.id))
.collect::<Vec<_>>()
.join(", ")
);
return Err(Error::ErrHeaderExtensionNotFound);
}
let track_id = sender.track().track_id().to_string();
self.peer_connection
.handle_write(RTCMessage::RtpPacket(track_id, packet))
}
pub fn write_rtcp(&mut self, packets: Vec<Box<dyn rtcp::Packet>>) -> Result<()> {
let sender = self.peer_connection.rtp_transceivers[self.id.0]
.sender_mut()
.as_mut()
.unwrap();
let track_id = sender.track().track_id().to_string();
self.peer_connection
.handle_write(RTCMessage::RtcpPacket(track_id, packets))
}
}