1use crate::bitreader::BitReader;
11use crate::error::{DecoderError, Result};
12
13#[derive(Debug, Clone)]
14pub struct Wmv2Params {
15 pub width: u32,
16 pub height: u32,
17}
18
19impl Wmv2Params {
20 pub fn new(width: u32, height: u32) -> Self {
21 Wmv2Params { width, height }
22 }
23}
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub enum Wmv2FrameType {
27 I,
28 P,
29}
30
31#[derive(Debug, Clone)]
32pub struct Wmv2FrameHeader {
33 pub frame_type: Wmv2FrameType,
34 pub pquant: u8,
36
37 pub frame_skipped: bool,
40
41 pub header_bits: usize,
44}
45
46impl Wmv2FrameHeader {
47 pub fn parse_candidates(data: &[u8], mb_w: u32, mb_h: u32) -> Vec<Self> {
51 let mut out = Vec::new();
52 if data.is_empty() {
53 return out;
54 }
55 if let Some(h) = Self::parse_ref_picture_header(data, mb_w, mb_h) {
56 out.push(h);
57 }
58 out
59 }
60
61 pub fn parse(data: &[u8], mb_w: u32, mb_h: u32) -> Result<Self> {
62 if data.is_empty() {
63 return Err(DecoderError::InvalidData("Empty WMV2 payload".into()));
64 }
65 let mut cands = Self::parse_candidates(data, mb_w, mb_h);
66 if cands.is_empty() {
67 return Err(DecoderError::InvalidData("Could not parse WMV2 picture header".into()));
68 }
69 Ok(cands.remove(0))
70 }
71
72 fn parse_ref_picture_header(data: &[u8], mb_w: u32, mb_h: u32) -> Option<Self> {
80 const SKIP_TYPE_COL: u32 = 3;
81
82 let mut br = BitReader::new(data);
83
84 let is_p = br.read_bit()?;
86 let frame_type = if is_p { Wmv2FrameType::P } else { Wmv2FrameType::I };
87
88 if frame_type == Wmv2FrameType::I {
89 let _i7 = br.read_bits(7)?;
90 let _ = _i7;
91 }
92
93 let qscale = br.read_bits(5)? as u8;
94 if qscale == 0 {
95 return None;
96 }
97
98 let mut frame_skipped = false;
99
100 if frame_type == Wmv2FrameType::P {
103 if br.peek_bits(1)? == 1 {
104 let mut gb = br.clone();
105 let skip_type = gb.read_bits(2)?;
106 let mut run: i32 = if skip_type == SKIP_TYPE_COL {
107 mb_w as i32
108 } else {
109 mb_h as i32
110 };
111
112 while run > 0 {
113 let block = run.min(25);
114 let bits = gb.read_bits(block as u8)?;
115 if bits != ((1u32 << block) - 1) {
116 break;
117 }
118 run -= block;
119 }
120
121 if run == 0 {
122 frame_skipped = true;
123 }
124 }
125 }
126
127 let header_bits = br.bits_read();
128
129 Some(Wmv2FrameHeader {
130 frame_type,
131 pquant: qscale,
132 frame_skipped,
133 header_bits,
134 })
135 }
136}
137
138impl std::fmt::Display for Wmv2FrameType {
139 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
140 match self {
141 Wmv2FrameType::I => write!(f, "I"),
142 Wmv2FrameType::P => write!(f, "P"),
143 }
144 }
145}