/* This file is part of jellything (https://codeberg.org/metamuffin/jellything) which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2023 metamuffin */ use crate::{read::ReadExt, write::write_vint}; use anyhow::Result; use std::io::Cursor; pub enum LacingType { Xiph, FixedSize, Ebml, } pub struct Block { pub track: u64, pub keyframe: bool, pub discardable: bool, pub timestamp_off: i16, pub invisible: bool, pub lacing: Option, pub data: Vec, } impl Block { pub fn parse(buf: &[u8]) -> Result { let (track, c) = Cursor::new(buf).read_vint_len()?; let timestamp_off = i16::from_be_bytes(buf[c..c + 2].try_into().unwrap()); let flags = buf[c + 2]; let data = Vec::from(&buf[c + 3..]); let invisible = (flags & 0b1000) == 0b1000; let lacing = match flags & 0b110 { 0b000 => None, 0b010 => Some(LacingType::Xiph), 0b100 => Some(LacingType::FixedSize), 0b110 => Some(LacingType::Ebml), _ => unreachable!(), }; let keyframe = (flags & 0b10000000) == 0b10000000; let discardable = (flags & 0b1) == 0b1; Ok(Self { keyframe, discardable, track, data, invisible, lacing, timestamp_off, }) } pub fn dump(&self) -> Vec { let mut out = vec![]; write_vint(&mut out, self.track).unwrap(); out.extend(self.timestamp_off.to_be_bytes().into_iter()); out.push( match self.discardable { true => 0b1, false => 0b0, } | match self.keyframe { true => 0b10000000, false => 0b00000000, } | match self.invisible { true => 0b1000, false => 0b0000, } | match self.lacing { Some(LacingType::Xiph) => 0b010, Some(LacingType::Ebml) => 0b100, Some(LacingType::FixedSize) => 0b110, None => 0b0000, }, ); out.extend(self.data.iter()); out } }