#![forbid(unsafe_code)]
use crate::DecodeError;
use mediaway_sw::h264::BitReader;
use super::ref_table::RefTable;
pub(super) fn parse_frame_size(r: &mut BitReader<'_>) -> Result<(u32, u32), DecodeError> {
let map_err = |_| DecodeError::InvalidInput;
let width = r.read_bits(16).map_err(map_err)?.saturating_add(1);
let height = r.read_bits(16).map_err(map_err)?.saturating_add(1);
Ok((width, height))
}
pub(super) fn parse_render_size(
r: &mut BitReader<'_>,
width: u32,
height: u32,
) -> Result<(u32, u32), DecodeError> {
let map_err = |_| DecodeError::InvalidInput;
let different = r.read_bit().map_err(map_err)? != 0;
if different {
let render_width = r.read_bits(16).map_err(map_err)?.saturating_add(1);
let render_height = r.read_bits(16).map_err(map_err)?.saturating_add(1);
Ok((render_width, render_height))
} else {
Ok((width, height))
}
}
pub(super) fn parse_frame_size_with_refs(
r: &mut BitReader<'_>,
ref_frame_idx: [u8; 3],
ref_table: &RefTable,
) -> Result<(u32, u32), DecodeError> {
let map_err = |_| DecodeError::InvalidInput;
let mut found: Option<(u32, u32)> = None;
for &idx in &ref_frame_idx {
let found_ref = r.read_bit().map_err(map_err)? != 0;
if found_ref {
let size = ref_table
.size(usize::from(idx))
.ok_or(DecodeError::InvalidInput)?;
found = Some(size);
break;
}
}
let (width, height) = match found {
Some(size) => size,
None => parse_frame_size(r)?,
};
parse_render_size(r, width, height)
}
#[cfg(test)]
#[path = "frame_size_tests.rs"]
mod tests;