scrap
scrap copied to clipboard
Intermitent blank output when using '#![windows_subsystem = "windows"]' on Windows 10
Was just testing this rad library with some sample code and noticed it's ultra reliable when called in a standard console mode, but I wanted the console not in the screenshot so tried wrapping it #![windows_subsystem = "windows"], now 4 out of 5 attempts to call this produces a blank output.
Testing on Windows 10.
`//#![windows_subsystem = "windows"]
extern crate repng; extern crate scrap;
use scrap::{Capturer, Display}; use std::io::ErrorKind::WouldBlock; use std::fs::File; use std::thread; use std::time::Duration;
fn main() { let one_second = Duration::new(1, 0); let one_frame = one_second / 60;
let display = Display::primary().expect("Couldn't find primary display.");
let mut capturer = Capturer::new(display).expect("Couldn't begin capture.");
let (width, height) = (capturer.width(), capturer.height());
loop {
// Wait until there's a frame.
let buffer = match capturer.frame() {
Ok(buffer) => buffer,
Err(error) => {
if error.kind() == WouldBlock {
// Keep spinning.
// println!("Waiting...");
thread::sleep(one_frame);
continue;
} else {
panic!("Error: {}", error);
}
}
};
// println!("Captured! Saving...");
// Flip the ARGB image into a BGRA image.
let mut bitflipped = Vec::with_capacity(width * height * 4);
let stride = buffer.len() / height;
for y in 0..height {
for x in 0..width {
let i = stride * y + 4 * x;
bitflipped.extend_from_slice(&[
buffer[i + 2],
buffer[i + 1],
buffer[i],
255,
]);
}
}
// Save the image.
repng::encode(
File::create("screenshot.png").unwrap(),
width as u32,
height as u32,
&bitflipped,
).unwrap();
// println!("Image saved to `screenshot.png`.");
break;
}
}`
I too experienced this on Windows; a workaround I used was to wrap the let buffer = match capturer.frame
in a loop, sleep + continue'ing until I got a non-black frame, at which point I returned out of the loop.
if !buffer.to_vec().iter().any(|&x| x != 0) {
thread::sleep(Duration::new(0, 1)); // sleep 1ms
continue;
}
return buffer;
I recall when this happened (which seemed pretty inconsistent), I'd need to wait 5-15ms before getting a non-solid-black buffer, which sounded suspiciously like I had to wait for the "next frame" @ 60hz.
Thanks for the workaround, it's helped and gives a consistent output.
Odd the output is blank still somtimes to need this as I was already waiting on match error for another frame.
@McSpidey @Nebual any further progress on figuring this out? I am experiencing this and it occurs if I shake the mouse a bunch, every frame is all 0s and WouldBlock does not show, so it seems to be interrupt-related.
The section here where Buffer length: is printed out 3 times in a row (without blocking for the next frame) occurred while the mouse was being shaken. When the mouse stopped moving it resumed normal behavior.
This behavior is also reproducible only when the mouse is moved on the screen being captured, if the mouse is moving on the other screen, no blank frames are captured.
Sorry, I haven't revisited this. That's a good find re mouse interrupts though.
Hi, I am currently facing this issue working with the example code. This is what I have currently.
let mut buffer = None;
let display = Display::primary().expect("Couldn't find primary display.");
let mut capturer = Capturer::new(display).expect("Couldn't begin capture.");
let (mut w, mut h);
while buffer.is_none() {
(w, h) = (&mut capturer.width(), &mut capturer.height());
// Wait until there's a frame.
match &mut capturer.frame() {
Ok(buf) => {
buffer = Some(buf);
break;
}
Err(error) => {
if error.kind() == WouldBlock {
// Keep spinning.
thread::sleep(one_frame);
continue;
} else {
panic!("Error: {}", error);
}
}
};
}
//further computation
The blank output occurs for me whenever the WouldBlock error is returned, so I assume this is a problem with calling capture.frame() inside a loop. Trying to learn more about lifetimes to remedy this, any help would be appreciated .