#[cfg(test)]
mod vp9_test;
use crate::{
error::Error,
packetizer::{Depacketizer, Payloader},
};
use anyhow::Result;
use bytes::{Buf, Bytes};
#[derive(Default, Debug, Copy, Clone)]
pub struct Vp9Payloader;
impl Payloader for Vp9Payloader {
fn payload(&mut self, mtu: usize, payload: &Bytes) -> Result<Vec<Bytes>> {
if payload.is_empty() || mtu == 0 {
return Ok(vec![]);
}
let mut payloads = vec![];
let mut payload_data_remaining = payload.len();
let mut payload_data_index = 0;
while payload_data_remaining > 0 {
let current_fragment_size = std::cmp::min(mtu as usize, payload_data_remaining);
payloads.push(
payload.slice(payload_data_index..payload_data_index + current_fragment_size),
);
payload_data_remaining -= current_fragment_size;
payload_data_index += current_fragment_size;
}
Ok(payloads)
}
fn clone_to(&self) -> Box<dyn Payloader + Send + Sync> {
Box::new(*self)
}
}
#[derive(PartialEq, Debug, Default, Clone)]
pub struct Vp9Packet {
pub i: u8, pub p: u8, pub l: u8, pub f: u8, pub b: u8, pub e: u8, pub v: u8, pub z: u8,
pub picture_id: u16,
pub layer_index: Option<Vp9LayerIndex>,
pub p_diff: Vec<u8>,
pub scalability_structure: Option<Vp9ScalabilityStructure>,
pub payload: Bytes,
}
#[derive(PartialEq, Debug, Default, Clone)]
pub struct Vp9LayerIndex {
pub tid: u8,
pub u: u8,
pub sid: u8,
pub d: u8,
pub tl0_pic_idx: u8,
}
#[derive(PartialEq, Debug, Default, Clone)]
pub struct Vp9ScalabilityStructure {
pub ns: u8,
pub y: u8,
pub g: u8,
pub frame_resolution: Vec<Vp9FrameResolution>,
pub ng: u8,
pub picture_group: Vec<Vp9PictureGroup>,
}
#[derive(PartialEq, Debug, Default, Clone)]
pub struct Vp9FrameResolution {
pub width: u16,
pub height: u16,
}
#[derive(PartialEq, Debug, Default, Clone)]
pub struct Vp9PictureGroup {
pub tid: u8,
pub u: u8,
pub r: u8,
pub p_diff: Vec<u8>,
}
impl Depacketizer for Vp9Packet {
fn depacketize(&mut self, packet: &Bytes) -> Result<()> {
if packet.len() < 2 {
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.i = (b & 0x80) >> 7;
self.p = (b & 0x40) >> 6;
self.l = (b & 0x20) >> 5;
self.f = (b & 0x10) >> 4;
self.b = (b & 0x08) >> 3;
self.e = (b & 0x04) >> 2;
self.v = (b & 0x02) >> 1;
self.z = b & 0x01;
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 {
let mut l = Vp9LayerIndex::default();
b = reader.get_u8();
payload_index += 1;
l.tid = (b & 0b1110_0000) >> 5;
l.u = (b & 0b0001_0000) >> 4;
l.sid = (b & 0b0000_1110) >> 1;
l.d = b & 0b0000_0001;
if self.f == 0 {
l.tl0_pic_idx = reader.get_u8();
payload_index += 1;
}
self.layer_index = Some(l);
}
if self.f == 1 && self.p == 1 {
loop {
b = reader.get_u8();
payload_index += 1;
self.p_diff.push((b & 0b1111_1110) >> 1);
let has_more = (b & 1) > 0;
if !has_more || self.p_diff.len() == 3 {
break;
}
}
}
if self.v == 1 {
let mut s = Vp9ScalabilityStructure::default();
b = reader.get_u8();
payload_index += 1;
s.ns = (b & 0b1110_0000) >> 5;
s.y = (b & 0b0001_0000) >> 4;
s.g = (b & 0b0000_1000) >> 3;
if s.y == 1 {
for _ in 0..(s.ns + 1) {
s.frame_resolution.push(Vp9FrameResolution {
width: reader.get_u16(),
height: reader.get_u16(),
});
payload_index += 4;
}
}
if s.g == 1 {
s.ng = reader.get_u8();
payload_index += 1;
for _ in 0..s.ng {
b = reader.get_u8();
payload_index += 1;
let mut p = Vp9PictureGroup {
tid: (b & 0b1110_0000) >> 5,
u: (b & 0b0001_0000) >> 4,
r: (b & 0b0000_1100) >> 2,
..Default::default()
};
for _ in 0..p.r {
p.p_diff.push(reader.get_u8());
payload_index += 1;
}
}
}
}
self.payload = packet.slice(payload_index..);
Ok(())
}
}