1use std::fmt;
5
6use crate::rbsp::{BitRead, BitReaderError};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum CavlcContext {
10 NC(u8),
11 ChromaDC,
12}
13
14#[derive(Debug)]
15pub enum CavlcError {
16 IoError(BitReaderError),
17 InvalidCode(&'static str),
18 OutOfRange { field: &'static str, value: i64 },
19}
20
21impl fmt::Display for CavlcError {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 match self {
24 CavlcError::IoError(e) => write!(f, "bitstream I/O: {e:?}"),
25 CavlcError::InvalidCode(ctx) => write!(f, "invalid VLC code: {ctx}"),
26 CavlcError::OutOfRange { field, value } => {
27 write!(f, "{field} out of range: {value}")
28 }
29 }
30 }
31}
32
33impl std::error::Error for CavlcError {}
34
35impl From<BitReaderError> for CavlcError {
36 fn from(e: BitReaderError) -> Self {
37 CavlcError::IoError(e)
38 }
39}
40
41type CoeffTokenTable = &'static [(u8, u16, u8, u8)];
42
43fn read_coeff_token_vlc<R: BitRead>(
44 r: &mut R,
45 table: CoeffTokenTable,
46 name: &'static str,
47) -> Result<(u8, u8), CavlcError> {
48 let mut accum: u16 = 0;
49 let mut bits_read: u8 = 0;
50 let mut table_idx = 0;
51
52 loop {
53 let bit = r.read_bit(name)?;
54 accum = (accum << 1) | (bit as u16);
55 bits_read += 1;
56
57 while table_idx < table.len() && table[table_idx].0 == bits_read {
58 let (_, code_val, tc, to) = table[table_idx];
59 if code_val == accum {
60 return Ok((tc, to));
61 }
62 table_idx += 1;
63 }
64
65 if table_idx >= table.len() || bits_read > 16 {
66 return Err(CavlcError::InvalidCode(name));
67 }
68 }
69}
70
71type ValueVlcTable = &'static [(u8, u16, u8)];
72
73fn read_value_vlc<R: BitRead>(
74 r: &mut R,
75 table: ValueVlcTable,
76 name: &'static str,
77) -> Result<u8, CavlcError> {
78 let mut accum: u16 = 0;
79 let mut bits_read: u8 = 0;
80 let mut table_idx = 0;
81
82 loop {
83 let bit = r.read_bit(name)?;
84 accum = (accum << 1) | (bit as u16);
85 bits_read += 1;
86
87 while table_idx < table.len() && table[table_idx].0 == bits_read {
88 let (_, code_val, val) = table[table_idx];
89 if code_val == accum {
90 return Ok(val);
91 }
92 table_idx += 1;
93 }
94
95 if table_idx >= table.len() || bits_read > 16 {
96 return Err(CavlcError::InvalidCode(name));
97 }
98 }
99}
100
101fn read_coeff_token<R: BitRead>(r: &mut R, nc: CavlcContext) -> Result<(u8, u8), CavlcError> {
102 match nc {
103 CavlcContext::NC(n) if n >= 8 => read_coeff_token_fixed6(r),
104 CavlcContext::NC(4..=7) => read_coeff_token_vlc(r, COEFF_TOKEN_4, "coeff_token (4<=nC<8)"),
105 CavlcContext::NC(2..=3) => read_coeff_token_vlc(r, COEFF_TOKEN_2, "coeff_token (2<=nC<4)"),
106 CavlcContext::NC(_) => read_coeff_token_vlc(r, COEFF_TOKEN_0, "coeff_token (nC<2)"),
107 CavlcContext::ChromaDC => {
108 read_coeff_token_vlc(r, COEFF_TOKEN_CHROMA_DC, "coeff_token (ChromaDC)")
109 }
110 }
111}
112
113fn read_coeff_token_fixed6<R: BitRead>(r: &mut R) -> Result<(u8, u8), CavlcError> {
114 let code: u8 = r.read::<6, u8>("coeff_token")?;
115 if code == 3 {
116 return Ok((0, 0));
117 }
118 let total_coeff = (code >> 2) + 1;
119 let trailing_ones = code & 3;
120 if trailing_ones > core::cmp::min(3, total_coeff) {
121 return Err(CavlcError::InvalidCode(
122 "coeff_token nC>=8: trailing_ones > total_coeff",
123 ));
124 }
125 Ok((total_coeff, trailing_ones))
126}
127
128#[rustfmt::skip]
130static COEFF_TOKEN_0: CoeffTokenTable = &[
131 ( 1, 0b1, 0, 0),
133 ( 2, 0b01, 1, 1),
134 ( 3, 0b001, 2, 2),
135 ( 5, 0b00011, 3, 3),
136 ( 6, 0b000101, 1, 0),
137 ( 6, 0b000100, 2, 1),
138 ( 6, 0b000011, 4, 3),
139 ( 7, 0b0000101, 3, 2),
140 ( 7, 0b0000100, 5, 3),
141 ( 8, 0b00000111, 2, 0),
142 ( 8, 0b00000110, 3, 1),
143 ( 8, 0b00000101, 4, 2),
144 ( 8, 0b00000100, 6, 3),
145 ( 9, 0b000000111, 3, 0),
146 ( 9, 0b000000110, 4, 1),
147 ( 9, 0b000000101, 5, 2),
148 ( 9, 0b000000100, 7, 3),
149 (10, 0b0000000111, 4, 0),
150 (10, 0b0000000110, 5, 1),
151 (10, 0b0000000101, 6, 2),
152 (10, 0b0000000100, 8, 3),
153 (11, 0b00000000111, 5, 0),
154 (11, 0b00000000110, 6, 1),
155 (11, 0b00000000101, 7, 2),
156 (11, 0b00000000100, 9, 3),
157 (13, 0b0000000001111, 6, 0),
158 (13, 0b0000000001110, 7, 1),
159 (13, 0b0000000001101, 8, 2),
160 (13, 0b0000000001100, 10, 3),
161 (13, 0b0000000001011, 7, 0),
162 (13, 0b0000000001010, 8, 1),
163 (13, 0b0000000001001, 9, 2),
164 (13, 0b0000000001000, 8, 0),
165 (14, 0b00000000001111, 9, 0),
166 (14, 0b00000000001110, 9, 1),
167 (14, 0b00000000001101, 10, 2),
168 (14, 0b00000000001100, 11, 3),
169 (14, 0b00000000001011, 10, 0),
170 (14, 0b00000000001010, 10, 1),
171 (14, 0b00000000001001, 11, 2),
172 (14, 0b00000000001000, 12, 3),
173 (15, 0b000000000001111, 11, 0),
174 (15, 0b000000000001110, 11, 1),
175 (15, 0b000000000001101, 12, 2),
176 (15, 0b000000000001100, 13, 3),
177 (15, 0b000000000001011, 12, 0),
178 (15, 0b000000000001010, 12, 1),
179 (15, 0b000000000001001, 13, 2),
180 (15, 0b000000000001000, 14, 3),
181 (15, 0b000000000000001, 13, 1),
182 (16, 0b0000000000001111, 13, 0),
183 (16, 0b0000000000001110, 14, 1),
184 (16, 0b0000000000001101, 14, 2),
185 (16, 0b0000000000001100, 15, 3),
186 (16, 0b0000000000001011, 14, 0),
187 (16, 0b0000000000001010, 15, 1),
188 (16, 0b0000000000001001, 15, 2),
189 (16, 0b0000000000001000, 16, 3),
190 (16, 0b0000000000000111, 15, 0),
191 (16, 0b0000000000000110, 16, 1),
192 (16, 0b0000000000000101, 16, 2),
193 (16, 0b0000000000000100, 16, 0),
194];
195
196#[rustfmt::skip]
198static COEFF_TOKEN_2: CoeffTokenTable = &[
199 ( 2, 0b11, 0, 0),
200 ( 2, 0b10, 1, 1),
201 ( 3, 0b011, 2, 2),
202 ( 4, 0b0101, 3, 3),
203 ( 4, 0b0100, 4, 3),
204 ( 5, 0b00111, 2, 1),
205 ( 5, 0b00110, 5, 3),
206 ( 6, 0b001011, 1, 0),
207 ( 6, 0b001010, 3, 1),
208 ( 6, 0b001001, 3, 2),
209 ( 6, 0b001000, 6, 3),
210 ( 6, 0b000111, 2, 0),
211 ( 6, 0b000110, 4, 1),
212 ( 6, 0b000101, 4, 2),
213 ( 6, 0b000100, 7, 3),
214 ( 7, 0b0000111, 3, 0),
215 ( 7, 0b0000110, 5, 1),
216 ( 7, 0b0000101, 5, 2),
217 ( 7, 0b0000100, 8, 3),
218 ( 8, 0b00000111, 4, 0),
219 ( 8, 0b00000110, 6, 1),
220 ( 8, 0b00000101, 6, 2),
221 ( 8, 0b00000100, 5, 0),
222 ( 9, 0b000000111, 6, 0),
223 ( 9, 0b000000110, 7, 1),
224 ( 9, 0b000000101, 7, 2),
225 ( 9, 0b000000100, 9, 3),
226 (11, 0b00000001111, 7, 0),
227 (11, 0b00000001110, 8, 1),
228 (11, 0b00000001101, 8, 2),
229 (11, 0b00000001100, 10, 3),
230 (11, 0b00000001011, 8, 0),
231 (11, 0b00000001010, 9, 1),
232 (11, 0b00000001001, 9, 2),
233 (11, 0b00000001000, 11, 3),
234 (12, 0b000000001111, 9, 0),
235 (12, 0b000000001110, 10, 1),
236 (12, 0b000000001101, 10, 2),
237 (12, 0b000000001100, 12, 3),
238 (12, 0b000000001011, 10, 0),
239 (12, 0b000000001010, 11, 1),
240 (12, 0b000000001001, 11, 2),
241 (12, 0b000000001000, 11, 0),
242 (13, 0b0000000001111, 12, 0),
243 (13, 0b0000000001110, 12, 1),
244 (13, 0b0000000001101, 12, 2),
245 (13, 0b0000000001100, 13, 3),
246 (13, 0b0000000001011, 13, 0),
247 (13, 0b0000000001010, 13, 1),
248 (13, 0b0000000001001, 13, 2),
249 (13, 0b0000000001000, 14, 3),
250 (13, 0b0000000000111, 14, 0),
251 (13, 0b0000000000110, 14, 2),
252 (13, 0b0000000000001, 15, 3),
253 (14, 0b00000000001011, 14, 1),
254 (14, 0b00000000001010, 15, 2),
255 (14, 0b00000000001001, 15, 0),
256 (14, 0b00000000001000, 15, 1),
257 (14, 0b00000000000111, 16, 0),
258 (14, 0b00000000000110, 16, 1),
259 (14, 0b00000000000101, 16, 2),
260 (14, 0b00000000000100, 16, 3),
261];
262
263#[rustfmt::skip]
265static COEFF_TOKEN_4: CoeffTokenTable = &[
266 ( 4, 0b1111, 0, 0),
267 ( 4, 0b1110, 1, 1),
268 ( 4, 0b1101, 2, 2),
269 ( 4, 0b1100, 3, 3),
270 ( 4, 0b1011, 4, 3),
271 ( 4, 0b1010, 5, 3),
272 ( 4, 0b1001, 6, 3),
273 ( 4, 0b1000, 7, 3),
274 ( 5, 0b01111, 2, 1),
275 ( 5, 0b01110, 3, 2),
276 ( 5, 0b01101, 8, 3),
277 ( 5, 0b01100, 3, 1),
278 ( 5, 0b01011, 4, 2),
279 ( 5, 0b01010, 4, 1),
280 ( 5, 0b01001, 5, 2),
281 ( 5, 0b01000, 5, 1),
282 ( 6, 0b001111, 1, 0),
283 ( 6, 0b001110, 6, 1),
284 ( 6, 0b001101, 6, 2),
285 ( 6, 0b001100, 9, 3),
286 ( 6, 0b001011, 2, 0),
287 ( 6, 0b001010, 7, 1),
288 ( 6, 0b001001, 7, 2),
289 ( 6, 0b001000, 3, 0),
290 ( 7, 0b0001111, 4, 0),
291 ( 7, 0b0001110, 8, 1),
292 ( 7, 0b0001101, 8, 2),
293 ( 7, 0b0001100, 10, 3),
294 ( 7, 0b0001011, 5, 0),
295 ( 7, 0b0001010, 9, 2),
296 ( 7, 0b0001001, 6, 0),
297 ( 7, 0b0001000, 7, 0),
298 ( 8, 0b00001111, 8, 0),
299 ( 8, 0b00001110, 9, 1),
300 ( 8, 0b00001101, 10, 2),
301 ( 8, 0b00001100, 11, 3),
302 ( 8, 0b00001011, 9, 0),
303 ( 8, 0b00001010, 10, 1),
304 ( 8, 0b00001001, 11, 2),
305 ( 8, 0b00001000, 12, 3),
306 ( 9, 0b000001111, 10, 0),
307 ( 9, 0b000001110, 11, 1),
308 ( 9, 0b000001101, 12, 2),
309 ( 9, 0b000001100, 13, 3),
310 ( 9, 0b000001011, 11, 0),
311 ( 9, 0b000001010, 12, 1),
312 ( 9, 0b000001001, 13, 2),
313 ( 9, 0b000001000, 12, 0),
314 ( 9, 0b000000111, 13, 1),
315 (10, 0b0000001101, 13, 0),
316 (10, 0b0000001100, 14, 1),
317 (10, 0b0000001011, 14, 2),
318 (10, 0b0000001010, 14, 3),
319 (10, 0b0000001001, 14, 0),
320 (10, 0b0000001000, 15, 1),
321 (10, 0b0000000111, 15, 2),
322 (10, 0b0000000110, 15, 3),
323 (10, 0b0000000101, 15, 0),
324 (10, 0b0000000100, 16, 1),
325 (10, 0b0000000011, 16, 2),
326 (10, 0b0000000010, 16, 3),
327 (10, 0b0000000001, 16, 0),
328];
329
330#[rustfmt::skip]
332static COEFF_TOKEN_CHROMA_DC: CoeffTokenTable = &[
333 ( 1, 0b1, 1, 1),
334 ( 2, 0b01, 0, 0),
335 ( 3, 0b001, 2, 2),
336 ( 6, 0b000111, 1, 0),
337 ( 6, 0b000110, 2, 1),
338 ( 6, 0b000101, 3, 3),
339 ( 6, 0b000100, 2, 0),
340 ( 6, 0b000011, 3, 0),
341 ( 6, 0b000010, 4, 0),
342 ( 7, 0b0000011, 3, 1),
343 ( 7, 0b0000010, 3, 2),
344 ( 7, 0b0000000, 4, 3),
345 ( 8, 0b00000011, 4, 1),
346 ( 8, 0b00000010, 4, 2),
347];
348
349fn read_level_prefix<R: BitRead>(r: &mut R) -> Result<u32, CavlcError> {
350 let mut prefix = 0u32;
351 loop {
352 if r.read_bit("level_prefix")? {
353 return Ok(prefix);
354 }
355 prefix += 1;
356 if prefix > 32 {
357 return Err(CavlcError::InvalidCode("level_prefix exceeds 32"));
358 }
359 }
360}
361
362fn read_level<R: BitRead>(r: &mut R, suffix_length: u32) -> Result<i32, CavlcError> {
363 let level_prefix = read_level_prefix(r)?;
364
365 let level_suffix_size = if level_prefix == 14 && suffix_length == 0 {
366 4
367 } else if level_prefix >= 15 {
368 level_prefix - 3
369 } else {
370 suffix_length
371 };
372
373 let level_suffix: u32 = if level_suffix_size > 0 {
374 r.read_var(level_suffix_size, "level_suffix")?
375 } else {
376 0
377 };
378
379 let level_code = {
380 let prefix_part = core::cmp::min(15, level_prefix) << suffix_length;
381 let mut code = prefix_part + level_suffix;
382 if level_prefix >= 15 && suffix_length == 0 {
383 code += 15;
384 }
385 if level_prefix >= 16 {
386 code += (1u32 << (level_prefix - 3)) - 4096;
387 }
388 code
389 };
390
391 let level_val = if level_code & 1 == 0 {
392 (level_code as i32 >> 1) + 1
393 } else {
394 -(level_code as i32 >> 1) - 1
395 };
396
397 Ok(level_val)
398}
399
400fn update_suffix_length(suffix_length: &mut u32, level_val: i32) {
401 let abs_level = level_val.unsigned_abs();
402 if *suffix_length == 0 {
403 *suffix_length = 1;
404 }
405 if abs_level > (3u32 << (*suffix_length - 1)) && *suffix_length < 6 {
406 *suffix_length += 1;
407 }
408}
409
410#[rustfmt::skip]
411static TOTAL_ZEROS_1: ValueVlcTable = &[
412 (1, 0b1, 0),
413 (3, 0b011, 1),
414 (3, 0b010, 2),
415 (4, 0b0011, 3),
416 (4, 0b0010, 4),
417 (5, 0b00011, 5),
418 (5, 0b00010, 6),
419 (6, 0b000011, 7),
420 (6, 0b000010, 8),
421 (7, 0b0000011, 9),
422 (7, 0b0000010, 10),
423 (8, 0b00000011, 11),
424 (8, 0b00000010, 12),
425 (9, 0b000000011, 13),
426 (9, 0b000000010, 14),
427 (9, 0b000000001, 15),
428];
429
430#[rustfmt::skip]
431static TOTAL_ZEROS_2: ValueVlcTable = &[
432 (3, 0b111, 0),
433 (3, 0b110, 1),
434 (3, 0b101, 2),
435 (3, 0b100, 3),
436 (3, 0b011, 4),
437 (4, 0b0101, 5),
438 (4, 0b0100, 6),
439 (4, 0b0011, 7),
440 (4, 0b0010, 8),
441 (5, 0b00011, 9),
442 (5, 0b00010, 10),
443 (6, 0b000011, 11),
444 (6, 0b000010, 12),
445 (6, 0b000001, 13),
446 (6, 0b000000, 14),
447];
448
449#[rustfmt::skip]
450static TOTAL_ZEROS_3: ValueVlcTable = &[
451 (3, 0b111, 1),
452 (3, 0b110, 2),
453 (3, 0b101, 3),
454 (3, 0b100, 6),
455 (3, 0b011, 7),
456 (4, 0b0101, 0),
457 (4, 0b0100, 4),
458 (4, 0b0011, 5),
459 (4, 0b0010, 8),
460 (5, 0b00011, 9),
461 (5, 0b00010, 10),
462 (5, 0b00001, 12),
463 (6, 0b000001, 11),
464 (6, 0b000000, 13),
465];
466
467#[rustfmt::skip]
468static TOTAL_ZEROS_4: ValueVlcTable = &[
469 (3, 0b111, 1),
470 (3, 0b110, 4),
471 (3, 0b101, 5),
472 (3, 0b100, 6),
473 (3, 0b011, 8),
474 (4, 0b0101, 2),
475 (4, 0b0100, 3),
476 (4, 0b0011, 7),
477 (4, 0b0010, 9),
478 (5, 0b00011, 0),
479 (5, 0b00010, 10),
480 (5, 0b00001, 11),
481 (5, 0b00000, 12),
482];
483
484#[rustfmt::skip]
485static TOTAL_ZEROS_5: ValueVlcTable = &[
486 (3, 0b111, 3),
487 (3, 0b110, 4),
488 (3, 0b101, 5),
489 (3, 0b100, 6),
490 (3, 0b011, 7),
491 (4, 0b0101, 0),
492 (4, 0b0100, 1),
493 (4, 0b0011, 2),
494 (4, 0b0010, 8),
495 (4, 0b0001, 10),
496 (5, 0b00001, 9),
497 (5, 0b00000, 11),
498];
499
500#[rustfmt::skip]
501static TOTAL_ZEROS_6: ValueVlcTable = &[
502 (3, 0b111, 2),
503 (3, 0b110, 3),
504 (3, 0b101, 4),
505 (3, 0b100, 5),
506 (3, 0b011, 6),
507 (3, 0b010, 7),
508 (3, 0b001, 9),
509 (4, 0b0001, 8),
510 (5, 0b00001, 1),
511 (6, 0b000001, 0),
512 (6, 0b000000, 10),
513];
514
515#[rustfmt::skip]
516static TOTAL_ZEROS_7: ValueVlcTable = &[
517 (2, 0b11, 5),
518 (3, 0b101, 2),
519 (3, 0b100, 3),
520 (3, 0b011, 4),
521 (3, 0b010, 6),
522 (3, 0b001, 8),
523 (4, 0b0001, 7),
524 (5, 0b00001, 1),
525 (6, 0b000001, 0),
526 (6, 0b000000, 9),
527];
528
529#[rustfmt::skip]
530static TOTAL_ZEROS_8: ValueVlcTable = &[
531 (2, 0b11, 4),
532 (2, 0b10, 5),
533 (3, 0b011, 3),
534 (3, 0b010, 6),
535 (3, 0b001, 7),
536 (4, 0b0001, 1),
537 (5, 0b00001, 2),
538 (6, 0b000001, 0),
539 (6, 0b000000, 8),
540];
541
542#[rustfmt::skip]
543static TOTAL_ZEROS_9: ValueVlcTable = &[
544 (2, 0b11, 3),
545 (2, 0b10, 4),
546 (2, 0b01, 6),
547 (3, 0b001, 5),
548 (4, 0b0001, 2),
549 (5, 0b00001, 7),
550 (6, 0b000001, 0),
551 (6, 0b000000, 1),
552];
553
554#[rustfmt::skip]
555static TOTAL_ZEROS_10: ValueVlcTable = &[
556 (2, 0b11, 3),
557 (2, 0b10, 4),
558 (2, 0b01, 5),
559 (3, 0b001, 2),
560 (4, 0b0001, 6),
561 (5, 0b00001, 0),
562 (5, 0b00000, 1),
563];
564
565#[rustfmt::skip]
566static TOTAL_ZEROS_11: ValueVlcTable = &[
567 (1, 0b1, 4),
568 (3, 0b011, 5),
569 (3, 0b010, 3),
570 (3, 0b001, 2),
571 (4, 0b0001, 1),
572 (4, 0b0000, 0),
573];
574
575#[rustfmt::skip]
576static TOTAL_ZEROS_12: ValueVlcTable = &[
577 (1, 0b1, 3),
578 (2, 0b01, 2),
579 (3, 0b001, 4),
580 (4, 0b0001, 1),
581 (4, 0b0000, 0),
582];
583
584#[rustfmt::skip]
585static TOTAL_ZEROS_13: ValueVlcTable = &[
586 (1, 0b1, 2),
587 (2, 0b01, 3),
588 (3, 0b001, 1),
589 (3, 0b000, 0),
590];
591
592#[rustfmt::skip]
593static TOTAL_ZEROS_14: ValueVlcTable = &[
594 (1, 0b1, 2),
595 (2, 0b01, 1),
596 (2, 0b00, 0),
597];
598
599#[rustfmt::skip]
600static TOTAL_ZEROS_15: ValueVlcTable = &[
601 (1, 0b1, 1),
602 (1, 0b0, 0),
603];
604
605fn total_zeros_table_16(total_coeff: u8) -> Result<ValueVlcTable, CavlcError> {
606 match total_coeff {
607 1 => Ok(TOTAL_ZEROS_1),
608 2 => Ok(TOTAL_ZEROS_2),
609 3 => Ok(TOTAL_ZEROS_3),
610 4 => Ok(TOTAL_ZEROS_4),
611 5 => Ok(TOTAL_ZEROS_5),
612 6 => Ok(TOTAL_ZEROS_6),
613 7 => Ok(TOTAL_ZEROS_7),
614 8 => Ok(TOTAL_ZEROS_8),
615 9 => Ok(TOTAL_ZEROS_9),
616 10 => Ok(TOTAL_ZEROS_10),
617 11 => Ok(TOTAL_ZEROS_11),
618 12 => Ok(TOTAL_ZEROS_12),
619 13 => Ok(TOTAL_ZEROS_13),
620 14 => Ok(TOTAL_ZEROS_14),
621 15 => Ok(TOTAL_ZEROS_15),
622 _ => Err(CavlcError::OutOfRange {
623 field: "total_coeff for total_zeros",
624 value: total_coeff as i64,
625 }),
626 }
627}
628
629#[rustfmt::skip]
632static TOTAL_ZEROS_CHROMA_DC_1: ValueVlcTable = &[
633 (1, 0b1, 0),
634 (2, 0b01, 1),
635 (3, 0b001, 2),
636 (3, 0b000, 3),
637];
638
639#[rustfmt::skip]
640static TOTAL_ZEROS_CHROMA_DC_2: ValueVlcTable = &[
641 (1, 0b1, 0),
642 (2, 0b01, 1),
643 (2, 0b00, 2),
644];
645
646#[rustfmt::skip]
647static TOTAL_ZEROS_CHROMA_DC_3: ValueVlcTable = &[
648 (1, 0b1, 0),
649 (1, 0b0, 1),
650];
651
652fn total_zeros_table_4(total_coeff: u8) -> Result<ValueVlcTable, CavlcError> {
653 match total_coeff {
654 1 => Ok(TOTAL_ZEROS_CHROMA_DC_1),
655 2 => Ok(TOTAL_ZEROS_CHROMA_DC_2),
656 3 => Ok(TOTAL_ZEROS_CHROMA_DC_3),
657 _ => Err(CavlcError::OutOfRange {
658 field: "total_coeff for chroma_dc total_zeros",
659 value: total_coeff as i64,
660 }),
661 }
662}
663
664fn read_total_zeros<R: BitRead>(
665 r: &mut R,
666 total_coeff: u8,
667 max_num_coeff: usize,
668) -> Result<u8, CavlcError> {
669 let table = if max_num_coeff == 4 {
670 total_zeros_table_4(total_coeff)?
671 } else {
672 total_zeros_table_16(total_coeff)?
673 };
674 read_value_vlc(r, table, "total_zeros")
675}
676
677#[rustfmt::skip]
680static RUN_BEFORE_1: ValueVlcTable = &[
681 (1, 0b1, 0),
682 (1, 0b0, 1),
683];
684
685#[rustfmt::skip]
686static RUN_BEFORE_2: ValueVlcTable = &[
687 (1, 0b1, 0),
688 (2, 0b01, 1),
689 (2, 0b00, 2),
690];
691
692#[rustfmt::skip]
693static RUN_BEFORE_3: ValueVlcTable = &[
694 (2, 0b11, 0),
695 (2, 0b10, 1),
696 (2, 0b01, 2),
697 (2, 0b00, 3),
698];
699
700#[rustfmt::skip]
701static RUN_BEFORE_4: ValueVlcTable = &[
702 (2, 0b11, 0),
703 (2, 0b10, 1),
704 (2, 0b01, 2),
705 (3, 0b001, 3),
706 (3, 0b000, 4),
707];
708
709#[rustfmt::skip]
710static RUN_BEFORE_5: ValueVlcTable = &[
711 (2, 0b11, 0),
712 (2, 0b10, 1),
713 (3, 0b011, 2),
714 (3, 0b010, 3),
715 (3, 0b001, 4),
716 (3, 0b000, 5),
717];
718
719#[rustfmt::skip]
721static RUN_BEFORE_6: ValueVlcTable = &[
722 (2, 0b11, 0),
723 (3, 0b101, 5),
724 (3, 0b100, 6),
725 (3, 0b011, 3),
726 (3, 0b010, 4),
727 (3, 0b001, 2),
728 (3, 0b000, 1),
729];
730
731#[rustfmt::skip]
733static RUN_BEFORE_GT6: ValueVlcTable = &[
734 (3, 0b111, 0),
735 (3, 0b110, 1),
736 (3, 0b101, 2),
737 (3, 0b100, 3),
738 (3, 0b011, 4),
739 (3, 0b010, 5),
740 (3, 0b001, 6),
741 (4, 0b0001, 7),
742 (5, 0b00001, 8),
743 (6, 0b000001, 9),
744 (7, 0b0000001, 10),
745 (8, 0b00000001, 11),
746 (9, 0b000000001, 12),
747 (10, 0b0000000001, 13),
748 (11, 0b00000000001, 14),
749];
750
751fn read_run_before<R: BitRead>(r: &mut R, zeros_left: u8) -> Result<u8, CavlcError> {
752 if zeros_left == 0 {
753 return Ok(0);
754 }
755
756 let table: ValueVlcTable = match zeros_left {
757 1 => RUN_BEFORE_1,
758 2 => RUN_BEFORE_2,
759 3 => RUN_BEFORE_3,
760 4 => RUN_BEFORE_4,
761 5 => RUN_BEFORE_5,
762 6 => RUN_BEFORE_6,
763 _ => RUN_BEFORE_GT6,
764 };
765 read_value_vlc(r, table, "run_before")
766}
767
768pub(crate) fn residual_block_cavlc<R: BitRead>(
769 r: &mut R,
770 coeff_level: &mut [i32],
771 start_idx: usize,
772 end_idx: usize,
773 max_num_coeff: usize,
774 nc: CavlcContext,
775) -> Result<u8, CavlcError> {
776 for c in coeff_level[start_idx..=end_idx].iter_mut() {
778 *c = 0;
779 }
780
781 let (total_coeff, trailing_ones) = read_coeff_token(r, nc)?;
782
783 if total_coeff == 0 {
784 return Ok(0);
785 }
786
787 if total_coeff as usize > max_num_coeff {
788 return Err(CavlcError::OutOfRange {
789 field: "TotalCoeff",
790 value: total_coeff as i64,
791 });
792 }
793
794 let mut levels = [0i32; 16];
796
797 for item in levels.iter_mut().take(trailing_ones as usize) {
798 let negative = r.read_bit("trailing_ones_sign_flag")?;
799 *item = if negative { -1 } else { 1 };
800 }
801
802 let remaining = total_coeff as usize - trailing_ones as usize;
803
804 let mut suffix_length: u32 = if total_coeff > 10 && trailing_ones < 3 {
805 1
806 } else {
807 0
808 };
809
810 let level_start = trailing_ones as usize;
811 for i in 0..remaining {
812 let mut level_val = read_level(r, suffix_length)?;
813
814 if i == 0 && trailing_ones < 3 {
815 if level_val > 0 {
816 level_val += 1;
817 } else {
818 level_val -= 1;
819 }
820 }
821
822 levels[level_start + i] = level_val;
823
824 update_suffix_length(&mut suffix_length, level_val);
825 }
826
827 let total_zeros = if (total_coeff as usize) < max_num_coeff {
828 read_total_zeros(r, total_coeff, max_num_coeff)?
829 } else {
830 0
831 };
832 if (total_coeff as usize) + (total_zeros as usize) > max_num_coeff {
833 return Err(CavlcError::OutOfRange {
834 field: "total_coeff + total_zeros exceeds max_num_coeff",
835 value: (total_coeff as i64) + (total_zeros as i64),
836 });
837 }
838
839 let mut runs = [0u8; 16];
840 let mut zeros_left = total_zeros;
841
842 for item in runs.iter_mut().take(total_coeff as usize - 1) {
843 if zeros_left > 0 {
844 *item = read_run_before(r, zeros_left)?;
845 zeros_left = zeros_left
846 .checked_sub(*item)
847 .ok_or(CavlcError::OutOfRange {
848 field: "zeros_left underflow in run_before",
849 value: -(*item as i64),
850 })?;
851 }
852 }
853 runs[total_coeff as usize - 1] = zeros_left;
855
856 let mut coeff_idx = (total_coeff as usize + total_zeros as usize)
857 .checked_sub(1)
858 .ok_or(CavlcError::OutOfRange {
859 field: "coefficient position",
860 value: 0,
861 })?;
862
863 for i in 0..total_coeff as usize {
864 let pos = start_idx + coeff_idx;
865 if pos > end_idx {
866 return Err(CavlcError::OutOfRange {
867 field: "coefficient position exceeds end_idx",
868 value: pos as i64,
869 });
870 }
871 coeff_level[pos] = levels[i];
872
873 if i < total_coeff as usize - 1 {
874 coeff_idx =
875 coeff_idx
876 .checked_sub(1 + runs[i] as usize)
877 .ok_or(CavlcError::OutOfRange {
878 field: "coeff_idx underflow",
879 value: -(1i64),
880 })?;
881 }
882 }
883 Ok(total_coeff)
884}
885
886#[cfg(test)]
887mod tests {
888 use super::*;
889
890 fn check_prefix_free_coeff_token(table: CoeffTokenTable, name: &str) {
891 for i in 0..table.len() {
892 for j in (i + 1)..table.len() {
893 let (len_a, bits_a, tc_a, to_a) = table[i];
894 let (len_b, bits_b, tc_b, to_b) = table[j];
895 if len_a == len_b {
896 assert_ne!(
898 bits_a, bits_b,
899 "{name}: duplicate code at entries {i} (TC={tc_a},TO={to_a}) and {j} (TC={tc_b},TO={to_b}), len={len_a} bits={bits_a:#b}"
900 );
901 } else {
902 let (short_len, short_bits, long_len, long_bits) = if len_a < len_b {
904 (len_a, bits_a, len_b, bits_b)
905 } else {
906 (len_b, bits_b, len_a, bits_a)
907 };
908 let shifted = long_bits >> (long_len - short_len);
909 assert_ne!(
910 shifted, short_bits,
911 "{name}: prefix collision between entry {i} (len={len_a},bits={bits_a:#b},TC={tc_a},TO={to_a}) and entry {j} (len={len_b},bits={bits_b:#b},TC={tc_b},TO={to_b})"
912 );
913 }
914 }
915 }
916 }
917
918 fn check_coeff_token_coverage(table: CoeffTokenTable, max_num_coeff: u8, name: &str) {
919 let mut seen_pairs = std::collections::HashSet::new();
920 let mut seen_codes = std::collections::HashSet::new();
921 for (idx, &(len, bits, tc, to)) in table.iter().enumerate() {
922 assert!(len > 0, "{}[{}]: zero-length code", name, idx);
923 assert!(
924 (bits as u32) < (1u32 << len),
925 "{}[{}]: bits {:#b} don't fit in {} bits",
926 name,
927 idx,
928 bits,
929 len
930 );
931 assert!(
932 to <= tc.min(3),
933 "{}[{}]: TO={} > min(3, TC={})",
934 name,
935 idx,
936 to,
937 tc
938 );
939 assert!(
940 tc <= max_num_coeff,
941 "{}[{}]: TC={} > max={}",
942 name,
943 idx,
944 tc,
945 max_num_coeff
946 );
947 assert!(
948 seen_pairs.insert((tc, to)),
949 "{}[{}]: duplicate (TC={}, TO={})",
950 name,
951 idx,
952 tc,
953 to
954 );
955 assert!(
956 seen_codes.insert((len, bits)),
957 "{}[{}]: duplicate code (len={}, bits={:#b})",
958 name,
959 idx,
960 len,
961 bits
962 );
963 }
964 for tc in 0..=max_num_coeff {
966 for to in 0..=tc.min(3) {
967 assert!(
968 seen_pairs.contains(&(tc, to)),
969 "{}: missing (TC={}, TO={})",
970 name,
971 tc,
972 to
973 );
974 }
975 }
976 }
977
978 #[test]
979 fn coeff_token_tables_are_prefix_free() {
980 check_prefix_free_coeff_token(COEFF_TOKEN_0, "COEFF_TOKEN_0");
981 check_prefix_free_coeff_token(COEFF_TOKEN_2, "COEFF_TOKEN_2");
982 check_prefix_free_coeff_token(COEFF_TOKEN_4, "COEFF_TOKEN_4");
983 check_prefix_free_coeff_token(COEFF_TOKEN_CHROMA_DC, "COEFF_TOKEN_CHROMA_DC");
984 }
985
986 #[test]
987 fn coeff_token_0_complete_coverage() {
988 check_coeff_token_coverage(COEFF_TOKEN_0, 16, "COEFF_TOKEN_0");
989 }
990
991 #[test]
992 fn coeff_token_2_complete_coverage() {
993 check_coeff_token_coverage(COEFF_TOKEN_2, 16, "COEFF_TOKEN_2");
994 }
995
996 #[test]
997 fn coeff_token_4_complete_coverage() {
998 check_coeff_token_coverage(COEFF_TOKEN_4, 16, "COEFF_TOKEN_4");
999 }
1000
1001 #[test]
1002 fn coeff_token_chroma_dc_complete_coverage() {
1003 check_coeff_token_coverage(COEFF_TOKEN_CHROMA_DC, 4, "COEFF_TOKEN_CHROMA_DC");
1004 }
1005
1006 fn check_prefix_free_value_vlc(table: ValueVlcTable, name: &str) {
1007 for i in 0..table.len() {
1008 for j in (i + 1)..table.len() {
1009 let (len_a, bits_a, val_a) = table[i];
1010 let (len_b, bits_b, val_b) = table[j];
1011 if len_a == len_b {
1012 assert_ne!(
1013 bits_a, bits_b,
1014 "{name}: duplicate code at entries {i} (val={val_a}) and {j} (val={val_b}), len={len_a} bits={bits_a:#b}"
1015 );
1016 } else {
1017 let (short_len, short_bits, long_len, long_bits) = if len_a < len_b {
1018 (len_a, bits_a, len_b, bits_b)
1019 } else {
1020 (len_b, bits_b, len_a, bits_a)
1021 };
1022 let shifted = long_bits >> (long_len - short_len);
1023 assert_ne!(
1024 shifted, short_bits,
1025 "{name}: prefix collision between entry {i} (len={len_a},bits={bits_a:#b},val={val_a}) and entry {j} (len={len_b},bits={bits_b:#b},val={val_b})"
1026 );
1027 }
1028 }
1029 }
1030 }
1031
1032 fn check_value_vlc_coverage(table: ValueVlcTable, max_val: u8, name: &str) {
1033 let mut seen_vals = std::collections::HashSet::new();
1034 let mut seen_codes = std::collections::HashSet::new();
1035 for (idx, &(len, bits, val)) in table.iter().enumerate() {
1036 assert!(len > 0, "{}[{}]: zero-length code", name, idx);
1037 assert!(
1038 (bits as u32) < (1u32 << len),
1039 "{}[{}]: bits {:#b} don't fit in {} bits",
1040 name,
1041 idx,
1042 bits,
1043 len
1044 );
1045 assert!(
1046 val <= max_val,
1047 "{}[{}]: val={} > max={}",
1048 name,
1049 idx,
1050 val,
1051 max_val
1052 );
1053 assert!(
1054 seen_vals.insert(val),
1055 "{}[{}]: duplicate value {}",
1056 name,
1057 idx,
1058 val
1059 );
1060 assert!(
1061 seen_codes.insert((len, bits)),
1062 "{}[{}]: duplicate code (len={}, bits={:#b})",
1063 name,
1064 idx,
1065 len,
1066 bits
1067 );
1068 }
1069 for v in 0..=max_val {
1070 assert!(seen_vals.contains(&v), "{}: missing value {}", name, v);
1071 }
1072 }
1073
1074 #[test]
1075 fn total_zeros_luma_tables_complete_and_prefix_free() {
1076 let tables: &[(ValueVlcTable, u8, &str)] = &[
1077 (TOTAL_ZEROS_1, 15, "TOTAL_ZEROS_1"),
1078 (TOTAL_ZEROS_2, 14, "TOTAL_ZEROS_2"),
1079 (TOTAL_ZEROS_3, 13, "TOTAL_ZEROS_3"),
1080 (TOTAL_ZEROS_4, 12, "TOTAL_ZEROS_4"),
1081 (TOTAL_ZEROS_5, 11, "TOTAL_ZEROS_5"),
1082 (TOTAL_ZEROS_6, 10, "TOTAL_ZEROS_6"),
1083 (TOTAL_ZEROS_7, 9, "TOTAL_ZEROS_7"),
1084 (TOTAL_ZEROS_8, 8, "TOTAL_ZEROS_8"),
1085 (TOTAL_ZEROS_9, 7, "TOTAL_ZEROS_9"),
1086 (TOTAL_ZEROS_10, 6, "TOTAL_ZEROS_10"),
1087 (TOTAL_ZEROS_11, 5, "TOTAL_ZEROS_11"),
1088 (TOTAL_ZEROS_12, 4, "TOTAL_ZEROS_12"),
1089 (TOTAL_ZEROS_13, 3, "TOTAL_ZEROS_13"),
1090 (TOTAL_ZEROS_14, 2, "TOTAL_ZEROS_14"),
1091 (TOTAL_ZEROS_15, 1, "TOTAL_ZEROS_15"),
1092 ];
1093 for &(table, max_val, name) in tables {
1094 check_prefix_free_value_vlc(table, name);
1095 check_value_vlc_coverage(table, max_val, name);
1096 }
1097 }
1098
1099 #[test]
1100 fn total_zeros_chroma_dc_tables_complete_and_prefix_free() {
1101 let tables: &[(ValueVlcTable, u8, &str)] = &[
1102 (TOTAL_ZEROS_CHROMA_DC_1, 3, "TOTAL_ZEROS_CHROMA_DC_1"),
1103 (TOTAL_ZEROS_CHROMA_DC_2, 2, "TOTAL_ZEROS_CHROMA_DC_2"),
1104 (TOTAL_ZEROS_CHROMA_DC_3, 1, "TOTAL_ZEROS_CHROMA_DC_3"),
1105 ];
1106 for &(table, max_val, name) in tables {
1107 check_prefix_free_value_vlc(table, name);
1108 check_value_vlc_coverage(table, max_val, name);
1109 }
1110 }
1111
1112 #[test]
1113 fn run_before_tables_complete_and_prefix_free() {
1114 let tables: &[(ValueVlcTable, u8, &str)] = &[
1115 (RUN_BEFORE_1, 1, "RUN_BEFORE_1"),
1116 (RUN_BEFORE_2, 2, "RUN_BEFORE_2"),
1117 (RUN_BEFORE_3, 3, "RUN_BEFORE_3"),
1118 (RUN_BEFORE_4, 4, "RUN_BEFORE_4"),
1119 (RUN_BEFORE_5, 5, "RUN_BEFORE_5"),
1120 (RUN_BEFORE_6, 6, "RUN_BEFORE_6"),
1121 (RUN_BEFORE_GT6, 14, "RUN_BEFORE_GT6"),
1122 ];
1123 for &(table, max_val, name) in tables {
1124 check_prefix_free_value_vlc(table, name);
1125 check_value_vlc_coverage(table, max_val, name);
1126 }
1127 }
1128
1129 #[test]
1130 fn coeff_token_tables_sorted_by_length() {
1131 for (table, name) in [
1132 (COEFF_TOKEN_0, "COEFF_TOKEN_0"),
1133 (COEFF_TOKEN_2, "COEFF_TOKEN_2"),
1134 (COEFF_TOKEN_4, "COEFF_TOKEN_4"),
1135 (COEFF_TOKEN_CHROMA_DC, "COEFF_TOKEN_CHROMA_DC"),
1136 ] {
1137 for i in 1..table.len() {
1138 assert!(
1139 table[i].0 >= table[i - 1].0,
1140 "{name}: not sorted by length at index {i}: {} < {}",
1141 table[i].0,
1142 table[i - 1].0
1143 );
1144 }
1145 }
1146 }
1147
1148 #[test]
1149 fn value_vlc_tables_sorted_by_length() {
1150 let tables: &[(ValueVlcTable, &str)] = &[
1151 (TOTAL_ZEROS_1, "TOTAL_ZEROS_1"),
1152 (TOTAL_ZEROS_2, "TOTAL_ZEROS_2"),
1153 (TOTAL_ZEROS_3, "TOTAL_ZEROS_3"),
1154 (TOTAL_ZEROS_4, "TOTAL_ZEROS_4"),
1155 (TOTAL_ZEROS_5, "TOTAL_ZEROS_5"),
1156 (TOTAL_ZEROS_6, "TOTAL_ZEROS_6"),
1157 (TOTAL_ZEROS_7, "TOTAL_ZEROS_7"),
1158 (TOTAL_ZEROS_8, "TOTAL_ZEROS_8"),
1159 (TOTAL_ZEROS_9, "TOTAL_ZEROS_9"),
1160 (TOTAL_ZEROS_10, "TOTAL_ZEROS_10"),
1161 (TOTAL_ZEROS_11, "TOTAL_ZEROS_11"),
1162 (TOTAL_ZEROS_12, "TOTAL_ZEROS_12"),
1163 (TOTAL_ZEROS_13, "TOTAL_ZEROS_13"),
1164 (TOTAL_ZEROS_14, "TOTAL_ZEROS_14"),
1165 (TOTAL_ZEROS_15, "TOTAL_ZEROS_15"),
1166 (TOTAL_ZEROS_CHROMA_DC_1, "TOTAL_ZEROS_CHROMA_DC_1"),
1167 (TOTAL_ZEROS_CHROMA_DC_2, "TOTAL_ZEROS_CHROMA_DC_2"),
1168 (TOTAL_ZEROS_CHROMA_DC_3, "TOTAL_ZEROS_CHROMA_DC_3"),
1169 (RUN_BEFORE_1, "RUN_BEFORE_1"),
1170 (RUN_BEFORE_2, "RUN_BEFORE_2"),
1171 (RUN_BEFORE_3, "RUN_BEFORE_3"),
1172 (RUN_BEFORE_4, "RUN_BEFORE_4"),
1173 (RUN_BEFORE_5, "RUN_BEFORE_5"),
1174 (RUN_BEFORE_6, "RUN_BEFORE_6"),
1175 (RUN_BEFORE_GT6, "RUN_BEFORE_GT6"),
1176 ];
1177 for &(table, name) in tables {
1178 for i in 1..table.len() {
1179 assert!(
1180 table[i].0 >= table[i - 1].0,
1181 "{name}: not sorted by length at index {i}: {} < {}",
1182 table[i].0,
1183 table[i - 1].0
1184 );
1185 }
1186 }
1187 }
1188}