1use std::ptr::{null, null_mut};
2
3use core_foundation::{
4 array::CFArrayRef,
5 base::{kCFAllocatorDefault, Boolean, CFAllocatorRef, CFType, CFTypeID, TCFType},
6 dictionary::{CFDictionary, CFDictionaryRef},
7 string::{CFString, CFStringRef},
8};
9use libc::{c_void, size_t};
10
11use crate::{
12 base::CVOptionFlags,
13 buffer::TCVBuffer,
14 image_buffer::{CVImageBufferRef, TCVImageBuffer},
15 r#return::{kCVReturnInvalidArgument, kCVReturnSuccess, CVReturn},
16 OSType,
17};
18
19pub type CVPixelBufferRef = CVImageBufferRef;
20
21#[inline]
22const fn fourcc(code: &[u8; 4]) -> u32 {
23 ((code[0] as u32) << 24) | ((code[1] as u32) << 16) | ((code[2] as u32) << 8) | ((code[3] as u32) << 0)
24}
25
26pub type CVPixelBufferLockFlags = u64;
27
28pub const kCVPixelFormatType_1Monochrome: OSType = 0x00000001; pub const kCVPixelFormatType_2Indexed: OSType = 0x00000002; pub const kCVPixelFormatType_4Indexed: OSType = 0x00000004; pub const kCVPixelFormatType_8Indexed: OSType = 0x00000008; pub const kCVPixelFormatType_1IndexedGray_WhiteIsZero: OSType = 0x00000021; pub const kCVPixelFormatType_2IndexedGray_WhiteIsZero: OSType = 0x00000022; pub const kCVPixelFormatType_4IndexedGray_WhiteIsZero: OSType = 0x00000024; pub const kCVPixelFormatType_8IndexedGray_WhiteIsZero: OSType = 0x00000028; pub const kCVPixelFormatType_16BE555: OSType = 0x00000010; pub const kCVPixelFormatType_16LE555: OSType = fourcc(b"L555"); pub const kCVPixelFormatType_16LE5551: OSType = fourcc(b"5551"); pub const kCVPixelFormatType_16BE565: OSType = fourcc(b"B565"); pub const kCVPixelFormatType_16LE565: OSType = fourcc(b"L565"); pub const kCVPixelFormatType_24RGB: OSType = 0x00000018; pub const kCVPixelFormatType_24BGR: OSType = fourcc(b"24BG"); pub const kCVPixelFormatType_32ARGB: OSType = 0x00000020; pub const kCVPixelFormatType_32BGRA: OSType = fourcc(b"BGRA"); pub const kCVPixelFormatType_32ABGR: OSType = fourcc(b"ABGR"); pub const kCVPixelFormatType_32RGBA: OSType = fourcc(b"RGBA"); pub const kCVPixelFormatType_64ARGB: OSType = fourcc(b"b64a"); pub const kCVPixelFormatType_48RGB: OSType = fourcc(b"b48r"); pub const kCVPixelFormatType_32AlphaGray: OSType = fourcc(b"b32a"); pub const kCVPixelFormatType_16Gray: OSType = fourcc(b"b16g"); pub const kCVPixelFormatType_30RGB: OSType = fourcc(b"R10k"); pub const kCVPixelFormatType_422YpCbCr8: OSType = fourcc(b"2vuy"); pub const kCVPixelFormatType_4444YpCbCrA8: OSType = fourcc(b"v408"); pub const kCVPixelFormatType_4444YpCbCrA8R: OSType = fourcc(b"r408"); pub const kCVPixelFormatType_4444AYpCbCr8: OSType = fourcc(b"y408"); pub const kCVPixelFormatType_4444AYpCbCr16: OSType = fourcc(b"y416"); pub const kCVPixelFormatType_4444AYpCbCrFloat: OSType = fourcc(b"r4fl"); pub const kCVPixelFormatType_444YpCbCr8: OSType = fourcc(b"v308"); pub const kCVPixelFormatType_422YpCbCr16: OSType = fourcc(b"v216"); pub const kCVPixelFormatType_422YpCbCr10: OSType = fourcc(b"v210"); pub const kCVPixelFormatType_444YpCbCr10: OSType = fourcc(b"v410"); pub const kCVPixelFormatType_420YpCbCr8Planar: OSType = fourcc(b"y420"); pub const kCVPixelFormatType_420YpCbCr8PlanarFullRange: OSType = fourcc(b"f420"); pub const kCVPixelFormatType_422YpCbCr_4A_8BiPlanar: OSType = fourcc(b"a2vy"); pub const kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: OSType = fourcc(b"420v"); pub const kCVPixelFormatType_420YpCbCr8BiPlanarFullRange: OSType = fourcc(b"420f"); pub const kCVPixelFormatType_422YpCbCr8BiPlanarVideoRange: OSType = fourcc(b"422v"); pub const kCVPixelFormatType_422YpCbCr8BiPlanarFullRange: OSType = fourcc(b"422f"); pub const kCVPixelFormatType_444YpCbCr8BiPlanarVideoRange: OSType = fourcc(b"444v"); pub const kCVPixelFormatType_444YpCbCr8BiPlanarFullRange: OSType = fourcc(b"444f"); pub const kCVPixelFormatType_422YpCbCr8_yuvs: OSType = fourcc(b"yuvs"); pub const kCVPixelFormatType_422YpCbCr8FullRange: OSType = fourcc(b"yuvf"); pub const kCVPixelFormatType_OneComponent8: OSType = fourcc(b"L008"); pub const kCVPixelFormatType_TwoComponent8: OSType = fourcc(b"2C08"); pub const kCVPixelFormatType_30RGBLEPackedWideGamut: OSType = fourcc(b"w30r"); pub const kCVPixelFormatType_ARGB2101010LEPacked: OSType = fourcc(b"l10r"); pub const kCVPixelFormatType_40ARGBLEWideGamut: OSType = fourcc(b"w40a"); pub const kCVPixelFormatType_40ARGBLEWideGamutPremultiplied: OSType = fourcc(b"w40m"); pub const kCVPixelFormatType_OneComponent10: OSType = fourcc(b"L010"); pub const kCVPixelFormatType_OneComponent12: OSType = fourcc(b"L012"); pub const kCVPixelFormatType_OneComponent16: OSType = fourcc(b"L016"); pub const kCVPixelFormatType_TwoComponent16: OSType = fourcc(b"2C16"); pub const kCVPixelFormatType_OneComponent16Half: OSType = fourcc(b"L00h"); pub const kCVPixelFormatType_OneComponent32Float: OSType = fourcc(b"L00f"); pub const kCVPixelFormatType_TwoComponent16Half: OSType = fourcc(b"2C0h"); pub const kCVPixelFormatType_TwoComponent32Float: OSType = fourcc(b"2C0f"); pub const kCVPixelFormatType_64RGBAHalf: OSType = fourcc(b"RGhA"); pub const kCVPixelFormatType_128RGBAFloat: OSType = fourcc(b"RGfA"); pub const kCVPixelFormatType_14Bayer_GRBG: OSType = fourcc(b"grb4"); pub const kCVPixelFormatType_14Bayer_RGGB: OSType = fourcc(b"rgg4"); pub const kCVPixelFormatType_14Bayer_BGGR: OSType = fourcc(b"bgg4"); pub const kCVPixelFormatType_14Bayer_GBRG: OSType = fourcc(b"gbr4"); pub const kCVPixelFormatType_DisparityFloat16: OSType = fourcc(b"hdis"); pub const kCVPixelFormatType_DisparityFloat32: OSType = fourcc(b"fdis"); pub const kCVPixelFormatType_DepthFloat16: OSType = fourcc(b"hdep"); pub const kCVPixelFormatType_DepthFloat32: OSType = fourcc(b"fdep"); pub const kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange: OSType = fourcc(b"x420"); pub const kCVPixelFormatType_422YpCbCr10BiPlanarVideoRange: OSType = fourcc(b"x422"); pub const kCVPixelFormatType_444YpCbCr10BiPlanarVideoRange: OSType = fourcc(b"x444"); pub const kCVPixelFormatType_420YpCbCr10BiPlanarFullRange: OSType = fourcc(b"xf20"); pub const kCVPixelFormatType_422YpCbCr10BiPlanarFullRange: OSType = fourcc(b"xf22"); pub const kCVPixelFormatType_444YpCbCr10BiPlanarFullRange: OSType = fourcc(b"xf44"); pub const kCVPixelFormatType_420YpCbCr8VideoRange_8A_TriPlanar: OSType = fourcc(b"v0a8"); pub const kCVPixelFormatType_16VersatileBayer: OSType = fourcc(b"bp16"); pub const kCVPixelFormatType_64RGBA_DownscaledProResRAW: OSType = fourcc(b"bp64"); pub const kCVPixelFormatType_422YpCbCr16BiPlanarVideoRange: OSType = fourcc(b"sv22"); pub const kCVPixelFormatType_444YpCbCr16BiPlanarVideoRange: OSType = fourcc(b"sv44"); pub const kCVPixelFormatType_444YpCbCr16VideoRange_16A_TriPlanar: OSType = fourcc(b"s4as"); pub const kCVPixelFormatType_Lossless_32BGRA: OSType = fourcc(b"&BGA"); pub const kCVPixelFormatType_Lossless_420YpCbCr8BiPlanarVideoRange: OSType = fourcc(b"&8v0"); pub const kCVPixelFormatType_Lossless_420YpCbCr8BiPlanarFullRange: OSType = fourcc(b"&8f0"); pub const kCVPixelFormatType_Lossless_420YpCbCr10PackedBiPlanarVideoRange: OSType = fourcc(b"&xv0"); pub const kCVPixelFormatType_Lossless_422YpCbCr10PackedBiPlanarVideoRange: OSType = fourcc(b"&xv2"); pub const kCVPixelFormatType_Lossy_32BGRA: OSType = fourcc(b"-BGA"); pub const kCVPixelFormatType_Lossy_420YpCbCr8BiPlanarVideoRange: OSType = fourcc(b"-8v0"); pub const kCVPixelFormatType_Lossy_420YpCbCr8BiPlanarFullRange: OSType = fourcc(b"-8f0"); pub const kCVPixelFormatType_Lossy_420YpCbCr10PackedBiPlanarVideoRange: OSType = fourcc(b"-xv0"); pub const kCVPixelFormatType_Lossy_422YpCbCr10PackedBiPlanarVideoRange: OSType = fourcc(b"-xv2"); pub const kCVPixelBufferLock_ReadOnly: CVPixelBufferLockFlags = 0x00000001;
125
126#[repr(C)]
127pub struct CVPlanarComponentInfo {
128 pub offset: i32,
129 pub rowBytes: u32,
130}
131
132#[repr(C)]
133pub struct CVPlanarPixelBufferInfo {
134 pub componentInfo: [CVPlanarComponentInfo; 1],
135}
136
137#[repr(C)]
138pub struct CVPlanarPixelBufferInfo_YCbCrPlanar {
139 pub componentInfoY: CVPlanarComponentInfo,
140 pub componentInfoCb: CVPlanarComponentInfo,
141 pub componentInfoCr: CVPlanarComponentInfo,
142}
143
144#[repr(C)]
145pub struct CVPlanarPixelBufferInfo_YCbCrBiPlanar {
146 pub componentInfoY: CVPlanarComponentInfo,
147 pub componentInfoCbCr: CVPlanarComponentInfo,
148}
149
150pub type CVPixelBufferReleaseBytesCallback = extern "C" fn(releaseRefCon: *mut c_void, baseAddress: *const *const c_void);
151pub type CVPixelBufferReleasePlanarBytesCallback = extern "C" fn(
152 releaseRefCon: *mut c_void,
153 dataPtr: *const *const c_void,
154 dataSize: size_t,
155 numberOfPlanes: size_t,
156 planeAddresses: *const *const c_void,
157);
158
159extern "C" {
160 pub static kCVPixelBufferPixelFormatTypeKey: CFStringRef;
161 pub static kCVPixelBufferMemoryAllocatorKey: CFStringRef;
162 pub static kCVPixelBufferWidthKey: CFStringRef;
163 pub static kCVPixelBufferHeightKey: CFStringRef;
164 pub static kCVPixelBufferExtendedPixelsLeftKey: CFStringRef;
165 pub static kCVPixelBufferExtendedPixelsTopKey: CFStringRef;
166 pub static kCVPixelBufferExtendedPixelsRightKey: CFStringRef;
167 pub static kCVPixelBufferExtendedPixelsBottomKey: CFStringRef;
168 pub static kCVPixelBufferBytesPerRowAlignmentKey: CFStringRef;
169 pub static kCVPixelBufferCGBitmapContextCompatibilityKey: CFStringRef;
170 pub static kCVPixelBufferCGImageCompatibilityKey: CFStringRef;
171 pub static kCVPixelBufferOpenGLCompatibilityKey: CFStringRef;
172 pub static kCVPixelBufferPlaneAlignmentKey: CFStringRef;
173 pub static kCVPixelBufferIOSurfacePropertiesKey: CFStringRef;
174 #[cfg(target_os = "ios")]
175 pub static kCVPixelBufferOpenGLESCompatibilityKey: CFStringRef;
176 pub static kCVPixelBufferMetalCompatibilityKey: CFStringRef;
177 #[cfg(target_os = "macos")]
178 pub static kCVPixelBufferOpenGLTextureCacheCompatibilityKey: CFStringRef;
179 #[cfg(target_os = "ios")]
180 pub static kCVPixelBufferOpenGLESTextureCacheCompatibilityKey: CFStringRef;
181 pub static kCVPixelBufferVersatileBayerKey_BayerPattern: CFStringRef;
182}
183
184pub const kCVVersatileBayer_BayerPattern_RGGB: u32 = 0;
185pub const kCVVersatileBayer_BayerPattern_GRBG: u32 = 1;
186pub const kCVVersatileBayer_BayerPattern_GBRG: u32 = 2;
187pub const kCVVersatileBayer_BayerPattern_BGGR: u32 = 3;
188
189extern "C" {
190 pub static kCVPixelBufferProResRAWKey_SenselSitingOffsets: CFStringRef;
191 pub static kCVPixelBufferProResRAWKey_BlackLevel: CFStringRef;
192 pub static kCVPixelBufferProResRAWKey_WhiteLevel: CFStringRef;
193 pub static kCVPixelBufferProResRAWKey_WhiteBalanceCCT: CFStringRef;
194 pub static kCVPixelBufferProResRAWKey_WhiteBalanceRedFactor: CFStringRef;
195 pub static kCVPixelBufferProResRAWKey_WhiteBalanceBlueFactor: CFStringRef;
196 pub static kCVPixelBufferProResRAWKey_ColorMatrix: CFStringRef;
197 pub static kCVPixelBufferProResRAWKey_GainFactor: CFStringRef;
198 pub static kCVPixelBufferProResRAWKey_RecommendedCrop: CFStringRef;
199 pub static kCVPixelBufferProResRAWKey_MetadataExtension: CFStringRef;
200}
201
202extern "C" {
203 pub fn CVPixelBufferGetTypeID() -> CFTypeID;
204 pub fn CVPixelBufferRetain(texture: CVPixelBufferRef) -> CVPixelBufferRef;
205 pub fn CVPixelBufferRelease(texture: CVPixelBufferRef);
206 pub fn CVPixelBufferCreateResolvedAttributesDictionary(
207 allocator: CFAllocatorRef,
208 attributes: CFArrayRef,
209 resolvedDictionaryOut: *mut CFDictionaryRef,
210 ) -> CVReturn;
211 pub fn CVPixelBufferCreate(
212 allocator: CFAllocatorRef,
213 width: size_t,
214 height: size_t,
215 pixelFormatType: OSType,
216 pixelBufferAttributes: CFDictionaryRef,
217 pixelBufferOut: *mut CVPixelBufferRef,
218 ) -> CVReturn;
219 pub fn CVPixelBufferCreateWithBytes(
220 allocator: CFAllocatorRef,
221 width: size_t,
222 height: size_t,
223 pixelFormatType: OSType,
224 baseAddress: *mut c_void,
225 bytesPerRow: size_t,
226 releaseCallback: CVPixelBufferReleaseBytesCallback,
227 releaseRefCon: *mut c_void,
228 pixelBufferAttributes: CFDictionaryRef,
229 pixelBufferOut: *mut CVPixelBufferRef,
230 ) -> CVReturn;
231 pub fn CVPixelBufferCreateWithPlanarBytes(
232 allocator: CFAllocatorRef,
233 width: size_t,
234 height: size_t,
235 pixelFormatType: OSType,
236 dataPtr: *mut c_void,
237 dataSize: size_t,
238 numberOfPlanes: size_t,
239 planeBaseAddress: *const *mut c_void,
240 planeWidth: *const size_t,
241 planeHeight: *const size_t,
242 planeBytesPerRow: *const size_t,
243 releaseCallback: CVPixelBufferReleasePlanarBytesCallback,
244 releaseRefCon: *mut c_void,
245 pixelBufferAttributes: CFDictionaryRef,
246 pixelBufferOut: *mut CVPixelBufferRef,
247 ) -> CVReturn;
248 pub fn CVPixelBufferLockBaseAddress(pixelBuffer: CVPixelBufferRef, lockFlags: CVOptionFlags) -> CVReturn;
249 pub fn CVPixelBufferUnlockBaseAddress(pixelBuffer: CVPixelBufferRef, unlockFlags: CVOptionFlags) -> CVReturn;
250 pub fn CVPixelBufferGetWidth(pixelBuffer: CVPixelBufferRef) -> size_t;
251 pub fn CVPixelBufferGetHeight(pixelBuffer: CVPixelBufferRef) -> size_t;
252 pub fn CVPixelBufferGetPixelFormatType(pixelBuffer: CVPixelBufferRef) -> OSType;
253
254 pub fn CVPixelBufferGetBaseAddress(pixelBuffer: CVPixelBufferRef) -> *mut c_void;
255 pub fn CVPixelBufferGetBytesPerRow(pixelBuffer: CVPixelBufferRef) -> size_t;
256 pub fn CVPixelBufferGetDataSize(pixelBuffer: CVPixelBufferRef) -> size_t;
257 pub fn CVPixelBufferIsPlanar(pixelBuffer: CVPixelBufferRef) -> Boolean;
258 pub fn CVPixelBufferGetPlaneCount(pixelBuffer: CVPixelBufferRef) -> size_t;
259 pub fn CVPixelBufferGetWidthOfPlane(pixelBuffer: CVPixelBufferRef, planeIndex: size_t) -> size_t;
260 pub fn CVPixelBufferGetHeightOfPlane(pixelBuffer: CVPixelBufferRef, planeIndex: size_t) -> size_t;
261 pub fn CVPixelBufferGetBaseAddressOfPlane(pixelBuffer: CVPixelBufferRef, planeIndex: size_t) -> *mut c_void;
262 pub fn CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer: CVPixelBufferRef, planeIndex: size_t) -> size_t;
263 pub fn CVPixelBufferGetExtendedPixels(
264 pixelBuffer: CVPixelBufferRef,
265 extraColumnsOnLeft: *const size_t,
266 extraColumnsOnRight: *const size_t,
267 extraRowsOnTop: *const size_t,
268 extraRowsOnBottom: *const size_t,
269 );
270 pub fn CVPixelBufferFillExtendedPixels(pixelBuffer: CVPixelBufferRef) -> CVReturn;
271 pub fn CVPixelBufferCopyCreationAttributes(pixelBuffer: CVPixelBufferRef) -> CFDictionaryRef;
272}
273
274pub enum CVPixelBufferKeys {
275 PixelFormatType,
276 MemoryAllocator,
277 Width,
278 Height,
279 ExtendedPixelsLeft,
280 ExtendedPixelsTop,
281 ExtendedPixelsRight,
282 ExtendedPixelsBottom,
283 BytesPerRowAlignment,
284 CGBitmapContextCompatibility,
285 CGImageCompatibility,
286 OpenGLCompatibility,
287 PlaneAlignment,
288 IOSurfaceProperties,
289 #[cfg(target_os = "ios")]
290 OpenGLESCompatibility,
291 MetalCompatibility,
292 #[cfg(target_os = "macos")]
293 OpenGLTextureCacheCompatibility,
294 #[cfg(target_os = "ios")]
295 OpenGLESTextureCacheCompatibility,
296 VersatileBayerKey_BayerPattern,
297}
298
299impl From<CVPixelBufferKeys> for CFStringRef {
300 fn from(key: CVPixelBufferKeys) -> Self {
301 unsafe {
302 match key {
303 CVPixelBufferKeys::PixelFormatType => kCVPixelBufferPixelFormatTypeKey,
304 CVPixelBufferKeys::MemoryAllocator => kCVPixelBufferMemoryAllocatorKey,
305 CVPixelBufferKeys::Width => kCVPixelBufferWidthKey,
306 CVPixelBufferKeys::Height => kCVPixelBufferHeightKey,
307 CVPixelBufferKeys::ExtendedPixelsLeft => kCVPixelBufferExtendedPixelsLeftKey,
308 CVPixelBufferKeys::ExtendedPixelsTop => kCVPixelBufferExtendedPixelsTopKey,
309 CVPixelBufferKeys::ExtendedPixelsRight => kCVPixelBufferExtendedPixelsRightKey,
310 CVPixelBufferKeys::ExtendedPixelsBottom => kCVPixelBufferExtendedPixelsBottomKey,
311 CVPixelBufferKeys::BytesPerRowAlignment => kCVPixelBufferBytesPerRowAlignmentKey,
312 CVPixelBufferKeys::CGBitmapContextCompatibility => kCVPixelBufferCGBitmapContextCompatibilityKey,
313 CVPixelBufferKeys::CGImageCompatibility => kCVPixelBufferCGImageCompatibilityKey,
314 CVPixelBufferKeys::OpenGLCompatibility => kCVPixelBufferOpenGLCompatibilityKey,
315 CVPixelBufferKeys::PlaneAlignment => kCVPixelBufferPlaneAlignmentKey,
316 CVPixelBufferKeys::IOSurfaceProperties => kCVPixelBufferIOSurfacePropertiesKey,
317 #[cfg(target_os = "ios")]
318 CVPixelBufferKeys::OpenGLESCompatibility => kCVPixelBufferOpenGLESCompatibilityKey,
319 CVPixelBufferKeys::MetalCompatibility => kCVPixelBufferMetalCompatibilityKey,
320 #[cfg(target_os = "macos")]
321 CVPixelBufferKeys::OpenGLTextureCacheCompatibility => kCVPixelBufferOpenGLTextureCacheCompatibilityKey,
322 #[cfg(target_os = "ios")]
323 CVPixelBufferKeys::OpenGLESTextureCacheCompatibility => kCVPixelBufferOpenGLESTextureCacheCompatibilityKey,
324 CVPixelBufferKeys::VersatileBayerKey_BayerPattern => kCVPixelBufferVersatileBayerKey_BayerPattern,
325 }
326 }
327 }
328}
329
330impl From<CVPixelBufferKeys> for CFString {
331 fn from(key: CVPixelBufferKeys) -> Self {
332 unsafe { CFString::wrap_under_get_rule(CFStringRef::from(key)) }
333 }
334}
335
336impl TCVBuffer for CVPixelBuffer {}
337impl TCVImageBuffer for CVPixelBuffer {}
338
339pub struct CVPixelBuffer(CVPixelBufferRef);
340
341impl Drop for CVPixelBuffer {
342 fn drop(&mut self) {
343 unsafe { CVPixelBufferRelease(self.0) }
344 }
345}
346
347impl_TCFType!(CVPixelBuffer, CVPixelBufferRef, CVPixelBufferGetTypeID);
348impl_CFTypeDescription!(CVPixelBuffer);
349
350impl CVPixelBuffer {
351 #[inline]
352 pub fn new(
353 pixel_format: OSType,
354 width: usize,
355 height: usize,
356 options: Option<&CFDictionary<CFString, CFType>>,
357 ) -> Result<CVPixelBuffer, CVReturn> {
358 let mut pixel_buffer: CVPixelBufferRef = null_mut();
359 let status = unsafe {
360 CVPixelBufferCreate(
361 kCFAllocatorDefault,
362 width,
363 height,
364 pixel_format,
365 options.map_or(null(), |options| options.as_concrete_TypeRef()),
366 &mut pixel_buffer,
367 )
368 };
369 if status == kCVReturnSuccess {
370 Ok(unsafe { TCFType::wrap_under_create_rule(pixel_buffer) })
371 } else {
372 Err(status)
373 }
374 }
375
376 #[inline]
377 pub unsafe fn new_with_bytes(
378 pixel_format: OSType,
379 width: usize,
380 height: usize,
381 base_address: *mut c_void,
382 bytes_per_row: usize,
383 release_callback: CVPixelBufferReleaseBytesCallback,
384 release_ref_con: *mut c_void,
385 options: Option<&CFDictionary<CFString, CFType>>,
386 ) -> Result<CVPixelBuffer, CVReturn> {
387 let mut pixel_buffer: CVPixelBufferRef = null_mut();
388 let status = unsafe {
389 CVPixelBufferCreateWithBytes(
390 kCFAllocatorDefault,
391 width,
392 height,
393 pixel_format,
394 base_address,
395 bytes_per_row,
396 release_callback,
397 release_ref_con,
398 options.map_or(null(), |options| options.as_concrete_TypeRef()),
399 &mut pixel_buffer,
400 )
401 };
402 if status == kCVReturnSuccess {
403 Ok(unsafe { TCFType::wrap_under_create_rule(pixel_buffer) })
404 } else {
405 Err(status)
406 }
407 }
408
409 #[inline]
410 pub unsafe fn new_with_planar_bytes(
411 pixel_format: OSType,
412 width: usize,
413 height: usize,
414 data_ptr: *mut c_void,
415 data_size: usize,
416 number_of_planes: usize,
417 plane_base_address: Vec<*mut c_void>,
418 plane_width: Vec<usize>,
419 plane_height: Vec<usize>,
420 plane_bytes_per_row: Vec<usize>,
421 release_callback: CVPixelBufferReleasePlanarBytesCallback,
422 release_ref_con: *mut c_void,
423 options: Option<&CFDictionary<CFString, CFType>>,
424 ) -> Result<CVPixelBuffer, CVReturn> {
425 if plane_base_address.len() != number_of_planes ||
426 plane_width.len() != number_of_planes ||
427 plane_height.len() != number_of_planes ||
428 plane_bytes_per_row.len() != number_of_planes
429 {
430 return Err(kCVReturnInvalidArgument);
431 }
432 let mut pixel_buffer: CVPixelBufferRef = null_mut();
433 let status = unsafe {
434 CVPixelBufferCreateWithPlanarBytes(
435 kCFAllocatorDefault,
436 width,
437 height,
438 pixel_format,
439 data_ptr,
440 data_size,
441 number_of_planes,
442 plane_base_address.as_ptr(),
443 plane_width.as_ptr(),
444 plane_height.as_ptr(),
445 plane_bytes_per_row.as_ptr(),
446 release_callback,
447 release_ref_con,
448 options.map_or(null(), |options| options.as_concrete_TypeRef()),
449 &mut pixel_buffer,
450 )
451 };
452 if status == kCVReturnSuccess {
453 Ok(unsafe { TCFType::wrap_under_create_rule(pixel_buffer) })
454 } else {
455 Err(status)
456 }
457 }
458
459 #[inline]
460 pub fn lock_base_address(&self, options: CVPixelBufferLockFlags) -> CVReturn {
461 unsafe { CVPixelBufferLockBaseAddress(self.as_concrete_TypeRef(), options) }
462 }
463
464 #[inline]
465 pub fn unlock_base_address(&self, options: CVPixelBufferLockFlags) -> CVReturn {
466 unsafe { CVPixelBufferUnlockBaseAddress(self.as_concrete_TypeRef(), options) }
467 }
468
469 #[inline]
470 pub fn get_width(&self) -> usize {
471 unsafe { CVPixelBufferGetWidth(self.as_concrete_TypeRef()) }
472 }
473
474 #[inline]
475 pub fn get_height(&self) -> usize {
476 unsafe { CVPixelBufferGetHeight(self.as_concrete_TypeRef()) }
477 }
478
479 #[inline]
480 pub fn get_pixel_format(&self) -> OSType {
481 unsafe { CVPixelBufferGetPixelFormatType(self.as_concrete_TypeRef()) }
482 }
483
484 #[inline]
485 pub unsafe fn get_base_address(&self) -> *mut c_void {
486 unsafe { CVPixelBufferGetBaseAddress(self.as_concrete_TypeRef()) }
487 }
488
489 #[inline]
490 pub fn get_bytes_per_row(&self) -> usize {
491 unsafe { CVPixelBufferGetBytesPerRow(self.as_concrete_TypeRef()) }
492 }
493
494 #[inline]
495 pub fn get_data_size(&self) -> usize {
496 unsafe { CVPixelBufferGetDataSize(self.as_concrete_TypeRef()) }
497 }
498
499 #[inline]
500 pub fn is_planar(&self) -> bool {
501 unsafe { CVPixelBufferIsPlanar(self.as_concrete_TypeRef()) != 0 }
502 }
503
504 #[inline]
505 pub fn get_plane_count(&self) -> usize {
506 unsafe { CVPixelBufferGetPlaneCount(self.as_concrete_TypeRef()) }
507 }
508
509 #[inline]
510 pub fn get_width_of_plane(&self, plane_index: usize) -> usize {
511 unsafe { CVPixelBufferGetWidthOfPlane(self.as_concrete_TypeRef(), plane_index) }
512 }
513
514 #[inline]
515 pub fn get_height_of_plane(&self, plane_index: usize) -> usize {
516 unsafe { CVPixelBufferGetHeightOfPlane(self.as_concrete_TypeRef(), plane_index) }
517 }
518
519 #[inline]
520 pub unsafe fn get_base_address_of_plane(&self, plane_index: usize) -> *mut c_void {
521 unsafe { CVPixelBufferGetBaseAddressOfPlane(self.as_concrete_TypeRef(), plane_index) }
522 }
523
524 #[inline]
525 pub fn get_bytes_per_row_of_plane(&self, plane_index: usize) -> usize {
526 unsafe { CVPixelBufferGetBytesPerRowOfPlane(self.as_concrete_TypeRef(), plane_index) }
527 }
528
529 #[inline]
530 pub fn get_extended_pixels(&self) -> (usize, usize, usize, usize) {
531 unsafe {
532 let mut left = 0;
533 let mut right = 0;
534 let mut top = 0;
535 let mut bottom = 0;
536 CVPixelBufferGetExtendedPixels(self.as_concrete_TypeRef(), &mut left, &mut right, &mut top, &mut bottom);
537 (left, right, top, bottom)
538 }
539 }
540
541 #[inline]
542 pub fn fill_extended_pixels(&self) -> CVReturn {
543 unsafe { CVPixelBufferFillExtendedPixels(self.as_concrete_TypeRef()) }
544 }
545
546 #[inline]
547 pub fn copy_creation_attributes(&self) -> Option<CFDictionary<CFString, CFType>> {
548 unsafe {
549 let attributes = CVPixelBufferCopyCreationAttributes(self.as_concrete_TypeRef());
550 if attributes.is_null() {
551 None
552 } else {
553 Some(TCFType::wrap_under_create_rule(attributes))
554 }
555 }
556 }
557}