1#![allow(dead_code, clippy::needless_range_loop)]
14
15use alloc::string::String;
16use alloc::vec::Vec;
17
18pub struct BitReader<'a> {
22 data: &'a [u8],
23 byte_pos: usize,
24 bit_pos: u8, }
26
27impl<'a> BitReader<'a> {
28 pub fn new(data: &'a [u8]) -> Self {
29 Self {
30 data,
31 byte_pos: 0,
32 bit_pos: 0,
33 }
34 }
35
36 pub fn is_eof(&self) -> bool {
38 self.byte_pos >= self.data.len()
39 }
40
41 pub fn more_rbsp_data(&self) -> bool {
45 let Some(last) = self.data.iter().rposition(|&b| b != 0) else {
46 return false;
47 };
48 let tz = self.data.get(last).map_or(0, |b| b.trailing_zeros() as usize);
49 let stop_bit = last * 8 + (7 - tz);
50 self.byte_pos * 8 + (self.bit_pos as usize) < stop_bit
51 }
52
53 pub fn read_bit(&mut self) -> u32 {
55 if self.byte_pos >= self.data.len() {
56 return 0;
57 }
58 let byte = self.data[self.byte_pos];
59 let bit = (byte >> (7 - self.bit_pos)) & 1;
60 self.bit_pos += 1;
61 if self.bit_pos == 8 {
62 self.bit_pos = 0;
63 self.byte_pos += 1;
64 }
65 bit as u32
66 }
67
68 pub fn bit_position(&self) -> usize {
70 self.byte_pos * 8 + self.bit_pos as usize
71 }
72
73 pub fn byte_align(&mut self) {
75 if self.bit_pos != 0 {
76 self.bit_pos = 0;
77 self.byte_pos += 1;
78 }
79 }
80
81 pub fn read_bits(&mut self, n: u32) -> u32 {
83 let mut v = 0u32;
84 for _ in 0..n.min(32) {
86 v = (v << 1) | self.read_bit();
87 }
88 v
89 }
90
91 pub fn read_ue(&mut self) -> u32 {
94 let mut leading_zeros = 0u32;
95 while !self.is_eof() && self.read_bit() == 0 {
96 leading_zeros += 1;
97 if leading_zeros > 31 {
98 break;
99 } }
101 if leading_zeros == 0 {
102 return 0;
103 }
104 let suffix = self.read_bits(leading_zeros);
105 (1u32 << leading_zeros) - 1 + suffix
106 }
107
108 pub fn read_se(&mut self) -> i32 {
110 let k = self.read_ue();
111 if k == 0 {
112 0
113 } else if k & 1 == 1 {
114 (k.div_ceil(2)) as i32
115 } else {
116 -((k / 2) as i32)
117 }
118 }
119}
120
121pub fn extract_rbsp(payload: &[u8]) -> Vec<u8> {
124 let mut out = Vec::with_capacity(payload.len());
125 let mut zeros = 0usize;
126 let mut i = 0;
127 while i < payload.len() {
128 let b = payload[i];
129 if zeros >= 2 && b == 0x03 {
130 zeros = 0;
132 i += 1;
133 continue;
134 }
135 out.push(b);
136 if b == 0x00 {
137 zeros += 1;
138 } else {
139 zeros = 0;
140 }
141 i += 1;
142 }
143 out
144}
145
146#[derive(Clone)]
149pub struct NalUnit {
150 pub ref_idc: u8,
151 pub unit_type: u8,
152 pub rbsp: Vec<u8>, }
154
155impl NalUnit {
156 fn from_ebsp(ebsp: &[u8]) -> Option<NalUnit> {
157 if ebsp.is_empty() {
158 return None;
159 }
160 let header = ebsp[0];
161 if (header >> 7) & 1 != 0 {
162 return None;
163 } Some(NalUnit {
165 ref_idc: (header >> 5) & 3,
166 unit_type: header & 0x1F,
167 rbsp: extract_rbsp(&ebsp[1..]),
168 })
169 }
170}
171
172pub fn split_annexb(data: &[u8]) -> Vec<NalUnit> {
174 let mut nals = Vec::new();
175 let mut i = 0;
176 let n = data.len();
177 let mut start = None;
179 while i + 3 <= n {
180 if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 {
181 start = Some(i + 3);
182 i += 3;
183 break;
184 }
185 i += 1;
186 }
187 let mut s = match start {
188 Some(s) => s,
189 None => return nals,
190 };
191 while i + 3 <= n {
192 if data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1 {
193 let mut end = i;
195 if end > s && data[end - 1] == 0 {
196 end -= 1;
197 }
198 if let Some(nu) = NalUnit::from_ebsp(&data[s..end]) {
199 nals.push(nu);
200 }
201 s = i + 3;
202 i += 3;
203 } else {
204 i += 1;
205 }
206 }
207 if s < n {
208 if let Some(nu) = NalUnit::from_ebsp(&data[s..n]) {
209 nals.push(nu);
210 }
211 }
212 nals
213}
214
215pub fn split_avcc(data: &[u8], length_size: usize) -> Vec<NalUnit> {
217 let mut nals = Vec::new();
218 let mut i = 0;
219 while i + length_size <= data.len() {
220 let mut len = 0usize;
221 for _ in 0..length_size {
222 len = (len << 8) | data[i] as usize;
223 i += 1;
224 }
225 if len == 0 || i + len > data.len() {
226 break;
227 }
228 if let Some(nu) = NalUnit::from_ebsp(&data[i..i + len]) {
229 nals.push(nu);
230 }
231 i += len;
232 }
233 nals
234}
235
236#[derive(Default, Clone)]
239pub struct Sps {
240 pub profile_idc: u8,
241 pub level_idc: u8,
242 pub seq_parameter_set_id: u32,
243 pub log2_max_frame_num: u32,
244 pub pic_order_cnt_type: u32,
245 pub log2_max_pic_order_cnt_lsb: u32,
246 pub width: u32,
247 pub height: u32,
248 pub frame_mbs_only_flag: u32,
249 pub width_mbs: u32,
251 pub height_mbs: u32,
252 pub max_num_ref_frames: u32,
254 pub direct_8x8_inference_flag: bool,
256 pub crop_x: u32,
258 pub crop_y: u32,
259}
260
261pub fn parse_sps(rbsp: &[u8]) -> Result<Sps, &'static str> {
263 let mut r = BitReader::new(rbsp);
264 let mut sps = Sps {
265 profile_idc: r.read_bits(8) as u8,
266 ..Default::default()
267 };
268 let _constraint_flags = r.read_bits(8); sps.level_idc = r.read_bits(8) as u8;
270 sps.seq_parameter_set_id = r.read_ue();
271
272 if matches!(
274 sps.profile_idc,
275 100 | 110 | 122 | 244 | 44 | 83 | 86 | 118 | 128 | 138 | 139 | 134 | 135
276 ) {
277 let chroma_format_idc = r.read_ue();
281 if chroma_format_idc != 1 {
282 return Err("chroma format other than 4:2:0 not supported");
283 }
284 if r.read_ue() != 0 || r.read_ue() != 0 {
285 return Err("bit depth other than 8 not supported");
286 }
287 if r.read_bit() == 1 {
288 return Err("qpprime_y_zero_transform_bypass not supported");
289 }
290 if r.read_bit() == 1 {
291 return Err("SPS scaling matrix not supported");
292 }
293 }
294
295 sps.log2_max_frame_num = r.read_ue() + 4;
296 sps.pic_order_cnt_type = r.read_ue();
297 if sps.pic_order_cnt_type == 0 {
298 sps.log2_max_pic_order_cnt_lsb = r.read_ue() + 4;
299 } else if sps.pic_order_cnt_type == 1 {
300 let _delta_pic_order_always_zero_flag = r.read_bit();
301 let _offset_for_non_ref_pic = r.read_se();
302 let _offset_for_top_to_bottom_field = r.read_se();
303 let num_ref_frames_in_pic_order_cnt_cycle = r.read_ue().min(256);
305 for _ in 0..num_ref_frames_in_pic_order_cnt_cycle {
306 let _ = r.read_se();
307 }
308 }
309 sps.max_num_ref_frames = r.read_ue().min(16);
310 let _gaps_in_frame_num_value_allowed_flag = r.read_bit();
311
312 let pic_width_in_mbs_minus1 = r.read_ue();
313 let pic_height_in_map_units_minus1 = r.read_ue();
314 sps.frame_mbs_only_flag = r.read_bit();
315 if sps.frame_mbs_only_flag == 0 {
316 let _mb_adaptive_frame_field_flag = r.read_bit();
317 }
318 sps.direct_8x8_inference_flag = r.read_bit() == 1;
319
320 let mut crop_left = 0u32;
321 let mut crop_right = 0u32;
322 let mut crop_top = 0u32;
323 let mut crop_bottom = 0u32;
324 let frame_cropping_flag = r.read_bit();
325 if frame_cropping_flag == 1 {
326 crop_left = r.read_ue();
327 crop_right = r.read_ue();
328 crop_top = r.read_ue();
329 crop_bottom = r.read_ue();
330 }
331
332 let width_mbs = pic_width_in_mbs_minus1 + 1;
333 let height_map_units = pic_height_in_map_units_minus1 + 1;
334 sps.width_mbs = width_mbs;
335 sps.height_mbs = height_map_units * (2 - sps.frame_mbs_only_flag);
336 let raw_width = width_mbs * 16;
337 let raw_height = height_map_units * 16 * (2 - sps.frame_mbs_only_flag);
338
339 let crop_unit_x = 2u32;
341 let crop_unit_y = 2u32 * (2 - sps.frame_mbs_only_flag);
342 sps.width = raw_width.saturating_sub((crop_left + crop_right) * crop_unit_x);
343 sps.height = raw_height.saturating_sub((crop_top + crop_bottom) * crop_unit_y);
344 sps.crop_x = crop_left * crop_unit_x;
345 sps.crop_y = crop_top * crop_unit_y;
346 if sps.width == 0 || sps.height == 0 {
347 return Err("SPS produced zero dimensions");
348 }
349 Ok(sps)
350}
351
352#[derive(Default, Clone)]
353pub struct Pps {
354 pub pic_parameter_set_id: u32,
355 pub seq_parameter_set_id: u32,
356 pub entropy_coding_mode_flag: u32, pub bottom_field_pic_order_in_frame_present_flag: u32, pub pic_init_qp: i32, pub deblocking_filter_control_present_flag: u32,
360 pub constrained_intra_pred_flag: u32,
361 pub redundant_pic_cnt_present_flag: u32,
362 pub chroma_qp_index_offset: i32,
363 pub num_ref_idx_l0_default_active: u32,
365 pub weighted_pred_flag: u32,
367 pub num_ref_idx_l1_default_active: u32,
369 pub weighted_bipred_idc: u32,
371 pub transform_8x8_mode_flag: bool,
373 pub second_chroma_qp_index_offset: i32,
375}
376
377impl Pps {
378 pub fn chroma_qp_offsets(&self) -> [i32; 2] {
380 [self.chroma_qp_index_offset, self.second_chroma_qp_index_offset]
381 }
382}
383
384pub fn parse_pps(rbsp: &[u8]) -> Result<Pps, &'static str> {
385 let mut r = BitReader::new(rbsp);
386 let mut pps = Pps {
387 pic_parameter_set_id: r.read_ue(),
388 seq_parameter_set_id: r.read_ue(),
389 entropy_coding_mode_flag: r.read_bit(),
390 ..Default::default()
391 };
392 pps.bottom_field_pic_order_in_frame_present_flag = r.read_bit();
393 let num_slice_groups_minus1 = r.read_ue();
394 if num_slice_groups_minus1 > 0 {
395 return Err("slice groups not supported");
397 }
398 pps.num_ref_idx_l0_default_active = r.read_ue().min(31) + 1;
399 pps.num_ref_idx_l1_default_active = r.read_ue().min(31) + 1;
400 pps.weighted_pred_flag = r.read_bit();
401 pps.weighted_bipred_idc = r.read_bits(2);
402 let pic_init_qp_minus26 = r.read_se();
403 pps.pic_init_qp = 26 + pic_init_qp_minus26;
404 let _pic_init_qs_minus26 = r.read_se();
405 pps.chroma_qp_index_offset = r.read_se();
406 pps.deblocking_filter_control_present_flag = r.read_bit();
407 pps.constrained_intra_pred_flag = r.read_bit();
408 pps.redundant_pic_cnt_present_flag = r.read_bit();
409 pps.second_chroma_qp_index_offset = pps.chroma_qp_index_offset;
411 if r.more_rbsp_data() {
412 pps.transform_8x8_mode_flag = r.read_bit() == 1;
413 if r.read_bit() == 1 {
414 return Err("PPS scaling matrix not supported");
415 }
416 pps.second_chroma_qp_index_offset = r.read_se();
417 }
418 Ok(pps)
419}
420
421pub fn parse_avcc(avcc: &[u8]) -> Option<(usize, Vec<Vec<u8>>, Vec<Vec<u8>>)> {
424 if avcc.len() < 7 || avcc[0] != 1 {
425 return None;
426 }
427 let length_size = (avcc[4] & 0x03) as usize + 1;
428 let num_sps = (avcc[5] & 0x1F) as usize;
429 let mut i = 6;
430 let mut sps_list = Vec::new();
431 for _ in 0..num_sps {
432 if i + 2 > avcc.len() {
433 return None;
434 }
435 let len = ((avcc[i] as usize) << 8) | avcc[i + 1] as usize;
436 i += 2;
437 if i + len > avcc.len() {
438 return None;
439 }
440 sps_list.push(avcc[i..i + len].to_vec());
441 i += len;
442 }
443 if i >= avcc.len() {
444 return None;
445 }
446 let num_pps = avcc[i] as usize;
447 i += 1;
448 let mut pps_list = Vec::new();
449 for _ in 0..num_pps {
450 if i + 2 > avcc.len() {
451 return None;
452 }
453 let len = ((avcc[i] as usize) << 8) | avcc[i + 1] as usize;
454 i += 2;
455 if i + len > avcc.len() {
456 return None;
457 }
458 pps_list.push(avcc[i..i + len].to_vec());
459 i += len;
460 }
461 Some((length_size, sps_list, pps_list))
462}
463
464pub struct DecodedVideoFrame {
467 pub width: u32,
468 pub height: u32,
469 pub rgb_data: Vec<u8>,
470}
471
472pub struct H264Decoder {
473 sps: Option<Sps>,
474 pps: Option<Pps>,
475 width: u32,
476 height: u32,
477}
478
479impl Default for H264Decoder {
480 fn default() -> Self {
481 Self::new()
482 }
483}
484
485impl H264Decoder {
486 pub fn new() -> Self {
487 Self {
488 sps: None,
489 pps: None,
490 width: 0,
491 height: 0,
492 }
493 }
494
495 pub fn set_parameter_sets(&mut self, sps_payloads: &[Vec<u8>], pps_payloads: &[Vec<u8>]) {
497 for p in sps_payloads {
498 if let Some(nu) = NalUnit::from_ebsp(p) {
499 if nu.unit_type == 7 {
500 if let Ok(s) = parse_sps(&nu.rbsp) {
501 self.width = s.width;
502 self.height = s.height;
503 self.sps = Some(s);
504 }
505 }
506 }
507 }
508 for p in pps_payloads {
509 if let Some(nu) = NalUnit::from_ebsp(p) {
510 if nu.unit_type == 8 {
511 if let Ok(pp) = parse_pps(&nu.rbsp) {
512 self.pps = Some(pp);
513 }
514 }
515 }
516 }
517 }
518
519 pub fn decode_nal(&mut self, nal_data: &[u8]) -> Result<DecodedVideoFrame, &'static str> {
522 let nals = if has_start_code(nal_data) {
524 split_annexb(nal_data)
525 } else {
526 match NalUnit::from_ebsp(nal_data) {
528 Some(nu) => alloc::vec![nu],
529 None => return Err("invalid NAL"),
530 }
531 };
532
533 let mut produced: Option<DecodedVideoFrame> = None;
534 for nu in &nals {
535 match nu.unit_type {
536 7 => {
537 let s = parse_sps(&nu.rbsp)?;
538 self.width = s.width;
539 self.height = s.height;
540 self.sps = Some(s);
541 }
542 8 => {
543 self.pps = Some(parse_pps(&nu.rbsp)?);
544 }
545 1 | 5 => {
546 produced = Some(self.decode_slice(&nu.rbsp, nu.unit_type == 5)?);
547 }
548 _ => {}
549 }
550 }
551 produced.ok_or("no picture in NAL (parameter set only)")
552 }
553
554 pub fn decode_access_unit_avcc(
558 &mut self,
559 sample: &[u8],
560 length_size: usize,
561 ) -> Option<DecodedVideoFrame> {
562 let nals = split_avcc(sample, length_size);
563 let mut produced = None;
564 for nu in &nals {
565 match nu.unit_type {
566 7 => {
567 if let Ok(s) = parse_sps(&nu.rbsp) {
568 self.width = s.width;
569 self.height = s.height;
570 self.sps = Some(s);
571 }
572 }
573 8 => {
574 if let Ok(pp) = parse_pps(&nu.rbsp) {
575 self.pps = Some(pp);
576 }
577 }
578 1 | 5 => {
579 if let Ok(f) = self.decode_slice(&nu.rbsp, nu.unit_type == 5) {
580 produced = Some(f);
581 }
582 }
583 _ => {}
584 }
585 }
586 produced
587 }
588
589 fn decode_slice(
590 &mut self,
591 _rbsp: &[u8],
592 _is_idr: bool,
593 ) -> Result<DecodedVideoFrame, &'static str> {
594 let w = if self.width == 0 { 320 } else { self.width };
596 let h = if self.height == 0 { 180 } else { self.height };
597
598 let rgb_data = alloc::vec![0x20u8; (w * h * 3) as usize];
601 Ok(DecodedVideoFrame {
602 width: w,
603 height: h,
604 rgb_data,
605 })
606 }
607}
608
609fn has_start_code(d: &[u8]) -> bool {
610 d.len() >= 3
611 && d[0] == 0
612 && d[1] == 0
613 && (d[2] == 1 || (d.len() >= 4 && d[2] == 0 && d[3] == 1))
614}
615
616pub(crate) const NORM_ADJUST_4X4: [[i32; 3]; 6] = [
623 [10, 16, 13],
624 [11, 18, 14],
625 [13, 20, 16],
626 [14, 23, 18],
627 [16, 25, 20],
628 [18, 29, 23],
629];
630
631#[allow(clippy::manual_is_multiple_of)]
632fn pos_class_4x4(i: usize, j: usize) -> usize {
633 if i % 2 == 0 && j % 2 == 0 {
634 0
635 } else if i % 2 == 1 && j % 2 == 1 {
636 1
637 } else {
638 2
639 }
640}
641
642pub fn dequant_4x4(block: &mut [i32; 16], qp: i32) {
645 let m = (qp % 6) as usize;
646 let shift = qp / 6;
647 for i in 0..4 {
648 for j in 0..4 {
649 let idx = i * 4 + j;
650 let level_scale = 16 * NORM_ADJUST_4X4[m][pos_class_4x4(i, j)];
651 let c = block[idx];
652 block[idx] = if qp >= 24 {
653 (c * level_scale) << (shift - 4)
654 } else {
655 (c * level_scale + (1 << (3 - shift))) >> (4 - shift)
656 };
657 }
658 }
659}
660
661pub fn inverse_transform_4x4(block: &mut [i32; 16]) {
663 for i in 0..4 {
665 let o = i * 4;
666 let (d0, d1, d2, d3) = (block[o], block[o + 1], block[o + 2], block[o + 3]);
667 let e0 = d0 + d2;
668 let e1 = d0 - d2;
669 let e2 = (d1 >> 1) - d3;
670 let e3 = d1 + (d3 >> 1);
671 block[o] = e0 + e3;
672 block[o + 1] = e1 + e2;
673 block[o + 2] = e1 - e2;
674 block[o + 3] = e0 - e3;
675 }
676 for j in 0..4 {
678 let (d0, d1, d2, d3) = (block[j], block[4 + j], block[8 + j], block[12 + j]);
679 let e0 = d0 + d2;
680 let e1 = d0 - d2;
681 let e2 = (d1 >> 1) - d3;
682 let e3 = d1 + (d3 >> 1);
683 block[j] = (e0 + e3 + 32) >> 6;
684 block[4 + j] = (e1 + e2 + 32) >> 6;
685 block[8 + j] = (e1 - e2 + 32) >> 6;
686 block[12 + j] = (e0 - e3 + 32) >> 6;
687 }
688}
689
690fn clip1(v: i32) -> i32 {
696 v.clamp(0, 255)
697}
698
699pub fn intra_4x4_predict(
703 mode: u8,
704 top: &[i32; 8],
705 corner: i32,
706 left: &[i32; 4],
707 top_avail: bool,
708 left_avail: bool,
709) -> [i32; 16] {
710 let mut pred = [0i32; 16];
711 let pt = |i: i32| -> i32 {
713 if i < 0 {
714 corner
715 } else {
716 top[i as usize]
717 }
718 };
719 let pl = |i: i32| -> i32 {
720 if i < 0 {
721 corner
722 } else {
723 left[i as usize]
724 }
725 };
726 let put = |x: usize, y: usize, v: i32, p: &mut [i32; 16]| {
727 p[y * 4 + x] = v;
728 };
729
730 match mode {
731 0 => {
732 for y in 0..4 {
734 for x in 0..4 {
735 put(x, y, top[x], &mut pred);
736 }
737 }
738 }
739 1 => {
740 for y in 0..4 {
742 for x in 0..4 {
743 put(x, y, left[y], &mut pred);
744 }
745 }
746 }
747 2 => {
748 let dc = match (top_avail, left_avail) {
750 (true, true) => {
751 (top[0] + top[1] + top[2] + top[3] + left[0] + left[1] + left[2] + left[3] + 4)
752 >> 3
753 }
754 (true, false) => (top[0] + top[1] + top[2] + top[3] + 2) >> 2,
755 (false, true) => (left[0] + left[1] + left[2] + left[3] + 2) >> 2,
756 (false, false) => 128,
757 };
758 for v in pred.iter_mut() {
759 *v = dc;
760 }
761 }
762 3 => {
763 for y in 0..4i32 {
765 for x in 0..4i32 {
766 let v = if x == 3 && y == 3 {
767 (pt(6) + 3 * pt(7) + 2) >> 2
768 } else {
769 (pt(x + y) + 2 * pt(x + y + 1) + pt(x + y + 2) + 2) >> 2
770 };
771 put(x as usize, y as usize, v, &mut pred);
772 }
773 }
774 }
775 4 => {
776 for y in 0..4i32 {
778 for x in 0..4i32 {
779 let v = if x > y {
780 (pt(x - y - 2) + 2 * pt(x - y - 1) + pt(x - y) + 2) >> 2
781 } else if x < y {
782 (pl(y - x - 2) + 2 * pl(y - x - 1) + pl(y - x) + 2) >> 2
783 } else {
784 (pt(0) + 2 * corner + pl(0) + 2) >> 2
785 };
786 put(x as usize, y as usize, v, &mut pred);
787 }
788 }
789 }
790 5 => {
791 for y in 0..4i32 {
793 for x in 0..4i32 {
794 let z = 2 * x - y;
795 let v = if z >= 0 && z % 2 == 0 {
796 (pt(x - (y >> 1) - 1) + pt(x - (y >> 1)) + 1) >> 1
797 } else if z >= 0 {
798 (pt(x - (y >> 1) - 2) + 2 * pt(x - (y >> 1) - 1) + pt(x - (y >> 1)) + 2)
799 >> 2
800 } else if z == -1 {
801 (pl(0) + 2 * corner + pt(0) + 2) >> 2
802 } else {
803 (pl(y - 1) + 2 * pl(y - 2) + pl(y - 3) + 2) >> 2
804 };
805 put(x as usize, y as usize, v, &mut pred);
806 }
807 }
808 }
809 6 => {
810 for y in 0..4i32 {
812 for x in 0..4i32 {
813 let z = 2 * y - x;
814 let v = if z >= 0 && z % 2 == 0 {
815 (pl(y - (x >> 1) - 1) + pl(y - (x >> 1)) + 1) >> 1
816 } else if z >= 0 {
817 (pl(y - (x >> 1) - 2) + 2 * pl(y - (x >> 1) - 1) + pl(y - (x >> 1)) + 2)
818 >> 2
819 } else if z == -1 {
820 (pl(0) + 2 * corner + pt(0) + 2) >> 2
821 } else {
822 (pt(x - 1) + 2 * pt(x - 2) + pt(x - 3) + 2) >> 2
823 };
824 put(x as usize, y as usize, v, &mut pred);
825 }
826 }
827 }
828 7 => {
829 for y in 0..4i32 {
831 for x in 0..4i32 {
832 let v = if y % 2 == 0 {
833 (pt(x + (y >> 1)) + pt(x + (y >> 1) + 1) + 1) >> 1
834 } else {
835 (pt(x + (y >> 1)) + 2 * pt(x + (y >> 1) + 1) + pt(x + (y >> 1) + 2) + 2)
836 >> 2
837 };
838 put(x as usize, y as usize, v, &mut pred);
839 }
840 }
841 }
842 8 => {
843 for y in 0..4i32 {
845 for x in 0..4i32 {
846 let z = x + 2 * y;
847 let v = if z < 5 && z % 2 == 0 {
848 (pl(y + (x >> 1)) + pl(y + (x >> 1) + 1) + 1) >> 1
849 } else if z < 5 {
850 (pl(y + (x >> 1)) + 2 * pl(y + (x >> 1) + 1) + pl(y + (x >> 1) + 2) + 2)
851 >> 2
852 } else if z == 5 {
853 (pl(2) + 3 * pl(3) + 2) >> 2
854 } else {
855 pl(3)
856 };
857 put(x as usize, y as usize, v, &mut pred);
858 }
859 }
860 }
861 _ => {}
862 }
863 pred
864}
865
866pub fn intra_16x16_predict(
869 mode: u8,
870 top: &[i32; 16],
871 corner: i32,
872 left: &[i32; 16],
873 top_avail: bool,
874 left_avail: bool,
875) -> [i32; 256] {
876 let mut pred = [0i32; 256];
877 match mode {
878 0 => {
879 for y in 0..16 {
880 for x in 0..16 {
881 pred[y * 16 + x] = top[x];
882 }
883 }
884 }
885 1 => {
886 for y in 0..16 {
887 for x in 0..16 {
888 pred[y * 16 + x] = left[y];
889 }
890 }
891 }
892 2 => {
893 let st: i32 = top.iter().sum();
894 let sl: i32 = left.iter().sum();
895 let dc = match (top_avail, left_avail) {
896 (true, true) => (st + sl + 16) >> 5,
897 (true, false) => (st + 8) >> 4,
898 (false, true) => (sl + 8) >> 4,
899 (false, false) => 128,
900 };
901 for v in pred.iter_mut() {
902 *v = dc;
903 }
904 }
905 3 => {
906 let mut h = 0i32;
908 let mut v = 0i32;
909 for i in 0..8i32 {
910 let pt = |k: i32| -> i32 {
912 if k < 0 {
913 corner
914 } else {
915 top[k as usize]
916 }
917 };
918 let pl = |k: i32| -> i32 {
919 if k < 0 {
920 corner
921 } else {
922 left[k as usize]
923 }
924 };
925 h += (i + 1) * (pt(8 + i) - pt(6 - i));
926 v += (i + 1) * (pl(8 + i) - pl(6 - i));
927 }
928 let b = (5 * h + 32) >> 6;
929 let c = (5 * v + 32) >> 6;
930 let a = 16 * (top[15] + left[15]);
931 for y in 0..16i32 {
932 for x in 0..16i32 {
933 let val = (a + b * (x - 7) + c * (y - 7) + 16) >> 5;
934 pred[(y * 16 + x) as usize] = clip1(val);
935 }
936 }
937 }
938 _ => {}
939 }
940 pred
941}
942
943pub fn intra_chroma_predict(
946 mode: u8,
947 top: &[i32; 8],
948 corner: i32,
949 left: &[i32; 8],
950 top_avail: bool,
951 left_avail: bool,
952) -> [i32; 64] {
953 let mut pred = [0i32; 64];
954 match mode {
955 0 => {
956 let t0: i32 = top[0..4].iter().sum();
958 let t1: i32 = top[4..8].iter().sum();
959 let l0: i32 = left[0..4].iter().sum();
960 let l1: i32 = left[4..8].iter().sum();
961 let dc00 = match (top_avail, left_avail) {
963 (true, true) => (t0 + l0 + 4) >> 3,
964 (true, false) => (t0 + 2) >> 2,
965 (false, true) => (l0 + 2) >> 2,
966 (false, false) => 128,
967 };
968 let dc10 = if top_avail {
969 (t1 + 2) >> 2
970 } else if left_avail {
971 (l0 + 2) >> 2
972 } else {
973 128
974 };
975 let dc01 = if left_avail {
976 (l1 + 2) >> 2
977 } else if top_avail {
978 (t0 + 2) >> 2
979 } else {
980 128
981 };
982 let dc11 = match (top_avail, left_avail) {
983 (true, true) => (t1 + l1 + 4) >> 3,
984 (true, false) => (t1 + 2) >> 2,
985 (false, true) => (l1 + 2) >> 2,
986 (false, false) => 128,
987 };
988 for y in 0..8 {
989 for x in 0..8 {
990 let dc = match (x < 4, y < 4) {
991 (true, true) => dc00,
992 (false, true) => dc10,
993 (true, false) => dc01,
994 (false, false) => dc11,
995 };
996 pred[y * 8 + x] = dc;
997 }
998 }
999 }
1000 1 => {
1001 for y in 0..8 {
1002 for x in 0..8 {
1003 pred[y * 8 + x] = left[y];
1004 }
1005 }
1006 }
1007 2 => {
1008 for y in 0..8 {
1009 for x in 0..8 {
1010 pred[y * 8 + x] = top[x];
1011 }
1012 }
1013 }
1014 3 => {
1015 let pt = |k: i32| -> i32 {
1017 if k < 0 {
1018 corner
1019 } else {
1020 top[k as usize]
1021 }
1022 };
1023 let pl = |k: i32| -> i32 {
1024 if k < 0 {
1025 corner
1026 } else {
1027 left[k as usize]
1028 }
1029 };
1030 let mut h = 0i32;
1031 let mut v = 0i32;
1032 for i in 0..4i32 {
1033 h += (i + 1) * (pt(4 + i) - pt(2 - i));
1034 v += (i + 1) * (pl(4 + i) - pl(2 - i));
1035 }
1036 let b = (17 * h + 16) >> 5;
1037 let c = (17 * v + 16) >> 5;
1038 let a = 16 * (top[7] + left[7]);
1039 for y in 0..8i32 {
1040 for x in 0..8i32 {
1041 pred[(y * 8 + x) as usize] = clip1((a + b * (x - 3) + c * (y - 3) + 16) >> 5);
1042 }
1043 }
1044 }
1045 _ => {}
1046 }
1047 pred
1048}
1049
1050pub fn selftest() -> (usize, usize) {
1054 let mut passed = 0usize;
1055 let mut total = 0usize;
1056 let mut check = |cond: bool, label: &str| {
1057 total += 1;
1058 if cond {
1059 passed += 1;
1060 } else {
1061 crate::println!("H264_SELFTEST FAIL: {}", label);
1062 }
1063 };
1064
1065 {
1067 let data = [0xB2u8];
1068 let mut r = BitReader::new(&data);
1069 check(r.read_bits(4) == 0b1011, "read_bits hi nibble");
1070 check(r.read_bits(4) == 0b0010, "read_bits lo nibble");
1071 }
1072
1073 {
1078 let data = [0xA6u8, 0x40u8];
1079 let mut r = BitReader::new(&data);
1080 check(r.read_ue() == 0, "ue=0");
1081 check(r.read_ue() == 1, "ue=1");
1082 check(r.read_ue() == 2, "ue=2");
1083 check(r.read_ue() == 3, "ue=3");
1084 }
1085
1086 {
1090 let data = [0xA6u8, 0x42u8, 0x80u8];
1091 let mut r = BitReader::new(&data);
1092 check(r.read_se() == 0, "se=0");
1093 check(r.read_se() == 1, "se=1");
1094 check(r.read_se() == -1, "se=-1");
1095 check(r.read_se() == 2, "se=2");
1096 check(r.read_se() == -2, "se=-2");
1097 }
1098
1099 {
1101 let inb = [0x00u8, 0x00, 0x03, 0x01, 0x00, 0x00, 0x03, 0x03];
1102 let out = extract_rbsp(&inb);
1103 check(
1104 out == alloc::vec![0x00, 0x00, 0x01, 0x00, 0x00, 0x03],
1105 "rbsp de-emulation",
1106 );
1107 }
1108
1109 {
1111 let stream = [
1112 0x00, 0x00, 0x00, 0x01, 0x67, 0xAA, 0xBB, 0x00, 0x00, 0x01, 0x65, 0xCC, ];
1115 let nals = split_annexb(&stream);
1116 check(nals.len() == 2, "annexb count");
1117 check(
1118 nals.first().map(|n| n.unit_type == 7).unwrap_or(false),
1119 "annexb nal0 type7",
1120 );
1121 check(
1122 nals.get(1).map(|n| n.unit_type == 5).unwrap_or(false),
1123 "annexb nal1 type5",
1124 );
1125 }
1126
1127 {
1129 let stream = [0, 0, 0, 3, 0x67, 0xAA, 0xBB, 0, 0, 0, 2, 0x65, 0xCC];
1130 let nals = split_avcc(&stream, 4);
1131 check(nals.len() == 2, "avcc count");
1132 check(
1133 nals.get(1)
1134 .map(|n| n.unit_type == 5 && n.rbsp == alloc::vec![0xCC])
1135 .unwrap_or(false),
1136 "avcc nal1",
1137 );
1138 }
1139
1140 {
1146 let sps = [0x42u8, 0x00, 0x1e, 0xF4, 0x14, 0x26, 0x20];
1147 match parse_sps(&sps) {
1148 Ok(s) => {
1149 check(s.profile_idc == 66, "sps profile baseline");
1150 check(s.frame_mbs_only_flag == 1, "sps frame_mbs_only");
1151 check(s.width == 160 && s.height == 144, "sps 160x144");
1152 }
1153 Err(_) => check(false, "sps parse ok"),
1154 }
1155 }
1156
1157 {
1159 let mut b = [0i32; 16];
1160 b[0] = 64;
1161 inverse_transform_4x4(&mut b);
1162 check(b.iter().all(|&v| v == 1), "idct pure DC=64 -> 1");
1163
1164 let mut b2 = [0i32; 16];
1165 b2[0] = 4096;
1166 inverse_transform_4x4(&mut b2);
1167 check(b2.iter().all(|&v| v == 64), "idct pure DC=4096 -> 64");
1168 }
1169
1170 {
1172 let mut b = [0i32; 16];
1173 b[1] = 64;
1174 inverse_transform_4x4(&mut b);
1175 let expected = [1, 1, 0, -1, 1, 1, 0, -1, 1, 1, 0, -1, 1, 1, 0, -1];
1176 check(b == expected, "idct AC d(0,1)=64");
1177 }
1178
1179 {
1181 let mut b = [0i32; 16];
1182 b[0] = 1;
1183 dequant_4x4(&mut b, 24);
1184 check(b[0] == 160, "dequant DC c=1 qp=24 -> 160");
1185 inverse_transform_4x4(&mut b);
1186 check(b.iter().all(|&v| v == 3), "dequant+idct -> flat 3");
1187 }
1188
1189 {
1191 let mut a = [0i32; 16];
1192 a[5] = 1; let mut c = [0i32; 16];
1194 c[5] = 1;
1195 dequant_4x4(&mut a, 24);
1196 dequant_4x4(&mut c, 30);
1197 check(c[5] == a[5] * 2, "dequant qp+6 doubles");
1198 }
1199
1200 {
1203 let c = 100i32;
1204 let top = [c; 8];
1205 let left = [c; 4];
1206 let mut all_ok = true;
1207 for mode in 0..9u8 {
1208 let p = intra_4x4_predict(mode, &top, c, &left, true, true);
1209 if !p.iter().all(|&v| v == c) {
1210 all_ok = false;
1211 crate::println!(" intra4x4 mode {} broke constant", mode);
1212 }
1213 }
1214 check(all_ok, "intra4x4 constant invariant all modes");
1215 }
1216
1217 {
1219 let top = [10, 20, 30, 40, 50, 60, 70, 80];
1220 let left = [0; 4];
1221 let p = intra_4x4_predict(0, &top, 0, &left, true, true);
1222 check(
1223 p[0] == 10 && p[1] == 20 && p[2] == 30 && p[3] == 40 && p[12] == 10 && p[15] == 40,
1224 "intra4x4 vertical ramp",
1225 );
1226 }
1227
1228 {
1230 let top = [0; 8];
1231 let left = [10, 20, 30, 40];
1232 let p = intra_4x4_predict(1, &top, 0, &left, true, true);
1233 check(
1234 p[0] == 10 && p[1] == 10 && p[4] == 20 && p[8] == 30 && p[12] == 40 && p[15] == 40,
1235 "intra4x4 horizontal ramp",
1236 );
1237 }
1238
1239 {
1241 let top = [8, 8, 8, 8, 8, 8, 8, 8];
1242 let left = [16, 16, 16, 16];
1243 let p = intra_4x4_predict(2, &top, 0, &left, true, true);
1244 check(p.iter().all(|&v| v == 12), "intra4x4 DC both avail");
1245 }
1246
1247 {
1249 let c = 77i32;
1250 let top = [c; 16];
1251 let left = [c; 16];
1252 let mut all_ok = true;
1253 for mode in 0..4u8 {
1254 let p = intra_16x16_predict(mode, &top, c, &left, true, true);
1255 if !p.iter().all(|&v| v == c) {
1256 all_ok = false;
1257 crate::println!(" intra16x16 mode {} broke constant", mode);
1258 }
1259 }
1260 check(all_ok, "intra16x16 constant invariant all modes");
1261 }
1262
1263 {
1265 let top = [40; 16];
1266 let left = [80; 16];
1267 let p = intra_16x16_predict(2, &top, 0, &left, true, true);
1268 check(p.iter().all(|&v| v == 60), "intra16x16 DC value");
1269 }
1270
1271 {
1274 let ebsp = [
1275 0x42u8, 0xc0, 0x0a, 0xdd, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00,
1276 0x03, 0x00, 0x83, 0xc4, 0x89, 0xe0,
1277 ];
1278 let rbsp = extract_rbsp(&ebsp);
1279 match parse_sps(&rbsp) {
1280 Ok(s) => {
1281 check(s.profile_idc == 66, "real x264 SPS profile=66");
1282 check(s.width == 16 && s.height == 16, "real x264 SPS 16x16");
1283 }
1284 Err(_) => check(false, "real x264 SPS parse ok"),
1285 }
1286 }
1287
1288 {
1290 let c = 55i32;
1291 let top = [c; 8];
1292 let left = [c; 8];
1293 let mut all_ok = true;
1294 for mode in 0..4u8 {
1295 let p = intra_chroma_predict(mode, &top, c, &left, true, true);
1296 if !p.iter().all(|&v| v == c) {
1297 all_ok = false;
1298 crate::println!(" chroma mode {} broke constant", mode);
1299 }
1300 }
1301 check(all_ok, "chroma constant invariant all modes");
1302 }
1303
1304 {
1309 let top = [8, 8, 8, 8, 40, 40, 40, 40];
1310 let left = [16, 16, 16, 16, 60, 60, 60, 60];
1311 let p = intra_chroma_predict(0, &top, 0, &left, true, true);
1312 check(p[0] == 12, "chroma DC block(0,0)=12");
1313 check(p[4] == 40, "chroma DC block(4,0)=40");
1314 check(p[32] == 60, "chroma DC block(0,4)=60");
1315 check(p[36] == 50, "chroma DC block(4,4)=50");
1316 }
1317
1318 (passed, total)
1319}
1320
1321pub fn describe_sps(s: &Sps) -> String {
1323 alloc::format!(
1324 "SPS profile={} level={} {}x{} mbs_only={}",
1325 s.profile_idc,
1326 s.level_idc,
1327 s.width,
1328 s.height,
1329 s.frame_mbs_only_flag
1330 )
1331}