use apple_cf::cm::CMSampleBuffer;
use apple_cf::cv::CVPixelBuffer;
use crate::error::VTError;
use crate::ffi;
pub struct TaggedBufferGroup {
inner: ffi::CMTaggedBufferGroupRef,
}
unsafe impl Send for TaggedBufferGroup {}
unsafe impl Sync for TaggedBufferGroup {}
impl TaggedBufferGroup {
#[allow(clippy::missing_errors_doc)]
pub fn type_id() -> Result<usize, VTError> {
let type_id = ffi::dynamic::CMTaggedBufferGroupGetTypeID()?;
Ok(unsafe { type_id() })
}
#[must_use]
pub unsafe fn from_raw(ptr: ffi::CMTaggedBufferGroupRef) -> Option<Self> {
if ptr.is_null() {
None
} else {
Some(Self { inner: ptr })
}
}
#[must_use]
pub unsafe fn from_raw_retained(ptr: ffi::CMTaggedBufferGroupRef) -> Option<Self> {
if ptr.is_null() {
None
} else {
unsafe { ffi::CFRetain(ptr.cast()) };
Self::from_raw(ptr)
}
}
#[must_use]
pub const fn as_ptr(&self) -> ffi::CMTaggedBufferGroupRef {
self.inner
}
#[must_use]
pub fn len(&self) -> usize {
ffi::dynamic::CMTaggedBufferGroupGetCount().map_or(0, |count| {
usize::try_from(unsafe { count(self.inner) }).unwrap_or(0)
})
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[must_use]
pub fn pixel_buffer_at(&self, index: usize) -> Option<CVPixelBuffer> {
if index >= self.len() {
return None;
}
let index = isize::try_from(index).ok()?;
let pixel_buffer_at = ffi::dynamic::CMTaggedBufferGroupGetCVPixelBufferAtIndex().ok()?;
let ptr = unsafe { pixel_buffer_at(self.inner, index) };
if ptr.is_null() {
None
} else {
unsafe { CVPixelBuffer::from_raw_borrowed(ptr.cast()) }
}
}
#[must_use]
pub fn sample_buffer_at(&self, index: usize) -> Option<CMSampleBuffer> {
if index >= self.len() {
return None;
}
let index = isize::try_from(index).ok()?;
let sample_buffer_at = ffi::dynamic::CMTaggedBufferGroupGetCMSampleBufferAtIndex().ok()?;
let ptr = unsafe { sample_buffer_at(self.inner, index) };
unsafe { CMSampleBuffer::from_raw_borrowed(ptr.cast()) }
}
}
impl Clone for TaggedBufferGroup {
fn clone(&self) -> Self {
unsafe { Self::from_raw_retained(self.inner) }
.expect("tagged buffer group pointer must be non-null")
}
}
crate::utils::retained::vt_retained!(TaggedBufferGroup, field = inner, release = ffi::CFRelease);
impl core::fmt::Debug for TaggedBufferGroup {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("TaggedBufferGroup")
.field("ptr", &self.inner)
.field("len", &self.len())
.finish()
}
}