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(
68 "Could not parse WMV2 picture header".into(),
69 ));
70 }
71 Ok(cands.remove(0))
72 }
73
74 fn parse_ref_picture_header(data: &[u8], mb_w: u32, mb_h: u32) -> Option<Self> {
82 const SKIP_TYPE_COL: u32 = 3;
83
84 let mut br = BitReader::new(data);
85
86 let is_p = br.read_bit()?;
88 let frame_type = if is_p {
89 Wmv2FrameType::P
90 } else {
91 Wmv2FrameType::I
92 };
93
94 if frame_type == Wmv2FrameType::I {
95 let _i7 = br.read_bits(7)?;
96 let _ = _i7;
97 }
98
99 let qscale = br.read_bits(5)? as u8;
100 if qscale == 0 {
101 return None;
102 }
103
104 let mut frame_skipped = false;
105
106 if frame_type == Wmv2FrameType::P {
109 if br.peek_bits(1)? == 1 {
110 let mut gb = br.clone();
111 let skip_type = gb.read_bits(2)?;
112 let mut run: i32 = if skip_type == SKIP_TYPE_COL {
113 mb_w as i32
114 } else {
115 mb_h as i32
116 };
117
118 while run > 0 {
119 let block = run.min(25);
120 let bits = gb.read_bits(block as u8)?;
121 if bits != ((1u32 << block) - 1) {
122 break;
123 }
124 run -= block;
125 }
126
127 if run == 0 {
128 frame_skipped = true;
129 }
130 }
131 }
132
133 let header_bits = br.bits_read();
134
135 Some(Wmv2FrameHeader {
136 frame_type,
137 pquant: qscale,
138 frame_skipped,
139 header_bits,
140 })
141 }
142}
143
144impl std::fmt::Display for Wmv2FrameType {
145 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
146 match self {
147 Wmv2FrameType::I => write!(f, "I"),
148 Wmv2FrameType::P => write!(f, "P"),
149 }
150 }
151}