Skip to main content

wmv_decoder/
vc1.rs

1//! VC-1 / WMV9 syntax parser (Simple/Main and progressive Advanced Profile).
2//!
3//! The bitstream syntax in this module follows FFmpeg's `libavcodec/vc1.c`
4//! and SMPTE 421M.  It is intentionally kept separate from the reconstruction
5//! code in `decoder.rs` so ASF/WMV3 and ASF/WVC1 can share the same parser.
6
7use crate::bitreader::BitReader;
8use crate::error::{DecoderError, Result};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum Profile {
12    Simple,
13    Main,
14    Advanced,
15}
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum FrameType {
19    I,
20    P,
21    B,
22    BI,
23    Skipped,
24}
25
26impl std::fmt::Display for FrameType {
27    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28        match self {
29            FrameType::I => write!(f, "I"),
30            FrameType::P => write!(f, "P"),
31            FrameType::B => write!(f, "B"),
32            FrameType::BI => write!(f, "BI"),
33            FrameType::Skipped => write!(f, "skip"),
34        }
35    }
36}
37
38#[derive(Debug, Clone, Copy, PartialEq, Eq)]
39pub enum QuantizerMode {
40    Implicit = 0,
41    Explicit = 1,
42    NonUniform = 2,
43    Uniform = 3,
44}
45
46#[derive(Debug, Clone, Copy, PartialEq, Eq)]
47pub enum MvMode {
48    OneMvHpelBilin,
49    OneMv,
50    OneMvHpel,
51    IntensityComp,
52    MixedMv,
53}
54
55#[derive(Debug, Clone)]
56pub struct SequenceHeader {
57    pub profile: Profile,
58    pub level: u8,
59    pub max_b_frames: u8,
60    pub frame_rate_num: u32,
61    pub frame_rate_den: u32,
62    pub loop_filter: bool,
63    pub multires: bool,
64    pub fastuvmc: bool,
65    pub extended_mv: bool,
66    pub extended_dmv: bool,
67    pub dquant: u8,
68    pub vstransform: bool,
69    pub overlap: bool,
70    pub syncmarker: bool,
71    pub rangered: bool,
72    pub quantizer_mode: QuantizerMode,
73    pub finterpflag: bool,
74    pub res_x8: bool,
75    pub res_fasttx: bool,
76    pub res_rtm_flag: bool,
77    pub res_sprite: bool,
78    pub postprocflag: bool,
79    pub broadcast: bool,
80    pub interlace: bool,
81    pub tfcntrflag: bool,
82    pub psf: bool,
83    pub panscanflag: bool,
84    pub refdist_flag: bool,
85    pub broken_link: bool,
86    pub closed_entry: bool,
87    pub range_mapy: Option<u8>,
88    pub range_mapuv: Option<u8>,
89    pub hrd_num_leaky_buckets: u8,
90    pub width: u32,
91    pub height: u32,
92    pub display_width: u32,
93    pub display_height: u32,
94}
95
96fn find_vc1_marker(data: &[u8], from: usize) -> Option<usize> {
97    if data.len() < 4 || from >= data.len().saturating_sub(3) {
98        return None;
99    }
100    (from..=data.len() - 4).find(|&i| data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1)
101}
102
103/// Remove VC-1 start-code emulation prevention bytes, matching FFmpeg's
104/// `vc1_unescape_buffer()`: 00 00 03 xx (xx < 4) becomes 00 00 xx.
105pub fn vc1_unescape_buffer(data: &[u8]) -> Vec<u8> {
106    if data.len() < 4 {
107        return data.to_vec();
108    }
109    let mut out = Vec::with_capacity(data.len());
110    let mut i = 0usize;
111    while i < data.len() {
112        if data[i] == 3
113            && i >= 2
114            && data[i - 1] == 0
115            && data[i - 2] == 0
116            && i + 1 < data.len()
117            && data[i + 1] < 4
118        {
119            out.push(data[i + 1]);
120            i += 2;
121        } else {
122            out.push(data[i]);
123            i += 1;
124        }
125    }
126    out
127}
128
129impl SequenceHeader {
130    pub fn parse(data: &[u8]) -> Result<Self> {
131        if data.len() < 4 {
132            return Err(DecoderError::InvalidData(
133                "VC-1 sequence header too short".into(),
134            ));
135        }
136        let mut br = BitReader::new(data);
137        let profile = match need_bits(&mut br, 2, "PROFILE")? {
138            0 => Profile::Simple,
139            1 => Profile::Main,
140            3 => Profile::Advanced,
141            2 => {
142                return Err(DecoderError::Unsupported(
143                    "WMV3 Complex profile is not supported by the native decoder".into(),
144                ));
145            }
146            _ => unreachable!(),
147        };
148        if profile == Profile::Advanced {
149            return Err(DecoderError::Unsupported(
150                "VC-1 Advanced profile is not WMV3 Simple/Main syntax".into(),
151            ));
152        }
153
154        // FFmpeg ff_vc1_decode_sequence_header(), Simple/Main branch.
155        let res_y411 = need_bit(&mut br, "RES_Y411")?;
156        let res_sprite = need_bit(&mut br, "RES_SPRITE")?;
157        if res_y411 {
158            return Err(DecoderError::Unsupported(
159                "VC-1 old interlaced Y411 mode is unsupported".into(),
160            ));
161        }
162
163        let frmrtq_postproc = need_bits(&mut br, 3, "FRMRTQ_POSTPROC")?;
164        let _bitrtq_postproc = need_bits(&mut br, 5, "BITRTQ_POSTPROC")?;
165        let loop_filter = need_bit(&mut br, "LOOPFILTER")?;
166        let res_x8 = need_bit(&mut br, "RES_X8")?;
167        let multires = need_bit(&mut br, "MULTIRES")?;
168        let res_fasttx = need_bit(&mut br, "RES_FASTTX")?;
169        let fastuvmc = need_bit(&mut br, "FASTUVMC")?;
170        let extended_mv = need_bit(&mut br, "EXTENDED_MV")?;
171        let dquant = need_bits(&mut br, 2, "DQUANT")? as u8;
172        let vstransform = need_bit(&mut br, "VSTRANSFORM")?;
173        let res_transtab = need_bit(&mut br, "RES_TRANSTAB")?;
174        if res_transtab {
175            return Err(DecoderError::InvalidData(
176                "VC-1 reserved RES_TRANSTAB bit is set".into(),
177            ));
178        }
179        let overlap = need_bit(&mut br, "OVERLAP")?;
180        let syncmarker = need_bit(&mut br, "SYNCMARKER")?;
181        let rangered = need_bit(&mut br, "RANGERED")?;
182        let max_b_frames = need_bits(&mut br, 3, "MAXBFRAMES")? as u8;
183        let quantizer_mode = match need_bits(&mut br, 2, "QUANTIZER")? {
184            0 => QuantizerMode::Implicit,
185            1 => QuantizerMode::Explicit,
186            2 => QuantizerMode::NonUniform,
187            _ => QuantizerMode::Uniform,
188        };
189        let finterpflag = need_bit(&mut br, "FINTERPFLAG")?;
190
191        // Sprite streams carry additional fields. Ordinary WMV3 movies don't use
192        // this mode, but consume it correctly before rejecting unsupported sprite
193        // coding so the parser never silently desynchronizes.
194
195        let res_rtm_flag = if res_sprite {
196            let _sprite_w = need_bits(&mut br, 11, "SPRITE_WIDTH")?;
197            let _sprite_h = need_bits(&mut br, 11, "SPRITE_HEIGHT")?;
198            let _sprite_rate = need_bits(&mut br, 5, "SPRITE_RATE")?;
199            let _sprite_x8 = need_bit(&mut br, "SPRITE_X8")?;
200            let sprite_dc = need_bit(&mut br, "SPRITE_DC")?;
201            if sprite_dc {
202                return Err(DecoderError::Unsupported(
203                    "VC-1 sprite DC coding is unsupported".into(),
204                ));
205            }
206            let _slice_code = need_bits(&mut br, 3, "SPRITE_SLICE")?;
207            false
208        } else {
209            need_bit(&mut br, "RES_RTM_FLAG")?
210        };
211        if !res_fasttx {
212            let _reserved = need_bits(&mut br, 16, "RES_FASTTX_PAYLOAD")?;
213        }
214
215        // FRMRTQ_POSTPROC is not the coded frame rate. Keep a deterministic
216        // nominal value for legacy callers; ASF timestamps remain authoritative.
217        let (frame_rate_num, frame_rate_den) = match frmrtq_postproc {
218            0..=4 => (30, 1),
219            5 => (24000, 1001),
220            6 => (24, 1),
221            _ => (30, 1),
222        };
223
224        Ok(Self {
225            profile,
226            level: 0,
227            max_b_frames,
228            frame_rate_num,
229            frame_rate_den,
230            loop_filter,
231            multires,
232            fastuvmc,
233            extended_mv,
234            extended_dmv: false,
235            dquant,
236            vstransform,
237            overlap,
238            syncmarker,
239            rangered,
240            quantizer_mode,
241            finterpflag,
242            res_x8,
243            res_fasttx,
244            res_rtm_flag,
245            res_sprite,
246            postprocflag: false,
247            broadcast: false,
248            interlace: false,
249            tfcntrflag: false,
250            psf: false,
251            panscanflag: false,
252            refdist_flag: false,
253            broken_link: false,
254            closed_entry: false,
255            range_mapy: None,
256            range_mapuv: None,
257            hrd_num_leaky_buckets: 0,
258            width: 0,
259            height: 0,
260            display_width: 0,
261            display_height: 0,
262        })
263    }
264
265    /// Parse VC-1 Advanced Profile private data carried by WVC1.
266    ///
267    /// WVC1 ASF stream properties contain VC-1 start-code-delimited sequence
268    /// and entry-point units (the first byte is commonly the private-data
269    /// length). This follows FFmpeg's VC1/WVC1 initialization path: locate the
270    /// 0x0000010f sequence header and 0x0000010e entry point, remove VC-1
271    /// emulation-prevention bytes from each payload, then parse both units.
272    pub fn parse_wvc1(data: &[u8]) -> Result<Self> {
273        let mut seq_payload: Option<Vec<u8>> = None;
274        let mut entry_payload: Option<Vec<u8>> = None;
275
276        let mut pos = 0usize;
277        while let Some(start) = find_vc1_marker(data, pos) {
278            let marker = data[start + 3];
279            let next = find_vc1_marker(data, start + 4).unwrap_or(data.len());
280            if next > start + 4 {
281                let payload = vc1_unescape_buffer(&data[start + 4..next]);
282                match marker {
283                    0x0f => seq_payload = Some(payload),
284                    0x0e => entry_payload = Some(payload),
285                    _ => {}
286                }
287            }
288            if next >= data.len() {
289                break;
290            }
291            pos = next;
292        }
293
294        let seq_payload = seq_payload.ok_or_else(|| {
295            DecoderError::InvalidData("WVC1 extradata has no VC-1 sequence header".into())
296        })?;
297        let entry_payload = entry_payload.ok_or_else(|| {
298            DecoderError::InvalidData("WVC1 extradata has no VC-1 entry point".into())
299        })?;
300
301        let mut seq = Self::parse_advanced_sequence_payload(&seq_payload)?;
302        seq.apply_wvc1_entry_point(&entry_payload)?;
303        Ok(seq)
304    }
305
306    fn parse_advanced_sequence_payload(data: &[u8]) -> Result<Self> {
307        let mut br = BitReader::new(data);
308        let profile = match need_bits(&mut br, 2, "PROFILE")? {
309            3 => Profile::Advanced,
310            0 => Profile::Simple,
311            1 => Profile::Main,
312            2 => {
313                return Err(DecoderError::Unsupported(
314                    "WVC1 Complex profile is unsupported".into(),
315                ));
316            }
317            _ => unreachable!(),
318        };
319        if profile != Profile::Advanced {
320            return Err(DecoderError::InvalidData(format!(
321                "WVC1 sequence header is not Advanced Profile: {profile:?}"
322            )));
323        }
324
325        let level = need_bits(&mut br, 3, "LEVEL")? as u8;
326        if level >= 5 {
327            return Err(DecoderError::InvalidData(format!(
328                "VC-1 Advanced reserved LEVEL {level}"
329            )));
330        }
331        let chroma_format = need_bits(&mut br, 2, "CHROMAFORMAT")?;
332        if chroma_format != 1 {
333            return Err(DecoderError::Unsupported(format!(
334                "VC-1 Advanced chroma format {chroma_format} (only 4:2:0 is supported)"
335            )));
336        }
337
338        let _frmrtq_postproc = need_bits(&mut br, 3, "FRMRTQ_POSTPROC")?;
339        let _bitrtq_postproc = need_bits(&mut br, 5, "BITRTQ_POSTPROC")?;
340        let postprocflag = need_bit(&mut br, "POSTPROCFLAG")?;
341        let width = (need_bits(&mut br, 12, "MAX_CODED_WIDTH")? + 1) << 1;
342        let height = (need_bits(&mut br, 12, "MAX_CODED_HEIGHT")? + 1) << 1;
343        let broadcast = need_bit(&mut br, "PULLDOWN")?;
344        let interlace = need_bit(&mut br, "INTERLACE")?;
345        let tfcntrflag = need_bit(&mut br, "TFCNTRFLAG")?;
346        let finterpflag = need_bit(&mut br, "FINTERPFLAG")?;
347        let _reserved = need_bit(&mut br, "ADV_RESERVED")?;
348        let psf = need_bit(&mut br, "PSF")?;
349        if psf {
350            return Err(DecoderError::Unsupported(
351                "VC-1 Progressive Segmented Frame mode is unsupported".into(),
352            ));
353        }
354
355        let mut display_width = width;
356        let mut display_height = height;
357        let mut frame_rate_num = 0u32;
358        let mut frame_rate_den = 1u32;
359        if need_bit(&mut br, "DISPLAY_EXT")? {
360            display_width = need_bits(&mut br, 14, "DISP_HORIZ_SIZE")? + 1;
361            display_height = need_bits(&mut br, 14, "DISP_VERT_SIZE")? + 1;
362
363            if need_bit(&mut br, "ASPECT_RATIO_FLAG")? {
364                let ar = need_bits(&mut br, 4, "ASPECT_RATIO")?;
365                if ar == 15 {
366                    let _aspect_horiz = need_bits(&mut br, 8, "ASPECT_HORIZ_SIZE")? + 1;
367                    let _aspect_vert = need_bits(&mut br, 8, "ASPECT_VERT_SIZE")? + 1;
368                }
369            }
370
371            if need_bit(&mut br, "FRAMERATE_FLAG")? {
372                if need_bit(&mut br, "FRAMERATEIND")? {
373                    frame_rate_num = need_bits(&mut br, 16, "FRAMERATEEXP")? + 1;
374                    frame_rate_den = 32;
375                } else {
376                    const FPS_NR: [u32; 7] = [24, 25, 30, 50, 60, 48, 72];
377                    const FPS_DR: [u32; 2] = [1000, 1001];
378                    let nr = need_bits(&mut br, 8, "FRAMERATENR")? as usize;
379                    let dr = need_bits(&mut br, 4, "FRAMERATEDR")? as usize;
380                    if (1..=FPS_NR.len()).contains(&nr) && (1..=FPS_DR.len()).contains(&dr) {
381                        frame_rate_num = FPS_NR[nr - 1] * 1000;
382                        frame_rate_den = FPS_DR[dr - 1];
383                    }
384                }
385            }
386
387            if need_bit(&mut br, "COLOR_FORMAT_FLAG")? {
388                let _color_prim = need_bits(&mut br, 8, "COLOR_PRIM")?;
389                let _transfer_char = need_bits(&mut br, 8, "TRANSFER_CHAR")?;
390                let _matrix_coef = need_bits(&mut br, 8, "MATRIX_COEF")?;
391            }
392        }
393
394        let hrd_param_flag = need_bit(&mut br, "HRD_PARAM_FLAG")?;
395        let hrd_num_leaky_buckets = if hrd_param_flag {
396            let buckets = need_bits(&mut br, 5, "HRD_NUM_LEAKY_BUCKETS")? as u8;
397            need_bits(&mut br, 4, "BIT_RATE_EXPONENT")?;
398            need_bits(&mut br, 4, "BUFFER_SIZE_EXPONENT")?;
399            for _ in 0..buckets {
400                need_bits(&mut br, 16, "HRD_RATE")?;
401                need_bits(&mut br, 16, "HRD_BUFFER")?;
402            }
403            buckets
404        } else {
405            0
406        };
407
408        Ok(Self {
409            profile,
410            level,
411            max_b_frames: 7,
412            frame_rate_num,
413            frame_rate_den,
414            loop_filter: false,
415            multires: false,
416            fastuvmc: false,
417            extended_mv: false,
418            extended_dmv: false,
419            dquant: 0,
420            vstransform: false,
421            overlap: false,
422            syncmarker: false,
423            rangered: false,
424            quantizer_mode: QuantizerMode::Implicit,
425            finterpflag,
426            res_x8: false,
427            res_fasttx: false,
428            res_rtm_flag: true,
429            res_sprite: false,
430            postprocflag,
431            broadcast,
432            interlace,
433            tfcntrflag,
434            psf,
435            panscanflag: false,
436            refdist_flag: false,
437            broken_link: false,
438            closed_entry: false,
439            range_mapy: None,
440            range_mapuv: None,
441            hrd_num_leaky_buckets,
442            width,
443            height,
444            display_width,
445            display_height,
446        })
447    }
448
449    pub fn apply_wvc1_entry_point(&mut self, data: &[u8]) -> Result<()> {
450        let mut br = BitReader::new(data);
451        self.broken_link = need_bit(&mut br, "BROKEN_LINK")?;
452        self.closed_entry = need_bit(&mut br, "CLOSED_ENTRY")?;
453        self.panscanflag = need_bit(&mut br, "PANSCAN_FLAG")?;
454        self.refdist_flag = need_bit(&mut br, "REFDIST_FLAG")?;
455        self.loop_filter = need_bit(&mut br, "LOOPFILTER")?;
456        self.fastuvmc = need_bit(&mut br, "FASTUVMC")?;
457        self.extended_mv = need_bit(&mut br, "EXTENDED_MV")?;
458        self.dquant = need_bits(&mut br, 2, "DQUANT")? as u8;
459        self.vstransform = need_bit(&mut br, "VSTRANSFORM")?;
460        self.overlap = need_bit(&mut br, "OVERLAP")?;
461        self.quantizer_mode = match need_bits(&mut br, 2, "QUANTIZER")? {
462            0 => QuantizerMode::Implicit,
463            1 => QuantizerMode::Explicit,
464            2 => QuantizerMode::NonUniform,
465            _ => QuantizerMode::Uniform,
466        };
467
468        for _ in 0..self.hrd_num_leaky_buckets {
469            need_bits(&mut br, 8, "HRD_FULL")?;
470        }
471
472        if need_bit(&mut br, "CODED_SIZE_FLAG")? {
473            self.width = (need_bits(&mut br, 12, "CODED_WIDTH")? + 1) << 1;
474            self.height = (need_bits(&mut br, 12, "CODED_HEIGHT")? + 1) << 1;
475        }
476        self.extended_dmv = self.extended_mv && need_bit(&mut br, "EXTENDED_DMV")?;
477        self.range_mapy = if need_bit(&mut br, "RANGE_MAPY_FLAG")? {
478            Some(need_bits(&mut br, 3, "RANGE_MAPY")? as u8)
479        } else {
480            None
481        };
482        self.range_mapuv = if need_bit(&mut br, "RANGE_MAPUV_FLAG")? {
483            Some(need_bits(&mut br, 3, "RANGE_MAPUV")? as u8)
484        } else {
485            None
486        };
487        Ok(())
488    }
489
490    #[inline]
491    pub fn uses_transposed_scans(&self) -> bool {
492        self.profile == Profile::Advanced || self.res_fasttx
493    }
494}
495
496#[derive(Debug, Clone, Copy, PartialEq, Eq)]
497enum BitplaneMode {
498    Raw,
499    Norm2,
500    Diff2,
501    Norm6,
502    Diff6,
503    RowSkip,
504    ColSkip,
505}
506
507#[derive(Debug, Clone)]
508pub struct Bitplane {
509    pub data: Vec<u8>,
510    pub is_raw: bool,
511}
512
513const IMODE_CODES: [u16; 7] = [0, 2, 1, 3, 1, 2, 3];
514const IMODE_BITS: [u8; 7] = [4, 2, 3, 2, 4, 3, 3];
515const NORM2_CODES: [u16; 4] = [0, 4, 5, 3];
516const NORM2_BITS: [u8; 4] = [1, 3, 3, 2];
517const NORM6_CODES: [u16; 64] = [
518    0x001, 0x002, 0x003, 0x000, 0x004, 0x001, 0x002, 0x047, 0x005, 0x003, 0x004, 0x04B, 0x005,
519    0x04D, 0x04E, 0x30E, 0x006, 0x006, 0x007, 0x053, 0x008, 0x055, 0x056, 0x30D, 0x009, 0x059,
520    0x05A, 0x30C, 0x05C, 0x30B, 0x30A, 0x037, 0x007, 0x00A, 0x00B, 0x043, 0x00C, 0x045, 0x046,
521    0x309, 0x00D, 0x049, 0x04A, 0x308, 0x04C, 0x307, 0x306, 0x036, 0x00E, 0x051, 0x052, 0x305,
522    0x054, 0x304, 0x303, 0x035, 0x058, 0x302, 0x301, 0x034, 0x300, 0x033, 0x032, 0x007,
523];
524const NORM6_BITS: [u8; 64] = [
525    1, 4, 4, 8, 4, 8, 8, 10, 4, 8, 8, 10, 8, 10, 10, 13, 4, 8, 8, 10, 8, 10, 10, 13, 8, 10, 10, 13,
526    10, 13, 13, 9, 4, 8, 8, 10, 8, 10, 10, 13, 8, 10, 10, 13, 10, 13, 13, 9, 8, 10, 10, 13, 10, 13,
527    13, 9, 10, 13, 13, 9, 13, 9, 9, 6,
528];
529
530fn decode_prefix(br: &mut BitReader<'_>, codes: &[u16], bits: &[u8]) -> Option<usize> {
531    let max_len = bits.iter().copied().max()?;
532    for len in 1..=max_len {
533        let Some(peek) = br.peek_bits(len) else {
534            continue;
535        };
536        for (sym, (&code, &nb)) in codes.iter().zip(bits.iter()).enumerate() {
537            if nb == len && peek == code as u32 {
538                br.skip_bits(len);
539                return Some(sym);
540            }
541        }
542    }
543    None
544}
545
546fn decode_rowskip(
547    br: &mut BitReader<'_>,
548    data: &mut [u8],
549    x0: usize,
550    y0: usize,
551    width: usize,
552    height: usize,
553    stride: usize,
554) -> Option<()> {
555    for y in 0..height {
556        let row = (y0 + y) * stride + x0;
557        if br.read_bit()? {
558            for x in 0..width {
559                data[row + x] = br.read_bit()? as u8;
560            }
561        } else {
562            data[row..row + width].fill(0);
563        }
564    }
565    Some(())
566}
567
568fn decode_colskip(
569    br: &mut BitReader<'_>,
570    data: &mut [u8],
571    x0: usize,
572    y0: usize,
573    width: usize,
574    height: usize,
575    stride: usize,
576) -> Option<()> {
577    for x in 0..width {
578        if br.read_bit()? {
579            for y in 0..height {
580                data[(y0 + y) * stride + x0 + x] = br.read_bit()? as u8;
581            }
582        } else {
583            for y in 0..height {
584                data[(y0 + y) * stride + x0 + x] = 0;
585            }
586        }
587    }
588    Some(())
589}
590
591impl Bitplane {
592    /// Decode one VC-1 bitplane exactly as FFmpeg `bitplane_decoding()`.
593    /// RAW mode intentionally consumes no macroblock bits here; those bits are
594    /// interleaved in the macroblock layer and are consumed by `decoder.rs`.
595    pub fn decode(br: &mut BitReader<'_>, mb_w: usize, mb_h: usize) -> Option<Self> {
596        let mut data = vec![0u8; mb_w.checked_mul(mb_h)?];
597        let invert = br.read_bit()? as u8;
598        let imode = decode_prefix(br, &IMODE_CODES, &IMODE_BITS)?;
599        let mode = match imode {
600            0 => BitplaneMode::Raw,
601            1 => BitplaneMode::Norm2,
602            2 => BitplaneMode::Diff2,
603            3 => BitplaneMode::Norm6,
604            4 => BitplaneMode::Diff6,
605            5 => BitplaneMode::RowSkip,
606            6 => BitplaneMode::ColSkip,
607            _ => return None,
608        };
609
610        if mode == BitplaneMode::Raw {
611            return Some(Self { data, is_raw: true });
612        }
613
614        match mode {
615            BitplaneMode::Norm2 | BitplaneMode::Diff2 => {
616                let n = mb_w * mb_h;
617                let mut pos = 0usize;
618                if n & 1 != 0 {
619                    data[0] = br.read_bit()? as u8;
620                    pos = 1;
621                }
622                while pos + 1 < n {
623                    let code = decode_prefix(br, &NORM2_CODES, &NORM2_BITS)? as u8;
624                    data[pos] = code & 1;
625                    data[pos + 1] = code >> 1;
626                    pos += 2;
627                }
628            }
629            BitplaneMode::Norm6 | BitplaneMode::Diff6 => {
630                // FFmpeg uses 2x3 tiles when height is a multiple of 3 and
631                // width is not, otherwise 3x2 tiles.
632                if mb_h.is_multiple_of(3) && !mb_w.is_multiple_of(3) {
633                    for y in (0..mb_h).step_by(3) {
634                        for x in ((mb_w & 1)..mb_w).step_by(2) {
635                            let code = decode_prefix(br, &NORM6_CODES, &NORM6_BITS)? as u8;
636                            data[y * mb_w + x] = code & 1;
637                            data[y * mb_w + x + 1] = (code >> 1) & 1;
638                            data[(y + 1) * mb_w + x] = (code >> 2) & 1;
639                            data[(y + 1) * mb_w + x + 1] = (code >> 3) & 1;
640                            data[(y + 2) * mb_w + x] = (code >> 4) & 1;
641                            data[(y + 2) * mb_w + x + 1] = (code >> 5) & 1;
642                        }
643                    }
644                    if mb_w & 1 != 0 {
645                        decode_colskip(br, &mut data, 0, 0, 1, mb_h, mb_w)?;
646                    }
647                } else {
648                    let y0 = mb_h & 1;
649                    for y in (y0..mb_h).step_by(2) {
650                        for x in (mb_w % 3..mb_w).step_by(3) {
651                            let code = decode_prefix(br, &NORM6_CODES, &NORM6_BITS)? as u8;
652                            data[y * mb_w + x] = code & 1;
653                            data[y * mb_w + x + 1] = (code >> 1) & 1;
654                            data[y * mb_w + x + 2] = (code >> 2) & 1;
655                            data[(y + 1) * mb_w + x] = (code >> 3) & 1;
656                            data[(y + 1) * mb_w + x + 1] = (code >> 4) & 1;
657                            data[(y + 1) * mb_w + x + 2] = (code >> 5) & 1;
658                        }
659                    }
660                    let x = mb_w % 3;
661                    if x != 0 {
662                        decode_colskip(br, &mut data, 0, 0, x, mb_h, mb_w)?;
663                    }
664                    if mb_h & 1 != 0 && mb_w > x {
665                        decode_rowskip(br, &mut data, x, 0, mb_w - x, 1, mb_w)?;
666                    }
667                }
668            }
669            BitplaneMode::RowSkip => {
670                decode_rowskip(br, &mut data, 0, 0, mb_w, mb_h, mb_w)?;
671            }
672            BitplaneMode::ColSkip => {
673                decode_colskip(br, &mut data, 0, 0, mb_w, mb_h, mb_w)?;
674            }
675            BitplaneMode::Raw => unreachable!(),
676        }
677
678        if matches!(mode, BitplaneMode::Diff2 | BitplaneMode::Diff6) {
679            if !data.is_empty() {
680                data[0] ^= invert;
681                for x in 1..mb_w {
682                    data[x] ^= data[x - 1];
683                }
684                for y in 1..mb_h {
685                    let row = y * mb_w;
686                    let prev = row - mb_w;
687                    data[row] ^= data[prev];
688                    for x in 1..mb_w {
689                        let left = data[row + x - 1];
690                        let above = data[prev + x];
691                        if left != above {
692                            data[row + x] ^= invert;
693                        } else {
694                            data[row + x] ^= left;
695                        }
696                    }
697                }
698            }
699        } else if invert != 0 {
700            for v in &mut data {
701                *v = if *v == 0 { 1 } else { 0 };
702            }
703        }
704
705        Some(Self {
706            data,
707            is_raw: false,
708        })
709    }
710}
711
712#[derive(Debug, Clone, Copy, Default)]
713pub struct DQuantInfo {
714    pub enabled: bool,
715    pub profile: u8,
716    pub edge: u8,
717    pub bi_level: bool,
718    pub alt_pquant: u8,
719}
720
721#[derive(Debug, Clone)]
722pub struct PictureHeader {
723    pub frame_type: FrameType,
724    pub pqindex: u8,
725    pub pquant: u8,
726    pub halfqp: bool,
727    /// FFmpeg's pquantizer: true = uniform quantizer reconstruction.
728    pub pqual_mode: u8,
729    pub mvrange: u8,
730    pub rptfrm: u8,
731    pub pts_ms: u32,
732    pub rangeredfrm: bool,
733    pub rnd: Option<bool>,
734    pub header_bits: usize,
735    pub acpred_plane: Option<Vec<u8>>,
736    pub acpred_raw: bool,
737    pub condover: u8,
738    pub overflags_plane: Option<Vec<u8>>,
739    pub overflags_raw: bool,
740    pub skipmb_plane: Option<Vec<u8>>,
741    pub skipmb_raw: bool,
742    pub directmb_plane: Option<Vec<u8>>,
743    pub directmb_raw: bool,
744    pub mvtypemb_plane: Option<Vec<u8>>,
745    pub mvtypemb_raw: bool,
746    pub bfrac_num: i32,
747    pub bfrac_den: i32,
748    pub mv_mode: MvMode,
749    pub mv_mode2: MvMode,
750    pub lumscale: u8,
751    pub lumshift: u8,
752    pub mvtab: u8,
753    pub cbptab: u8,
754    pub ttmbf: bool,
755    pub ttfrm: u8,
756    pub transacfrm: u8,
757    pub transacfrm2: u8,
758    pub dctab: bool,
759    pub dquant: DQuantInfo,
760}
761
762const PQUANT_IMPLICIT: [u8; 32] = [
763    0, 1, 2, 3, 4, 5, 6, 7, 8, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
764    24, 25, 27, 29, 31,
765];
766const BFRAC: [(i32, i32); 23] = [
767    (1, 2),
768    (1, 3),
769    (2, 3),
770    (1, 4),
771    (3, 4),
772    (1, 5),
773    (2, 5),
774    (3, 5),
775    (4, 5),
776    (1, 6),
777    (5, 6),
778    (1, 7),
779    (2, 7),
780    (3, 7),
781    (4, 7),
782    (5, 7),
783    (6, 7),
784    (1, 8),
785    (3, 8),
786    (5, 8),
787    (7, 8),
788    (0, 0),
789    (0, 1),
790];
791const MV_PMODE: [[MvMode; 5]; 2] = [
792    [
793        MvMode::OneMvHpelBilin,
794        MvMode::OneMv,
795        MvMode::OneMvHpel,
796        MvMode::IntensityComp,
797        MvMode::MixedMv,
798    ],
799    [
800        MvMode::OneMv,
801        MvMode::MixedMv,
802        MvMode::OneMvHpel,
803        MvMode::IntensityComp,
804        MvMode::OneMvHpelBilin,
805    ],
806];
807const MV_PMODE2: [[MvMode; 4]; 2] = [
808    [
809        MvMode::OneMvHpelBilin,
810        MvMode::OneMv,
811        MvMode::OneMvHpel,
812        MvMode::MixedMv,
813    ],
814    [
815        MvMode::OneMv,
816        MvMode::MixedMv,
817        MvMode::OneMvHpel,
818        MvMode::OneMvHpelBilin,
819    ],
820];
821
822impl PictureHeader {
823    pub fn parse(
824        data: &[u8],
825        seq: &SequenceHeader,
826        pts_ms: u32,
827        mb_w: usize,
828        mb_h: usize,
829    ) -> Result<Self> {
830        if seq.profile == Profile::Advanced {
831            if seq.interlace {
832                return Err(DecoderError::Unsupported(
833                    "VC-1 Advanced interlaced pictures are not yet supported by the native decoder"
834                        .into(),
835                ));
836            }
837            return Self::parse_advanced_progressive(data, seq, pts_ms, mb_w, mb_h);
838        }
839
840        let mut br = BitReader::new(data);
841
842        if seq.finterpflag {
843            let _interpfrm = need_bit(&mut br, "INTERPFRM")?;
844        }
845        need_bits(&mut br, 2, "FRMCNT")?;
846        let rangeredfrm = seq.rangered && need_bit(&mut br, "RANGEREDFRM")?;
847
848        let mut frame_type = if need_bit(&mut br, "PTYPE")? {
849            FrameType::P
850        } else if seq.max_b_frames > 0 && !need_bit(&mut br, "PTYPE_B")? {
851            FrameType::B
852        } else {
853            FrameType::I
854        };
855
856        let mut bfrac_num = 1;
857        let mut bfrac_den = 2;
858        if frame_type == FrameType::B {
859            let mut idx = need_bits(&mut br, 3, "BFRACTION")? as usize;
860            if idx == 7 {
861                idx = 7 + need_bits(&mut br, 4, "BFRACTION_EXT")? as usize;
862            }
863            if idx >= BFRAC.len() || idx == 21 {
864                return Err(DecoderError::InvalidData("invalid VC-1 BFRACTION".into()));
865            }
866            let frac = BFRAC[idx];
867            if idx == 22 {
868                frame_type = FrameType::BI;
869                bfrac_num = 0;
870                bfrac_den = 1;
871            } else {
872                bfrac_num = frac.0;
873                bfrac_den = frac.1;
874            }
875        }
876
877        if matches!(frame_type, FrameType::I | FrameType::BI) {
878            need_bits(&mut br, 7, "BF")?;
879        }
880
881        let pqindex = need_bits(&mut br, 5, "PQINDEX")? as u8;
882        if pqindex == 0 {
883            return Err(DecoderError::InvalidData("VC-1 PQINDEX is zero".into()));
884        }
885        let pquant = match seq.quantizer_mode {
886            QuantizerMode::Implicit => PQUANT_IMPLICIT[pqindex as usize],
887            _ => pqindex,
888        };
889        let mut halfqp = if pqindex < 9 {
890            need_bit(&mut br, "HALFQP")?
891        } else {
892            false
893        };
894        let pquantizer = match seq.quantizer_mode {
895            QuantizerMode::Implicit => pqindex < 9,
896            QuantizerMode::NonUniform => false,
897            QuantizerMode::Explicit => need_bit(&mut br, "PQUANTIZER")?,
898            QuantizerMode::Uniform => true,
899        };
900
901        let mvrange = if seq.extended_mv {
902            read_unary(&mut br, false, 3, "MVRANGE")?
903        } else {
904            0
905        };
906        if seq.multires && frame_type != FrameType::B {
907            let _respic = need_bits(&mut br, 2, "RESPIC")?;
908        }
909        if seq.res_x8 && matches!(frame_type, FrameType::I | FrameType::BI) {
910            let x8_type = need_bit(&mut br, "X8_TYPE")?;
911            if x8_type {
912                return Err(DecoderError::Unsupported("VC-1 X8 intra coding".into()));
913            }
914        }
915
916        let mut skipmb_plane = None;
917        let mut skipmb_raw = false;
918        let mut directmb_plane = None;
919        let mut directmb_raw = false;
920        let mut mvtypemb_plane = None;
921        let mut mvtypemb_raw = false;
922        let mut mv_mode = MvMode::OneMv;
923        let mut mv_mode2 = MvMode::OneMv;
924        let mut lumscale = 32u8;
925        let mut lumshift = 0u8;
926        let mut mvtab = 0u8;
927        let mut cbptab = 0u8;
928        let mut ttmbf = true;
929        let mut ttfrm = 0u8;
930        let mut dq = DQuantInfo::default();
931
932        match frame_type {
933            FrameType::P => {
934                let lowquant = if pquant > 12 { 0usize } else { 1usize };
935                let mode_idx = read_unary(&mut br, true, 4, "MVMODE")? as usize;
936                mv_mode = MV_PMODE[lowquant][mode_idx.min(4)];
937                if mv_mode == MvMode::IntensityComp {
938                    let mode2_idx = read_unary(&mut br, true, 3, "MVMODE2")? as usize;
939                    mv_mode2 = MV_PMODE2[lowquant][mode2_idx.min(3)];
940                    lumscale = need_bits(&mut br, 6, "LUMSCALE")? as u8;
941                    lumshift = need_bits(&mut br, 6, "LUMSHIFT")? as u8;
942                } else {
943                    mv_mode2 = mv_mode;
944                }
945
946                if mv_mode == MvMode::MixedMv
947                    || (mv_mode == MvMode::IntensityComp && mv_mode2 == MvMode::MixedMv)
948                {
949                    let bp = Bitplane::decode(&mut br, mb_w, mb_h).ok_or_else(|| {
950                        DecoderError::InvalidData("invalid VC-1 MVTYPE bitplane".into())
951                    })?;
952                    mvtypemb_raw = bp.is_raw;
953                    if !bp.is_raw {
954                        mvtypemb_plane = Some(bp.data);
955                    }
956                }
957                let bp = Bitplane::decode(&mut br, mb_w, mb_h).ok_or_else(|| {
958                    DecoderError::InvalidData("invalid VC-1 SKIPMB bitplane".into())
959                })?;
960                skipmb_raw = bp.is_raw;
961                if !bp.is_raw {
962                    skipmb_plane = Some(bp.data);
963                }
964
965                mvtab = need_bits(&mut br, 2, "MVTAB")? as u8;
966                cbptab = need_bits(&mut br, 2, "CBPTAB")? as u8;
967                if seq.dquant != 0 {
968                    dq = parse_dquant(&mut br, seq.dquant, pquant)?;
969                    // VC-1 ยง8.1.1.8 / FFmpeg vop_dquant_decoding(): ALL_MBS with
970                    // DQBILEVEL=0 disables HALFQP for the picture.
971                    if dq.enabled && dq.profile == 3 && !dq.bi_level {
972                        halfqp = false;
973                    }
974                }
975                if seq.vstransform {
976                    ttmbf = need_bit(&mut br, "TTMBF")?;
977                    ttfrm = if ttmbf {
978                        [0u8, 3, 6, 7][need_bits(&mut br, 2, "TTFRM")? as usize]
979                    } else {
980                        0
981                    };
982                }
983            }
984            FrameType::B => {
985                mv_mode = if need_bit(&mut br, "MVMODE_B")? {
986                    MvMode::OneMv
987                } else {
988                    MvMode::OneMvHpelBilin
989                };
990                mv_mode2 = mv_mode;
991                let direct = Bitplane::decode(&mut br, mb_w, mb_h).ok_or_else(|| {
992                    DecoderError::InvalidData("invalid VC-1 DIRECTMB bitplane".into())
993                })?;
994                directmb_raw = direct.is_raw;
995                if !direct.is_raw {
996                    directmb_plane = Some(direct.data);
997                }
998                let skip = Bitplane::decode(&mut br, mb_w, mb_h).ok_or_else(|| {
999                    DecoderError::InvalidData("invalid VC-1 SKIPMB bitplane".into())
1000                })?;
1001                skipmb_raw = skip.is_raw;
1002                if !skip.is_raw {
1003                    skipmb_plane = Some(skip.data);
1004                }
1005                mvtab = need_bits(&mut br, 2, "MVTAB")? as u8;
1006                cbptab = need_bits(&mut br, 2, "CBPTAB")? as u8;
1007                if seq.dquant != 0 {
1008                    dq = parse_dquant(&mut br, seq.dquant, pquant)?;
1009                    // VC-1 ยง8.1.1.8 / FFmpeg vop_dquant_decoding(): ALL_MBS with
1010                    // DQBILEVEL=0 disables HALFQP for the picture.
1011                    if dq.enabled && dq.profile == 3 && !dq.bi_level {
1012                        halfqp = false;
1013                    }
1014                }
1015                if seq.vstransform {
1016                    ttmbf = need_bit(&mut br, "TTMBF")?;
1017                    ttfrm = if ttmbf {
1018                        [0u8, 3, 6, 7][need_bits(&mut br, 2, "TTFRM")? as usize]
1019                    } else {
1020                        0
1021                    };
1022                }
1023            }
1024            FrameType::I | FrameType::BI | FrameType::Skipped => {}
1025        }
1026
1027        // AC/DC table syntax. decode012 produces 0,1,2.
1028        let transacfrm = decode012(&mut br, "TRANSACFRM")?;
1029        let transacfrm2 = if matches!(frame_type, FrameType::I | FrameType::BI) {
1030            decode012(&mut br, "TRANSACFRM2")?
1031        } else {
1032            transacfrm
1033        };
1034        let dctab = need_bit(&mut br, "DCTAB")?;
1035
1036        Ok(Self {
1037            frame_type,
1038            pqindex,
1039            pquant,
1040            halfqp,
1041            pqual_mode: pquantizer as u8,
1042            mvrange,
1043            rptfrm: 0,
1044            pts_ms,
1045            rangeredfrm,
1046            rnd: None,
1047            header_bits: br.bits_read(),
1048            acpred_plane: None,
1049            acpred_raw: false,
1050            condover: 0,
1051            overflags_plane: None,
1052            overflags_raw: false,
1053            skipmb_plane,
1054            skipmb_raw,
1055            directmb_plane,
1056            directmb_raw,
1057            mvtypemb_plane,
1058            mvtypemb_raw,
1059            bfrac_num,
1060            bfrac_den,
1061            mv_mode,
1062            mv_mode2,
1063            lumscale,
1064            lumshift,
1065            mvtab,
1066            cbptab,
1067            ttmbf,
1068            ttfrm,
1069            transacfrm,
1070            transacfrm2,
1071            dctab,
1072            dquant: dq,
1073        })
1074    }
1075
1076    fn parse_advanced_progressive(
1077        data: &[u8],
1078        seq: &SequenceHeader,
1079        pts_ms: u32,
1080        mb_w: usize,
1081        mb_h: usize,
1082    ) -> Result<Self> {
1083        let mut br = BitReader::new(data);
1084
1085        let ptype = read_unary(&mut br, false, 4, "PTYPE")?;
1086        let mut frame_type = match ptype {
1087            0 => FrameType::P,
1088            1 => FrameType::B,
1089            2 => FrameType::I,
1090            3 => FrameType::BI,
1091            4 => FrameType::Skipped,
1092            _ => unreachable!(),
1093        };
1094
1095        if seq.tfcntrflag {
1096            need_bits(&mut br, 8, "TFCNTR")?;
1097        }
1098        let rptfrm = if seq.broadcast {
1099            need_bits(&mut br, 2, "RPTFRM")? as u8
1100        } else {
1101            0
1102        };
1103        if seq.panscanflag {
1104            return Err(DecoderError::Unsupported(
1105                "VC-1 Advanced pan-scan picture syntax is unsupported".into(),
1106            ));
1107        }
1108
1109        if frame_type == FrameType::Skipped {
1110            return Ok(Self {
1111                frame_type,
1112                pqindex: 1,
1113                pquant: 1,
1114                halfqp: false,
1115                pqual_mode: 1,
1116                mvrange: 0,
1117                rptfrm,
1118                pts_ms,
1119                rangeredfrm: false,
1120                rnd: None,
1121                header_bits: br.bits_read(),
1122                acpred_plane: None,
1123                acpred_raw: false,
1124                condover: 0,
1125                overflags_plane: None,
1126                overflags_raw: false,
1127                skipmb_plane: None,
1128                skipmb_raw: false,
1129                directmb_plane: None,
1130                directmb_raw: false,
1131                mvtypemb_plane: None,
1132                mvtypemb_raw: false,
1133                bfrac_num: 1,
1134                bfrac_den: 2,
1135                mv_mode: MvMode::OneMv,
1136                mv_mode2: MvMode::OneMv,
1137                lumscale: 32,
1138                lumshift: 0,
1139                mvtab: 0,
1140                cbptab: 0,
1141                ttmbf: true,
1142                ttfrm: 0,
1143                transacfrm: 0,
1144                transacfrm2: 0,
1145                dctab: false,
1146                dquant: DQuantInfo::default(),
1147            });
1148        }
1149
1150        let rnd = need_bit(&mut br, "RNDCTRL")?;
1151        if seq.finterpflag {
1152            need_bit(&mut br, "INTERPFRM")?;
1153        }
1154
1155        let mut bfrac_num = 1;
1156        let mut bfrac_den = 2;
1157        if frame_type == FrameType::B {
1158            let mut idx = need_bits(&mut br, 3, "BFRACTION")? as usize;
1159            if idx == 7 {
1160                idx = 7 + need_bits(&mut br, 4, "BFRACTION_EXT")? as usize;
1161            }
1162            if idx >= BFRAC.len() || idx == 21 {
1163                return Err(DecoderError::InvalidData("invalid VC-1 BFRACTION".into()));
1164            }
1165            if idx == 22 {
1166                frame_type = FrameType::BI;
1167                bfrac_num = 0;
1168                bfrac_den = 1;
1169            } else {
1170                (bfrac_num, bfrac_den) = BFRAC[idx];
1171            }
1172        }
1173
1174        let pqindex = need_bits(&mut br, 5, "PQINDEX")? as u8;
1175        if pqindex == 0 {
1176            return Err(DecoderError::InvalidData("VC-1 PQINDEX is zero".into()));
1177        }
1178        let pquant = match seq.quantizer_mode {
1179            QuantizerMode::Implicit => PQUANT_IMPLICIT[pqindex as usize],
1180            _ => pqindex,
1181        };
1182        let mut halfqp = if pqindex < 9 {
1183            need_bit(&mut br, "HALFQP")?
1184        } else {
1185            false
1186        };
1187        let pquantizer = match seq.quantizer_mode {
1188            QuantizerMode::Implicit => pqindex < 9,
1189            QuantizerMode::NonUniform => false,
1190            QuantizerMode::Explicit => need_bit(&mut br, "PQUANTIZER")?,
1191            QuantizerMode::Uniform => true,
1192        };
1193        if seq.postprocflag {
1194            need_bits(&mut br, 2, "POSTPROC")?;
1195        }
1196
1197        let mut acpred_plane = None;
1198        let mut acpred_raw = false;
1199        let mut condover = 0u8;
1200        let mut overflags_plane = None;
1201        let mut overflags_raw = false;
1202        let mut skipmb_plane = None;
1203        let mut skipmb_raw = false;
1204        let mut directmb_plane = None;
1205        let mut directmb_raw = false;
1206        let mut mvtypemb_plane = None;
1207        let mut mvtypemb_raw = false;
1208        let mut mv_mode = MvMode::OneMv;
1209        let mut mv_mode2 = MvMode::OneMv;
1210        let mut lumscale = 32u8;
1211        let mut lumshift = 0u8;
1212        let mut mvtab = 0u8;
1213        let mut cbptab = 0u8;
1214        let mut mvrange = 0u8;
1215        let mut ttmbf = true;
1216        let mut ttfrm = 0u8;
1217        let mut dq = DQuantInfo::default();
1218
1219        match frame_type {
1220            FrameType::I | FrameType::BI => {
1221                let bp = Bitplane::decode(&mut br, mb_w, mb_h).ok_or_else(|| {
1222                    DecoderError::InvalidData("invalid VC-1 Advanced ACPRED bitplane".into())
1223                })?;
1224                acpred_raw = bp.is_raw;
1225                if !bp.is_raw {
1226                    acpred_plane = Some(bp.data);
1227                }
1228
1229                if seq.overlap && pquant <= 8 {
1230                    condover = decode012(&mut br, "CONDOVER")?;
1231                    if condover == 2 {
1232                        let over = Bitplane::decode(&mut br, mb_w, mb_h).ok_or_else(|| {
1233                            DecoderError::InvalidData(
1234                                "invalid VC-1 Advanced OVERFLAGS bitplane".into(),
1235                            )
1236                        })?;
1237                        overflags_raw = over.is_raw;
1238                        if !over.is_raw {
1239                            overflags_plane = Some(over.data);
1240                        }
1241                    }
1242                }
1243            }
1244            FrameType::P => {
1245                if seq.extended_mv {
1246                    mvrange = read_unary(&mut br, false, 3, "MVRANGE")?;
1247                }
1248                let lowquant = if pquant > 12 { 0usize } else { 1usize };
1249                let mode_idx = read_unary(&mut br, true, 4, "MVMODE")? as usize;
1250                mv_mode = MV_PMODE[lowquant][mode_idx.min(4)];
1251                if mv_mode == MvMode::IntensityComp {
1252                    let mode2_idx = read_unary(&mut br, true, 3, "MVMODE2")? as usize;
1253                    mv_mode2 = MV_PMODE2[lowquant][mode2_idx.min(3)];
1254                    lumscale = need_bits(&mut br, 6, "LUMSCALE")? as u8;
1255                    lumshift = need_bits(&mut br, 6, "LUMSHIFT")? as u8;
1256                } else {
1257                    mv_mode2 = mv_mode;
1258                }
1259
1260                if mv_mode == MvMode::MixedMv
1261                    || (mv_mode == MvMode::IntensityComp && mv_mode2 == MvMode::MixedMv)
1262                {
1263                    let bp = Bitplane::decode(&mut br, mb_w, mb_h).ok_or_else(|| {
1264                        DecoderError::InvalidData("invalid VC-1 MVTYPE bitplane".into())
1265                    })?;
1266                    mvtypemb_raw = bp.is_raw;
1267                    if !bp.is_raw {
1268                        mvtypemb_plane = Some(bp.data);
1269                    }
1270                }
1271                let skip = Bitplane::decode(&mut br, mb_w, mb_h).ok_or_else(|| {
1272                    DecoderError::InvalidData("invalid VC-1 SKIPMB bitplane".into())
1273                })?;
1274                skipmb_raw = skip.is_raw;
1275                if !skip.is_raw {
1276                    skipmb_plane = Some(skip.data);
1277                }
1278                mvtab = need_bits(&mut br, 2, "MVTAB")? as u8;
1279                cbptab = need_bits(&mut br, 2, "CBPTAB")? as u8;
1280                if seq.dquant != 0 {
1281                    dq = parse_dquant(&mut br, seq.dquant, pquant)?;
1282                    if dq.enabled && dq.profile == 3 && !dq.bi_level {
1283                        halfqp = false;
1284                    }
1285                }
1286                if seq.vstransform {
1287                    ttmbf = need_bit(&mut br, "TTMBF")?;
1288                    ttfrm = if ttmbf {
1289                        [0u8, 3, 6, 7][need_bits(&mut br, 2, "TTFRM")? as usize]
1290                    } else {
1291                        0
1292                    };
1293                }
1294            }
1295            FrameType::B => {
1296                if seq.extended_mv {
1297                    mvrange = read_unary(&mut br, false, 3, "MVRANGE")?;
1298                }
1299                mv_mode = if need_bit(&mut br, "MVMODE_B")? {
1300                    MvMode::OneMv
1301                } else {
1302                    MvMode::OneMvHpelBilin
1303                };
1304                mv_mode2 = mv_mode;
1305                let direct = Bitplane::decode(&mut br, mb_w, mb_h).ok_or_else(|| {
1306                    DecoderError::InvalidData("invalid VC-1 DIRECTMB bitplane".into())
1307                })?;
1308                directmb_raw = direct.is_raw;
1309                if !direct.is_raw {
1310                    directmb_plane = Some(direct.data);
1311                }
1312                let skip = Bitplane::decode(&mut br, mb_w, mb_h).ok_or_else(|| {
1313                    DecoderError::InvalidData("invalid VC-1 SKIPMB bitplane".into())
1314                })?;
1315                skipmb_raw = skip.is_raw;
1316                if !skip.is_raw {
1317                    skipmb_plane = Some(skip.data);
1318                }
1319                mvtab = need_bits(&mut br, 2, "MVTAB")? as u8;
1320                cbptab = need_bits(&mut br, 2, "CBPTAB")? as u8;
1321                if seq.dquant != 0 {
1322                    dq = parse_dquant(&mut br, seq.dquant, pquant)?;
1323                    if dq.enabled && dq.profile == 3 && !dq.bi_level {
1324                        halfqp = false;
1325                    }
1326                }
1327                if seq.vstransform {
1328                    ttmbf = need_bit(&mut br, "TTMBF")?;
1329                    ttfrm = if ttmbf {
1330                        [0u8, 3, 6, 7][need_bits(&mut br, 2, "TTFRM")? as usize]
1331                    } else {
1332                        0
1333                    };
1334                }
1335            }
1336            FrameType::Skipped => unreachable!(),
1337        }
1338
1339        let transacfrm = decode012(&mut br, "TRANSACFRM")?;
1340        let transacfrm2 = if matches!(frame_type, FrameType::I | FrameType::BI) {
1341            decode012(&mut br, "TRANSACFRM2")?
1342        } else {
1343            transacfrm
1344        };
1345        let dctab = need_bit(&mut br, "DCTAB")?;
1346
1347        // Advanced I/BI pictures carry VOP DQuant after AC/DC table syntax.
1348        if matches!(frame_type, FrameType::I | FrameType::BI) && seq.dquant != 0 {
1349            dq = parse_dquant(&mut br, seq.dquant, pquant)?;
1350            if dq.enabled && dq.profile == 3 && !dq.bi_level {
1351                halfqp = false;
1352            }
1353        }
1354
1355        Ok(Self {
1356            frame_type,
1357            pqindex,
1358            pquant,
1359            halfqp,
1360            pqual_mode: pquantizer as u8,
1361            mvrange,
1362            rptfrm,
1363            pts_ms,
1364            rangeredfrm: false,
1365            rnd: Some(rnd),
1366            header_bits: br.bits_read(),
1367            acpred_plane,
1368            acpred_raw,
1369            condover,
1370            overflags_plane,
1371            overflags_raw,
1372            skipmb_plane,
1373            skipmb_raw,
1374            directmb_plane,
1375            directmb_raw,
1376            mvtypemb_plane,
1377            mvtypemb_raw,
1378            bfrac_num,
1379            bfrac_den,
1380            mv_mode,
1381            mv_mode2,
1382            lumscale,
1383            lumshift,
1384            mvtab,
1385            cbptab,
1386            ttmbf,
1387            ttfrm,
1388            transacfrm,
1389            transacfrm2,
1390            dctab,
1391            dquant: dq,
1392        })
1393    }
1394
1395    pub fn parse_simple(data: &[u8], seq: &SequenceHeader, pts_ms: u32) -> Result<Self> {
1396        let mb_w = seq.width.div_ceil(16).max(1) as usize;
1397        let mb_h = seq.height.div_ceil(16).max(1) as usize;
1398        Self::parse(data, seq, pts_ms, mb_w, mb_h)
1399    }
1400}
1401
1402fn parse_dquant(br: &mut BitReader<'_>, dquant: u8, pquant: u8) -> Result<DQuantInfo> {
1403    let mut out = DQuantInfo::default();
1404    if dquant != 2 {
1405        out.enabled = need_bit(br, "DQUANTFRM")?;
1406        if !out.enabled {
1407            return Ok(out);
1408        }
1409        out.profile = need_bits(br, 2, "DQPROFILE")? as u8;
1410        // FFmpeg enum values: SINGLE_EDGE=0, DOUBLE_EDGES=1, ALL_MBS=3.
1411        match out.profile {
1412            0 | 1 => out.edge = need_bits(br, 2, "DQSBEDGE")? as u8,
1413            3 => {
1414                out.bi_level = need_bit(br, "DQBILEVEL")?;
1415                if !out.bi_level {
1416                    return Ok(out);
1417                }
1418            }
1419            _ => {}
1420        }
1421    }
1422    // DQUANT == 2 still carries PQDIFF/ABSPQ, but FFmpeg leaves
1423    // dquantfrm clear. Do not turn it into per-macroblock MQUANT syntax.
1424    let pqdiff = need_bits(br, 3, "PQDIFF")? as u8;
1425    out.alt_pquant = if pqdiff == 7 {
1426        need_bits(br, 5, "ABSPQ")? as u8
1427    } else {
1428        // Match vop_dquant_decoding(): ALTPQUANT is not clamped here.
1429        // GET_MQUANT handles out-of-range macroblock values later.
1430        pquant + pqdiff + 1
1431    };
1432    Ok(out)
1433}
1434
1435fn decode012(br: &mut BitReader<'_>, what: &str) -> Result<u8> {
1436    if !need_bit(br, what)? {
1437        Ok(0)
1438    } else {
1439        Ok(if need_bit(br, what)? { 2 } else { 1 })
1440    }
1441}
1442
1443fn read_unary(br: &mut BitReader<'_>, stop: bool, max: u8, what: &str) -> Result<u8> {
1444    let mut n = 0u8;
1445    while n < max {
1446        let bit = need_bit(br, what)?;
1447        if bit == stop {
1448            break;
1449        }
1450        n += 1;
1451    }
1452    Ok(n)
1453}
1454
1455fn need_bit(br: &mut BitReader<'_>, what: &str) -> Result<bool> {
1456    br.read_bit()
1457        .ok_or_else(|| DecoderError::InvalidData(format!("truncated VC-1 {what}")))
1458}
1459
1460fn need_bits(br: &mut BitReader<'_>, n: u8, what: &str) -> Result<u32> {
1461    br.read_bits(n)
1462        .ok_or_else(|| DecoderError::InvalidData(format!("truncated VC-1 {what}")))
1463}
1464
1465#[cfg(test)]
1466mod tests {
1467    use super::*;
1468
1469    #[test]
1470    fn imode_prefixes_are_unique() {
1471        for i in 0..IMODE_CODES.len() {
1472            for j in i + 1..IMODE_CODES.len() {
1473                let a_len = IMODE_BITS[i];
1474                let b_len = IMODE_BITS[j];
1475                let min = a_len.min(b_len);
1476                let a = IMODE_CODES[i] >> (a_len - min);
1477                let b = IMODE_CODES[j] >> (b_len - min);
1478                assert_ne!(a, b, "IMODE prefix collision: {i} vs {j}");
1479            }
1480        }
1481    }
1482
1483    #[test]
1484    fn bfraction_has_extended_entries() {
1485        assert_eq!(BFRAC[0], (1, 2));
1486        assert_eq!(BFRAC[20], (7, 8));
1487        assert_eq!(BFRAC[22], (0, 1));
1488    }
1489
1490    #[test]
1491    fn wvc1_unescape_matches_vc1_emulation_prevention() {
1492        assert_eq!(
1493            vc1_unescape_buffer(&[0x12, 0x00, 0x00, 0x03, 0x01, 0x34]),
1494            vec![0x12, 0x00, 0x00, 0x01, 0x34]
1495        );
1496    }
1497
1498    #[test]
1499    fn parses_anemoi_advanced_sequence_and_first_i_header() {
1500        // WVC1 BITMAPINFO private data from anemoi_op.wmv. It contains an
1501        // Advanced sequence header (0x0f) followed by the entry point (0x0e).
1502        let extradata = [
1503            0x27, 0x00, 0x00, 0x01, 0x0f, 0xdb, 0xc0, 0x3b, 0xf2, 0x1b, 0x8a, 0x3b, 0xf8, 0x86,
1504            0xe8, 0x0c, 0x88, 0x00, 0x00, 0x01, 0x0e, 0x1a, 0x40, 0x40,
1505        ];
1506        let seq = SequenceHeader::parse_wvc1(&extradata).unwrap();
1507        assert_eq!(seq.profile, Profile::Advanced);
1508        assert_eq!(seq.level, 3);
1509        assert_eq!((seq.width, seq.height), (1920, 1080));
1510        assert_eq!((seq.display_width, seq.display_height), (1920, 1080));
1511        assert_eq!((seq.frame_rate_num, seq.frame_rate_den), (60_000, 1001));
1512        assert!(!seq.interlace);
1513        assert!(seq.broadcast);
1514        assert!(seq.loop_filter);
1515        assert!(seq.extended_mv);
1516        assert!(seq.vstransform);
1517        assert!(!seq.overlap);
1518        assert_eq!(seq.dquant, 0);
1519
1520        // Escaped prefix of the first ASF video media object. Its complete
1521        // Advanced picture header is 87 bits; the remaining bits begin the
1522        // first I-picture macroblock layer.
1523        let escaped = [
1524            0xc0, 0x82, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03,
1525            0x01, 0x06,
1526        ];
1527        let frame = vc1_unescape_buffer(&escaped);
1528        let pic = PictureHeader::parse(&frame, &seq, 0, 120, 68).unwrap();
1529        assert_eq!(pic.frame_type, FrameType::I);
1530        assert_eq!(pic.pqindex, 4);
1531        assert_eq!(pic.pquant, 4);
1532        assert_eq!(pic.rnd, Some(false));
1533        assert_eq!(pic.header_bits, 87);
1534        assert!(!pic.acpred_raw);
1535        assert!(pic.acpred_plane.is_some());
1536
1537        // The following one-byte ASF video object is the next coded picture
1538        // in anemoi_op.wmv. Advanced Profile encodes a skipped P picture as
1539        // PTYPE=1111 followed only by the two-bit RPTFRM field here.
1540        let skipped = PictureHeader::parse(&[0xf2], &seq, 33, 120, 68).unwrap();
1541        assert_eq!(skipped.frame_type, FrameType::Skipped);
1542        assert_eq!(skipped.header_bits, 6);
1543    }
1544}