1#![warn(missing_docs)]
2#![forbid(unsafe_code)]
3#![forbid(unused_results)]
4#![deny(clippy::as_conversions)]
5#![deny(clippy::panic)]
6#![deny(clippy::unwrap_used)]
7
8use std::{collections::HashMap, convert::TryInto};
10
11use bitreader::BitReader;
12
13pub use error::Vp9ParserError;
14
15mod error;
16pub mod ivf;
17
18type Result<T> = std::result::Result<T, Vp9ParserError>;
19
20const MAX_SEGMENTS: usize = 8;
22
23const MIN_TILE_WIDTH_B64: u8 = 4;
25
26const MAX_TILE_WIDTH_B64: u8 = 64;
28
29const INTRA_FRAME: usize = 0;
30const LAST_FRAME: usize = 1;
31const GOLDEN_FRAME: usize = 2;
32const ALTREF_FRAME: usize = 3;
33
34const SEG_LVL_ALT_Q: usize = 0;
35const SEG_LVL_ALT_L: usize = 1;
36const SEG_LVL_REF_FRAME: usize = 2;
37const SEG_LVL_SKIP: usize = 3;
38
39#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
41pub enum Profile {
42 Unknown,
44 Profile0,
46 Profile1,
48 Profile2,
50 Profile3,
52}
53
54impl From<u8> for Profile {
55 fn from(i: u8) -> Self {
56 match i {
57 0 => Profile::Profile0,
58 1 => Profile::Profile1,
59 2 => Profile::Profile2,
60 3 => Profile::Profile3,
61 _ => Profile::Unknown,
62 }
63 }
64}
65
66impl From<Profile> for u8 {
67 fn from(p: Profile) -> Self {
68 match p {
69 Profile::Profile0 => 0,
70 Profile::Profile1 => 1,
71 Profile::Profile2 => 2,
72 Profile::Profile3 => 3,
73 Profile::Unknown => u8::MAX,
74 }
75 }
76}
77
78#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
80pub enum Subsampling {
81 Yuv444,
83 Yuv440,
85 Yuv422,
87 Yuv420,
89}
90
91#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
93pub enum MetadataSubsampling {
94 Unknown,
96 Yuv420,
98 Yuv420Colocated,
100 Yuv422,
102 Yuv444,
104}
105
106impl From<u8> for MetadataSubsampling {
107 fn from(d: u8) -> Self {
108 match d {
109 0 => MetadataSubsampling::Yuv420,
110 1 => MetadataSubsampling::Yuv420Colocated,
111 2 => MetadataSubsampling::Yuv422,
112 3 => MetadataSubsampling::Yuv444,
113 _ => MetadataSubsampling::Unknown,
114 }
115 }
116}
117
118#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
120pub enum ColorSpace {
121 Unknown,
123 Bt601,
125 Bt709,
127 Smpte170,
129 Smpte240,
131 Bt2020,
133 Reserved,
135 Rgb,
137}
138
139impl From<u8> for ColorSpace {
140 fn from(i: u8) -> Self {
141 match i {
142 1 => ColorSpace::Bt601,
143 2 => ColorSpace::Bt709,
144 3 => ColorSpace::Smpte170,
145 4 => ColorSpace::Smpte240,
146 5 => ColorSpace::Bt2020,
147 6 => ColorSpace::Reserved,
148 7 => ColorSpace::Rgb,
149 _ => ColorSpace::Unknown,
150 }
151 }
152}
153
154#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
156pub enum ColorDepth {
157 Unknown,
159 Depth8,
161 Depth10,
163 Depth12,
165}
166
167impl From<u8> for ColorDepth {
168 fn from(d: u8) -> Self {
169 match d {
170 8 => ColorDepth::Depth8,
171 10 => ColorDepth::Depth10,
172 12 => ColorDepth::Depth12,
173 _ => ColorDepth::Unknown,
174 }
175 }
176}
177
178#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
181pub enum ColorRange {
182 StudioSwing,
184 FullSwing,
186}
187
188impl From<bool> for ColorRange {
189 fn from(b: bool) -> Self {
190 match b {
191 false => ColorRange::StudioSwing,
192 true => ColorRange::FullSwing,
193 }
194 }
195}
196
197#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
199pub enum InterpolationFilter {
200 Unknown,
202 Eighttap,
204 EighttapSmooth,
206 EighttapSharp,
208 Bilinear,
210 Switchable,
212}
213
214#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
216pub enum FrameType {
217 KeyFrame,
219 NonKeyFrame,
221}
222
223impl From<bool> for FrameType {
224 fn from(b: bool) -> Self {
225 match b {
226 false => FrameType::KeyFrame,
227 true => FrameType::NonKeyFrame,
228 }
229 }
230}
231
232#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
234pub enum ResetFrameContext {
235 Unknown,
237 No0,
239 No1,
241 SingleReset,
243 FullReset,
245}
246
247impl From<u8> for ResetFrameContext {
248 fn from(i: u8) -> Self {
249 match i {
250 0 => ResetFrameContext::No0,
251 1 => ResetFrameContext::No1,
252 2 => ResetFrameContext::SingleReset,
253 3 => ResetFrameContext::FullReset,
254 _ => ResetFrameContext::Unknown,
255 }
256 }
257}
258
259#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
261pub enum Level {
262 Unknown,
264 Level1,
266 Level1_1,
268 Level2,
270 Level2_1,
272 Level3,
274 Level3_1,
276 Level4,
278 Level4_1,
280 Level5,
282 Level5_1,
284 Level5_2,
286 Level6,
288 Level6_1,
290 Level6_2,
292}
293
294impl From<u8> for Level {
295 fn from(d: u8) -> Self {
296 match d {
297 10 => Level::Level1,
298 11 => Level::Level1_1,
299 20 => Level::Level2,
300 21 => Level::Level2_1,
301 30 => Level::Level3,
302 31 => Level::Level3_1,
303 40 => Level::Level4,
304 41 => Level::Level4_1,
305 50 => Level::Level5,
306 51 => Level::Level5_1,
307 52 => Level::Level5_2,
308 60 => Level::Level6,
309 61 => Level::Level6_1,
310 62 => Level::Level6_2,
311 _ => Level::Unknown,
312 }
313 }
314}
315
316#[derive(Clone, Copy, Debug)]
318pub struct Metadata {
319 profile: Profile,
320 level: Level,
321 color_depth: ColorDepth,
322 chroma_subsampling: MetadataSubsampling,
323}
324
325impl Metadata {
326 pub fn new(data: &[u8]) -> Result<Self> {
328 let mut pos = 0;
329
330 let mut features: HashMap<u8, u8> = HashMap::with_capacity(4);
331 while pos < data.len() {
332 let (id, value) = Self::read_feature(&mut pos, data);
333 let _ = features.insert(id, value);
334 }
335
336 let profile = *features.get(&1).ok_or(Vp9ParserError::InvalidMetadata)?;
337 let level = *features.get(&2).ok_or(Vp9ParserError::InvalidMetadata)?;
338 let color_depth = *features.get(&3).ok_or(Vp9ParserError::InvalidMetadata)?;
339 let chroma_subsampling = *features.get(&4).ok_or(Vp9ParserError::InvalidMetadata)?;
340
341 Ok(Self {
342 profile: profile.into(),
343 level: level.into(),
344 color_depth: color_depth.into(),
345 chroma_subsampling: chroma_subsampling.into(),
346 })
347 }
348
349 pub fn profile(&self) -> Profile {
351 self.profile
352 }
353
354 pub fn level(&self) -> Level {
356 self.level
357 }
358
359 pub fn color_depth(&self) -> ColorDepth {
361 self.color_depth
362 }
363
364 pub fn chroma_subsampling(&self) -> MetadataSubsampling {
366 self.chroma_subsampling
367 }
368
369 #[inline]
371 fn read_feature(pos: &mut usize, data: &[u8]) -> (u8, u8) {
372 let id = data[*pos];
373 let value = data[*pos + 1];
374 *pos += 2;
375 (id, value)
376 }
377}
378
379#[derive(Clone, Debug)]
381pub struct Frame {
382 data: Vec<u8>,
383 profile: Profile,
384 show_existing_frame: bool,
385 frame_to_show_map_idx: Option<u8>,
386 last_frame_type: FrameType,
387 frame_type: FrameType,
388 show_frame: bool,
389 error_resilient_mode: bool,
390 intra_only: bool,
391 reset_frame_context: ResetFrameContext,
392 ref_frame_indices: [u8; 3],
393 ref_frame_sign_bias: [bool; 4],
394 allow_high_precision_mv: bool,
395 refresh_frame_context: bool,
396 refresh_frame_flags: u8,
397 frame_parallel_decoding_mode: bool,
398 frame_context_idx: u8,
399 uncompressed_header_size: usize,
400 compressed_header_size: usize,
401 tile_size: usize,
402 color_depth: ColorDepth,
403 color_space: ColorSpace,
404 color_range: ColorRange,
405 subsampling_x: bool,
406 subsampling_y: bool,
407 width: u16,
408 height: u16,
409 render_width: u16,
410 render_height: u16,
411 mi_cols: u16,
412 mi_rows: u16,
413 tile_rows_log2: u8,
414 tile_cols_log2: u8,
415 interpolation_filter: InterpolationFilter,
416 loop_filter_level: u8,
417 loop_filter_sharpness: u8,
418 loop_filter_delta_enabled: bool,
419 update_ref_delta: bool,
420 loop_filter_ref_deltas: [i8; 4],
421 update_mode_delta: bool,
422 loop_filter_mode_deltas: [i8; 2],
423 base_q_idx: i32,
424 delta_q_y_dc: i32,
425 delta_q_uv_dc: i32,
426 delta_q_uv_ac: i32,
427 lossless: bool,
428 segmentation_enabled: bool,
429 segmentation_update_map: bool,
430 segment_tree_probs: [u8; 7],
431 segment_pred_probs: [u8; 3],
432 segmentation_temporal_update: bool,
433 segmentation_update_data: bool,
434 segmentation_abs_or_delta_update: bool,
435 segment_feature_enabled: [[bool; 4]; 8],
436 segment_feature_data: [[i16; 4]; 8],
437}
438
439impl Frame {
440 pub(crate) fn new(
442 parser: &Vp9Parser,
443 uncompressed_header_size: usize,
444 compressed_header_size: usize,
445 tile_size: usize,
446 data: Vec<u8>,
447 ) -> Self {
448 Self {
449 data,
450 profile: parser.profile,
451 show_existing_frame: parser.show_existing_frame,
452 frame_to_show_map_idx: parser.frame_to_show_map_idx,
453 last_frame_type: parser.last_frame_type,
454 frame_type: parser.frame_type,
455 show_frame: parser.show_frame,
456 error_resilient_mode: parser.error_resilient_mode,
457 intra_only: parser.intra_only,
458 reset_frame_context: parser.reset_frame_context,
459 ref_frame_indices: parser.ref_frame_indices,
460 ref_frame_sign_bias: parser.ref_frame_sign_bias,
461 allow_high_precision_mv: parser.allow_high_precision_mv,
462 refresh_frame_context: parser.refresh_frame_context,
463 refresh_frame_flags: parser.refresh_frame_flags,
464 frame_parallel_decoding_mode: parser.frame_parallel_decoding_mode,
465 frame_context_idx: parser.frame_context_idx,
466 uncompressed_header_size,
467 compressed_header_size,
468 tile_size,
469 color_depth: parser.color_depth,
470 color_space: parser.color_space,
471 color_range: parser.color_range,
472 subsampling_x: parser.subsampling_x,
473 subsampling_y: parser.subsampling_y,
474 width: parser.width,
475 height: parser.height,
476 render_width: parser.render_width,
477 render_height: parser.render_height,
478 mi_cols: parser.mi_cols,
479 mi_rows: parser.mi_rows,
480 tile_rows_log2: parser.tile_rows_log2,
481 tile_cols_log2: parser.tile_cols_log2,
482 interpolation_filter: parser.interpolation_filter,
483 loop_filter_level: parser.loop_filter_level,
484 loop_filter_sharpness: parser.loop_filter_sharpness,
485 loop_filter_delta_enabled: parser.loop_filter_delta_enabled,
486 update_ref_delta: parser.update_ref_delta,
487 loop_filter_ref_deltas: parser.loop_filter_ref_deltas,
488 update_mode_delta: parser.update_mode_delta,
489 loop_filter_mode_deltas: parser.loop_filter_mode_deltas,
490 base_q_idx: parser.base_q_idx,
491 delta_q_y_dc: parser.delta_q_y_dc,
492 delta_q_uv_dc: parser.delta_q_uv_dc,
493 delta_q_uv_ac: parser.delta_q_uv_ac,
494 lossless: parser.lossless,
495 segmentation_enabled: parser.segmentation_enabled,
496 segmentation_update_map: parser.segmentation_update_map,
497 segment_tree_probs: parser.segment_tree_probs,
498 segment_pred_probs: parser.segment_pred_probs,
499 segmentation_temporal_update: parser.segmentation_temporal_update,
500 segmentation_update_data: parser.segmentation_update_data,
501 segmentation_abs_or_delta_update: parser.segmentation_abs_or_delta_update,
502 segment_feature_enabled: parser.segment_feature_enabled,
503 segment_feature_data: parser.segment_feature_data,
504 }
505 }
506
507 pub fn compressed_header_data(&self) -> &[u8] {
509 &self.data[self.uncompressed_header_size
510 ..self.uncompressed_header_size + self.compressed_header_size]
511 }
512
513 pub fn compressed_header_and_tile_data(&self) -> &[u8] {
515 &self.data[self.uncompressed_header_size..self.data.len()]
516 }
517
518 pub fn tile_data(&self) -> &[u8] {
520 &self.data[self.uncompressed_header_size + self.compressed_header_size..self.data.len()]
521 }
522
523 pub fn profile(&self) -> Profile {
525 self.profile
526 }
527
528 pub fn show_existing_frame(&self) -> bool {
531 self.show_existing_frame
532 }
533
534 pub fn frame_to_show_map_idx(&self) -> Option<u8> {
536 self.frame_to_show_map_idx
537 }
538
539 pub fn last_frame_type(&self) -> FrameType {
541 self.last_frame_type
542 }
543
544 pub fn frame_type(&self) -> FrameType {
546 self.frame_type
547 }
548
549 pub fn show_frame(&self) -> bool {
551 self.show_frame
552 }
553
554 pub fn error_resilient_mode(&self) -> bool {
559 self.error_resilient_mode
560 }
561
562 pub fn intra_only(&self) -> bool {
567 self.intra_only
568 }
569
570 pub fn reset_frame_context(&self) -> ResetFrameContext {
572 self.reset_frame_context
573 }
574
575 pub fn ref_frame_indices(&self) -> &[u8; 3] {
577 &self.ref_frame_indices
578 }
579
580 pub fn last_ref_frame_index(&self) -> u8 {
582 self.ref_frame_indices[0]
583 }
584
585 pub fn golden_ref_frame_index(&self) -> u8 {
587 self.ref_frame_indices[1]
588 }
589
590 pub fn alt_ref_frame_index(&self) -> u8 {
592 self.ref_frame_indices[2]
593 }
594
595 pub fn ref_frame_sign_bias(&self) -> &[bool; 4] {
597 &self.ref_frame_sign_bias
598 }
599
600 pub fn allow_high_precision_mv(&self) -> bool {
604 self.allow_high_precision_mv
605 }
606
607 pub fn refresh_frame_context(&self) -> bool {
610 self.refresh_frame_context
611 }
612
613 pub fn refresh_frame_flags(&self) -> u8 {
618 self.refresh_frame_flags
619 }
620
621 pub fn frame_parallel_decoding_mode(&self) -> bool {
623 self.frame_parallel_decoding_mode
624 }
625
626 pub fn frame_context_idx(&self) -> u8 {
628 self.frame_context_idx
629 }
630
631 pub fn uncompressed_header_size(&self) -> usize {
633 self.uncompressed_header_size
634 }
635
636 pub fn compressed_header_size(&self) -> usize {
638 self.compressed_header_size
639 }
640
641 pub fn tile_size(&self) -> usize {
643 self.tile_size
644 }
645
646 pub fn color_depth(&self) -> ColorDepth {
648 self.color_depth
649 }
650
651 pub fn color_space(&self) -> ColorSpace {
653 self.color_space
654 }
655
656 pub fn color_range(&self) -> ColorRange {
658 self.color_range
659 }
660
661 pub fn subsampling(&self) -> Subsampling {
663 if !self.subsampling_x && !self.subsampling_y {
664 Subsampling::Yuv444
665 } else if !self.subsampling_x && self.subsampling_y {
666 Subsampling::Yuv440
667 } else if self.subsampling_x && !self.subsampling_y {
668 Subsampling::Yuv422
669 } else {
670 Subsampling::Yuv420
671 }
672 }
673
674 pub fn subsampling_x(&self) -> bool {
676 self.subsampling_x
677 }
678
679 pub fn subsampling_y(&self) -> bool {
681 self.subsampling_y
682 }
683
684 pub fn width(&self) -> u16 {
686 self.width
687 }
688
689 pub fn height(&self) -> u16 {
691 self.height
692 }
693
694 pub fn render_width(&self) -> u16 {
696 self.render_width
697 }
698
699 pub fn render_height(&self) -> u16 {
701 self.render_height
702 }
703
704 pub fn mi_cols(&self) -> u16 {
706 self.mi_cols
707 }
708
709 pub fn mi_rows(&self) -> u16 {
711 self.mi_rows
712 }
713
714 pub fn tile_rows_log2(&self) -> u8 {
717 self.tile_rows_log2
718 }
719
720 pub fn tile_cols_log2(&self) -> u8 {
723 self.tile_cols_log2
724 }
725
726 pub fn interpolation_filter(&self) -> InterpolationFilter {
728 self.interpolation_filter
729 }
730
731 pub fn loop_filter_level(&self) -> u8 {
733 self.loop_filter_level
734 }
735
736 pub fn loop_filter_sharpness(&self) -> u8 {
738 self.loop_filter_sharpness
739 }
740
741 pub fn loop_filter_delta_enabled(&self) -> bool {
744 self.loop_filter_delta_enabled
745 }
746
747 pub fn update_ref_delta(&self) -> bool {
749 self.update_ref_delta
750 }
751
752 pub fn loop_filter_ref_deltas(&self) -> &[i8; 4] {
754 &self.loop_filter_ref_deltas
755 }
756
757 pub fn update_mode_delta(&self) -> bool {
759 self.update_mode_delta
760 }
761
762 pub fn loop_filter_mode_deltas(&self) -> &[i8; 2] {
764 &self.loop_filter_mode_deltas
765 }
766
767 pub fn base_q_idx(&self) -> i32 {
770 self.base_q_idx
771 }
772
773 pub fn delta_q_y_dc(&self) -> i32 {
775 self.delta_q_y_dc
776 }
777
778 pub fn delta_q_uv_dc(&self) -> i32 {
780 self.delta_q_uv_dc
781 }
782
783 pub fn delta_q_uv_ac(&self) -> i32 {
785 self.delta_q_uv_ac
786 }
787
788 pub fn lossless(&self) -> bool {
791 self.lossless
792 }
793
794 pub fn segmentation_enabled(&self) -> bool {
796 self.segmentation_enabled
797 }
798
799 pub fn segmentation_update_map(&self) -> bool {
801 self.segmentation_update_map
802 }
803
804 pub fn segment_tree_probs(&self) -> &[u8; 7] {
806 &self.segment_tree_probs
807 }
808
809 pub fn segment_pred_probs(&self) -> &[u8; 3] {
811 &self.segment_pred_probs
812 }
813
814 pub fn segmentation_temporal_update(&self) -> bool {
817 self.segmentation_temporal_update
818 }
819
820 pub fn segmentation_update_data(&self) -> bool {
822 self.segmentation_update_data
823 }
824
825 pub fn segmentation_abs_or_delta_update(&self) -> bool {
828 self.segmentation_abs_or_delta_update
829 }
830
831 pub fn segment_feature_enabled(&self) -> &[[bool; 4]; 8] {
833 &self.segment_feature_enabled
834 }
835
836 pub fn segment_feature_data(&self) -> &[[i16; 4]; 8] {
838 &self.segment_feature_data
839 }
840
841 pub fn into_vec(self) -> Vec<u8> {
843 let Frame { data, .. } = self;
844 data
845 }
846}
847
848#[derive(Clone, Debug)]
850pub struct Vp9Parser {
851 ref_frame_sizes: [(u16, u16); 8],
852 profile: Profile,
853 show_existing_frame: bool,
854 frame_to_show_map_idx: Option<u8>,
855 last_frame_type: FrameType,
856 frame_type: FrameType,
857 show_frame: bool,
858 error_resilient_mode: bool,
859 intra_only: bool,
860 reset_frame_context: ResetFrameContext,
861 ref_frame_indices: [u8; 3],
862 ref_frame_sign_bias: [bool; 4],
863 allow_high_precision_mv: bool,
864 refresh_frame_context: bool,
865 refresh_frame_flags: u8,
866 frame_parallel_decoding_mode: bool,
867 frame_context_idx: u8,
868 color_depth: ColorDepth,
869 color_space: ColorSpace,
870 color_range: ColorRange,
871 subsampling_x: bool,
872 subsampling_y: bool,
873 width: u16,
874 height: u16,
875 render_width: u16,
876 render_height: u16,
877 mi_cols: u16,
878 mi_rows: u16,
879 tile_rows_log2: u8,
880 tile_cols_log2: u8,
881 interpolation_filter: InterpolationFilter,
882 loop_filter_level: u8,
883 loop_filter_sharpness: u8,
884 loop_filter_delta_enabled: bool,
885 update_ref_delta: bool,
886 loop_filter_ref_deltas: [i8; 4],
887 update_mode_delta: bool,
888 loop_filter_mode_deltas: [i8; 2],
889 base_q_idx: i32,
890 delta_q_y_dc: i32,
891 delta_q_uv_dc: i32,
892 delta_q_uv_ac: i32,
893 lossless: bool,
894 segmentation_enabled: bool,
895 segmentation_update_map: bool,
896 segment_tree_probs: [u8; 7],
897 segment_pred_probs: [u8; 3],
898 segmentation_temporal_update: bool,
899 segmentation_update_data: bool,
900 segmentation_abs_or_delta_update: bool,
901 segment_feature_enabled: [[bool; 4]; 8],
902 segment_feature_data: [[i16; 4]; 8],
903}
904
905impl Default for Vp9Parser {
906 fn default() -> Self {
907 Self {
908 ref_frame_sizes: [(0u16, 0u16); 8],
909 show_existing_frame: false,
910 frame_to_show_map_idx: None,
911 profile: Profile::Profile0,
912 last_frame_type: FrameType::NonKeyFrame,
913 frame_type: FrameType::NonKeyFrame,
914 show_frame: false,
915 error_resilient_mode: false,
916 intra_only: false,
917 reset_frame_context: ResetFrameContext::No0,
918 refresh_frame_flags: 0,
919 ref_frame_indices: [0u8; 3],
920 ref_frame_sign_bias: [false; 4],
921 allow_high_precision_mv: false,
922 refresh_frame_context: false,
923 frame_parallel_decoding_mode: true,
924 frame_context_idx: 0,
925 color_depth: ColorDepth::Depth8,
926 color_space: ColorSpace::Unknown,
927 color_range: ColorRange::StudioSwing,
928 subsampling_x: true,
929 subsampling_y: true,
930 width: 0,
931 height: 0,
932 render_width: 0,
933 render_height: 0,
934 mi_cols: 0,
935 mi_rows: 0,
936 tile_rows_log2: 0,
937 tile_cols_log2: 0,
938 interpolation_filter: InterpolationFilter::Eighttap,
939 loop_filter_level: 0,
940 loop_filter_sharpness: 0,
941 loop_filter_delta_enabled: false,
942 update_ref_delta: false,
943 loop_filter_ref_deltas: [1, 0, -1, -1],
944 update_mode_delta: false,
945 loop_filter_mode_deltas: [0, 0],
946 base_q_idx: 0,
947 delta_q_y_dc: 0,
948 delta_q_uv_dc: 0,
949 delta_q_uv_ac: 0,
950 lossless: false,
951 segmentation_enabled: false,
952 segmentation_update_map: false,
953 segment_tree_probs: [0u8; 7],
954 segment_pred_probs: [0u8; 3],
955 segmentation_temporal_update: false,
956 segmentation_update_data: false,
957 segmentation_abs_or_delta_update: false,
958 segment_feature_enabled: [[false; 4]; 8],
959 segment_feature_data: [[0i16; 4]; 8],
960 }
961 }
962}
963
964impl Vp9Parser {
965 pub fn new() -> Self {
967 Default::default()
968 }
969
970 pub fn reset(&mut self) {
972 *self = Vp9Parser::default();
973 }
974
975 pub fn parse_packet(&mut self, mut packet: Vec<u8>) -> Result<Vec<Frame>> {
981 if packet.is_empty() {
982 return Ok(vec![]);
983 }
984
985 let last_byte_index = packet.len() - 1;
987 let last_byte = packet[last_byte_index];
988 if last_byte & 0b1110_0000 == 0b1100_0000 {
989 let bytes_per_framesize_minus_1 = (last_byte & 0b11000) >> 3;
990 let frames_in_superframe_minus_1 = last_byte & 0b111;
991 let bytes_size: usize = (bytes_per_framesize_minus_1 + 1).into();
992 let frame_count: usize = (frames_in_superframe_minus_1 + 1).into();
993 let index_size = 2 + frame_count * bytes_size;
994 let first_byte_index = packet.len() - index_size;
995 let first_byte = packet[first_byte_index];
996
997 if first_byte == last_byte {
999 let mut frames = Vec::with_capacity(frame_count);
1000
1001 let index_start = first_byte_index + 1;
1002 let entry_size = frame_count * bytes_size;
1003
1004 let mut entry_data = Vec::with_capacity(entry_size);
1005 entry_data.extend_from_slice(&packet[index_start..index_start + entry_size]);
1006
1007 match frame_count {
1008 1 => {
1009 let frame_size = self.read_frame_size(&mut entry_data, bytes_size, 0)?;
1011 packet.truncate(frame_size);
1012 let frame = self.parse_frame(packet)?;
1013
1014 frames.push(frame);
1015 }
1016 2 => {
1017 let frame_size = self.read_frame_size(&mut entry_data, bytes_size, 0)?;
1021 let mut left_over = packet.split_off(frame_size);
1022 let first_frame = self.parse_frame(packet)?;
1023
1024 let frame_size = self.read_frame_size(&mut entry_data, bytes_size, 1)?;
1025 left_over.truncate(frame_size);
1026 let second_frame = self.parse_frame(left_over)?;
1027
1028 frames.push(first_frame);
1029 frames.push(second_frame);
1030 }
1031 _ => {
1032 for frame_index in 0..frame_count {
1034 let frame_size =
1035 self.read_frame_size(&mut entry_data, bytes_size, frame_index)?;
1036
1037 let left_over = packet.split_off(frame_size);
1038 let frame = self.parse_frame(packet)?;
1039 frames.push(frame);
1040
1041 packet = left_over;
1042 }
1043 }
1044 }
1045
1046 return Ok(frames);
1047 }
1048 }
1049
1050 let frame = self.parse_frame(packet)?;
1052 Ok(vec![frame])
1053 }
1054
1055 fn read_frame_size(
1056 &self,
1057 entry_data: &mut [u8],
1058 bytes_size: usize,
1059 index: usize,
1060 ) -> Result<usize> {
1061 let value: usize = match bytes_size {
1064 1 => u8::from_le_bytes(entry_data[index..index + 1].try_into()?).into(),
1065 2 => u16::from_le_bytes(entry_data[index * 2..(index * 2) + 2].try_into()?).into(),
1066 3 => {
1067 let bytes = &entry_data[index * 3..(index * 3) + 3];
1068 u32::from_le_bytes([bytes[0], bytes[1], bytes[2], 0x0]).try_into()?
1069 }
1070 4 => {
1071 u32::from_le_bytes(entry_data[index * 4..(index * 4) + 4].try_into()?).try_into()?
1072 }
1073 _ => {
1074 return Err(Vp9ParserError::InvalidFrameSizeByteSize(bytes_size));
1075 }
1076 };
1077 Ok(value)
1078 }
1079
1080 fn parse_frame(&mut self, data: Vec<u8>) -> Result<Frame> {
1081 let mut br = BitReader::new(&data);
1082
1083 let frame_marker = br.read_u8(2)?;
1084 if frame_marker != 2 {
1085 return Err(Vp9ParserError::InvalidFrameMarker);
1086 }
1087
1088 let profile_low_bit = br.read_u8(1)?;
1089 let profile_high_bit = br.read_u8(1)?;
1090 self.profile = ((profile_high_bit << 1) + profile_low_bit).into();
1091 if self.profile == Profile::Profile3 {
1092 let _reserved_zero = br.read_u8(1)?;
1093 }
1094
1095 self.show_existing_frame = br.read_bool()?;
1096
1097 if self.show_existing_frame {
1098 self.frame_to_show_map_idx = Some(br.read_u8(3)?);
1099 self.refresh_frame_flags = 0;
1100 self.loop_filter_level = 0;
1101
1102 let frame = Frame::new(self, 0, 0, 0, vec![]);
1103 return Ok(frame);
1104 } else {
1105 self.frame_to_show_map_idx = None;
1106 }
1107
1108 self.last_frame_type = self.frame_type;
1109 self.frame_type = br.read_bool()?.into();
1110
1111 self.show_frame = br.read_bool()?;
1112 self.error_resilient_mode = br.read_bool()?;
1113
1114 if self.frame_type == FrameType::KeyFrame {
1115 self.frame_sync_code(&mut br)?;
1116 self.color_config(&mut br)?;
1117 self.frame_size(&mut br)?;
1118 self.render_size(&mut br)?;
1119 self.refresh_frame_flags = 0xFF;
1120 } else {
1121 if !self.show_frame {
1122 self.intra_only = br.read_bool()?
1123 } else {
1124 self.intra_only = false;
1125 };
1126
1127 if !self.error_resilient_mode {
1128 self.reset_frame_context = br.read_u8(2)?.into()
1129 } else {
1130 self.reset_frame_context = ResetFrameContext::No0;
1131 };
1132
1133 if self.intra_only {
1134 self.frame_sync_code(&mut br)?;
1135 if self.profile > Profile::Profile0 {
1136 self.color_config(&mut br)?;
1137 } else {
1138 self.color_depth = ColorDepth::Depth8;
1139 self.color_space = ColorSpace::Bt601;
1140 self.subsampling_x = true;
1141 self.subsampling_y = true;
1142 }
1143 self.refresh_frame_flags = br.read_u8(8)?;
1144 self.frame_size(&mut br)?;
1145 self.render_size(&mut br)?;
1146 } else {
1147 self.refresh_frame_flags = br.read_u8(8)?;
1148 for i in 0..3 {
1149 self.ref_frame_indices[i] = br.read_u8(3)?;
1150 self.ref_frame_sign_bias[LAST_FRAME + i] = br.read_bool()?;
1151 }
1152 self.frame_size_with_refs(&mut br)?;
1153 self.allow_high_precision_mv = br.read_bool()?;
1154 self.read_interpolation_filter(&mut br)?;
1155 }
1156 }
1157
1158 if !self.error_resilient_mode {
1159 self.refresh_frame_context = br.read_bool()?;
1160 self.frame_parallel_decoding_mode = br.read_bool()?;
1161 } else {
1162 self.refresh_frame_context = false;
1163 self.frame_parallel_decoding_mode = false;
1164 };
1165
1166 self.frame_context_idx = br.read_u8(2)?;
1167
1168 if self.intra_only || self.error_resilient_mode {
1169 self.frame_context_idx = 0
1170 }
1171
1172 if self.frame_type == FrameType::KeyFrame || self.error_resilient_mode || self.intra_only {
1173 self.loop_filter_ref_deltas[INTRA_FRAME] = 1;
1175 self.loop_filter_ref_deltas[LAST_FRAME] = 0;
1176 self.loop_filter_ref_deltas[GOLDEN_FRAME] = -1;
1177 self.loop_filter_ref_deltas[ALTREF_FRAME] = -1;
1178 self.loop_filter_mode_deltas[0] = 0;
1179 self.loop_filter_mode_deltas[1] = 0;
1180 }
1181 self.loop_filter_params(&mut br)?;
1182
1183 self.quantization_params(&mut br)?;
1184 self.segmentation_params(&mut br)?;
1185 self.tile_info(&mut br)?;
1186
1187 let compressed_header_size: usize = (br.read_u16(16)?).into();
1188 self.trailing_bits(&mut br)?;
1189 let uncompressed_header_size: usize = (br.position() / 8).try_into()?;
1190
1191 let size = data.len();
1192 let tile_size = size - (uncompressed_header_size + compressed_header_size);
1193
1194 let frame = Frame::new(
1195 self,
1196 uncompressed_header_size,
1197 compressed_header_size,
1198 tile_size,
1199 data,
1200 );
1201
1202 self.refresh_ref_frames();
1203
1204 Ok(frame)
1205 }
1206
1207 fn refresh_ref_frames(&mut self) {
1209 let flags = self.refresh_frame_flags;
1210 let new_width = self.width;
1211 let new_height = self.height;
1212 self.ref_frame_sizes
1213 .iter_mut()
1214 .enumerate()
1215 .for_each(|(i, (width, height))| {
1216 if (flags >> i) & 1 == 1 {
1217 *width = new_width;
1218 *height = new_height;
1219 }
1220 });
1221 }
1222
1223 fn frame_sync_code(&self, br: &mut BitReader) -> Result<()> {
1224 let frame_sync_byte_0 = br.read_u8(8)?;
1225 let frame_sync_byte_1 = br.read_u8(8)?;
1226 let frame_sync_byte_2 = br.read_u8(8)?;
1227
1228 if frame_sync_byte_0 != 0x49 && frame_sync_byte_1 != 0x83 && frame_sync_byte_2 != 0x42 {
1229 return Err(Vp9ParserError::InvalidSyncByte);
1230 }
1231
1232 Ok(())
1233 }
1234
1235 fn color_config(&mut self, br: &mut BitReader) -> Result<()> {
1236 if self.profile >= Profile::Profile2 {
1237 let ten_or_twelve_bit = br.read_bool()?;
1238 if ten_or_twelve_bit {
1239 self.color_depth = ColorDepth::Depth12;
1240 } else {
1241 self.color_depth = ColorDepth::Depth10;
1242 }
1243 } else {
1244 self.color_depth = ColorDepth::Depth8;
1245 };
1246
1247 self.color_space = br.read_u8(3)?.into();
1248
1249 if self.color_space == ColorSpace::Rgb {
1250 self.color_range = ColorRange::FullSwing;
1251 if self.profile == Profile::Profile1 || self.profile == Profile::Profile3 {
1252 self.subsampling_x = false;
1253 self.subsampling_y = false;
1254 let _reserved_zero = br.read_u8(1)?;
1255 }
1256 } else {
1257 self.color_range = br.read_bool()?.into();
1258 if self.profile == Profile::Profile1 || self.profile == Profile::Profile3 {
1259 self.subsampling_x = br.read_bool()?;
1260 self.subsampling_y = br.read_bool()?;
1261 let _reserved_zero = br.read_u8(1)?;
1262 } else {
1263 self.subsampling_x = true;
1264 self.subsampling_y = true;
1265 }
1266 }
1267
1268 Ok(())
1269 }
1270
1271 fn frame_size(&mut self, br: &mut BitReader) -> Result<()> {
1272 let frame_width_minus_1 = br.read_u16(16)?;
1273 let frame_height_minus_1 = br.read_u16(16)?;
1274 self.width = frame_width_minus_1 + 1;
1275 self.height = frame_height_minus_1 + 1;
1276
1277 self.compute_image_size();
1278
1279 Ok(())
1280 }
1281
1282 fn render_size(&mut self, br: &mut BitReader) -> Result<()> {
1283 let render_and_frame_size_different = br.read_bool()?;
1284 if render_and_frame_size_different {
1285 let render_width_minus_1 = br.read_u16(16)?;
1286 let render_height_minus_1 = br.read_u16(16)?;
1287 self.render_width = render_width_minus_1 + 1;
1288 self.render_height = render_height_minus_1 + 1;
1289 } else {
1290 self.render_width = self.width;
1291 self.render_height = self.height;
1292 }
1293
1294 Ok(())
1295 }
1296
1297 fn frame_size_with_refs(&mut self, br: &mut BitReader) -> Result<()> {
1298 let mut found_ref = false;
1299 for i in 0..3 {
1300 found_ref = br.read_bool()?;
1301 if found_ref {
1302 let sizes = *self
1303 .ref_frame_sizes
1304 .get(usize::from(self.ref_frame_indices[i]))
1305 .ok_or(Vp9ParserError::InvalidRefFrameIndex)?;
1306
1307 self.width = sizes.0;
1308 self.height = sizes.1;
1309 break;
1310 }
1311 }
1312
1313 if !found_ref {
1314 self.frame_size(br)?;
1315 } else {
1316 self.compute_image_size();
1317 }
1318
1319 self.render_size(br)?;
1320
1321 Ok(())
1322 }
1323
1324 fn compute_image_size(&mut self) {
1325 self.mi_cols = (self.width + 7) >> 3;
1326 self.mi_rows = (self.height + 7) >> 3;
1327 }
1328
1329 fn read_interpolation_filter(&mut self, br: &mut BitReader) -> Result<()> {
1330 let is_filter_switchable = br.read_bool()?;
1331 if is_filter_switchable {
1332 self.interpolation_filter = InterpolationFilter::Switchable;
1333 } else {
1334 let raw_interpolation_filter = br.read_u8(2)?;
1335 self.interpolation_filter = match raw_interpolation_filter {
1336 0 => InterpolationFilter::EighttapSmooth,
1337 1 => InterpolationFilter::Eighttap,
1338 2 => InterpolationFilter::EighttapSharp,
1339 3 => InterpolationFilter::Bilinear,
1340 _ => InterpolationFilter::Unknown,
1341 };
1342 }
1343
1344 Ok(())
1345 }
1346
1347 fn loop_filter_params(&mut self, br: &mut BitReader) -> Result<()> {
1348 self.loop_filter_level = br.read_u8(6)?;
1349 self.loop_filter_sharpness = br.read_u8(3)?;
1350 self.loop_filter_delta_enabled = br.read_bool()?;
1351
1352 if self.loop_filter_delta_enabled {
1353 let loop_filter_delta_update = br.read_bool()?;
1354 if loop_filter_delta_update {
1355 for delta in self.loop_filter_ref_deltas.iter_mut() {
1356 let update_ref_delta = br.read_bool()?;
1357 if update_ref_delta {
1358 *delta = br.read_inverse_i8(6)?;
1359 }
1360 }
1361
1362 for mode in self.loop_filter_mode_deltas.iter_mut() {
1363 let update_mode_delta = br.read_bool()?;
1364 if update_mode_delta {
1365 *mode = br.read_inverse_i8(6)?;
1366 }
1367 }
1368 }
1369 }
1370
1371 Ok(())
1372 }
1373
1374 fn quantization_params(&mut self, br: &mut BitReader) -> Result<()> {
1375 self.base_q_idx = (br.read_u8(8)?).into();
1376 self.delta_q_y_dc = self.read_delta_q(br)?;
1377 self.delta_q_uv_dc = self.read_delta_q(br)?;
1378 self.delta_q_uv_ac = self.read_delta_q(br)?;
1379 self.lossless = self.base_q_idx == 0
1380 && self.delta_q_y_dc == 0
1381 && self.delta_q_uv_dc == 0
1382 && self.delta_q_uv_ac == 0;
1383
1384 Ok(())
1385 }
1386
1387 fn read_delta_q(&self, br: &mut BitReader) -> Result<i32> {
1388 let delta_coded = br.read_bool()?;
1389 if delta_coded {
1390 let delta_q = (br.read_inverse_i8(4)?).into();
1391 Ok(delta_q)
1392 } else {
1393 Ok(0)
1394 }
1395 }
1396
1397 fn segmentation_params(&mut self, br: &mut BitReader) -> Result<()> {
1398 self.segmentation_enabled = br.read_bool()?;
1399 if self.segmentation_enabled {
1400 self.segmentation_update_map = br.read_bool()?;
1401 if self.segmentation_update_map {
1402 for prob in self.segment_tree_probs.iter_mut() {
1403 *prob = Self::read_prob(br)?;
1404 }
1405
1406 self.segmentation_temporal_update = br.read_bool()?;
1407 for prob in self.segment_pred_probs.iter_mut() {
1408 *prob = if self.segmentation_temporal_update {
1409 Self::read_prob(br)?
1410 } else {
1411 255
1412 };
1413 }
1414 }
1415
1416 self.segmentation_update_data = br.read_bool()?;
1417 if self.segmentation_update_data {
1418 self.segmentation_abs_or_delta_update = br.read_bool()?;
1419 for i in 0..MAX_SEGMENTS {
1420 self.segment_feature_enabled[i][SEG_LVL_ALT_Q] = br.read_bool()?;
1421 if self.segment_feature_enabled[i][SEG_LVL_ALT_Q] {
1422 self.segment_feature_data[i][SEG_LVL_ALT_Q] = br.read_inverse_i16(8)?;
1423 };
1424 self.segment_feature_enabled[i][SEG_LVL_ALT_L] = br.read_bool()?;
1425 if self.segment_feature_enabled[i][SEG_LVL_ALT_L] {
1426 self.segment_feature_data[i][SEG_LVL_ALT_L] = br.read_inverse_i16(6)?;
1427 };
1428 self.segment_feature_enabled[i][SEG_LVL_REF_FRAME] = br.read_bool()?;
1429 if self.segment_feature_enabled[i][SEG_LVL_REF_FRAME] {
1430 self.segment_feature_data[i][SEG_LVL_REF_FRAME] = br.read_inverse_i16(2)?;
1431 };
1432 self.segment_feature_enabled[i][SEG_LVL_SKIP] = br.read_bool()?;
1433 self.segment_feature_data[i][SEG_LVL_SKIP] = 0;
1434 }
1435 }
1436 }
1437
1438 Ok(())
1439 }
1440
1441 fn read_prob(br: &mut BitReader) -> Result<u8> {
1442 let prob_coded = br.read_bool()?;
1443 if prob_coded {
1444 let prob = br.read_u8(8)?;
1445 Ok(prob)
1446 } else {
1447 Ok(255)
1448 }
1449 }
1450
1451 fn tile_info(&mut self, br: &mut BitReader) -> Result<()> {
1452 let min_log2_tile_cols = self.calc_min_log2_tile_cols()?;
1453 let max_log2_tile_cols = self.calc_max_log2_tile_cols()?;
1454 self.tile_cols_log2 = min_log2_tile_cols;
1455 while self.tile_cols_log2 < max_log2_tile_cols {
1456 let increment_tile_cols_log2 = br.read_bool()?;
1457 if increment_tile_cols_log2 {
1458 self.tile_cols_log2 += 1;
1459 } else {
1460 break;
1461 }
1462 }
1463 self.tile_rows_log2 = br.read_u8(1)?;
1464 if self.tile_rows_log2 == 1 {
1465 let increment_tile_rows_log2 = br.read_u8(1)?;
1466 self.tile_rows_log2 += increment_tile_rows_log2;
1467 }
1468
1469 Ok(())
1470 }
1471
1472 fn calc_min_log2_tile_cols(&self) -> Result<u8> {
1473 let mut min_log2 = 0;
1474 let sb64_cols: u8 = ((self.mi_cols + 7) >> 3).try_into()?;
1475 while (MAX_TILE_WIDTH_B64 << min_log2) < sb64_cols {
1476 min_log2 += 1;
1477 }
1478 Ok(min_log2)
1479 }
1480
1481 fn calc_max_log2_tile_cols(&self) -> Result<u8> {
1482 let mut max_log2 = 1;
1483 let sb64_cols: u8 = ((self.mi_cols + 7) >> 3).try_into()?;
1484 while (sb64_cols >> max_log2) >= MIN_TILE_WIDTH_B64 {
1485 max_log2 += 1;
1486 }
1487 Ok(max_log2 - 1)
1488 }
1489
1490 fn trailing_bits(&self, br: &mut BitReader) -> Result<()> {
1492 while br.is_aligned(1) {
1493 let zero_bit = br.read_bool()?;
1494 if zero_bit {
1495 return Err(Vp9ParserError::InvalidPadding);
1496 }
1497 }
1498
1499 Ok(())
1500 }
1501}
1502
1503trait SignedRead {
1505 fn read_inverse_i8(&mut self, bits: u8) -> Result<i8>;
1506 fn read_inverse_i16(&mut self, bits: u8) -> Result<i16>;
1507}
1508
1509impl<'a> SignedRead for BitReader<'a> {
1510 fn read_inverse_i8(&mut self, bits: u8) -> Result<i8> {
1511 debug_assert!(bits < 8);
1512
1513 let value: i8 = self.read_u8(bits)?.try_into()?;
1514 if self.read_bool()? {
1515 Ok(-(value))
1516 } else {
1517 Ok(value)
1518 }
1519 }
1520
1521 fn read_inverse_i16(&mut self, bits: u8) -> Result<i16> {
1522 debug_assert!(bits < 16);
1523
1524 let value: i16 = self.read_u16(bits)?.try_into()?;
1525 if self.read_bool()? {
1526 Ok(-(value))
1527 } else {
1528 Ok(value)
1529 }
1530 }
1531}
1532
1533#[cfg(test)]
1534mod tests {
1535 use super::*;
1536
1537 #[test]
1538 fn parse_metadata() -> Result<()> {
1539 let data: Vec<u8> = vec![0x04, 0x02, 0x03, 0x08, 0x02, 0x28, 0x01, 0x03];
1540
1541 let metadata = Metadata::new(&data)?;
1542
1543 assert_eq!(metadata.profile(), Profile::Profile3);
1544 assert_eq!(metadata.level(), Level::Level4);
1545 assert_eq!(metadata.color_depth(), ColorDepth::Depth8);
1546 assert_eq!(metadata.chroma_subsampling(), MetadataSubsampling::Yuv422);
1547
1548 Ok(())
1549 }
1550}