@@ -65,6 +65,7 @@ use std::io::prelude::*;
6565use std:: num:: NonZeroU8 ;
6666use std:: rc:: Rc ;
6767use std:: sync:: atomic:: Ordering :: Relaxed ;
68+ use std:: sync:: Mutex ;
6869use 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;
0 commit comments