core_video/
buffer.rs

1use std::mem;
2
3use core_foundation::{
4    base::{Boolean, CFGetTypeID, CFType, CFTypeID, CFTypeRef, TCFType, TCFTypeRef},
5    dictionary::{CFDictionary, CFDictionaryRef},
6    string::{CFString, CFStringRef},
7};
8use libc::c_void;
9#[cfg(feature = "objc")]
10use objc2::encode::{Encoding, RefEncode};
11
12#[repr(C)]
13pub struct __CVBuffer(c_void);
14
15pub type CVBufferRef = *mut __CVBuffer;
16
17pub type CVAttachmentMode = u32;
18pub const kCVAttachmentMode_ShouldNotPropagate: CVAttachmentMode = 0;
19pub const kCVAttachmentMode_ShouldPropagate: CVAttachmentMode = 1;
20
21extern "C" {
22    pub static kCVBufferPropagatedAttachmentsKey: CFStringRef;
23    pub static kCVBufferNonPropagatedAttachmentsKey: CFStringRef;
24
25    pub static kCVBufferMovieTimeKey: CFStringRef;
26    pub static kCVBufferTimeValueKey: CFStringRef;
27    pub static kCVBufferTimeScaleKey: CFStringRef;
28
29    pub fn CVBufferRetain(buffer: CVBufferRef) -> CVBufferRef;
30    pub fn CVBufferRelease(buffer: CVBufferRef);
31    pub fn CVBufferSetAttachment(buffer: CVBufferRef, key: CFStringRef, value: CFTypeRef, attachmentMode: CVAttachmentMode);
32    pub fn CVBufferGetAttachment(buffer: CVBufferRef, key: CFStringRef, attachmentMode: *mut CVAttachmentMode) -> CFTypeRef;
33    pub fn CVBufferRemoveAttachment(buffer: CVBufferRef, key: CFStringRef);
34    pub fn CVBufferRemoveAllAttachments(buffer: CVBufferRef);
35    pub fn CVBufferGetAttachments(buffer: CVBufferRef, attachmentMode: CVAttachmentMode) -> CFDictionaryRef;
36    pub fn CVBufferSetAttachments(buffer: CVBufferRef, theAttachments: CFDictionaryRef, attachmentMode: CVAttachmentMode);
37    pub fn CVBufferPropagateAttachments(sourceBuffer: CVBufferRef, destinationBuffer: CVBufferRef);
38    pub fn CVBufferCopyAttachments(sourceBuffer: CVBufferRef, attachmentMode: CVAttachmentMode) -> CFDictionaryRef;
39    pub fn CVBufferCopyAttachment(buffer: CVBufferRef, key: CFStringRef, attachmentMode: *mut CVAttachmentMode) -> CFTypeRef;
40    pub fn CVBufferHasAttachment(buffer: CVBufferRef, key: CFStringRef) -> Boolean;
41}
42
43#[cfg(feature = "objc")]
44unsafe impl RefEncode for __CVBuffer {
45    const ENCODING_REF: Encoding = Encoding::Pointer(&Encoding::Struct("__CVBuffer", &[]));
46}
47
48pub enum CVBufferAttachmentsKeys {
49    Propagated,
50    NonPropagated,
51}
52
53impl From<CVBufferAttachmentsKeys> for CFStringRef {
54    fn from(key: CVBufferAttachmentsKeys) -> CFStringRef {
55        unsafe {
56            match key {
57                CVBufferAttachmentsKeys::Propagated => kCVBufferPropagatedAttachmentsKey,
58                CVBufferAttachmentsKeys::NonPropagated => kCVBufferNonPropagatedAttachmentsKey,
59            }
60        }
61    }
62}
63
64impl From<CVBufferAttachmentsKeys> for CFString {
65    fn from(key: CVBufferAttachmentsKeys) -> CFString {
66        unsafe { CFString::wrap_under_get_rule(CFStringRef::from(key)) }
67    }
68}
69
70pub enum CVBufferKeys {
71    MovieTime,
72    TimeValue,
73    TimeScale,
74}
75
76impl From<CVBufferKeys> for CFStringRef {
77    fn from(key: CVBufferKeys) -> CFStringRef {
78        unsafe {
79            match key {
80                CVBufferKeys::MovieTime => kCVBufferMovieTimeKey,
81                CVBufferKeys::TimeValue => kCVBufferTimeValueKey,
82                CVBufferKeys::TimeScale => kCVBufferTimeScaleKey,
83            }
84        }
85    }
86}
87
88impl From<CVBufferKeys> for CFString {
89    fn from(key: CVBufferKeys) -> CFString {
90        unsafe { CFString::wrap_under_get_rule(CFStringRef::from(key)) }
91    }
92}
93
94pub struct CVBuffer(CVBufferRef);
95
96impl Drop for CVBuffer {
97    fn drop(&mut self) {
98        unsafe { CVBufferRelease(self.0) }
99    }
100}
101
102impl CVBuffer {
103    #[inline]
104    pub fn as_concrete_TypeRef(&self) -> CVBufferRef {
105        self.0
106    }
107
108    #[inline]
109    pub fn as_CFType(&self) -> CFType {
110        unsafe { CFType::wrap_under_get_rule(self.as_CFTypeRef()) }
111    }
112
113    #[inline]
114    pub fn as_CFTypeRef(&self) -> CFTypeRef {
115        self.as_concrete_TypeRef() as CFTypeRef
116    }
117
118    #[inline]
119    pub fn into_CFType(self) -> CFType {
120        let reference = self.as_CFTypeRef();
121        mem::forget(self);
122        unsafe { CFType::wrap_under_create_rule(reference) }
123    }
124
125    #[inline]
126    pub unsafe fn wrap_under_create_rule(reference: CVBufferRef) -> CVBuffer {
127        CVBuffer(reference)
128    }
129
130    #[inline]
131    pub unsafe fn wrap_under_get_rule(reference: CVBufferRef) -> CVBuffer {
132        CVBuffer(CVBufferRetain(reference))
133    }
134
135    #[inline]
136    pub fn type_of(&self) -> CFTypeID {
137        unsafe { CFGetTypeID(self.as_CFTypeRef()) }
138    }
139
140    #[inline]
141    pub fn instance_of<T: TCFType>(&self) -> bool {
142        self.type_of() == T::type_id()
143    }
144}
145
146impl Clone for CVBuffer {
147    #[inline]
148    fn clone(&self) -> CVBuffer {
149        unsafe { CVBuffer::wrap_under_get_rule(self.0) }
150    }
151}
152
153impl PartialEq for CVBuffer {
154    #[inline]
155    fn eq(&self, other: &CVBuffer) -> bool {
156        self.as_CFType().eq(&other.as_CFType())
157    }
158}
159
160impl Eq for CVBuffer {}
161
162impl_CFTypeDescription!(CVBuffer);
163
164pub trait TCVBuffer: TCFType {
165    #[inline]
166    fn as_buffer(&self) -> CVBuffer {
167        unsafe { CVBuffer::wrap_under_get_rule(self.as_concrete_TypeRef().as_void_ptr() as CVBufferRef) }
168    }
169
170    #[inline]
171    fn into_buffer(self) -> CVBuffer
172    where
173        Self: Sized,
174    {
175        let reference = self.as_concrete_TypeRef().as_void_ptr() as CVBufferRef;
176        mem::forget(self);
177        unsafe { CVBuffer::wrap_under_create_rule(reference) }
178    }
179}
180
181impl CVBuffer {
182    #[inline]
183    pub fn downcast<T: TCVBuffer>(&self) -> Option<T> {
184        if self.instance_of::<T>() {
185            unsafe { Some(T::wrap_under_get_rule(T::Ref::from_void_ptr(self.as_concrete_TypeRef() as *const c_void))) }
186        } else {
187            None
188        }
189    }
190
191    #[inline]
192    pub fn downcast_into<T: TCVBuffer>(self) -> Option<T> {
193        if self.instance_of::<T>() {
194            unsafe {
195                let reference = T::Ref::from_void_ptr(self.as_concrete_TypeRef() as *const c_void);
196                mem::forget(self);
197                Some(T::wrap_under_create_rule(reference))
198            }
199        } else {
200            None
201        }
202    }
203}
204
205impl CVBuffer {
206    #[inline]
207    pub fn set_attachment(&self, key: &CFString, value: &CFType, attachment_mode: CVAttachmentMode) {
208        unsafe {
209            CVBufferSetAttachment(self.as_concrete_TypeRef(), key.as_concrete_TypeRef(), value.as_concrete_TypeRef(), attachment_mode);
210        }
211    }
212
213    #[inline]
214    pub fn get_attachment(&self, key: &CFString, attachment_mode: Option<&mut CVAttachmentMode>) -> Option<CFType> {
215        unsafe {
216            let attachment_mode = match attachment_mode {
217                Some(attachment_mode) => attachment_mode as *mut CVAttachmentMode,
218                None => std::ptr::null_mut(),
219            };
220            let value = CVBufferGetAttachment(self.as_concrete_TypeRef(), key.as_concrete_TypeRef(), attachment_mode);
221            if value.is_null() {
222                None
223            } else {
224                Some(TCFType::wrap_under_get_rule(value))
225            }
226        }
227    }
228
229    #[inline]
230    pub fn remove_attachment(&self, key: &CFString) {
231        unsafe {
232            CVBufferRemoveAttachment(self.as_concrete_TypeRef(), key.as_concrete_TypeRef());
233        }
234    }
235
236    #[inline]
237    pub fn remove_all_attachments(&self) {
238        unsafe {
239            CVBufferRemoveAllAttachments(self.as_concrete_TypeRef());
240        }
241    }
242
243    #[inline]
244    pub fn get_attachments(&self, attachment_mode: CVAttachmentMode) -> Option<CFDictionary<CFString, CFType>> {
245        unsafe {
246            let attachments = CVBufferGetAttachments(self.as_concrete_TypeRef(), attachment_mode);
247            if attachments.is_null() {
248                None
249            } else {
250                Some(TCFType::wrap_under_get_rule(attachments))
251            }
252        }
253    }
254
255    #[inline]
256    pub fn set_attachments(&self, the_attachments: &CFDictionary<CFString, CFType>, attachment_mode: CVAttachmentMode) {
257        unsafe {
258            CVBufferSetAttachments(self.as_concrete_TypeRef(), the_attachments.as_concrete_TypeRef(), attachment_mode);
259        }
260    }
261
262    #[inline]
263    pub fn propagate_attachments(&self, destination_buffer: &CVBuffer) {
264        unsafe {
265            CVBufferPropagateAttachments(self.as_concrete_TypeRef(), destination_buffer.as_concrete_TypeRef());
266        }
267    }
268
269    #[inline]
270    pub fn copy_attachments(&self, attachment_mode: CVAttachmentMode) -> Option<CFDictionary<CFString, CFType>> {
271        unsafe {
272            let attachments = CVBufferCopyAttachments(self.as_concrete_TypeRef(), attachment_mode);
273            if attachments.is_null() {
274                None
275            } else {
276                Some(TCFType::wrap_under_create_rule(attachments))
277            }
278        }
279    }
280
281    #[inline]
282    pub fn copy_attachment(&self, key: &CFString, attachment_mode: Option<&mut CVAttachmentMode>) -> Option<CFType> {
283        unsafe {
284            let attachment_mode = match attachment_mode {
285                Some(attachment_mode) => attachment_mode as *mut CVAttachmentMode,
286                None => std::ptr::null_mut(),
287            };
288            let attachment = CVBufferCopyAttachment(self.as_concrete_TypeRef(), key.as_concrete_TypeRef(), attachment_mode);
289            if attachment.is_null() {
290                None
291            } else {
292                Some(TCFType::wrap_under_create_rule(attachment))
293            }
294        }
295    }
296
297    #[inline]
298    pub fn has_attachment(&self, key: &CFString) -> bool {
299        unsafe { CVBufferHasAttachment(self.as_concrete_TypeRef(), key.as_concrete_TypeRef()) != 0 }
300    }
301}