From 38f66df091e1d2b4ce8f7be84d40af73a98a0c78 Mon Sep 17 00:00:00 2001 From: Sangha Lee Date: Wed, 21 Dec 2022 04:12:34 +0900 Subject: [PATCH] implement RGB0 #2608 --- libs/scrap/src/common/wayland.rs | 6 +++++ libs/scrap/src/wayland/capturable.rs | 2 ++ libs/scrap/src/wayland/pipewire.rs | 33 ++++++++++++++++++---------- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/libs/scrap/src/common/wayland.rs b/libs/scrap/src/common/wayland.rs index 2593e56fe..6e89568e1 100644 --- a/libs/scrap/src/common/wayland.rs +++ b/libs/scrap/src/common/wayland.rs @@ -50,6 +50,12 @@ impl TraitCapturer for Capturer { } else { x })), + PixelProvider::RGB0(w, h, x) => Ok(Frame(if self.2 { + crate::common::rgba_to_i420(w as _, h as _, &x, &mut self.3); + &self.3[..] + } else { + x + })), PixelProvider::NONE => Err(std::io::ErrorKind::WouldBlock.into()), _ => Err(map_err("Invalid data")), } diff --git a/libs/scrap/src/wayland/capturable.rs b/libs/scrap/src/wayland/capturable.rs index 05a5ec71d..61f80ecbf 100644 --- a/libs/scrap/src/wayland/capturable.rs +++ b/libs/scrap/src/wayland/capturable.rs @@ -4,6 +4,7 @@ use std::error::Error; pub enum PixelProvider<'a> { // 8 bits per color RGB(usize, usize, &'a [u8]), + RGB0(usize, usize, &'a [u8]), BGR0(usize, usize, &'a [u8]), // width, height, stride BGR0S(usize, usize, usize, &'a [u8]), @@ -14,6 +15,7 @@ impl<'a> PixelProvider<'a> { pub fn size(&self) -> (usize, usize) { match self { PixelProvider::RGB(w, h, _) => (*w, *h), + PixelProvider::RGB0(w, h, _) => (*w, *h), PixelProvider::BGR0(w, h, _) => (*w, *h), PixelProvider::BGR0S(w, h, _, _) => (*w, *h), PixelProvider::NONE => (0, 0), diff --git a/libs/scrap/src/wayland/pipewire.rs b/libs/scrap/src/wayland/pipewire.rs index d43a1b278..8e3848862 100644 --- a/libs/scrap/src/wayland/pipewire.rs +++ b/libs/scrap/src/wayland/pipewire.rs @@ -117,6 +117,7 @@ impl Capturable for PipeWireCapturable { pub struct PipeWireRecorder { buffer: Option>, buffer_cropped: Vec, + pix_fmt: String, is_cropped: bool, pipeline: gst::Pipeline, appsink: AppSink, @@ -144,19 +145,27 @@ impl PipeWireRecorder { pipeline.add_many(&[&src, &sink])?; src.link(&sink)?; + let appsink = sink .dynamic_cast::() .map_err(|_| GStreamerError("Sink element is expected to be an appsink!".into()))?; - appsink.set_caps(Some(&gst::Caps::new_simple( + let mut caps = gst::Caps::new_empty(); + caps.merge_structure(gst::structure::Structure::new( "video/x-raw", &[("format", &"BGRx")], - ))); + )); + caps.merge_structure(gst::structure::Structure::new( + "video/x-raw", + &[("format", &"RGBx")], + )); + appsink.set_caps(Some(&caps)); pipeline.set_state(gst::State::Playing)?; Ok(Self { pipeline, appsink, buffer: None, + pix_fmt: "".into(), width: 0, height: 0, buffer_cropped: vec![], @@ -179,6 +188,7 @@ impl Recorder for PipeWireRecorder { .ok_or("Failed to get structure")?; let w: i32 = cap.value("width")?.get()?; let h: i32 = cap.value("height")?.get()?; + self.pix_fmt = cap.value("format")?.get()?; let w = w as usize; let h = h as usize; let buf = sample @@ -241,15 +251,16 @@ impl Recorder for PipeWireRecorder { if self.buffer.is_none() { return Err(Box::new(GStreamerError("No buffer available!".into()))); } - Ok(PixelProvider::BGR0( - self.width, - self.height, - if self.is_cropped { - self.buffer_cropped.as_slice() - } else { - self.buffer.as_ref().unwrap().as_slice() - }, - )) + let buf = if self.is_cropped { + self.buffer_cropped.as_slice() + } else { + self.buffer.as_ref().unwrap().as_slice() + }; + match self.pix_fmt.as_str() { + "BGRx" => Ok(PixelProvider::BGR0(self.width, self.height, buf)), + "RGBx" => Ok(PixelProvider::RGB0(self.width, self.height, buf)), + _ => unreachable!(), + } } }