use crate::media_stream::MediaStreamId;
use crate::media_stream::track_capabilities::MediaTrackCapabilities;
use crate::media_stream::track_constraints::MediaTrackConstraints;
use crate::media_stream::track_settings::MediaTrackSettings;
use crate::media_stream::track_state::MediaStreamTrackState;
use crate::rtp_transceiver::rtp_sender::{
RTCRtpCodec, RTCRtpCodingParameters, RTCRtpEncodingParameters, RtpCodecKind,
};
use crate::rtp_transceiver::{RtpStreamId, SSRC};
pub type MediaStreamTrackId = String;
#[derive(Default, Debug, Clone)]
pub struct MediaStreamTrack {
stream_id: MediaStreamId,
track_id: MediaStreamTrackId,
label: String,
kind: RtpCodecKind,
codings: Vec<RTCRtpEncodingParameters>,
muted: bool,
enabled: bool,
ready_state: MediaStreamTrackState,
restrictable: bool,
capabilities: MediaTrackCapabilities,
constraints: MediaTrackConstraints,
settings: MediaTrackSettings,
}
impl MediaStreamTrack {
pub fn new(
stream_id: MediaStreamId,
track_id: MediaStreamTrackId,
label: String,
kind: RtpCodecKind,
codings: Vec<RTCRtpEncodingParameters>,
) -> Self {
Self {
stream_id,
track_id,
label,
kind,
codings,
muted: false,
enabled: true,
ready_state: MediaStreamTrackState::Live,
restrictable: false,
..Default::default()
}
}
pub fn stream_id(&self) -> &MediaStreamId {
&self.stream_id
}
pub fn track_id(&self) -> &MediaStreamTrackId {
&self.track_id
}
pub fn label(&self) -> &String {
&self.label
}
pub fn kind(&self) -> RtpCodecKind {
self.kind
}
pub fn rid(&self, ssrc: SSRC) -> Option<&RtpStreamId> {
self.codings
.iter()
.find(|coding| {
!coding.rtp_coding_parameters.rid.is_empty()
&& coding
.rtp_coding_parameters
.ssrc
.is_some_and(|t_ssrc| t_ssrc == ssrc)
})
.map(|coding| &coding.rtp_coding_parameters.rid)
}
pub fn codec(&self, ssrc: SSRC) -> Option<&RTCRtpCodec> {
self.codings
.iter()
.find(|coding| {
!coding.codec.mime_type.is_empty()
&& coding
.rtp_coding_parameters
.ssrc
.is_some_and(|track_ssrc| track_ssrc == ssrc)
})
.map(|coding| &coding.codec)
}
pub fn ssrcs(&self) -> impl Iterator<Item = SSRC> {
self.codings
.iter()
.filter(|coding| coding.rtp_coding_parameters.ssrc.is_some())
.map(|coding| coding.rtp_coding_parameters.ssrc.unwrap_or_default())
}
pub fn enabled(&self) -> bool {
self.enabled
}
pub fn set_enabled(&mut self, enabled: bool) {
self.enabled = enabled;
}
pub fn muted(&self) -> bool {
self.muted
}
pub fn stop(&mut self) {
self.ready_state = MediaStreamTrackState::Ended;
}
pub fn get_capabilities(&self) -> &MediaTrackCapabilities {
&self.capabilities
}
pub fn get_constraints(&self) -> &MediaTrackConstraints {
&self.constraints
}
pub fn get_settings(&self) -> &MediaTrackSettings {
&self.settings
}
pub fn apply_constraints(&mut self, constraints: Option<MediaTrackConstraints>) {
if self.ready_state == MediaStreamTrackState::Ended {
return;
}
if let Some(constraints) = constraints {
self.constraints = constraints;
}
}
pub(crate) fn set_codec_by_ssrc(&mut self, codec: RTCRtpCodec, ssrc: SSRC) -> bool {
if let Some(coding) = self.codings.iter_mut().find(|coding| {
coding
.rtp_coding_parameters
.ssrc
.is_some_and(|t_ssrc| t_ssrc == ssrc)
}) {
coding.codec = codec;
false
} else {
self.codings.push(RTCRtpEncodingParameters {
rtp_coding_parameters: RTCRtpCodingParameters {
rid: "".to_string(),
ssrc: Some(ssrc),
rtx: None,
fec: None,
},
codec,
..Default::default()
});
true
}
}
pub(crate) fn set_codec_ssrc_by_rid(
&mut self,
codec: RTCRtpCodec,
ssrc: SSRC,
rid: &RtpStreamId,
) -> bool {
if let Some(coding) = self
.codings
.iter_mut()
.find(|coding| &coding.rtp_coding_parameters.rid == rid)
{
coding.codec = codec;
coding.rtp_coding_parameters.ssrc = Some(ssrc);
false
} else {
self.codings.push(RTCRtpEncodingParameters {
rtp_coding_parameters: RTCRtpCodingParameters {
rid: rid.to_string(),
ssrc: Some(ssrc),
rtx: None,
fec: None,
},
codec,
..Default::default()
});
true
}
}
pub(crate) fn get_codec_by_ssrc(&self, ssrc: SSRC) -> Option<&RTCRtpCodec> {
self.codings
.iter()
.find(|coding| {
coding
.rtp_coding_parameters
.ssrc
.is_some_and(|t_ssrc| t_ssrc == ssrc)
})
.map(|coding| &coding.codec)
}
pub(crate) fn codings(&self) -> &[RTCRtpEncodingParameters] {
&self.codings
}
}