blob: 1d7a24e43d20e7ab88b18e97531ea38e4d9dd23c [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use {
anyhow::{format_err, Error},
bitfield::bitfield,
std::{cmp::min, collections::VecDeque},
};
bitfield! {
/// The header for an RTP packet.
/// The meaning of each field will vary based on the negotiated codec.
struct RtpHeader(MSB0 [u8]);
u8, version, set_version: 1, 0;
bool, padding, set_padding: 2;
bool, extension, set_extension: 3;
u8, csrc_count, set_csrc_count: 7, 4;
bool, marker, set_marker: 8;
u8, payload_type, set_payload_type: 15, 9;
u16, sequence_number, set_sequence_number: 31, 16;
u32, timestamp, set_timestamp: 63, 32;
u32, ssrc, set_ssrc: 95, 64;
}
const RTP_HEADER_LEN: usize = 12;
/// Set to the RTP version specified by RFC 3550 which is the version supported here.
const RTP_VERSION: u8 = 2;
/// Dynamic payload type indicated by RFC 3551, recommended by the A2DP spec.
const RTP_PAYLOAD_DYNAMIC: u8 = 96;
pub trait RtpPacketBuilder: Send {
/// Adds a `frame` of audio to the RTP packet, which represents `samples` audio samples.
/// Returns a vector of packets that are ready to be transmitted (which can be empty),
/// or an Error if the frame could not be added.
fn add_frame(&mut self, frame: Vec<u8>, samples: u32) -> Result<Vec<Vec<u8>>, Error>;
}
/// A PacketBuilder that implements the SBC RTP Payload format as specified in A2DP 1.3.2 Section
/// 4.3.4.
pub(crate) struct SbcRtpPacketBuilder {
/// maximum size of the RTP packet, including headers
max_packet_size: usize,
/// next sequence number to be used
next_sequence: u16,
/// Timestamp of the last packet sent so far, in audio sample units
timestamp: u32,
/// Frames that will be in the next RtpPacket to be sent.
frames: VecDeque<Vec<u8>>,
/// Total samples that those frames represent.
samples: u32,
}
impl SbcRtpPacketBuilder {
const MAX_FRAMES_PER_PACKET: usize = 15;
pub fn new(max_packet_size: usize) -> Self {
Self {
max_packet_size,
next_sequence: 1,
timestamp: 0,
frames: VecDeque::new(),
samples: 0,
}
}
/// Return the header length of a RTP packet encapsulating SBC, including the pre-frame
/// data, which is one octet long.
fn header_len(&self) -> usize {
RTP_HEADER_LEN + 1
}
/// The total number of bytes currently waiting to be sent in the next frame.
fn frame_bytes_len(&self) -> usize {
self.frames.iter().map(Vec::len).sum()
}
/// Build the next RTP packet using the frames queued.
/// After the packet is returned, the frames are clear and the state is updated to
/// track building the next packet.
/// Panics if called when there are no frames to be sent.
fn build_packet(&mut self) -> Vec<u8> {
if self.frames.is_empty() {
panic!("Can't build an empty RTP SBC packet: no frames");
}
let mut header = RtpHeader([0; RTP_HEADER_LEN]);
header.set_version(RTP_VERSION);
header.set_payload_type(RTP_PAYLOAD_DYNAMIC);
header.set_sequence_number(self.next_sequence);
header.set_timestamp(self.timestamp);
let mut packet: Vec<u8> = header.0.iter().cloned().collect();
packet.push(self.frames.len() as u8);
let mut frames_bytes = self.frames.drain(..).flatten().collect();
packet.append(&mut frames_bytes);
self.next_sequence = self.next_sequence.wrapping_add(1);
self.timestamp = self.timestamp.wrapping_add(self.samples);
self.samples = 0;
packet
}
}
impl RtpPacketBuilder for SbcRtpPacketBuilder {
fn add_frame(&mut self, frame: Vec<u8>, samples: u32) -> Result<Vec<Vec<u8>>, Error> {
if (frame.len() + self.header_len()) > self.max_packet_size {
return Err(format_err!("Media packet too large for RTP max size"));
}
let mut packets = Vec::new();
let packet_size_with_new = self.header_len() + self.frame_bytes_len() + frame.len();
if packet_size_with_new > self.max_packet_size {
packets.push(self.build_packet());
}
self.frames.push_back(frame);
self.samples = self.samples + samples;
if self.frames.len() == Self::MAX_FRAMES_PER_PACKET {
packets.push(self.build_packet());
}
Ok(packets)
}
}
/// A packetbuilder that works for MPEG-2,4 AAC as specified in A2DP 1.3.1 Section 4.5 and
/// RFC 3016.
pub(crate) struct AacRtpPacketBuilder {
/// The maximum size of a RTP packet, including headers.
max_packet_size: usize,
/// The next sequence number to be used
next_sequence: u16,
/// Timestamp of the last packet sent so far.
timestamp: u32,
}
impl AacRtpPacketBuilder {
pub fn new(max_packet_size: usize) -> Self {
Self { max_packet_size, next_sequence: 1, timestamp: 0 }
}
}
impl RtpPacketBuilder for AacRtpPacketBuilder {
fn add_frame(&mut self, mut frame: Vec<u8>, samples: u32) -> Result<Vec<Vec<u8>>, Error> {
let mut header = RtpHeader([0; RTP_HEADER_LEN]);
header.set_version(RTP_VERSION);
header.set_payload_type(RTP_PAYLOAD_DYNAMIC);
header.set_timestamp(self.timestamp);
let mut left = frame.len();
let mut packets = Vec::new();
while left > 0 {
let mux_element_space = self.max_packet_size - RTP_HEADER_LEN;
header.set_sequence_number(self.next_sequence);
// RFC 3016: If the end of this frame will be included, set the marker to 1
if left <= mux_element_space {
header.set_marker(true);
}
let header_iter = header.0.iter().cloned();
let packet_frame_end = min(mux_element_space, frame.len());
let frame_bytes_iter = frame.drain(..packet_frame_end);
let packet = header_iter.chain(frame_bytes_iter).collect();
packets.push(packet);
left = left.saturating_sub(packet_frame_end);
self.next_sequence = self.next_sequence.wrapping_add(1);
}
self.timestamp = self.timestamp.wrapping_add(samples);
Ok(packets)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sbc_packet_builder_max_len() {
// 4 bytes leeway for the frames, plus one byte for the payload header.
let mut builder = SbcRtpPacketBuilder::new(RTP_HEADER_LEN + 5);
assert!(builder.add_frame(vec![0xf0], 1).unwrap().is_empty());
assert!(builder.add_frame(vec![0x9f], 2).unwrap().is_empty());
assert!(builder.add_frame(vec![0x92], 4).unwrap().is_empty());
assert!(builder.add_frame(vec![0x96], 8).unwrap().is_empty());
let mut result = builder.add_frame(vec![0xf0], 16).expect("no error");
let expected = &[
0x80, 0x60, 0x00, 0x01, // Sequence num
0x00, 0x00, 0x00, 0x00, // timestamp = 0
0x00, 0x00, 0x00, 0x00, // SSRC = 0
0x04, // Frames in this packet
0xf0, 0x9f, 0x92, 0x96, // 💖
];
let result = result.drain(..).next().expect("a packet after 4 frames");
assert_eq!(expected.len(), result.len());
assert_eq!(expected, &result[0..expected.len()]);
assert!(builder.add_frame(vec![0x9f], 32).unwrap().is_empty());
assert!(builder.add_frame(vec![0x92], 64).unwrap().is_empty());
assert!(builder.add_frame(vec![0x96], 128).unwrap().is_empty());
let mut result = builder.add_frame(vec![0x33], 256).expect("no error");
let expected = &[
0x80, 0x60, 0x00, 0x02, // Sequence num
0x00, 0x00, 0x00, 0x0F, // timestamp = 2^0 + 2^1 + 2^2 + 2^3)
0x00, 0x00, 0x00, 0x00, // SSRC = 0
0x04, // Frames in this packet
0xf0, 0x9f, 0x92, 0x96, // 💖
];
let result = result.drain(..).next().expect("a packet after 4 more frames");
assert_eq!(expected.len(), result.len());
assert_eq!(expected, &result[0..expected.len()]);
// Trying to push a packet that will never fit in the max returns an error.
let result = builder.add_frame(vec![0x01, 0x02, 0x03, 0x04, 0x05], 512);
assert!(result.is_err());
}
#[test]
fn sbc_packet_builder_max_frames() {
let max_tx_size = 200;
let mut builder = SbcRtpPacketBuilder::new(max_tx_size);
assert!(builder.add_frame(vec![0xf0], 1).unwrap().is_empty());
assert!(builder.add_frame(vec![0x9f], 2).unwrap().is_empty());
assert!(builder.add_frame(vec![0x92], 4).unwrap().is_empty());
assert!(builder.add_frame(vec![0x96], 8).unwrap().is_empty());
assert!(builder.add_frame(vec![0xf0], 16).unwrap().is_empty());
assert!(builder.add_frame(vec![0x9f], 32).unwrap().is_empty());
assert!(builder.add_frame(vec![0x92], 64).unwrap().is_empty());
assert!(builder.add_frame(vec![0x96], 128).unwrap().is_empty());
assert!(builder.add_frame(vec![0xf0], 256).unwrap().is_empty());
assert!(builder.add_frame(vec![0x9f], 512).unwrap().is_empty());
assert!(builder.add_frame(vec![0x92], 1024).unwrap().is_empty());
assert!(builder.add_frame(vec![0x96], 2048).unwrap().is_empty());
assert!(builder.add_frame(vec![0x33], 4096).unwrap().is_empty());
assert!(builder.add_frame(vec![0x33], 8192).unwrap().is_empty());
let mut result = builder.add_frame(vec![0x33], 16384).expect("no error");
let expected = &[
0x80, 0x60, 0x00, 0x01, // Sequence num
0x00, 0x00, 0x00, 0x00, // timestamp = 0
0x00, 0x00, 0x00, 0x00, // SSRC = 0
0x0F, // 15 frames in this packet
0xf0, 0x9f, 0x92, 0x96, // 💖
0xf0, 0x9f, 0x92, 0x96, // 💖
0xf0, 0x9f, 0x92, 0x96, // 💖
0x33, 0x33, 0x33, // !!!
];
let result = result.drain(..).next().expect("should have a packet");
assert_eq!(expected.len(), result.len());
assert_eq!(expected, &result[0..expected.len()]);
assert!(builder.add_frame(vec![0xf0, 0x9f, 0x92, 0x96], 32768).unwrap().is_empty());
let rest_of_packet: Vec<u8> = (4..(max_tx_size - RTP_HEADER_LEN - 1) as u8).collect();
assert!(builder.add_frame(rest_of_packet, 65536).unwrap().is_empty());
let mut result = builder.add_frame(vec![0x33], 131072).expect("no error");
let expected = &[
0x80, 0x60, 0x00, 0x02, // Sequence num
0x00, 0x00, 0x7F, 0xFF, // timestamp = 2^0 + 2^1 + ... + 2^14 (sent last time)
0x00, 0x00, 0x00, 0x00, // SSRC = 0
0x02, // 2 frames in this packet
0xf0, 0x9f, 0x92, 0x96, // 💖
];
let result = result.drain(..).next().expect("a packet after max bytes exceeded");
assert!(expected.len() <= result.len());
assert_eq!(expected, &result[0..expected.len()]);
}
#[test]
fn aac_packet_buikder() {
let mut builder = AacRtpPacketBuilder::new(5 + RTP_HEADER_LEN);
// One packet has at max one frame in it, so it is returned immediately.
let result = builder
.add_frame(vec![0xf0], 1)
.unwrap()
.drain(..)
.next()
.expect("should return a frame");
let expected = &[
0x80, // Version=2, padding, extension (0), csrc count (0),
0xE0, // Marker (1), Payload Type (96)
0x00, 0x01, // Sequence num
0x00, 0x00, 0x00, 0x00, // timestamp = 0
0x00, 0x00, 0x00, 0x00, // SSRC = 0
0xf0, // frame payload.
];
assert_eq!(expected.len(), result.len());
assert_eq!(expected, &result[0..expected.len()]);
let result = builder
.add_frame(vec![0xf0, 0x9f, 0x92, 0x96], 2)
.unwrap()
.drain(..)
.next()
.expect("should return a frame");
let expected = &[
0x80, // Version=2, padding, extension (0), csrc count (0),
0xE0, // Marker (1), Payload Type (96)
0x00, 0x02, // Sequence num
0x00, 0x00, 0x00, 0x01, // timestamp = 1
0x00, 0x00, 0x00, 0x00, // SSRC = 0
0xf0, 0x9f, 0x92, 0x96, // frame payload.
];
assert_eq!(expected.len(), result.len());
assert_eq!(expected, &result[0..expected.len()]);
}
#[test]
fn aac_packet_builder_fragmentation() {
let mut builder = AacRtpPacketBuilder::new(2 + RTP_HEADER_LEN);
// One packet has at max one frame in it, so it is returned immediately.
let frames = builder.add_frame(vec![0xf0, 0x9f, 0x92, 0x96], 1).unwrap();
assert_eq!(2, frames.len());
let first_expected = &[
0x80, // Version=2, padding, extension (0), csrc count (0),
0x60, // Marker (0), Payload Type (96)
0x00, 0x01, // Sequence num
0x00, 0x00, 0x00, 0x00, // timestamp = 0
0x00, 0x00, 0x00, 0x00, // SSRC = 0
0xf0, 0x9f, // frame payload.
];
assert_eq!(first_expected.len(), frames[0].len());
assert_eq!(first_expected, &frames[0][0..first_expected.len()]);
let second_expected = &[
0x80, // Version=2, padding, extension (0), csrc count (0),
0xE0, // Marker (1), Payload Type (96)
0x00, 0x02, // Sequence num
0x00, 0x00, 0x00, 0x00, // timestamp = 0
0x00, 0x00, 0x00, 0x00, // SSRC = 0
0x92, 0x96, // frame payload.
];
assert_eq!(second_expected.len(), frames[1].len());
assert_eq!(second_expected, &frames[1][0..second_expected.len()]);
let frames = builder.add_frame(vec![0xf0, 0x9f], 2).unwrap();
assert_eq!(1, frames.len());
let result = frames.first().unwrap();
let expected = &[
0x80, // Version=2, padding, extension (0), csrc count (0),
0xE0, // Marker (1), Payload Type (96)
0x00, 0x03, // Sequence num
0x00, 0x00, 0x00, 0x01, // timestamp = 1
0x00, 0x00, 0x00, 0x00, // SSRC = 0
0xf0, 0x9f, // frame payload.
];
assert_eq!(expected.len(), result.len());
assert_eq!(expected, &result[0..expected.len()]);
}
}