Coverage Report

Created: 2025-07-11 07:25

/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
                &region_org,
949
0
                &region_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
}