Skip to main content

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