use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)]
#[serde(tag = "kind", rename_all = "lowercase")]
#[non_exhaustive]
pub enum RtpCodecCapabilityFinalized {
#[serde(rename_all = "camelCase")]
Audio {
mime_type: MimeTypeAudio,
preferred_payload_type: u8,
clock_rate: u32,
channels: u8,
parameters: BTreeMap<String, RtpCodecParametersParametersValue>,
rtcp_feedback: Vec<RtcpFeedback>,
},
#[serde(rename_all = "camelCase")]
Video {
mime_type: MimeTypeVideo,
preferred_payload_type: u8,
clock_rate: u32,
parameters: BTreeMap<String, RtpCodecParametersParametersValue>,
rtcp_feedback: Vec<RtcpFeedback>,
},
}
impl RtpCodecCapabilityFinalized {
pub(crate) fn is_rtx(&self) -> bool {
match self {
Self::Audio { mime_type, .. } => mime_type == &MimeTypeAudio::RTX,
Self::Video { mime_type, .. } => mime_type == &MimeTypeVideo::RTX,
}
}
pub(crate) fn clock_rate(&self) -> u32 {
match self {
Self::Audio { clock_rate, .. } => *clock_rate,
Self::Video { clock_rate, .. } => *clock_rate,
}
}
pub(crate) fn parameters(&self) -> &BTreeMap<String, RtpCodecParametersParametersValue> {
match self {
Self::Audio { parameters, .. } => parameters,
Self::Video { parameters, .. } => parameters,
}
}
pub(crate) fn preferred_payload_type(&self) -> u8 {
match self {
Self::Audio {
preferred_payload_type,
..
} => *preferred_payload_type,
Self::Video {
preferred_payload_type,
..
} => *preferred_payload_type,
}
}
}
#[derive(Debug, Default, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct RtpCapabilitiesFinalized {
pub codecs: Vec<RtpCodecCapabilityFinalized>,
pub header_extensions: Vec<RtpHeaderExtension>,
pub fec_mechanisms: Vec<String>,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum MediaKind {
Audio,
Video,
}
#[derive(Debug, Copy, Clone, PartialEq, Deserialize, Serialize)]
#[serde(untagged)]
pub enum MimeType {
Audio(MimeTypeAudio),
Video(MimeTypeVideo),
}
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)]
pub enum MimeTypeAudio {
#[serde(rename = "audio/opus")]
Opus,
#[serde(rename = "audio/PCMU")]
PCMU,
#[serde(rename = "audio/PCMA")]
PCMA,
#[serde(rename = "audio/ISAC")]
ISAC,
#[serde(rename = "audio/G722")]
G722,
#[serde(rename = "audio/iLBC")]
iLBC,
#[serde(rename = "audio/SILK")]
SILK,
#[serde(rename = "audio/CN")]
CN,
#[serde(rename = "audio/telephone-event")]
TelephoneEvent,
#[serde(rename = "audio/rtx")]
RTX,
#[serde(rename = "audio/red")]
RED,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)]
pub enum MimeTypeVideo {
#[serde(rename = "video/VP8")]
VP8,
#[serde(rename = "video/VP9")]
VP9,
#[serde(rename = "video/H264")]
H264,
#[serde(rename = "video/H265")]
H265,
#[serde(rename = "video/rtx")]
RTX,
#[serde(rename = "video/red")]
RED,
#[serde(rename = "video/ulpfec")]
ULPFEC,
}
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)]
#[serde(tag = "kind", rename_all = "lowercase")]
pub enum RtpCodecCapability {
#[serde(rename_all = "camelCase")]
Audio {
mime_type: MimeTypeAudio,
#[serde(skip_serializing_if = "Option::is_none")]
preferred_payload_type: Option<u8>,
clock_rate: u32,
channels: u8,
parameters: BTreeMap<String, RtpCodecParametersParametersValue>,
rtcp_feedback: Vec<RtcpFeedback>,
},
#[serde(rename_all = "camelCase")]
Video {
mime_type: MimeTypeVideo,
#[serde(skip_serializing_if = "Option::is_none")]
preferred_payload_type: Option<u8>,
clock_rate: u32,
parameters: BTreeMap<String, RtpCodecParametersParametersValue>,
rtcp_feedback: Vec<RtcpFeedback>,
},
}
impl RtpCodecCapability {
pub(crate) fn mime_type(&self) -> MimeType {
match self {
Self::Audio { mime_type, .. } => MimeType::Audio(*mime_type),
Self::Video { mime_type, .. } => MimeType::Video(*mime_type),
}
}
pub(crate) fn parameters(&self) -> &BTreeMap<String, RtpCodecParametersParametersValue> {
match self {
Self::Audio { parameters, .. } => parameters,
Self::Video { parameters, .. } => parameters,
}
}
pub(crate) fn parameters_mut(
&mut self,
) -> &mut BTreeMap<String, RtpCodecParametersParametersValue> {
match self {
Self::Audio { parameters, .. } => parameters,
Self::Video { parameters, .. } => parameters,
}
}
pub(crate) fn preferred_payload_type(&self) -> Option<u8> {
match self {
Self::Audio {
preferred_payload_type,
..
} => *preferred_payload_type,
Self::Video {
preferred_payload_type,
..
} => *preferred_payload_type,
}
}
pub(crate) fn rtcp_feedback(&self) -> &Vec<RtcpFeedback> {
match self {
Self::Audio { rtcp_feedback, .. } => rtcp_feedback,
Self::Video { rtcp_feedback, .. } => rtcp_feedback,
}
}
}
#[derive(Debug, Default, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RtpCapabilities {
pub codecs: Vec<RtpCodecCapability>,
pub header_extensions: Vec<RtpHeaderExtension>,
pub fec_mechanisms: Vec<String>,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum RtpHeaderExtensionDirection {
SendRecv,
SendOnly,
RecvOnly,
Inactive,
}
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RtpHeaderExtension {
#[serde(skip_serializing_if = "Option::is_none")]
pub kind: Option<MediaKind>,
pub uri: String,
pub preferred_id: u16,
pub preferred_encrypt: bool,
pub direction: RtpHeaderExtensionDirection,
}
#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RtpParameters {
#[serde(skip_serializing_if = "Option::is_none")]
pub mid: Option<String>,
pub codecs: Vec<RtpCodecParameters>,
pub header_extensions: Vec<RtpHeaderExtensionParameters>,
pub encodings: Vec<RtpEncodingParameters>,
pub rtcp: RtcpParameters,
}
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)]
#[serde(untagged)]
pub enum RtpCodecParametersParametersValue {
String(String),
Number(u32),
}
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)]
#[serde(untagged, rename_all = "lowercase")]
pub enum RtpCodecParameters {
#[serde(rename_all = "camelCase")]
Audio {
mime_type: MimeTypeAudio,
payload_type: u8,
clock_rate: u32,
channels: u8,
parameters: BTreeMap<String, RtpCodecParametersParametersValue>,
rtcp_feedback: Vec<RtcpFeedback>,
},
#[serde(rename_all = "camelCase")]
Video {
mime_type: MimeTypeVideo,
payload_type: u8,
clock_rate: u32,
parameters: BTreeMap<String, RtpCodecParametersParametersValue>,
rtcp_feedback: Vec<RtcpFeedback>,
},
}
impl RtpCodecParameters {
pub(crate) fn is_rtx(&self) -> bool {
match self {
Self::Audio { mime_type, .. } => mime_type == &MimeTypeAudio::RTX,
Self::Video { mime_type, .. } => mime_type == &MimeTypeVideo::RTX,
}
}
pub(crate) fn mime_type(&self) -> MimeType {
match self {
Self::Audio { mime_type, .. } => MimeType::Audio(*mime_type),
Self::Video { mime_type, .. } => MimeType::Video(*mime_type),
}
}
pub(crate) fn payload_type(&self) -> u8 {
match self {
Self::Audio { payload_type, .. } => *payload_type,
Self::Video { payload_type, .. } => *payload_type,
}
}
pub(crate) fn parameters(&self) -> &BTreeMap<String, RtpCodecParametersParametersValue> {
match self {
Self::Audio { parameters, .. } => parameters,
Self::Video { parameters, .. } => parameters,
}
}
pub(crate) fn rtcp_feedback_mut(&mut self) -> &mut Vec<RtcpFeedback> {
match self {
Self::Audio { rtcp_feedback, .. } => rtcp_feedback,
Self::Video { rtcp_feedback, .. } => rtcp_feedback,
}
}
}
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)]
pub struct RtcpFeedback {
pub r#type: String,
pub parameter: String,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)]
pub struct RtpEncodingParametersRtx {
pub ssrc: u32,
}
#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RtpEncodingParameters {
#[serde(skip_serializing_if = "Option::is_none")]
pub ssrc: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub rid: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub codec_payload_type: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
pub rtx: Option<RtpEncodingParametersRtx>,
#[serde(skip_serializing_if = "Option::is_none")]
pub dtx: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub scalability_mode: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub scale_resolution_down_by: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_bitrate: Option<u32>,
}
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)]
pub struct RtpHeaderExtensionParameters {
pub uri: String,
pub id: u16,
pub encrypt: bool,
pub parameters: BTreeMap<String, RtpCodecParametersParametersValue>,
}
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RtcpParameters {
#[serde(skip_serializing_if = "Option::is_none")]
pub cname: Option<String>,
pub reduced_size: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub mux: Option<bool>,
}
impl Default for RtcpParameters {
fn default() -> Self {
Self {
cname: None,
reduced_size: true,
mux: None,
}
}
}