#[cfg(test)]
mod vp8_test;
use crate::{
error::{Error, Result},
packetizer::{Depacketizer, Payloader},
};
use bytes::{Buf, BufMut, Bytes, BytesMut};
pub const VP8_HEADER_SIZE: usize = 1;
#[derive(Default, Debug, Copy, Clone)]
pub struct Vp8Payloader {
pub enable_picture_id: bool,
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.enable_picture_id {
if self.picture_id == 0 || self.picture_id < 128 {
VP8_HEADER_SIZE + 2
} else {
VP8_HEADER_SIZE + 3
}
} else {
VP8_HEADER_SIZE
};
let max_fragment_size = mtu as isize - using_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 self.enable_picture_id {
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 tid: u8,
pub y: u8,
pub key_idx: u8,
}
impl Depacketizer for Vp8Packet {
fn depacketize(&mut self, packet: &Bytes) -> Result<Bytes> {
let payload_len = packet.len();
if payload_len < 4 {
return Err(Error::ErrShortPacket);
}
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 payload_index >= payload_len {
return Err(Error::ErrShortPacket);
}
if self.l == 1 {
self.tl0_pic_idx = reader.get_u8();
payload_index += 1;
}
if payload_index >= payload_len {
return Err(Error::ErrShortPacket);
}
if self.t == 1 || self.k == 1 {
let b = reader.get_u8();
if self.t == 1 {
self.tid = b >> 6;
self.y = (b >> 5) & 0x1;
}
if self.k == 1 {
self.key_idx = b & 0x1F;
}
payload_index += 1;
}
if payload_index >= packet.len() {
return Err(Error::ErrShortPacket);
}
Ok(packet.slice(payload_index..))
}
fn is_partition_head(&self, payload: &Bytes) -> bool {
if payload.is_empty() {
false
} else {
(payload[0] & 0x10) != 0
}
}
fn is_partition_tail(&self, marker: bool, _payload: &Bytes) -> bool {
marker
}
}