Skip to main content

rav1e/api/
internal.rs

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