Skip to main content

video_toolbox/
session.rs

1use std::{
2    mem,
3    ptr::{addr_of_mut, null_mut},
4};
5
6use core_foundation::{
7    base::{kCFAllocatorDefault, CFAllocatorRef, CFGetTypeID, CFRetain, CFType, CFTypeID, CFTypeRef, OSStatus, TCFType, TCFTypeRef},
8    declare_TCFType,
9    dictionary::{CFDictionary, CFDictionaryRef},
10    impl_CFTypeDescription,
11    string::{CFString, CFStringRef},
12};
13use libc::c_void;
14
15pub type VTSessionRef = CFTypeRef;
16
17pub type FrameDelay = i32;
18
19pub const kVTUnlimitedFrameDelayCount: FrameDelay = -1;
20
21extern "C" {
22    pub fn VTSessionCopySupportedPropertyDictionary(session: VTSessionRef, supportedPropertyDictionaryOut: *mut CFDictionaryRef) -> OSStatus;
23
24    pub static kVTPropertyTypeKey: CFStringRef;
25    pub static kVTPropertyType_Enumeration: CFStringRef;
26    pub static kVTPropertyType_Boolean: CFStringRef;
27    pub static kVTPropertyType_Number: CFStringRef;
28    pub static kVTPropertyReadWriteStatusKey: CFStringRef;
29    pub static kVTPropertyReadWriteStatus_ReadOnly: CFStringRef;
30    pub static kVTPropertyReadWriteStatus_ReadWrite: CFStringRef;
31    pub static kVTPropertyShouldBeSerializedKey: CFStringRef;
32    pub static kVTPropertySupportedValueMinimumKey: CFStringRef;
33    pub static kVTPropertySupportedValueMaximumKey: CFStringRef;
34    pub static kVTPropertySupportedValueListKey: CFStringRef;
35    pub static kVTPropertyDocumentationKey: CFStringRef;
36
37    pub fn VTSessionSetProperty(session: VTSessionRef, propertyKey: CFStringRef, propertyValue: CFTypeRef) -> OSStatus;
38    pub fn VTSessionSetProperties(session: VTSessionRef, propertyDictionary: CFDictionaryRef) -> OSStatus;
39    pub fn VTSessionCopyProperty(
40        session: VTSessionRef,
41        propertyKey: CFStringRef,
42        allocator: CFAllocatorRef,
43        propertyValueOut: *mut c_void,
44    ) -> OSStatus;
45    pub fn VTSessionCopySerializableProperties(session: VTSessionRef, allocator: CFAllocatorRef, dictionaryOut: *mut CFDictionaryRef) -> OSStatus;
46}
47
48declare_TCFType!(VTSession, VTSessionRef);
49impl_CFTypeDescription!(VTSession);
50
51impl VTSession {
52    #[inline]
53    pub fn as_concrete_TypeRef(&self) -> VTSessionRef {
54        self.0
55    }
56
57    #[inline]
58    pub fn as_CFType(&self) -> CFType {
59        unsafe { CFType::wrap_under_get_rule(self.as_CFTypeRef()) }
60    }
61
62    #[inline]
63    pub fn as_CFTypeRef(&self) -> CFTypeRef {
64        self.as_concrete_TypeRef() as CFTypeRef
65    }
66
67    #[inline]
68    pub fn into_CFType(self) -> CFType {
69        let reference = self.as_CFTypeRef();
70        mem::forget(self);
71        unsafe { CFType::wrap_under_create_rule(reference) }
72    }
73
74    #[inline]
75    pub unsafe fn wrap_under_create_rule(reference: VTSessionRef) -> VTSession {
76        VTSession(reference)
77    }
78
79    #[inline]
80    pub unsafe fn wrap_under_get_rule(reference: VTSessionRef) -> VTSession {
81        VTSession(CFRetain(reference as CFTypeRef) as VTSessionRef)
82    }
83
84    #[inline]
85    pub fn type_of(&self) -> CFTypeID {
86        unsafe { CFGetTypeID(self.as_CFTypeRef()) }
87    }
88
89    #[inline]
90    pub fn instance_of<T: TCFType>(&self) -> bool {
91        self.type_of() == T::type_id()
92    }
93}
94
95impl Clone for VTSession {
96    #[inline]
97    fn clone(&self) -> VTSession {
98        unsafe { VTSession::wrap_under_get_rule(self.0) }
99    }
100}
101
102impl PartialEq for VTSession {
103    #[inline]
104    fn eq(&self, other: &VTSession) -> bool {
105        self.as_CFType().eq(&other.as_CFType())
106    }
107}
108
109pub trait TVTSession: TCFType {
110    #[inline]
111    fn as_session(&self) -> VTSession {
112        unsafe { VTSession::wrap_under_get_rule(self.as_concrete_TypeRef().as_void_ptr() as VTSessionRef) }
113    }
114
115    #[inline]
116    fn into_session(self) -> VTSession
117    where
118        Self: Sized,
119    {
120        let reference = self.as_concrete_TypeRef().as_void_ptr() as VTSessionRef;
121        mem::forget(self);
122        unsafe { VTSession::wrap_under_create_rule(reference) }
123    }
124}
125
126impl VTSession {
127    #[inline]
128    pub fn downcast<T: TVTSession>(&self) -> Option<T> {
129        if self.instance_of::<T>() {
130            unsafe { Some(T::wrap_under_get_rule(T::Ref::from_void_ptr(self.as_concrete_TypeRef().as_void_ptr()))) }
131        } else {
132            None
133        }
134    }
135
136    #[inline]
137    pub fn downcast_into<T: TVTSession>(self) -> Option<T> {
138        if self.instance_of::<T>() {
139            unsafe {
140                let reference = T::Ref::from_void_ptr(self.as_concrete_TypeRef().as_void_ptr());
141                mem::forget(self);
142                Some(T::wrap_under_create_rule(reference))
143            }
144        } else {
145            None
146        }
147    }
148}
149
150impl VTSession {
151    pub fn copy_supported_property_dictionary(&self) -> Result<CFDictionary<CFString, CFType>, OSStatus> {
152        unsafe {
153            let mut dict: CFDictionaryRef = null_mut();
154            let status = VTSessionCopySupportedPropertyDictionary(self.as_concrete_TypeRef(), &mut dict);
155            if status == 0 {
156                Ok(CFDictionary::wrap_under_create_rule(dict))
157            } else {
158                Err(status)
159            }
160        }
161    }
162
163    pub fn copy_property(&self, property_key: CFString) -> Result<CFType, OSStatus> {
164        unsafe {
165            let mut value: CFTypeRef = null_mut();
166            let status = VTSessionCopyProperty(
167                self.as_concrete_TypeRef(),
168                property_key.as_concrete_TypeRef(),
169                kCFAllocatorDefault,
170                addr_of_mut!(value).cast(),
171            );
172            if status == 0 {
173                Ok(CFType::wrap_under_create_rule(value))
174            } else {
175                Err(status)
176            }
177        }
178    }
179
180    pub fn copy_serializable_properties(&self) -> Result<CFDictionary<CFString, CFType>, OSStatus> {
181        unsafe {
182            let mut dict: CFDictionaryRef = null_mut();
183            let status = VTSessionCopySerializableProperties(self.as_concrete_TypeRef(), kCFAllocatorDefault, &mut dict);
184            if status == 0 {
185                Ok(CFDictionary::wrap_under_create_rule(dict))
186            } else {
187                Err(status)
188            }
189        }
190    }
191
192    pub fn set_property(&self, property_key: CFString, property_value: CFType) -> Result<(), OSStatus> {
193        unsafe {
194            let status = VTSessionSetProperty(self.as_concrete_TypeRef(), property_key.as_concrete_TypeRef(), property_value.as_concrete_TypeRef());
195            if status == 0 {
196                Ok(())
197            } else {
198                Err(status)
199            }
200        }
201    }
202
203    pub fn set_properties(&self, property_dictionary: &CFDictionary<CFString, CFType>) -> Result<(), OSStatus> {
204        unsafe {
205            let status = VTSessionSetProperties(self.as_concrete_TypeRef(), property_dictionary.as_concrete_TypeRef());
206            if status == 0 {
207                Ok(())
208            } else {
209                Err(status)
210            }
211        }
212    }
213}