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 && br.peek_bits(1)? == 1 {
109 let mut gb = br.clone();
110 let skip_type = gb.read_bits(2)?;
111 let mut run: i32 = if skip_type == SKIP_TYPE_COL {
112 mb_w as i32
113 } else {
114 mb_h as i32
115 };
116
117 while run > 0 {
118 let block = run.min(25);
119 let bits = gb.read_bits(block as u8)?;
120 if bits != ((1u32 << block) - 1) {
121 break;
122 }
123 run -= block;
124 }
125
126 if run == 0 {
127 frame_skipped = true;
128 }
129 }
130
131 let header_bits = br.bits_read();
132
133 Some(Wmv2FrameHeader {
134 frame_type,
135 pquant: qscale,
136 frame_skipped,
137 header_bits,
138 })
139 }
140}
141
142impl std::fmt::Display for Wmv2FrameType {
143 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
144 match self {
145 Wmv2FrameType::I => write!(f, "I"),
146 Wmv2FrameType::P => write!(f, "P"),
147 }
148 }
149}