Return PNG encoded screen preview
(&self)
| 120 | |
| 121 | /// Return PNG encoded screen preview |
| 122 | pub fn preview(&self) -> anyhow::Result<Vec<u8>> { |
| 123 | use gst::prelude::*; |
| 124 | use scrap::Capturer; |
| 125 | |
| 126 | let mut capturer = Capturer::new(self.display.clone_device()).unwrap(); |
| 127 | |
| 128 | let width; |
| 129 | let height; |
| 130 | let data; |
| 131 | |
| 132 | loop { |
| 133 | let frame = match capturer.frame(std::time::Duration::ZERO) { |
| 134 | Ok(frame) => frame, |
| 135 | Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => continue, |
| 136 | Err(err) if err.kind() == std::io::ErrorKind::InvalidData => { |
| 137 | eprintln!("Received invalid data, skipping"); |
| 138 | continue |
| 139 | }, |
| 140 | Err(err) => panic!("{err}"), |
| 141 | }; |
| 142 | |
| 143 | let scrap::Frame::PixelBuffer(pixel_buffer) = frame else { |
| 144 | eprintln!("Received frame is not PixelBuffer, skipping"); |
| 145 | continue |
| 146 | }; |
| 147 | |
| 148 | width = pixel_buffer.width(); |
| 149 | height = pixel_buffer.height(); |
| 150 | data = pixel_buffer.data().to_vec(); |
| 151 | |
| 152 | break; |
| 153 | }; |
| 154 | |
| 155 | let pipeline = |
| 156 | gst::parse::launch("appsrc name=input ! videoconvert ! pngenc ! appsink name=output").unwrap() |
| 157 | .dynamic_cast::<gst::Pipeline>().unwrap(); |
| 158 | |
| 159 | pipeline.by_name("input").unwrap().dynamic_cast::<gst_app::AppSrc>().unwrap() |
| 160 | .set_callbacks(gst_app::AppSrcCallbacks::builder() |
| 161 | .need_data(move |source, _| { |
| 162 | let caps = gst::Caps::builder("video/x-raw") |
| 163 | .field("format", "BGRx") |
| 164 | .field("width", width as i32) |
| 165 | .field("height", height as i32) |
| 166 | .build(); |
| 167 | |
| 168 | source.set_caps(Some(&caps)); |
| 169 | |
| 170 | let buffer = gst::Buffer::from_slice(data.clone()); |
| 171 | |
| 172 | let _ = source.push_buffer(buffer); |
| 173 | |
| 174 | source.end_of_stream().unwrap(); |
| 175 | }).build()); |
| 176 | |
| 177 | let preview = Arc::new(Mutex::new(None)); |
| 178 | |
| 179 | pipeline.by_name("output").unwrap().dynamic_cast::<gst_app::AppSink>().unwrap() |
no test coverage detected