/rust/registry/src/index.crates.io-6f17d22bba15001f/rav1e-0.7.1/src/api/internal.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2018-2022, The rav1e contributors. All rights reserved |
2 | | // |
3 | | // This source code is subject to the terms of the BSD 2 Clause License and |
4 | | // the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
5 | | // was not distributed with this source code in the LICENSE file, you can |
6 | | // obtain it at www.aomedia.org/license/software. If the Alliance for Open |
7 | | // Media Patent License 1.0 was not distributed with this source code in the |
8 | | // PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
9 | | #![deny(missing_docs)] |
10 | | |
11 | | use crate::activity::ActivityMask; |
12 | | use crate::api::lookahead::*; |
13 | | use crate::api::{ |
14 | | EncoderConfig, EncoderStatus, FrameType, Opaque, Packet, T35, |
15 | | }; |
16 | | use crate::color::ChromaSampling::Cs400; |
17 | | use crate::cpu_features::CpuFeatureLevel; |
18 | | use crate::dist::get_satd; |
19 | | use crate::encoder::*; |
20 | | use crate::frame::*; |
21 | | use crate::partition::*; |
22 | | use crate::rate::{ |
23 | | RCState, FRAME_NSUBTYPES, FRAME_SUBTYPE_I, FRAME_SUBTYPE_P, |
24 | | FRAME_SUBTYPE_SEF, |
25 | | }; |
26 | | use crate::scenechange::SceneChangeDetector; |
27 | | use crate::stats::EncoderStats; |
28 | | use crate::tiling::Area; |
29 | | use crate::util::Pixel; |
30 | | use arrayvec::ArrayVec; |
31 | | use std::cmp; |
32 | | use std::collections::{BTreeMap, BTreeSet}; |
33 | | use std::env; |
34 | | use std::fs; |
35 | | use std::path::PathBuf; |
36 | | use std::sync::Arc; |
37 | | |
38 | | /// The set of options that controls frame re-ordering and reference picture |
39 | | /// selection. |
40 | | /// The options stored here are invariant over the whole encode. |
41 | | #[derive(Debug, Clone, Copy)] |
42 | | pub struct InterConfig { |
43 | | /// Whether frame re-ordering is enabled. |
44 | | reorder: bool, |
45 | | /// Whether P-frames can use multiple references. |
46 | | pub(crate) multiref: bool, |
47 | | /// The depth of the re-ordering pyramid. |
48 | | /// The current code cannot support values larger than 2. |
49 | | pub(crate) pyramid_depth: u64, |
50 | | /// Number of input frames in group. |
51 | | pub(crate) group_input_len: u64, |
52 | | /// Number of output frames in group. |
53 | | /// This includes both hidden frames and "show existing frame" frames. |
54 | | group_output_len: u64, |
55 | | /// Interval between consecutive S-frames. |
56 | | /// Keyframes reset this interval. |
57 | | /// This MUST be a multiple of group_input_len. |
58 | | pub(crate) switch_frame_interval: u64, |
59 | | } |
60 | | |
61 | | impl InterConfig { |
62 | 0 | pub(crate) fn new(enc_config: &EncoderConfig) -> InterConfig { |
63 | 0 | let reorder = !enc_config.low_latency; |
64 | | // A group always starts with (group_output_len - group_input_len) hidden |
65 | | // frames, followed by group_input_len shown frames. |
66 | | // The shown frames iterate over the input frames in order, with frames |
67 | | // already encoded as hidden frames now displayed with Show Existing |
68 | | // Frame. |
69 | | // For example, for a pyramid depth of 2, the group is as follows: |
70 | | // |TU |TU |TU |TU |
71 | | // idx_in_group_output: 0 1 2 3 4 5 |
72 | | // input_frameno: 4 2 1 SEF 3 SEF |
73 | | // output_frameno: 1 2 3 4 5 6 |
74 | | // level: 0 1 2 1 2 0 |
75 | | // ^^^^^ ^^^^^^^^^^^^^ |
76 | | // hidden shown |
77 | | // TODO: This only works for pyramid_depth <= 2 --- after that we need |
78 | | // more hidden frames in the middle of the group. |
79 | 0 | let pyramid_depth = if reorder { 2 } else { 0 }; |
80 | 0 | let group_input_len = 1 << pyramid_depth; |
81 | 0 | let group_output_len = group_input_len + pyramid_depth; |
82 | 0 | let switch_frame_interval = enc_config.switch_frame_interval; |
83 | 0 | assert!(switch_frame_interval % group_input_len == 0); |
84 | | InterConfig { |
85 | 0 | reorder, |
86 | 0 | multiref: reorder || enc_config.speed_settings.multiref, |
87 | 0 | pyramid_depth, |
88 | 0 | group_input_len, |
89 | 0 | group_output_len, |
90 | 0 | switch_frame_interval, |
91 | 0 | } |
92 | 0 | } |
93 | | |
94 | | /// Get the index of an output frame in its re-ordering group given the output |
95 | | /// frame number of the frame in the current keyframe gop. |
96 | | /// When re-ordering is disabled, this always returns 0. |
97 | 0 | pub(crate) fn get_idx_in_group_output( |
98 | 0 | &self, output_frameno_in_gop: u64, |
99 | 0 | ) -> u64 { |
100 | 0 | // The first frame in the GOP should be a keyframe and is not re-ordered, |
101 | 0 | // so we should not be calling this function on it. |
102 | 0 | debug_assert!(output_frameno_in_gop > 0); |
103 | 0 | (output_frameno_in_gop - 1) % self.group_output_len |
104 | 0 | } |
105 | | |
106 | | /// Get the order-hint of an output frame given the output frame number of the |
107 | | /// frame in the current keyframe gop and the index of that output frame |
108 | | /// in its re-ordering gorup. |
109 | 0 | pub(crate) fn get_order_hint( |
110 | 0 | &self, output_frameno_in_gop: u64, idx_in_group_output: u64, |
111 | 0 | ) -> u32 { |
112 | 0 | // The first frame in the GOP should be a keyframe, but currently this |
113 | 0 | // function only handles inter frames. |
114 | 0 | // We could return 0 for keyframes if keyframe support is needed. |
115 | 0 | debug_assert!(output_frameno_in_gop > 0); |
116 | | // Which P-frame group in the current gop is this output frame in? |
117 | | // Subtract 1 because the first frame in the gop is always a keyframe. |
118 | 0 | let group_idx = (output_frameno_in_gop - 1) / self.group_output_len; |
119 | | // Get the offset to the corresponding input frame. |
120 | | // TODO: This only works with pyramid_depth <= 2. |
121 | 0 | let offset = if idx_in_group_output < self.pyramid_depth { |
122 | 0 | self.group_input_len >> idx_in_group_output |
123 | | } else { |
124 | 0 | idx_in_group_output - self.pyramid_depth + 1 |
125 | | }; |
126 | | // Construct the final order hint relative to the start of the group. |
127 | 0 | (self.group_input_len * group_idx + offset) as u32 |
128 | 0 | } |
129 | | |
130 | | /// Get the level of the current frame in the pyramid. |
131 | 0 | pub(crate) const fn get_level(&self, idx_in_group_output: u64) -> u64 { |
132 | 0 | if !self.reorder { |
133 | 0 | 0 |
134 | 0 | } else if idx_in_group_output < self.pyramid_depth { |
135 | | // Hidden frames are output first (to be shown in the future). |
136 | 0 | idx_in_group_output |
137 | | } else { |
138 | | // Shown frames |
139 | | // TODO: This only works with pyramid_depth <= 2. |
140 | 0 | pos_to_lvl( |
141 | 0 | idx_in_group_output - self.pyramid_depth + 1, |
142 | 0 | self.pyramid_depth, |
143 | 0 | ) |
144 | | } |
145 | 0 | } |
146 | | |
147 | 0 | pub(crate) const fn get_slot_idx(&self, level: u64, order_hint: u32) -> u32 { |
148 | 0 | // Frames with level == 0 are stored in slots 0..4, and frames with higher |
149 | 0 | // values of level in slots 4..8 |
150 | 0 | if level == 0 { |
151 | 0 | (order_hint >> self.pyramid_depth) & 3 |
152 | | } else { |
153 | | // This only works with pyramid_depth <= 4. |
154 | 0 | 3 + level as u32 |
155 | | } |
156 | 0 | } |
157 | | |
158 | 0 | pub(crate) const fn get_show_frame(&self, idx_in_group_output: u64) -> bool { |
159 | 0 | idx_in_group_output >= self.pyramid_depth |
160 | 0 | } |
161 | | |
162 | 0 | pub(crate) const fn get_show_existing_frame( |
163 | 0 | &self, idx_in_group_output: u64, |
164 | 0 | ) -> bool { |
165 | 0 | // The self.reorder test here is redundant, but short-circuits the rest, |
166 | 0 | // avoiding a bunch of work when it's false. |
167 | 0 | self.reorder |
168 | 0 | && self.get_show_frame(idx_in_group_output) |
169 | 0 | && (idx_in_group_output - self.pyramid_depth + 1).count_ones() == 1 |
170 | 0 | && idx_in_group_output != self.pyramid_depth |
171 | 0 | } |
172 | | |
173 | 0 | pub(crate) fn get_input_frameno( |
174 | 0 | &self, output_frameno_in_gop: u64, gop_input_frameno_start: u64, |
175 | 0 | ) -> u64 { |
176 | 0 | if output_frameno_in_gop == 0 { |
177 | 0 | gop_input_frameno_start |
178 | | } else { |
179 | 0 | let idx_in_group_output = |
180 | 0 | self.get_idx_in_group_output(output_frameno_in_gop); |
181 | 0 | let order_hint = |
182 | 0 | self.get_order_hint(output_frameno_in_gop, idx_in_group_output); |
183 | 0 | gop_input_frameno_start + order_hint as u64 |
184 | | } |
185 | 0 | } |
186 | | |
187 | 0 | const fn max_reordering_latency(&self) -> u64 { |
188 | 0 | self.group_input_len |
189 | 0 | } |
190 | | |
191 | 0 | pub(crate) const fn keyframe_lookahead_distance(&self) -> u64 { |
192 | 0 | self.max_reordering_latency() + 1 |
193 | 0 | } |
194 | | |
195 | 0 | pub(crate) const fn allowed_ref_frames(&self) -> &[RefType] { |
196 | | use crate::partition::RefType::*; |
197 | 0 | if self.reorder { |
198 | 0 | &ALL_INTER_REFS |
199 | 0 | } else if self.multiref { |
200 | 0 | &[LAST_FRAME, LAST2_FRAME, LAST3_FRAME, GOLDEN_FRAME] |
201 | | } else { |
202 | 0 | &[LAST_FRAME] |
203 | | } |
204 | 0 | } |
205 | | } |
206 | | |
207 | | // Thin wrapper for frame-related data |
208 | | // that gets cached and reused throughout the life of a frame. |
209 | | #[derive(Clone)] |
210 | | pub(crate) struct FrameData<T: Pixel> { |
211 | | pub(crate) fi: FrameInvariants<T>, |
212 | | pub(crate) fs: FrameState<T>, |
213 | | } |
214 | | |
215 | | impl<T: Pixel> FrameData<T> { |
216 | 0 | pub(crate) fn new(fi: FrameInvariants<T>, frame: Arc<Frame<T>>) -> Self { |
217 | 0 | let fs = FrameState::new_with_frame(&fi, frame); |
218 | 0 | FrameData { fi, fs } |
219 | 0 | } Unexecuted instantiation: <rav1e::api::internal::FrameData<u16>>::new Unexecuted instantiation: <rav1e::api::internal::FrameData<u8>>::new |
220 | | } |
221 | | |
222 | | type FrameQueue<T> = BTreeMap<u64, Option<Arc<Frame<T>>>>; |
223 | | type FrameDataQueue<T> = BTreeMap<u64, Option<FrameData<T>>>; |
224 | | |
225 | | // the fields pub(super) are accessed only by the tests |
226 | | pub(crate) struct ContextInner<T: Pixel> { |
227 | | pub(crate) frame_count: u64, |
228 | | pub(crate) limit: Option<u64>, |
229 | | pub(crate) output_frameno: u64, |
230 | | pub(super) inter_cfg: InterConfig, |
231 | | pub(super) frames_processed: u64, |
232 | | /// Maps *input_frameno* to frames |
233 | | pub(super) frame_q: FrameQueue<T>, |
234 | | /// Maps *output_frameno* to frame data |
235 | | pub(super) frame_data: FrameDataQueue<T>, |
236 | | /// A list of the input_frameno for keyframes in this encode. |
237 | | /// Needed so that we don't need to keep all of the frame_invariants in |
238 | | /// memory for the whole life of the encode. |
239 | | // TODO: Is this needed at all? |
240 | | keyframes: BTreeSet<u64>, |
241 | | // TODO: Is this needed at all? |
242 | | keyframes_forced: BTreeSet<u64>, |
243 | | /// A storage space for reordered frames. |
244 | | packet_data: Vec<u8>, |
245 | | /// Maps `output_frameno` to `gop_output_frameno_start`. |
246 | | gop_output_frameno_start: BTreeMap<u64, u64>, |
247 | | /// Maps `output_frameno` to `gop_input_frameno_start`. |
248 | | pub(crate) gop_input_frameno_start: BTreeMap<u64, u64>, |
249 | | keyframe_detector: SceneChangeDetector<T>, |
250 | | pub(crate) config: Arc<EncoderConfig>, |
251 | | seq: Arc<Sequence>, |
252 | | pub(crate) rc_state: RCState, |
253 | | maybe_prev_log_base_q: Option<i64>, |
254 | | /// The next `input_frameno` to be processed by lookahead. |
255 | | next_lookahead_frame: u64, |
256 | | /// The next `output_frameno` to be computed by lookahead. |
257 | | next_lookahead_output_frameno: u64, |
258 | | /// Optional opaque to be sent back to the user |
259 | | opaque_q: BTreeMap<u64, Opaque>, |
260 | | /// Optional T35 metadata per frame |
261 | | t35_q: BTreeMap<u64, Box<[T35]>>, |
262 | | } |
263 | | |
264 | | impl<T: Pixel> ContextInner<T> { |
265 | 0 | pub fn new(enc: &EncoderConfig) -> Self { |
266 | 0 | // initialize with temporal delimiter |
267 | 0 | let packet_data = TEMPORAL_DELIMITER.to_vec(); |
268 | 0 | let mut keyframes = BTreeSet::new(); |
269 | 0 | keyframes.insert(0); |
270 | | |
271 | 0 | let maybe_ac_qi_max = |
272 | 0 | if enc.quantizer < 255 { Some(enc.quantizer as u8) } else { None }; |
273 | | |
274 | 0 | let seq = Arc::new(Sequence::new(enc)); |
275 | 0 | let inter_cfg = InterConfig::new(enc); |
276 | 0 | let lookahead_distance = inter_cfg.keyframe_lookahead_distance() as usize; |
277 | 0 |
|
278 | 0 | ContextInner { |
279 | 0 | frame_count: 0, |
280 | 0 | limit: None, |
281 | 0 | inter_cfg, |
282 | 0 | output_frameno: 0, |
283 | 0 | frames_processed: 0, |
284 | 0 | frame_q: BTreeMap::new(), |
285 | 0 | frame_data: BTreeMap::new(), |
286 | 0 | keyframes, |
287 | 0 | keyframes_forced: BTreeSet::new(), |
288 | 0 | packet_data, |
289 | 0 | gop_output_frameno_start: BTreeMap::new(), |
290 | 0 | gop_input_frameno_start: BTreeMap::new(), |
291 | 0 | keyframe_detector: SceneChangeDetector::new( |
292 | 0 | enc.clone(), |
293 | 0 | CpuFeatureLevel::default(), |
294 | 0 | lookahead_distance, |
295 | 0 | seq.clone(), |
296 | 0 | ), |
297 | 0 | config: Arc::new(enc.clone()), |
298 | 0 | seq, |
299 | 0 | rc_state: RCState::new( |
300 | 0 | enc.width as i32, |
301 | 0 | enc.height as i32, |
302 | 0 | enc.time_base.den as i64, |
303 | 0 | enc.time_base.num as i64, |
304 | 0 | enc.bitrate, |
305 | 0 | maybe_ac_qi_max, |
306 | 0 | enc.min_quantizer, |
307 | 0 | enc.max_key_frame_interval as i32, |
308 | 0 | enc.reservoir_frame_delay, |
309 | 0 | ), |
310 | 0 | maybe_prev_log_base_q: None, |
311 | 0 | next_lookahead_frame: 1, |
312 | 0 | next_lookahead_output_frameno: 0, |
313 | 0 | opaque_q: BTreeMap::new(), |
314 | 0 | t35_q: BTreeMap::new(), |
315 | 0 | } |
316 | 0 | } Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::new Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::new |
317 | | |
318 | 0 | #[profiling::function] Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::send_frame Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::send_frame |
319 | | pub fn send_frame( |
320 | | &mut self, mut frame: Option<Arc<Frame<T>>>, |
321 | | params: Option<FrameParameters>, |
322 | | ) -> Result<(), EncoderStatus> { |
323 | | if let Some(ref mut frame) = frame { |
324 | | use crate::api::color::ChromaSampling; |
325 | | let EncoderConfig { width, height, chroma_sampling, .. } = *self.config; |
326 | | let planes = |
327 | | if chroma_sampling == ChromaSampling::Cs400 { 1 } else { 3 }; |
328 | | // Try to add padding |
329 | | if let Some(ref mut frame) = Arc::get_mut(frame) { |
330 | | for plane in frame.planes[..planes].iter_mut() { |
331 | | plane.pad(width, height); |
332 | | } |
333 | | } |
334 | | // Enforce that padding is added |
335 | | for (p, plane) in frame.planes[..planes].iter().enumerate() { |
336 | | assert!( |
337 | | plane.probe_padding(width, height), |
338 | | "Plane {p} was not padded before passing Frame to send_frame()." |
339 | | ); |
340 | | } |
341 | | } |
342 | | |
343 | | let input_frameno = self.frame_count; |
344 | | let is_flushing = frame.is_none(); |
345 | | if !is_flushing { |
346 | | self.frame_count += 1; |
347 | | } |
348 | | self.frame_q.insert(input_frameno, frame); |
349 | | |
350 | | if let Some(params) = params { |
351 | | if params.frame_type_override == FrameTypeOverride::Key { |
352 | | self.keyframes_forced.insert(input_frameno); |
353 | | } |
354 | | if let Some(op) = params.opaque { |
355 | | self.opaque_q.insert(input_frameno, op); |
356 | | } |
357 | | self.t35_q.insert(input_frameno, params.t35_metadata); |
358 | | } |
359 | | |
360 | | if !self.needs_more_frame_q_lookahead(self.next_lookahead_frame) { |
361 | | let lookahead_frames = self |
362 | | .frame_q |
363 | | .range(self.next_lookahead_frame - 1..) |
364 | 0 | .filter_map(|(&_input_frameno, frame)| frame.as_ref()) Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::send_frame::{closure#0} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::send_frame::{closure#0} |
365 | | .collect::<Vec<&Arc<Frame<T>>>>(); |
366 | | |
367 | | if is_flushing { |
368 | | // This is the last time send_frame is called, process all the |
369 | | // remaining frames. |
370 | | for cur_lookahead_frames in |
371 | 0 | std::iter::successors(Some(&lookahead_frames[..]), |s| s.get(1..)) Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::send_frame::{closure#1} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::send_frame::{closure#1} |
372 | | { |
373 | | if cur_lookahead_frames.len() < 2 { |
374 | | // All frames have been processed |
375 | | break; |
376 | | } |
377 | | |
378 | | Self::compute_keyframe_placement( |
379 | | cur_lookahead_frames, |
380 | | &self.keyframes_forced, |
381 | | &mut self.keyframe_detector, |
382 | | &mut self.next_lookahead_frame, |
383 | | &mut self.keyframes, |
384 | | ); |
385 | | } |
386 | | } else { |
387 | | Self::compute_keyframe_placement( |
388 | | &lookahead_frames, |
389 | | &self.keyframes_forced, |
390 | | &mut self.keyframe_detector, |
391 | | &mut self.next_lookahead_frame, |
392 | | &mut self.keyframes, |
393 | | ); |
394 | | } |
395 | | } |
396 | | |
397 | | self.compute_frame_invariants(); |
398 | | |
399 | | Ok(()) |
400 | | } |
401 | | |
402 | | /// Indicates whether more frames need to be read into the frame queue |
403 | | /// in order for frame queue lookahead to be full. |
404 | 0 | fn needs_more_frame_q_lookahead(&self, input_frameno: u64) -> bool { |
405 | 0 | let lookahead_end = self.frame_q.keys().last().cloned().unwrap_or(0); |
406 | 0 | let frames_needed = |
407 | 0 | input_frameno + self.inter_cfg.keyframe_lookahead_distance() + 1; |
408 | 0 | lookahead_end < frames_needed && self.needs_more_frames(lookahead_end) |
409 | 0 | } Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::needs_more_frame_q_lookahead Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::needs_more_frame_q_lookahead |
410 | | |
411 | | /// Indicates whether more frames need to be processed into `FrameInvariants` |
412 | | /// in order for FI lookahead to be full. |
413 | 0 | pub fn needs_more_fi_lookahead(&self) -> bool { |
414 | 0 | let ready_frames = self.get_rdo_lookahead_frames().count(); |
415 | 0 | ready_frames < self.config.speed_settings.rdo_lookahead_frames + 1 |
416 | 0 | && self.needs_more_frames(self.next_lookahead_frame) |
417 | 0 | } Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::needs_more_fi_lookahead Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::needs_more_fi_lookahead |
418 | | |
419 | 0 | pub fn needs_more_frames(&self, frame_count: u64) -> bool { |
420 | 0 | self.limit.map(|limit| frame_count < limit).unwrap_or(true) Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::needs_more_frames::{closure#0} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::needs_more_frames::{closure#0} |
421 | 0 | } Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::needs_more_frames Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::needs_more_frames |
422 | | |
423 | 0 | fn get_rdo_lookahead_frames( |
424 | 0 | &self, |
425 | 0 | ) -> impl Iterator<Item = (&u64, &FrameData<T>)> { |
426 | 0 | self |
427 | 0 | .frame_data |
428 | 0 | .iter() |
429 | 0 | .skip_while(move |(&output_frameno, _)| { |
430 | 0 | output_frameno < self.output_frameno |
431 | 0 | }) Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::get_rdo_lookahead_frames::{closure#0} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::get_rdo_lookahead_frames::{closure#0} |
432 | 0 | .filter_map(|(fno, data)| data.as_ref().map(|data| (fno, data))) Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::get_rdo_lookahead_frames::{closure#1} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::get_rdo_lookahead_frames::{closure#1} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::get_rdo_lookahead_frames::{closure#1}::{closure#0} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::get_rdo_lookahead_frames::{closure#1}::{closure#0} |
433 | 0 | .filter(|(_, data)| !data.fi.is_show_existing_frame()) Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::get_rdo_lookahead_frames::{closure#2} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::get_rdo_lookahead_frames::{closure#2} |
434 | 0 | .take(self.config.speed_settings.rdo_lookahead_frames + 1) |
435 | 0 | } Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::get_rdo_lookahead_frames Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::get_rdo_lookahead_frames |
436 | | |
437 | 0 | fn next_keyframe_input_frameno( |
438 | 0 | &self, gop_input_frameno_start: u64, ignore_limit: bool, |
439 | 0 | ) -> u64 { |
440 | 0 | let next_detected = self |
441 | 0 | .keyframes |
442 | 0 | .iter() |
443 | 0 | .find(|&&input_frameno| input_frameno > gop_input_frameno_start) Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::next_keyframe_input_frameno::{closure#0} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::next_keyframe_input_frameno::{closure#0} |
444 | 0 | .cloned(); |
445 | 0 | let mut next_limit = |
446 | 0 | gop_input_frameno_start + self.config.max_key_frame_interval; |
447 | 0 | if !ignore_limit && self.limit.is_some() { |
448 | 0 | next_limit = next_limit.min(self.limit.unwrap()); |
449 | 0 | } |
450 | 0 | if next_detected.is_none() { |
451 | 0 | return next_limit; |
452 | 0 | } |
453 | 0 | cmp::min(next_detected.unwrap(), next_limit) |
454 | 0 | } Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::next_keyframe_input_frameno Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::next_keyframe_input_frameno |
455 | | |
456 | 0 | fn set_frame_properties( |
457 | 0 | &mut self, output_frameno: u64, |
458 | 0 | ) -> Result<(), EncoderStatus> { |
459 | 0 | let fi = self.build_frame_properties(output_frameno)?; |
460 | | |
461 | 0 | self.frame_data.insert( |
462 | 0 | output_frameno, |
463 | 0 | fi.map(|fi| { |
464 | 0 | let frame = self |
465 | 0 | .frame_q |
466 | 0 | .get(&fi.input_frameno) |
467 | 0 | .as_ref() |
468 | 0 | .unwrap() |
469 | 0 | .as_ref() |
470 | 0 | .unwrap(); |
471 | 0 | FrameData::new(fi, frame.clone()) |
472 | 0 | }), Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::set_frame_properties::{closure#0} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::set_frame_properties::{closure#0} |
473 | 0 | ); |
474 | 0 |
|
475 | 0 | Ok(()) |
476 | 0 | } Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::set_frame_properties Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::set_frame_properties |
477 | | |
478 | | #[allow(unused)] |
479 | 0 | pub fn build_dump_properties() -> PathBuf { |
480 | 0 | let mut data_location = PathBuf::new(); |
481 | 0 | if env::var_os("RAV1E_DATA_PATH").is_some() { |
482 | 0 | data_location.push(&env::var_os("RAV1E_DATA_PATH").unwrap()); |
483 | 0 | } else { |
484 | 0 | data_location.push(&env::current_dir().unwrap()); |
485 | 0 | data_location.push(".lookahead_data"); |
486 | 0 | } |
487 | 0 | fs::create_dir_all(&data_location).unwrap(); |
488 | 0 | data_location |
489 | 0 | } |
490 | | |
491 | 0 | fn build_frame_properties( |
492 | 0 | &mut self, output_frameno: u64, |
493 | 0 | ) -> Result<Option<FrameInvariants<T>>, EncoderStatus> { |
494 | 0 | let (prev_gop_output_frameno_start, prev_gop_input_frameno_start) = |
495 | 0 | if output_frameno == 0 { |
496 | 0 | (0, 0) |
497 | | } else { |
498 | 0 | ( |
499 | 0 | self.gop_output_frameno_start[&(output_frameno - 1)], |
500 | 0 | self.gop_input_frameno_start[&(output_frameno - 1)], |
501 | 0 | ) |
502 | | }; |
503 | | |
504 | 0 | self |
505 | 0 | .gop_output_frameno_start |
506 | 0 | .insert(output_frameno, prev_gop_output_frameno_start); |
507 | 0 | self |
508 | 0 | .gop_input_frameno_start |
509 | 0 | .insert(output_frameno, prev_gop_input_frameno_start); |
510 | 0 |
|
511 | 0 | let output_frameno_in_gop = |
512 | 0 | output_frameno - self.gop_output_frameno_start[&output_frameno]; |
513 | 0 | let mut input_frameno = self.inter_cfg.get_input_frameno( |
514 | 0 | output_frameno_in_gop, |
515 | 0 | self.gop_input_frameno_start[&output_frameno], |
516 | 0 | ); |
517 | 0 |
|
518 | 0 | if self.needs_more_frame_q_lookahead(input_frameno) { |
519 | 0 | return Err(EncoderStatus::NeedMoreData); |
520 | 0 | } |
521 | | |
522 | 0 | let t35_metadata = if let Some(t35) = self.t35_q.remove(&input_frameno) { |
523 | 0 | t35 |
524 | | } else { |
525 | 0 | Box::new([]) |
526 | | }; |
527 | | |
528 | 0 | if output_frameno_in_gop > 0 { |
529 | 0 | let next_keyframe_input_frameno = self.next_keyframe_input_frameno( |
530 | 0 | self.gop_input_frameno_start[&output_frameno], |
531 | 0 | false, |
532 | 0 | ); |
533 | 0 | let prev_input_frameno = |
534 | 0 | self.get_previous_fi(output_frameno).input_frameno; |
535 | 0 | if input_frameno >= next_keyframe_input_frameno { |
536 | 0 | if !self.inter_cfg.reorder |
537 | 0 | || ((output_frameno_in_gop - 1) % self.inter_cfg.group_output_len |
538 | 0 | == 0 |
539 | 0 | && prev_input_frameno == (next_keyframe_input_frameno - 1)) |
540 | | { |
541 | 0 | input_frameno = next_keyframe_input_frameno; |
542 | 0 |
|
543 | 0 | // If we'll return early, do it before modifying the state. |
544 | 0 | match self.frame_q.get(&input_frameno) { |
545 | 0 | Some(Some(_)) => {} |
546 | | _ => { |
547 | 0 | return Err(EncoderStatus::NeedMoreData); |
548 | | } |
549 | | } |
550 | | |
551 | 0 | *self.gop_output_frameno_start.get_mut(&output_frameno).unwrap() = |
552 | 0 | output_frameno; |
553 | 0 | *self.gop_input_frameno_start.get_mut(&output_frameno).unwrap() = |
554 | 0 | next_keyframe_input_frameno; |
555 | | } else { |
556 | 0 | let fi = FrameInvariants::new_inter_frame( |
557 | 0 | self.get_previous_coded_fi(output_frameno), |
558 | 0 | &self.inter_cfg, |
559 | 0 | self.gop_input_frameno_start[&output_frameno], |
560 | 0 | output_frameno_in_gop, |
561 | 0 | next_keyframe_input_frameno, |
562 | 0 | self.config.error_resilient, |
563 | 0 | t35_metadata, |
564 | 0 | ); |
565 | 0 | assert!(fi.is_none()); |
566 | 0 | return Ok(fi); |
567 | | } |
568 | 0 | } |
569 | 0 | } |
570 | | |
571 | 0 | match self.frame_q.get(&input_frameno) { |
572 | 0 | Some(Some(_)) => {} |
573 | | _ => { |
574 | 0 | return Err(EncoderStatus::NeedMoreData); |
575 | | } |
576 | | } |
577 | | |
578 | | // Now that we know the input_frameno, look up the correct frame type |
579 | 0 | let frame_type = if self.keyframes.contains(&input_frameno) { |
580 | 0 | FrameType::KEY |
581 | | } else { |
582 | 0 | FrameType::INTER |
583 | | }; |
584 | 0 | if frame_type == FrameType::KEY { |
585 | 0 | *self.gop_output_frameno_start.get_mut(&output_frameno).unwrap() = |
586 | 0 | output_frameno; |
587 | 0 | *self.gop_input_frameno_start.get_mut(&output_frameno).unwrap() = |
588 | 0 | input_frameno; |
589 | 0 | } |
590 | | |
591 | 0 | let output_frameno_in_gop = |
592 | 0 | output_frameno - self.gop_output_frameno_start[&output_frameno]; |
593 | 0 | if output_frameno_in_gop == 0 { |
594 | 0 | let fi = FrameInvariants::new_key_frame( |
595 | 0 | self.config.clone(), |
596 | 0 | self.seq.clone(), |
597 | 0 | self.gop_input_frameno_start[&output_frameno], |
598 | 0 | t35_metadata, |
599 | 0 | ); |
600 | 0 | Ok(Some(fi)) |
601 | | } else { |
602 | 0 | let next_keyframe_input_frameno = self.next_keyframe_input_frameno( |
603 | 0 | self.gop_input_frameno_start[&output_frameno], |
604 | 0 | false, |
605 | 0 | ); |
606 | 0 | let fi = FrameInvariants::new_inter_frame( |
607 | 0 | self.get_previous_coded_fi(output_frameno), |
608 | 0 | &self.inter_cfg, |
609 | 0 | self.gop_input_frameno_start[&output_frameno], |
610 | 0 | output_frameno_in_gop, |
611 | 0 | next_keyframe_input_frameno, |
612 | 0 | self.config.error_resilient, |
613 | 0 | t35_metadata, |
614 | 0 | ); |
615 | 0 | assert!(fi.is_some()); |
616 | 0 | Ok(fi) |
617 | | } |
618 | 0 | } Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::build_frame_properties Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::build_frame_properties |
619 | | |
620 | 0 | fn get_previous_fi(&self, output_frameno: u64) -> &FrameInvariants<T> { |
621 | 0 | let res = self |
622 | 0 | .frame_data |
623 | 0 | .iter() |
624 | 0 | .filter(|(fno, _)| **fno < output_frameno) Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::get_previous_fi::{closure#0} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::get_previous_fi::{closure#0} |
625 | 0 | .rfind(|(_, fd)| fd.is_some()) Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::get_previous_fi::{closure#1} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::get_previous_fi::{closure#1} |
626 | 0 | .unwrap(); |
627 | 0 | &res.1.as_ref().unwrap().fi |
628 | 0 | } Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::get_previous_fi Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::get_previous_fi |
629 | | |
630 | 0 | fn get_previous_coded_fi(&self, output_frameno: u64) -> &FrameInvariants<T> { |
631 | 0 | let res = self |
632 | 0 | .frame_data |
633 | 0 | .iter() |
634 | 0 | .filter(|(fno, _)| **fno < output_frameno) Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::get_previous_coded_fi::{closure#0} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::get_previous_coded_fi::{closure#0} |
635 | 0 | .rfind(|(_, fd)| { |
636 | 0 | fd.as_ref().map(|fd| !fd.fi.is_show_existing_frame()).unwrap_or(false) Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::get_previous_coded_fi::{closure#1}::{closure#0} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::get_previous_coded_fi::{closure#1}::{closure#0} |
637 | 0 | }) Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::get_previous_coded_fi::{closure#1} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::get_previous_coded_fi::{closure#1} |
638 | 0 | .unwrap(); |
639 | 0 | &res.1.as_ref().unwrap().fi |
640 | 0 | } Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::get_previous_coded_fi Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::get_previous_coded_fi |
641 | | |
642 | 0 | pub(crate) fn done_processing(&self) -> bool { |
643 | 0 | self.limit.map(|limit| self.frames_processed == limit).unwrap_or(false) Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::done_processing::{closure#0} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::done_processing::{closure#0} |
644 | 0 | } Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::done_processing Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::done_processing |
645 | | |
646 | | /// Computes lookahead motion vectors and fills in `lookahead_mvs`, |
647 | | /// `rec_buffer` and `lookahead_rec_buffer` on the `FrameInvariants`. This |
648 | | /// function must be called after every new `FrameInvariants` is initially |
649 | | /// computed. |
650 | 0 | #[profiling::function] Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::compute_lookahead_motion_vectors Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::compute_lookahead_motion_vectors |
651 | | fn compute_lookahead_motion_vectors(&mut self, output_frameno: u64) { |
652 | | let frame_data = self.frame_data.get(&output_frameno).unwrap(); |
653 | | |
654 | | // We're only interested in valid frames which are not show-existing-frame. |
655 | | // Those two don't modify the rec_buffer so there's no need to do anything |
656 | | // special about it either, it'll propagate on its own. |
657 | | if frame_data |
658 | | .as_ref() |
659 | 0 | .map(|fd| fd.fi.is_show_existing_frame()) Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::compute_lookahead_motion_vectors::{closure#0} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::compute_lookahead_motion_vectors::{closure#0} |
660 | | .unwrap_or(true) |
661 | | { |
662 | | return; |
663 | | } |
664 | | |
665 | | let qps = { |
666 | | let fti = frame_data.as_ref().unwrap().fi.get_frame_subtype(); |
667 | | self.rc_state.select_qi( |
668 | | self, |
669 | | output_frameno, |
670 | | fti, |
671 | | self.maybe_prev_log_base_q, |
672 | | 0, |
673 | | ) |
674 | | }; |
675 | | |
676 | | let frame_data = |
677 | | self.frame_data.get_mut(&output_frameno).unwrap().as_mut().unwrap(); |
678 | | let fs = &mut frame_data.fs; |
679 | | let fi = &mut frame_data.fi; |
680 | | let coded_data = fi.coded_frame_data.as_mut().unwrap(); |
681 | | |
682 | | #[cfg(feature = "dump_lookahead_data")] |
683 | | { |
684 | | let data_location = Self::build_dump_properties(); |
685 | | let plane = &fs.input_qres; |
686 | | let mut file_name = format!("{:010}-qres", fi.input_frameno); |
687 | | let buf: Vec<_> = plane.iter().map(|p| p.as_()).collect(); |
688 | | image::GrayImage::from_vec( |
689 | | plane.cfg.width as u32, |
690 | | plane.cfg.height as u32, |
691 | | buf, |
692 | | ) |
693 | | .unwrap() |
694 | | .save(data_location.join(file_name).with_extension("png")) |
695 | | .unwrap(); |
696 | | let plane = &fs.input_hres; |
697 | | file_name = format!("{:010}-hres", fi.input_frameno); |
698 | | let buf: Vec<_> = plane.iter().map(|p| p.as_()).collect(); |
699 | | image::GrayImage::from_vec( |
700 | | plane.cfg.width as u32, |
701 | | plane.cfg.height as u32, |
702 | | buf, |
703 | | ) |
704 | | .unwrap() |
705 | | .save(data_location.join(file_name).with_extension("png")) |
706 | | .unwrap(); |
707 | | } |
708 | | |
709 | | // Do not modify the next output frame's FrameInvariants. |
710 | | if self.output_frameno == output_frameno { |
711 | | // We do want to propagate the lookahead_rec_buffer though. |
712 | | let rfs = Arc::new(ReferenceFrame { |
713 | | order_hint: fi.order_hint, |
714 | | width: fi.width as u32, |
715 | | height: fi.height as u32, |
716 | | render_width: fi.render_width, |
717 | | render_height: fi.render_height, |
718 | | // Use the original frame contents. |
719 | | frame: fs.input.clone(), |
720 | | input_hres: fs.input_hres.clone(), |
721 | | input_qres: fs.input_qres.clone(), |
722 | | cdfs: fs.cdfs, |
723 | | frame_me_stats: fs.frame_me_stats.clone(), |
724 | | output_frameno, |
725 | | segmentation: fs.segmentation, |
726 | | }); |
727 | | for i in 0..REF_FRAMES { |
728 | | if (fi.refresh_frame_flags & (1 << i)) != 0 { |
729 | | coded_data.lookahead_rec_buffer.frames[i] = Some(Arc::clone(&rfs)); |
730 | | coded_data.lookahead_rec_buffer.deblock[i] = fs.deblock; |
731 | | } |
732 | | } |
733 | | |
734 | | return; |
735 | | } |
736 | | |
737 | | // Our lookahead_rec_buffer should be filled with correct original frame |
738 | | // data from the previous frames. Copy it into rec_buffer because that's |
739 | | // what the MV search uses. During the actual encoding rec_buffer is |
740 | | // overwritten with its correct values anyway. |
741 | | fi.rec_buffer = coded_data.lookahead_rec_buffer.clone(); |
742 | | |
743 | | // Estimate lambda with rate-control dry-run |
744 | | fi.set_quantizers(&qps); |
745 | | |
746 | | // TODO: as in the encoding code, key frames will have no references. |
747 | | // However, for block importance purposes we want key frames to act as |
748 | | // P-frames in this instance. |
749 | | // |
750 | | // Compute the motion vectors. |
751 | | compute_motion_vectors(fi, fs, &self.inter_cfg); |
752 | | |
753 | | let coded_data = fi.coded_frame_data.as_mut().unwrap(); |
754 | | |
755 | | #[cfg(feature = "dump_lookahead_data")] |
756 | | { |
757 | | use crate::partition::RefType::*; |
758 | | let data_location = Self::build_dump_properties(); |
759 | | let file_name = format!("{:010}-mvs", fi.input_frameno); |
760 | | let second_ref_frame = if !self.inter_cfg.multiref { |
761 | | LAST_FRAME // make second_ref_frame match first |
762 | | } else if fi.idx_in_group_output == 0 { |
763 | | LAST2_FRAME |
764 | | } else { |
765 | | ALTREF_FRAME |
766 | | }; |
767 | | |
768 | | // Use the default index, it corresponds to the last P-frame or to the |
769 | | // backwards lower reference (so the closest previous frame). |
770 | | let index = if second_ref_frame.to_index() != 0 { 0 } else { 1 }; |
771 | | |
772 | | let me_stats = &fs.frame_me_stats.read().expect("poisoned lock")[index]; |
773 | | use byteorder::{NativeEndian, WriteBytesExt}; |
774 | | // dynamic allocation: debugging only |
775 | | let mut buf = vec![]; |
776 | | buf.write_u64::<NativeEndian>(me_stats.rows as u64).unwrap(); |
777 | | buf.write_u64::<NativeEndian>(me_stats.cols as u64).unwrap(); |
778 | | for y in 0..me_stats.rows { |
779 | | for x in 0..me_stats.cols { |
780 | | let mv = me_stats[y][x].mv; |
781 | | buf.write_i16::<NativeEndian>(mv.row).unwrap(); |
782 | | buf.write_i16::<NativeEndian>(mv.col).unwrap(); |
783 | | } |
784 | | } |
785 | | ::std::fs::write( |
786 | | data_location.join(file_name).with_extension("bin"), |
787 | | buf, |
788 | | ) |
789 | | .unwrap(); |
790 | | } |
791 | | |
792 | | // Set lookahead_rec_buffer on this FrameInvariants for future |
793 | | // FrameInvariants to pick it up. |
794 | | let rfs = Arc::new(ReferenceFrame { |
795 | | order_hint: fi.order_hint, |
796 | | width: fi.width as u32, |
797 | | height: fi.height as u32, |
798 | | render_width: fi.render_width, |
799 | | render_height: fi.render_height, |
800 | | // Use the original frame contents. |
801 | | frame: fs.input.clone(), |
802 | | input_hres: fs.input_hres.clone(), |
803 | | input_qres: fs.input_qres.clone(), |
804 | | cdfs: fs.cdfs, |
805 | | frame_me_stats: fs.frame_me_stats.clone(), |
806 | | output_frameno, |
807 | | segmentation: fs.segmentation, |
808 | | }); |
809 | | for i in 0..REF_FRAMES { |
810 | | if (fi.refresh_frame_flags & (1 << i)) != 0 { |
811 | | coded_data.lookahead_rec_buffer.frames[i] = Some(Arc::clone(&rfs)); |
812 | | coded_data.lookahead_rec_buffer.deblock[i] = fs.deblock; |
813 | | } |
814 | | } |
815 | | } |
816 | | |
817 | | /// Computes lookahead intra cost approximations and fills in |
818 | | /// `lookahead_intra_costs` on the `FrameInvariants`. |
819 | 0 | fn compute_lookahead_intra_costs(&mut self, output_frameno: u64) { |
820 | 0 | let frame_data = self.frame_data.get(&output_frameno).unwrap(); |
821 | 0 | let fd = &frame_data.as_ref(); |
822 | 0 |
|
823 | 0 | // We're only interested in valid frames which are not show-existing-frame. |
824 | 0 | if fd.map(|fd| fd.fi.is_show_existing_frame()).unwrap_or(true) { Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::compute_lookahead_intra_costs::{closure#0} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::compute_lookahead_intra_costs::{closure#0} |
825 | 0 | return; |
826 | 0 | } |
827 | 0 |
|
828 | 0 | let fi = &fd.unwrap().fi; |
829 | 0 |
|
830 | 0 | self |
831 | 0 | .frame_data |
832 | 0 | .get_mut(&output_frameno) |
833 | 0 | .unwrap() |
834 | 0 | .as_mut() |
835 | 0 | .unwrap() |
836 | 0 | .fi |
837 | 0 | .coded_frame_data |
838 | 0 | .as_mut() |
839 | 0 | .unwrap() |
840 | 0 | .lookahead_intra_costs = self |
841 | 0 | .keyframe_detector |
842 | 0 | .intra_costs |
843 | 0 | .remove(&fi.input_frameno) |
844 | 0 | .unwrap_or_else(|| { |
845 | 0 | let frame = self.frame_q[&fi.input_frameno].as_ref().unwrap(); |
846 | 0 |
|
847 | 0 | let temp_plane = self |
848 | 0 | .keyframe_detector |
849 | 0 | .temp_plane |
850 | 0 | .get_or_insert_with(|| frame.planes[0].clone()); Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::compute_lookahead_intra_costs::{closure#1}::{closure#0} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::compute_lookahead_intra_costs::{closure#1}::{closure#0} |
851 | 0 |
|
852 | 0 | // We use the cached values from scenechange if available, |
853 | 0 | // otherwise we need to calculate them here. |
854 | 0 | estimate_intra_costs( |
855 | 0 | temp_plane, |
856 | 0 | &**frame, |
857 | 0 | fi.sequence.bit_depth, |
858 | 0 | fi.cpu_feature_level, |
859 | 0 | ) |
860 | 0 | }); Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::compute_lookahead_intra_costs::{closure#1} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::compute_lookahead_intra_costs::{closure#1} |
861 | 0 | } Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::compute_lookahead_intra_costs Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::compute_lookahead_intra_costs |
862 | | |
863 | 0 | #[profiling::function] Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::compute_keyframe_placement Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::compute_keyframe_placement |
864 | | pub fn compute_keyframe_placement( |
865 | | lookahead_frames: &[&Arc<Frame<T>>], keyframes_forced: &BTreeSet<u64>, |
866 | | keyframe_detector: &mut SceneChangeDetector<T>, |
867 | | next_lookahead_frame: &mut u64, keyframes: &mut BTreeSet<u64>, |
868 | | ) { |
869 | | if keyframes_forced.contains(next_lookahead_frame) |
870 | | || keyframe_detector.analyze_next_frame( |
871 | | lookahead_frames, |
872 | | *next_lookahead_frame, |
873 | | *keyframes.iter().last().unwrap(), |
874 | | ) |
875 | | { |
876 | | keyframes.insert(*next_lookahead_frame); |
877 | | } |
878 | | |
879 | | *next_lookahead_frame += 1; |
880 | | } |
881 | | |
882 | 0 | #[profiling::function] Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::compute_frame_invariants Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::compute_frame_invariants |
883 | | pub fn compute_frame_invariants(&mut self) { |
884 | | while self.set_frame_properties(self.next_lookahead_output_frameno).is_ok() |
885 | | { |
886 | | self |
887 | | .compute_lookahead_motion_vectors(self.next_lookahead_output_frameno); |
888 | | if self.config.temporal_rdo() { |
889 | | self.compute_lookahead_intra_costs(self.next_lookahead_output_frameno); |
890 | | } |
891 | | self.next_lookahead_output_frameno += 1; |
892 | | } |
893 | | } |
894 | | |
895 | 0 | #[profiling::function] Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::update_block_importances Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::update_block_importances |
896 | | fn update_block_importances( |
897 | | fi: &FrameInvariants<T>, me_stats: &crate::me::FrameMEStats, |
898 | | frame: &Frame<T>, reference_frame: &Frame<T>, bit_depth: usize, |
899 | | bsize: BlockSize, len: usize, |
900 | | reference_frame_block_importances: &mut [f32], |
901 | | ) { |
902 | | let coded_data = fi.coded_frame_data.as_ref().unwrap(); |
903 | | let plane_org = &frame.planes[0]; |
904 | | let plane_ref = &reference_frame.planes[0]; |
905 | | let lookahead_intra_costs_lines = |
906 | | coded_data.lookahead_intra_costs.chunks_exact(coded_data.w_in_imp_b); |
907 | | let block_importances_lines = |
908 | | coded_data.block_importances.chunks_exact(coded_data.w_in_imp_b); |
909 | | |
910 | | lookahead_intra_costs_lines |
911 | | .zip(block_importances_lines) |
912 | | .zip(me_stats.rows_iter().step_by(2)) |
913 | | .enumerate() |
914 | | .flat_map( |
915 | 0 | |(y, ((lookahead_intra_costs, block_importances), me_stats_line))| { |
916 | 0 | lookahead_intra_costs |
917 | 0 | .iter() |
918 | 0 | .zip(block_importances.iter()) |
919 | 0 | .zip(me_stats_line.iter().step_by(2)) |
920 | 0 | .enumerate() |
921 | 0 | .map(move |(x, ((&intra_cost, &future_importance), &me_stat))| { |
922 | 0 | let mv = me_stat.mv; |
923 | 0 |
|
924 | 0 | // Coordinates of the top-left corner of the reference block, in MV |
925 | 0 | // units. |
926 | 0 | let reference_x = |
927 | 0 | x as i64 * IMP_BLOCK_SIZE_IN_MV_UNITS + mv.col as i64; |
928 | 0 | let reference_y = |
929 | 0 | y as i64 * IMP_BLOCK_SIZE_IN_MV_UNITS + mv.row as i64; |
930 | 0 |
|
931 | 0 | let region_org = plane_org.region(Area::Rect { |
932 | 0 | x: (x * IMPORTANCE_BLOCK_SIZE) as isize, |
933 | 0 | y: (y * IMPORTANCE_BLOCK_SIZE) as isize, |
934 | 0 | width: IMPORTANCE_BLOCK_SIZE, |
935 | 0 | height: IMPORTANCE_BLOCK_SIZE, |
936 | 0 | }); |
937 | 0 |
|
938 | 0 | let region_ref = plane_ref.region(Area::Rect { |
939 | 0 | x: reference_x as isize |
940 | 0 | / IMP_BLOCK_MV_UNITS_PER_PIXEL as isize, |
941 | 0 | y: reference_y as isize |
942 | 0 | / IMP_BLOCK_MV_UNITS_PER_PIXEL as isize, |
943 | 0 | width: IMPORTANCE_BLOCK_SIZE, |
944 | 0 | height: IMPORTANCE_BLOCK_SIZE, |
945 | 0 | }); |
946 | 0 |
|
947 | 0 | let inter_cost = get_satd( |
948 | 0 | ®ion_org, |
949 | 0 | ®ion_ref, |
950 | 0 | bsize.width(), |
951 | 0 | bsize.height(), |
952 | 0 | bit_depth, |
953 | 0 | fi.cpu_feature_level, |
954 | 0 | ) as f32; |
955 | 0 |
|
956 | 0 | let intra_cost = intra_cost as f32; |
957 | | // let intra_cost = lookahead_intra_costs[x] as f32; |
958 | | // let future_importance = block_importances[x]; |
959 | | |
960 | 0 | let propagate_fraction = if intra_cost <= inter_cost { |
961 | 0 | 0. |
962 | | } else { |
963 | 0 | 1. - inter_cost / intra_cost |
964 | | }; |
965 | | |
966 | 0 | let propagate_amount = (intra_cost + future_importance) |
967 | 0 | * propagate_fraction |
968 | 0 | / len as f32; |
969 | 0 | (propagate_amount, reference_x, reference_y) |
970 | 0 | }) Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::update_block_importances::{closure#0}::{closure#0} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::update_block_importances::{closure#0}::{closure#0} |
971 | 0 | }, Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::update_block_importances::{closure#0} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::update_block_importances::{closure#0} |
972 | | ) |
973 | 0 | .for_each(|(propagate_amount, reference_x, reference_y)| { |
974 | 0 | let mut propagate = |
975 | 0 | |block_x_in_mv_units, block_y_in_mv_units, fraction| { |
976 | 0 | let x = block_x_in_mv_units / IMP_BLOCK_SIZE_IN_MV_UNITS; |
977 | 0 | let y = block_y_in_mv_units / IMP_BLOCK_SIZE_IN_MV_UNITS; |
978 | 0 |
|
979 | 0 | // TODO: propagate partially if the block is partially off-frame |
980 | 0 | // (possible on right and bottom edges)? |
981 | 0 | if x >= 0 |
982 | 0 | && y >= 0 |
983 | 0 | && (x as usize) < coded_data.w_in_imp_b |
984 | 0 | && (y as usize) < coded_data.h_in_imp_b |
985 | 0 | { |
986 | 0 | reference_frame_block_importances |
987 | 0 | [y as usize * coded_data.w_in_imp_b + x as usize] += |
988 | 0 | propagate_amount * fraction; |
989 | 0 | } |
990 | 0 | }; Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::update_block_importances::{closure#1}::{closure#0} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::update_block_importances::{closure#1}::{closure#0} |
991 | | |
992 | | // Coordinates of the top-left corner of the block intersecting the |
993 | | // reference block from the top-left. |
994 | 0 | let top_left_block_x = (reference_x |
995 | 0 | - if reference_x < 0 { IMP_BLOCK_SIZE_IN_MV_UNITS - 1 } else { 0 }) |
996 | | / IMP_BLOCK_SIZE_IN_MV_UNITS |
997 | | * IMP_BLOCK_SIZE_IN_MV_UNITS; |
998 | 0 | let top_left_block_y = (reference_y |
999 | 0 | - if reference_y < 0 { IMP_BLOCK_SIZE_IN_MV_UNITS - 1 } else { 0 }) |
1000 | | / IMP_BLOCK_SIZE_IN_MV_UNITS |
1001 | | * IMP_BLOCK_SIZE_IN_MV_UNITS; |
1002 | | |
1003 | 0 | debug_assert!(reference_x >= top_left_block_x); |
1004 | 0 | debug_assert!(reference_y >= top_left_block_y); |
1005 | | |
1006 | 0 | let top_right_block_x = top_left_block_x + IMP_BLOCK_SIZE_IN_MV_UNITS; |
1007 | 0 | let top_right_block_y = top_left_block_y; |
1008 | 0 | let bottom_left_block_x = top_left_block_x; |
1009 | 0 | let bottom_left_block_y = |
1010 | 0 | top_left_block_y + IMP_BLOCK_SIZE_IN_MV_UNITS; |
1011 | 0 | let bottom_right_block_x = top_right_block_x; |
1012 | 0 | let bottom_right_block_y = bottom_left_block_y; |
1013 | 0 |
|
1014 | 0 | let top_left_block_fraction = ((top_right_block_x - reference_x) |
1015 | 0 | * (bottom_left_block_y - reference_y)) |
1016 | 0 | as f32 |
1017 | 0 | / IMP_BLOCK_AREA_IN_MV_UNITS as f32; |
1018 | 0 |
|
1019 | 0 | propagate(top_left_block_x, top_left_block_y, top_left_block_fraction); |
1020 | 0 |
|
1021 | 0 | let top_right_block_fraction = |
1022 | 0 | ((reference_x + IMP_BLOCK_SIZE_IN_MV_UNITS - top_right_block_x) |
1023 | 0 | * (bottom_left_block_y - reference_y)) as f32 |
1024 | 0 | / IMP_BLOCK_AREA_IN_MV_UNITS as f32; |
1025 | 0 |
|
1026 | 0 | propagate( |
1027 | 0 | top_right_block_x, |
1028 | 0 | top_right_block_y, |
1029 | 0 | top_right_block_fraction, |
1030 | 0 | ); |
1031 | 0 |
|
1032 | 0 | let bottom_left_block_fraction = ((top_right_block_x - reference_x) |
1033 | 0 | * (reference_y + IMP_BLOCK_SIZE_IN_MV_UNITS - bottom_left_block_y)) |
1034 | 0 | as f32 |
1035 | 0 | / IMP_BLOCK_AREA_IN_MV_UNITS as f32; |
1036 | 0 |
|
1037 | 0 | propagate( |
1038 | 0 | bottom_left_block_x, |
1039 | 0 | bottom_left_block_y, |
1040 | 0 | bottom_left_block_fraction, |
1041 | 0 | ); |
1042 | 0 |
|
1043 | 0 | let bottom_right_block_fraction = |
1044 | 0 | ((reference_x + IMP_BLOCK_SIZE_IN_MV_UNITS - top_right_block_x) |
1045 | 0 | * (reference_y + IMP_BLOCK_SIZE_IN_MV_UNITS - bottom_left_block_y)) |
1046 | 0 | as f32 |
1047 | 0 | / IMP_BLOCK_AREA_IN_MV_UNITS as f32; |
1048 | 0 |
|
1049 | 0 | propagate( |
1050 | 0 | bottom_right_block_x, |
1051 | 0 | bottom_right_block_y, |
1052 | 0 | bottom_right_block_fraction, |
1053 | 0 | ); |
1054 | 0 | }); Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::update_block_importances::{closure#1} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::update_block_importances::{closure#1} |
1055 | | } |
1056 | | |
1057 | | /// Computes the block importances for the current output frame. |
1058 | 0 | #[profiling::function] Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::compute_block_importances Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::compute_block_importances |
1059 | | fn compute_block_importances(&mut self) { |
1060 | | // SEF don't need block importances. |
1061 | | if self.frame_data[&self.output_frameno] |
1062 | | .as_ref() |
1063 | | .unwrap() |
1064 | | .fi |
1065 | | .is_show_existing_frame() |
1066 | | { |
1067 | | return; |
1068 | | } |
1069 | | |
1070 | | // Get a list of output_framenos that we want to propagate through. |
1071 | | let output_framenos = self |
1072 | | .get_rdo_lookahead_frames() |
1073 | 0 | .map(|(&output_frameno, _)| output_frameno) Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::compute_block_importances::{closure#0} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::compute_block_importances::{closure#0} |
1074 | | .collect::<Vec<_>>(); |
1075 | | |
1076 | | // The first one should be the current output frame. |
1077 | | assert_eq!(output_framenos[0], self.output_frameno); |
1078 | | |
1079 | | // First, initialize them all with zeros. |
1080 | | for output_frameno in output_framenos.iter() { |
1081 | | let fi = &mut self |
1082 | | .frame_data |
1083 | | .get_mut(output_frameno) |
1084 | | .unwrap() |
1085 | | .as_mut() |
1086 | | .unwrap() |
1087 | | .fi; |
1088 | | for x in |
1089 | | fi.coded_frame_data.as_mut().unwrap().block_importances.iter_mut() |
1090 | | { |
1091 | | *x = 0.; |
1092 | | } |
1093 | | } |
1094 | | |
1095 | | // Now compute and propagate the block importances from the end. The |
1096 | | // current output frame will get its block importances from the future |
1097 | | // frames. |
1098 | | let bsize = BlockSize::from_width_and_height( |
1099 | | IMPORTANCE_BLOCK_SIZE, |
1100 | | IMPORTANCE_BLOCK_SIZE, |
1101 | | ); |
1102 | | |
1103 | | for &output_frameno in output_framenos.iter().skip(1).rev() { |
1104 | | // TODO: see comment above about key frames not having references. |
1105 | | if self |
1106 | | .frame_data |
1107 | | .get(&output_frameno) |
1108 | | .unwrap() |
1109 | | .as_ref() |
1110 | | .unwrap() |
1111 | | .fi |
1112 | | .frame_type |
1113 | | == FrameType::KEY |
1114 | | { |
1115 | | continue; |
1116 | | } |
1117 | | |
1118 | | // Remove fi from the map temporarily and put it back in in the end of |
1119 | | // the iteration. This is required because we need to mutably borrow |
1120 | | // referenced fis from the map, and that wouldn't be possible if this was |
1121 | | // an active borrow. |
1122 | | // |
1123 | | // Performance note: Contrary to intuition, |
1124 | | // removing the data and re-inserting it at the end |
1125 | | // is more performant because it avoids a very expensive clone. |
1126 | | let output_frame_data = |
1127 | | self.frame_data.remove(&output_frameno).unwrap().unwrap(); |
1128 | | { |
1129 | | let fi = &output_frame_data.fi; |
1130 | | let fs = &output_frame_data.fs; |
1131 | | |
1132 | | let frame = self.frame_q[&fi.input_frameno].as_ref().unwrap(); |
1133 | | |
1134 | | // There can be at most 3 of these. |
1135 | | let mut unique_indices = ArrayVec::<_, 3>::new(); |
1136 | | |
1137 | | for (mv_index, &rec_index) in fi.ref_frames.iter().enumerate() { |
1138 | 0 | if !unique_indices.iter().any(|&(_, r)| r == rec_index) { Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::compute_block_importances::{closure#1} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::compute_block_importances::{closure#1} |
1139 | | unique_indices.push((mv_index, rec_index)); |
1140 | | } |
1141 | | } |
1142 | | |
1143 | | let bit_depth = self.config.bit_depth; |
1144 | | let frame_data = &mut self.frame_data; |
1145 | | let len = unique_indices.len(); |
1146 | | |
1147 | | let lookahead_me_stats = |
1148 | | fs.frame_me_stats.read().expect("poisoned lock"); |
1149 | | |
1150 | | // Compute and propagate the importance, split evenly between the |
1151 | | // referenced frames. |
1152 | 0 | unique_indices.iter().for_each(|&(mv_index, rec_index)| { |
1153 | 0 | // Use rec_buffer here rather than lookahead_rec_buffer because |
1154 | 0 | // rec_buffer still contains the reference frames for the current frame |
1155 | 0 | // (it's only overwritten when the frame is encoded), while |
1156 | 0 | // lookahead_rec_buffer already contains reference frames for the next |
1157 | 0 | // frame (for the reference propagation to work correctly). |
1158 | 0 | let reference = |
1159 | 0 | fi.rec_buffer.frames[rec_index as usize].as_ref().unwrap(); |
1160 | 0 | let reference_frame = &reference.frame; |
1161 | 0 | let reference_output_frameno = reference.output_frameno; |
1162 | 0 | let me_stats = &lookahead_me_stats[mv_index]; |
1163 | 0 |
|
1164 | 0 | // We should never use frame as its own reference. |
1165 | 0 | assert_ne!(reference_output_frameno, output_frameno); |
1166 | | |
1167 | 0 | if let Some(reference_frame_block_importances) = |
1168 | 0 | frame_data.get_mut(&reference_output_frameno).map(|data| { |
1169 | 0 | &mut data |
1170 | 0 | .as_mut() |
1171 | 0 | .unwrap() |
1172 | 0 | .fi |
1173 | 0 | .coded_frame_data |
1174 | 0 | .as_mut() |
1175 | 0 | .unwrap() |
1176 | 0 | .block_importances |
1177 | 0 | }) Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::compute_block_importances::{closure#2}::{closure#0} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::compute_block_importances::{closure#2}::{closure#0} |
1178 | 0 | { |
1179 | 0 | Self::update_block_importances( |
1180 | 0 | fi, |
1181 | 0 | me_stats, |
1182 | 0 | frame, |
1183 | 0 | reference_frame, |
1184 | 0 | bit_depth, |
1185 | 0 | bsize, |
1186 | 0 | len, |
1187 | 0 | reference_frame_block_importances, |
1188 | 0 | ); |
1189 | 0 | } |
1190 | 0 | }); Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::compute_block_importances::{closure#2} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::compute_block_importances::{closure#2} |
1191 | | } |
1192 | | self.frame_data.insert(output_frameno, Some(output_frame_data)); |
1193 | | } |
1194 | | |
1195 | | if !output_framenos.is_empty() { |
1196 | | let fi = &mut self |
1197 | | .frame_data |
1198 | | .get_mut(&output_framenos[0]) |
1199 | | .unwrap() |
1200 | | .as_mut() |
1201 | | .unwrap() |
1202 | | .fi; |
1203 | | let coded_data = fi.coded_frame_data.as_mut().unwrap(); |
1204 | | let block_importances = coded_data.block_importances.iter(); |
1205 | | let lookahead_intra_costs = coded_data.lookahead_intra_costs.iter(); |
1206 | | let distortion_scales = coded_data.distortion_scales.iter_mut(); |
1207 | | for ((&propagate_cost, &intra_cost), distortion_scale) in |
1208 | | block_importances.zip(lookahead_intra_costs).zip(distortion_scales) |
1209 | | { |
1210 | | *distortion_scale = crate::rdo::distortion_scale_for( |
1211 | | propagate_cost as f64, |
1212 | | intra_cost as f64, |
1213 | | ); |
1214 | | } |
1215 | | #[cfg(feature = "dump_lookahead_data")] |
1216 | | { |
1217 | | use byteorder::{NativeEndian, WriteBytesExt}; |
1218 | | |
1219 | | let coded_data = fi.coded_frame_data.as_ref().unwrap(); |
1220 | | |
1221 | | let mut buf = vec![]; |
1222 | | let data_location = Self::build_dump_properties(); |
1223 | | let file_name = format!("{:010}-imps", fi.input_frameno); |
1224 | | buf.write_u64::<NativeEndian>(coded_data.h_in_imp_b as u64).unwrap(); |
1225 | | buf.write_u64::<NativeEndian>(coded_data.w_in_imp_b as u64).unwrap(); |
1226 | | buf.write_u64::<NativeEndian>(fi.get_frame_subtype() as u64).unwrap(); |
1227 | | for y in 0..coded_data.h_in_imp_b { |
1228 | | for x in 0..coded_data.w_in_imp_b { |
1229 | | buf |
1230 | | .write_f32::<NativeEndian>(f64::from( |
1231 | | coded_data.distortion_scales[y * coded_data.w_in_imp_b + x], |
1232 | | ) as f32) |
1233 | | .unwrap(); |
1234 | | } |
1235 | | } |
1236 | | ::std::fs::write( |
1237 | | data_location.join(file_name).with_extension("bin"), |
1238 | | buf, |
1239 | | ) |
1240 | | .unwrap(); |
1241 | | } |
1242 | | } |
1243 | | } |
1244 | | |
1245 | 0 | pub(crate) fn encode_packet( |
1246 | 0 | &mut self, cur_output_frameno: u64, |
1247 | 0 | ) -> Result<Packet<T>, EncoderStatus> { |
1248 | 0 | if self |
1249 | 0 | .frame_data |
1250 | 0 | .get(&cur_output_frameno) |
1251 | 0 | .unwrap() |
1252 | 0 | .as_ref() |
1253 | 0 | .unwrap() |
1254 | 0 | .fi |
1255 | 0 | .is_show_existing_frame() |
1256 | | { |
1257 | 0 | if !self.rc_state.ready() { |
1258 | 0 | return Err(EncoderStatus::NotReady); |
1259 | 0 | } |
1260 | 0 |
|
1261 | 0 | self.encode_show_existing_packet(cur_output_frameno) |
1262 | 0 | } else if let Some(Some(_)) = self.frame_q.get( |
1263 | 0 | &self |
1264 | 0 | .frame_data |
1265 | 0 | .get(&cur_output_frameno) |
1266 | 0 | .unwrap() |
1267 | 0 | .as_ref() |
1268 | 0 | .unwrap() |
1269 | 0 | .fi |
1270 | 0 | .input_frameno, |
1271 | 0 | ) { |
1272 | 0 | if !self.rc_state.ready() { |
1273 | 0 | return Err(EncoderStatus::NotReady); |
1274 | 0 | } |
1275 | 0 |
|
1276 | 0 | self.encode_normal_packet(cur_output_frameno) |
1277 | | } else { |
1278 | 0 | Err(EncoderStatus::NeedMoreData) |
1279 | | } |
1280 | 0 | } Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::encode_packet Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::encode_packet |
1281 | | |
1282 | 0 | #[profiling::function] Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::encode_show_existing_packet Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::encode_show_existing_packet |
1283 | | pub fn encode_show_existing_packet( |
1284 | | &mut self, cur_output_frameno: u64, |
1285 | | ) -> Result<Packet<T>, EncoderStatus> { |
1286 | | let frame_data = |
1287 | | self.frame_data.get_mut(&cur_output_frameno).unwrap().as_mut().unwrap(); |
1288 | | let sef_data = encode_show_existing_frame( |
1289 | | &frame_data.fi, |
1290 | | &mut frame_data.fs, |
1291 | | &self.inter_cfg, |
1292 | | ); |
1293 | | let bits = (sef_data.len() * 8) as i64; |
1294 | | self.packet_data.extend(sef_data); |
1295 | | self.rc_state.update_state( |
1296 | | bits, |
1297 | | FRAME_SUBTYPE_SEF, |
1298 | | frame_data.fi.show_frame, |
1299 | | 0, |
1300 | | false, |
1301 | | false, |
1302 | | ); |
1303 | | let (rec, source) = if frame_data.fi.show_frame { |
1304 | | (Some(frame_data.fs.rec.clone()), Some(frame_data.fs.input.clone())) |
1305 | | } else { |
1306 | | (None, None) |
1307 | | }; |
1308 | | |
1309 | | self.output_frameno += 1; |
1310 | | |
1311 | | let input_frameno = frame_data.fi.input_frameno; |
1312 | | let frame_type = frame_data.fi.frame_type; |
1313 | | let qp = frame_data.fi.base_q_idx; |
1314 | | let enc_stats = frame_data.fs.enc_stats.clone(); |
1315 | | self.finalize_packet(rec, source, input_frameno, frame_type, qp, enc_stats) |
1316 | | } |
1317 | | |
1318 | 0 | #[profiling::function] Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::encode_normal_packet Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::encode_normal_packet |
1319 | | pub fn encode_normal_packet( |
1320 | | &mut self, cur_output_frameno: u64, |
1321 | | ) -> Result<Packet<T>, EncoderStatus> { |
1322 | | let mut frame_data = |
1323 | | self.frame_data.remove(&cur_output_frameno).unwrap().unwrap(); |
1324 | | |
1325 | | let mut log_isqrt_mean_scale = 0i64; |
1326 | | |
1327 | | if let Some(coded_data) = frame_data.fi.coded_frame_data.as_mut() { |
1328 | | if self.config.tune == Tune::Psychovisual { |
1329 | | let frame = |
1330 | | self.frame_q[&frame_data.fi.input_frameno].as_ref().unwrap(); |
1331 | | coded_data.activity_mask = ActivityMask::from_plane(&frame.planes[0]); |
1332 | | coded_data.activity_mask.fill_scales( |
1333 | | frame_data.fi.sequence.bit_depth, |
1334 | | &mut coded_data.activity_scales, |
1335 | | ); |
1336 | | log_isqrt_mean_scale = coded_data.compute_spatiotemporal_scores(); |
1337 | | } else { |
1338 | | coded_data.activity_mask = ActivityMask::default(); |
1339 | | log_isqrt_mean_scale = coded_data.compute_temporal_scores(); |
1340 | | } |
1341 | | #[cfg(feature = "dump_lookahead_data")] |
1342 | | { |
1343 | | use crate::encoder::Scales::*; |
1344 | | let input_frameno = frame_data.fi.input_frameno; |
1345 | | if self.config.tune == Tune::Psychovisual { |
1346 | | coded_data.dump_scales( |
1347 | | Self::build_dump_properties(), |
1348 | | ActivityScales, |
1349 | | input_frameno, |
1350 | | ); |
1351 | | coded_data.dump_scales( |
1352 | | Self::build_dump_properties(), |
1353 | | SpatiotemporalScales, |
1354 | | input_frameno, |
1355 | | ); |
1356 | | } |
1357 | | coded_data.dump_scales( |
1358 | | Self::build_dump_properties(), |
1359 | | DistortionScales, |
1360 | | input_frameno, |
1361 | | ); |
1362 | | } |
1363 | | } |
1364 | | |
1365 | | let fti = frame_data.fi.get_frame_subtype(); |
1366 | | let qps = self.rc_state.select_qi( |
1367 | | self, |
1368 | | cur_output_frameno, |
1369 | | fti, |
1370 | | self.maybe_prev_log_base_q, |
1371 | | log_isqrt_mean_scale, |
1372 | | ); |
1373 | | frame_data.fi.set_quantizers(&qps); |
1374 | | |
1375 | | if self.rc_state.needs_trial_encode(fti) { |
1376 | | let mut trial_fs = frame_data.fs.clone(); |
1377 | | let data = encode_frame(&frame_data.fi, &mut trial_fs, &self.inter_cfg); |
1378 | | self.rc_state.update_state( |
1379 | | (data.len() * 8) as i64, |
1380 | | fti, |
1381 | | frame_data.fi.show_frame, |
1382 | | qps.log_target_q, |
1383 | | true, |
1384 | | false, |
1385 | | ); |
1386 | | let qps = self.rc_state.select_qi( |
1387 | | self, |
1388 | | cur_output_frameno, |
1389 | | fti, |
1390 | | self.maybe_prev_log_base_q, |
1391 | | log_isqrt_mean_scale, |
1392 | | ); |
1393 | | frame_data.fi.set_quantizers(&qps); |
1394 | | } |
1395 | | |
1396 | | let data = |
1397 | | encode_frame(&frame_data.fi, &mut frame_data.fs, &self.inter_cfg); |
1398 | | #[cfg(feature = "dump_lookahead_data")] |
1399 | | { |
1400 | | let input_frameno = frame_data.fi.input_frameno; |
1401 | | let data_location = Self::build_dump_properties(); |
1402 | | frame_data.fs.segmentation.dump_threshold(data_location, input_frameno); |
1403 | | } |
1404 | | let enc_stats = frame_data.fs.enc_stats.clone(); |
1405 | | self.maybe_prev_log_base_q = Some(qps.log_base_q); |
1406 | | // TODO: Add support for dropping frames. |
1407 | | self.rc_state.update_state( |
1408 | | (data.len() * 8) as i64, |
1409 | | fti, |
1410 | | frame_data.fi.show_frame, |
1411 | | qps.log_target_q, |
1412 | | false, |
1413 | | false, |
1414 | | ); |
1415 | | self.packet_data.extend(data); |
1416 | | |
1417 | | let planes = |
1418 | | if frame_data.fi.sequence.chroma_sampling == Cs400 { 1 } else { 3 }; |
1419 | | |
1420 | | Arc::get_mut(&mut frame_data.fs.rec).unwrap().pad( |
1421 | | frame_data.fi.width, |
1422 | | frame_data.fi.height, |
1423 | | planes, |
1424 | | ); |
1425 | | |
1426 | | let (rec, source) = if frame_data.fi.show_frame { |
1427 | | (Some(frame_data.fs.rec.clone()), Some(frame_data.fs.input.clone())) |
1428 | | } else { |
1429 | | (None, None) |
1430 | | }; |
1431 | | |
1432 | | update_rec_buffer(cur_output_frameno, &mut frame_data.fi, &frame_data.fs); |
1433 | | |
1434 | | // Copy persistent fields into subsequent FrameInvariants. |
1435 | | let rec_buffer = frame_data.fi.rec_buffer.clone(); |
1436 | | for subsequent_fi in self |
1437 | | .frame_data |
1438 | | .iter_mut() |
1439 | 0 | .skip_while(|(&output_frameno, _)| output_frameno <= cur_output_frameno) Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::encode_normal_packet::{closure#0} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::encode_normal_packet::{closure#0} |
1440 | | // Here we want the next valid non-show-existing-frame inter frame. |
1441 | | // |
1442 | | // Copying to show-existing-frame frames isn't actually required |
1443 | | // for correct encoding, but it's needed for the reconstruction to |
1444 | | // work correctly. |
1445 | 0 | .filter_map(|(_, frame_data)| frame_data.as_mut().map(|fd| &mut fd.fi)) Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::encode_normal_packet::{closure#1} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::encode_normal_packet::{closure#1} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::encode_normal_packet::{closure#1}::{closure#0} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::encode_normal_packet::{closure#1}::{closure#0} |
1446 | 0 | .take_while(|fi| fi.frame_type != FrameType::KEY) Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::encode_normal_packet::{closure#2} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::encode_normal_packet::{closure#2} |
1447 | | { |
1448 | | subsequent_fi.rec_buffer = rec_buffer.clone(); |
1449 | | subsequent_fi.set_ref_frame_sign_bias(); |
1450 | | |
1451 | | // Stop after the first non-show-existing-frame. |
1452 | | if !subsequent_fi.is_show_existing_frame() { |
1453 | | break; |
1454 | | } |
1455 | | } |
1456 | | |
1457 | | self.frame_data.insert(cur_output_frameno, Some(frame_data)); |
1458 | | let frame_data = |
1459 | | self.frame_data.get(&cur_output_frameno).unwrap().as_ref().unwrap(); |
1460 | | let fi = &frame_data.fi; |
1461 | | |
1462 | | self.output_frameno += 1; |
1463 | | |
1464 | | if fi.show_frame { |
1465 | | let input_frameno = fi.input_frameno; |
1466 | | let frame_type = fi.frame_type; |
1467 | | let qp = fi.base_q_idx; |
1468 | | self.finalize_packet( |
1469 | | rec, |
1470 | | source, |
1471 | | input_frameno, |
1472 | | frame_type, |
1473 | | qp, |
1474 | | enc_stats, |
1475 | | ) |
1476 | | } else { |
1477 | | Err(EncoderStatus::Encoded) |
1478 | | } |
1479 | | } |
1480 | | |
1481 | 0 | #[profiling::function] Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::receive_packet Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::receive_packet |
1482 | | pub fn receive_packet(&mut self) -> Result<Packet<T>, EncoderStatus> { |
1483 | | if self.done_processing() { |
1484 | | return Err(EncoderStatus::LimitReached); |
1485 | | } |
1486 | | |
1487 | | if self.needs_more_fi_lookahead() { |
1488 | | return Err(EncoderStatus::NeedMoreData); |
1489 | | } |
1490 | | |
1491 | | // Find the next output_frameno corresponding to a non-skipped frame. |
1492 | | self.output_frameno = self |
1493 | | .frame_data |
1494 | | .iter() |
1495 | 0 | .skip_while(|(&output_frameno, _)| output_frameno < self.output_frameno) Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::receive_packet::{closure#0} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::receive_packet::{closure#0} |
1496 | 0 | .find(|(_, data)| data.is_some()) Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::receive_packet::{closure#1} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::receive_packet::{closure#1} |
1497 | 0 | .map(|(&output_frameno, _)| output_frameno) Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::receive_packet::{closure#2} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::receive_packet::{closure#2} |
1498 | | .ok_or(EncoderStatus::NeedMoreData)?; // TODO: doesn't play well with the below check? |
1499 | | |
1500 | | let input_frameno = |
1501 | | self.frame_data[&self.output_frameno].as_ref().unwrap().fi.input_frameno; |
1502 | | if !self.needs_more_frames(input_frameno) { |
1503 | | return Err(EncoderStatus::LimitReached); |
1504 | | } |
1505 | | |
1506 | | if self.config.temporal_rdo() { |
1507 | | // Compute the block importances for the current output frame. |
1508 | | self.compute_block_importances(); |
1509 | | } |
1510 | | |
1511 | | let cur_output_frameno = self.output_frameno; |
1512 | | |
1513 | | let mut ret = self.encode_packet(cur_output_frameno); |
1514 | | |
1515 | | if let Ok(ref mut pkt) = ret { |
1516 | | self.garbage_collect(pkt.input_frameno); |
1517 | | pkt.opaque = self.opaque_q.remove(&pkt.input_frameno); |
1518 | | } |
1519 | | |
1520 | | ret |
1521 | | } |
1522 | | |
1523 | 0 | fn finalize_packet( |
1524 | 0 | &mut self, rec: Option<Arc<Frame<T>>>, source: Option<Arc<Frame<T>>>, |
1525 | 0 | input_frameno: u64, frame_type: FrameType, qp: u8, |
1526 | 0 | enc_stats: EncoderStats, |
1527 | 0 | ) -> Result<Packet<T>, EncoderStatus> { |
1528 | 0 | let data = self.packet_data.clone(); |
1529 | 0 | self.packet_data.clear(); |
1530 | 0 | if write_temporal_delimiter(&mut self.packet_data).is_err() { |
1531 | 0 | return Err(EncoderStatus::Failure); |
1532 | 0 | } |
1533 | 0 |
|
1534 | 0 | self.frames_processed += 1; |
1535 | 0 | Ok(Packet { |
1536 | 0 | data, |
1537 | 0 | rec, |
1538 | 0 | source, |
1539 | 0 | input_frameno, |
1540 | 0 | frame_type, |
1541 | 0 | qp, |
1542 | 0 | enc_stats, |
1543 | 0 | opaque: None, |
1544 | 0 | }) |
1545 | 0 | } Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::finalize_packet Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::finalize_packet |
1546 | | |
1547 | 0 | #[profiling::function] Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::garbage_collect Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::garbage_collect |
1548 | | fn garbage_collect(&mut self, cur_input_frameno: u64) { |
1549 | | if cur_input_frameno == 0 { |
1550 | | return; |
1551 | | } |
1552 | | let frame_q_start = self.frame_q.keys().next().cloned().unwrap_or(0); |
1553 | | for i in frame_q_start..cur_input_frameno { |
1554 | | self.frame_q.remove(&i); |
1555 | | } |
1556 | | |
1557 | | if self.output_frameno < 2 { |
1558 | | return; |
1559 | | } |
1560 | | let fi_start = self.frame_data.keys().next().cloned().unwrap_or(0); |
1561 | | for i in fi_start..(self.output_frameno - 1) { |
1562 | | self.frame_data.remove(&i); |
1563 | | self.gop_output_frameno_start.remove(&i); |
1564 | | self.gop_input_frameno_start.remove(&i); |
1565 | | } |
1566 | | } |
1567 | | |
1568 | | /// Counts the number of output frames of each subtype in the next |
1569 | | /// `reservoir_frame_delay` temporal units (needed for rate control). |
1570 | | /// Returns the number of output frames (excluding SEF frames) and output TUs |
1571 | | /// until the last keyframe in the next `reservoir_frame_delay` temporal units, |
1572 | | /// or the end of the interval, whichever comes first. |
1573 | | /// The former is needed because it indicates the number of rate estimates we |
1574 | | /// will make. |
1575 | | /// The latter is needed because it indicates the number of times new bitrate |
1576 | | /// is added to the buffer. |
1577 | 0 | pub(crate) fn guess_frame_subtypes( |
1578 | 0 | &self, nframes: &mut [i32; FRAME_NSUBTYPES + 1], |
1579 | 0 | reservoir_frame_delay: i32, |
1580 | 0 | ) -> (i32, i32) { |
1581 | 0 | for fti in 0..=FRAME_NSUBTYPES { |
1582 | 0 | nframes[fti] = 0; |
1583 | 0 | } |
1584 | | |
1585 | | // Two-pass calls this function before receive_packet(), and in particular |
1586 | | // before the very first send_frame(), when the following maps are empty. |
1587 | | // In this case, return 0 as the default value. |
1588 | 0 | let mut prev_keyframe_input_frameno = *self |
1589 | 0 | .gop_input_frameno_start |
1590 | 0 | .get(&self.output_frameno) |
1591 | 0 | .unwrap_or_else(|| { |
1592 | 0 | assert!(self.output_frameno == 0); |
1593 | 0 | &0 |
1594 | 0 | }); Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::guess_frame_subtypes::{closure#0} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::guess_frame_subtypes::{closure#0} |
1595 | 0 | let mut prev_keyframe_output_frameno = *self |
1596 | 0 | .gop_output_frameno_start |
1597 | 0 | .get(&self.output_frameno) |
1598 | 0 | .unwrap_or_else(|| { |
1599 | 0 | assert!(self.output_frameno == 0); |
1600 | 0 | &0 |
1601 | 0 | }); Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::guess_frame_subtypes::{closure#1} Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::guess_frame_subtypes::{closure#1} |
1602 | 0 |
|
1603 | 0 | let mut prev_keyframe_ntus = 0; |
1604 | 0 | // Does not include SEF frames. |
1605 | 0 | let mut prev_keyframe_nframes = 0; |
1606 | 0 | let mut acc: [i32; FRAME_NSUBTYPES + 1] = [0; FRAME_NSUBTYPES + 1]; |
1607 | | // Updates the frame counts with the accumulated values when we hit a |
1608 | | // keyframe. |
1609 | 0 | fn collect_counts( |
1610 | 0 | nframes: &mut [i32; FRAME_NSUBTYPES + 1], |
1611 | 0 | acc: &mut [i32; FRAME_NSUBTYPES + 1], |
1612 | 0 | ) { |
1613 | 0 | for fti in 0..=FRAME_NSUBTYPES { |
1614 | 0 | nframes[fti] += acc[fti]; |
1615 | 0 | acc[fti] = 0; |
1616 | 0 | } |
1617 | 0 | acc[FRAME_SUBTYPE_I] += 1; |
1618 | 0 | } |
1619 | 0 | let mut output_frameno = self.output_frameno; |
1620 | 0 | let mut ntus = 0; |
1621 | 0 | // Does not include SEF frames. |
1622 | 0 | let mut nframes_total = 0; |
1623 | 0 | while ntus < reservoir_frame_delay { |
1624 | 0 | let output_frameno_in_gop = |
1625 | 0 | output_frameno - prev_keyframe_output_frameno; |
1626 | 0 | let is_kf = |
1627 | 0 | if let Some(Some(frame_data)) = self.frame_data.get(&output_frameno) { |
1628 | 0 | if frame_data.fi.frame_type == FrameType::KEY { |
1629 | 0 | prev_keyframe_input_frameno = frame_data.fi.input_frameno; |
1630 | 0 | // We do not currently use forward keyframes, so they should always |
1631 | 0 | // end the current TU (thus we always increment ntus below). |
1632 | 0 | debug_assert!(frame_data.fi.show_frame); |
1633 | 0 | true |
1634 | | } else { |
1635 | 0 | false |
1636 | | } |
1637 | | } else { |
1638 | | // It is possible to be invoked for the first time from twopass_out() |
1639 | | // before receive_packet() is called, in which case frame_invariants |
1640 | | // will not be populated. |
1641 | | // Force the first frame in each GOP to be a keyframe in that case. |
1642 | 0 | output_frameno_in_gop == 0 |
1643 | | }; |
1644 | 0 | if is_kf { |
1645 | 0 | collect_counts(nframes, &mut acc); |
1646 | 0 | prev_keyframe_output_frameno = output_frameno; |
1647 | 0 | prev_keyframe_ntus = ntus; |
1648 | 0 | prev_keyframe_nframes = nframes_total; |
1649 | 0 | output_frameno += 1; |
1650 | 0 | ntus += 1; |
1651 | 0 | nframes_total += 1; |
1652 | 0 | continue; |
1653 | 0 | } |
1654 | 0 | let idx_in_group_output = |
1655 | 0 | self.inter_cfg.get_idx_in_group_output(output_frameno_in_gop); |
1656 | 0 | let input_frameno = prev_keyframe_input_frameno |
1657 | 0 | + self |
1658 | 0 | .inter_cfg |
1659 | 0 | .get_order_hint(output_frameno_in_gop, idx_in_group_output) |
1660 | 0 | as u64; |
1661 | 0 | // For rate control purposes, ignore any limit on frame count that has |
1662 | 0 | // been set. |
1663 | 0 | // We pretend that we will keep encoding frames forever to prevent the |
1664 | 0 | // control loop from driving us into the rails as we come up against a |
1665 | 0 | // hard stop (with no more chance to correct outstanding errors). |
1666 | 0 | let next_keyframe_input_frameno = |
1667 | 0 | self.next_keyframe_input_frameno(prev_keyframe_input_frameno, true); |
1668 | 0 | // If we are re-ordering, we may skip some output frames in the final |
1669 | 0 | // re-order group of the GOP. |
1670 | 0 | if input_frameno >= next_keyframe_input_frameno { |
1671 | | // If we have encoded enough whole groups to reach the next keyframe, |
1672 | | // then start the next keyframe gop. |
1673 | 0 | if 1 |
1674 | 0 | + (output_frameno - prev_keyframe_output_frameno) |
1675 | 0 | / self.inter_cfg.group_output_len |
1676 | 0 | * self.inter_cfg.group_input_len |
1677 | 0 | >= next_keyframe_input_frameno - prev_keyframe_input_frameno |
1678 | 0 | { |
1679 | 0 | collect_counts(nframes, &mut acc); |
1680 | 0 | prev_keyframe_input_frameno = input_frameno; |
1681 | 0 | prev_keyframe_output_frameno = output_frameno; |
1682 | 0 | prev_keyframe_ntus = ntus; |
1683 | 0 | prev_keyframe_nframes = nframes_total; |
1684 | 0 | // We do not currently use forward keyframes, so they should always |
1685 | 0 | // end the current TU. |
1686 | 0 | output_frameno += 1; |
1687 | 0 | ntus += 1; |
1688 | 0 | } |
1689 | 0 | output_frameno += 1; |
1690 | 0 | continue; |
1691 | 0 | } |
1692 | 0 | if self.inter_cfg.get_show_existing_frame(idx_in_group_output) { |
1693 | 0 | acc[FRAME_SUBTYPE_SEF] += 1; |
1694 | 0 | } else { |
1695 | 0 | // TODO: Implement golden P-frames. |
1696 | 0 | let fti = FRAME_SUBTYPE_P |
1697 | 0 | + (self.inter_cfg.get_level(idx_in_group_output) as usize); |
1698 | 0 | acc[fti] += 1; |
1699 | 0 | nframes_total += 1; |
1700 | 0 | } |
1701 | 0 | if self.inter_cfg.get_show_frame(idx_in_group_output) { |
1702 | 0 | ntus += 1; |
1703 | 0 | } |
1704 | 0 | output_frameno += 1; |
1705 | | } |
1706 | 0 | if prev_keyframe_output_frameno <= self.output_frameno { |
1707 | | // If there were no keyframes at all, or only the first frame was a |
1708 | | // keyframe, the accumulators never flushed and still contain counts for |
1709 | | // the entire buffer. |
1710 | | // In both cases, we return these counts. |
1711 | 0 | collect_counts(nframes, &mut acc); |
1712 | 0 | (nframes_total, ntus) |
1713 | | } else { |
1714 | | // Otherwise, we discard what remains in the accumulators as they contain |
1715 | | // the counts from and past the last keyframe. |
1716 | 0 | (prev_keyframe_nframes, prev_keyframe_ntus) |
1717 | | } |
1718 | 0 | } Unexecuted instantiation: <rav1e::api::internal::ContextInner<u8>>::guess_frame_subtypes Unexecuted instantiation: <rav1e::api::internal::ContextInner<u16>>::guess_frame_subtypes |
1719 | | } |