1- use anyhow:: { Context , Result } ;
2- use image:: save_buffer;
3- use image:: ColorType :: Rgba8 ;
41use std:: borrow:: Borrow ;
5- use std:: ops:: { Add , Sub } ;
62use std:: sync:: mpsc:: Receiver ;
73use std:: sync:: { Arc , Mutex } ;
84use std:: time:: { Duration , Instant } ;
5+
6+ use anyhow:: { Context , Result } ;
7+ use image:: save_buffer;
8+ use image:: ColorType :: Rgba8 ;
9+ use smol:: stream:: block_on;
910use tempfile:: TempDir ;
1011
12+ use crate :: common:: { Frame , Recorder } ;
1113use crate :: utils:: { file_name_for, IMG_EXT } ;
12- use crate :: { ImageOnHeap , PlatformApi , WindowId } ;
14+ use crate :: { Image , PlatformApi , WindowId } ;
1315
1416/// captures screenshots as file on disk
1517/// collects also the timecodes when they have been captured
@@ -22,60 +24,49 @@ pub fn capture_thread(
2224 tempdir : Arc < Mutex < TempDir > > ,
2325 force_natural : bool ,
2426) -> Result < ( ) > {
25- let duration = Duration :: from_millis ( 250 ) ;
26- let start = Instant :: now ( ) ;
27- let mut idle_duration = Duration :: from_millis ( 0 ) ;
28- let mut last_frame: Option < ImageOnHeap > = None ;
27+ let recorder = Recorder :: new ( api, win_id, 4 ) ;
28+ let mut last_frame: Option < Frame > = None ;
2929 let mut identical_frames = 0 ;
30- let mut last_now = Instant :: now ( ) ;
31- loop {
32- // blocks for a timeout
33- if rx. recv_timeout ( duration) . is_ok ( ) {
34- break ;
35- }
36- let now = Instant :: now ( ) ;
37- let effective_now = now. sub ( idle_duration) ;
38- let tc = effective_now. saturating_duration_since ( start) . as_millis ( ) ;
39- let image = api. capture_window_screenshot ( win_id) ?;
30+ let start = Instant :: now ( ) ;
31+
32+ for frame in block_on ( recorder) {
4033 if !force_natural {
41- if last_frame. is_some ( )
42- && image
43- . samples
44- . as_slice ( )
45- . eq ( last_frame. as_ref ( ) . unwrap ( ) . samples . as_slice ( ) )
46- {
47- identical_frames += 1 ;
48- } else {
49- identical_frames = 0 ;
34+ let image: & Image = frame. as_ref ( ) ;
35+ if let Some ( last_image) = last_frame. as_ref ( ) {
36+ let last_image: & Image = last_image. as_ref ( ) ;
37+ if image. samples . as_slice ( ) . eq ( last_image. samples . as_slice ( ) ) {
38+ identical_frames += 1 ;
39+ } else {
40+ identical_frames = 0 ;
41+ }
5042 }
5143 }
5244
53- if identical_frames > 0 {
54- // let's track now the duration as idle
55- idle_duration = idle_duration. add ( now. duration_since ( last_now) ) ;
56- } else {
57- if let Err ( e) = save_frame ( & image, tc, tempdir. lock ( ) . unwrap ( ) . borrow ( ) , file_name_for)
58- {
59- eprintln ! ( "{}" , & e) ;
60- return Err ( e) ;
61- }
45+ if identical_frames == 0 {
46+ let tc: & Instant = frame. as_ref ( ) ;
47+ let tc = tc. duration_since ( start) . as_millis ( ) ;
48+ save_image ( & frame, tc, tempdir. lock ( ) . unwrap ( ) . borrow ( ) , file_name_for) ?;
6249 time_codes. lock ( ) . unwrap ( ) . push ( tc) ;
63- last_frame = Some ( image) ;
64- identical_frames = 0 ;
50+ last_frame = Some ( frame) ;
51+ }
52+
53+ // when there is a message we should just stop
54+ if rx. recv_timeout ( Duration :: from_millis ( 1 ) ) . is_ok ( ) {
55+ break ;
6556 }
66- last_now = now;
6757 }
6858
6959 Ok ( ( ) )
7060}
7161
7262/// saves a frame as a tga file
73- pub fn save_frame (
74- image : & ImageOnHeap ,
63+ pub fn save_image (
64+ image : impl AsRef < Image > ,
7565 time_code : u128 ,
7666 tempdir : & TempDir ,
7767 file_name_for : fn ( & u128 , & str ) -> String ,
7868) -> Result < ( ) > {
69+ let image = image. as_ref ( ) ;
7970 save_buffer (
8071 tempdir. path ( ) . join ( file_name_for ( & time_code, IMG_EXT ) ) ,
8172 & image. samples ,
0 commit comments