#![allow(dead_code)]
use alloc::string::String;
use alloc::vec::Vec;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct FourCC(pub [u8; 4]);
impl FourCC {
pub const FTYP: Self = Self(*b"ftyp");
pub const META: Self = Self(*b"meta");
pub const HDLR: Self = Self(*b"hdlr");
pub const PITM: Self = Self(*b"pitm");
pub const ILOC: Self = Self(*b"iloc");
pub const IINF: Self = Self(*b"iinf");
pub const INFE: Self = Self(*b"infe");
pub const IPRP: Self = Self(*b"iprp");
pub const IPCO: Self = Self(*b"ipco");
pub const IPMA: Self = Self(*b"ipma");
pub const MDAT: Self = Self(*b"mdat");
pub const ISPE: Self = Self(*b"ispe");
pub const HVCB: Self = Self(*b"hvcB");
pub const HVCC: Self = Self(*b"hvcC");
pub const COLR: Self = Self(*b"colr");
pub const PIXI: Self = Self(*b"pixi");
pub const IREF: Self = Self(*b"iref");
pub const AUXC: Self = Self(*b"auxC");
pub const IDAT: Self = Self(*b"idat");
pub const DIMG: Self = Self(*b"dimg");
pub const CLAP: Self = Self(*b"clap");
pub const IROT: Self = Self(*b"irot");
pub const AUXL: Self = Self(*b"auxl");
pub const IMIR: Self = Self(*b"imir");
pub const THMB: Self = Self(*b"thmb");
pub const CDSC: Self = Self(*b"cdsc");
pub const CLLI: Self = Self(*b"clli");
pub const MDCV: Self = Self(*b"mdcv");
pub const AV1C: Self = Self(*b"av1C");
pub const UNCC: Self = Self(*b"uncC");
pub const CMPC: Self = Self(*b"cmpC");
pub const MOOV: Self = Self(*b"moov");
pub const TRAK: Self = Self(*b"trak");
pub const TKHD: Self = Self(*b"tkhd");
pub const MDIA: Self = Self(*b"mdia");
pub const MDHD: Self = Self(*b"mdhd");
pub const MINF: Self = Self(*b"minf");
pub const STBL: Self = Self(*b"stbl");
pub const STSD: Self = Self(*b"stsd");
pub const STSZ: Self = Self(*b"stsz");
pub const STCO: Self = Self(*b"stco");
pub const CO64: Self = Self(*b"co64");
pub const STSC: Self = Self(*b"stsc");
pub const STSS: Self = Self(*b"stss");
pub const HVC1: Self = Self(*b"hvc1");
pub const HEV1: Self = Self(*b"hev1");
pub const TREF: Self = Self(*b"tref");
pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() >= 4 {
Some(Self([bytes[0], bytes[1], bytes[2], bytes[3]]))
} else {
None
}
}
pub fn as_str(&self) -> &str {
core::str::from_utf8(&self.0).unwrap_or("????")
}
}
impl core::fmt::Display for FourCC {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
pub struct BoxHeader {
pub box_type: FourCC,
pub size: u64,
pub content_offset: usize,
}
#[derive(Debug)]
pub struct Box<'a> {
pub header: BoxHeader,
pub content: &'a [u8],
}
impl<'a> Box<'a> {
pub fn box_type(&self) -> FourCC {
self.header.box_type
}
#[allow(dead_code)]
pub fn version_flags(&self) -> Option<(u8, u32)> {
if self.content.len() >= 4 {
let version = self.content[0];
let flags = u32::from_be_bytes([0, self.content[1], self.content[2], self.content[3]]);
Some((version, flags))
} else {
None
}
}
}
pub struct BoxIterator<'a> {
data: &'a [u8],
offset: usize,
}
impl<'a> BoxIterator<'a> {
pub fn new(data: &'a [u8]) -> Self {
Self { data, offset: 0 }
}
}
impl<'a> Iterator for BoxIterator<'a> {
type Item = Box<'a>;
fn next(&mut self) -> Option<Self::Item> {
if self.offset + 8 > self.data.len() {
return None;
}
let data = &self.data[self.offset..];
let size_32 = u32::from_be_bytes([data[0], data[1], data[2], data[3]]);
let box_type = FourCC::from_bytes(&data[4..8])?;
let (size, header_size): (u64, usize) = if size_32 == 1 {
if data.len() < 16 {
return None;
}
let ext_size = u64::from_be_bytes([
data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15],
]);
(ext_size, 16)
} else if size_32 == 0 {
((self.data.len() - self.offset) as u64, 8)
} else {
(size_32 as u64, 8)
};
let size_usize = usize::try_from(size).ok()?;
if size_usize < header_size {
return None;
}
let box_end = self.offset.checked_add(size_usize)?;
if box_end > self.data.len() {
return None;
}
let content = &data[header_size..size_usize];
let box_item = Box {
header: BoxHeader {
box_type,
size,
content_offset: self.offset + header_size,
},
content,
};
self.offset = box_end;
Some(box_item)
}
}
#[derive(Debug, Clone)]
pub struct ItemLocation {
pub item_id: u32,
pub construction_method: u8,
pub base_offset: u64,
pub extents: Vec<(u64, u64)>,
}
#[derive(Debug, Clone)]
pub struct ItemInfo {
pub item_id: u32,
pub item_type: FourCC,
pub item_name: String,
pub content_type: String,
pub hidden: bool,
}
#[derive(Debug, Clone, Copy)]
pub struct ContentLightLevelBox {
pub max_content_light_level: u16,
pub max_frame_average_light_level: u16,
}
#[derive(Debug, Clone, Copy)]
pub struct MasteringDisplayBox {
pub primaries_xy: [(u16, u16); 3],
pub white_point_xy: (u16, u16),
pub max_luminance: u32,
pub min_luminance: u32,
}
#[derive(Debug, Clone, Copy)]
pub struct CleanAperture {
pub width_n: u32,
pub width_d: u32,
pub height_n: u32,
pub height_d: u32,
pub horiz_off_n: i32,
pub horiz_off_d: u32,
pub vert_off_n: i32,
pub vert_off_d: u32,
}
#[derive(Debug, Clone, Copy)]
pub struct ImageRotation {
pub angle: u16,
}
#[derive(Debug, Clone, Copy)]
pub struct ImageMirror {
pub axis: u8,
}
#[derive(Debug, Clone, Copy)]
pub struct ImageSpatialExtents {
pub width: u32,
pub height: u32,
}
#[derive(Debug, Clone)]
pub struct HevcDecoderConfig {
pub config_version: u8,
pub general_profile_space: u8,
pub general_tier_flag: bool,
pub general_profile_idc: u8,
pub general_profile_compatibility_flags: u32,
pub general_constraint_indicator_flags: u64,
pub general_level_idc: u8,
pub chroma_format: u8,
pub bit_depth_luma_minus8: u8,
pub bit_depth_chroma_minus8: u8,
pub length_size_minus_one: u8,
pub nal_units: Vec<Vec<u8>>,
}
#[derive(Debug, Clone)]
pub struct Av1DecoderConfig {
pub seq_profile: u8,
pub seq_level_idx_0: u8,
pub high_bitdepth: bool,
pub twelve_bit: bool,
pub monochrome: bool,
pub chroma_subsampling_x: bool,
pub chroma_subsampling_y: bool,
pub config_obus: Vec<u8>,
}
impl Av1DecoderConfig {
pub fn bit_depth(&self) -> u8 {
if !self.high_bitdepth {
8
} else if self.twelve_bit {
12
} else {
10
}
}
pub fn chroma_format(&self) -> u8 {
if self.monochrome {
0
} else if self.chroma_subsampling_x && self.chroma_subsampling_y {
1 } else if self.chroma_subsampling_x {
2 } else {
3 }
}
}
#[derive(Debug, Clone)]
pub struct UncompressedConfig {
pub profile: u32,
pub components: Vec<UncompressedComponent>,
pub sampling_type: u8,
pub interleave_type: u8,
pub block_size: u8,
pub components_little_endian: bool,
pub block_pad_lsb: bool,
pub block_little_endian: bool,
pub block_reversed: bool,
pub pad_unknown: bool,
pub pixel_size: u8,
pub row_align_size: u32,
pub tile_align_size: u32,
pub num_tile_cols_minus_one: u32,
pub num_tile_rows_minus_one: u32,
}
#[derive(Debug, Clone)]
pub struct UncompressedComponent {
pub component_index: u16,
pub component_bit_depth_minus_one: u8,
pub component_format: u8,
pub component_align_size: u8,
}
#[derive(Debug, Clone)]
pub struct CompressionConfig {
pub compression_type: FourCC,
}
#[derive(Debug, Clone)]
pub enum ColorInfo {
IccProfile(Vec<u8>),
Nclx {
color_primaries: u16,
transfer_characteristics: u16,
matrix_coefficients: u16,
full_range: bool,
},
}
#[derive(Debug, Clone, Copy)]
pub enum Transform {
CleanAperture(CleanAperture),
Mirror(ImageMirror),
Rotation(ImageRotation),
}
#[derive(Debug, Clone)]
pub enum ItemProperty {
ImageExtents(ImageSpatialExtents),
HevcConfig(HevcDecoderConfig),
Av1Config(Av1DecoderConfig),
UncompressedConfig(UncompressedConfig),
CompressionConfig(CompressionConfig),
ColorInfo(ColorInfo),
CleanAperture(CleanAperture),
Rotation(ImageRotation),
Mirror(ImageMirror),
AuxiliaryType(AuxiliaryTypeProperty),
ContentLightLevel(ContentLightLevelBox),
MasteringDisplay(MasteringDisplayBox),
Unknown,
}
#[derive(Debug, Clone)]
pub struct AuxiliaryTypeProperty {
pub aux_type: String,
pub subtype_data: Vec<u8>,
}
#[derive(Debug, Clone)]
pub struct PropertyAssociation {
pub item_id: u32,
pub properties: Vec<(u16, bool)>,
}
#[derive(Debug, Clone)]
pub struct ItemReference {
pub reference_type: FourCC,
pub from_item_id: u32,
pub to_item_ids: Vec<u32>,
}