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}