1#![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#[derive(Debug, Clone, Copy)]
41pub struct InterConfig {
42 reorder: bool,
44 pub(crate) multiref: bool,
46 pub(crate) pyramid_depth: u64,
49 pub(crate) group_input_len: u64,
51 group_output_len: u64,
54 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 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 pub(crate) fn get_idx_in_group_output(
97 &self, output_frameno_in_gop: u64,
98 ) -> u64 {
99 debug_assert!(output_frameno_in_gop > 0);
102 (output_frameno_in_gop - 1) % self.group_output_len
103 }
104
105 pub(crate) fn get_order_hint(
109 &self, output_frameno_in_gop: u64, idx_in_group_output: u64,
110 ) -> u32 {
111 debug_assert!(output_frameno_in_gop > 0);
115 let group_idx = (output_frameno_in_gop - 1) / self.group_output_len;
118 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 (self.group_input_len * group_idx + offset) as u32
127 }
128
129 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 idx_in_group_output
136 } else {
137 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 if level == 0 {
150 (order_hint >> self.pyramid_depth) & 3
151 } else {
152 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 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#[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
224pub(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 pub(super) frame_q: FrameQueue<T>,
233 pub(super) frame_data: FrameDataQueue<T>,
235 keyframes: BTreeSet<u64>,
240 keyframes_forced: BTreeSet<u64>,
242 packet_data: Vec<u8>,
244 gop_output_frameno_start: BTreeMap<u64, u64>,
246 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 next_lookahead_frame: u64,
255 next_lookahead_output_frameno: u64,
257 opaque_q: BTreeMap<u64, Opaque>,
259 t35_q: BTreeMap<u64, Box<[T35]>>,
261}
262
263impl<T: Pixel> ContextInner<T> {
264 pub fn new(enc: &EncoderConfig) -> Self {
265 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 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 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 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 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 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 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 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 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 #[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 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 if self.output_frameno == output_frameno {
730 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 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 fi.rec_buffer = coded_data.lookahead_rec_buffer.clone();
761
762 fi.set_quantizers(&qps);
764
765 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 } else if fi.idx_in_group_output == 0 {
782 LAST2_FRAME
783 } else {
784 ALTREF_FRAME
785 };
786
787 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 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 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 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 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 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 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 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 ®ion_org,
965 ®ion_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 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 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 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 #[profiling::function]
1075 fn compute_block_importances(&mut self) {
1076 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 let output_framenos = self
1088 .get_rdo_lookahead_frames()
1089 .map(|(&output_frameno, _)| output_frameno)
1090 .collect::<Vec<_>>();
1091
1092 assert_eq!(output_framenos[0], self.output_frameno);
1094
1095 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 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 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 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 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 unique_indices.iter().for_each(|&(mv_index, rec_index)| {
1169 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 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 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 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 .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 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 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)?; 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 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 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 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 let mut prev_keyframe_nframes = 0;
1622 let mut acc: [i32; FRAME_NSUBTYPES + 1] = [0; FRAME_NSUBTYPES + 1];
1623 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 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 debug_assert!(frame_data.fi.show_frame);
1649 true
1650 } else {
1651 false
1652 }
1653 } else {
1654 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 let next_keyframe_input_frameno =
1683 self.next_keyframe_input_frameno(prev_keyframe_input_frameno, true);
1684 if input_frameno >= next_keyframe_input_frameno {
1687 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 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 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 collect_counts(nframes, &mut acc);
1728 (nframes_total, ntus)
1729 } else {
1730 (prev_keyframe_nframes, prev_keyframe_ntus)
1733 }
1734 }
1735}