Skip to main content

waycap_rs/encoders/
dma_buf_encoder.rs

1use crate::{
2    encoders::video::{PipewireSPA, StartVideoEncoder},
3    types::video_frame::RawVideoFrame,
4    VideoEncoder,
5};
6#[cfg(feature = "vaapi")]
7use crate::VaapiEncoder;
8#[cfg(feature = "nvidia")]
9use crate::NvencEncoder;
10#[cfg(all(feature = "vaapi", feature = "nvidia"))]
11use crate::types::error::WaycapError;
12#[cfg(all(feature = "vaapi", feature = "nvidia", feature = "vulkan"))]
13use crate::waycap_vulkan::{detect_gpu_vendor, GpuVendor};
14#[cfg(all(feature = "vaapi", feature = "nvidia", feature = "egl"))]
15use crate::waycap_egl::{detect_gpu_vendor, GpuVendor};
16use crossbeam::channel::Receiver;
17
18use crate::types::error::Result;
19
20/// "Encoder" which provides the raw DMA-Buf pointers directly.
21///
22/// Allows for using the image directly on the GPU, which makes it far more performant when, for example, trying to display it to a user.
23/// The implementations of [`crate::NvencEncoder`] and [`crate::VaapiEncoder`] show how a [`RawVideoFrame`] can be used.
24#[derive(Default)]
25pub struct DmaBufEncoder {
26    receiver: Option<Receiver<RawVideoFrame>>,
27}
28
29impl StartVideoEncoder for DmaBufEncoder {
30    fn start_processing(
31        capture: &mut crate::Capture<Self>,
32        input: Receiver<RawVideoFrame>,
33    ) -> Result<()> {
34        capture
35            .video_encoder
36            .as_mut()
37            .expect("start_processing should be called after Capture.video_encoder is set")
38            .lock()
39            .unwrap()
40            .receiver = Some(input);
41        Ok(())
42    }
43}
44impl VideoEncoder for DmaBufEncoder {
45    type Output = RawVideoFrame;
46
47    fn reset(&mut self) -> crate::types::error::Result<()> {
48        Ok(())
49    }
50
51    fn output(&mut self) -> Option<Receiver<Self::Output>> {
52        self.receiver.clone()
53    }
54
55    fn drop_processor(&mut self) {}
56
57    fn drain(&mut self) -> crate::types::error::Result<()> {
58        Ok(())
59    }
60
61    fn get_encoder(&self) -> &Option<ffmpeg_next::codec::encoder::Video> {
62        &None
63    }
64}
65
66impl PipewireSPA for DmaBufEncoder {
67    #[allow(unreachable_code)]
68    fn get_spa_definition() -> Result<pipewire::spa::pod::Object> {
69        #[cfg(all(feature = "vaapi", feature = "nvidia"))]
70        return match detect_gpu_vendor()? {
71            GpuVendor::NVIDIA => NvencEncoder::get_spa_definition(),
72            GpuVendor::AMD | GpuVendor::INTEL => VaapiEncoder::get_spa_definition(),
73            GpuVendor::UNKNOWN => Err(WaycapError::Init(
74                "Unknown/Unimplemented GPU vendor".to_string(),
75            )),
76        };
77        #[cfg(all(feature = "vaapi", not(feature = "nvidia")))]
78        return VaapiEncoder::get_spa_definition();
79        #[cfg(all(feature = "nvidia", not(feature = "vaapi")))]
80        return NvencEncoder::get_spa_definition();
81        unreachable!()
82    }
83}