Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add (simple) docs to all relevant functions/structs #6

Merged
merged 1 commit into from
Jan 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,23 @@ impl<'a> App<'a> {
const SUBTYPE_MASK: u8 = Self::MAX_COUNT;
pub const NAME_LEN: usize = 4;

/// The (optional) padding used by this [`App`] packet
pub fn padding(&self) -> Option<u8> {
parser::parse_padding(self.data)
}

/// The SSRC this [`App`] packet refers to
pub fn ssrc(&self) -> u32 {
parser::parse_ssrc(self.data)
}

/// The `name` for this [`App`] packet. The `name` should be a sequence of 4 ASCII
/// characters.
pub fn name(&self) -> [u8; App::NAME_LEN] {
self.data[8..8 + Self::NAME_LEN].try_into().unwrap()
}

/// The `name` for this [`App`] as a string.
pub fn get_name_string(&self) -> Result<String, std::string::FromUtf8Error> {
// name is fixed length potentially zero terminated
String::from_utf8(Vec::from_iter(self.name().iter().map_while(|&b| {
Expand All @@ -57,6 +62,7 @@ impl<'a> App<'a> {
})))
}

/// The application specific data
pub fn data(&self) -> &[u8] {
&self.data[12..self.data.len() - self.padding().unwrap_or(0) as usize]
}
Expand Down Expand Up @@ -97,11 +103,13 @@ impl<'a> AppBuilder<'a> {
self
}

/// The subtype to use for this [`App`] packet
pub fn subtype(mut self, subtype: u8) -> Self {
self.subtype = subtype;
self
}

/// The data to use for this [`App`] packet
pub fn data(mut self, data: &'a [u8]) -> Self {
self.data = data;
self
Expand Down
5 changes: 5 additions & 0 deletions src/bye.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,19 @@ impl<'a> Bye<'a> {
const MAX_SOURCES: u8 = Self::MAX_COUNT;
const MAX_REASON_LEN: u8 = 0xff;

/// The (optional) padding used by this [`Bye`] packet
pub fn padding(&self) -> Option<u8> {
parser::parse_padding(self.data)
}

/// The list of ssrcs that this [`Bye`] packet refers to
pub fn ssrcs(&self) -> impl Iterator<Item = u32> + '_ {
self.data[4..4 + self.count() as usize * 4]
.chunks_exact(4)
.map(u32_from_be_bytes)
}

/// The (optional) reason for the [`Bye`] as raw data. The reason should be an ASCII string.
pub fn reason(&self) -> Option<&[u8]> {
let offset = self.count() as usize * 4 + 4;
let reason_aligned_len = self
Expand All @@ -78,10 +81,12 @@ impl<'a> Bye<'a> {
Some(&self.data[offset + 1..end])
}

/// The (optional) reason for the [`Bye`] as a string
pub fn get_reason_string(&self) -> Option<Result<String, std::string::FromUtf8Error>> {
self.reason().map(|r| String::from_utf8(r.into()))
}

/// Create a new [`ByeBuilder`]
pub fn builder() -> ByeBuilder<'a> {
ByeBuilder::new()
}
Expand Down
24 changes: 24 additions & 0 deletions src/compound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use crate::{
RtcpPacket, RtcpParseError, RtcpWriteError,
};

/// A (currently) unknown RTCP packet type. Can also be used as a way to parse a custom RTCP packet
/// type.
#[derive(Debug, PartialEq, Eq)]
pub struct Unknown<'a> {
data: &'a [u8],
Expand Down Expand Up @@ -54,10 +56,13 @@ impl<'a> RtcpPacketParser<'a> for Unknown<'a> {
}

impl<'a> Unknown<'a> {
/// The data of this RTCP packet
pub fn data(&self) -> &[u8] {
self.data
}

/// Try to parse this unknown RTCP packet as a different RTCP packet. Can be used with an
/// external implementation of [`RtcpPacket`] to parse a custom RTCP packet.
pub fn try_as<P>(&'a self) -> Result<P, RtcpParseError>
where
P: RtcpPacket,
Expand All @@ -66,11 +71,14 @@ impl<'a> Unknown<'a> {
TryFrom::try_from(self)
}

/// The builder for an [`Unknown`] RTCP packet. The data does not include the 4 byte RTCP
/// header.
pub fn builder(type_: u8, data: &'a [u8]) -> UnknownBuilder<'a> {
UnknownBuilder::new(type_, data)
}
}

/// Unknown RTCP packet builder
#[derive(Debug)]
#[must_use = "The builder must be built to be used"]
pub struct UnknownBuilder<'a> {
Expand All @@ -81,6 +89,8 @@ pub struct UnknownBuilder<'a> {
}

impl<'a> UnknownBuilder<'a> {
/// Create a new builder for an [`Unknown`] RTCP packet. The data does not include the 4 byte RTCP
/// header.
pub fn new(type_: u8, data: &'a [u8]) -> UnknownBuilder<'a> {
UnknownBuilder {
padding: 0,
Expand All @@ -90,11 +100,14 @@ impl<'a> UnknownBuilder<'a> {
}
}

/// Sets the number of padding bytes to use for this Unknown packet
pub fn padding(mut self, padding: u8) -> Self {
self.padding = padding;
self
}

/// Set the count (or possibly type) field in the RTCP header. The exact interpretation of
/// this value is RTCP packet specific.
pub fn count(mut self, count: u8) -> Self {
self.count = count;
self
Expand Down Expand Up @@ -150,6 +163,8 @@ impl<'a> RtcpPacketWriter for UnknownBuilder<'a> {
}
}

/// A (closed) enum of all currently known RTCP packet types. The Unknown variant can be used to
/// parse a custom RTCP packet.
#[derive(Debug)]
pub enum Packet<'a> {
App(crate::App<'a>),
Expand Down Expand Up @@ -217,6 +232,7 @@ impl<'a> RtcpPacketParser<'a> for Packet<'a> {
}

impl<'a> Packet<'a> {
/// Try parsing this [`Packet`] as a particular [`RtcpPacket`] implementation.
pub fn try_as<P>(&'a self) -> Result<P, RtcpParseError>
where
P: RtcpPacket,
Expand All @@ -226,6 +242,7 @@ impl<'a> Packet<'a> {
}
}

/// A compound RTCP packet consisting of multiple RTCP packets one after the other
#[derive(Debug)]
pub struct Compound<'a> {
data: &'a [u8],
Expand All @@ -234,6 +251,9 @@ pub struct Compound<'a> {
}

impl<'a> Compound<'a> {
/// Parse data into a [`Compound`] RTCP packet.
///
/// This will validate that the length of each individual RTCP packet is valid upfront.
pub fn parse(data: &'a [u8]) -> Result<Self, RtcpParseError> {
let mut offset = 0;
let mut packet_length;
Expand Down Expand Up @@ -271,6 +291,7 @@ impl<'a> Compound<'a> {
})
}

/// Create a new [`CompoundBuilder`]
pub fn builder() -> CompoundBuilder<'a> {
CompoundBuilder::default()
}
Expand Down Expand Up @@ -300,6 +321,7 @@ impl<'a> Iterator for Compound<'a> {
}
}

/// A builder for a RTCP packet
#[derive(Debug)]
#[must_use = "The builder must be built to be used"]
pub enum PacketBuilder<'a> {
Expand Down Expand Up @@ -357,13 +379,15 @@ impl<'a> RtcpPacketWriter for PacketBuilder<'a> {
}
}

/// A builder for a [`Compound`] RTCP packet
#[derive(Default, Debug)]
#[must_use = "The builder must be built to be used"]
pub struct CompoundBuilder<'a> {
packets: Vec<Box<dyn RtcpPacketWriter + 'a>>,
}

impl<'a> CompoundBuilder<'a> {
/// Add a packet to the compound rtcp packet
pub fn add_packet(mut self, packet: impl RtcpPacketWriter + 'a) -> Self {
self.packets.push(Box::new(packet));
self
Expand Down
6 changes: 6 additions & 0 deletions src/feedback/fir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::prelude::*;
use crate::utils::u32_from_be_bytes;
use crate::{RtcpParseError, RtcpWriteError};

/// An entry in a Full Intra Refresh
#[derive(Debug, PartialEq, Eq)]
pub struct FirEntry {
ssrc: u32,
Expand All @@ -18,10 +19,12 @@ impl FirEntry {
Self { ssrc, sequence }
}

/// The SSRC for this FIR
pub fn ssrc(&self) -> u32 {
self.ssrc
}

/// The sequence count of the request. Intended for deduplication.
pub fn sequence(&self) -> u8 {
self.sequence
}
Expand Down Expand Up @@ -63,6 +66,7 @@ impl<'a> Fir<'a> {
FirParserEntryIter { parser: self, i: 0 }
}

/// Create a new [`FirBuilder`]
pub fn builder() -> FirBuilder {
FirBuilder::default()
}
Expand All @@ -83,12 +87,14 @@ impl<'a> FciParser<'a> for Fir<'a> {
}
}

/// Builder for a Full Intra Refresh packet
#[derive(Debug, Default)]
pub struct FirBuilder {
ssrc_seq: HashMap<u32, u8>,
}

impl FirBuilder {
/// Add an SSRC to this FIR packet. An existing SSRC will have their sequence number updated.
pub fn add_ssrc(mut self, ssrc: u32, sequence: u8) -> Self {
self.ssrc_seq
.entry(ssrc)
Expand Down
30 changes: 30 additions & 0 deletions src/feedback/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ pub mod pli;
pub mod rpsi;
pub mod sli;

/// The type of feedback packet. There is currently transport and payload values supported for
/// feedback packets.
#[derive(Debug, Default, PartialEq, Eq)]
pub struct FciFeedbackPacketType {
transport: bool,
Expand Down Expand Up @@ -109,18 +111,27 @@ impl<'a> TransportFeedback<'a> {
}
}

/// The (optional) padding used by this [`TransportFeedback`] packet
pub fn padding(&self) -> Option<u8> {
parser::parse_padding(self.data)
}

/// The SSRC of the sender sending this feedback
pub fn sender_ssrc(&self) -> u32 {
parser::parse_ssrc(self.data)
}

/// The SSRC of the media this packet refers to. May be unset (0) in some feedback types.
pub fn media_ssrc(&self) -> u32 {
parser::parse_ssrc(&self.data[4..])
}

/// Parse the Feedback Control Information into a concrete type.
///
/// Will fail if:
/// * The FCI does not support transport feedback,
/// * the feedback type does not match the FCI
/// * The FCI implementation fails to parse the contained data
pub fn parse_fci<F: FciParser<'a>>(&self) -> Result<F, RtcpParseError> {
if F::PACKET_TYPE & FciFeedbackPacketType::TRANSPORT == FciFeedbackPacketType::NONE {
return Err(RtcpParseError::WrongImplementation);
Expand All @@ -143,11 +154,14 @@ pub struct TransportFeedbackBuilder<'a> {
}

impl<'a> TransportFeedbackBuilder<'a> {
/// Set the SSRC this feedback packet is being sent from
pub fn sender_ssrc(mut self, sender_ssrc: u32) -> Self {
self.sender_ssrc = sender_ssrc;
self
}

/// Set the SSRC this feedback packet is being directed towards. May be 0 if the specific
/// feedback type allows.
pub fn media_ssrc(mut self, media_ssrc: u32) -> Self {
self.media_ssrc = media_ssrc;
self
Expand Down Expand Up @@ -293,18 +307,27 @@ impl<'a> PayloadFeedback<'a> {
}
}

/// The (optional) padding used by this [`PayloadFeedback`] packet
pub fn padding(&self) -> Option<u8> {
parser::parse_padding(self.data)
}

/// The SSRC of the sender sending this feedback
pub fn sender_ssrc(&self) -> u32 {
parser::parse_ssrc(self.data)
}

/// The SSRC of the media this packet refers to. May be unset (0) in some feedback types.
pub fn media_ssrc(&self) -> u32 {
parser::parse_ssrc(&self.data[4..])
}

/// Parse the Feedback Control Information into a concrete type.
///
/// Will fail if:
/// * The FCI does not support payload feedback,
/// * the feedback type does not match the FCI
/// * The FCI implementation fails to parse the contained data
pub fn parse_fci<F: FciParser<'a>>(&self) -> Result<F, RtcpParseError> {
if F::PACKET_TYPE & FciFeedbackPacketType::PAYLOAD == FciFeedbackPacketType::NONE {
return Err(RtcpParseError::WrongImplementation);
Expand All @@ -327,11 +350,14 @@ pub struct PayloadFeedbackBuilder<'a> {
}

impl<'a> PayloadFeedbackBuilder<'a> {
/// Set the SSRC this feedback packet is being sent from
pub fn sender_ssrc(mut self, sender_ssrc: u32) -> Self {
self.sender_ssrc = sender_ssrc;
self
}

/// Set the SSRC this feedback packet is being directed towards. May be 0 if the specific
/// feedback type allows.
pub fn media_ssrc(mut self, media_ssrc: u32) -> Self {
self.media_ssrc = media_ssrc;
self
Expand Down Expand Up @@ -392,6 +418,7 @@ impl<'a> RtcpPacketWriter for PayloadFeedbackBuilder<'a> {
}
}

/// Trait for parsing FCI data in [`TransportFeedback`] or [`PayloadFeedback`] packets
pub trait FciParser<'a>: Sized {
const PACKET_TYPE: FciFeedbackPacketType;
const FCI_FORMAT: u8;
Expand Down Expand Up @@ -446,8 +473,11 @@ impl<'a> std::ops::Deref for FciBuilderWrapper<'a> {
}
}

/// Trait for writing a particular FCI implementation with a [`TransportFeedbackBuilder`] or
/// [`PayloadFeedbackBuilder`].
pub trait FciBuilder<'a>: RtcpPacketWriter {
/// The format field value to place in the RTCP header
fn format(&self) -> u8;
/// The type of feedback packet this FCI data supports being placed in
fn supports_feedback_type(&self) -> FciFeedbackPacketType;
}
Loading
Loading