Skip to content
File

Blob: firmware/vendor/str0m/src/packet/contiguity_vp8.rs

rust186 lines
1use super::Vp8CodecExtra;
2use super::contiguity::FrameContiguityState;
3 
4#[derive(Debug, Default)]
5pub struct Vp8Contiguity {
6 /// last picture id of layer 0 that we allowed emitting
7 last_tl0_picture_id: Option<u64>,
8 /// last picture id of any layer that we allowed emitting
9 last_picture_id: Option<u64>,
10}
11 
12impl Vp8Contiguity {
13 pub fn new() -> Self {
14 Self::default()
15 }
16 
17 /// Called when depacketizing a new frame is ready to be emitted
18 ///
19 /// Returns whether we can emit such frame and whether it's decodable with contiguity
20 pub fn check(&mut self, next: &Vp8CodecExtra, contiguous_seq: bool) -> (bool, bool) {
21 let mut frame_state: FrameContiguityState = self.into();
22 let res = frame_state.next_frame(
23 next.picture_id,
24 next.tl0_picture_id,
25 Some(next.layer_index.into()),
26 contiguous_seq,
27 );
28 
29 *self = frame_state.into();
30 res
31 }
32}
33 
34impl From<&mut Vp8Contiguity> for FrameContiguityState {
35 fn from(value: &mut Vp8Contiguity) -> Self {
36 Self {
37 last_picture_id: value.last_picture_id,
38 last_tl0_picture_id: value.last_tl0_picture_id,
39 }
40 }
41}
42 
43impl From<FrameContiguityState> for Vp8Contiguity {
44 fn from(value: FrameContiguityState) -> Self {
45 Self {
46 last_picture_id: value.last_picture_id,
47 last_tl0_picture_id: value.last_tl0_picture_id,
48 }
49 }
50}
51 
52#[cfg(test)]
53mod test {
54 
55 use super::Vp8Contiguity;
56 const L1T3_LAYERS: &[u64] = &[0, 2, 1, 2];
57 const L1T2_LAYERS: &[u64] = &[0, 1, 0, 1];
58 
59 #[test]
60 fn contiguous_l1t3() {
61 let mut contiguity = Vp8Contiguity::new();
62 
63 for i in 0..100 {
64 let next = &crate::packet::Vp8CodecExtra {
65 discardable: false,
66 sync: true,
67 layer_index: L1T3_LAYERS[i as usize % 4] as u8,
68 picture_id: Some(i),
69 tl0_picture_id: Some(i / 4),
70 is_keyframe: false,
71 };
72 
73 let res = contiguity.check(next, true);
74 assert_eq!(res, (true, true), "Failure at picture {} {:?}", i, next);
75 }
76 }
77 
78 #[test]
79 fn contiguous_l1t3_no_l2_contig_l0() {
80 const L1T3_LAYERS: &[u64] = &[0, 2, 1, 2];
81 
82 let mut contiguity = Vp8Contiguity::new();
83 
84 for i in 0..100 {
85 let layer_index = L1T3_LAYERS[i as usize % 4] as u8;
86 if layer_index == 2 {
87 continue;
88 }
89 
90 let next = &crate::packet::Vp8CodecExtra {
91 discardable: false,
92 sync: i % 8 == 0,
93 layer_index,
94 picture_id: Some(i),
95 tl0_picture_id: Some(i / 4),
96 is_keyframe: false,
97 };
98 
99 let (emit, contiguous) = contiguity.check(next, true);
100 
101 // all layer 0 are contiguous therefore no discontinuity
102 assert_eq!(emit, next.layer_index == 0);
103 assert!(contiguous);
104 
105 if layer_index == 1 {
106 // frames on layer 1 are not emitted (could be improved tracking more deps)
107 // and we don't raise a discontinuity (stream still decodable)
108 assert!(!emit);
109 assert!(contiguous);
110 }
111 }
112 }
113 
114 #[test]
115 fn contiguous_l1t3_no_l2_discontig_l0() {
116 const L1T3_LAYERS: &[u64] = &[0, 2, 1, 2];
117 
118 let mut contiguity = Vp8Contiguity::new();
119 
120 for i in 0..100 {
121 let layer_index = L1T3_LAYERS[i as usize % 4] as u8;
122 if layer_index == 2 {
123 continue;
124 }
125 
126 let next = &crate::packet::Vp8CodecExtra {
127 discardable: false,
128 sync: i % 8 == 0,
129 layer_index,
130 picture_id: Some(i),
131 tl0_picture_id: Some(i),
132 is_keyframe: false,
133 };
134 
135 let (emit, _) = contiguity.check(next, true);
136 
137 assert!(emit == (next.layer_index == 0));
138 }
139 }
140 
141 #[test]
142 fn contiguous_l1t2() {
143 let mut contiguity = Vp8Contiguity::new();
144 
145 for i in 0..100 {
146 let next = &crate::packet::Vp8CodecExtra {
147 discardable: false,
148 sync: true,
149 layer_index: L1T2_LAYERS[i as usize % 4] as u8,
150 picture_id: Some(i),
151 tl0_picture_id: Some(i / 2),
152 is_keyframe: false,
153 };
154 
155 let res = contiguity.check(next, true);
156 assert_eq!(res, (true, true), "Failure at picture {} {:?}", i, next);
157 }
158 }
159 
160 #[test]
161 fn contiguous_l1t1_no_l1_contig_l0() {
162 let mut contiguity = Vp8Contiguity::new();
163 
164 for i in 0..100 {
165 let layer_index = L1T2_LAYERS[i as usize % 4] as u8;
166 if layer_index == 1 {
167 continue;
168 }
169 
170 let next = &crate::packet::Vp8CodecExtra {
171 discardable: false,
172 sync: i % 8 == 0,
173 layer_index,
174 picture_id: Some(i),
175 tl0_picture_id: Some(i / 2),
176 is_keyframe: false,
177 };
178 
179 let (emit, _) = contiguity.check(next, true);
180 
181 // all layer 0 are contiguous therefore can be emitted
182 assert_eq!(emit, next.layer_index == 0);
183 }
184 }
185}