Skip to content
File

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

rust105 lines
1use super::CodecExtra;
2use super::contiguity_vp8::Vp8Contiguity;
3use super::contiguity_vp9::Vp9Contiguity;
4 
5#[derive(Debug)]
6pub enum Contiguity {
7 Vp8(Vp8Contiguity),
8 Vp9(Vp9Contiguity),
9 None,
10}
11 
12impl Contiguity {
13 pub fn check(&mut self, next: &CodecExtra, contiguous_seq: bool) -> (bool, bool) {
14 match (self, next) {
15 (Self::Vp8(contiguity), CodecExtra::Vp8(next)) => {
16 contiguity.check(next, contiguous_seq)
17 }
18 (Self::Vp9(contiguity), CodecExtra::Vp9(next)) => {
19 contiguity.check(next, contiguous_seq)
20 }
21 (Self::Vp8(_) | Self::Vp9(_) | Self::None, _) => (true, contiguous_seq),
22 }
23 }
24}
25 
26#[derive(Debug)]
27pub(crate) struct FrameContiguityState {
28 /// last picture id of layer 0 that we allowed emitting
29 pub(crate) last_picture_id: Option<u64>,
30 
31 /// last picture id of any layer that we allowed emitting
32 pub(crate) last_tl0_picture_id: Option<u64>,
33}
34 
35impl FrameContiguityState {
36 /// Returns whether we can emit such frame and whether it's decodable with contiguity
37 pub(crate) fn next_frame(
38 &mut self,
39 picture_id: Option<u64>,
40 tl0_picture_id: Option<u64>,
41 layer_index: Option<u64>,
42 contiguous_seq: bool,
43 ) -> (bool, bool) {
44 let Some(picture_id) = picture_id else {
45 // picture id is not enabled or not progressing anyway
46 return (true, contiguous_seq);
47 };
48 
49 let Some(tl0_picture_id) = tl0_picture_id else {
50 return (true, contiguous_seq);
51 };
52 
53 let (Some(last_tl0_picture_id), Some(last_picture_id)) =
54 (self.last_tl0_picture_id, self.last_picture_id)
55 else {
56 self.last_tl0_picture_id = Some(tl0_picture_id);
57 self.last_picture_id = Some(picture_id);
58 return (true, true);
59 };
60 
61 // discard older pictures if any
62 if picture_id <= last_picture_id {
63 return (false, true);
64 }
65 
66 if layer_index == Some(0) {
67 if tl0_picture_id == last_tl0_picture_id {
68 warn!(
69 "VP8 or VP9: 2 subsequent frames on layer zero must \
70 have different tl0 picture id: encoding problem?"
71 );
72 }
73 
74 // Frame on layer 0: always emit and report discontinuity if not subsequent
75 let emit = true;
76 // note: we use wrapping add because the encoder can restart if the
77 // camera is closed / reopened and here we only care about
78 // contiguity
79 let contiguous = tl0_picture_id == last_tl0_picture_id.wrapping_add(1);
80 
81 self.last_tl0_picture_id = Some(tl0_picture_id);
82 self.last_picture_id = Some(picture_id);
83 
84 return (emit, contiguous);
85 }
86 
87 // Frame on layer 1 or 2: only emit if they refer to the current layer 0
88 // and they are subsequent
89 let emit =
90 tl0_picture_id == last_tl0_picture_id && picture_id == last_picture_id.wrapping_add(1);
91 
92 if emit {
93 self.last_picture_id = Some(picture_id);
94 if !contiguous_seq {
95 // this as happened in Safari + very lossy network (very rare)
96 debug!(
97 "VP8 or VP9: contiguous pictures implies contiguous seq numbers: encoding issue ?"
98 )
99 }
100 }
101 
102 (emit, true)
103 }
104}