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