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}