libobs_wrapper\encoders/
mod.rs1use crate::{
2 context::ObsContext,
3 enums::{ObsEncoderType, OsEnumType},
4 run_with_obs,
5 runtime::ObsRuntime,
6 utils::{ObsError, ENCODER_HIDE_FLAGS},
7};
8use std::{ffi::CStr, os::raw::c_char};
9
10pub mod audio;
11mod enums;
12mod property_helper;
13pub use property_helper::*;
14pub mod video;
15pub use enums::*;
16
17pub trait ObsContextEncoders {
18 fn best_video_encoder(&self) -> Result<ObsVideoEncoderBuilder, ObsError>;
19
20 fn best_audio_encoder(&self) -> Result<ObsAudioEncoderBuilder, ObsError>;
21
22 fn available_audio_encoders(&self) -> Result<Vec<ObsAudioEncoderBuilder>, ObsError>;
23
24 fn available_video_encoders(&self) -> Result<Vec<ObsVideoEncoderBuilder>, ObsError>;
25}
26
27fn get_encoders_raw(
28 encoder_type: ObsEncoderType,
29 runtime: &ObsRuntime,
30) -> Result<Vec<String>, ObsError> {
31 let type_primitive = encoder_type as OsEnumType;
32
33 run_with_obs!(runtime, move || {
34 let mut n = 0;
35 let mut encoders = Vec::new();
36
37 let mut ptr: *const c_char = unsafe { std::mem::zeroed() };
38 while unsafe { libobs::obs_enum_encoder_types(n, &mut ptr) } {
39 n += 1;
40 let cstring = unsafe { CStr::from_ptr(ptr) };
41 if let Ok(enc) = cstring.to_str() {
42 unsafe {
43 let is_hidden = libobs::obs_get_encoder_caps(ptr) & ENCODER_HIDE_FLAGS != 0;
44 if is_hidden || libobs::obs_get_encoder_type(ptr) != type_primitive {
45 continue;
46 }
47 }
48
49 log::debug!("Found encoder: {}", enc);
50 encoders.push(enc.into());
51 }
52 }
53
54 encoders.sort_unstable();
55 encoders
56 })
57}
58
59impl ObsContextEncoders for ObsContext {
60 fn best_video_encoder(&self) -> Result<ObsVideoEncoderBuilder, ObsError> {
61 let encoders = self.available_video_encoders()?;
62 encoders
63 .into_iter()
64 .next()
65 .ok_or(ObsError::NoAvailableEncoders)
66 }
67
68 fn best_audio_encoder(&self) -> Result<ObsAudioEncoderBuilder, ObsError> {
69 let encoders = self.available_audio_encoders()?;
70 encoders
71 .into_iter()
72 .next()
73 .ok_or(ObsError::NoAvailableEncoders)
74 }
75
76 fn available_audio_encoders(&self) -> Result<Vec<ObsAudioEncoderBuilder>, ObsError> {
77 Ok(get_encoders_raw(ObsEncoderType::Audio, &self.runtime)?
78 .into_iter()
79 .map(|x| ObsAudioEncoderBuilder::new(self.clone(), &x))
80 .collect::<Vec<_>>())
81 }
82
83 fn available_video_encoders(&self) -> Result<Vec<ObsVideoEncoderBuilder>, ObsError> {
84 Ok(get_encoders_raw(ObsEncoderType::Video, &self.runtime)?
85 .into_iter()
86 .map(|x| ObsVideoEncoderBuilder::new(self.clone(), &x))
87 .collect::<Vec<_>>())
88 }
89}