libobs_wrapper\data/
video.rs

1use std::ptr;
2
3use display_info::DisplayInfo;
4use libobs::obs_video_info;
5
6use crate::{enums::{ObsColorspace, ObsGraphicsModule, ObsScaleType, ObsVideoFormat, ObsVideoRange, OsEnumType}, unsafe_send::SendableComp, utils::ObsString};
7
8/// A wrapper for `obs_video_info`, which is used
9/// to pass information to libobs for the new OBS
10/// video context after resetting the old OBS
11/// video context.
12#[derive(Clone, Debug, PartialEq, Eq)]
13pub struct ObsVideoInfo {
14    ovi: SendableComp<obs_video_info>,
15    // False positive. This is necessary to ensure
16    // that the graphics module string in the
17    // `obs_video_info` struct does not free.
18    #[allow(dead_code)]
19    graphics_module: ObsString,
20}
21
22impl ObsVideoInfo {
23    /// Creates a new `ObsVideoInfo`.
24    ///
25    /// Note that this function is not meant to
26    /// be used externally. The recommended,
27    /// supported way to build new `ObsVideoInfo`
28    /// structs is through `ObsVideoInfoBuilder`.
29    pub fn new(ovi: obs_video_info, graphics_module: ObsString) -> Self {
30        Self {
31            ovi: SendableComp(ovi),
32            graphics_module,
33        }
34    }
35
36    /// Returns an `ObsVideoInfo` pointer.
37    pub fn as_ptr(&mut self) -> *mut obs_video_info {
38        ptr::addr_of_mut!(self.ovi.0)
39    }
40
41    pub fn graphics_module(&self) -> &ObsString {
42        &self.graphics_module
43    }
44}
45
46impl Default for ObsVideoInfo {
47    fn default() -> Self {
48        ObsVideoInfoBuilder::new().build()
49    }
50}
51
52/// A structure intended to help make
53/// creating new `ObsVideoInfo` structs
54/// easier for resetting the OBS video
55/// context.
56#[derive(Clone, Debug)]
57pub struct ObsVideoInfoBuilder {
58    adapter: u32,
59    graphics_module: ObsGraphicsModule,
60    fps_num: u32,
61    fps_den: u32,
62    base_width: u32,
63    base_height: u32,
64    output_width: u32,
65    output_height: u32,
66    output_format: ObsVideoFormat,
67    gpu_conversion: bool,
68    colorspace: ObsColorspace,
69    range: ObsVideoRange,
70    scale_type: ObsScaleType,
71}
72
73impl ObsVideoInfoBuilder {
74    /// Creates a new `ObsVideoInfoBuilder`
75    /// for creating new `ObsVideoInfo` to
76    /// pass to the video context reset
77    /// function.
78    ///
79    /// This function comes with
80    /// sensible default values and chooses
81    /// the backend depending on which
82    /// if the OS supports DX11 (Windows)
83    /// or not (OpenGL on MacOS and Unix).
84    pub fn new() -> Self {
85        let display_infos = DisplayInfo::all().unwrap();
86        let (mut width, mut height) = (1920, 1080);
87        for display_info in display_infos {
88            if display_info.is_primary {
89                width = display_info.width;
90                height = display_info.height;
91                break;
92            }
93        }
94
95        Self {
96            adapter: 0,
97            #[cfg(target_family = "unix")]
98            graphics_module: ObsGraphicsModule::OpenGL,
99            #[cfg(target_family = "windows")]
100            graphics_module: ObsGraphicsModule::DirectX11,
101            fps_num: 30,
102            fps_den: 1,
103            base_width: width,
104            base_height: height,
105            output_width: width,
106            output_height: height,
107            output_format: ObsVideoFormat::NV12,
108            gpu_conversion: true,
109            colorspace: ObsColorspace::CS709,
110            range: ObsVideoRange::Default,
111            scale_type: ObsScaleType::Lanczos,
112        }
113    }
114
115    /// Consumes the `ObsVideoInfoBuilder`
116    /// to create an `ObsVideoInfo`.
117    pub fn build(self) -> ObsVideoInfo {
118        let graphics_mod_str = match self.graphics_module {
119            ObsGraphicsModule::OpenGL => ObsString::new("libobs-opengl"),
120            ObsGraphicsModule::DirectX11 => ObsString::new("libobs-d3d11"),
121        };
122
123        let ovi = obs_video_info {
124            adapter: self.adapter,
125            graphics_module: graphics_mod_str.as_ptr().0,
126            fps_num: self.fps_num,
127            fps_den: self.fps_den,
128            base_width: self.base_width,
129            base_height: self.base_height,
130            output_width: self.output_width,
131            output_height: self.output_height,
132            output_format: self.output_format as OsEnumType,
133            gpu_conversion: self.gpu_conversion,
134            colorspace: self.colorspace as OsEnumType,
135            range: self.range as OsEnumType,
136            scale_type: self.scale_type as OsEnumType,
137        };
138
139        drop(self);
140
141        ObsVideoInfo {
142            ovi: SendableComp(ovi),
143            graphics_module: graphics_mod_str,
144        }
145    }
146
147    /// Sets the GPU adapter device
148    /// that the video output is coming
149    /// from.
150    pub fn adapter(mut self, value: u32) -> Self {
151        self.adapter = value;
152        self
153    }
154
155    /// Sets the graphics backend
156    /// that libobs uses to record.
157    pub fn graphics_module(mut self, value: ObsGraphicsModule) -> Self {
158        self.graphics_module = value;
159        self
160    }
161
162    /// Sets the framerate of the
163    /// output video. Note that this
164    /// value may not reflect the
165    /// final framerate if `fps_den`
166    /// is not equal to 1.
167    pub fn fps_num(mut self, value: u32) -> Self {
168        self.fps_num = value;
169        self
170    }
171
172    /// Divides the FPS numerator to
173    /// allow for fractional FPS
174    /// counts on output.
175    pub fn fps_den(mut self, value: u32) -> Self {
176        self.fps_den = value;
177        self
178    }
179
180    /// Sets the width of the screen
181    /// being recorded.
182    pub fn base_width(mut self, value: u32) -> Self {
183        self.base_width = value;
184        self
185    }
186
187    /// Sets the height of the screen
188    /// being recorded.
189    pub fn base_height(mut self, value: u32) -> Self {
190        self.base_height = value;
191        self
192    }
193
194    /// Sets the width of the video
195    /// output.
196    pub fn output_width(mut self, value: u32) -> Self {
197        self.output_width = value;
198        self
199    }
200
201    /// Sets the height of the video
202    /// output.
203    pub fn output_height(mut self, value: u32) -> Self {
204        self.output_height = value;
205        self
206    }
207
208    /// Sets the format in which the
209    /// video will be output.
210    pub fn output_format(mut self, value: ObsVideoFormat) -> Self {
211        self.output_format = value;
212        self
213    }
214
215    /// Sets whether the GPU will handle
216    /// conversion in the video.
217    pub fn gpu_conversion(mut self, value: bool) -> Self {
218        self.gpu_conversion = value;
219        self
220    }
221
222    /// Sets the video colorspace.
223    pub fn colorspace(mut self, value: ObsColorspace) -> Self {
224        self.colorspace = value;
225        self
226    }
227
228    /// Sets the video range.
229    pub fn range(mut self, value: ObsVideoRange) -> Self {
230        self.range = value;
231        self
232    }
233
234    /// Sets the video scaling type.
235    pub fn scale_type(mut self, value: ObsScaleType) -> Self {
236        self.scale_type = value;
237        self
238    }
239}
240
241impl Default for ObsVideoInfoBuilder {
242    fn default() -> Self {
243        Self::new()
244    }
245}