use serde::{Deserialize, Serialize};
use web_time::{Duration, Instant};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct RtpHeader {
pub sequence_number: u16,
pub timestamp: u32,
pub ssrc: u32,
pub payload_type: u8,
pub marker: bool,
}
impl RtpHeader {
pub fn new(
sequence_number: u16,
timestamp: u32,
ssrc: u32,
payload_type: u8,
marker: bool,
) -> Self {
Self {
sequence_number,
timestamp,
ssrc,
payload_type,
marker,
}
}
pub fn is_sequence_newer(&self, other_seq: u16) -> bool {
let diff = self.sequence_number.wrapping_sub(other_seq);
diff < 0x8000
}
pub fn is_timestamp_newer(&self, other_timestamp: u32) -> bool {
let diff = self.timestamp.wrapping_sub(other_timestamp);
diff < 0x80000000
}
}
#[derive(Debug, Clone)]
pub struct AudioPacket {
pub header: RtpHeader,
pub payload: Vec<u8>,
pub arrival_time: Instant,
pub sample_rate: u32,
pub channels: u8,
pub duration_ms: u32,
}
impl AudioPacket {
pub fn new(
header: RtpHeader,
payload: Vec<u8>,
sample_rate: u32,
channels: u8,
duration_ms: u32,
) -> Self {
Self {
header,
payload,
arrival_time: Instant::now(),
sample_rate,
channels,
duration_ms,
}
}
pub fn payload_size(&self) -> usize {
self.payload.len()
}
pub fn age(&self) -> Duration {
self.arrival_time.elapsed()
}
pub fn is_older_than(&self, max_age: Duration) -> bool {
self.age() > max_age
}
pub fn expected_samples(&self) -> usize {
((self.sample_rate as u64 * self.duration_ms as u64) / 1000) as usize
* self.channels as usize
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::thread;
#[test]
fn test_rtp_header_sequence_comparison() {
let header1 = RtpHeader::new(100, 1000, 12345, 96, false);
let header2 = RtpHeader::new(101, 1000, 12345, 96, false);
assert!(header2.is_sequence_newer(header1.sequence_number));
assert!(!header1.is_sequence_newer(header2.sequence_number));
}
#[test]
fn test_rtp_header_sequence_wraparound() {
let header1 = RtpHeader::new(65535, 1000, 12345, 96, false);
let header2 = RtpHeader::new(0, 1000, 12345, 96, false);
assert!(header2.is_sequence_newer(header1.sequence_number));
}
#[test]
fn test_audio_packet_age() {
let header = RtpHeader::new(100, 1000, 12345, 96, false);
let packet = AudioPacket::new(header, vec![0; 160], 16000, 1, 20);
thread::sleep(Duration::from_millis(10));
assert!(packet.age() >= Duration::from_millis(10));
}
#[test]
fn test_expected_samples() {
let header = RtpHeader::new(100, 1000, 12345, 96, false);
let packet = AudioPacket::new(header, vec![0; 320], 16000, 1, 20);
assert_eq!(packet.expected_samples(), 320);
}
}