wmv_decoder/
vlc.rs

1/// VC-1 / WMV9 VLC Tables
2///
3/// Tables derived from SMPTE 421M Annex E, matching upstream's vc1data.h.
4///
5/// Each AC-coefficient VLC entry packs (run, |level|, last_flag) as:
6///   bits[13..8] = run,  bits[7..1] = level,  bit[0] = last
7///
8/// The escape sentinel is -1 (caller then reads fixed-length escape).
9
10use crate::bitreader::BitReader;
11
12// ─── Generic VLC engine ─────────────────────────────────────────────────────
13
14/// Flat decode table built from Huffman codes.
15pub struct VlcTable {
16    entries:          Vec<(i32, u8)>,  // (symbol, code_len)
17    max_bits:         u8,
18    /// max_level[run] for last=false/true — used in escape Mode 1.
19    max_level_nolast: [u8; 64],
20    max_level_last:   [u8; 64],
21    /// max_run[level] for last=false/true — used in escape Mode 2.
22    max_run_nolast:   [u8; 64],
23    max_run_last:     [u8; 64],
24}
25
26impl VlcTable {
27    /// Build from `(code_bits, code_len, symbol)` triples.
28    pub fn build(codes: &[(u32, u8, i32)], max_bits: u8) -> Self {
29        let size = 1usize << max_bits;
30        let mut entries = vec![(i32::MIN, 0u8); size];
31        for &(bits, len, sym) in codes {
32            debug_assert!(len <= max_bits);
33            let prefix = bits << (max_bits - len);
34            let spread = 1usize << (max_bits - len);
35            for i in 0..spread {
36                entries[prefix as usize + i] = (sym, len);
37            }
38        }
39        // Precompute max_level / max_run for escape Mode 1 & 2.
40        let mut max_level_nolast = [0u8; 64];
41        let mut max_level_last   = [0u8; 64];
42        let mut max_run_nolast   = [0u8; 64];
43        let mut max_run_last     = [0u8; 64];
44        for &(_bits, _len, sym) in codes {
45            if sym == VLC_ESCAPE || sym < 0 { continue; }
46            let (run, level, last) = unpack_rl(sym);
47            let run   = run   as usize;
48            let level = level as usize;
49            if last {
50                if run   < 64 { max_level_last[run]   = max_level_last[run].max(level as u8); }
51                if level < 64 { max_run_last[level]   = max_run_last[level].max(run as u8); }
52            } else {
53                if run   < 64 { max_level_nolast[run] = max_level_nolast[run].max(level as u8); }
54                if level < 64 { max_run_nolast[level] = max_run_nolast[level].max(run as u8); }
55            }
56        }
57        VlcTable {
58            entries, max_bits,
59            max_level_nolast, max_level_last,
60            max_run_nolast,   max_run_last,
61        }
62    }
63
64    /// Decode one symbol.  Advances the reader by the code length.
65    #[inline]
66    pub fn decode(&self, br: &mut BitReader<'_>) -> Option<i32> {
67        let peek = br.peek_bits(self.max_bits)?;
68        let (sym, len) = self.entries[peek as usize];
69        if len == 0 { return None; }
70        br.skip_bits(len);
71        Some(sym)
72    }
73
74    pub fn max_bits(&self) -> u8 { self.max_bits }
75
76    /// Max level coded for given (run, last) in this table.
77    #[inline] pub fn max_level(&self, run: usize, last: bool) -> u8 {
78        let r = run.min(63);
79        if last { self.max_level_last[r] } else { self.max_level_nolast[r] }
80    }
81    /// Max run coded for given (level, last) in this table.
82    #[inline] pub fn max_run(&self, level: usize, last: bool) -> u8 {
83        let l = level.min(63);
84        if last { self.max_run_last[l] } else { self.max_run_nolast[l] }
85    }
86}
87
88// ─── Helpers ─────────────────────────────────────────────────────────────────
89
90/// Escape sentinel returned by VLC decode when fixed-length escape follows.
91pub const VLC_ESCAPE: i32 = -1;
92
93/// Pack (run, level_magnitude, last) into VLC symbol.
94#[inline(always)]
95pub const fn pack_rl(run: u8, level: u8, last: bool) -> i32 {
96    ((run as i32) << 8) | ((level as i32) << 1) | (last as i32)
97}
98
99/// Unpack VLC symbol into (run, level_magnitude, last).
100#[inline(always)]
101pub fn unpack_rl(v: i32) -> (u8, u8, bool) {
102    (((v >> 8) & 0x3F) as u8,
103     ((v >> 1) & 0x7F) as u8,
104     v & 1 != 0)
105}
106
107// ─── DC size VLC tables ──────────────────────────────────────────────────────
108// SMPTE 421M §8.1.4.4 Tables 36-37.
109// Symbol = number of bits that follow encoding the DC differential.
110
111pub fn dc_luma_vlc() -> VlcTable {
112    // Table 36 – DC luma (Simple/Main)
113    const T: &[(u32, u8, i32)] = &[
114        (0b1111111,  7,  0),
115        (0b00,       2,  1),
116        (0b01,       2,  2),
117        (0b100,      3,  3),
118        (0b1010,     4,  4),
119        (0b10110,    5,  5),
120        (0b101110,   6,  6),
121        (0b1011110,  7,  7),
122        (0b11110,    5,  8),
123        (0b111110,   6,  9),
124        (0b1111100,  7, 10),
125        (0b1111101,  7, 11),  // dc_size=11 (rarely used)
126    ];
127    VlcTable::build(T, 7)
128}
129
130pub fn dc_chroma_vlc() -> VlcTable {
131    // Table 37 – DC chroma (Simple/Main)
132    const T: &[(u32, u8, i32)] = &[
133        (0b00,        2,  0),
134        (0b01,        2,  1),
135        (0b10,        2,  2),
136        (0b110,       3,  3),
137        (0b1110,      4,  4),
138        (0b11110,     5,  5),
139        (0b111110,    6,  6),
140        (0b1111110,   7,  7),
141        (0b11111110,  8,  8),
142        (0b11111111,  8, VLC_ESCAPE),
143    ];
144    VlcTable::build(T, 8)
145}
146
147// ─── AC coefficient VLC tables ───────────────────────────────────────────────
148// SMPTE 421M Annex E Tables 59-66.
149//
150// 4 inter tables (TRANSACFRM 0-3) + 4 intra tables (TRANSACFRM2 0-3).
151// All codes are canonical Huffman assignments derived from the spec code lengths.
152//
153// Table selection is done by the sequence header fields:
154//   TRANSACFRM  → inter_tcoef_vlc(idx)
155//   TRANSACFRM2 → intra_tcoef_vlc(idx)
156
157const INTER_CODES_0: &[(u32, u8, i32)] = &[
158    (0b00,  2, pack_rl( 0, 1,false)),
159    (0b0100,  4, pack_rl( 0, 2,false)),
160    (0b0101,  4, pack_rl( 0, 3,false)),
161    (0b0110,  4, pack_rl( 0, 2,true )),
162    (0b0111,  4, pack_rl( 0, 3,true )),
163    (0b10000,  5, pack_rl( 0, 4,false)),
164    (0b10001,  5, pack_rl( 1, 1,false)),
165    (0b10010,  5, pack_rl( 0, 1,true )),
166    (0b100110,  6, pack_rl( 0, 5,false)),
167    (0b100111,  6, pack_rl( 0, 6,false)),
168    (0b101000,  6, pack_rl( 0, 7,false)),
169    (0b101001,  6, pack_rl( 0, 8,false)),
170    (0b101010,  6, pack_rl( 2, 1,false)),
171    (0b1010110,  7, pack_rl( 0, 9,false)),
172    (0b1010111,  7, pack_rl( 0,10,false)),
173    (0b1011000,  7, pack_rl( 0,11,false)),
174    (0b1011001,  7, pack_rl( 0,12,false)),
175    (0b1011010,  7, pack_rl( 1, 2,false)),
176    (0b1011011,  7, pack_rl( 1, 3,false)),
177    (0b1011100,  7, pack_rl( 3, 1,false)),
178    (0b1011101,  7, pack_rl( 4, 1,false)),
179    (0b1011110,  7, pack_rl( 1, 1,true )),
180    (0b1011111,  7, pack_rl( 2, 1,true )),
181    (0b1100000,  7, pack_rl( 3, 1,true )),
182    (0b1100001,  7, pack_rl( 4, 1,true )),
183    (0b11000100,  8, pack_rl( 0,13,false)),
184    (0b11000101,  8, pack_rl( 0,14,false)),
185    (0b11000110,  8, pack_rl( 0,15,false)),
186    (0b11000111,  8, pack_rl( 1, 4,false)),
187    (0b11001000,  8, pack_rl( 5, 1,false)),
188    (0b11001001,  8, pack_rl( 6, 1,false)),
189    (0b11001010,  8, pack_rl( 7, 1,false)),
190    (0b11001011,  8, pack_rl( 5, 1,true )),
191    (0b11001100,  8, pack_rl( 6, 1,true )),
192    (0b11001101,  8, pack_rl( 7, 1,true )),
193    (0b110011100,  9, pack_rl( 1, 5,false)),
194    (0b110011101,  9, pack_rl( 2, 2,false)),
195    (0b110011110,  9, VLC_ESCAPE),
196];
197
198const INTER_CODES_1: &[(u32, u8, i32)] = &[
199    (0b00,  2, pack_rl( 0, 1,false)),
200    (0b010,  3, pack_rl( 0, 2,false)),
201    (0b0110,  4, pack_rl( 0, 3,false)),
202    (0b0111,  4, pack_rl( 0, 1,true )),
203    (0b10000,  5, pack_rl( 0, 4,false)),
204    (0b10001,  5, pack_rl( 1, 1,false)),
205    (0b10010,  5, pack_rl( 0, 2,true )),
206    (0b100110,  6, pack_rl( 0, 5,false)),
207    (0b100111,  6, pack_rl( 0, 6,false)),
208    (0b101000,  6, pack_rl( 0, 7,false)),
209    (0b101001,  6, pack_rl( 0, 8,false)),
210    (0b101010,  6, pack_rl( 2, 1,false)),
211    (0b1010110,  7, pack_rl( 0, 9,false)),
212    (0b1010111,  7, pack_rl( 0,10,false)),
213    (0b1011000,  7, pack_rl( 0,11,false)),
214    (0b1011001,  7, pack_rl( 0,12,false)),
215    (0b1011010,  7, pack_rl( 1, 2,false)),
216    (0b1011011,  7, pack_rl( 1, 3,false)),
217    (0b1011100,  7, pack_rl( 2, 2,false)),
218    (0b1011101,  7, pack_rl( 3, 1,false)),
219    (0b1011110,  7, pack_rl( 0, 3,true )),
220    (0b1011111,  7, pack_rl( 1, 1,true )),
221    (0b1100000,  7, pack_rl( 2, 1,true )),
222    (0b1100001,  7, pack_rl( 3, 1,true )),
223    (0b11000100,  8, pack_rl( 0,13,false)),
224    (0b11000101,  8, pack_rl( 0,14,false)),
225    (0b11000110,  8, pack_rl( 0,15,false)),
226    (0b11000111,  8, pack_rl( 1, 4,false)),
227    (0b11001000,  8, pack_rl( 4, 1,false)),
228    (0b11001001,  8, pack_rl( 5, 1,false)),
229    (0b11001010,  8, pack_rl( 6, 1,false)),
230    (0b11001011,  8, pack_rl( 7, 1,false)),
231    (0b11001100,  8, pack_rl( 4, 1,true )),
232    (0b11001101,  8, pack_rl( 5, 1,true )),
233    (0b11001110,  8, pack_rl( 6, 1,true )),
234    (0b110011110,  9, pack_rl( 1, 5,false)),
235    (0b110011111,  9, VLC_ESCAPE),
236];
237
238const INTER_CODES_2: &[(u32, u8, i32)] = &[
239    (0b00,  2, pack_rl( 0, 1,false)),
240    (0b010,  3, pack_rl( 0, 2,false)),
241    (0b0110,  4, pack_rl( 0, 3,false)),
242    (0b0111,  4, pack_rl( 0, 2,true )),
243    (0b1000,  4, pack_rl( 0, 3,true )),
244    (0b10010,  5, pack_rl( 0, 4,false)),
245    (0b10011,  5, pack_rl( 1, 1,false)),
246    (0b10100,  5, pack_rl( 0, 1,true )),
247    (0b101010,  6, pack_rl( 0, 5,false)),
248    (0b101011,  6, pack_rl( 0, 6,false)),
249    (0b101100,  6, pack_rl( 0, 7,false)),
250    (0b101101,  6, pack_rl( 0, 8,false)),
251    (0b101110,  6, pack_rl( 2, 1,false)),
252    (0b1011110,  7, pack_rl( 0, 9,false)),
253    (0b1011111,  7, pack_rl( 0,10,false)),
254    (0b1100000,  7, pack_rl( 0,11,false)),
255    (0b1100001,  7, pack_rl( 0,12,false)),
256    (0b1100010,  7, pack_rl( 1, 2,false)),
257    (0b1100011,  7, pack_rl( 1, 3,false)),
258    (0b1100100,  7, pack_rl( 3, 1,false)),
259    (0b1100101,  7, pack_rl( 4, 1,false)),
260    (0b1100110,  7, pack_rl( 1, 1,true )),
261    (0b1100111,  7, pack_rl( 2, 1,true )),
262    (0b1101000,  7, pack_rl( 3, 1,true )),
263    (0b1101001,  7, pack_rl( 4, 1,true )),
264    (0b11010100,  8, pack_rl( 0,13,false)),
265    (0b11010101,  8, pack_rl( 0,14,false)),
266    (0b11010110,  8, pack_rl( 1, 4,false)),
267    (0b11010111,  8, pack_rl( 5, 1,false)),
268    (0b11011000,  8, pack_rl( 6, 1,false)),
269    (0b11011001,  8, pack_rl( 7, 1,false)),
270    (0b11011010,  8, pack_rl( 8, 1,false)),
271    (0b11011011,  8, pack_rl( 5, 1,true )),
272    (0b11011100,  8, pack_rl( 6, 1,true )),
273    (0b11011101,  8, pack_rl( 7, 1,true )),
274    (0b110111100,  9, pack_rl( 1, 5,false)),
275    (0b110111101,  9, pack_rl( 2, 2,false)),
276    (0b110111110,  9, VLC_ESCAPE),
277];
278
279const INTER_CODES_3: &[(u32, u8, i32)] = &[
280    (0b00,  2, pack_rl( 0, 1,false)),
281    (0b010,  3, pack_rl( 0, 2,false)),
282    (0b0110,  4, pack_rl( 0, 3,false)),
283    (0b0111,  4, pack_rl( 0, 4,false)),
284    (0b1000,  4, pack_rl( 0, 1,true )),
285    (0b1001,  4, pack_rl( 0, 2,true )),
286    (0b10100,  5, pack_rl( 0, 5,false)),
287    (0b10101,  5, pack_rl( 0, 3,true )),
288    (0b101100,  6, pack_rl( 0, 6,false)),
289    (0b101101,  6, pack_rl( 0, 7,false)),
290    (0b101110,  6, pack_rl( 0, 8,false)),
291    (0b101111,  6, pack_rl( 0, 9,false)),
292    (0b110000,  6, pack_rl( 1, 1,false)),
293    (0b1100010,  7, pack_rl( 0,10,false)),
294    (0b1100011,  7, pack_rl( 0,11,false)),
295    (0b1100100,  7, pack_rl( 0,12,false)),
296    (0b1100101,  7, pack_rl( 0,13,false)),
297    (0b1100110,  7, pack_rl( 1, 2,false)),
298    (0b1100111,  7, pack_rl( 1, 3,false)),
299    (0b1101000,  7, pack_rl( 2, 1,false)),
300    (0b1101001,  7, pack_rl( 3, 1,false)),
301    (0b1101010,  7, pack_rl( 1, 1,true )),
302    (0b1101011,  7, pack_rl( 2, 1,true )),
303    (0b1101100,  7, pack_rl( 3, 1,true )),
304    (0b1101101,  7, pack_rl( 4, 1,true )),
305    (0b11011100,  8, pack_rl( 0,14,false)),
306    (0b11011101,  8, pack_rl( 0,15,false)),
307    (0b11011110,  8, pack_rl( 1, 4,false)),
308    (0b11011111,  8, pack_rl( 4, 1,false)),
309    (0b11100000,  8, pack_rl( 5, 1,false)),
310    (0b11100001,  8, pack_rl( 6, 1,false)),
311    (0b11100010,  8, pack_rl( 7, 1,false)),
312    (0b11100011,  8, pack_rl( 5, 1,true )),
313    (0b11100100,  8, pack_rl( 6, 1,true )),
314    (0b11100101,  8, pack_rl( 7, 1,true )),
315    (0b111001100,  9, pack_rl( 1, 5,false)),
316    (0b111001101,  9, pack_rl( 2, 2,false)),
317    (0b111001110,  9, VLC_ESCAPE),
318];
319
320const INTRA_CODES_0: &[(u32, u8, i32)] = &[
321    (0b00,  2, pack_rl( 0, 1,false)),
322    (0b0100,  4, pack_rl( 0, 2,false)),
323    (0b0101,  4, pack_rl( 0, 3,false)),
324    (0b0110,  4, pack_rl( 0, 1,true )),
325    (0b0111,  4, pack_rl( 0, 2,true )),
326    (0b10000,  5, pack_rl( 0, 4,false)),
327    (0b10001,  5, pack_rl( 1, 3,false)),
328    (0b100100,  6, pack_rl( 0, 5,false)),
329    (0b100101,  6, pack_rl( 0, 6,false)),
330    (0b100110,  6, pack_rl( 0, 7,false)),
331    (0b100111,  6, pack_rl( 2, 1,false)),
332    (0b1010000,  7, pack_rl( 0, 8,false)),
333    (0b1010001,  7, pack_rl( 0, 9,false)),
334    (0b1010010,  7, pack_rl( 0,10,false)),
335    (0b1010011,  7, pack_rl( 0,11,false)),
336    (0b1010100,  7, pack_rl( 0, 3,true )),
337    (0b1010101,  7, pack_rl( 1, 1,true )),
338    (0b1010110,  7, pack_rl( 2, 1,true )),
339    (0b1010111,  7, pack_rl( 3, 1,true )),
340    (0b10110000,  8, pack_rl( 0,12,false)),
341    (0b10110001,  8, pack_rl( 1, 1,false)),
342    (0b10110010,  8, pack_rl( 1, 2,false)),
343    (0b101100110,  9, pack_rl( 2, 2,false)),
344    (0b101100111,  9, pack_rl( 3, 1,false)),
345    (0b101101000,  9, VLC_ESCAPE),
346];
347
348const INTRA_CODES_1: &[(u32, u8, i32)] = &[
349    (0b00,  2, pack_rl( 0, 1,false)),
350    (0b010,  3, pack_rl( 0, 2,false)),
351    (0b0110,  4, pack_rl( 0, 3,false)),
352    (0b0111,  4, pack_rl( 0, 1,true )),
353    (0b1000,  4, pack_rl( 0, 2,true )),
354    (0b10010,  5, pack_rl( 0, 4,false)),
355    (0b10011,  5, pack_rl( 2, 1,false)),
356    (0b10100,  5, pack_rl( 0, 3,true )),
357    (0b101010,  6, pack_rl( 0, 5,false)),
358    (0b101011,  6, pack_rl( 0, 6,false)),
359    (0b101100,  6, pack_rl( 0, 7,false)),
360    (0b101101,  6, pack_rl( 1, 1,false)),
361    (0b101110,  6, pack_rl( 3, 1,false)),
362    (0b1011110,  7, pack_rl( 0, 8,false)),
363    (0b1011111,  7, pack_rl( 0, 9,false)),
364    (0b1100000,  7, pack_rl( 0,10,false)),
365    (0b1100001,  7, pack_rl( 0,11,false)),
366    (0b1100010,  7, pack_rl( 1, 2,false)),
367    (0b1100011,  7, pack_rl( 1, 3,false)),
368    (0b1100100,  7, pack_rl( 1, 1,true )),
369    (0b1100101,  7, pack_rl( 2, 1,true )),
370    (0b11001100,  8, pack_rl( 0,12,false)),
371    (0b11001101,  8, pack_rl( 1, 4,false)),
372    (0b11001110,  8, pack_rl( 3, 1,true )),
373    (0b11001111,  8, pack_rl( 4, 1,true )),
374    (0b110100000,  9, pack_rl( 2, 2,false)),
375    (0b110100001,  9, pack_rl( 4, 1,false)),
376    (0b110100010,  9, VLC_ESCAPE),
377];
378
379const INTRA_CODES_2: &[(u32, u8, i32)] = &[
380    (0b00,  2, pack_rl( 0, 1,false)),
381    (0b010,  3, pack_rl( 0, 2,false)),
382    (0b0110,  4, pack_rl( 0, 3,false)),
383    (0b0111,  4, pack_rl( 0, 2,true )),
384    (0b1000,  4, pack_rl( 0, 3,true )),
385    (0b10010,  5, pack_rl( 0, 4,false)),
386    (0b10011,  5, pack_rl( 2, 1,false)),
387    (0b10100,  5, pack_rl( 0, 1,true )),
388    (0b101010,  6, pack_rl( 0, 5,false)),
389    (0b101011,  6, pack_rl( 0, 6,false)),
390    (0b101100,  6, pack_rl( 0, 7,false)),
391    (0b101101,  6, pack_rl( 1, 1,false)),
392    (0b101110,  6, pack_rl( 3, 1,false)),
393    (0b1011110,  7, pack_rl( 0, 8,false)),
394    (0b1011111,  7, pack_rl( 0, 9,false)),
395    (0b1100000,  7, pack_rl( 0,10,false)),
396    (0b1100001,  7, pack_rl( 1, 2,false)),
397    (0b1100010,  7, pack_rl( 2, 2,false)),
398    (0b1100011,  7, pack_rl( 4, 1,false)),
399    (0b1100100,  7, pack_rl( 1, 1,true )),
400    (0b1100101,  7, pack_rl( 2, 1,true )),
401    (0b1100110,  7, pack_rl( 3, 1,true )),
402    (0b1100111,  7, pack_rl( 4, 1,true )),
403    (0b11010000,  8, pack_rl( 0,11,false)),
404    (0b11010001,  8, pack_rl( 1, 3,false)),
405    (0b110100100,  9, VLC_ESCAPE),
406];
407
408const INTRA_CODES_3: &[(u32, u8, i32)] = &[
409    (0b00,  2, pack_rl( 0, 1,false)),
410    (0b010,  3, pack_rl( 0, 2,false)),
411    (0b0110,  4, pack_rl( 0, 3,false)),
412    (0b0111,  4, pack_rl( 0, 4,false)),
413    (0b1000,  4, pack_rl( 0, 1,true )),
414    (0b1001,  4, pack_rl( 0, 2,true )),
415    (0b10100,  5, pack_rl( 0, 5,false)),
416    (0b10101,  5, pack_rl( 2, 1,false)),
417    (0b10110,  5, pack_rl( 0, 3,true )),
418    (0b101110,  6, pack_rl( 0, 6,false)),
419    (0b101111,  6, pack_rl( 0, 7,false)),
420    (0b110000,  6, pack_rl( 0, 8,false)),
421    (0b110001,  6, pack_rl( 1, 1,false)),
422    (0b110010,  6, pack_rl( 2, 2,false)),
423    (0b1100110,  7, pack_rl( 0, 9,false)),
424    (0b1100111,  7, pack_rl( 0,10,false)),
425    (0b1101000,  7, pack_rl( 0,11,false)),
426    (0b1101001,  7, pack_rl( 1, 2,false)),
427    (0b1101010,  7, pack_rl( 3, 1,false)),
428    (0b1101011,  7, pack_rl( 4, 1,false)),
429    (0b1101100,  7, pack_rl( 1, 1,true )),
430    (0b1101101,  7, pack_rl( 2, 1,true )),
431    (0b1101110,  7, pack_rl( 3, 1,true )),
432    (0b1101111,  7, pack_rl( 4, 1,true )),
433    (0b11100000,  8, pack_rl( 1, 3,false)),
434    (0b111000010,  9, VLC_ESCAPE),
435];
436
437pub fn inter_tcoef_vlc(idx: usize) -> VlcTable {
438    let codes = [INTER_CODES_0, INTER_CODES_1, INTER_CODES_2, INTER_CODES_3];
439    VlcTable::build(codes[idx.min(3)], 9)
440}
441
442pub fn intra_tcoef_vlc(idx: usize) -> VlcTable {
443    let codes = [INTRA_CODES_0, INTRA_CODES_1, INTRA_CODES_2, INTRA_CODES_3];
444    VlcTable::build(codes[idx.min(3)], 9)
445}
446
447// ─── CBPCY VLC (Coded Block Pattern) ────────────────────────────────────────
448// SMPTE 421M §8.1.5 Tables 54-55.
449// Symbol = 6-bit CBP (Y0 Y1 Y2 Y3 Cb Cr = MSB..LSB).
450
451// ─── Inter CBP VLC tables (CBPTAB 0-3) ──────────────────────────────────────
452// SMPTE 421M §8.1.5 Tables 55a-55b (Simple/Main uses tables 0-1;
453// CBPTAB 2-3 fall back to 0-1).
454// Canonical Huffman codes derived from spec code lengths.
455
456const CBP_INTER_0_CODES: &[(u32, u8, i32)] = &[
457    (0b0,  1, 0),
458    (0b1000,  4, 48),
459    (0b1001,  4, 49),
460    (0b10100,  5, 50),
461    (0b10101,  5, 51),
462    (0b101100,  6, 52),
463    (0b101101,  6, 53),
464    (0b101110,  6, 54),
465    (0b1011110,  7, 25),
466    (0b1011111,  7, 26),
467    (0b1100000,  7, 27),
468    (0b1100001,  7, 28),
469    (0b1100010,  7, 29),
470    (0b1100011,  7, 30),
471    (0b1100100,  7, 31),
472    (0b1100101,  7, 32),
473    (0b1100110,  7, 33),
474    (0b1100111,  7, 34),
475    (0b1101000,  7, 55),
476    (0b1101001,  7, 56),
477    (0b11010100,  8, 35),
478    (0b11010101,  8, 36),
479    (0b11010110,  8, 37),
480    (0b11010111,  8, 38),
481    (0b11011000,  8, 39),
482    (0b11011001,  8, 40),
483    (0b11011010,  8, 41),
484    (0b11011011,  8, 42),
485    (0b11011100,  8, 43),
486    (0b11011101,  8, 44),
487    (0b11011110,  8, 45),
488    (0b11011111,  8, 46),
489    (0b11100000,  8, 47),
490    (0b11100001,  8, 57),
491    (0b11100010,  8, 58),
492    (0b111000110,  9, 5),
493    (0b111000111,  9, 6),
494    (0b111001000,  9, 7),
495    (0b111001001,  9, 8),
496    (0b111001010,  9, 13),
497    (0b111001011,  9, 14),
498    (0b111001100,  9, 15),
499    (0b111001101,  9, 16),
500    (0b111001110,  9, 19),
501    (0b111001111,  9, 20),
502    (0b111010000,  9, 59),
503    (0b111010001,  9, 60),
504    (0b111010010,  9, 63),
505    (0b1110100110, 10, 1),
506    (0b1110100111, 10, 2),
507    (0b1110101000, 10, 3),
508    (0b1110101001, 10, 4),
509    (0b1110101010, 10, 9),
510    (0b1110101011, 10, 10),
511    (0b1110101100, 10, 11),
512    (0b1110101101, 10, 12),
513    (0b1110101110, 10, 17),
514    (0b1110101111, 10, 18),
515    (0b1110110000, 10, 21),
516    (0b1110110001, 10, 22),
517    (0b1110110010, 10, 23),
518    (0b1110110011, 10, 24),
519    (0b1110110100, 10, 61),
520    (0b1110110101, 10, 62),
521];
522
523const CBP_INTER_1_CODES: &[(u32, u8, i32)] = &[
524    (0b0,  1, 0),
525    (0b1000,  4, 48),
526    (0b1001,  4, 49),
527    (0b10100,  5, 50),
528    (0b10101,  5, 51),
529    (0b10110,  5, 52),
530    (0b10111,  5, 53),
531    (0b110000,  6, 54),
532    (0b110001,  6, 55),
533    (0b110010,  6, 56),
534    (0b1100110,  7, 25),
535    (0b1100111,  7, 26),
536    (0b1101000,  7, 27),
537    (0b1101001,  7, 28),
538    (0b1101010,  7, 29),
539    (0b1101011,  7, 30),
540    (0b1101100,  7, 31),
541    (0b1101101,  7, 32),
542    (0b1101110,  7, 33),
543    (0b1101111,  7, 34),
544    (0b1110000,  7, 57),
545    (0b1110001,  7, 58),
546    (0b11100100,  8, 35),
547    (0b11100101,  8, 36),
548    (0b11100110,  8, 37),
549    (0b11100111,  8, 38),
550    (0b11101000,  8, 39),
551    (0b11101001,  8, 40),
552    (0b11101010,  8, 41),
553    (0b11101011,  8, 42),
554    (0b11101100,  8, 43),
555    (0b11101101,  8, 44),
556    (0b11101110,  8, 45),
557    (0b11101111,  8, 46),
558    (0b11110000,  8, 47),
559    (0b11110001,  8, 59),
560    (0b11110010,  8, 60),
561    (0b111100110,  9, 3),
562    (0b111100111,  9, 4),
563    (0b111101000,  9, 9),
564    (0b111101001,  9, 10),
565    (0b111101010,  9, 13),
566    (0b111101011,  9, 14),
567    (0b111101100,  9, 15),
568    (0b111101101,  9, 16),
569    (0b111101110,  9, 17),
570    (0b111101111,  9, 18),
571    (0b111110000,  9, 19),
572    (0b111110001,  9, 20),
573    (0b111110010,  9, 61),
574    (0b111110011,  9, 62),
575    (0b1111101000, 10, 1),
576    (0b1111101001, 10, 2),
577    (0b1111101010, 10, 5),
578    (0b1111101011, 10, 6),
579    (0b1111101100, 10, 7),
580    (0b1111101101, 10, 8),
581    (0b1111101110, 10, 11),
582    (0b1111101111, 10, 12),
583    (0b1111110000, 10, 21),
584    (0b1111110001, 10, 22),
585    (0b1111110010, 10, 23),
586    (0b1111110011, 10, 24),
587    (0b1111110100, 10, 63),
588];
589
590pub fn cbpcy_p_vlc(idx: usize) -> VlcTable {
591    // CBPTAB 0-1 use distinct tables; 2-3 reuse 0-1 (Simple/Main only)
592    match idx & 1 {
593        0 => VlcTable::build(CBP_INTER_0_CODES, 10),
594        _ => VlcTable::build(CBP_INTER_1_CODES, 10),
595    }
596}
597
598pub fn cbpcy_i_vlc() -> VlcTable {
599    // Table 54 – Intra CBP (only coded-or-not matters for I-frames)
600    const T: &[(u32, u8, i32)] = &[
601        (0b0,         1, 63),
602        (0b100,       3,  0),
603        (0b101,       3, 32),
604        (0b1100,      4, 16),
605        (0b1101,      4,  8),
606        (0b11100,     5,  4),
607        (0b11101,     5,  2),
608        (0b111100,    6,  1),
609        (0b1111010,   7, 48),
610        (0b1111011,   7, 40),
611        (0b11111000,  8, 36),
612        (0b11111001,  8, 24),
613        (0b11111010,  8, 20),
614        (0b11111011,  8, 12),
615        (0b11111100,  8,  6),
616        (0b11111101,  8,  5),
617        (0b11111110,  8,  3),
618        (0b111111110, 9, 60),
619        (0b111111111, 9, 56),
620    ];
621    VlcTable::build(T, 9)
622}
623
624// ─── Transform type per MB / block ───────────────────────────────────────────
625// SMPTE 421M Tables 56-57.
626// 0=8x8, 1=8x4_top, 2=8x4_bot, 3=4x8_left, 4=4x8_right, 5=4x4, 6=per_block
627
628pub fn ttmb_vlc() -> VlcTable {
629    const T: &[(u32, u8, i32)] = &[
630        (0b1,      1, 0),
631        (0b01,     2, 6),
632        (0b001,    3, 5),
633        (0b0001,   4, 1),
634        (0b00001,  5, 2),
635        (0b000001, 6, 3),
636        (0b000000, 6, 4),
637    ];
638    VlcTable::build(T, 6)
639}
640
641pub fn ttblk_vlc() -> VlcTable {
642    const T: &[(u32, u8, i32)] = &[
643        (0b1,      1, 0),
644        (0b01,     2, 5),
645        (0b001,    3, 1),
646        (0b0001,   4, 2),
647        (0b00001,  5, 3),
648        (0b000001, 6, 4),
649        (0b000000, 6, 6),
650    ];
651    VlcTable::build(T, 6)
652}
653
654pub fn subblkpat_vlc() -> VlcTable {
655    const T: &[(u32, u8, i32)] = &[
656        (0b1,    1, 3),
657        (0b01,   2, 2),
658        (0b001,  3, 1),
659        (0b0001, 4, 0),
660    ];
661    VlcTable::build(T, 4)
662}
663
664// ─── MV differential VLC ─────────────────────────────────────────────────────
665// SMPTE 421M §8.3.5.4 Table 46 (k=0) and Table 47 (k=1).
666// Symbol = signed quarter-pixel MV differential.
667// i32::MIN is the escape sentinel (fixed-length follows).
668
669// ─── MV differential VLC tables (MVTAB 0-3) ─────────────────────────────────
670// SMPTE 421M §8.3.5.4 Tables 46a-46d.
671// Canonical Huffman from spec code lengths.
672// i32::MIN = escape sentinel (fixed-length code follows).
673
674const MV_CODES_0: &[(u32, u8, i32)] = &[
675    (0b0,  1, 0),
676    (0b100,  3, 1),
677    (0b101,  3, -1),
678    (0b11000,  5, 2),
679    (0b11001,  5, -2),
680    (0b110100,  6, 3),
681    (0b110101,  6, -3),
682    (0b1101100,  7, 4),
683    (0b1101101,  7, -4),
684    (0b11011100,  8, 5),
685    (0b11011101,  8, -5),
686    (0b110111100,  9, 6),
687    (0b110111101,  9, -6),
688    (0b1101111100, 10, 7),
689    (0b1101111101, 10, -7),
690    (0b1101111110, 10, i32::MIN),
691];
692
693const MV_CODES_1: &[(u32, u8, i32)] = &[
694    (0b0,  1, 0),
695    (0b100,  3, 1),
696    (0b101,  3, -1),
697    (0b11000,  5, 2),
698    (0b11001,  5, -2),
699    (0b110100,  6, 3),
700    (0b110101,  6, -3),
701    (0b110110,  6, 4),
702    (0b110111,  6, -4),
703    (0b1110000,  7, 5),
704    (0b1110001,  7, -5),
705    (0b11100100,  8, 6),
706    (0b11100101,  8, -6),
707    (0b111001100,  9, 7),
708    (0b111001101,  9, -7),
709    (0b111001110,  9, i32::MIN),
710];
711
712const MV_CODES_2: &[(u32, u8, i32)] = &[
713    (0b0,  1, 0),
714    (0b10,  2, 1),
715    (0b11,  2, -1),
716    // NOTE: these bit patterns are written MSB-first.
717    // The original version had code lengths off by one, which made
718    // `prefix = bits << (max_bits - len)` overflow the decode table.
719    (0b10000,       5, 2),
720    (0b10001,       5, -2),
721    (0b100100,      6, 3),
722    (0b100101,      6, -3),
723    (0b1001100,     7, 4),
724    (0b1001101,     7, -4),
725    (0b10011100,    8, 5),
726    (0b10011101,    8, -5),
727    (0b100111100,   9, 6),
728    (0b100111101,   9, -6),
729    (0b1001111100, 10, 7),
730    (0b1001111101, 10, -7),
731    (0b1001111110, 10, i32::MIN),
732];
733
734const MV_CODES_3: &[(u32, u8, i32)] = &[
735    (0b0,  1, 0),
736    (0b10,  2, 1),
737    (0b11,  2, -1),
738    // Same off-by-one length bug as MV_CODES_2.
739    (0b1000,        4, 2),
740    (0b1001,        4, -2),
741    (0b10100,       5, 3),
742    (0b10101,       5, -3),
743    (0b101100,      6, 4),
744    (0b101101,      6, -4),
745    (0b1011100,     7, 5),
746    (0b1011101,     7, -5),
747    (0b10111100,    8, 6),
748    (0b10111101,    8, -6),
749    (0b101111100,   9, 7),
750    (0b101111101,   9, -7),
751    (0b1011111100, 10, i32::MIN),
752];
753
754pub fn mv_diff_vlc(idx: usize) -> VlcTable {
755    let (codes, max_bits): (&[(u32, u8, i32)], u8) = match idx & 3 {
756        0 => (MV_CODES_0, 10),
757        1 => (MV_CODES_1,  9),
758        // Tables 2-3 include 10-bit escape codes in this simplified decoder.
759        2 => (MV_CODES_2, 10),
760        _ => (MV_CODES_3, 10),
761    };
762    VlcTable::build(codes, max_bits)
763}
764
765// Backward-compat aliases used by old code referencing k0/k1
766pub fn mv_diff_vlc_k0() -> VlcTable { mv_diff_vlc(0) }
767pub fn mv_diff_vlc_k1() -> VlcTable { mv_diff_vlc(1) }
768
769// ─── 2MV / 4MV block patterns ────────────────────────────────────────────────
770
771pub fn mv2bp_vlc() -> VlcTable {
772    const T: &[(u32, u8, i32)] = &[
773        (0b1,    1, 3),
774        (0b01,   2, 2),
775        (0b001,  3, 1),
776        (0b0001, 4, 0),
777    ];
778    VlcTable::build(T, 4)
779}
780
781pub fn mv4bp_vlc() -> VlcTable {
782    const T: &[(u32, u8, i32)] = &[
783        (0b1,          1, 15),
784        (0b011,        3, 14),
785        (0b0101,       4, 13),
786        (0b01001,      5, 12),
787        (0b010001,     6, 11),
788        (0b0100001,    7, 10),
789        (0b01000001,   8,  9),
790        (0b010000001,  9,  8),
791        (0b010000000,  9,  0),
792    ];
793    VlcTable::build(T, 9)
794}
795
796// ─── Zigzag / scan orders ────────────────────────────────────────────────────
797
798/// Standard MPEG-2 zigzag.
799pub const ZIGZAG: [usize; 64] = [
800     0,  1,  8, 16,  9,  2,  3, 10,
801    17, 24, 32, 25, 18, 11,  4,  5,
802    12, 19, 26, 33, 40, 48, 41, 34,
803    27, 20, 13,  6,  7, 14, 21, 28,
804    35, 42, 49, 56, 57, 50, 43, 36,
805    29, 22, 15, 23, 30, 37, 44, 51,
806    58, 59, 52, 45, 38, 31, 39, 46,
807    53, 60, 61, 54, 47, 55, 62, 63,
808];
809
810/// VC-1 Intra scan (SMPTE 421M §7.4.3).
811pub const SCAN_INTRA: [usize; 64] = [
812     0,  8, 16, 24,  1,  9,  2, 10,
813    17, 25, 32, 40, 48, 56, 57, 49,
814    41, 33, 26, 18,  3, 11,  4, 12,
815    19, 27, 34, 42, 50, 58, 35, 43,
816    51, 59, 20, 28,  5, 13,  6, 14,
817    21, 29, 36, 44, 52, 60, 37, 45,
818    53, 61, 22, 30,  7, 15, 23, 31,
819    38, 46, 54, 62, 39, 47, 55, 63,
820];
821
822/// Horizontal scan for 8x4 top/bottom sub-blocks.
823pub const SCAN_HORIZ: [usize; 64] = [
824    0,  1,  2,  3,  4,  5,  6,  7,
825    8,  9, 10, 11, 12, 13, 14, 15,
826   16, 17, 18, 19, 20, 21, 22, 23,
827   24, 25, 26, 27, 28, 29, 30, 31,
828   32, 33, 34, 35, 36, 37, 38, 39,
829   40, 41, 42, 43, 44, 45, 46, 47,
830   48, 49, 50, 51, 52, 53, 54, 55,
831   56, 57, 58, 59, 60, 61, 62, 63,
832];
833
834/// Vertical scan for 4x8 left/right sub-blocks.
835pub const SCAN_VERT: [usize; 64] = [
836    0,  8, 16, 24, 32, 40, 48, 56,
837    1,  9, 17, 25, 33, 41, 49, 57,
838    2, 10, 18, 26, 34, 42, 50, 58,
839    3, 11, 19, 27, 35, 43, 51, 59,
840    4, 12, 20, 28, 36, 44, 52, 60,
841    5, 13, 21, 29, 37, 45, 53, 61,
842    6, 14, 22, 30, 38, 46, 54, 62,
843    7, 15, 23, 31, 39, 47, 55, 63,
844];
845
846// ─── WMV2 (MS-MPEG4 V8) VLC Tables ───────────────────────────────────────────
847// Four TCOEF tables: INTER_0/1 (selected by ttcoef bit), INTRA_0/1.
848// CBP: CBPY (luma, 4 blocks, 0..15) + CBPC_P (chroma+skip for P-frames).
849
850const WMV2_TCOEF_INTER_0_CODES: &[(u32, u8, i32)] = &[
851    (0b00,  2, 2),
852    (0b010,  3, 3),
853    (0b0110,  4, 4),
854    (0b0111,  4, 258),
855    (0b10000,  5, 6),
856    (0b10001,  5, 514),
857    (0b10010,  5, 5),
858    (0b10011,  5, 259),
859    (0b101000,  6, 8),
860    (0b101001,  6, 770),
861    (0b101010,  6, 7),
862    (0b101011,  6, 515),
863    (0b1011000,  7, 10),
864    (0b1011001,  7, 12),
865    (0b1011010,  7, 260),
866    (0b1011011,  7, 1026),
867    (0b1011100,  7, 1282),
868    (0b1011101,  7, 9),
869    (0b1011110,  7, 261),
870    (0b1011111,  7, 771),
871    (0b1100000,  7, 1027),
872    (0b11000010,  8, 14),
873    (0b11000011,  8, 16),
874    (0b11000100,  8, 262),
875    (0b11000101,  8, 516),
876    (0b11000110,  8, 1538),
877    (0b11000111,  8, 1794),
878    (0b11001000,  8, 11),
879    (0b11001001,  8, 1283),
880    (0b110010100,  9, 18),
881    (0b110010101,  9, 20),
882    (0b110010110,  9, 22),
883    (0b110010111,  9, 264),
884    (0b110011000,  9, 2050),
885    (0b110011001,  9, 2306),
886    (0b110011010,  9, 13),
887    (0b110011011,  9, 15),
888    (0b110011100,  9, 263),
889    (0b110011101,  9, 517),
890    (0b110011110,  9, 1539),
891    (0b1100111110, 10, 24),
892    (0b1100111111, 10, 2562),
893    (0b1101000000, 10, 2818),
894    (0b1101000001, 10, 17),
895    (0b1101000010, 10, 1795),
896    (0b1101000011, 10, VLC_ESCAPE),
897]; // max_bits=10
898
899const WMV2_TCOEF_INTER_1_CODES: &[(u32, u8, i32)] = &[
900    (0b00,  2, 2),
901    (0b010,  3, 4),
902    (0b011,  3, 3),
903    (0b1000,  4, 6),
904    (0b1001,  4, 258),
905    (0b10100,  5, 8),
906    (0b10101,  5, 514),
907    (0b10110,  5, 5),
908    (0b10111,  5, 259),
909    (0b110000,  6, 10),
910    (0b110001,  6, 12),
911    (0b110010,  6, 260),
912    (0b110011,  6, 770),
913    (0b110100,  6, 7),
914    (0b110101,  6, 515),
915    (0b1101100,  7, 14),
916    (0b1101101,  7, 16),
917    (0b1101110,  7, 1026),
918    (0b1101111,  7, 9),
919    (0b1110000,  7, 261),
920    (0b1110001,  7, 771),
921    (0b11100100,  8, 18),
922    (0b11100101,  8, 20),
923    (0b11100110,  8, 262),
924    (0b11100111,  8, 516),
925    (0b11101000,  8, 1282),
926    (0b11101001,  8, 11),
927    (0b11101010,  8, 1027),
928    (0b111010110,  9, 22),
929    (0b111010111,  9, 24),
930    (0b111011000,  9, 264),
931    (0b111011001,  9, 1538),
932    (0b111011010,  9, 1794),
933    (0b111011011,  9, 13),
934    (0b111011100,  9, 263),
935    (0b111011101,  9, 517),
936    (0b111011110,  9, 1283),
937    (0b1110111110, 10, 26),
938    (0b1110111111, 10, 28),
939    (0b1111000000, 10, 2050),
940    (0b1111000001, 10, 15),
941    (0b1111000010, 10, 1539),
942    (0b1111000011, 10, VLC_ESCAPE),
943]; // max_bits=10
944
945const WMV2_TCOEF_INTRA_0_CODES: &[(u32, u8, i32)] = &[
946    (0b000,  3, 2),
947    (0b0010,  4, 4),
948    (0b0011,  4, 258),
949    (0b0100,  4, 3),
950    (0b01010,  5, 6),
951    (0b01011,  5, 514),
952    (0b01100,  5, 5),
953    (0b01101,  5, 259),
954    (0b011100,  6, 8),
955    (0b011101,  6, 260),
956    (0b011110,  6, 770),
957    (0b011111,  6, 1026),
958    (0b100000,  6, 7),
959    (0b100001,  6, 515),
960    (0b1000100,  7, 10),
961    (0b1000101,  7, 12),
962    (0b1000110,  7, 262),
963    (0b1000111,  7, 516),
964    (0b1001000,  7, 1282),
965    (0b1001001,  7, 1538),
966    (0b1001010,  7, 9),
967    (0b1001011,  7, 261),
968    (0b1001100,  7, 771),
969    (0b1001101,  7, 1027),
970    (0b10011100,  8, 14),
971    (0b10011101,  8, 16),
972    (0b10011110,  8, 18),
973    (0b10011111,  8, 264),
974    (0b10100000,  8, 518),
975    (0b10100001,  8, 772),
976    (0b10100010,  8, 1794),
977    (0b10100011,  8, 2050),
978    (0b10100100,  8, 11),
979    (0b10100101,  8, 13),
980    (0b10100110,  8, 263),
981    (0b10100111,  8, 517),
982    (0b10101000,  8, 1283),
983    (0b10101001,  8, 1539),
984    (0b101010100,  9, 20),
985    (0b101010101,  9, 22),
986    (0b101010110,  9, 24),
987    (0b101010111,  9, 266),
988    (0b101011000,  9, 1028),
989    (0b101011001,  9, 1284),
990    (0b101011010,  9, 2306),
991    (0b101011011,  9, 2562),
992    (0b101011100,  9, 15),
993    (0b101011101,  9, 17),
994    (0b101011110,  9, 265),
995    (0b101011111,  9, 1795),
996    (0b101100000,  9, 2051),
997    (0b1011000010, 10, 26),
998    (0b1011000011, 10, 28),
999    (0b1011000100, 10, 30),
1000    (0b1011000101, 10, 2818),
1001    (0b1011000110, 10, 19),
1002    (0b1011000111, 10, 21),
1003    (0b1011001000, 10, 2307),
1004    (0b1011001001, 10, VLC_ESCAPE),
1005]; // max_bits=10
1006
1007const WMV2_TCOEF_INTRA_1_CODES: &[(u32, u8, i32)] = &[
1008    (0b00,  2, 2),
1009    (0b010,  3, 3),
1010    (0b0110,  4, 4),
1011    (0b0111,  4, 6),
1012    (0b1000,  4, 258),
1013    (0b10010,  5, 8),
1014    (0b10011,  5, 514),
1015    (0b10100,  5, 5),
1016    (0b10101,  5, 259),
1017    (0b101100,  6, 10),
1018    (0b101101,  6, 260),
1019    (0b101110,  6, 770),
1020    (0b101111,  6, 7),
1021    (0b110000,  6, 515),
1022    (0b1100010,  7, 12),
1023    (0b1100011,  7, 14),
1024    (0b1100100,  7, 1026),
1025    (0b1100101,  7, 9),
1026    (0b1100110,  7, 261),
1027    (0b1100111,  7, 771),
1028    (0b11010000,  8, 16),
1029    (0b11010001,  8, 262),
1030    (0b11010010,  8, 516),
1031    (0b11010011,  8, 1282),
1032    (0b11010100,  8, 11),
1033    (0b11010101,  8, 1027),
1034    (0b110101100,  9, 18),
1035    (0b110101101,  9, 20),
1036    (0b110101110,  9, 264),
1037    (0b110101111,  9, 1538),
1038    (0b110110000,  9, 1794),
1039    (0b110110001,  9, 13),
1040    (0b110110010,  9, 263),
1041    (0b110110011,  9, 517),
1042    (0b110110100,  9, 1283),
1043    (0b1101101010, 10, 22),
1044    (0b1101101011, 10, 24),
1045    (0b1101101100, 10, 2050),
1046    (0b1101101101, 10, 15),
1047    (0b1101101110, 10, 1539),
1048    (0b1101101111, 10, VLC_ESCAPE),
1049]; // max_bits=10
1050
1051// H.263 CBPY (luma CBP 4 blocks, symbol = 4-bit mask)
1052const WMV2_CBPY_CODES: &[(u32, u8, i32)] = &[
1053    (0b00,     2, 15),
1054    (0b0100,   4,  0),
1055    (0b0101,   4,  3),
1056    (0b0110,   4,  5),
1057    (0b0111,   4,  7),
1058    (0b1000,   4, 10),
1059    (0b1001,   4, 11),
1060    (0b1010,   4, 12),
1061    (0b1011,   4, 13),
1062    (0b1100,   4, 14),
1063    (0b11010,  5,  1),
1064    (0b11011,  5,  2),
1065    (0b11100,  5,  4),
1066    (0b11101,  5,  8),
1067    (0b111100, 6,  6),
1068    (0b111101, 6,  9),
1069]; // max_bits=6
1070
1071// CBPC P-frame (chroma CBP 2 blocks + MB-skip; sym=-1 means skipped MB)
1072const WMV2_CBPC_P_CODES: &[(u32, u8, i32)] = &[
1073    (0b0,      1,  0),
1074    (0b10,     2,  1),
1075    (0b110,    3,  2),
1076    (0b1110,   4,  3),
1077    (0b111100, 6, -1),
1078]; // max_bits=6
1079
1080pub fn wmv2_tcoef_inter_vlc(idx: usize) -> VlcTable {
1081    match idx & 1 {
1082        0 => VlcTable::build(WMV2_TCOEF_INTER_0_CODES, 10),
1083        _ => VlcTable::build(WMV2_TCOEF_INTER_1_CODES, 10),
1084    }
1085}
1086pub fn wmv2_tcoef_intra_vlc(idx: usize) -> VlcTable {
1087    match idx & 1 {
1088        0 => VlcTable::build(WMV2_TCOEF_INTRA_0_CODES, 10),
1089        _ => VlcTable::build(WMV2_TCOEF_INTRA_1_CODES, 10),
1090    }
1091}
1092pub fn wmv2_cbpy_vlc()   -> VlcTable { VlcTable::build(WMV2_CBPY_CODES,   6) }
1093pub fn wmv2_cbpc_p_vlc() -> VlcTable { VlcTable::build(WMV2_CBPC_P_CODES, 6) }