1#![allow(dead_code, clippy::needless_range_loop)]
8
9use super::h264::{
10 dequant_4x4, extract_rbsp, intra_16x16_predict, intra_4x4_predict, intra_chroma_predict,
11 inverse_transform_4x4, parse_avcc, parse_pps, parse_sps, split_annexb, split_avcc, BitReader,
12 Pps, Sps, NORM_ADJUST_4X4,
13};
14use alloc::vec::Vec;
15
16const ZIGZAG_4X4: [usize; 16] = [0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15];
18
19const LUMA_4X4_BLOCK_XY: [(usize, usize); 16] = [
22 (0, 0),
23 (4, 0),
24 (0, 4),
25 (4, 4),
26 (8, 0),
27 (12, 0),
28 (8, 4),
29 (12, 4),
30 (0, 8),
31 (4, 8),
32 (0, 12),
33 (4, 12),
34 (8, 8),
35 (12, 8),
36 (8, 12),
37 (12, 12),
38];
39
40fn clip1(v: i32) -> i32 {
41 v.clamp(0, 255)
42}
43
44type TokEntry = (u8, u16, u8, u8);
49
50const COEFF_TOKEN_0: &[TokEntry] = &[
52 (1, 0b1, 0, 0),
53 (6, 0b000101, 1, 0),
54 (2, 0b01, 1, 1),
55 (8, 0b00000111, 2, 0),
56 (6, 0b000100, 2, 1),
57 (3, 0b001, 2, 2),
58 (9, 0b000000111, 3, 0),
59 (8, 0b00000110, 3, 1),
60 (7, 0b0000101, 3, 2),
61 (5, 0b00011, 3, 3),
62 (10, 0b0000000111, 4, 0),
63 (9, 0b000000110, 4, 1),
64 (8, 0b00000101, 4, 2),
65 (6, 0b000011, 4, 3),
66 (11, 0b00000000111, 5, 0),
67 (10, 0b0000000110, 5, 1),
68 (9, 0b000000101, 5, 2),
69 (7, 0b0000100, 5, 3),
70 (13, 0b0000000001111, 6, 0),
71 (11, 0b00000000110, 6, 1),
72 (10, 0b0000000101, 6, 2),
73 (8, 0b00000100, 6, 3),
74 (13, 0b0000000001011, 7, 0),
75 (13, 0b0000000001110, 7, 1),
76 (11, 0b00000000101, 7, 2),
77 (9, 0b000000100, 7, 3),
78 (13, 0b0000000001000, 8, 0),
79 (13, 0b0000000001010, 8, 1),
80 (13, 0b0000000001101, 8, 2),
81 (10, 0b0000000100, 8, 3),
82 (14, 0b00000000001111, 9, 0),
83 (14, 0b00000000001110, 9, 1),
84 (13, 0b0000000001001, 9, 2),
85 (11, 0b00000000100, 9, 3),
86 (14, 0b00000000001011, 10, 0),
87 (14, 0b00000000001010, 10, 1),
88 (14, 0b00000000001101, 10, 2),
89 (13, 0b0000000001100, 10, 3),
90 (15, 0b000000000001111, 11, 0),
91 (15, 0b000000000001110, 11, 1),
92 (14, 0b00000000001001, 11, 2),
93 (14, 0b00000000001100, 11, 3),
94 (15, 0b000000000001011, 12, 0),
95 (15, 0b000000000001010, 12, 1),
96 (15, 0b000000000001101, 12, 2),
97 (14, 0b00000000001000, 12, 3),
98 (16, 0b0000000000001111, 13, 0),
99 (15, 0b000000000000001, 13, 1),
100 (15, 0b000000000001001, 13, 2),
101 (15, 0b000000000001100, 13, 3),
102 (16, 0b0000000000001011, 14, 0),
103 (16, 0b0000000000001110, 14, 1),
104 (16, 0b0000000000001101, 14, 2),
105 (15, 0b000000000001000, 14, 3),
106 (16, 0b0000000000000111, 15, 0),
107 (16, 0b0000000000001010, 15, 1),
108 (16, 0b0000000000001001, 15, 2),
109 (16, 0b0000000000001100, 15, 3),
110 (16, 0b0000000000000100, 16, 0),
111 (16, 0b0000000000000110, 16, 1),
112 (16, 0b0000000000000101, 16, 2),
113 (16, 0b0000000000001000, 16, 3),
114];
115
116const COEFF_TOKEN_CHROMA_DC: &[TokEntry] = &[
118 (2, 0b01, 0, 0),
119 (6, 0b000111, 1, 0),
120 (1, 0b1, 1, 1),
121 (6, 0b000100, 2, 0),
122 (6, 0b000110, 2, 1),
123 (3, 0b001, 2, 2),
124 (6, 0b000011, 3, 0),
125 (7, 0b0000011, 3, 1),
126 (7, 0b0000010, 3, 2),
127 (6, 0b000101, 3, 3),
128 (6, 0b000010, 4, 0),
129 (8, 0b00000011, 4, 1),
130 (8, 0b00000010, 4, 2),
131 (7, 0b0000000, 4, 3),
132];
133
134fn read_coeff_token(r: &mut BitReader, table: &[TokEntry]) -> Option<(u8, u8)> {
136 let mut code: u16 = 0;
137 for len in 1..=16u8 {
138 code = (code << 1) | (r.read_bit() as u16);
139 for &(l, c, tc, t1) in table {
140 if l == len && c == code {
141 return Some((tc, t1));
142 }
143 }
144 }
145 None
146}
147
148const COEFF_TOKEN_2: &[TokEntry] = &[
150 (2, 0b11, 0, 0),
151 (6, 0b001011, 1, 0),
152 (2, 0b10, 1, 1),
153 (6, 0b000111, 2, 0),
154 (5, 0b00111, 2, 1),
155 (3, 0b011, 2, 2),
156 (7, 0b0000111, 3, 0),
157 (6, 0b001010, 3, 1),
158 (6, 0b001001, 3, 2),
159 (4, 0b0101, 3, 3),
160 (8, 0b00000111, 4, 0),
161 (6, 0b000110, 4, 1),
162 (6, 0b000101, 4, 2),
163 (4, 0b0100, 4, 3),
164 (8, 0b00000100, 5, 0),
165 (7, 0b0000110, 5, 1),
166 (7, 0b0000101, 5, 2),
167 (5, 0b00110, 5, 3),
168 (9, 0b000000111, 6, 0),
169 (8, 0b00000110, 6, 1),
170 (8, 0b00000101, 6, 2),
171 (6, 0b001000, 6, 3),
172 (11, 0b00000001111, 7, 0),
173 (9, 0b000000110, 7, 1),
174 (9, 0b000000101, 7, 2),
175 (6, 0b000100, 7, 3),
176 (11, 0b00000001011, 8, 0),
177 (11, 0b00000001110, 8, 1),
178 (11, 0b00000001101, 8, 2),
179 (7, 0b0000100, 8, 3),
180 (12, 0b000000001111, 9, 0),
181 (11, 0b00000001010, 9, 1),
182 (11, 0b00000001001, 9, 2),
183 (9, 0b000000100, 9, 3),
184 (12, 0b000000001011, 10, 0),
185 (12, 0b000000001110, 10, 1),
186 (12, 0b000000001101, 10, 2),
187 (11, 0b00000001100, 10, 3),
188 (12, 0b000000001000, 11, 0),
189 (12, 0b000000001010, 11, 1),
190 (12, 0b000000001001, 11, 2),
191 (11, 0b00000001000, 11, 3),
192 (13, 0b0000000001111, 12, 0),
193 (13, 0b0000000001110, 12, 1),
194 (13, 0b0000000001101, 12, 2),
195 (12, 0b000000001100, 12, 3),
196 (13, 0b0000000001011, 13, 0),
197 (13, 0b0000000001010, 13, 1),
198 (13, 0b0000000001001, 13, 2),
199 (13, 0b0000000001100, 13, 3),
200 (13, 0b0000000000111, 14, 0),
201 (14, 0b00000000001011, 14, 1),
202 (13, 0b0000000000110, 14, 2),
203 (13, 0b0000000001000, 14, 3),
204 (14, 0b00000000001001, 15, 0),
205 (14, 0b00000000001000, 15, 1),
206 (14, 0b00000000001010, 15, 2),
207 (13, 0b0000000000001, 15, 3),
208 (14, 0b00000000000111, 16, 0),
209 (14, 0b00000000000110, 16, 1),
210 (14, 0b00000000000101, 16, 2),
211 (14, 0b00000000000100, 16, 3),
212];
213
214const COEFF_TOKEN_4: &[TokEntry] = &[
216 (4, 0b1111, 0, 0),
217 (6, 0b001111, 1, 0),
218 (4, 0b1110, 1, 1),
219 (6, 0b001011, 2, 0),
220 (5, 0b01111, 2, 1),
221 (4, 0b1101, 2, 2),
222 (6, 0b001000, 3, 0),
223 (5, 0b01100, 3, 1),
224 (5, 0b01110, 3, 2),
225 (4, 0b1100, 3, 3),
226 (7, 0b0001111, 4, 0),
227 (5, 0b01010, 4, 1),
228 (5, 0b01011, 4, 2),
229 (4, 0b1011, 4, 3),
230 (7, 0b0001011, 5, 0),
231 (5, 0b01000, 5, 1),
232 (5, 0b01001, 5, 2),
233 (4, 0b1010, 5, 3),
234 (7, 0b0001001, 6, 0),
235 (6, 0b001110, 6, 1),
236 (6, 0b001101, 6, 2),
237 (4, 0b1001, 6, 3),
238 (7, 0b0001000, 7, 0),
239 (6, 0b001010, 7, 1),
240 (6, 0b001001, 7, 2),
241 (4, 0b1000, 7, 3),
242 (8, 0b00001111, 8, 0),
243 (7, 0b0001110, 8, 1),
244 (7, 0b0001101, 8, 2),
245 (5, 0b01101, 8, 3),
246 (8, 0b00001011, 9, 0),
247 (8, 0b00001110, 9, 1),
248 (7, 0b0001010, 9, 2),
249 (6, 0b001100, 9, 3),
250 (9, 0b000001111, 10, 0),
251 (8, 0b00001010, 10, 1),
252 (8, 0b00001101, 10, 2),
253 (7, 0b0001100, 10, 3),
254 (9, 0b000001011, 11, 0),
255 (9, 0b000001110, 11, 1),
256 (8, 0b00001001, 11, 2),
257 (8, 0b00001100, 11, 3),
258 (9, 0b000001000, 12, 0),
259 (9, 0b000001010, 12, 1),
260 (9, 0b000001101, 12, 2),
261 (8, 0b00001000, 12, 3),
262 (10, 0b0000001101, 13, 0),
263 (9, 0b000000111, 13, 1),
264 (9, 0b000001001, 13, 2),
265 (9, 0b000001100, 13, 3),
266 (10, 0b0000001001, 14, 0),
267 (10, 0b0000001100, 14, 1),
268 (10, 0b0000001011, 14, 2),
269 (10, 0b0000001010, 14, 3),
270 (10, 0b0000000101, 15, 0),
271 (10, 0b0000001000, 15, 1),
272 (10, 0b0000000111, 15, 2),
273 (10, 0b0000000110, 15, 3),
274 (10, 0b0000000001, 16, 0),
275 (10, 0b0000000100, 16, 1),
276 (10, 0b0000000011, 16, 2),
277 (10, 0b0000000010, 16, 3),
278];
279
280fn read_coeff_token_nc(r: &mut BitReader, n_c: i32) -> Option<(u8, u8)> {
282 if n_c == -1 {
283 return read_coeff_token(r, COEFF_TOKEN_CHROMA_DC);
284 }
285 if n_c >= 8 {
286 let code = r.read_bits(6);
287 if code == 3 {
288 return Some((0, 0));
289 }
290 return Some(((code >> 2) as u8 + 1, (code & 3) as u8));
291 }
292 let table = if n_c < 2 {
293 COEFF_TOKEN_0
294 } else if n_c < 4 {
295 COEFF_TOKEN_2
296 } else {
297 COEFF_TOKEN_4
298 };
299 read_coeff_token(r, table)
300}
301
302const CBP_INTRA_MAP: [u8; 48] = [
304 47, 31, 15, 0, 23, 27, 29, 30, 7, 11, 13, 14, 39, 43, 45, 46, 16, 3, 5, 10, 12, 19, 21, 26, 28,
305 35, 37, 42, 44, 1, 2, 4, 8, 17, 18, 20, 24, 6, 9, 22, 25, 32, 33, 34, 36, 40, 38, 41,
306];
307
308const CBP_INTER_MAP: [u8; 48] = [
310 0, 16, 1, 2, 4, 8, 32, 3, 5, 10, 12, 15, 47, 7, 11, 13, 14, 6, 9, 31, 35, 37, 42, 44, 33, 34,
311 36, 40, 39, 43, 45, 46, 17, 18, 20, 24, 19, 21, 26, 28, 23, 27, 29, 30, 22, 25, 38, 41,
312];
313
314const ALPHA_TABLE: [u8; 52] = [
316 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 5, 6, 7, 8, 9, 10, 12, 13, 15, 17, 20,
317 22, 25, 28, 32, 36, 40, 45, 50, 56, 63, 71, 80, 90, 101, 113, 127, 144, 162, 182, 203, 226,
318 255, 255,
319];
320const BETA_TABLE: [u8; 52] = [
321 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 6, 6, 7, 7, 8, 8,
322 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18,
323];
324const TC0_TABLE: [[u8; 3]; 52] = [
326 [0, 0, 0],
327 [0, 0, 0],
328 [0, 0, 0],
329 [0, 0, 0],
330 [0, 0, 0],
331 [0, 0, 0],
332 [0, 0, 0],
333 [0, 0, 0],
334 [0, 0, 0],
335 [0, 0, 0],
336 [0, 0, 0],
337 [0, 0, 0],
338 [0, 0, 0],
339 [0, 0, 0],
340 [0, 0, 0],
341 [0, 0, 0],
342 [0, 0, 0],
343 [0, 0, 1],
344 [0, 0, 1],
345 [0, 0, 1],
346 [0, 0, 1],
347 [0, 1, 1],
348 [0, 1, 1],
349 [1, 1, 1],
350 [1, 1, 1],
351 [1, 1, 1],
352 [1, 1, 1],
353 [1, 1, 2],
354 [1, 1, 2],
355 [1, 1, 2],
356 [1, 1, 2],
357 [1, 2, 3],
358 [1, 2, 3],
359 [2, 2, 3],
360 [2, 2, 4],
361 [2, 3, 4],
362 [2, 3, 4],
363 [3, 3, 5],
364 [3, 4, 6],
365 [3, 4, 6],
366 [4, 5, 7],
367 [4, 5, 8],
368 [4, 6, 9],
369 [5, 7, 10],
370 [6, 8, 11],
371 [6, 8, 13],
372 [7, 10, 14],
373 [8, 11, 16],
374 [9, 12, 18],
375 [10, 13, 20],
376 [11, 15, 23],
377 [13, 17, 25],
378];
379
380const TOTAL_ZEROS_16: &[&[(u8, u16)]] = &[
383 &[
384 (1, 0b1),
385 (3, 0b011),
386 (3, 0b010),
387 (4, 0b0011),
388 (4, 0b0010),
389 (5, 0b00011),
390 (5, 0b00010),
391 (6, 0b000011),
392 (6, 0b000010),
393 (7, 0b0000011),
394 (7, 0b0000010),
395 (8, 0b00000011),
396 (8, 0b00000010),
397 (9, 0b000000011),
398 (9, 0b000000010),
399 (9, 0b000000001),
400 ],
401 &[
402 (3, 0b111),
403 (3, 0b110),
404 (3, 0b101),
405 (3, 0b100),
406 (3, 0b011),
407 (4, 0b0101),
408 (4, 0b0100),
409 (4, 0b0011),
410 (4, 0b0010),
411 (5, 0b00011),
412 (5, 0b00010),
413 (6, 0b000011),
414 (6, 0b000010),
415 (6, 0b000001),
416 (6, 0b000000),
417 ],
418 &[
419 (4, 0b0101),
420 (3, 0b111),
421 (3, 0b110),
422 (3, 0b101),
423 (4, 0b0100),
424 (4, 0b0011),
425 (3, 0b100),
426 (3, 0b011),
427 (4, 0b0010),
428 (5, 0b00011),
429 (5, 0b00010),
430 (6, 0b000001),
431 (5, 0b00001),
432 (6, 0b000000),
433 ],
434 &[
435 (5, 0b00011),
436 (3, 0b111),
437 (4, 0b0101),
438 (4, 0b0100),
439 (3, 0b110),
440 (3, 0b101),
441 (3, 0b100),
442 (4, 0b0011),
443 (3, 0b011),
444 (4, 0b0010),
445 (5, 0b00010),
446 (5, 0b00001),
447 (5, 0b00000),
448 ],
449 &[
450 (4, 0b0101),
451 (4, 0b0100),
452 (4, 0b0011),
453 (3, 0b111),
454 (3, 0b110),
455 (3, 0b101),
456 (3, 0b100),
457 (3, 0b011),
458 (4, 0b0010),
459 (5, 0b00001),
460 (4, 0b0001),
461 (5, 0b00000),
462 ],
463 &[
464 (6, 0b000001),
465 (5, 0b00001),
466 (3, 0b111),
467 (3, 0b110),
468 (3, 0b101),
469 (3, 0b100),
470 (3, 0b011),
471 (3, 0b010),
472 (4, 0b0001),
473 (3, 0b001),
474 (6, 0b000000),
475 ],
476 &[
477 (6, 0b000001),
478 (5, 0b00001),
479 (3, 0b101),
480 (3, 0b100),
481 (3, 0b011),
482 (2, 0b11),
483 (3, 0b010),
484 (4, 0b0001),
485 (3, 0b001),
486 (6, 0b000000),
487 ],
488 &[
489 (6, 0b000001),
490 (4, 0b0001),
491 (5, 0b00001),
492 (3, 0b011),
493 (2, 0b11),
494 (2, 0b10),
495 (3, 0b010),
496 (3, 0b001),
497 (6, 0b000000),
498 ],
499 &[
500 (6, 0b000001),
501 (6, 0b000000),
502 (4, 0b0001),
503 (2, 0b11),
504 (2, 0b10),
505 (3, 0b001),
506 (2, 0b01),
507 (5, 0b00001),
508 ],
509 &[
510 (5, 0b00001),
511 (5, 0b00000),
512 (3, 0b001),
513 (2, 0b11),
514 (2, 0b10),
515 (2, 0b01),
516 (4, 0b0001),
517 ],
518 &[
519 (4, 0b0000),
520 (4, 0b0001),
521 (3, 0b001),
522 (3, 0b010),
523 (1, 0b1),
524 (3, 0b011),
525 ],
526 &[(4, 0b0000), (4, 0b0001), (2, 0b01), (1, 0b1), (3, 0b001)],
527 &[(3, 0b000), (3, 0b001), (1, 0b1), (2, 0b01)],
528 &[(2, 0b00), (2, 0b01), (1, 0b1)],
529 &[(1, 0b0), (1, 0b1)],
530];
531
532const TOTAL_ZEROS_CHROMA: &[&[(u8, u16)]] = &[
534 &[(1, 0b1), (2, 0b01), (3, 0b001), (3, 0b000)],
535 &[(1, 0b1), (2, 0b01), (2, 0b00)],
536 &[(1, 0b1), (1, 0b0)],
537];
538
539fn read_total_zeros(r: &mut BitReader, total_coeff: u8, tables: &[&[(u8, u16)]]) -> u8 {
540 let row = tables[(total_coeff - 1) as usize];
541 let mut code: u16 = 0;
542 for len in 1..=9u8 {
543 code = (code << 1) | (r.read_bit() as u16);
544 for (tz, &(l, c)) in row.iter().enumerate() {
545 if l == len && c == code {
546 return tz as u8;
547 }
548 }
549 }
550 0
551}
552
553const RUN_BEFORE: &[&[(u8, u16)]] = &[
555 &[(1, 0b1), (1, 0b0)],
556 &[(1, 0b1), (2, 0b01), (2, 0b00)],
557 &[(2, 0b11), (2, 0b10), (2, 0b01), (2, 0b00)],
558 &[(2, 0b11), (2, 0b10), (2, 0b01), (3, 0b001), (3, 0b000)],
559 &[
560 (2, 0b11),
561 (2, 0b10),
562 (3, 0b011),
563 (3, 0b010),
564 (3, 0b001),
565 (3, 0b000),
566 ],
567 &[
568 (2, 0b11),
569 (3, 0b000),
570 (3, 0b001),
571 (3, 0b011),
572 (3, 0b010),
573 (3, 0b101),
574 (3, 0b100),
575 ],
576 &[
577 (3, 0b111),
578 (3, 0b110),
579 (3, 0b101),
580 (3, 0b100),
581 (3, 0b011),
582 (3, 0b010),
583 (3, 0b001),
584 (4, 0b0001),
585 (5, 0b00001),
586 (6, 0b000001),
587 (7, 0b0000001),
588 (8, 0b00000001),
589 (9, 0b000000001),
590 (10, 0b0000000001),
591 (11, 0b00000000001),
592 ],
593];
594
595fn read_run_before(r: &mut BitReader, zeros_left: i32) -> i32 {
596 let idx = (zeros_left.min(7) - 1).max(0) as usize;
597 let row = RUN_BEFORE[idx];
598 let mut code: u16 = 0;
599 for len in 1..=11u8 {
600 code = (code << 1) | (r.read_bit() as u16);
601 for (run, &(l, c)) in row.iter().enumerate() {
602 if l == len && c == code {
603 return run as i32;
604 }
605 }
606 }
607 0
608}
609
610fn residual_block_cavlc(
613 r: &mut BitReader,
614 max_num_coeff: usize,
615 n_c: i32,
616 tz_tables: &[&[(u8, u16)]],
617) -> ([i32; 16], u8) {
618 let mut coeff = [0i32; 16];
619 let (total_coeff, trailing_ones) = match read_coeff_token_nc(r, n_c) {
620 Some(v) => v,
621 None => return (coeff, 0),
622 };
623 let ret_total = total_coeff;
624 if total_coeff == 0 {
625 return (coeff, 0);
626 }
627 let total_coeff = total_coeff as usize;
628 let trailing_ones = trailing_ones as usize;
629
630 let mut level = [0i32; 16];
632 for i in 0..trailing_ones {
633 level[i] = if r.read_bit() == 1 { -1 } else { 1 };
634 }
635 let mut suffix_length: u32 = if total_coeff > 10 && trailing_ones < 3 {
636 1
637 } else {
638 0
639 };
640 for i in trailing_ones..total_coeff {
641 let mut level_prefix = 0u32;
642 while r.read_bit() == 0 {
643 level_prefix += 1;
644 if level_prefix > 31 {
645 break;
646 }
647 }
648 let mut suffix_size = suffix_length;
649 if level_prefix == 14 && suffix_length == 0 {
650 suffix_size = 4;
651 } else if level_prefix >= 15 {
652 suffix_size = level_prefix - 3;
653 }
654 let level_suffix = if suffix_size > 0 {
655 r.read_bits(suffix_size) as i32
656 } else {
657 0
658 };
659 let mut level_code = ((level_prefix.min(15) << suffix_length) as i32) + level_suffix;
660 if level_prefix >= 15 && suffix_length == 0 {
661 level_code += 15;
662 }
663 if level_prefix >= 16 {
664 level_code += (1 << (level_prefix - 3)) - 4096;
665 }
666 if i == trailing_ones && trailing_ones < 3 {
667 level_code += 2;
668 }
669 level[i] = if level_code % 2 == 0 {
670 (level_code + 2) >> 1
671 } else {
672 (-level_code - 1) >> 1
673 };
674 if suffix_length == 0 {
675 suffix_length = 1;
676 }
677 if level[i].unsigned_abs() > (3u32 << (suffix_length - 1)) && suffix_length < 6 {
678 suffix_length += 1;
679 }
680 }
681
682 let total_zeros = if total_coeff < max_num_coeff {
684 read_total_zeros(r, total_coeff as u8, tz_tables) as i32
685 } else {
686 0
687 };
688
689 let mut run = [0i32; 16];
691 let mut zeros_left = total_zeros;
692 for i in 0..total_coeff {
693 if i < total_coeff - 1 && zeros_left > 0 {
694 let rb = read_run_before(r, zeros_left);
695 run[i] = rb;
696 zeros_left -= rb;
697 } else if i == total_coeff - 1 {
698 run[i] = zeros_left;
699 } else {
700 run[i] = 0;
701 }
702 }
703
704 let mut coeff_ctr: i32 = -1;
706 for i in (0..total_coeff).rev() {
707 coeff_ctr += run[i] + 1;
708 if (coeff_ctr as usize) < 16 {
709 coeff[coeff_ctr as usize] = level[i];
710 }
711 }
712 (coeff, ret_total)
713}
714
715fn inverse_hadamard_4x4(b: &mut [i32; 16]) {
719 for i in 0..4 {
720 let o = i * 4;
721 let (a0, a1, a2, a3) = (
722 b[o] + b[o + 2],
723 b[o] - b[o + 2],
724 b[o + 1] - b[o + 3],
725 b[o + 1] + b[o + 3],
726 );
727 b[o] = a0 + a3;
728 b[o + 1] = a1 + a2;
729 b[o + 2] = a1 - a2;
730 b[o + 3] = a0 - a3;
731 }
732 for j in 0..4 {
733 let (a0, a1, a2, a3) = (
734 b[j] + b[8 + j],
735 b[j] - b[8 + j],
736 b[4 + j] - b[12 + j],
737 b[4 + j] + b[12 + j],
738 );
739 b[j] = a0 + a3;
740 b[4 + j] = a1 + a2;
741 b[8 + j] = a1 - a2;
742 b[12 + j] = a0 - a3;
743 }
744}
745
746fn scale_luma_dc(f: &mut [i32; 16], qp: i32) {
748 let m = (qp % 6) as usize;
749 let ls = 16 * NORM_ADJUST_4X4[m][0];
750 let shift = qp / 6;
751 for v in f.iter_mut() {
752 *v = if qp >= 36 {
753 (*v * ls) << (shift - 6)
754 } else {
755 (*v * ls + (1 << (5 - shift))) >> (6 - shift)
756 };
757 }
758}
759
760pub struct DecodedYuv {
763 pub width: u32,
764 pub height: u32,
765 pub y: Vec<u8>,
766 pub u: Vec<u8>,
767 pub v: Vec<u8>,
768}
769
770pub fn yuv_to_rgb(yuv: &DecodedYuv) -> Vec<u8> {
772 let w = yuv.width as usize;
773 let h = yuv.height as usize;
774 let cw = (yuv.width / 2) as usize;
775 let mut rgb = alloc::vec![0u8; w * h * 3];
776 let mut oi = 0usize;
777 for y in 0..h {
778 let yrow = y * w;
779 let crow = (y >> 1) * cw;
780 for x in 0..w {
781 let yy = yuv.y[yrow + x] as i32;
782 let ci = crow + (x >> 1);
783 let cu = yuv.u[ci] as i32 - 128;
784 let cv = yuv.v[ci] as i32 - 128;
785 let r = yy + ((91881 * cv) >> 16);
786 let g = yy - ((22554 * cu + 46802 * cv) >> 16);
787 let b = yy + ((116130 * cu) >> 16);
788 rgb[oi] = r.clamp(0, 255) as u8;
789 rgb[oi + 1] = g.clamp(0, 255) as u8;
790 rgb[oi + 2] = b.clamp(0, 255) as u8;
791 oi += 3;
792 }
793 }
794 rgb
795}
796
797pub struct VideoDecoder {
799 sps: Option<Sps>,
800 pps: Option<Pps>,
801 length_size: usize,
802 reference: Option<DecodedYuv>,
803}
804
805impl Default for VideoDecoder {
806 fn default() -> Self {
807 Self::new()
808 }
809}
810
811impl VideoDecoder {
812 pub fn new() -> Self {
813 Self {
814 sps: None,
815 pps: None,
816 length_size: 4,
817 reference: None,
818 }
819 }
820
821 pub fn init_avcc(&mut self, avcc: &[u8]) {
823 if let Some((ls, sps_list, pps_list)) = parse_avcc(avcc) {
824 self.length_size = ls;
825 if let Some(p) = sps_list.first() {
826 if p.len() > 1 {
827 self.sps = parse_sps(&extract_rbsp(&p[1..])).ok();
828 }
829 }
830 if let Some(p) = pps_list.first() {
831 if p.len() > 1 {
832 self.pps = parse_pps(&extract_rbsp(&p[1..])).ok();
833 }
834 }
835 }
836 }
837
838 pub fn decode_sample_rgb(&mut self, sample: &[u8]) -> Option<(u32, u32, Vec<u8>)> {
840 let nals = split_avcc(sample, self.length_size);
841 let mut out = None;
842 for nu in &nals {
843 match nu.unit_type {
844 7 => self.sps = parse_sps(&nu.rbsp).ok(),
845 8 => self.pps = parse_pps(&nu.rbsp).ok(),
846 1 | 5 => {
847 let (s, p) = match (self.sps.clone(), self.pps.clone()) {
848 (Some(s), Some(p)) => (s, p),
849 _ => continue,
850 };
851 if let Ok(frame) =
852 decode_slice(&s, &p, &nu.rbsp, nu.unit_type == 5, self.reference.as_ref())
853 {
854 out = Some((frame.width, frame.height, yuv_to_rgb(&frame)));
855 self.reference = Some(frame);
856 }
857 }
858 _ => {}
859 }
860 }
861 out
862 }
863}
864
865struct DecState {
867 yuv: DecodedYuv,
868 blk_w: usize, nnz_luma: Vec<u8>, mode_luma: Vec<i8>, decoded: Vec<bool>, cblk_w: usize, nnz_chroma: [Vec<u8>; 2], mb_w: usize, mb_qp: Vec<i32>, mv_l0: Vec<[i16; 2]>, is_inter: Vec<bool>, blk_h: usize, }
880
881fn combine_nc(na: i32, nb: i32) -> i32 {
883 if na >= 0 && nb >= 0 {
884 (na + nb + 1) >> 1
885 } else if na >= 0 {
886 na
887 } else if nb >= 0 {
888 nb
889 } else {
890 0
891 }
892}
893
894impl DecState {
895 fn li(&self, bx4: usize, by4: usize) -> usize {
896 by4 * self.blk_w + bx4
897 }
898
899 fn luma_nc(&self, bx4: usize, by4: usize) -> i32 {
901 let na = if bx4 > 0 {
902 self.nnz_luma[self.li(bx4 - 1, by4)] as i32
903 } else {
904 -1
905 };
906 let nb = if by4 > 0 {
907 self.nnz_luma[self.li(bx4, by4 - 1)] as i32
908 } else {
909 -1
910 };
911 combine_nc(na, nb)
912 }
913
914 fn pred_i4x4_mode(&self, bx4: usize, by4: usize) -> i32 {
916 if bx4 == 0 || by4 == 0 {
917 return 2;
918 } let ma = self.mode_luma[self.li(bx4 - 1, by4)];
920 let mb = self.mode_luma[self.li(bx4, by4 - 1)];
921 let ma = if ma >= 0 { ma as i32 } else { 2 };
922 let mb = if mb >= 0 { mb as i32 } else { 2 };
923 ma.min(mb)
924 }
925
926 fn predict_luma_4x4(&self, px: usize, py: usize, mode: u8) -> [i32; 16] {
929 let w = self.yuv.width as usize;
930 let top_avail = py > 0;
931 let left_avail = px > 0;
932 let bx4 = px / 4;
933 let by4 = py / 4;
934 let mut top = [0i32; 8];
935 let mut left = [0i32; 4];
936 let mut corner = 0i32;
937 if top_avail {
938 for x in 0..4 {
939 top[x] = self.yuv.y[(py - 1) * w + px + x] as i32;
940 }
941 let tr_ok = by4 > 0 && bx4 + 1 < self.blk_w && self.decoded[self.li(bx4 + 1, by4 - 1)];
943 if tr_ok {
944 for x in 0..4 {
945 top[4 + x] = self.yuv.y[(py - 1) * w + px + 4 + x] as i32;
946 }
947 } else {
948 for x in 0..4 {
949 top[4 + x] = top[3];
950 }
951 }
952 }
953 if left_avail {
954 for y in 0..4 {
955 left[y] = self.yuv.y[(py + y) * w + px - 1] as i32;
956 }
957 }
958 if top_avail && left_avail {
959 corner = self.yuv.y[(py - 1) * w + px - 1] as i32;
960 }
961 intra_4x4_predict(mode, &top, corner, &left, top_avail, left_avail)
962 }
963}
964
965pub fn decode_slice(
968 sps: &Sps,
969 pps: &Pps,
970 rbsp: &[u8],
971 is_idr: bool,
972 reference: Option<&DecodedYuv>,
973) -> Result<DecodedYuv, &'static str> {
974 if pps.entropy_coding_mode_flag != 0 {
975 return Err("CABAC not supported");
976 }
977 if sps.width_mbs == 0 || sps.height_mbs == 0 || sps.width_mbs > 300 || sps.height_mbs > 300 {
979 return Err("invalid frame dimensions");
980 }
981 let width = sps.width_mbs * 16;
982 let height = sps.height_mbs * 16;
983 let cw = width / 2;
984 let ch = height / 2;
985 let yuv = DecodedYuv {
986 width,
987 height,
988 y: alloc::vec![0u8; (width * height) as usize],
989 u: alloc::vec![128u8; (cw * ch) as usize],
990 v: alloc::vec![128u8; (cw * ch) as usize],
991 };
992 let blk_w = (width / 4) as usize;
993 let blk_h = (height / 4) as usize;
994 let cblk_w = (cw / 4) as usize;
995 let cblk_h = (ch / 4) as usize;
996 let mut st = DecState {
997 yuv,
998 blk_w,
999 nnz_luma: alloc::vec![0u8; blk_w * blk_h],
1000 mode_luma: alloc::vec![-1i8; blk_w * blk_h],
1001 decoded: alloc::vec![false; blk_w * blk_h],
1002 cblk_w,
1003 nnz_chroma: [
1004 alloc::vec![0u8; cblk_w * cblk_h],
1005 alloc::vec![0u8; cblk_w * cblk_h],
1006 ],
1007 mb_w: sps.width_mbs as usize,
1008 mb_qp: alloc::vec![0i32; (sps.width_mbs * sps.height_mbs) as usize],
1009 mv_l0: alloc::vec![[0i16; 2]; blk_w * blk_h],
1010 is_inter: alloc::vec![false; blk_w * blk_h],
1011 blk_h,
1012 };
1013
1014 let mut r = BitReader::new(rbsp);
1015
1016 let _first_mb_in_slice = r.read_ue();
1018 let slice_type = r.read_ue();
1019 let is_i = slice_type % 5 == 2 || slice_type % 5 == 4;
1020 let is_p = slice_type.is_multiple_of(5);
1021 if !is_i && !is_p {
1022 return Err("only I/P slices supported");
1023 }
1024 if is_p {
1025 match reference {
1028 None => return Err("P slice without reference frame"),
1029 Some(r) if r.width != width || r.height != height => {
1030 return Err("reference dimension mismatch")
1031 }
1032 _ => {}
1033 }
1034 }
1035 let _pps_id = r.read_ue();
1036 let _frame_num = r.read_bits(sps.log2_max_frame_num);
1037 if is_idr {
1038 let _idr_pic_id = r.read_ue();
1039 }
1040 if sps.pic_order_cnt_type == 0 {
1041 let _pic_order_cnt_lsb = r.read_bits(sps.log2_max_pic_order_cnt_lsb);
1042 if pps.bottom_field_pic_order_in_frame_present_flag != 0 {
1043 let _delta = r.read_se();
1044 }
1045 }
1046 if pps.redundant_pic_cnt_present_flag != 0 {
1047 let _redundant_pic_cnt = r.read_ue();
1048 }
1049 if is_p {
1051 let num_ref_idx_override = r.read_bit();
1052 if num_ref_idx_override == 1 {
1053 let _num_ref_idx_l0_active_minus1 = r.read_ue();
1054 }
1055 if r.read_bit() == 1 {
1057 for _ in 0..64 {
1058 let idc = r.read_ue();
1059 if idc == 3 || r.is_eof() {
1060 break;
1061 }
1062 let _ = r.read_ue();
1063 }
1064 }
1065 }
1066 if is_idr {
1068 let _no_output_of_prior_pics = r.read_bit();
1069 let _long_term_reference = r.read_bit();
1070 } else {
1071 let adaptive = r.read_bit();
1072 if adaptive == 1 {
1073 for _ in 0..64 {
1074 let mmco = r.read_ue();
1075 if mmco == 0 || r.is_eof() {
1076 break;
1077 }
1078 if mmco == 1 || mmco == 3 {
1079 let _ = r.read_ue();
1080 }
1081 if mmco == 2 {
1082 let _ = r.read_ue();
1083 }
1084 if mmco == 3 || mmco == 6 {
1085 let _ = r.read_ue();
1086 }
1087 if mmco == 4 {
1088 let _ = r.read_ue();
1089 }
1090 }
1091 }
1092 }
1093 let slice_qp_delta = r.read_se();
1094 let slice_qp = pps.pic_init_qp + slice_qp_delta;
1095 let mut disable_deblock_idc = 0u32;
1096 let mut alpha_off = 0i32;
1097 let mut beta_off = 0i32;
1098 if pps.deblocking_filter_control_present_flag != 0 {
1099 disable_deblock_idc = r.read_ue();
1100 if disable_deblock_idc != 1 {
1101 alpha_off = r.read_se() * 2;
1102 beta_off = r.read_se() * 2;
1103 }
1104 }
1105
1106 let mb_w = sps.width_mbs;
1108 let mb_h = sps.height_mbs;
1109 let total_mb = (mb_w * mb_h) as usize;
1110 let mut qp = slice_qp;
1111
1112 if is_i {
1113 for mb_idx in 0..total_mb {
1114 let mb_x = (mb_idx as u32 % mb_w) * 16;
1115 let mb_y = (mb_idx as u32 / mb_w) * 16;
1116 if let Err(e) = decode_mb(&mut r, &mut st, mb_x, mb_y, &mut qp, pps) {
1117 crate::println!(
1118 " H264 decode stopped at mb {} (of {}): {}",
1119 mb_idx,
1120 total_mb,
1121 e
1122 );
1123 return Err(e);
1124 }
1125 }
1126 } else {
1127 let refr = reference.ok_or("P slice without reference frame")?;
1130 let mut mb_idx = 0usize;
1131 while mb_idx < total_mb {
1132 let skip_run = r.read_ue() as usize;
1133 for _ in 0..skip_run {
1134 if mb_idx >= total_mb {
1135 break;
1136 }
1137 let mb_x = (mb_idx as u32 % mb_w) * 16;
1138 let mb_y = (mb_idx as u32 / mb_w) * 16;
1139 decode_pskip(&mut st, mb_x, mb_y, qp, refr);
1140 mb_idx += 1;
1141 }
1142 if mb_idx >= total_mb {
1143 break;
1144 }
1145 let mb_x = (mb_idx as u32 % mb_w) * 16;
1146 let mb_y = (mb_idx as u32 / mb_w) * 16;
1147 if let Err(e) = decode_mb_p(&mut r, &mut st, mb_x, mb_y, &mut qp, pps, refr) {
1148 crate::println!(
1149 " H264 P decode stopped at mb {} (of {}): {}",
1150 mb_idx,
1151 total_mb,
1152 e
1153 );
1154 return Err(e);
1155 }
1156 mb_idx += 1;
1157 }
1158 }
1159
1160 if disable_deblock_idc != 1 {
1162 deblock_frame(
1163 &mut st,
1164 mb_w as usize,
1165 mb_h as usize,
1166 alpha_off,
1167 beta_off,
1168 pps.chroma_qp_index_offset,
1169 );
1170 }
1171
1172 Ok(st.yuv)
1173}
1174
1175#[allow(clippy::too_many_arguments)]
1176fn decode_mb(
1177 r: &mut BitReader,
1178 st: &mut DecState,
1179 mb_x: u32,
1180 mb_y: u32,
1181 qp: &mut i32,
1182 pps: &Pps,
1183) -> Result<(), &'static str> {
1184 let mb_type = r.read_ue();
1185 if mb_type == 25 {
1186 return decode_mb_ipcm(r, st, mb_x, mb_y);
1187 }
1188 if mb_type == 0 {
1189 decode_mb_i4x4(r, st, mb_x, mb_y, qp, pps)
1190 } else if (1..=24).contains(&mb_type) {
1191 decode_mb_i16x16(r, st, mb_x, mb_y, qp, mb_type, pps)
1192 } else {
1193 Err("unsupported mb_type (non-I)")
1194 }
1195}
1196
1197fn decode_mb_ipcm(
1199 r: &mut BitReader,
1200 st: &mut DecState,
1201 mb_x: u32,
1202 mb_y: u32,
1203) -> Result<(), &'static str> {
1204 r.byte_align();
1205 let w = st.yuv.width as usize;
1206 let cw = (st.yuv.width / 2) as usize;
1207 let (mx, my) = (mb_x as usize, mb_y as usize);
1208 for by in 0..16 {
1209 for bx in 0..16 {
1210 st.yuv.y[(my + by) * w + mx + bx] = r.read_bits(8) as u8;
1211 }
1212 }
1213 let (cmx, cmy) = (mx / 2, my / 2);
1214 for by in 0..8 {
1215 for bx in 0..8 {
1216 st.yuv.u[(cmy + by) * cw + cmx + bx] = r.read_bits(8) as u8;
1217 }
1218 }
1219 for by in 0..8 {
1220 for bx in 0..8 {
1221 st.yuv.v[(cmy + by) * cw + cmx + bx] = r.read_bits(8) as u8;
1222 }
1223 }
1224 let bx0 = mx / 4;
1226 let by0 = my / 4;
1227 for dy in 0..4 {
1228 for dx in 0..4 {
1229 let li = st.li(bx0 + dx, by0 + dy);
1230 st.nnz_luma[li] = 16;
1231 st.mode_luma[li] = -1;
1232 st.decoded[li] = true;
1233 }
1234 }
1235 let cbx0 = cmx / 4;
1236 let cby0 = cmy / 4;
1237 for comp in 0..2 {
1238 for dy in 0..2 {
1239 for dx in 0..2 {
1240 st.nnz_chroma[comp][(cby0 + dy) * st.cblk_w + cbx0 + dx] = 16;
1241 }
1242 }
1243 }
1244 st.mb_qp[(my / 16) * st.mb_w + (mx / 16)] = 0;
1246 Ok(())
1247}
1248
1249fn median3(a: i16, b: i16, c: i16) -> i16 {
1250 a + b + c - a.min(b).min(c) - a.max(b).max(c)
1251}
1252
1253fn mv_predict_16x16(st: &DecState, mb_x: u32, mb_y: u32) -> [i16; 2] {
1257 let bx0 = (mb_x / 4) as i32;
1258 let by0 = (mb_y / 4) as i32;
1259 let getn = |bx: i32, by: i32| -> (bool, bool, [i16; 2]) {
1261 if bx >= 0 && by >= 0 && (bx as usize) < st.blk_w && (by as usize) < st.blk_h {
1262 let li = (by as usize) * st.blk_w + bx as usize;
1263 if st.decoded[li] {
1264 if st.is_inter[li] {
1265 return (true, true, st.mv_l0[li]);
1266 }
1267 return (true, false, [0, 0]); }
1269 }
1270 (false, false, [0, 0])
1271 };
1272 let (_a_av, a_m, mva) = getn(bx0 - 1, by0); let (_b_av, b_m, mvb) = getn(bx0, by0 - 1); let (c_av, c_m0, mvc0) = getn(bx0 + 4, by0 - 1); let (mut c_m, mut mvc) = (c_m0, mvc0);
1276 if !c_av {
1277 let (_d_av, d_m, mvd) = getn(bx0 - 1, by0 - 1);
1279 c_m = d_m;
1280 mvc = mvd;
1281 }
1282 let b_mb_avail = mb_y > 0;
1284 let c_mb_avail = mb_y > 0 && (bx0 + 4 < st.blk_w as i32 || mb_x > 0);
1285 if !b_mb_avail && !c_mb_avail && mb_x > 0 {
1286 return mva;
1287 }
1288 let matches = a_m as i32 + b_m as i32 + c_m as i32;
1289 if matches == 1 {
1290 if a_m {
1291 return mva;
1292 }
1293 if b_m {
1294 return mvb;
1295 }
1296 return mvc;
1297 }
1298 [
1299 median3(mva[0], mvb[0], mvc[0]),
1300 median3(mva[1], mvb[1], mvc[1]),
1301 ]
1302}
1303
1304fn predict_pskip_mv(st: &DecState, mb_x: u32, mb_y: u32) -> [i16; 2] {
1306 let bx0 = (mb_x / 4) as usize;
1307 let by0 = (mb_y / 4) as usize;
1308 let a_avail = mb_x > 0;
1309 let b_avail = mb_y > 0;
1310 if !a_avail || !b_avail {
1311 return [0, 0];
1312 }
1313 let mva = st.mv_l0[by0 * st.blk_w + bx0 - 1];
1314 let mvb = st.mv_l0[(by0 - 1) * st.blk_w + bx0];
1315 if mva == [0, 0] || mvb == [0, 0] {
1317 return [0, 0];
1318 }
1319 let _ = (bx0, by0);
1320 mv_predict(st, mb_x as usize, mb_y as usize, 16, MvDir::None)
1321}
1322
1323fn interp_luma_core<F: Fn(isize, isize) -> i32>(get: F, fx: i32, fy: i32) -> i32 {
1325 let tap =
1326 |a: i32, b: i32, c: i32, d: i32, e: i32, f: i32| a - 5 * b + 20 * c + 20 * d - 5 * e + f;
1327 if fx == 0 && fy == 0 {
1328 return get(0, 0);
1329 }
1330 let hh = |dy: isize| -> i32 {
1332 clip1(
1333 (tap(
1334 get(-2, dy),
1335 get(-1, dy),
1336 get(0, dy),
1337 get(1, dy),
1338 get(2, dy),
1339 get(3, dy),
1340 ) + 16)
1341 >> 5,
1342 )
1343 };
1344 let vh = |dx: isize| -> i32 {
1345 clip1(
1346 (tap(
1347 get(dx, -2),
1348 get(dx, -1),
1349 get(dx, 0),
1350 get(dx, 1),
1351 get(dx, 2),
1352 get(dx, 3),
1353 ) + 16)
1354 >> 5,
1355 )
1356 };
1357 let jj = || -> i32 {
1358 let vi = |dx: isize| {
1359 tap(
1360 get(dx, -2),
1361 get(dx, -1),
1362 get(dx, 0),
1363 get(dx, 1),
1364 get(dx, 2),
1365 get(dx, 3),
1366 )
1367 };
1368 clip1((tap(vi(-2), vi(-1), vi(0), vi(1), vi(2), vi(3)) + 512) >> 10)
1369 };
1370 match (fx, fy) {
1371 (1, 0) => (get(0, 0) + hh(0) + 1) >> 1,
1372 (2, 0) => hh(0),
1373 (3, 0) => (get(1, 0) + hh(0) + 1) >> 1,
1374 (0, 1) => (get(0, 0) + vh(0) + 1) >> 1,
1375 (0, 2) => vh(0),
1376 (0, 3) => (get(0, 1) + vh(0) + 1) >> 1,
1377 (2, 2) => jj(),
1378 (1, 1) => (hh(0) + vh(0) + 1) >> 1,
1379 (3, 1) => (hh(0) + vh(1) + 1) >> 1,
1380 (1, 3) => (vh(0) + hh(1) + 1) >> 1,
1381 (3, 3) => (vh(1) + hh(1) + 1) >> 1,
1382 (2, 1) => (hh(0) + jj() + 1) >> 1,
1383 (1, 2) => (vh(0) + jj() + 1) >> 1,
1384 (3, 2) => (jj() + vh(1) + 1) >> 1,
1385 (2, 3) => (jj() + hh(1) + 1) >> 1,
1386 _ => get(0, 0),
1387 }
1388}
1389
1390fn interp_luma_sample(refr: &DecodedYuv, x: isize, y: isize, fx: i32, fy: i32) -> i32 {
1392 let w = refr.width as isize;
1393 let h = refr.height as isize;
1394 interp_luma_core(
1395 |dx, dy| {
1396 let sx = (x + dx).clamp(0, w - 1);
1397 let sy = (y + dy).clamp(0, h - 1);
1398 refr.y[(sy * w + sx) as usize] as i32
1399 },
1400 fx,
1401 fy,
1402 )
1403}
1404
1405fn mc_part_luma(
1407 st: &mut DecState,
1408 px: usize,
1409 py: usize,
1410 pw: usize,
1411 ph: usize,
1412 mv: [i16; 2],
1413 refr: &DecodedYuv,
1414) {
1415 let w = st.yuv.width as usize;
1416 let h = st.yuv.height as usize;
1417 let fx = (mv[0] & 3) as i32;
1418 let fy = (mv[1] & 3) as i32;
1419 let ix = (mv[0] >> 2) as isize;
1420 let iy = (mv[1] >> 2) as isize;
1421 if fx == 0 && fy == 0 {
1423 let sx0 = px as isize + ix;
1424 let sy0 = py as isize + iy;
1425 if sx0 >= 0
1426 && sy0 >= 0
1427 && sx0 + pw as isize <= w as isize
1428 && sy0 + ph as isize <= h as isize
1429 {
1430 let (sx0, sy0) = (sx0 as usize, sy0 as usize);
1431 for y in 0..ph {
1432 let s = (sy0 + y) * w + sx0;
1433 let d = (py + y) * w + px;
1434 st.yuv.y[d..d + pw].copy_from_slice(&refr.y[s..s + pw]);
1435 }
1436 return;
1437 }
1438 }
1439 let wi = w as isize;
1441 let hi = h as isize;
1442 let halo_ok = px as isize + ix - 2 >= 0
1443 && py as isize + iy - 2 >= 0
1444 && px as isize + ix + pw as isize + 2 < wi
1445 && py as isize + iy + ph as isize + 2 < hi;
1446 if halo_ok {
1447 let needs_j = matches!((fx, fy), (2, 2) | (2, 1) | (2, 3) | (1, 2) | (3, 2));
1450 if needs_j {
1451 let base_x = px as isize + ix;
1452 let base_y = py as isize + iy;
1453 let tap = |a: i32, b: i32, c: i32, d: i32, e: i32, f: i32| {
1454 a - 5 * b + 20 * c + 20 * d - 5 * e + f
1455 };
1456 let g = |rx: isize, ry: isize| refr.y[(ry * wi + rx) as usize] as i32;
1457 let mut vrow = [0i32; 21]; for y in 0..ph {
1459 let ry = base_y + y as isize;
1460 for c in 0..pw + 5 {
1461 let rx = base_x + c as isize - 2;
1462 vrow[c] = tap(
1463 g(rx, ry - 2),
1464 g(rx, ry - 1),
1465 g(rx, ry),
1466 g(rx, ry + 1),
1467 g(rx, ry + 2),
1468 g(rx, ry + 3),
1469 );
1470 }
1471 for x in 0..pw {
1472 let j = clip1(
1473 (tap(
1474 vrow[x],
1475 vrow[x + 1],
1476 vrow[x + 2],
1477 vrow[x + 3],
1478 vrow[x + 4],
1479 vrow[x + 5],
1480 ) + 512)
1481 >> 10,
1482 );
1483 let rx = base_x + x as isize;
1484 let val = match (fx, fy) {
1485 (2, 2) => j,
1486 (2, 1) => {
1487 let b = clip1(
1488 (tap(
1489 g(rx - 2, ry),
1490 g(rx - 1, ry),
1491 g(rx, ry),
1492 g(rx + 1, ry),
1493 g(rx + 2, ry),
1494 g(rx + 3, ry),
1495 ) + 16)
1496 >> 5,
1497 );
1498 (b + j + 1) >> 1
1499 }
1500 (2, 3) => {
1501 let s = clip1(
1502 (tap(
1503 g(rx - 2, ry + 1),
1504 g(rx - 1, ry + 1),
1505 g(rx, ry + 1),
1506 g(rx + 1, ry + 1),
1507 g(rx + 2, ry + 1),
1508 g(rx + 3, ry + 1),
1509 ) + 16)
1510 >> 5,
1511 );
1512 (j + s + 1) >> 1
1513 }
1514 (1, 2) => {
1515 let hp = clip1(
1516 (tap(
1517 g(rx, ry - 2),
1518 g(rx, ry - 1),
1519 g(rx, ry),
1520 g(rx, ry + 1),
1521 g(rx, ry + 2),
1522 g(rx, ry + 3),
1523 ) + 16)
1524 >> 5,
1525 );
1526 (hp + j + 1) >> 1
1527 }
1528 (3, 2) => {
1529 let m = clip1(
1530 (tap(
1531 g(rx + 1, ry - 2),
1532 g(rx + 1, ry - 1),
1533 g(rx + 1, ry),
1534 g(rx + 1, ry + 1),
1535 g(rx + 1, ry + 2),
1536 g(rx + 1, ry + 3),
1537 ) + 16)
1538 >> 5,
1539 );
1540 (j + m + 1) >> 1
1541 }
1542 _ => j,
1543 };
1544 st.yuv.y[(py + y) * w + px + x] = val as u8;
1545 }
1546 }
1547 return;
1548 }
1549 for y in 0..ph {
1550 for x in 0..pw {
1551 let bx = px as isize + x as isize + ix;
1552 let by = py as isize + y as isize + iy;
1553 let v = interp_luma_core(
1554 |dx, dy| refr.y[((by + dy) * wi + bx + dx) as usize] as i32,
1555 fx,
1556 fy,
1557 );
1558 st.yuv.y[(py + y) * w + px + x] = v as u8;
1559 }
1560 }
1561 return;
1562 }
1563 let needs_j = matches!((fx, fy), (2, 2) | (2, 1) | (2, 3) | (1, 2) | (3, 2));
1567 if needs_j {
1568 let base_x = px as isize + ix;
1569 let base_y = py as isize + iy;
1570 let tap =
1571 |a: i32, b: i32, c: i32, d: i32, e: i32, f: i32| a - 5 * b + 20 * c + 20 * d - 5 * e + f;
1572 let g = |rx: isize, ry: isize| {
1573 let cx = rx.clamp(0, wi - 1);
1574 let cy = ry.clamp(0, hi - 1);
1575 refr.y[(cy * wi + cx) as usize] as i32
1576 };
1577 let mut vrow = [0i32; 21]; for y in 0..ph {
1579 let ry = base_y + y as isize;
1580 for c in 0..pw + 5 {
1581 let rx = base_x + c as isize - 2;
1582 vrow[c] = tap(
1583 g(rx, ry - 2),
1584 g(rx, ry - 1),
1585 g(rx, ry),
1586 g(rx, ry + 1),
1587 g(rx, ry + 2),
1588 g(rx, ry + 3),
1589 );
1590 }
1591 for x in 0..pw {
1592 let j = clip1(
1593 (tap(
1594 vrow[x],
1595 vrow[x + 1],
1596 vrow[x + 2],
1597 vrow[x + 3],
1598 vrow[x + 4],
1599 vrow[x + 5],
1600 ) + 512)
1601 >> 10,
1602 );
1603 let rx = base_x + x as isize;
1604 let val = match (fx, fy) {
1605 (2, 2) => j,
1606 (2, 1) => {
1607 let b = clip1(
1608 (tap(
1609 g(rx - 2, ry),
1610 g(rx - 1, ry),
1611 g(rx, ry),
1612 g(rx + 1, ry),
1613 g(rx + 2, ry),
1614 g(rx + 3, ry),
1615 ) + 16)
1616 >> 5,
1617 );
1618 (b + j + 1) >> 1
1619 }
1620 (2, 3) => {
1621 let s = clip1(
1622 (tap(
1623 g(rx - 2, ry + 1),
1624 g(rx - 1, ry + 1),
1625 g(rx, ry + 1),
1626 g(rx + 1, ry + 1),
1627 g(rx + 2, ry + 1),
1628 g(rx + 3, ry + 1),
1629 ) + 16)
1630 >> 5,
1631 );
1632 (j + s + 1) >> 1
1633 }
1634 (1, 2) => {
1635 let hp = clip1(
1636 (tap(
1637 g(rx, ry - 2),
1638 g(rx, ry - 1),
1639 g(rx, ry),
1640 g(rx, ry + 1),
1641 g(rx, ry + 2),
1642 g(rx, ry + 3),
1643 ) + 16)
1644 >> 5,
1645 );
1646 (hp + j + 1) >> 1
1647 }
1648 (3, 2) => {
1649 let m = clip1(
1650 (tap(
1651 g(rx + 1, ry - 2),
1652 g(rx + 1, ry - 1),
1653 g(rx + 1, ry),
1654 g(rx + 1, ry + 1),
1655 g(rx + 1, ry + 2),
1656 g(rx + 1, ry + 3),
1657 ) + 16)
1658 >> 5,
1659 );
1660 (j + m + 1) >> 1
1661 }
1662 _ => j,
1663 };
1664 st.yuv.y[(py + y) * w + px + x] = val as u8;
1665 }
1666 }
1667 return;
1668 }
1669 for y in 0..ph {
1670 for x in 0..pw {
1671 let bx = px as isize + x as isize + ix;
1672 let by = py as isize + y as isize + iy;
1673 st.yuv.y[(py + y) * w + px + x] = interp_luma_sample(refr, bx, by, fx, fy) as u8;
1674 }
1675 }
1676}
1677
1678fn interp_chroma_sample(
1680 plane: &[u8],
1681 cw: isize,
1682 ch: isize,
1683 x: isize,
1684 y: isize,
1685 fx: i32,
1686 fy: i32,
1687) -> i32 {
1688 let get = |dx: isize, dy: isize| -> i32 {
1689 let sx = (x + dx).clamp(0, cw - 1);
1690 let sy = (y + dy).clamp(0, ch - 1);
1691 plane[(sy * cw + sx) as usize] as i32
1692 };
1693 let a = get(0, 0);
1694 let b = get(1, 0);
1695 let c = get(0, 1);
1696 let d = get(1, 1);
1697 ((8 - fx) * (8 - fy) * a + fx * (8 - fy) * b + (8 - fx) * fy * c + fx * fy * d + 32) >> 6
1698}
1699
1700fn mc_part_chroma(
1702 st: &mut DecState,
1703 px: usize,
1704 py: usize,
1705 pw: usize,
1706 ph: usize,
1707 mv: [i16; 2],
1708 refr: &DecodedYuv,
1709) {
1710 let cw = (st.yuv.width / 2) as isize;
1711 let chh = (st.yuv.height / 2) as isize;
1712 let cx = px / 2;
1713 let cy = py / 2;
1714 let cpw = pw / 2;
1715 let cph = ph / 2;
1716 let fx = (mv[0] & 7) as i32;
1717 let fy = (mv[1] & 7) as i32;
1718 let ix = (mv[0] >> 3) as isize;
1719 let iy = (mv[1] >> 3) as isize;
1720 let cwz = cw as usize;
1721 let integer = fx == 0 && fy == 0;
1722 let sx0 = cx as isize + ix;
1723 let sy0 = cy as isize + iy;
1724 let in_bounds = sx0 >= 0 && sy0 >= 0 && sx0 + cpw as isize <= cw && sy0 + cph as isize <= chh;
1725 for comp in 0..2 {
1726 let (dst, src) = if comp == 0 {
1727 (&mut st.yuv.u, &refr.u)
1728 } else {
1729 (&mut st.yuv.v, &refr.v)
1730 };
1731 if integer && in_bounds {
1732 let (sx0, sy0) = (sx0 as usize, sy0 as usize);
1733 for y in 0..cph {
1734 let s = (sy0 + y) * cwz + sx0;
1735 let d = (cy + y) * cwz + cx;
1736 dst[d..d + cpw].copy_from_slice(&src[s..s + cpw]);
1737 }
1738 continue;
1739 }
1740 for y in 0..cph {
1741 for x in 0..cpw {
1742 let bx = cx as isize + x as isize + ix;
1743 let by = cy as isize + y as isize + iy;
1744 dst[(cy + y) * cwz + cx + x] =
1745 interp_chroma_sample(src, cw, chh, bx, by, fx, fy) as u8;
1746 }
1747 }
1748 }
1749}
1750
1751fn mc_part(
1753 st: &mut DecState,
1754 px: usize,
1755 py: usize,
1756 pw: usize,
1757 ph: usize,
1758 mv: [i16; 2],
1759 refr: &DecodedYuv,
1760) {
1761 mc_part_luma(st, px, py, pw, ph, mv, refr);
1762 mc_part_chroma(st, px, py, pw, ph, mv, refr);
1763}
1764
1765fn store_part_mv(st: &mut DecState, px: usize, py: usize, pw: usize, ph: usize, mv: [i16; 2]) {
1767 let bx0 = px / 4;
1768 let by0 = py / 4;
1769 for dy in 0..ph / 4 {
1770 for dx in 0..pw / 4 {
1771 let li = (by0 + dy) * st.blk_w + bx0 + dx;
1772 st.mv_l0[li] = mv;
1773 st.is_inter[li] = true;
1774 st.mode_luma[li] = -1;
1775 st.nnz_luma[li] = 0;
1776 st.decoded[li] = true;
1777 }
1778 }
1779}
1780
1781#[derive(Clone, Copy, PartialEq)]
1783enum MvDir {
1784 None,
1785 A,
1786 B,
1787 C,
1788}
1789
1790fn part_neighbors(
1793 st: &DecState,
1794 px: usize,
1795 py: usize,
1796 pw: usize,
1797) -> ((bool, [i16; 2]), (bool, [i16; 2]), (bool, [i16; 2])) {
1798 let bx0 = (px / 4) as i32;
1799 let by0 = (py / 4) as i32;
1800 let getn = |bx: i32, by: i32| -> (bool, bool, [i16; 2]) {
1801 if bx >= 0 && by >= 0 && (bx as usize) < st.blk_w && (by as usize) < st.blk_h {
1802 let li = (by as usize) * st.blk_w + bx as usize;
1803 if st.decoded[li] {
1804 if st.is_inter[li] {
1805 return (true, true, st.mv_l0[li]);
1806 }
1807 return (true, false, [0, 0]);
1808 }
1809 }
1810 (false, false, [0, 0])
1811 };
1812 let (_a, am, mva) = getn(bx0 - 1, by0);
1813 let (_b, bm, mvb) = getn(bx0, by0 - 1);
1814 let (cav, cm0, mvc0) = getn(bx0 + (pw / 4) as i32, by0 - 1);
1815 let (mut cm, mut mvc) = (cm0, mvc0);
1816 if !cav {
1817 let (_d, dm, mvd) = getn(bx0 - 1, by0 - 1);
1818 cm = dm;
1819 mvc = mvd;
1820 }
1821 ((am, mva), (bm, mvb), (cm, mvc))
1822}
1823
1824fn mv_predict(st: &DecState, px: usize, py: usize, pw: usize, dir: MvDir) -> [i16; 2] {
1826 let ((am, mva), (bm, mvb), (cm, mvc)) = part_neighbors(st, px, py, pw);
1827 match dir {
1828 MvDir::A if am => return mva,
1829 MvDir::B if bm => return mvb,
1830 MvDir::C if cm => return mvc,
1831 _ => {}
1832 }
1833 let bx0 = (px / 4) as i32;
1835 let b_pic = (py / 4) > 0;
1836 let c_pic = (py / 4) > 0 && ((bx0 + (pw / 4) as i32) < st.blk_w as i32 || (px / 4) > 0);
1837 if !b_pic && !c_pic && (px / 4) > 0 {
1838 return mva;
1839 }
1840 let matches = am as i32 + bm as i32 + cm as i32;
1841 if matches == 1 {
1842 if am {
1843 return mva;
1844 }
1845 if bm {
1846 return mvb;
1847 }
1848 return mvc;
1849 }
1850 [
1851 median3(mva[0], mvb[0], mvc[0]),
1852 median3(mva[1], mvb[1], mvc[1]),
1853 ]
1854}
1855
1856fn set_mb_inter_grids(st: &mut DecState, mb_x: u32, mb_y: u32, mv: [i16; 2], qp: i32) {
1858 let bx0 = (mb_x / 4) as usize;
1859 let by0 = (mb_y / 4) as usize;
1860 for dy in 0..4 {
1861 for dx in 0..4 {
1862 let li = (by0 + dy) * st.blk_w + bx0 + dx;
1863 st.mv_l0[li] = mv;
1864 st.nnz_luma[li] = 0;
1865 st.mode_luma[li] = -1;
1866 st.is_inter[li] = true;
1867 st.decoded[li] = true;
1868 }
1869 }
1870 let cbx0 = (mb_x / 8) as usize;
1871 let cby0 = (mb_y / 8) as usize;
1872 for comp in 0..2 {
1873 for dy in 0..2 {
1874 for dx in 0..2 {
1875 st.nnz_chroma[comp][(cby0 + dy) * st.cblk_w + cbx0 + dx] = 0;
1876 }
1877 }
1878 }
1879 st.mb_qp[(mb_y / 16) as usize * st.mb_w + (mb_x / 16) as usize] = qp;
1880}
1881
1882fn decode_pskip(st: &mut DecState, mb_x: u32, mb_y: u32, qp: i32, refr: &DecodedYuv) {
1884 let mv = predict_pskip_mv(st, mb_x, mb_y);
1885 let (px, py) = (mb_x as usize, mb_y as usize);
1886 mc_part(st, px, py, 16, 16, mv, refr);
1887 store_part_mv(st, px, py, 16, 16, mv);
1888 st.mb_qp[(mb_y / 16) as usize * st.mb_w + (mb_x / 16) as usize] = qp;
1889}
1890
1891fn add_inter_luma_residual(
1893 r: &mut BitReader,
1894 st: &mut DecState,
1895 mb_x: u32,
1896 mb_y: u32,
1897 cbp_luma: u32,
1898 qp: i32,
1899) {
1900 let w = st.yuv.width as usize;
1901 let bx0 = (mb_x / 4) as usize;
1902 let by0 = (mb_y / 4) as usize;
1903 for blk in 0..16 {
1904 let (bx, by) = LUMA_4X4_BLOCK_XY[blk];
1905 let bx4 = bx0 + bx / 4;
1906 let by4 = by0 + by / 4;
1907 let li = by4 * st.blk_w + bx4;
1908 if cbp_luma & (1 << (blk / 4)) != 0 {
1909 let nc = st.luma_nc(bx4, by4);
1910 let (scan, tc) = residual_block_cavlc(r, 16, nc, TOTAL_ZEROS_16);
1911 st.nnz_luma[li] = tc;
1912 let mut block = [0i32; 16];
1913 for k in 0..16 {
1914 block[ZIGZAG_4X4[k]] = scan[k];
1915 }
1916 dequant_4x4(&mut block, qp);
1917 inverse_transform_4x4(&mut block);
1918 for yy in 0..4 {
1919 for xx in 0..4 {
1920 let px = mb_x as usize + bx + xx;
1921 let py = mb_y as usize + by + yy;
1922 let cur = st.yuv.y[py * w + px] as i32;
1923 st.yuv.y[py * w + px] = clip1(cur + block[yy * 4 + xx]) as u8;
1924 }
1925 }
1926 } else {
1927 st.nnz_luma[li] = 0;
1928 }
1929 }
1930}
1931
1932fn add_inter_chroma_residual(
1934 r: &mut BitReader,
1935 st: &mut DecState,
1936 mb_x: u32,
1937 mb_y: u32,
1938 cbp_chroma: u32,
1939 qp_y: i32,
1940 chroma_qp_off: i32,
1941) {
1942 let cw = (st.yuv.width / 2) as usize;
1943 let cmb_x = (mb_x / 2) as usize;
1944 let cmb_y = (mb_y / 2) as usize;
1945 let cbx0 = cmb_x / 4;
1946 let cby0 = cmb_y / 4;
1947 let qpc = chroma_qp(qp_y, chroma_qp_off);
1948 let mut dc = [[0i32; 4]; 2];
1949 if cbp_chroma != 0 {
1950 for comp in 0..2 {
1951 let (scan, _) = residual_block_cavlc(r, 4, -1, TOTAL_ZEROS_CHROMA);
1952 let f = inverse_hadamard_2x2([scan[0], scan[1], scan[2], scan[3]]);
1953 for i in 0..4 {
1954 dc[comp][i] = scale_chroma_dc(f[i], qpc);
1955 }
1956 }
1957 }
1958 let mut ac = [[[0i32; 16]; 4]; 2];
1959 if cbp_chroma == 2 {
1960 for comp in 0..2 {
1961 for blk in 0..4 {
1962 let bx = (blk % 2) * 4;
1963 let by = (blk / 2) * 4;
1964 let cbx4 = cbx0 + bx / 4;
1965 let cby4 = cby0 + by / 4;
1966 let nc = chroma_nc(st, comp, cbx4, cby4);
1967 let (scan, tc) = residual_block_cavlc(r, 15, nc, TOTAL_ZEROS_16);
1968 for k in 0..15 {
1969 ac[comp][blk][ZIGZAG_4X4[k + 1]] = scan[k];
1970 }
1971 st.nnz_chroma[comp][cby4 * st.cblk_w + cbx4] = tc;
1972 }
1973 }
1974 }
1975 if cbp_chroma == 0 {
1976 return;
1977 }
1978 for comp in 0..2 {
1979 let plane: &mut Vec<u8> = if comp == 0 {
1980 &mut st.yuv.u
1981 } else {
1982 &mut st.yuv.v
1983 };
1984 for blk in 0..4 {
1985 let bx = (blk % 2) * 4;
1986 let by = (blk / 2) * 4;
1987 let mut block = ac[comp][blk];
1988 dequant_4x4(&mut block, qpc);
1989 block[0] = dc[comp][blk];
1990 inverse_transform_4x4(&mut block);
1991 for yy in 0..4 {
1992 for xx in 0..4 {
1993 let px = cmb_x + bx + xx;
1994 let py = cmb_y + by + yy;
1995 let cur = plane[py * cw + px] as i32;
1996 plane[py * cw + px] = clip1(cur + block[yy * 4 + xx]) as u8;
1997 }
1998 }
1999 }
2000 }
2001}
2002
2003fn decode_p8x8(
2006 r: &mut BitReader,
2007 st: &mut DecState,
2008 px: usize,
2009 py: usize,
2010 refr: &DecodedYuv,
2011) -> Result<(), &'static str> {
2012 let mut sub_types = [0u32; 4];
2013 for s in sub_types.iter_mut() {
2014 *s = r.read_ue();
2015 if *s > 3 {
2016 return Err("bad sub_mb_type");
2017 }
2018 }
2019 for (i, &stype) in sub_types.iter().enumerate() {
2021 let sx = px + (i % 2) * 8;
2022 let sy = py + (i / 2) * 8;
2023 let parts: &[(usize, usize, usize, usize)] = match stype {
2024 0 => &[(0, 0, 8, 8)],
2025 1 => &[(0, 0, 8, 4), (0, 4, 8, 4)],
2026 2 => &[(0, 0, 4, 8), (4, 0, 4, 8)],
2027 _ => &[(0, 0, 4, 4), (4, 0, 4, 4), (0, 4, 4, 4), (4, 4, 4, 4)],
2028 };
2029 for &(ox, oy, pw, ph) in parts {
2030 let ppx = sx + ox;
2031 let ppy = sy + oy;
2032 let mvd_x = r.read_se() as i16;
2033 let mvd_y = r.read_se() as i16;
2034 let mvp = mv_predict(st, ppx, ppy, pw, MvDir::None);
2035 let mv = [mvp[0].wrapping_add(mvd_x), mvp[1].wrapping_add(mvd_y)];
2036 mc_part(st, ppx, ppy, pw, ph, mv, refr);
2037 store_part_mv(st, ppx, ppy, pw, ph, mv);
2038 }
2039 }
2040 Ok(())
2041}
2042
2043#[allow(clippy::too_many_arguments)]
2045fn decode_mb_p(
2046 r: &mut BitReader,
2047 st: &mut DecState,
2048 mb_x: u32,
2049 mb_y: u32,
2050 qp: &mut i32,
2051 pps: &Pps,
2052 refr: &DecodedYuv,
2053) -> Result<(), &'static str> {
2054 let mb_type = r.read_ue();
2055 if mb_type >= 5 {
2056 let it = mb_type - 5;
2057 if it == 25 {
2058 return decode_mb_ipcm(r, st, mb_x, mb_y);
2059 }
2060 if it == 0 {
2061 return decode_mb_i4x4(r, st, mb_x, mb_y, qp, pps);
2062 }
2063 if (1..=24).contains(&it) {
2064 return decode_mb_i16x16(r, st, mb_x, mb_y, qp, it, pps);
2065 }
2066 return Err("bad intra mb_type in P slice");
2067 }
2068 let px = mb_x as usize;
2070 let py = mb_y as usize;
2071 let do_part = |r: &mut BitReader,
2073 st: &mut DecState,
2074 ppx: usize,
2075 ppy: usize,
2076 pw: usize,
2077 ph: usize,
2078 dir: MvDir| {
2079 let mvd_x = r.read_se() as i16;
2080 let mvd_y = r.read_se() as i16;
2081 let mvp = mv_predict(st, ppx, ppy, pw, dir);
2082 let mv = [mvp[0].wrapping_add(mvd_x), mvp[1].wrapping_add(mvd_y)];
2083 mc_part(st, ppx, ppy, pw, ph, mv, refr);
2084 store_part_mv(st, ppx, ppy, pw, ph, mv);
2085 };
2086 match mb_type {
2087 0 => {
2088 do_part(r, st, px, py, 16, 16, MvDir::None);
2090 }
2091 1 => {
2092 do_part(r, st, px, py, 16, 8, MvDir::B);
2095 do_part(r, st, px, py + 8, 16, 8, MvDir::A);
2096 }
2097 2 => {
2098 do_part(r, st, px, py, 8, 16, MvDir::A);
2100 do_part(r, st, px + 8, py, 8, 16, MvDir::C);
2101 }
2102 3 | 4 => {
2103 decode_p8x8(r, st, px, py, refr)?;
2105 }
2106 _ => return Err("unknown P mb_type"),
2107 }
2108
2109 let codenum = r.read_ue() as usize;
2110 if codenum >= 48 {
2111 return Err("inter cbp codeNum out of range");
2112 }
2113 let cbp = CBP_INTER_MAP[codenum] as u32;
2114 let cbp_luma = cbp & 0xf;
2115 let cbp_chroma = cbp >> 4;
2116 let cur_qp = if cbp != 0 {
2117 let d = r.read_se();
2118 *qp = (*qp + d + 52) % 52;
2119 *qp
2120 } else {
2121 *qp
2122 };
2123 st.mb_qp[(mb_y / 16) as usize * st.mb_w + (mb_x / 16) as usize] = cur_qp;
2124
2125 add_inter_luma_residual(r, st, mb_x, mb_y, cbp_luma, cur_qp);
2126 add_inter_chroma_residual(
2127 r,
2128 st,
2129 mb_x,
2130 mb_y,
2131 cbp_chroma,
2132 cur_qp,
2133 pps.chroma_qp_index_offset,
2134 );
2135 Ok(())
2136}
2137
2138fn reconstruct_luma_4x4(st: &mut DecState, px: usize, py: usize, mode: u8, residual: &[i32; 16]) {
2140 let pred = st.predict_luma_4x4(px, py, mode);
2141 let w = st.yuv.width as usize;
2142 for yy in 0..4 {
2143 for xx in 0..4 {
2144 let v = clip1(pred[yy * 4 + xx] + residual[yy * 4 + xx]);
2145 st.yuv.y[(py + yy) * w + px + xx] = v as u8;
2146 }
2147 }
2148 let di = st.li(px / 4, py / 4);
2149 st.decoded[di] = true;
2150}
2151
2152fn decode_mb_i16x16(
2153 r: &mut BitReader,
2154 st: &mut DecState,
2155 mb_x: u32,
2156 mb_y: u32,
2157 qp: &mut i32,
2158 mb_type: u32,
2159 pps: &Pps,
2160) -> Result<(), &'static str> {
2161 let m1 = mb_type - 1;
2162 let i16_pred = (m1 % 4) as u8;
2163 let cbp_chroma = (m1 / 4) % 3;
2164 let cbp_luma = if m1 / 12 != 0 { 15 } else { 0 };
2165
2166 let intra_chroma_pred_mode = r.read_ue() as u8;
2167 let mb_qp_delta = r.read_se();
2168 *qp = (*qp + mb_qp_delta + 52) % 52;
2169 let cur_qp = *qp;
2170 st.mb_qp[(mb_y / 16) as usize * st.mb_w + (mb_x / 16) as usize] = cur_qp;
2171
2172 let bx0 = (mb_x / 4) as usize;
2174 let by0 = (mb_y / 4) as usize;
2175 let dc_nc = st.luma_nc(bx0, by0);
2176 let (dc_scan, _) = residual_block_cavlc(r, 16, dc_nc, TOTAL_ZEROS_16);
2177 let mut dc_block = [0i32; 16];
2178 for k in 0..16 {
2179 dc_block[ZIGZAG_4X4[k]] = dc_scan[k];
2180 }
2181 inverse_hadamard_4x4(&mut dc_block);
2182 scale_luma_dc(&mut dc_block, cur_qp);
2183
2184 let mut luma_ac = [[0i32; 16]; 16];
2186 for blk in 0..16 {
2187 let (bx, by) = LUMA_4X4_BLOCK_XY[blk];
2188 let bx4 = bx0 + bx / 4;
2189 let by4 = by0 + by / 4;
2190 let li = st.li(bx4, by4);
2191 if cbp_luma != 0 {
2192 let nc = st.luma_nc(bx4, by4);
2193 let (ac_scan, tc) = residual_block_cavlc(r, 15, nc, TOTAL_ZEROS_16);
2194 for k in 0..15 {
2195 luma_ac[blk][ZIGZAG_4X4[k + 1]] = ac_scan[k];
2196 }
2197 st.nnz_luma[li] = tc;
2198 } else {
2199 st.nnz_luma[li] = 0;
2200 }
2201 }
2202
2203 let w = st.yuv.width as usize;
2205 let mut top = [0i32; 16];
2206 let mut left = [0i32; 16];
2207 let top_avail = mb_y > 0;
2208 let left_avail = mb_x > 0;
2209 if top_avail {
2210 for x in 0..16 {
2211 top[x] = st.yuv.y[(mb_y as usize - 1) * w + mb_x as usize + x] as i32;
2212 }
2213 }
2214 if left_avail {
2215 for y in 0..16 {
2216 left[y] = st.yuv.y[(mb_y as usize + y) * w + mb_x as usize - 1] as i32;
2217 }
2218 }
2219 let corner = if top_avail && left_avail {
2220 st.yuv.y[(mb_y as usize - 1) * w + mb_x as usize - 1] as i32
2221 } else {
2222 0
2223 };
2224 let pred = intra_16x16_predict(i16_pred, &top, corner, &left, top_avail, left_avail);
2225
2226 for blk in 0..16 {
2228 let (bx, by) = LUMA_4X4_BLOCK_XY[blk];
2229 let dc_idx = (by / 4) * 4 + (bx / 4);
2230 let mut block = luma_ac[blk];
2231 dequant_4x4(&mut block, cur_qp);
2232 block[0] = dc_block[dc_idx];
2233 inverse_transform_4x4(&mut block);
2234 for yy in 0..4 {
2235 for xx in 0..4 {
2236 let px = mb_x as usize + bx + xx;
2237 let py = mb_y as usize + by + yy;
2238 let p = pred[(by + yy) * 16 + (bx + xx)];
2239 st.yuv.y[py * w + px] = clip1(p + block[yy * 4 + xx]) as u8;
2240 }
2241 }
2242 let di = st.li((mb_x as usize + bx) / 4, (mb_y as usize + by) / 4);
2243 st.decoded[di] = true;
2244 }
2245
2246 decode_chroma(
2247 r,
2248 st,
2249 mb_x,
2250 mb_y,
2251 cbp_chroma,
2252 intra_chroma_pred_mode,
2253 cur_qp,
2254 pps.chroma_qp_index_offset,
2255 )
2256}
2257
2258fn decode_mb_i4x4(
2259 r: &mut BitReader,
2260 st: &mut DecState,
2261 mb_x: u32,
2262 mb_y: u32,
2263 qp: &mut i32,
2264 pps: &Pps,
2265) -> Result<(), &'static str> {
2266 let bx0 = (mb_x / 4) as usize;
2267 let by0 = (mb_y / 4) as usize;
2268
2269 let mut modes = [0u8; 16];
2271 for blk in 0..16 {
2272 let (bx, by) = LUMA_4X4_BLOCK_XY[blk];
2273 let bx4 = bx0 + bx / 4;
2274 let by4 = by0 + by / 4;
2275 let pred_mode = st.pred_i4x4_mode(bx4, by4);
2276 let mode = if r.read_bit() == 1 {
2277 pred_mode
2278 } else {
2279 let rem = r.read_bits(3) as i32;
2280 if rem < pred_mode {
2281 rem
2282 } else {
2283 rem + 1
2284 }
2285 };
2286 modes[blk] = mode as u8;
2287 let li = st.li(bx4, by4);
2288 st.mode_luma[li] = mode as i8;
2289 }
2290
2291 let intra_chroma_pred_mode = r.read_ue() as u8;
2292 let codenum = r.read_ue() as usize;
2293 if codenum >= 48 {
2294 return Err("cbp codeNum out of range");
2295 }
2296 let cbp = CBP_INTRA_MAP[codenum] as u32;
2297 let cbp_luma = cbp & 0xf;
2298 let cbp_chroma = cbp >> 4;
2299
2300 let cur_qp = if cbp != 0 {
2301 let mb_qp_delta = r.read_se();
2302 *qp = (*qp + mb_qp_delta + 52) % 52;
2303 *qp
2304 } else {
2305 *qp
2306 };
2307 st.mb_qp[(mb_y / 16) as usize * st.mb_w + (mb_x / 16) as usize] = cur_qp;
2308
2309 for blk in 0..16 {
2311 let (bx, by) = LUMA_4X4_BLOCK_XY[blk];
2312 let bx4 = bx0 + bx / 4;
2313 let by4 = by0 + by / 4;
2314 let mut block = [0i32; 16];
2315 let li = st.li(bx4, by4);
2316 if cbp_luma & (1 << (blk / 4)) != 0 {
2317 let nc = st.luma_nc(bx4, by4);
2318 let (scan, tc) = residual_block_cavlc(r, 16, nc, TOTAL_ZEROS_16);
2319 for k in 0..16 {
2320 block[ZIGZAG_4X4[k]] = scan[k];
2321 }
2322 st.nnz_luma[li] = tc;
2323 } else {
2324 st.nnz_luma[li] = 0;
2325 }
2326 dequant_4x4(&mut block, cur_qp);
2327 inverse_transform_4x4(&mut block);
2328 reconstruct_luma_4x4(
2329 st,
2330 mb_x as usize + bx,
2331 mb_y as usize + by,
2332 modes[blk],
2333 &block,
2334 );
2335 }
2336
2337 decode_chroma(
2338 r,
2339 st,
2340 mb_x,
2341 mb_y,
2342 cbp_chroma,
2343 intra_chroma_pred_mode,
2344 cur_qp,
2345 pps.chroma_qp_index_offset,
2346 )
2347}
2348
2349fn chroma_qp(qp_y: i32, offset: i32) -> i32 {
2351 let qpi = (qp_y + offset).clamp(0, 51);
2352 if qpi < 30 {
2353 qpi
2354 } else {
2355 const MAP: [i32; 22] = [
2356 29, 30, 31, 32, 32, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, 39, 39, 39, 39,
2357 ];
2358 MAP[(qpi - 30) as usize]
2359 }
2360}
2361
2362fn inverse_hadamard_2x2(c: [i32; 4]) -> [i32; 4] {
2364 [
2365 c[0] + c[1] + c[2] + c[3],
2366 c[0] - c[1] + c[2] - c[3],
2367 c[0] + c[1] - c[2] - c[3],
2368 c[0] - c[1] - c[2] + c[3],
2369 ]
2370}
2371
2372fn scale_chroma_dc(f: i32, qpc: i32) -> i32 {
2374 let ls = 16 * NORM_ADJUST_4X4[(qpc % 6) as usize][0];
2375 ((f * ls) << (qpc / 6)) >> 5
2376}
2377
2378fn chroma_nc(st: &DecState, comp: usize, cbx4: usize, cby4: usize) -> i32 {
2380 let na = if cbx4 > 0 {
2381 st.nnz_chroma[comp][cby4 * st.cblk_w + cbx4 - 1] as i32
2382 } else {
2383 -1
2384 };
2385 let nb = if cby4 > 0 {
2386 st.nnz_chroma[comp][(cby4 - 1) * st.cblk_w + cbx4] as i32
2387 } else {
2388 -1
2389 };
2390 combine_nc(na, nb)
2391}
2392
2393fn decode_chroma(
2395 r: &mut BitReader,
2396 st: &mut DecState,
2397 mb_x: u32,
2398 mb_y: u32,
2399 cbp_chroma: u32,
2400 chroma_pred_mode: u8,
2401 qp_y: i32,
2402 chroma_qp_offset: i32,
2403) -> Result<(), &'static str> {
2404 let cw = (st.yuv.width / 2) as usize;
2405 let cmb_x = (mb_x / 2) as usize;
2406 let cmb_y = (mb_y / 2) as usize;
2407 let cbx0 = cmb_x / 4;
2408 let cby0 = cmb_y / 4;
2409 let qpc = chroma_qp(qp_y, chroma_qp_offset);
2410
2411 let mut dc = [[0i32; 4]; 2];
2414 if cbp_chroma != 0 {
2415 for comp in 0..2 {
2416 let (scan, _) = residual_block_cavlc(r, 4, -1, TOTAL_ZEROS_CHROMA);
2417 let raw = [scan[0], scan[1], scan[2], scan[3]];
2419 let f = inverse_hadamard_2x2(raw);
2420 for i in 0..4 {
2421 dc[comp][i] = scale_chroma_dc(f[i], qpc);
2422 }
2423 }
2424 }
2425 let mut ac = [[[0i32; 16]; 4]; 2]; if cbp_chroma == 2 {
2427 for comp in 0..2 {
2428 for blk in 0..4 {
2429 let bx = (blk % 2) * 4;
2430 let by = (blk / 2) * 4;
2431 let cbx4 = cbx0 + bx / 4;
2432 let cby4 = cby0 + by / 4;
2433 let nc = chroma_nc(st, comp, cbx4, cby4);
2434 let (scan, tc) = residual_block_cavlc(r, 15, nc, TOTAL_ZEROS_16);
2435 for k in 0..15 {
2436 ac[comp][blk][ZIGZAG_4X4[k + 1]] = scan[k];
2437 }
2438 st.nnz_chroma[comp][cby4 * st.cblk_w + cbx4] = tc;
2439 }
2440 }
2441 }
2442
2443 let ca_t = cmb_y > 0;
2445 let ca_l = cmb_x > 0;
2446 for comp in 0..2 {
2447 let plane: &mut Vec<u8> = if comp == 0 {
2448 &mut st.yuv.u
2449 } else {
2450 &mut st.yuv.v
2451 };
2452 let mut ct = [0i32; 8];
2453 let mut cl = [0i32; 8];
2454 if ca_t {
2455 for x in 0..8 {
2456 ct[x] = plane[(cmb_y - 1) * cw + cmb_x + x] as i32;
2457 }
2458 }
2459 if ca_l {
2460 for y in 0..8 {
2461 cl[y] = plane[(cmb_y + y) * cw + cmb_x - 1] as i32;
2462 }
2463 }
2464 let corner = if ca_t && ca_l {
2465 plane[(cmb_y - 1) * cw + cmb_x - 1] as i32
2466 } else {
2467 0
2468 };
2469 let cpred = intra_chroma_predict(chroma_pred_mode, &ct, corner, &cl, ca_t, ca_l);
2470
2471 for blk in 0..4 {
2472 let bx = (blk % 2) * 4;
2473 let by = (blk / 2) * 4;
2474 let mut block = ac[comp][blk];
2475 dequant_4x4(&mut block, qpc);
2476 block[0] = dc[comp][blk]; inverse_transform_4x4(&mut block);
2478 for yy in 0..4 {
2479 for xx in 0..4 {
2480 let px = cmb_x + bx + xx;
2481 let py = cmb_y + by + yy;
2482 let p = cpred[(by + yy) * 8 + (bx + xx)];
2483 plane[py * cw + px] = clip1(p + block[yy * 4 + xx]) as u8;
2484 }
2485 }
2486 }
2487 }
2488 Ok(())
2489}
2490
2491fn iclip(v: i32, lo: i32, hi: i32) -> i32 {
2494 v.clamp(lo, hi)
2495}
2496
2497fn deblock_thresh(qpav: i32, alpha_off: i32, beta_off: i32, bs: u8) -> (i32, i32, i32) {
2499 let ia = iclip(qpav + alpha_off, 0, 51) as usize;
2500 let ib = iclip(qpav + beta_off, 0, 51) as usize;
2501 let tc0 = if (1..=3).contains(&bs) {
2503 TC0_TABLE[ia][(bs - 1) as usize] as i32
2504 } else {
2505 0
2506 };
2507 (ALPHA_TABLE[ia] as i32, BETA_TABLE[ib] as i32, tc0)
2508}
2509
2510#[allow(clippy::too_many_arguments)]
2512fn deblock_luma_edge(
2513 plane: &mut [u8],
2514 w: usize,
2515 vert: bool,
2516 ex: usize,
2517 ey: usize,
2518 len: usize,
2519 bs: u8,
2520 alpha: i32,
2521 beta: i32,
2522 tc0: i32,
2523) {
2524 if bs == 0 || alpha == 0 {
2525 return;
2526 }
2527 let across: isize = if vert { 1 } else { w as isize };
2528 for i in 0..len {
2529 let p0i: isize = if vert {
2530 ((ey + i) * w + (ex - 1)) as isize
2531 } else {
2532 ((ey - 1) * w + (ex + i)) as isize
2533 };
2534 let idx = |o: isize| -> usize { (p0i + o * across) as usize };
2535 let p0 = plane[idx(0)] as i32;
2536 let p1 = plane[idx(-1)] as i32;
2537 let p2 = plane[idx(-2)] as i32;
2538 let p3 = plane[idx(-3)] as i32;
2539 let q0 = plane[idx(1)] as i32;
2540 let q1 = plane[idx(2)] as i32;
2541 let q2 = plane[idx(3)] as i32;
2542 if (p0 - q0).abs() >= alpha || (p1 - p0).abs() >= beta || (q1 - q0).abs() >= beta {
2543 continue;
2544 }
2545 let ap = (p2 - p0).abs();
2546 let aq = (q2 - q0).abs();
2547 if bs < 4 {
2548 let mut tc = tc0;
2549 if ap < beta {
2550 tc += 1;
2551 }
2552 if aq < beta {
2553 tc += 1;
2554 }
2555 let delta = iclip(((q0 - p0) * 4 + (p1 - q1) + 4) >> 3, -tc, tc);
2556 plane[idx(0)] = clip1(p0 + delta) as u8;
2557 plane[idx(1)] = clip1(q0 - delta) as u8;
2558 if ap < beta {
2559 let d = iclip((p2 + ((p0 + q0 + 1) >> 1) - 2 * p1) >> 1, -tc0, tc0);
2560 plane[idx(-1)] = clip1(p1 + d) as u8;
2561 }
2562 if aq < beta {
2563 let d = iclip((q2 + ((p0 + q0 + 1) >> 1) - 2 * q1) >> 1, -tc0, tc0);
2564 plane[idx(2)] = clip1(q1 + d) as u8;
2565 }
2566 } else {
2567 let strong = (p0 - q0).abs() < (alpha >> 2) + 2;
2568 if ap < beta && strong {
2569 plane[idx(0)] = clip1((p2 + 2 * p1 + 2 * p0 + 2 * q0 + q1 + 4) >> 3) as u8;
2570 plane[idx(-1)] = clip1((p2 + p1 + p0 + q0 + 2) >> 2) as u8;
2571 plane[idx(-2)] = clip1((2 * p3 + 3 * p2 + p1 + p0 + q0 + 4) >> 3) as u8;
2572 } else {
2573 plane[idx(0)] = clip1((2 * p1 + p0 + q1 + 2) >> 2) as u8;
2574 }
2575 if aq < beta && strong {
2576 let q3 = plane[idx(4)] as i32;
2577 plane[idx(1)] = clip1((q2 + 2 * q1 + 2 * q0 + 2 * p0 + p1 + 4) >> 3) as u8;
2578 plane[idx(2)] = clip1((q2 + q1 + q0 + p0 + 2) >> 2) as u8;
2579 plane[idx(3)] = clip1((2 * q3 + 3 * q2 + q1 + q0 + p0 + 4) >> 3) as u8;
2580 } else {
2581 plane[idx(1)] = clip1((2 * q1 + q0 + p1 + 2) >> 2) as u8;
2582 }
2583 }
2584 }
2585}
2586
2587#[allow(clippy::too_many_arguments)]
2589fn deblock_chroma_edge(
2590 plane: &mut [u8],
2591 cw: usize,
2592 vert: bool,
2593 ex: usize,
2594 ey: usize,
2595 len: usize,
2596 bs: u8,
2597 alpha: i32,
2598 beta: i32,
2599 tc0: i32,
2600) {
2601 if bs == 0 || alpha == 0 {
2602 return;
2603 }
2604 let across: isize = if vert { 1 } else { cw as isize };
2605 for i in 0..len {
2606 let p0i: isize = if vert {
2607 ((ey + i) * cw + (ex - 1)) as isize
2608 } else {
2609 ((ey - 1) * cw + (ex + i)) as isize
2610 };
2611 let idx = |o: isize| -> usize { (p0i + o * across) as usize };
2612 let p0 = plane[idx(0)] as i32;
2613 let p1 = plane[idx(-1)] as i32;
2614 let q0 = plane[idx(1)] as i32;
2615 let q1 = plane[idx(2)] as i32;
2616 if (p0 - q0).abs() >= alpha || (p1 - p0).abs() >= beta || (q1 - q0).abs() >= beta {
2617 continue;
2618 }
2619 if bs < 4 {
2620 let tc = tc0 + 1;
2621 let delta = iclip(((q0 - p0) * 4 + (p1 - q1) + 4) >> 3, -tc, tc);
2622 plane[idx(0)] = clip1(p0 + delta) as u8;
2623 plane[idx(1)] = clip1(q0 - delta) as u8;
2624 } else {
2625 plane[idx(0)] = clip1((2 * p1 + p0 + q1 + 2) >> 2) as u8;
2626 plane[idx(1)] = clip1((2 * q1 + q0 + p1 + 2) >> 2) as u8;
2627 }
2628 }
2629}
2630
2631fn boundary_strength(st: &DecState, p_li: usize, q_li: usize, is_mb_edge: bool) -> u8 {
2635 let p_intra = !st.is_inter[p_li];
2636 let q_intra = !st.is_inter[q_li];
2637 if p_intra || q_intra {
2638 return if is_mb_edge { 4 } else { 3 };
2639 }
2640 if st.nnz_luma[p_li] > 0 || st.nnz_luma[q_li] > 0 {
2641 return 2;
2642 }
2643 let m = st.mv_l0[p_li];
2645 let n = st.mv_l0[q_li];
2646 if (m[0] - n[0]).abs() >= 4 || (m[1] - n[1]).abs() >= 4 {
2647 return 1;
2648 }
2649 0
2650}
2651
2652fn deblock_frame(
2653 st: &mut DecState,
2654 mb_w: usize,
2655 mb_h: usize,
2656 alpha_off: i32,
2657 beta_off: i32,
2658 chroma_qp_off: i32,
2659) {
2660 let w = st.yuv.width as usize;
2661 let cw = (st.yuv.width / 2) as usize;
2662 let blk_w = st.blk_w;
2663 for mby in 0..mb_h {
2664 for mbx in 0..mb_w {
2665 let qp = st.mb_qp[mby * mb_w + mbx];
2666 let qp_left = if mbx > 0 {
2667 st.mb_qp[mby * mb_w + mbx - 1]
2668 } else {
2669 qp
2670 };
2671 let qp_top = if mby > 0 {
2672 st.mb_qp[(mby - 1) * mb_w + mbx]
2673 } else {
2674 qp
2675 };
2676 let qbx = mbx * 4; let qby = mby * 4;
2678
2679 for k in 0..4usize {
2681 let xe = k * 4;
2682 if xe == 0 && mbx == 0 {
2683 continue;
2684 }
2685 let is_mb_edge = xe == 0;
2686 let qp2 = if is_mb_edge { qp_left } else { qp };
2687 let qpav = (qp + qp2 + 1) >> 1;
2688 for seg in 0..4usize {
2689 let qx = qbx + k;
2690 let qy = qby + seg;
2691 let q_li = qy * blk_w + qx;
2692 let p_li = qy * blk_w + qx - 1;
2693 let bs = boundary_strength(st, p_li, q_li, is_mb_edge);
2694 if bs == 0 {
2695 continue;
2696 }
2697 let (a, b, t) = deblock_thresh(qpav, alpha_off, beta_off, bs);
2698 deblock_luma_edge(
2699 &mut st.yuv.y,
2700 w,
2701 true,
2702 mbx * 16 + xe,
2703 mby * 16 + seg * 4,
2704 4,
2705 bs,
2706 a,
2707 b,
2708 t,
2709 );
2710 }
2711 }
2712 for k in 0..4usize {
2714 let ye = k * 4;
2715 if ye == 0 && mby == 0 {
2716 continue;
2717 }
2718 let is_mb_edge = ye == 0;
2719 let qp2 = if is_mb_edge { qp_top } else { qp };
2720 let qpav = (qp + qp2 + 1) >> 1;
2721 for seg in 0..4usize {
2722 let qx = qbx + seg;
2723 let qy = qby + k;
2724 let q_li = qy * blk_w + qx;
2725 let p_li = (qy - 1) * blk_w + qx;
2726 let bs = boundary_strength(st, p_li, q_li, is_mb_edge);
2727 if bs == 0 {
2728 continue;
2729 }
2730 let (a, b, t) = deblock_thresh(qpav, alpha_off, beta_off, bs);
2731 deblock_luma_edge(
2732 &mut st.yuv.y,
2733 w,
2734 false,
2735 mbx * 16 + seg * 4,
2736 mby * 16 + ye,
2737 4,
2738 bs,
2739 a,
2740 b,
2741 t,
2742 );
2743 }
2744 }
2745 let qpc = chroma_qp(qp, chroma_qp_off);
2747 let qpc_left = chroma_qp(qp_left, chroma_qp_off);
2748 let qpc_top = chroma_qp(qp_top, chroma_qp_off);
2749 for comp in 0..2usize {
2750 for ck in 0..2usize {
2752 let cxe = ck * 4;
2753 let luma_k = ck * 2; if cxe == 0 && mbx == 0 {
2755 continue;
2756 }
2757 let is_mb_edge = cxe == 0;
2758 let qpav = (qpc + if is_mb_edge { qpc_left } else { qpc } + 1) >> 1;
2759 for seg in 0..4usize {
2760 let qx = qbx + luma_k;
2761 let qy = qby + seg;
2762 let q_li = qy * blk_w + qx;
2763 let p_li = qy * blk_w + qx - 1;
2764 let bs = boundary_strength(st, p_li, q_li, is_mb_edge);
2765 if bs == 0 {
2766 continue;
2767 }
2768 let (a, b, t) = deblock_thresh(qpav, alpha_off, beta_off, bs);
2769 let plane = if comp == 0 {
2770 &mut st.yuv.u
2771 } else {
2772 &mut st.yuv.v
2773 };
2774 deblock_chroma_edge(
2775 plane,
2776 cw,
2777 true,
2778 mbx * 8 + cxe,
2779 mby * 8 + seg * 2,
2780 2,
2781 bs,
2782 a,
2783 b,
2784 t,
2785 );
2786 }
2787 }
2788 for ck in 0..2usize {
2790 let cye = ck * 4;
2791 let luma_k = ck * 2;
2792 if cye == 0 && mby == 0 {
2793 continue;
2794 }
2795 let is_mb_edge = cye == 0;
2796 let qpav = ((qpc + if is_mb_edge { qpc_top } else { qpc }) + 1) >> 1;
2797 for seg in 0..4usize {
2798 let qx = qbx + seg;
2799 let qy = qby + luma_k;
2800 let q_li = qy * blk_w + qx;
2801 let p_li = (qy - 1) * blk_w + qx;
2802 let bs = boundary_strength(st, p_li, q_li, is_mb_edge);
2803 if bs == 0 {
2804 continue;
2805 }
2806 let (a, b, t) = deblock_thresh(qpav, alpha_off, beta_off, bs);
2807 let plane = if comp == 0 {
2808 &mut st.yuv.u
2809 } else {
2810 &mut st.yuv.v
2811 };
2812 deblock_chroma_edge(
2813 plane,
2814 cw,
2815 false,
2816 mbx * 8 + seg * 2,
2817 mby * 8 + cye,
2818 2,
2819 bs,
2820 a,
2821 b,
2822 t,
2823 );
2824 }
2825 }
2826 }
2827 }
2828 }
2829}
2830
2831fn is_prefix_free(entries: &[(u8, u16)], label: &str) -> bool {
2835 let mut ok = true;
2836 for i in 0..entries.len() {
2837 for j in 0..entries.len() {
2838 if i == j {
2839 continue;
2840 }
2841 let (la, ca) = entries[i];
2842 let (lb, cb) = entries[j];
2843 if la <= lb && (cb >> (lb - la)) == ca {
2844 crate::println!(
2845 " PREFIX-CONFLICT in {}: ({},{:b}) is prefix of ({},{:b})",
2846 label,
2847 la,
2848 ca,
2849 lb,
2850 cb
2851 );
2852 ok = false;
2853 }
2854 }
2855 }
2856 ok
2857}
2858
2859fn check_token_complete(t: &[TokEntry], max_tc: u8, label: &str) -> bool {
2862 let mut ok = true;
2863 for tc in 0..=max_tc {
2864 let max_t1 = if tc == 0 { 0 } else { tc.min(3) };
2865 for t1 in 0..=max_t1 {
2866 let count = t.iter().filter(|&&(_, _, c, o)| c == tc && o == t1).count();
2867 if count != 1 {
2868 crate::println!(
2869 " TOKEN {} ({},{}) appears {} times (want 1)",
2870 label,
2871 tc,
2872 t1,
2873 count
2874 );
2875 ok = false;
2876 }
2877 }
2878 }
2879 ok
2880}
2881
2882pub fn tables_selftest() {
2884 let mut ok = true;
2885 let toks: [(&str, &[TokEntry]); 4] = [
2886 ("coeff_token_0", COEFF_TOKEN_0),
2887 ("coeff_token_2", COEFF_TOKEN_2),
2888 ("coeff_token_4", COEFF_TOKEN_4),
2889 ("coeff_token_cdc", COEFF_TOKEN_CHROMA_DC),
2890 ];
2891 for (name, t) in toks {
2892 let e: Vec<(u8, u16)> = t.iter().map(|&(l, c, _, _)| (l, c)).collect();
2893 if !is_prefix_free(&e, name) {
2894 ok = false;
2895 }
2896 }
2897 if !check_token_complete(COEFF_TOKEN_0, 16, "tok0") {
2898 ok = false;
2899 }
2900 if !check_token_complete(COEFF_TOKEN_2, 16, "tok2") {
2901 ok = false;
2902 }
2903 if !check_token_complete(COEFF_TOKEN_4, 16, "tok4") {
2904 ok = false;
2905 }
2906 if !check_token_complete(COEFF_TOKEN_CHROMA_DC, 4, "tokCDC") {
2907 ok = false;
2908 }
2909 for (i, row) in TOTAL_ZEROS_16.iter().enumerate() {
2911 let tc = i + 1;
2912 if row.len() != 17 - tc {
2913 crate::println!(
2914 " TZ16 row tc={} has {} entries (want {})",
2915 tc,
2916 row.len(),
2917 17 - tc
2918 );
2919 ok = false;
2920 }
2921 }
2922 for (i, row) in TOTAL_ZEROS_16.iter().enumerate() {
2923 if !is_prefix_free(row, "tz16") {
2924 crate::println!(" (tz16 row tc={})", i + 1);
2925 ok = false;
2926 }
2927 }
2928 for row in TOTAL_ZEROS_CHROMA.iter() {
2929 if !is_prefix_free(row, "tzC") {
2930 ok = false;
2931 }
2932 }
2933 for row in RUN_BEFORE.iter() {
2934 if !is_prefix_free(row, "run_before") {
2935 ok = false;
2936 }
2937 }
2938 if !ok {
2940 crate::println!("H264_TABLES: CONFLICTS FOUND");
2941 }
2942}
2943
2944fn run_golden(
2948 clip: &[u8],
2949 ref_yuv: &[u8],
2950) -> Result<(usize, usize, usize, usize, usize), &'static str> {
2951 let nals = split_annexb(clip);
2952 let mut sps: Option<Sps> = None;
2953 let mut pps: Option<Pps> = None;
2954 let mut reference: Option<DecodedYuv> = None;
2955 for nu in &nals {
2956 match nu.unit_type {
2957 7 => {
2958 sps = Some(parse_sps(&nu.rbsp)?);
2959 }
2960 8 => {
2961 pps = Some(parse_pps(&nu.rbsp)?);
2962 }
2963 1 | 5 => {
2964 let s = sps.as_ref().ok_or("no SPS")?;
2965 let p = pps.as_ref().ok_or("no PPS")?;
2966 let frame = decode_slice(s, p, &nu.rbsp, nu.unit_type == 5, reference.as_ref())?;
2967 reference = Some(frame);
2968 }
2969 _ => {}
2970 }
2971 }
2972 let yuv = reference.ok_or("no slice decoded")?;
2973 let yn = (yuv.width * yuv.height) as usize;
2974 let cn = yuv.u.len();
2975 let fsize = yn + 2 * cn;
2977 let nframes = ref_yuv.len() / fsize;
2978 let off = (nframes.saturating_sub(1)) * fsize;
2979 let mut ym = 0;
2980 for i in 0..yn {
2981 if yuv.y[i] == ref_yuv[off + i] {
2982 ym += 1;
2983 }
2984 }
2985 let mut um = 0;
2986 for i in 0..cn {
2987 if yuv.u[i] == ref_yuv[off + yn + i] {
2988 um += 1;
2989 }
2990 }
2991 let mut vm = 0;
2992 for i in 0..cn {
2993 if yuv.v[i] == ref_yuv[off + yn + cn + i] {
2994 vm += 1;
2995 }
2996 }
2997 Ok((ym, um, vm, yn, cn))
2998}
2999
3000fn run_golden_debug(clip: &[u8], ref_yuv: &[u8]) {
3002 let nals = split_annexb(clip);
3003 let mut sps: Option<Sps> = None;
3004 let mut pps: Option<Pps> = None;
3005 let mut reference: Option<DecodedYuv> = None;
3006 for nu in &nals {
3007 match nu.unit_type {
3008 7 => sps = parse_sps(&nu.rbsp).ok(),
3009 8 => pps = parse_pps(&nu.rbsp).ok(),
3010 1 | 5 => {
3011 if let (Some(s), Some(p)) = (sps.as_ref(), pps.as_ref()) {
3012 if let Ok(f) =
3013 decode_slice(s, p, &nu.rbsp, nu.unit_type == 5, reference.as_ref())
3014 {
3015 reference = Some(f);
3016 }
3017 }
3018 }
3019 _ => {}
3020 }
3021 }
3022 if let Some(yuv) = reference {
3023 let w = yuv.width as usize;
3024 let h = yuv.height as usize;
3025 let fsize = w * h + 2 * yuv.u.len();
3026 let off = (ref_yuv.len() / fsize).saturating_sub(1) * fsize;
3027 let mut shown = 0;
3028 'outer: for mby in (0..h).step_by(16) {
3029 for mbx in (0..w).step_by(16) {
3030 let mut bad = 0;
3031 let mut first = (0u8, 0u8, 0usize, 0usize);
3032 for yy in 0..16 {
3033 for xx in 0..16 {
3034 let i = (mby + yy) * w + mbx + xx;
3035 if yuv.y[i] != ref_yuv[off + i] {
3036 if bad == 0 {
3037 first = (yuv.y[i], ref_yuv[off + i], mbx + xx, mby + yy);
3038 }
3039 bad += 1;
3040 }
3041 }
3042 }
3043 if bad > 0 {
3044 crate::println!(
3045 " MB({},{}) bad={}/256 first@({},{}) got={} exp={}",
3046 mbx,
3047 mby,
3048 bad,
3049 first.2,
3050 first.3,
3051 first.0,
3052 first.1
3053 );
3054 shown += 1;
3055 if shown >= 8 {
3056 break 'outer;
3057 }
3058 }
3059 }
3060 }
3061 }
3062}
3063
3064pub fn golden_test() -> bool {
3066 use super::h264_golden::*;
3067 tables_selftest();
3068 let mut pass = 0usize;
3069 let mut total = 0usize;
3070 for (name, clip, refy) in [
3071 ("flat", FLAT_H264.as_slice(), FLAT_YUV.as_slice()),
3072 ("clip", CLIP_H264.as_slice(), CLIP_YUV.as_slice()),
3073 ("big", BIG_H264.as_slice(), BIG_YUV.as_slice()),
3074 ("dbclip", DBCLIP_H264.as_slice(), DBCLIP_YUV.as_slice()),
3075 ("dbbig", DBBIG_H264.as_slice(), DBBIG_YUV.as_slice()),
3076 ("pskip", PSKIP_H264.as_slice(), PSKIP_YUV.as_slice()),
3077 ("pint16", PINT16_H264.as_slice(), PINT16_YUV.as_slice()),
3078 ("psub", PSUB_H264.as_slice(), PSUB_YUV.as_slice()),
3079 ("ppart", PPART_H264.as_slice(), PPART_YUV.as_slice()),
3080 ("dbp", DBP_H264.as_slice(), DBP_YUV.as_slice()),
3081 ] {
3082 match run_golden(clip, refy) {
3083 Ok((ym, um, vm, yn, cn)) => {
3084 total += 1;
3085 if ym == yn && um == cn && vm == cn {
3086 pass += 1;
3087 } else {
3088 crate::println!(
3090 "H264_GOLDEN {}: MISMATCH Y {}/{} U {}/{} V {}/{}",
3091 name,
3092 ym,
3093 yn,
3094 um,
3095 cn,
3096 vm,
3097 cn
3098 );
3099 if ym != yn {
3100 run_golden_debug(clip, refy);
3101 }
3102 }
3103 }
3104 Err(e) => {
3105 total += 1;
3106 crate::println!("H264_GOLDEN {}: ERROR {}", name, e);
3107 }
3108 }
3109 }
3110 crate::info!("[H264] Golden test pass: {}/{}", pass, total);
3112 pass == total
3113}