decklink/device/output/
mod.rs1mod audio;
2mod device;
3mod enums;
4mod video;
5mod video_callback;
6
7use crate::device::output::device::DecklinkOutputDevicePtr;
8use crate::device::output::video_callback::register_callback;
9use crate::display_mode::{
10 iterate_display_modes, wrap_display_mode, DecklinkDisplayMode, DecklinkDisplayModeId,
11};
12use crate::frame::DecklinkPixelFormat;
13use crate::{sdk, SdkError};
14use num_traits::FromPrimitive;
15use std::ptr::null_mut;
16use std::rc::Rc;
17use std::sync::atomic::{AtomicBool, Ordering};
18use std::sync::Arc;
19
20pub use crate::device::output::audio::DecklinkOutputDeviceAudio;
21pub use crate::device::output::enums::*;
22pub use crate::device::output::video::{
23 DecklinkOutputDeviceVideoScheduled, DecklinkOutputDeviceVideoSync,
24};
25pub use crate::device::output::video_callback::DeckLinkVideoOutputCallback;
26use crate::device::{DecklinkDeviceDisplayModes, DecklinkDisplayModeSupport};
27
28use self::video::DecklinkOutputDeviceVideoImpl;
29
30pub struct DecklinkOutputDevice {
31 ptr: Arc<DecklinkOutputDevicePtr>,
32}
33
34impl DecklinkDeviceDisplayModes<enums::DecklinkVideoOutputFlags> for DecklinkOutputDevice {
35 fn does_support_video_mode(
36 &self,
37 mode: DecklinkDisplayModeId,
38 pixel_format: DecklinkPixelFormat,
39 flags: enums::DecklinkVideoOutputFlags,
40 ) -> Result<(DecklinkDisplayModeSupport, Option<DecklinkDisplayMode>), SdkError> {
41 let mut supported = sdk::_DecklinkDisplayModeSupport_decklinkDisplayModeNotSupported;
42 let mut display_mode = null_mut();
43 let result = unsafe {
44 sdk::cdecklink_output_does_support_video_mode(
45 self.ptr.dev,
46 mode as u32,
47 pixel_format as u32,
48 flags.bits(),
49 &mut supported,
50 &mut display_mode,
51 )
52 };
53 SdkError::result_or_else(result, move || {
54 let supported2 = DecklinkDisplayModeSupport::from_u32(supported)
55 .unwrap_or(DecklinkDisplayModeSupport::NotSupported);
56 if display_mode.is_null() || supported2 == DecklinkDisplayModeSupport::NotSupported {
57 (DecklinkDisplayModeSupport::NotSupported, None)
58 } else {
59 unsafe { (supported2, Some(wrap_display_mode(display_mode))) }
60 }
61 })
62 }
63
64 fn display_modes(&self) -> Result<Vec<DecklinkDisplayMode>, SdkError> {
65 unsafe {
66 let mut it = null_mut();
67 let ok = sdk::cdecklink_output_get_display_mode_iterator(self.ptr.dev, &mut it);
68 if SdkError::is_ok(ok) {
69 let v = iterate_display_modes(it);
70 sdk::cdecklink_display_mode_iterator_release(it);
71 v
72 } else {
73 Err(SdkError::from(ok))
74 }
75 }
76 }
77}
78impl DecklinkOutputDevice {
80 pub(crate) fn from(ptr: *mut crate::sdk::cdecklink_output_t) -> DecklinkOutputDevice {
81 DecklinkOutputDevice {
82 ptr: Arc::new(DecklinkOutputDevicePtr {
83 dev: ptr,
84 video_active: Rc::new(AtomicBool::new(false)),
85 audio_active: Rc::new(AtomicBool::new(false)),
86 }),
87 }
88 }
89
90 unsafe fn enable_video_output_inner(
93 &self,
94 mode: DecklinkDisplayModeId,
95 flags: enums::DecklinkVideoOutputFlags,
96 ) -> i32 {
97 if self.ptr.video_active.swap(true, Ordering::Relaxed) {
98 SdkError::ACCESSDENIED as i32
100 } else {
101 sdk::cdecklink_output_enable_video_output(self.ptr.dev, mode as u32, flags.bits())
102 }
103 }
104
105 pub fn is_scheduled_playback_running(&self) -> Result<bool, SdkError> {
106 unsafe {
107 let mut running = false;
108 let result =
109 sdk::cdecklink_output_is_scheduled_playback_running(self.ptr.dev, &mut running);
110 SdkError::result_or(result, running)
111 }
112 }
113
114 pub fn enable_video_output_scheduled(
115 &self,
116 mode: DecklinkDisplayModeId,
117 flags: enums::DecklinkVideoOutputFlags,
118 timescale: i64,
119 ) -> Result<Box<dyn DecklinkOutputDeviceVideoScheduled>, SdkError> {
120 match register_callback(&self.ptr) {
121 Err(e) => Err(e),
123 Ok(wrapper) => {
124 let result = unsafe { self.enable_video_output_inner(mode, flags) };
126 SdkError::result_or_else(result, || {
127 let r: Box<dyn DecklinkOutputDeviceVideoScheduled> = Box::new(
128 DecklinkOutputDeviceVideoImpl::from(&self.ptr, wrapper, timescale),
129 );
130 r
131 })
132 }
133 }
134 }
135 pub fn enable_video_output_sync(
136 &self,
137 mode: DecklinkDisplayModeId,
138 flags: enums::DecklinkVideoOutputFlags,
139 ) -> Result<Box<dyn DecklinkOutputDeviceVideoSync>, SdkError> {
140 let result = unsafe { self.enable_video_output_inner(mode, flags) };
141 SdkError::result_or_else(result, || {
142 let r: Box<dyn DecklinkOutputDeviceVideoSync> = Box::new(
143 DecklinkOutputDeviceVideoImpl::from(&self.ptr, null_mut(), 1000),
144 );
145 r
146 })
147 }
148
149 pub fn enable_audio_output(
152 &self,
153 sample_rate: enums::DecklinkAudioSampleRate,
154 sample_type: enums::DecklinkAudioSampleType,
155 channels: u32,
156 stream_type: enums::DecklinkAudioOutputStreamType,
157 ) -> Result<DecklinkOutputDeviceAudio, SdkError> {
158 if self.ptr.audio_active.swap(true, Ordering::Relaxed) {
159 Err(SdkError::ACCESSDENIED)
161 } else {
162 unsafe {
163 let result = sdk::cdecklink_output_enable_audio_output(
164 self.ptr.dev,
165 sample_rate as u32,
166 sample_type as u32,
167 channels,
168 stream_type as u32,
169 );
170 SdkError::result_or_else(result, || DecklinkOutputDeviceAudio::from(&self.ptr))
171 }
172 }
173 }
174}