Skip to content

Commit 936469b

Browse files
committed
Log invalid pts and frame numbers
1 parent c7df9b0 commit 936469b

File tree

3 files changed

+61
-8
lines changed

3 files changed

+61
-8
lines changed

src/collector.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ pub(crate) struct InputFrameResized {
3535
pub frame_blurred: ImgVec<RGB8>,
3636
/// Time in seconds when to display the frame. First frame should start at 0.
3737
pub presentation_timestamp: f64,
38+
39+
/// Debugging bad inputs
40+
pub original_index: usize,
3841
}
3942

4043
/// Collect frames that will be encoded

src/lib.rs

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ use std::io::prelude::*;
6565
use std::num::NonZeroU8;
6666
use std::rc::Rc;
6767
use std::sync::atomic::Ordering::Relaxed;
68+
use std::sync::Mutex;
6869
use std::thread;
6970

7071
/// Number of repetitions
@@ -515,7 +516,7 @@ impl Writer {
515516
}
516517

517518
#[inline(never)]
518-
fn write_frames(&self, write_queue: Receiver<FrameMessage>, writer: &mut dyn Write, reporter: &mut dyn ProgressReporter) -> CatResult<()> {
519+
fn write_frames(&self, write_queue: Receiver<FrameMessage>, writer: &mut dyn Write, reporter: &Mutex<Option<&mut dyn ProgressReporter>>) -> CatResult<()> {
519520
let (lzw_queue, lzw_recv) = ordqueue_new(2);
520521
minipool::new_scope((if self.settings.s.fast || self.settings.gifsicle_loss() > 0 { 3 } else { 1 }).try_into().unwrap(), "lzw", move || {
521522
let mut pts_in_delay_units = 0_u64;
@@ -534,12 +535,15 @@ impl Writer {
534535

535536
enc.write_frame(frame, delay, screen_width, screen_height, &self.settings.s)?;
536537

538+
let mut reporter_lock = reporter.lock().map_err(|_| Error::ThreadSend)?;
539+
let reporter = reporter_lock.as_deref_mut().ok_or(Error::Aborted)?;
537540
reporter.written_bytes(written.get());
538541

539542
// loop to report skipped frames too
540543
while n_done < ordinal_frame_number {
541544
n_done += 1;
542545
if !reporter.increase() {
546+
*reporter_lock = None; // prevent further abort-caused errors from being logged
543547
return Err(Error::Aborted);
544548
}
545549
}
@@ -549,9 +553,9 @@ impl Writer {
549553
} else {
550554
Ok(())
551555
}
552-
}, move |abort| {
556+
}, move |failed| {
553557
for FrameMessage {frame, frame_index, ordinal_frame_number, end_pts, screen_width, screen_height } in write_queue {
554-
if abort.load(Relaxed) {
558+
if failed.load(Relaxed) {
555559
return Err(Error::Aborted);
556560
}
557561

@@ -575,14 +579,16 @@ impl Writer {
575579

576580
#[inline(never)]
577581
fn write_inner(&self, decode_queue_recv: Receiver<InputFrame>, writer: &mut dyn Write, reporter: &mut dyn ProgressReporter) -> CatResult<()> {
582+
let reporter = &Mutex::new(Some(reporter));
583+
578584
thread::scope(|s| {
579585
let (diff_queue, diff_queue_recv) = ordqueue_new(0);
580586
let resize_thread = thread::Builder::new().name("resize".into()).spawn_scoped(s, move || {
581587
self.make_resize(decode_queue_recv, diff_queue)
582588
})?;
583589
let (quant_queue, quant_queue_recv) = crossbeam_channel::bounded(0);
584590
let diff_thread = thread::Builder::new().name("diff".into()).spawn_scoped(s, move || {
585-
self.make_diffs(diff_queue_recv, quant_queue)
591+
self.make_diffs(diff_queue_recv, quant_queue, reporter)
586592
})?;
587593
let (remap_queue, remap_queue_recv) = ordqueue_new(0);
588594
let quant_thread = thread::Builder::new().name("quant".into()).spawn_scoped(s, move || {
@@ -628,6 +634,7 @@ impl Writer {
628634
let resized = resized_binary_alpha(image, self.settings.s.width, self.settings.s.height, self.settings.matte)?;
629635
let frame_blurred = if self.settings.extra_effort { smart_blur(resized.as_ref()) } else { less_smart_blur(resized.as_ref()) };
630636
diff_queue.send(frame.frame_index, InputFrameResized {
637+
original_index: frame.frame_index,
631638
frame: resized,
632639
frame_blurred,
633640
presentation_timestamp: frame.presentation_timestamp,
@@ -638,7 +645,7 @@ impl Writer {
638645
}
639646

640647
/// Find differences between frames, and compute importance maps
641-
fn make_diffs(&self, mut inputs: OrdQueueIter<InputFrameResized>, diffs: Sender<DiffMessage>) -> CatResult<()> {
648+
fn make_diffs(&self, mut inputs: OrdQueueIter<InputFrameResized>, diffs: Sender<DiffMessage>, reporter: &Mutex<Option<&mut dyn ProgressReporter>>) -> CatResult<()> {
642649
let first_frame = inputs.next().ok_or(Error::NoFrames)?;
643650

644651
let mut last_frame_duration = if first_frame.presentation_timestamp > 1. / 100. {
@@ -652,6 +659,7 @@ impl Writer {
652659
let mut denoiser = Denoiser::new(first_frame.frame.width(), first_frame.frame.height(), self.settings.motion_quality)?;
653660

654661
let mut ordinal_frame_number = 0;
662+
let mut next_original_index_expected = 0;
655663
let mut last_frame_pts = 0.;
656664
let mut next_frame = Some(first_frame);
657665
loop {
@@ -664,11 +672,23 @@ impl Writer {
664672

665673
////////////////////// Feed denoiser: /////////////////////
666674

667-
if let Some(InputFrameResized { frame, frame_blurred, presentation_timestamp: raw_pts }) = next_frame {
675+
if let Some(InputFrameResized { frame, frame_blurred, original_index, presentation_timestamp: raw_pts }) = next_frame {
676+
if original_index != next_original_index_expected {
677+
if let Some(r) = &mut *reporter.lock().map_err(|_| Error::ThreadSend)? {
678+
r.error(format!("expected frame_number {next_original_index_expected}, got {original_index}"));
679+
}
680+
}
681+
next_original_index_expected = original_index + 1;
668682
ordinal_frame_number += 1;
669683

670-
let pts = raw_pts - last_frame_duration.shift_every_pts_by();
671-
if let LastFrameDuration::FrameRate(duration) = &mut last_frame_duration {
684+
let mut pts = raw_pts - last_frame_duration.shift_every_pts_by();
685+
if pts < last_frame_pts {
686+
if let Some(r) = &mut *reporter.lock().map_err(|_| Error::ThreadSend)? {
687+
r.error(format!("expected frame_number {original_index} to have pts > {last_frame_pts:0.3}, got {raw_pts:0.3}"));
688+
}
689+
pts = last_frame_pts;
690+
}
691+
else if let LastFrameDuration::FrameRate(duration) = &mut last_frame_duration {
672692
*duration = pts - last_frame_pts;
673693
}
674694
last_frame_pts = pts;

tests/tests.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,36 @@ fn all_dupe_frames() {
8282
assert_eq!(delays, [130]);
8383
}
8484

85+
#[test]
86+
fn errors() {
87+
let (c, w) = new(Settings::default()).unwrap();
88+
89+
struct Errors(Vec<String>);
90+
impl progress::ProgressReporter for Errors {
91+
fn increase(&mut self) -> bool { true }
92+
fn error(&mut self, msg: String) {
93+
self.0.push(msg);
94+
}
95+
}
96+
97+
let t = std::thread::spawn(move || {
98+
c.add_frame_png_file(1, frame_filename(1), 0.0).unwrap();
99+
c.add_frame_png_file(1, frame_filename(1), 2.0).unwrap();
100+
c.add_frame_png_file(2, frame_filename(1), 1.1).unwrap();
101+
});
102+
103+
104+
let mut out = Vec::new();
105+
let mut errs = Errors(vec![]);
106+
w.write(&mut out, &mut errs).unwrap();
107+
t.join().unwrap();
108+
109+
errs.0.sort(); // order may change?
110+
assert_eq!("expected frame_number 0, got 1", errs.0[0]);
111+
assert_eq!("expected frame_number 2 to have pts > 2.000, got 1.100", errs.0[1]);
112+
assert_eq!("expected frame_number 2, got 1", errs.0[2]);
113+
}
114+
85115
#[test]
86116
fn all_but_one_dupe_frames() {
87117
let (c, w) = new(Settings::default()).unwrap();

0 commit comments

Comments
 (0)