use super::bitreader::BitReader;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Mpeg2SeqInfo {
pub width: u32,
pub height: u32,
}
pub fn parse_mpeg2_sequence_header(sample: &[u8]) -> Option<Mpeg2SeqInfo> {
let seq_hdr_start = find_mpeg2_start_code(sample, 0xB3)?;
let hdr_body_off = seq_hdr_start + 4;
if hdr_body_off + 3 > sample.len() {
return None;
}
let b = &sample[hdr_body_off..hdr_body_off + 3];
let mut width = (((b[0] as u32) << 4) | ((b[1] as u32) >> 4)) & 0x0FFF;
let mut height = (((b[1] as u32 & 0x0F) << 8) | (b[2] as u32)) & 0x0FFF;
let search_from = hdr_body_off + 3;
if search_from < sample.len()
&& let Some(ext_start) = find_mpeg2_start_code(&sample[search_from..], 0xB5)
{
let ext_body_off = search_from + ext_start + 4;
if ext_body_off + 3 <= sample.len() {
let mut br = BitReader::new(&sample[ext_body_off..]);
if let Some(id) = br.read_bits(4)
&& id == 1
{
let _profile_level = br.read_bits(8)?;
let _progressive = br.read_bits(1)?;
let _chroma = br.read_bits(2)?;
let h_ext = br.read_bits(2)?;
let v_ext = br.read_bits(2)?;
width |= h_ext << 12;
height |= v_ext << 12;
}
}
}
if width == 0 || height == 0 {
return None;
}
Some(Mpeg2SeqInfo { width, height })
}
fn find_mpeg2_start_code(data: &[u8], target: u8) -> Option<usize> {
let mut i = 0;
while i + 4 <= data.len() {
if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 && data[i + 3] == target {
return Some(i);
}
i += 1;
}
None
}