#[cfg(test)]
mod vp8_test;
use crate::{
error::Error,
packetizer::{Depacketizer, Payloader},
};
use anyhow::Result;
use bytes::{Buf, BufMut, Bytes, BytesMut};
pub const VP8_HEADER_SIZE: usize = 1;
#[derive(Default, Debug, Copy, Clone)]
pub struct Vp8Payloader {
picture_id: u16,
}
impl Payloader for Vp8Payloader {
fn payload(&mut self, mtu: usize, payload: &Bytes) -> Result<Vec<Bytes>> {
if payload.is_empty() || mtu == 0 {
return Ok(vec![]);
}
let using_header_size = if self.picture_id == 0 || self.picture_id < 128 {
VP8_HEADER_SIZE + 2
} else {
VP8_HEADER_SIZE + 3
};
let max_fragment_size = mtu as isize - VP8_HEADER_SIZE as isize;
let mut payload_data_remaining = payload.len() as isize;
let mut payload_data_index: usize = 0;
let mut payloads = vec![];
if std::cmp::min(max_fragment_size, payload_data_remaining) <= 0 {
return Ok(payloads);
}
let mut first = true;
while payload_data_remaining > 0 {
let current_fragment_size =
std::cmp::min(max_fragment_size, payload_data_remaining) as usize;
let mut out = BytesMut::with_capacity(using_header_size + current_fragment_size);
let mut buf = vec![0u8; 4];
if first {
buf[0] = 0x10;
first = false;
}
if using_header_size == VP8_HEADER_SIZE + 2 {
buf[0] |= 0x80;
buf[1] |= 0x80;
buf[2] |= (self.picture_id & 0x7F) as u8;
} else if using_header_size == VP8_HEADER_SIZE + 3 {
buf[0] |= 0x80;
buf[1] |= 0x80;
buf[2] |= 0x80 | ((self.picture_id >> 8) & 0x7F) as u8;
buf[3] |= (self.picture_id & 0xFF) as u8;
}
out.put(&buf[..using_header_size]);
out.put(
&*payload.slice(payload_data_index..payload_data_index + current_fragment_size),
);
payloads.push(out.freeze());
payload_data_remaining -= current_fragment_size as isize;
payload_data_index += current_fragment_size;
}
self.picture_id += 1;
self.picture_id &= 0x7FFF;
Ok(payloads)
}
fn clone_to(&self) -> Box<dyn Payloader + Send + Sync> {
Box::new(*self)
}
}
#[derive(PartialEq, Debug, Default, Clone)]
pub struct Vp8Packet {
pub x: u8,
pub n: u8,
pub s: u8,
pub pid: u8,
pub i: u8,
pub l: u8,
pub t: u8,
pub k: u8,
pub picture_id: u16,
pub tl0_pic_idx: u8,
pub payload: Bytes,
}
impl Depacketizer for Vp8Packet {
fn depacketize(&mut self, packet: &Bytes) -> Result<()> {
if packet.len() < 4 {
return Err(Error::ErrShortPacket.into());
}
let reader = &mut packet.clone();
let mut payload_index = 0;
let mut b = reader.get_u8();
payload_index += 1;
self.x = (b & 0x80) >> 7;
self.n = (b & 0x20) >> 5;
self.s = (b & 0x10) >> 4;
self.pid = b & 0x07;
if self.x == 1 {
b = reader.get_u8();
payload_index += 1;
self.i = (b & 0x80) >> 7;
self.l = (b & 0x40) >> 6;
self.t = (b & 0x20) >> 5;
self.k = (b & 0x10) >> 4;
}
if self.i == 1 {
b = reader.get_u8();
payload_index += 1;
if b & 0x80 > 0 {
self.picture_id = (((b & 0x7f) as u16) << 8) | (reader.get_u8() as u16);
payload_index += 1;
} else {
self.picture_id = b as u16;
}
}
if self.l == 1 {
reader.get_u8();
payload_index += 1;
}
if self.t == 1 || self.k == 1 {
payload_index += 1;
}
if payload_index >= packet.len() {
return Err(Error::ErrShortPacket.into());
}
self.payload = packet.slice(payload_index..);
Ok(())
}
}