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