From ed53c211c366ee8c3dbc1ac2c026008ca51afabb Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Sun, 14 Mar 2021 13:08:02 +0100 Subject: [PATCH 1/5] Factor out the lookahead computation out of send_frame Preliminary to the by_gop encoding refactor. --- src/api/internal.rs | 50 ++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/src/api/internal.rs b/src/api/internal.rs index bf3ddc2270..492fba7664 100644 --- a/src/api/internal.rs +++ b/src/api/internal.rs @@ -257,6 +257,7 @@ pub(crate) struct ContextInner { next_lookahead_output_frameno: u64, /// Optional opaque to be sent back to the user opaque_q: BTreeMap, + is_flushing: bool, } impl ContextInner { @@ -310,29 +311,12 @@ impl ContextInner { next_lookahead_frame: 1, next_lookahead_output_frameno: 0, opaque_q: BTreeMap::new(), + is_flushing: false, } } - #[hawktracer(send_frame)] - pub fn send_frame( - &mut self, frame: Option>>, params: Option, - ) -> Result<(), EncoderStatus> { - let input_frameno = self.frame_count; - let is_flushing = frame.is_none(); - if !is_flushing { - self.frame_count += 1; - } - self.frame_q.insert(input_frameno, frame); - - if let Some(params) = params { - if params.frame_type_override == FrameTypeOverride::Key { - self.keyframes_forced.insert(input_frameno); - } - if let Some(op) = params.opaque { - self.opaque_q.insert(input_frameno, op); - } - } - + // lookahead computations + pub(crate) fn compute_fi(&mut self) { if !self.needs_more_frame_q_lookahead(self.next_lookahead_frame) { let lookahead_frames = self .frame_q @@ -340,7 +324,7 @@ impl ContextInner { .filter_map(|(&_input_frameno, frame)| frame.clone()) .collect::>(); - if is_flushing { + if self.is_flushing { // This is the last time send_frame is called, process all the // remaining frames. for cur_lookahead_frames in @@ -359,6 +343,30 @@ impl ContextInner { } self.compute_frame_invariants(); + } + + #[hawktracer(send_frame)] + pub fn send_frame( + &mut self, frame: Option>>, params: Option, + ) -> Result<(), EncoderStatus> { + let input_frameno = self.frame_count; + + self.is_flushing = frame.is_none(); + if !self.is_flushing { + self.frame_count += 1; + } + self.frame_q.insert(input_frameno, frame); + + if let Some(params) = params { + if params.frame_type_override == FrameTypeOverride::Key { + self.keyframes_forced.insert(input_frameno); + } + if let Some(op) = params.opaque { + self.opaque_q.insert(input_frameno, op); + } + } + + self.compute_fi(); Ok(()) } From 6f47f2cffc766c15509cee42b1b86985d455770a Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Sun, 14 Mar 2021 14:27:42 +0100 Subject: [PATCH 2/5] Move the lookahead computation in the receive_packet And update the channel-api similarly. --- src/api/channel.rs | 1 + src/api/internal.rs | 4 ++-- src/api/test.rs | 8 +++++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/api/channel.rs b/src/api/channel.rs index 217a128c64..6b5a847c06 100644 --- a/src/api/channel.rs +++ b/src/api/channel.rs @@ -482,6 +482,7 @@ impl Config { let (frame, params) = f; let _ = inner.send_frame(frame, params); // TODO make sure it cannot fail. + inner.compute_fi(); } inner.limit = Some(inner.frame_count); diff --git a/src/api/internal.rs b/src/api/internal.rs index 492fba7664..c7bd683b3a 100644 --- a/src/api/internal.rs +++ b/src/api/internal.rs @@ -366,8 +366,6 @@ impl ContextInner { } } - self.compute_fi(); - Ok(()) } @@ -1287,6 +1285,8 @@ impl ContextInner { return Err(EncoderStatus::LimitReached); } + self.compute_fi(); + if self.needs_more_fi_lookahead() { return Err(EncoderStatus::NeedMoreData); } diff --git a/src/api/test.rs b/src/api/test.rs index 5cbeaa6ea1..79f86c89f7 100644 --- a/src/api/test.rs +++ b/src/api/test.rs @@ -274,8 +274,9 @@ fn send_test_frame(ctx: &mut Context, content_value: T) { } fn get_frame_invariants( - ctx: Context, + mut ctx: Context, ) -> impl Iterator> { + ctx.inner.compute_fi(); ctx.inner.frame_data.into_iter().map(|(_, v)| v.fi) } @@ -1777,6 +1778,7 @@ fn lookahead_size_properly_bounded( for i in 0..LIMIT { let input = ctx.new_frame(); let _ = ctx.send_frame(input); + ctx.inner.compute_fi(); pre_receive_frame_q_lens[i] = ctx.inner.frame_q.len(); pre_receive_fi_lens[i] = ctx.inner.frame_data.len(); while ctx.receive_packet().is_ok() { @@ -2047,6 +2049,7 @@ fn min_quantizer_bounds_correctly() { ctx.flush(); for i in 0..limit { + ctx.inner.compute_fi(); ctx.inner.encode_packet(i).unwrap(); let frame_data = ctx.inner.frame_data.get(&i).unwrap(); if i == 0 { @@ -2078,6 +2081,7 @@ fn min_quantizer_bounds_correctly() { ctx.flush(); for i in 0..limit { + ctx.inner.compute_fi(); ctx.inner.encode_packet(i).unwrap(); let frame_data = ctx.inner.frame_data.get(&i).unwrap(); if i == 0 { @@ -2112,6 +2116,7 @@ fn max_quantizer_bounds_correctly() { ctx.flush(); for i in 0..limit { + ctx.inner.compute_fi(); ctx.inner.encode_packet(i).unwrap(); let frame_data = ctx.inner.frame_data.get(&i).unwrap(); if i == 0 { @@ -2143,6 +2148,7 @@ fn max_quantizer_bounds_correctly() { ctx.flush(); for i in 0..limit { + ctx.inner.compute_fi(); ctx.inner.encode_packet(i).unwrap(); let frame_data = ctx.inner.frame_data.get(&i).unwrap(); if i == 0 { From 393d22cd5e4162a78b9d39c78c2165454f3f945b Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Mon, 15 Mar 2021 13:52:15 +0100 Subject: [PATCH 3/5] Do not use the frame_q FrameData.fs contains already the input frame, take a reference from it. --- src/api/internal.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/internal.rs b/src/api/internal.rs index c7bd683b3a..aba6562ed9 100644 --- a/src/api/internal.rs +++ b/src/api/internal.rs @@ -1001,7 +1001,7 @@ impl ContextInner { let output_frame_data = self.frame_data.remove(&output_frameno).unwrap(); let fi = &output_frame_data.fi; - let frame = self.frame_q[&fi.input_frameno].as_ref().unwrap(); + let frame = &output_frame_data.fs.input; // There can be at most 3 of these. let mut unique_indices = ArrayVec::<_, 3>::new(); From 962621432e0a24c9e69c6713f12d1616b3572665 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Mon, 15 Mar 2021 14:59:44 +0100 Subject: [PATCH 4/5] Do not compute the qi if it not going to be used --- src/api/internal.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/api/internal.rs b/src/api/internal.rs index aba6562ed9..8d2b27a178 100644 --- a/src/api/internal.rs +++ b/src/api/internal.rs @@ -582,6 +582,13 @@ impl ContextInner { fn compute_lookahead_motion_vectors(&mut self, output_frameno: u64) { let qps = { let frame_data = self.frame_data.get(&output_frameno).unwrap(); + // We're only interested in valid frames which are not show-existing-frame. + // Those two don't modify the rec_buffer so there's no need to do anything + // special about it either, it'll propagate on its own. + if frame_data.fi.invalid || frame_data.fi.show_existing_frame { + return; + } + let fti = frame_data.fi.get_frame_subtype(); self.rc_state.select_qi( self, @@ -594,13 +601,6 @@ impl ContextInner { let fs = &mut frame_data.fs; let fi = &mut frame_data.fi; - // We're only interested in valid frames which are not show-existing-frame. - // Those two don't modify the rec_buffer so there's no need to do anything - // special about it either, it'll propagate on its own. - if fi.invalid || fi.show_existing_frame { - return; - } - #[cfg(feature = "dump_lookahead_data")] { let data_location = Self::build_dump_properties(); From 53fc05b303df3323ede9bddc44cf7e9ec2e735b6 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Mon, 15 Mar 2021 16:37:33 +0100 Subject: [PATCH 5/5] Explicitly skip processing non-valid frame invariants --- src/api/internal.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/api/internal.rs b/src/api/internal.rs index 8d2b27a178..6caee4a368 100644 --- a/src/api/internal.rs +++ b/src/api/internal.rs @@ -424,14 +424,15 @@ impl ContextInner { fn set_frame_properties( &mut self, output_frameno: u64, - ) -> Result<(), EncoderStatus> { + ) -> Result { let fi = self.build_frame_properties(output_frameno)?; + let valid = !fi.invalid; let frame = self.frame_q.get(&fi.input_frameno).as_ref().unwrap().as_ref().unwrap(); self.frame_data.insert(output_frameno, FrameData::new(fi, frame.clone())); - Ok(()) + Ok(valid) } #[allow(unused)] @@ -780,12 +781,17 @@ impl ContextInner { #[hawktracer(compute_frame_invariants)] pub fn compute_frame_invariants(&mut self) { - while self.set_frame_properties(self.next_lookahead_output_frameno).is_ok() + while let Ok(valid) = + self.set_frame_properties(self.next_lookahead_output_frameno) { - self - .compute_lookahead_motion_vectors(self.next_lookahead_output_frameno); - if self.config.temporal_rdo() { - self.compute_lookahead_intra_costs(self.next_lookahead_output_frameno); + if valid { + self.compute_lookahead_motion_vectors( + self.next_lookahead_output_frameno, + ); + if self.config.temporal_rdo() { + self + .compute_lookahead_intra_costs(self.next_lookahead_output_frameno); + } } self.next_lookahead_output_frameno += 1; }