1use std::ptr::{null, null_mut};
2
3use core_foundation::{
4 array::CFArrayRef,
5 base::{kCFAllocatorDefault, Boolean, CFAllocatorRef, CFType, CFTypeID, TCFType},
6 declare_TCFType,
7 dictionary::{CFDictionary, CFDictionaryRef},
8 impl_CFTypeDescription, impl_TCFType,
9 string::{CFString, CFStringRef},
10};
11use libc::{c_void, size_t};
12
13use crate::{
14 base::CVOptionFlags,
15 buffer::TCVBuffer,
16 image_buffer::{CVImageBufferRef, TCVImageBuffer},
17 r#return::{kCVReturnInvalidArgument, kCVReturnSuccess, CVReturn},
18 OSType,
19};
20
21pub type CVPixelBufferRef = CVImageBufferRef;
22
23#[inline]
24const fn fourcc(code: &[u8; 4]) -> u32 {
25 ((code[0] as u32) << 24) | ((code[1] as u32) << 16) | ((code[2] as u32) << 8) | ((code[3] as u32) << 0)
26}
27
28pub type CVPixelBufferLockFlags = u64;
29
30pub 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;
187
188#[repr(C)]
189pub struct CVPlanarComponentInfo {
190 pub offset: i32,
191 pub rowBytes: u32,
192}
193
194#[repr(C)]
195pub struct CVPlanarPixelBufferInfo {
196 pub componentInfo: [CVPlanarComponentInfo; 1],
197}
198
199#[repr(C)]
200pub struct CVPlanarPixelBufferInfo_YCbCrPlanar {
201 pub componentInfoY: CVPlanarComponentInfo,
202 pub componentInfoCb: CVPlanarComponentInfo,
203 pub componentInfoCr: CVPlanarComponentInfo,
204}
205
206#[repr(C)]
207pub struct CVPlanarPixelBufferInfo_YCbCrBiPlanar {
208 pub componentInfoY: CVPlanarComponentInfo,
209 pub componentInfoCbCr: CVPlanarComponentInfo,
210}
211
212pub type CVPixelBufferReleaseBytesCallback = extern "C" fn(releaseRefCon: *mut c_void, baseAddress: *const *const c_void);
213pub type CVPixelBufferReleasePlanarBytesCallback = extern "C" fn(
214 releaseRefCon: *mut c_void,
215 dataPtr: *const *const c_void,
216 dataSize: size_t,
217 numberOfPlanes: size_t,
218 planeAddresses: *const *const c_void,
219);
220
221extern "C" {
222 pub static kCVPixelBufferPixelFormatTypeKey: CFStringRef;
223 pub static kCVPixelBufferMemoryAllocatorKey: CFStringRef;
224 pub static kCVPixelBufferWidthKey: CFStringRef;
225 pub static kCVPixelBufferHeightKey: CFStringRef;
226 pub static kCVPixelBufferExtendedPixelsLeftKey: CFStringRef;
227 pub static kCVPixelBufferExtendedPixelsTopKey: CFStringRef;
228 pub static kCVPixelBufferExtendedPixelsRightKey: CFStringRef;
229 pub static kCVPixelBufferExtendedPixelsBottomKey: CFStringRef;
230 pub static kCVPixelBufferBytesPerRowAlignmentKey: CFStringRef;
231 pub static kCVPixelBufferCGBitmapContextCompatibilityKey: CFStringRef;
232 pub static kCVPixelBufferCGImageCompatibilityKey: CFStringRef;
233 pub static kCVPixelBufferOpenGLCompatibilityKey: CFStringRef;
234 pub static kCVPixelBufferPlaneAlignmentKey: CFStringRef;
235 pub static kCVPixelBufferIOSurfacePropertiesKey: CFStringRef;
236 #[cfg(target_os = "ios")]
237 pub static kCVPixelBufferOpenGLESCompatibilityKey: CFStringRef;
238 pub static kCVPixelBufferMetalCompatibilityKey: CFStringRef;
239 #[cfg(target_os = "macos")]
240 pub static kCVPixelBufferOpenGLTextureCacheCompatibilityKey: CFStringRef;
241 #[cfg(target_os = "ios")]
242 pub static kCVPixelBufferOpenGLESTextureCacheCompatibilityKey: CFStringRef;
243 pub static kCVPixelBufferVersatileBayerKey_BayerPattern: CFStringRef;
244}
245
246pub const kCVVersatileBayer_BayerPattern_RGGB: u32 = 0;
247pub const kCVVersatileBayer_BayerPattern_GRBG: u32 = 1;
248pub const kCVVersatileBayer_BayerPattern_GBRG: u32 = 2;
249pub const kCVVersatileBayer_BayerPattern_BGGR: u32 = 3;
250
251extern "C" {
252 pub static kCVPixelBufferProResRAWKey_SenselSitingOffsets: CFStringRef;
253 pub static kCVPixelBufferProResRAWKey_BlackLevel: CFStringRef;
254 pub static kCVPixelBufferProResRAWKey_WhiteLevel: CFStringRef;
255 pub static kCVPixelBufferProResRAWKey_WhiteBalanceCCT: CFStringRef;
256 pub static kCVPixelBufferProResRAWKey_WhiteBalanceRedFactor: CFStringRef;
257 pub static kCVPixelBufferProResRAWKey_WhiteBalanceBlueFactor: CFStringRef;
258 pub static kCVPixelBufferProResRAWKey_ColorMatrix: CFStringRef;
259 pub static kCVPixelBufferProResRAWKey_GainFactor: CFStringRef;
260 pub static kCVPixelBufferProResRAWKey_RecommendedCrop: CFStringRef;
261 pub static kCVPixelBufferProResRAWKey_MetadataExtension: CFStringRef;
262}
263
264extern "C" {
265 pub fn CVPixelBufferGetTypeID() -> CFTypeID;
266 pub fn CVPixelBufferRetain(texture: CVPixelBufferRef) -> CVPixelBufferRef;
267 pub fn CVPixelBufferRelease(texture: CVPixelBufferRef);
268 pub fn CVPixelBufferCreateResolvedAttributesDictionary(
269 allocator: CFAllocatorRef,
270 attributes: CFArrayRef,
271 resolvedDictionaryOut: *mut CFDictionaryRef,
272 ) -> CVReturn;
273 pub fn CVPixelBufferCreate(
274 allocator: CFAllocatorRef,
275 width: size_t,
276 height: size_t,
277 pixelFormatType: OSType,
278 pixelBufferAttributes: CFDictionaryRef,
279 pixelBufferOut: *mut CVPixelBufferRef,
280 ) -> CVReturn;
281 pub fn CVPixelBufferCreateWithBytes(
282 allocator: CFAllocatorRef,
283 width: size_t,
284 height: size_t,
285 pixelFormatType: OSType,
286 baseAddress: *mut c_void,
287 bytesPerRow: size_t,
288 releaseCallback: CVPixelBufferReleaseBytesCallback,
289 releaseRefCon: *mut c_void,
290 pixelBufferAttributes: CFDictionaryRef,
291 pixelBufferOut: *mut CVPixelBufferRef,
292 ) -> CVReturn;
293 pub fn CVPixelBufferCreateWithPlanarBytes(
294 allocator: CFAllocatorRef,
295 width: size_t,
296 height: size_t,
297 pixelFormatType: OSType,
298 dataPtr: *mut c_void,
299 dataSize: size_t,
300 numberOfPlanes: size_t,
301 planeBaseAddress: *const *mut c_void,
302 planeWidth: *const size_t,
303 planeHeight: *const size_t,
304 planeBytesPerRow: *const size_t,
305 releaseCallback: CVPixelBufferReleasePlanarBytesCallback,
306 releaseRefCon: *mut c_void,
307 pixelBufferAttributes: CFDictionaryRef,
308 pixelBufferOut: *mut CVPixelBufferRef,
309 ) -> CVReturn;
310 pub fn CVPixelBufferLockBaseAddress(pixelBuffer: CVPixelBufferRef, lockFlags: CVOptionFlags) -> CVReturn;
311 pub fn CVPixelBufferUnlockBaseAddress(pixelBuffer: CVPixelBufferRef, unlockFlags: CVOptionFlags) -> CVReturn;
312 pub fn CVPixelBufferGetWidth(pixelBuffer: CVPixelBufferRef) -> size_t;
313 pub fn CVPixelBufferGetHeight(pixelBuffer: CVPixelBufferRef) -> size_t;
314 pub fn CVPixelBufferGetPixelFormatType(pixelBuffer: CVPixelBufferRef) -> OSType;
315
316 pub fn CVPixelBufferGetBaseAddress(pixelBuffer: CVPixelBufferRef) -> *mut c_void;
317 pub fn CVPixelBufferGetBytesPerRow(pixelBuffer: CVPixelBufferRef) -> size_t;
318 pub fn CVPixelBufferGetDataSize(pixelBuffer: CVPixelBufferRef) -> size_t;
319 pub fn CVPixelBufferIsPlanar(pixelBuffer: CVPixelBufferRef) -> Boolean;
320 pub fn CVPixelBufferGetPlaneCount(pixelBuffer: CVPixelBufferRef) -> size_t;
321 pub fn CVPixelBufferGetWidthOfPlane(pixelBuffer: CVPixelBufferRef, planeIndex: size_t) -> size_t;
322 pub fn CVPixelBufferGetHeightOfPlane(pixelBuffer: CVPixelBufferRef, planeIndex: size_t) -> size_t;
323 pub fn CVPixelBufferGetBaseAddressOfPlane(pixelBuffer: CVPixelBufferRef, planeIndex: size_t) -> *mut c_void;
324 pub fn CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer: CVPixelBufferRef, planeIndex: size_t) -> size_t;
325 pub fn CVPixelBufferGetExtendedPixels(
326 pixelBuffer: CVPixelBufferRef,
327 extraColumnsOnLeft: *const size_t,
328 extraColumnsOnRight: *const size_t,
329 extraRowsOnTop: *const size_t,
330 extraRowsOnBottom: *const size_t,
331 );
332 pub fn CVPixelBufferFillExtendedPixels(pixelBuffer: CVPixelBufferRef) -> CVReturn;
333 pub fn CVPixelBufferCopyCreationAttributes(pixelBuffer: CVPixelBufferRef) -> CFDictionaryRef;
334}
335
336pub enum CVPixelBufferKeys {
337 PixelFormatType,
338 MemoryAllocator,
339 Width,
340 Height,
341 ExtendedPixelsLeft,
342 ExtendedPixelsTop,
343 ExtendedPixelsRight,
344 ExtendedPixelsBottom,
345 BytesPerRowAlignment,
346 CGBitmapContextCompatibility,
347 CGImageCompatibility,
348 OpenGLCompatibility,
349 PlaneAlignment,
350 IOSurfaceProperties,
351 #[cfg(target_os = "ios")]
352 OpenGLESCompatibility,
353 MetalCompatibility,
354 #[cfg(target_os = "macos")]
355 OpenGLTextureCacheCompatibility,
356 #[cfg(target_os = "ios")]
357 OpenGLESTextureCacheCompatibility,
358 VersatileBayerKey_BayerPattern,
359}
360
361impl From<CVPixelBufferKeys> for CFStringRef {
362 fn from(key: CVPixelBufferKeys) -> Self {
363 unsafe {
364 match key {
365 CVPixelBufferKeys::PixelFormatType => kCVPixelBufferPixelFormatTypeKey,
366 CVPixelBufferKeys::MemoryAllocator => kCVPixelBufferMemoryAllocatorKey,
367 CVPixelBufferKeys::Width => kCVPixelBufferWidthKey,
368 CVPixelBufferKeys::Height => kCVPixelBufferHeightKey,
369 CVPixelBufferKeys::ExtendedPixelsLeft => kCVPixelBufferExtendedPixelsLeftKey,
370 CVPixelBufferKeys::ExtendedPixelsTop => kCVPixelBufferExtendedPixelsTopKey,
371 CVPixelBufferKeys::ExtendedPixelsRight => kCVPixelBufferExtendedPixelsRightKey,
372 CVPixelBufferKeys::ExtendedPixelsBottom => kCVPixelBufferExtendedPixelsBottomKey,
373 CVPixelBufferKeys::BytesPerRowAlignment => kCVPixelBufferBytesPerRowAlignmentKey,
374 CVPixelBufferKeys::CGBitmapContextCompatibility => kCVPixelBufferCGBitmapContextCompatibilityKey,
375 CVPixelBufferKeys::CGImageCompatibility => kCVPixelBufferCGImageCompatibilityKey,
376 CVPixelBufferKeys::OpenGLCompatibility => kCVPixelBufferOpenGLCompatibilityKey,
377 CVPixelBufferKeys::PlaneAlignment => kCVPixelBufferPlaneAlignmentKey,
378 CVPixelBufferKeys::IOSurfaceProperties => kCVPixelBufferIOSurfacePropertiesKey,
379 #[cfg(target_os = "ios")]
380 CVPixelBufferKeys::OpenGLESCompatibility => kCVPixelBufferOpenGLESCompatibilityKey,
381 CVPixelBufferKeys::MetalCompatibility => kCVPixelBufferMetalCompatibilityKey,
382 #[cfg(target_os = "macos")]
383 CVPixelBufferKeys::OpenGLTextureCacheCompatibility => kCVPixelBufferOpenGLTextureCacheCompatibilityKey,
384 #[cfg(target_os = "ios")]
385 CVPixelBufferKeys::OpenGLESTextureCacheCompatibility => kCVPixelBufferOpenGLESTextureCacheCompatibilityKey,
386 CVPixelBufferKeys::VersatileBayerKey_BayerPattern => kCVPixelBufferVersatileBayerKey_BayerPattern,
387 }
388 }
389 }
390}
391
392impl From<CVPixelBufferKeys> for CFString {
393 fn from(key: CVPixelBufferKeys) -> Self {
394 unsafe { CFString::wrap_under_get_rule(CFStringRef::from(key)) }
395 }
396}
397
398declare_TCFType!(CVPixelBuffer, CVPixelBufferRef);
399impl_TCFType!(CVPixelBuffer, CVPixelBufferRef, CVPixelBufferGetTypeID);
400impl_CFTypeDescription!(CVPixelBuffer);
401
402impl TCVBuffer for CVPixelBuffer {}
403impl TCVImageBuffer for CVPixelBuffer {}
404
405impl CVPixelBuffer {
406 #[inline]
407 pub fn new(
408 pixel_format: OSType,
409 width: usize,
410 height: usize,
411 options: Option<&CFDictionary<CFString, CFType>>,
412 ) -> Result<CVPixelBuffer, CVReturn> {
413 let mut pixel_buffer: CVPixelBufferRef = null_mut();
414 let status = unsafe {
415 CVPixelBufferCreate(
416 kCFAllocatorDefault,
417 width,
418 height,
419 pixel_format,
420 options.map_or(null(), |options| options.as_concrete_TypeRef()),
421 &mut pixel_buffer,
422 )
423 };
424 if status == kCVReturnSuccess {
425 Ok(unsafe { TCFType::wrap_under_create_rule(pixel_buffer) })
426 } else {
427 Err(status)
428 }
429 }
430
431 #[inline]
432 pub unsafe fn new_with_bytes(
433 pixel_format: OSType,
434 width: usize,
435 height: usize,
436 base_address: *mut c_void,
437 bytes_per_row: usize,
438 release_callback: CVPixelBufferReleaseBytesCallback,
439 release_ref_con: *mut c_void,
440 options: Option<&CFDictionary<CFString, CFType>>,
441 ) -> Result<CVPixelBuffer, CVReturn> {
442 let mut pixel_buffer: CVPixelBufferRef = null_mut();
443 let status = unsafe {
444 CVPixelBufferCreateWithBytes(
445 kCFAllocatorDefault,
446 width,
447 height,
448 pixel_format,
449 base_address,
450 bytes_per_row,
451 release_callback,
452 release_ref_con,
453 options.map_or(null(), |options| options.as_concrete_TypeRef()),
454 &mut pixel_buffer,
455 )
456 };
457 if status == kCVReturnSuccess {
458 Ok(unsafe { TCFType::wrap_under_create_rule(pixel_buffer) })
459 } else {
460 Err(status)
461 }
462 }
463
464 #[inline]
465 pub unsafe fn new_with_planar_bytes(
466 pixel_format: OSType,
467 width: usize,
468 height: usize,
469 data_ptr: *mut c_void,
470 data_size: usize,
471 number_of_planes: usize,
472 plane_base_address: Vec<*mut c_void>,
473 plane_width: Vec<usize>,
474 plane_height: Vec<usize>,
475 plane_bytes_per_row: Vec<usize>,
476 release_callback: CVPixelBufferReleasePlanarBytesCallback,
477 release_ref_con: *mut c_void,
478 options: Option<&CFDictionary<CFString, CFType>>,
479 ) -> Result<CVPixelBuffer, CVReturn> {
480 if plane_base_address.len() != number_of_planes ||
481 plane_width.len() != number_of_planes ||
482 plane_height.len() != number_of_planes ||
483 plane_bytes_per_row.len() != number_of_planes
484 {
485 return Err(kCVReturnInvalidArgument);
486 }
487 let mut pixel_buffer: CVPixelBufferRef = null_mut();
488 let status = unsafe {
489 CVPixelBufferCreateWithPlanarBytes(
490 kCFAllocatorDefault,
491 width,
492 height,
493 pixel_format,
494 data_ptr,
495 data_size,
496 number_of_planes,
497 plane_base_address.as_ptr(),
498 plane_width.as_ptr(),
499 plane_height.as_ptr(),
500 plane_bytes_per_row.as_ptr(),
501 release_callback,
502 release_ref_con,
503 options.map_or(null(), |options| options.as_concrete_TypeRef()),
504 &mut pixel_buffer,
505 )
506 };
507 if status == kCVReturnSuccess {
508 Ok(unsafe { TCFType::wrap_under_create_rule(pixel_buffer) })
509 } else {
510 Err(status)
511 }
512 }
513
514 #[inline]
515 pub fn lock_base_address(&self, options: CVPixelBufferLockFlags) -> CVReturn {
516 unsafe { CVPixelBufferLockBaseAddress(self.as_concrete_TypeRef(), options) }
517 }
518
519 #[inline]
520 pub fn unlock_base_address(&self, options: CVPixelBufferLockFlags) -> CVReturn {
521 unsafe { CVPixelBufferUnlockBaseAddress(self.as_concrete_TypeRef(), options) }
522 }
523
524 #[inline]
525 pub fn get_width(&self) -> usize {
526 unsafe { CVPixelBufferGetWidth(self.as_concrete_TypeRef()) }
527 }
528
529 #[inline]
530 pub fn get_height(&self) -> usize {
531 unsafe { CVPixelBufferGetHeight(self.as_concrete_TypeRef()) }
532 }
533
534 #[inline]
535 pub fn get_pixel_format(&self) -> OSType {
536 unsafe { CVPixelBufferGetPixelFormatType(self.as_concrete_TypeRef()) }
537 }
538
539 #[inline]
540 pub unsafe fn get_base_address(&self) -> *mut c_void {
541 unsafe { CVPixelBufferGetBaseAddress(self.as_concrete_TypeRef()) }
542 }
543
544 #[inline]
545 pub fn get_bytes_per_row(&self) -> usize {
546 unsafe { CVPixelBufferGetBytesPerRow(self.as_concrete_TypeRef()) }
547 }
548
549 #[inline]
550 pub fn get_data_size(&self) -> usize {
551 unsafe { CVPixelBufferGetDataSize(self.as_concrete_TypeRef()) }
552 }
553
554 #[inline]
555 pub fn is_planar(&self) -> bool {
556 unsafe { CVPixelBufferIsPlanar(self.as_concrete_TypeRef()) != 0 }
557 }
558
559 #[inline]
560 pub fn get_plane_count(&self) -> usize {
561 unsafe { CVPixelBufferGetPlaneCount(self.as_concrete_TypeRef()) }
562 }
563
564 #[inline]
565 pub fn get_width_of_plane(&self, plane_index: usize) -> usize {
566 unsafe { CVPixelBufferGetWidthOfPlane(self.as_concrete_TypeRef(), plane_index) }
567 }
568
569 #[inline]
570 pub fn get_height_of_plane(&self, plane_index: usize) -> usize {
571 unsafe { CVPixelBufferGetHeightOfPlane(self.as_concrete_TypeRef(), plane_index) }
572 }
573
574 #[inline]
575 pub unsafe fn get_base_address_of_plane(&self, plane_index: usize) -> *mut c_void {
576 unsafe { CVPixelBufferGetBaseAddressOfPlane(self.as_concrete_TypeRef(), plane_index) }
577 }
578
579 #[inline]
580 pub fn get_bytes_per_row_of_plane(&self, plane_index: usize) -> usize {
581 unsafe { CVPixelBufferGetBytesPerRowOfPlane(self.as_concrete_TypeRef(), plane_index) }
582 }
583
584 #[inline]
585 pub fn get_extended_pixels(&self) -> (usize, usize, usize, usize) {
586 unsafe {
587 let mut left = 0;
588 let mut right = 0;
589 let mut top = 0;
590 let mut bottom = 0;
591 CVPixelBufferGetExtendedPixels(self.as_concrete_TypeRef(), &mut left, &mut right, &mut top, &mut bottom);
592 (left, right, top, bottom)
593 }
594 }
595
596 #[inline]
597 pub fn fill_extended_pixels(&self) -> CVReturn {
598 unsafe { CVPixelBufferFillExtendedPixels(self.as_concrete_TypeRef()) }
599 }
600
601 #[inline]
602 pub fn copy_creation_attributes(&self) -> Option<CFDictionary<CFString, CFType>> {
603 unsafe {
604 let attributes = CVPixelBufferCopyCreationAttributes(self.as_concrete_TypeRef());
605 if attributes.is_null() {
606 None
607 } else {
608 Some(TCFType::wrap_under_create_rule(attributes))
609 }
610 }
611 }
612}