Skip to content
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
204 changes: 197 additions & 7 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,12 @@ impl<P: PayloadLength, E: PayloadLength> RtpPacketBuilder<P, E> {
pub fn calculate_size(&self) -> Result<usize, RtpWriteError> {
let payload_len = self.payloads.iter().map(|p| p.len()).sum::<usize>();
let extension_len = if let Some((_ext_id, ext_data)) = self.extension.as_ref() {
if ext_data.len() > u16::MAX as usize {
return Err(RtpWriteError::PacketTooLarge);
}
if ext_data.len() % 4 != 0 {
return Err(RtpWriteError::ExtensionDataNotPadded);
}
if ext_data.len() > u16::MAX as usize {
return Err(RtpWriteError::PacketTooLarge);
}
4 + ext_data.len()
} else {
0
Expand Down Expand Up @@ -323,7 +323,7 @@ pub trait PayloadLength {
fn len(&self) -> usize;
/// Whether the data contains any bytes.
fn is_empty(&self) -> bool {
self.len() != 0
self.len() == 0
}
}

Expand Down Expand Up @@ -504,9 +504,8 @@ impl<'b, 'c> RtpPacketWriter for RtpPacketWriterMutSlice<'_, 'b, 'c> {

fn finish(&mut self) -> Self::Output {
if let Some(padding) = self.padding.take() {
if padding > 1 {
self.output[self.write_i..self.write_i + padding as usize - 1].fill(0);
}
debug_assert!(padding > 0);
self.output[self.write_i..self.write_i + padding as usize - 1].fill(0);
self.write_i += padding as usize;
self.output[self.write_i - 1] = padding;
}
Expand Down Expand Up @@ -585,14 +584,31 @@ impl<'b, 'c> RtpPacketWriter for RtpPacketWriterMutVec<'_, 'b, 'c> {
mod tests {
use super::*;

#[test]
fn payload_length() {
let data = [3; 9];
let data2: [u8; _] = [];
assert!(PayloadLength::is_empty(&data2));
assert!(!PayloadLength::is_empty(&data));
assert_eq!(PayloadLength::len(&data), 9);
assert_eq!(PayloadLength::len(&&data), 9);
assert_eq!(PayloadLength::len(&data.as_slice()), 9);
assert_eq!(PayloadLength::len(&data.to_vec()), 9);
}

#[test]
fn write_rtp_default() {
let mut data = [0; 128];
let mut vec = vec![];
let mut vec2 = vec![];
let builder = RtpPacketBuilder::new().payload_type(96);
let size = builder.write_into(&mut data).unwrap();
let buf = builder.write_vec().unwrap();
let buf2 = builder.write_vec_unchecked();
assert_eq!(buf, buf2);
builder.write_into_vec(&mut vec).unwrap();
builder.write_into_vec_unchecked(&mut vec2);
assert_eq!(vec, vec2);
drop(builder);
let data = &data[..size];
assert_eq!(size, buf.len());
Expand All @@ -618,6 +634,7 @@ mod tests {
fn write_rtp_header() {
let mut data = [0; 128];
let mut vec = vec![];
let mut vec2 = vec![];
let builder = RtpPacketBuilder::new()
.payload_type(96)
.marker_bit(true)
Expand All @@ -627,7 +644,11 @@ mod tests {
.add_csrc(0x0b0c0d0e);
let size = builder.write_into(&mut data).unwrap();
let buf = builder.write_vec().unwrap();
let buf2 = builder.write_vec_unchecked();
assert_eq!(buf, buf2);
builder.write_into_vec(&mut vec).unwrap();
builder.write_into_vec_unchecked(&mut vec2);
assert_eq!(vec, vec2);
drop(builder);
let data = &data[..size];
assert_eq!(size, buf.len());
Expand Down Expand Up @@ -655,13 +676,20 @@ mod tests {
fn write_rtp_header_multiple_csrcs() {
let mut data = [0; 128];
let mut vec = vec![];
let mut vec2 = vec![];
let builder = RtpPacketBuilder::new()
.payload_type(96)
.add_csrc(0x01020304)
.add_csrc(0x05060708);
let size = builder.write_into(&mut data).unwrap();
let size2 = builder.write_into_unchecked(&mut data);
assert_eq!(size, size2);
let buf = builder.write_vec().unwrap();
let buf2 = builder.write_vec_unchecked();
assert_eq!(buf, buf2);
builder.write_into_vec(&mut vec).unwrap();
builder.write_into_vec_unchecked(&mut vec2);
assert_eq!(vec, vec2);
drop(builder);
let data = &data[..size];
assert_eq!(size, buf.len());
Expand All @@ -681,6 +709,7 @@ mod tests {
fn write_rtp_multiple_payloads() {
let mut data = [0; 128];
let mut vec = vec![];
let mut vec2 = vec![];
let payload_data = [1, 2, 3, 4, 5, 6, 7, 8];
let more_payload_data = [9, 10, 11];
let builder = RtpPacketBuilder::new()
Expand All @@ -691,7 +720,11 @@ mod tests {
let size = builder.write_into(&mut data).unwrap();
assert_eq!(size, 24);
let buf = builder.write_vec().unwrap();
let buf2 = builder.write_vec_unchecked();
assert_eq!(buf, buf2);
builder.write_into_vec(&mut vec).unwrap();
builder.write_into_vec_unchecked(&mut vec2);
assert_eq!(vec, vec2);
drop(builder);
let data = &data[..size];
assert_eq!(size, buf.len());
Expand All @@ -709,6 +742,7 @@ mod tests {
fn write_rtp_extension() {
let mut data = [0; 128];
let mut vec = vec![];
let mut vec2 = vec![];
let extension_data = [1, 2, 3, 4, 5, 6, 7, 8];
let builder = RtpPacketBuilder::new()
.payload_type(96)
Expand All @@ -720,7 +754,11 @@ mod tests {
.extension(0x9876, extension_data.as_ref());
let size = builder.write_into(&mut data).unwrap();
let buf = builder.write_vec().unwrap();
let buf2 = builder.write_vec_unchecked();
assert_eq!(buf, buf2);
builder.write_into_vec(&mut vec).unwrap();
builder.write_into_vec_unchecked(&mut vec2);
assert_eq!(vec, vec2);
drop(builder);
let data = &data[..size];
assert_eq!(size, buf.len());
Expand All @@ -744,10 +782,56 @@ mod tests {
}
}

#[test]
fn write_rtp_extension_clear() {
let mut data = [0; 128];
let mut vec = vec![];
let mut vec2 = vec![];
let extension_data = [1, 2, 3, 4, 5, 6, 7, 8];
let builder = RtpPacketBuilder::new()
.payload_type(96)
.marker_bit(true)
.sequence_number(0x0102)
.timestamp(0x03040506)
.ssrc(0x0708090a)
.add_csrc(0x0b0c0d0e)
.extension(0x9876, extension_data.as_ref())
.clear_extension();
let size = builder.write_into(&mut data).unwrap();
let buf = builder.write_vec().unwrap();
let buf2 = builder.write_vec_unchecked();
assert_eq!(buf, buf2);
builder.write_into_vec(&mut vec).unwrap();
builder.write_into_vec_unchecked(&mut vec2);
assert_eq!(vec, vec2);
drop(builder);
let data = &data[..size];
assert_eq!(size, buf.len());
assert_eq!(size, vec.len());
for data in [data, buf.as_ref(), vec.as_ref()] {
println!("{data:?}");
let rtp = RtpPacket::parse(data).unwrap();
assert_eq!(rtp.version(), 2);
assert_eq!(rtp.padding(), None);
assert_eq!(rtp.n_csrcs(), 1);
assert!(rtp.marker_bit());
assert_eq!(rtp.payload_type(), 96);
assert_eq!(rtp.sequence_number(), 0x0102);
assert_eq!(rtp.timestamp(), 0x03040506);
assert_eq!(rtp.ssrc(), 0x0708090a);
let mut csrc = rtp.csrc();
assert_eq!(csrc.next(), Some(0x0b0c0d0e));
assert_eq!(csrc.next(), None);
assert_eq!(rtp.extension(), None);
assert_eq!(rtp.payload(), &[]);
}
}

#[test]
fn write_rtp_extension_payload_padding() {
let mut data = [0; 128];
let mut vec = vec![];
let mut vec2 = vec![];
let extension_data = [1, 2, 3, 4, 5, 6, 7, 8];
let payload_data = [1, 2, 3, 4, 5, 6, 7, 8];
let builder = RtpPacketBuilder::new()
Expand All @@ -762,7 +846,11 @@ mod tests {
.padding(7);
let size = builder.write_into(&mut data).unwrap();
let buf = builder.write_vec().unwrap();
let buf2 = builder.write_vec_unchecked();
assert_eq!(buf, buf2);
builder.write_into_vec(&mut vec).unwrap();
builder.write_into_vec_unchecked(&mut vec2);
assert_eq!(vec, vec2);
drop(builder);
let data = &data[..size];
assert_eq!(size, buf.len());
Expand All @@ -786,6 +874,49 @@ mod tests {
}
}

#[test]
fn write_rtp_extension_payload_maybe_padding() {
let mut data = [0; 128];
let mut vec = vec![];
let mut vec2 = vec![];
let builder = RtpPacketBuilder::new()
.payload_type(96)
.marker_bit(true)
.sequence_number(0x0102)
.timestamp(0x03040506)
.ssrc(0x0708090a)
.add_csrc(0x0b0c0d0e)
.maybe_padding(Some(7));
let size = builder.write_into(&mut data).unwrap();
let buf = builder.write_vec().unwrap();
let buf2 = builder.write_vec_unchecked();
assert_eq!(buf, buf2);
builder.write_into_vec(&mut vec).unwrap();
builder.write_into_vec_unchecked(&mut vec2);
assert_eq!(vec, vec2);
drop(builder);
let data = &data[..size];
assert_eq!(size, buf.len());
assert_eq!(size, vec.len());
for data in [data, buf.as_ref(), vec.as_ref()] {
println!("{data:?}");
let rtp = RtpPacket::parse(data).unwrap();
assert_eq!(rtp.version(), 2);
assert_eq!(rtp.padding(), Some(7));
assert_eq!(rtp.n_csrcs(), 1);
assert!(rtp.marker_bit());
assert_eq!(rtp.payload_type(), 96);
assert_eq!(rtp.sequence_number(), 0x0102);
assert_eq!(rtp.timestamp(), 0x03040506);
assert_eq!(rtp.ssrc(), 0x0708090a);
let mut csrc = rtp.csrc();
assert_eq!(csrc.next(), Some(0x0b0c0d0e));
assert_eq!(csrc.next(), None);
assert_eq!(rtp.extension(), None);
assert_eq!(rtp.payload(), &[]);
}
}

#[test]
fn write_rtp_invalid_padding() {
let mut data = [0; 128];
Expand Down Expand Up @@ -842,6 +973,65 @@ mod tests {
);
}

#[test]
fn write_rtp_max_contributions() {
let mut data = [0; 128];
let mut vec = vec![];
let mut vec2 = vec![];
let builder = RtpPacketBuilder::new()
.payload_type(96)
.marker_bit(true)
.sequence_number(0x0102)
.timestamp(0x03040506)
.ssrc(0x0708090a)
.maybe_padding(Some(7))
.add_csrc(1)
.add_csrc(2)
.add_csrc(3)
.add_csrc(4)
.add_csrc(5)
.add_csrc(6)
.add_csrc(7)
.add_csrc(8)
.add_csrc(9)
.add_csrc(10)
.add_csrc(11)
.add_csrc(12)
.add_csrc(13)
.add_csrc(14)
.add_csrc(15);
let size = builder.write_into(&mut data).unwrap();
let buf = builder.write_vec().unwrap();
let buf2 = builder.write_vec_unchecked();
assert_eq!(buf, buf2);
builder.write_into_vec(&mut vec).unwrap();
builder.write_into_vec_unchecked(&mut vec2);
assert_eq!(vec, vec2);
drop(builder);
let data = &data[..size];
assert_eq!(size, buf.len());
assert_eq!(size, vec.len());
for data in [data, buf.as_ref(), vec.as_ref()] {
println!("{data:?}");
let rtp = RtpPacket::parse(data).unwrap();
assert_eq!(rtp.version(), 2);
assert_eq!(rtp.padding(), Some(7));
assert_eq!(rtp.n_csrcs(), 15);
assert!(rtp.marker_bit());
assert_eq!(rtp.payload_type(), 96);
assert_eq!(rtp.sequence_number(), 0x0102);
assert_eq!(rtp.timestamp(), 0x03040506);
assert_eq!(rtp.ssrc(), 0x0708090a);
let mut csrc = rtp.csrc();
for i in 1..16 {
assert_eq!(csrc.next(), Some(i));
}
assert_eq!(csrc.next(), None);
assert_eq!(rtp.extension(), None);
assert_eq!(rtp.payload(), &[]);
}
}

#[test]
fn write_rtp_too_many_contributions() {
let mut data = [0; 128];
Expand Down
Loading
Loading