use byteorder::{BigEndian, ByteOrder, LittleEndian};
const AVIIF_KEYFRAME: u32 = 0x0000_0010;
#[derive(Clone, Copy, Debug)]
pub struct Frame {
pub id: u32,
pub flag: u32,
pub offset: u32,
pub length: u32,
}
impl Frame {
#[must_use]
pub fn new(bytes: &[u8]) -> Self {
let mut iter = bytes.chunks(4);
Self {
id: BigEndian::read_u32(iter.next().unwrap_or_default()),
flag: LittleEndian::read_u32(iter.next().unwrap_or_default()),
offset: LittleEndian::read_u32(iter.next().unwrap_or_default()),
length: LittleEndian::read_u32(iter.next().unwrap_or_default()),
}
}
#[must_use]
pub fn as_bytes(&self) -> [u8; 16] {
let mut buf = [0u8; 16];
BigEndian::write_u32_into(&[self.id], &mut buf[..4]);
LittleEndian::write_u32_into(&[self.flag, self.offset, self.length], &mut buf[4..]);
buf
}
#[must_use]
pub fn is_videoframe(&self) -> bool {
let id = self.id_as_u8_array();
&id[2..4] == b"db" || &id[2..4] == b"dc"
}
#[must_use]
pub fn is_audioframe(&self) -> bool {
let id = self.id_as_u8_array();
&id[2..4] == b"wb"
}
#[must_use]
pub fn is_iframe(&self) -> bool {
if self.is_videoframe() {
return self.flag & AVIIF_KEYFRAME != 0;
}
false
}
#[must_use]
pub fn is_pframe(&self) -> bool {
if self.is_videoframe() {
return self.flag & AVIIF_KEYFRAME == 0;
}
false
}
fn id_as_u8_array(&self) -> [u8; 4] {
let mut buf = [0u8; 4];
BigEndian::write_u32(&mut buf, self.id);
buf
}
}