use super::{CMBlockBuffer, CMFormatDescription, CMTime};
use crate::ffi;
use std::fmt;
pub struct CMSampleBuffer(*mut std::ffi::c_void);
unsafe impl Send for CMSampleBuffer {}
unsafe impl Sync for CMSampleBuffer {}
impl CMSampleBuffer {
#[must_use]
pub const unsafe fn from_ptr(ptr: *mut std::ffi::c_void) -> Self {
Self(ptr)
}
#[must_use]
pub fn from_raw(ptr: *mut std::ffi::c_void) -> Option<Self> {
if ptr.is_null() {
None
} else {
Some(Self(ptr))
}
}
#[must_use]
pub unsafe fn from_raw_retained(ptr: *mut std::ffi::c_void) -> Option<Self> {
if ptr.is_null() {
None
} else {
let retained = unsafe { ffi::cm_sample_buffer_retain(ptr) };
Self::from_raw(retained)
}
}
#[must_use]
pub const fn as_ptr(&self) -> *mut std::ffi::c_void {
self.0
}
#[must_use]
pub fn is_valid(&self) -> bool {
unsafe { ffi::cm_sample_buffer_is_valid(self.0) }
}
#[must_use]
pub fn data_is_ready(&self) -> bool {
unsafe { ffi::cm_sample_buffer_data_is_ready(self.0) }
}
#[must_use]
pub fn num_samples(&self) -> i64 {
unsafe { ffi::cm_sample_buffer_get_num_samples(self.0) }
}
#[must_use]
pub fn presentation_timestamp(&self) -> CMTime {
let mut t = CMTime::INVALID;
unsafe {
ffi::cm_sample_buffer_get_presentation_timestamp(
self.0,
&mut t.value,
&mut t.timescale,
&mut t.flags,
&mut t.epoch,
);
}
t
}
#[must_use]
pub fn decode_timestamp(&self) -> CMTime {
let mut t = CMTime::INVALID;
unsafe {
ffi::cm_sample_buffer_get_decode_timestamp(
self.0,
&mut t.value,
&mut t.timescale,
&mut t.flags,
&mut t.epoch,
);
}
t
}
#[must_use]
pub fn duration(&self) -> CMTime {
let mut t = CMTime::INVALID;
unsafe {
ffi::cm_sample_buffer_get_duration(
self.0,
&mut t.value,
&mut t.timescale,
&mut t.flags,
&mut t.epoch,
);
}
t
}
#[must_use]
pub fn data_buffer(&self) -> Option<CMBlockBuffer> {
let ptr = unsafe { ffi::cm_sample_buffer_get_data_buffer(self.0) };
if ptr.is_null() {
None
} else {
let retained = unsafe { ffi::cm_block_buffer_retain(ptr) };
CMBlockBuffer::from_raw(retained)
}
}
#[must_use]
pub fn format_description(&self) -> Option<CMFormatDescription> {
let ptr = unsafe { ffi::cm_sample_buffer_get_format_description(self.0) };
if ptr.is_null() {
None
} else {
let retained = unsafe { ffi::cm_format_description_retain(ptr) };
CMFormatDescription::from_raw(retained)
}
}
#[must_use]
pub fn image_buffer_ptr(&self) -> *mut std::ffi::c_void {
unsafe { ffi::cm_sample_buffer_get_image_buffer(self.0) }
}
}
impl Clone for CMSampleBuffer {
fn clone(&self) -> Self {
let retained = unsafe { ffi::cm_sample_buffer_retain(self.0) };
Self(retained)
}
}
impl Drop for CMSampleBuffer {
fn drop(&mut self) {
if !self.0.is_null() {
unsafe { ffi::cm_sample_buffer_release(self.0) };
}
}
}
impl PartialEq for CMSampleBuffer {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl Eq for CMSampleBuffer {}
impl std::hash::Hash for CMSampleBuffer {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
unsafe {
let h = ffi::cm_sample_buffer_hash(self.0);
h.hash(state);
}
}
}
impl fmt::Debug for CMSampleBuffer {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("CMSampleBuffer")
.field("ptr", &self.0)
.field("num_samples", &self.num_samples())
.field("pts", &self.presentation_timestamp())
.finish()
}
}