Skip to main content

core_video/
pixel_buffer_pool.rs

1use std::ptr::{null, null_mut};
2
3use core_foundation::{
4    base::{kCFAllocatorDefault, CFAllocatorRef, CFType, CFTypeID, TCFType},
5    dictionary::{CFDictionary, CFDictionaryRef},
6    impl_CFTypeDescription, impl_TCFType,
7    string::{CFString, CFStringRef},
8};
9use libc::c_void;
10
11use crate::{
12    base::CVOptionFlags,
13    pixel_buffer::{CVPixelBuffer, CVPixelBufferRef},
14    r#return::{kCVReturnSuccess, CVReturn},
15};
16
17#[repr(C)]
18pub struct __CVPixelBufferPool(c_void);
19
20pub type CVPixelBufferPoolRef = *mut __CVPixelBufferPool;
21
22pub type CVPixelBufferPoolFlushFlags = CVOptionFlags;
23
24pub const kCVPixelBufferPoolFlushExcessBuffers: CVPixelBufferPoolFlushFlags = 1;
25
26extern "C" {
27    pub static kCVPixelBufferPoolMinimumBufferCountKey: CFStringRef;
28    pub static kCVPixelBufferPoolMaximumBufferAgeKey: CFStringRef;
29
30    pub static kCVPixelBufferPoolAllocationThresholdKey: CFStringRef;
31    pub static kCVPixelBufferPoolFreeBufferNotification: CFStringRef;
32
33    pub fn CVPixelBufferPoolGetTypeID() -> CFTypeID;
34    pub fn CVPixelBufferPoolRetain(pixelBufferPool: CVPixelBufferPoolRef) -> CVPixelBufferPoolRef;
35    pub fn CVPixelBufferPoolRelease(pixelBufferPool: CVPixelBufferPoolRef);
36    pub fn CVPixelBufferPoolCreate(
37        allocator: CFAllocatorRef,
38        poolAttributes: CFDictionaryRef,
39        pixelBufferAttributes: CFDictionaryRef,
40        poolOut: *mut CVPixelBufferPoolRef,
41    ) -> CVReturn;
42    pub fn CVPixelBufferPoolGetAttributes(pool: CVPixelBufferPoolRef) -> CFDictionaryRef;
43    pub fn CVPixelBufferPoolGetPixelBufferAttributes(pool: CVPixelBufferPoolRef) -> CFDictionaryRef;
44    pub fn CVPixelBufferPoolCreatePixelBuffer(
45        allocator: CFAllocatorRef,
46        pixelBufferPool: CVPixelBufferPoolRef,
47        pixelBufferOut: *mut CVPixelBufferRef,
48    ) -> CVReturn;
49    pub fn CVPixelBufferPoolCreatePixelBufferWithAuxAttributes(
50        allocator: CFAllocatorRef,
51        pixelBufferPool: CVPixelBufferPoolRef,
52        auxAttributes: CFDictionaryRef,
53        pixelBufferOut: *mut CVPixelBufferRef,
54    ) -> CVReturn;
55    pub fn CVPixelBufferPoolFlush(pool: CVPixelBufferPoolRef, options: CVPixelBufferPoolFlushFlags);
56}
57
58pub enum CVPixelBufferPoolKeys {
59    MinimumBufferCount,
60    MaximumBufferAge,
61    AllocationThreshold,
62    FreeBufferNotification,
63}
64
65impl From<CVPixelBufferPoolKeys> for CFStringRef {
66    fn from(key: CVPixelBufferPoolKeys) -> CFStringRef {
67        match key {
68            CVPixelBufferPoolKeys::MinimumBufferCount => unsafe { kCVPixelBufferPoolMinimumBufferCountKey },
69            CVPixelBufferPoolKeys::MaximumBufferAge => unsafe { kCVPixelBufferPoolMaximumBufferAgeKey },
70            CVPixelBufferPoolKeys::AllocationThreshold => unsafe { kCVPixelBufferPoolAllocationThresholdKey },
71            CVPixelBufferPoolKeys::FreeBufferNotification => unsafe { kCVPixelBufferPoolFreeBufferNotification },
72        }
73    }
74}
75
76impl From<CVPixelBufferPoolKeys> for CFString {
77    fn from(key: CVPixelBufferPoolKeys) -> CFString {
78        unsafe { CFString::wrap_under_get_rule(CFStringRef::from(key)) }
79    }
80}
81
82pub struct CVPixelBufferPool(CVPixelBufferPoolRef);
83
84impl Drop for CVPixelBufferPool {
85    fn drop(&mut self) {
86        unsafe { CVPixelBufferPoolRelease(self.0) }
87    }
88}
89
90impl_TCFType!(CVPixelBufferPool, CVPixelBufferPoolRef, CVPixelBufferPoolGetTypeID);
91impl_CFTypeDescription!(CVPixelBufferPool);
92
93impl CVPixelBufferPool {
94    #[inline]
95    pub fn new(
96        pool_attributes: Option<&CFDictionary<CFString, CFType>>,
97        pixel_buffer_attributes: Option<&CFDictionary<CFString, CFType>>,
98    ) -> Result<CVPixelBufferPool, CVReturn> {
99        let mut pool: CVPixelBufferPoolRef = null_mut();
100        let status = unsafe {
101            CVPixelBufferPoolCreate(
102                kCFAllocatorDefault,
103                pool_attributes.map_or(null(), |attrs| attrs.as_concrete_TypeRef()),
104                pixel_buffer_attributes.map_or(null(), |attrs| attrs.as_concrete_TypeRef()),
105                &mut pool,
106            )
107        };
108        if status == kCVReturnSuccess {
109            Ok(unsafe { TCFType::wrap_under_create_rule(pool) })
110        } else {
111            Err(status)
112        }
113    }
114
115    #[inline]
116    pub fn get_attributes(&self) -> Option<CFDictionary<CFString, CFType>> {
117        unsafe {
118            let attributes = CVPixelBufferPoolGetAttributes(self.as_concrete_TypeRef());
119            if attributes.is_null() {
120                None
121            } else {
122                Some(TCFType::wrap_under_create_rule(attributes))
123            }
124        }
125    }
126
127    #[inline]
128    pub fn get_pixel_buffer_attributes(&self) -> Option<CFDictionary<CFString, CFType>> {
129        unsafe {
130            let attributes = CVPixelBufferPoolGetPixelBufferAttributes(self.as_concrete_TypeRef());
131            if attributes.is_null() {
132                None
133            } else {
134                Some(TCFType::wrap_under_create_rule(attributes))
135            }
136        }
137    }
138
139    #[inline]
140    pub fn create_pixel_buffer(&self) -> Result<CVPixelBuffer, CVReturn> {
141        let mut pixel_buffer: CVPixelBufferRef = null_mut();
142        let status = unsafe { CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, self.as_concrete_TypeRef(), &mut pixel_buffer) };
143        if status == kCVReturnSuccess {
144            Ok(unsafe { TCFType::wrap_under_create_rule(pixel_buffer) })
145        } else {
146            Err(status)
147        }
148    }
149
150    #[inline]
151    pub fn create_pixel_buffer_with_aux_attributes(&self, auxAttributes: Option<&CFDictionary<CFString, CFType>>) -> Result<CVPixelBuffer, CVReturn> {
152        let mut pixel_buffer: CVPixelBufferRef = null_mut();
153        let status = unsafe {
154            CVPixelBufferPoolCreatePixelBufferWithAuxAttributes(
155                kCFAllocatorDefault,
156                self.as_concrete_TypeRef(),
157                auxAttributes.map_or(null(), |attrs| attrs.as_concrete_TypeRef()),
158                &mut pixel_buffer,
159            )
160        };
161        if status == kCVReturnSuccess {
162            Ok(unsafe { TCFType::wrap_under_create_rule(pixel_buffer) })
163        } else {
164            Err(status)
165        }
166    }
167}