Switch fully to Rust Livekit (redux) (#27126)
Swift bindings BEGONE Release Notes: - Switched from using the Swift LiveKit bindings, to the Rust bindings, fixing https://github.com/zed-industries/zed/issues/9396, a crash when leaving a collaboration session, and making Zed easier to build. --------- Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com> Co-authored-by: Michael Sloan <michael@zed.dev>
This commit is contained in:
parent
c8fb95cd1b
commit
8a307e7b89
68 changed files with 2393 additions and 7579 deletions
|
@ -20,6 +20,7 @@ core-foundation.workspace = true
|
|||
ctor.workspace = true
|
||||
foreign-types = "0.5"
|
||||
metal.workspace = true
|
||||
core-video.workspace = true
|
||||
objc = "0.2"
|
||||
|
||||
[build-dependencies]
|
||||
|
|
|
@ -3,213 +3,6 @@
|
|||
|
||||
mod bindings;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
use core_foundation::{
|
||||
base::{CFTypeID, TCFType},
|
||||
declare_TCFType, impl_CFTypeDescription, impl_TCFType,
|
||||
};
|
||||
#[cfg(target_os = "macos")]
|
||||
use std::ffi::c_void;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod io_surface {
|
||||
use super::*;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __IOSurface(c_void);
|
||||
// The ref type must be a pointer to the underlying struct.
|
||||
pub type IOSurfaceRef = *const __IOSurface;
|
||||
|
||||
declare_TCFType!(IOSurface, IOSurfaceRef);
|
||||
impl_TCFType!(IOSurface, IOSurfaceRef, IOSurfaceGetTypeID);
|
||||
impl_CFTypeDescription!(IOSurface);
|
||||
|
||||
#[link(name = "IOSurface", kind = "framework")]
|
||||
extern "C" {
|
||||
fn IOSurfaceGetTypeID() -> CFTypeID;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod core_video {
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use super::*;
|
||||
pub use crate::bindings::{
|
||||
kCVPixelFormatType_32BGRA, kCVPixelFormatType_420YpCbCr8BiPlanarFullRange,
|
||||
kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, kCVPixelFormatType_420YpCbCr8Planar,
|
||||
};
|
||||
use crate::bindings::{kCVReturnSuccess, CVReturn, OSType};
|
||||
use anyhow::{anyhow, Result};
|
||||
use core_foundation::{
|
||||
base::kCFAllocatorDefault, dictionary::CFDictionaryRef, mach_port::CFAllocatorRef,
|
||||
};
|
||||
use foreign_types::ForeignTypeRef;
|
||||
use io_surface::{IOSurface, IOSurfaceRef};
|
||||
use metal::{MTLDevice, MTLPixelFormat};
|
||||
use std::ptr;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CVImageBuffer(c_void);
|
||||
// The ref type must be a pointer to the underlying struct.
|
||||
pub type CVImageBufferRef = *const __CVImageBuffer;
|
||||
|
||||
declare_TCFType!(CVImageBuffer, CVImageBufferRef);
|
||||
impl_TCFType!(CVImageBuffer, CVImageBufferRef, CVImageBufferGetTypeID);
|
||||
impl_CFTypeDescription!(CVImageBuffer);
|
||||
|
||||
impl CVImageBuffer {
|
||||
pub fn io_surface(&self) -> IOSurface {
|
||||
unsafe {
|
||||
IOSurface::wrap_under_get_rule(CVPixelBufferGetIOSurface(
|
||||
self.as_concrete_TypeRef(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn width(&self) -> usize {
|
||||
unsafe { CVPixelBufferGetWidth(self.as_concrete_TypeRef()) }
|
||||
}
|
||||
|
||||
pub fn height(&self) -> usize {
|
||||
unsafe { CVPixelBufferGetHeight(self.as_concrete_TypeRef()) }
|
||||
}
|
||||
|
||||
pub fn plane_width(&self, plane: usize) -> usize {
|
||||
unsafe { CVPixelBufferGetWidthOfPlane(self.as_concrete_TypeRef(), plane) }
|
||||
}
|
||||
|
||||
pub fn plane_height(&self, plane: usize) -> usize {
|
||||
unsafe { CVPixelBufferGetHeightOfPlane(self.as_concrete_TypeRef(), plane) }
|
||||
}
|
||||
|
||||
pub fn pixel_format_type(&self) -> OSType {
|
||||
unsafe { CVPixelBufferGetPixelFormatType(self.as_concrete_TypeRef()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[link(name = "CoreVideo", kind = "framework")]
|
||||
extern "C" {
|
||||
fn CVImageBufferGetTypeID() -> CFTypeID;
|
||||
fn CVPixelBufferGetIOSurface(buffer: CVImageBufferRef) -> IOSurfaceRef;
|
||||
fn CVPixelBufferGetWidth(buffer: CVImageBufferRef) -> usize;
|
||||
fn CVPixelBufferGetHeight(buffer: CVImageBufferRef) -> usize;
|
||||
fn CVPixelBufferGetWidthOfPlane(buffer: CVImageBufferRef, plane: usize) -> usize;
|
||||
fn CVPixelBufferGetHeightOfPlane(buffer: CVImageBufferRef, plane: usize) -> usize;
|
||||
fn CVPixelBufferGetPixelFormatType(buffer: CVImageBufferRef) -> OSType;
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CVMetalTextureCache(c_void);
|
||||
pub type CVMetalTextureCacheRef = *const __CVMetalTextureCache;
|
||||
|
||||
declare_TCFType!(CVMetalTextureCache, CVMetalTextureCacheRef);
|
||||
impl_TCFType!(
|
||||
CVMetalTextureCache,
|
||||
CVMetalTextureCacheRef,
|
||||
CVMetalTextureCacheGetTypeID
|
||||
);
|
||||
impl_CFTypeDescription!(CVMetalTextureCache);
|
||||
|
||||
impl CVMetalTextureCache {
|
||||
/// # Safety
|
||||
///
|
||||
/// metal_device must be valid according to CVMetalTextureCacheCreate
|
||||
pub unsafe fn new(metal_device: *mut MTLDevice) -> Result<Self> {
|
||||
let mut this = ptr::null();
|
||||
let result = CVMetalTextureCacheCreate(
|
||||
kCFAllocatorDefault,
|
||||
ptr::null(),
|
||||
metal_device,
|
||||
ptr::null(),
|
||||
&mut this,
|
||||
);
|
||||
if result == kCVReturnSuccess {
|
||||
Ok(CVMetalTextureCache::wrap_under_create_rule(this))
|
||||
} else {
|
||||
Err(anyhow!("could not create texture cache, code: {}", result))
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// The arguments to this function must be valid according to CVMetalTextureCacheCreateTextureFromImage
|
||||
pub unsafe fn create_texture_from_image(
|
||||
&self,
|
||||
source: CVImageBufferRef,
|
||||
texture_attributes: CFDictionaryRef,
|
||||
pixel_format: MTLPixelFormat,
|
||||
width: usize,
|
||||
height: usize,
|
||||
plane_index: usize,
|
||||
) -> Result<CVMetalTexture> {
|
||||
let mut this = ptr::null();
|
||||
let result = CVMetalTextureCacheCreateTextureFromImage(
|
||||
kCFAllocatorDefault,
|
||||
self.as_concrete_TypeRef(),
|
||||
source,
|
||||
texture_attributes,
|
||||
pixel_format,
|
||||
width,
|
||||
height,
|
||||
plane_index,
|
||||
&mut this,
|
||||
);
|
||||
if result == kCVReturnSuccess {
|
||||
Ok(CVMetalTexture::wrap_under_create_rule(this))
|
||||
} else {
|
||||
Err(anyhow!("could not create texture, code: {}", result))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[link(name = "CoreVideo", kind = "framework")]
|
||||
extern "C" {
|
||||
fn CVMetalTextureCacheGetTypeID() -> CFTypeID;
|
||||
fn CVMetalTextureCacheCreate(
|
||||
allocator: CFAllocatorRef,
|
||||
cache_attributes: CFDictionaryRef,
|
||||
metal_device: *const MTLDevice,
|
||||
texture_attributes: CFDictionaryRef,
|
||||
cache_out: *mut CVMetalTextureCacheRef,
|
||||
) -> CVReturn;
|
||||
fn CVMetalTextureCacheCreateTextureFromImage(
|
||||
allocator: CFAllocatorRef,
|
||||
texture_cache: CVMetalTextureCacheRef,
|
||||
source_image: CVImageBufferRef,
|
||||
texture_attributes: CFDictionaryRef,
|
||||
pixel_format: MTLPixelFormat,
|
||||
width: usize,
|
||||
height: usize,
|
||||
plane_index: usize,
|
||||
texture_out: *mut CVMetalTextureRef,
|
||||
) -> CVReturn;
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CVMetalTexture(c_void);
|
||||
pub type CVMetalTextureRef = *const __CVMetalTexture;
|
||||
|
||||
declare_TCFType!(CVMetalTexture, CVMetalTextureRef);
|
||||
impl_TCFType!(CVMetalTexture, CVMetalTextureRef, CVMetalTextureGetTypeID);
|
||||
impl_CFTypeDescription!(CVMetalTexture);
|
||||
|
||||
impl CVMetalTexture {
|
||||
pub fn as_texture_ref(&self) -> &metal::TextureRef {
|
||||
unsafe {
|
||||
let texture = CVMetalTextureGetTexture(self.as_concrete_TypeRef());
|
||||
metal::TextureRef::from_ptr(texture as *mut _)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[link(name = "CoreVideo", kind = "framework")]
|
||||
extern "C" {
|
||||
fn CVMetalTextureGetTypeID() -> CFTypeID;
|
||||
fn CVMetalTextureGetTexture(texture: CVMetalTextureRef) -> *mut c_void;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod core_media {
|
||||
#![allow(non_snake_case)]
|
||||
|
@ -218,7 +11,6 @@ pub mod core_media {
|
|||
kCMSampleAttachmentKey_NotSync, kCMTimeInvalid, kCMVideoCodecType_H264, CMItemIndex,
|
||||
CMSampleTimingInfo, CMTime, CMTimeMake, CMVideoCodecType,
|
||||
};
|
||||
use crate::core_video::{CVImageBuffer, CVImageBufferRef};
|
||||
use anyhow::{anyhow, Result};
|
||||
use core_foundation::{
|
||||
array::{CFArray, CFArrayRef},
|
||||
|
@ -228,6 +20,7 @@ pub mod core_media {
|
|||
impl_CFTypeDescription, impl_TCFType,
|
||||
string::CFString,
|
||||
};
|
||||
use core_video::image_buffer::{CVImageBuffer, CVImageBufferRef};
|
||||
use std::{ffi::c_void, ptr};
|
||||
|
||||
#[repr(C)]
|
||||
|
@ -422,129 +215,138 @@ pub mod core_media {
|
|||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod video_toolbox {
|
||||
pub mod core_video {
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
core_media::{CMSampleBufferRef, CMTime, CMVideoCodecType},
|
||||
core_video::CVImageBufferRef,
|
||||
#[cfg(target_os = "macos")]
|
||||
use core_foundation::{
|
||||
base::{CFTypeID, TCFType},
|
||||
declare_TCFType, impl_CFTypeDescription, impl_TCFType,
|
||||
};
|
||||
#[cfg(target_os = "macos")]
|
||||
use std::ffi::c_void;
|
||||
|
||||
pub use crate::bindings::{
|
||||
kCVPixelFormatType_32BGRA, kCVPixelFormatType_420YpCbCr8BiPlanarFullRange,
|
||||
kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, kCVPixelFormatType_420YpCbCr8Planar,
|
||||
};
|
||||
use crate::bindings::{kCVReturnSuccess, CVReturn};
|
||||
use anyhow::{anyhow, Result};
|
||||
pub use bindings::VTEncodeInfoFlags;
|
||||
use core_foundation::{base::OSStatus, dictionary::CFDictionaryRef, mach_port::CFAllocatorRef};
|
||||
use core_foundation::{
|
||||
base::kCFAllocatorDefault, dictionary::CFDictionaryRef, mach_port::CFAllocatorRef,
|
||||
};
|
||||
use foreign_types::ForeignTypeRef;
|
||||
|
||||
use metal::{MTLDevice, MTLPixelFormat};
|
||||
use std::ptr;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __VTCompressionSession(c_void);
|
||||
// The ref type must be a pointer to the underlying struct.
|
||||
pub type VTCompressionSessionRef = *const __VTCompressionSession;
|
||||
pub struct __CVMetalTextureCache(c_void);
|
||||
pub type CVMetalTextureCacheRef = *const __CVMetalTextureCache;
|
||||
|
||||
declare_TCFType!(VTCompressionSession, VTCompressionSessionRef);
|
||||
declare_TCFType!(CVMetalTextureCache, CVMetalTextureCacheRef);
|
||||
impl_TCFType!(
|
||||
VTCompressionSession,
|
||||
VTCompressionSessionRef,
|
||||
VTCompressionSessionGetTypeID
|
||||
CVMetalTextureCache,
|
||||
CVMetalTextureCacheRef,
|
||||
CVMetalTextureCacheGetTypeID
|
||||
);
|
||||
impl_CFTypeDescription!(VTCompressionSession);
|
||||
impl_CFTypeDescription!(CVMetalTextureCache);
|
||||
|
||||
impl VTCompressionSession {
|
||||
/// Create a new compression session.
|
||||
///
|
||||
impl CVMetalTextureCache {
|
||||
/// # Safety
|
||||
///
|
||||
/// The callback must be a valid function pointer. and the callback_data must be valid
|
||||
/// in whatever terms that callback expects.
|
||||
pub unsafe fn new(
|
||||
width: usize,
|
||||
height: usize,
|
||||
codec: CMVideoCodecType,
|
||||
callback: VTCompressionOutputCallback,
|
||||
callback_data: *const c_void,
|
||||
) -> Result<Self> {
|
||||
/// metal_device must be valid according to CVMetalTextureCacheCreate
|
||||
pub unsafe fn new(metal_device: *mut MTLDevice) -> Result<Self> {
|
||||
let mut this = ptr::null();
|
||||
let result = VTCompressionSessionCreate(
|
||||
let result = CVMetalTextureCacheCreate(
|
||||
kCFAllocatorDefault,
|
||||
ptr::null(),
|
||||
width as i32,
|
||||
height as i32,
|
||||
codec,
|
||||
metal_device,
|
||||
ptr::null(),
|
||||
ptr::null(),
|
||||
ptr::null(),
|
||||
callback,
|
||||
callback_data,
|
||||
&mut this,
|
||||
);
|
||||
|
||||
if result == 0 {
|
||||
Ok(Self::wrap_under_create_rule(this))
|
||||
if result == kCVReturnSuccess {
|
||||
Ok(CVMetalTextureCache::wrap_under_create_rule(this))
|
||||
} else {
|
||||
Err(anyhow!(
|
||||
"error creating compression session, code {}",
|
||||
result
|
||||
))
|
||||
Err(anyhow!("could not create texture cache, code: {}", result))
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// The arguments to this function must be valid according to VTCompressionSessionEncodeFrame
|
||||
pub unsafe fn encode_frame(
|
||||
/// The arguments to this function must be valid according to CVMetalTextureCacheCreateTextureFromImage
|
||||
pub unsafe fn create_texture_from_image(
|
||||
&self,
|
||||
buffer: CVImageBufferRef,
|
||||
presentation_timestamp: CMTime,
|
||||
duration: CMTime,
|
||||
) -> Result<()> {
|
||||
let result = VTCompressionSessionEncodeFrame(
|
||||
source: ::core_video::image_buffer::CVImageBufferRef,
|
||||
texture_attributes: CFDictionaryRef,
|
||||
pixel_format: MTLPixelFormat,
|
||||
width: usize,
|
||||
height: usize,
|
||||
plane_index: usize,
|
||||
) -> Result<CVMetalTexture> {
|
||||
let mut this = ptr::null();
|
||||
let result = CVMetalTextureCacheCreateTextureFromImage(
|
||||
kCFAllocatorDefault,
|
||||
self.as_concrete_TypeRef(),
|
||||
buffer,
|
||||
presentation_timestamp,
|
||||
duration,
|
||||
ptr::null(),
|
||||
ptr::null(),
|
||||
ptr::null_mut(),
|
||||
source,
|
||||
texture_attributes,
|
||||
pixel_format,
|
||||
width,
|
||||
height,
|
||||
plane_index,
|
||||
&mut this,
|
||||
);
|
||||
if result == 0 {
|
||||
Ok(())
|
||||
if result == kCVReturnSuccess {
|
||||
Ok(CVMetalTexture::wrap_under_create_rule(this))
|
||||
} else {
|
||||
Err(anyhow!("error encoding frame, code {}", result))
|
||||
Err(anyhow!("could not create texture, code: {}", result))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type VTCompressionOutputCallback = Option<
|
||||
unsafe extern "C" fn(
|
||||
outputCallbackRefCon: *mut c_void,
|
||||
sourceFrameRefCon: *mut c_void,
|
||||
status: OSStatus,
|
||||
infoFlags: VTEncodeInfoFlags,
|
||||
sampleBuffer: CMSampleBufferRef,
|
||||
),
|
||||
>;
|
||||
|
||||
#[link(name = "VideoToolbox", kind = "framework")]
|
||||
#[link(name = "CoreVideo", kind = "framework")]
|
||||
extern "C" {
|
||||
fn VTCompressionSessionGetTypeID() -> CFTypeID;
|
||||
fn VTCompressionSessionCreate(
|
||||
fn CVMetalTextureCacheGetTypeID() -> CFTypeID;
|
||||
fn CVMetalTextureCacheCreate(
|
||||
allocator: CFAllocatorRef,
|
||||
width: i32,
|
||||
height: i32,
|
||||
codec_type: CMVideoCodecType,
|
||||
encoder_specification: CFDictionaryRef,
|
||||
source_image_buffer_attributes: CFDictionaryRef,
|
||||
compressed_data_allocator: CFAllocatorRef,
|
||||
output_callback: VTCompressionOutputCallback,
|
||||
output_callback_ref_con: *const c_void,
|
||||
compression_session_out: *mut VTCompressionSessionRef,
|
||||
) -> OSStatus;
|
||||
fn VTCompressionSessionEncodeFrame(
|
||||
session: VTCompressionSessionRef,
|
||||
image_buffer: CVImageBufferRef,
|
||||
presentation_timestamp: CMTime,
|
||||
duration: CMTime,
|
||||
frame_properties: CFDictionaryRef,
|
||||
source_frame_ref_con: *const c_void,
|
||||
output_flags: *mut VTEncodeInfoFlags,
|
||||
) -> OSStatus;
|
||||
cache_attributes: CFDictionaryRef,
|
||||
metal_device: *const MTLDevice,
|
||||
texture_attributes: CFDictionaryRef,
|
||||
cache_out: *mut CVMetalTextureCacheRef,
|
||||
) -> CVReturn;
|
||||
fn CVMetalTextureCacheCreateTextureFromImage(
|
||||
allocator: CFAllocatorRef,
|
||||
texture_cache: CVMetalTextureCacheRef,
|
||||
source_image: ::core_video::image_buffer::CVImageBufferRef,
|
||||
texture_attributes: CFDictionaryRef,
|
||||
pixel_format: MTLPixelFormat,
|
||||
width: usize,
|
||||
height: usize,
|
||||
plane_index: usize,
|
||||
texture_out: *mut CVMetalTextureRef,
|
||||
) -> CVReturn;
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __CVMetalTexture(c_void);
|
||||
pub type CVMetalTextureRef = *const __CVMetalTexture;
|
||||
|
||||
declare_TCFType!(CVMetalTexture, CVMetalTextureRef);
|
||||
impl_TCFType!(CVMetalTexture, CVMetalTextureRef, CVMetalTextureGetTypeID);
|
||||
impl_CFTypeDescription!(CVMetalTexture);
|
||||
|
||||
impl CVMetalTexture {
|
||||
pub fn as_texture_ref(&self) -> &metal::TextureRef {
|
||||
unsafe {
|
||||
let texture = CVMetalTextureGetTexture(self.as_concrete_TypeRef());
|
||||
metal::TextureRef::from_ptr(texture as *mut _)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[link(name = "CoreVideo", kind = "framework")]
|
||||
extern "C" {
|
||||
fn CVMetalTextureGetTypeID() -> CFTypeID;
|
||||
fn CVMetalTextureGetTexture(texture: CVMetalTextureRef) -> *mut c_void;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue