#![cfg(target_os = "macos")]
#![cfg(feature = "iosurface")]
use std::os::raw::c_void;
use std::error::Error;
use std::fmt::Display;
use crate::{platform::{macos::{frame::MacosVideoFrame, objc_wrap::IOSurfaceRef}, platform_impl::objc_wrap::{IOSurfaceDecrementUseCount, IOSurfaceIncrementUseCount}}, prelude::VideoFrame};
pub struct IoSurface(IOSurfaceRef);
impl IoSurface {
pub fn get_raw(&self) -> *const c_void {
self.0
}
pub(crate) fn from_ref_unretained(r: IOSurfaceRef) -> Self {
unsafe { IOSurfaceIncrementUseCount(r); }
IoSurface(r)
}
}
impl Clone for IoSurface {
fn clone(&self) -> Self {
unsafe { IOSurfaceIncrementUseCount(self.0); }
IoSurface(self.0)
}
}
impl Drop for IoSurface {
fn drop(&mut self) {
unsafe { IOSurfaceDecrementUseCount(self.0); }
}
}
pub trait MacosIoSurfaceVideoFrameExt {
fn get_iosurface(&self) -> Result<IoSurface, GetIoSurfaceError>;
}
#[derive(Debug)]
pub enum GetIoSurfaceError{
NoImageBuffer,
NoIoSurface
}
impl Display for GetIoSurfaceError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::NoImageBuffer => f.write_str("GetIoSurfaceError::NoImageBuffer"),
Self::NoIoSurface => f.write_str("GetIoSurfaceError::NoIoSurface"),
}
}
}
impl Error for GetIoSurfaceError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
None
}
fn description(&self) -> &str {
"description() is deprecated; use Display"
}
fn cause(&self) -> Option<&dyn Error> {
self.source()
}
}
impl MacosIoSurfaceVideoFrameExt for VideoFrame {
fn get_iosurface(&self) -> Result<IoSurface, GetIoSurfaceError> {
match &self.impl_video_frame {
MacosVideoFrame::SCStream(frame) => {
match frame.sample_buffer.get_image_buffer() {
Some(image_buffer) => {
match image_buffer.get_iosurface_ptr() {
Some(ptr) => {
Ok(IoSurface::from_ref_unretained(ptr))
},
None => Err(GetIoSurfaceError::NoIoSurface)
}
},
None => Err(GetIoSurfaceError::NoImageBuffer)
}
},
MacosVideoFrame::CGDisplayStream(frame) => {
Ok(IoSurface::from_ref_unretained(frame.io_surface.0))
}
}
}
}