Capture screen in BGRA8 and render it in capture example app

This commit is contained in:
Antonio Scandurra 2022-08-31 11:02:48 +02:00
parent 37da841716
commit 79a7a0e0e7
10 changed files with 156 additions and 71 deletions

View file

@ -10,5 +10,9 @@ doctest = false
[dependencies]
block = "0.1"
core-foundation = "0.9.3"
foreign-types = "0.3"
metal = "0.21.0"
objc = "0.2"
[build-dependencies]
bindgen = "0.59.2"

29
crates/media/build.rs Normal file
View file

@ -0,0 +1,29 @@
use std::{env, path::PathBuf, process::Command};
fn main() {
let sdk_path = String::from_utf8(
Command::new("xcrun")
.args(&["--sdk", "macosx", "--show-sdk-path"])
.output()
.unwrap()
.stdout,
)
.unwrap();
let sdk_path = sdk_path.trim_end();
println!("cargo:rerun-if-changed=src/bindings.h");
let bindings = bindgen::Builder::default()
.header("src/bindings.h")
.clang_arg(format!("-isysroot{}", sdk_path))
.clang_arg("-xobjective-c")
.allowlist_var("kCVPixelFormatType_.*")
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.layout_tests(false)
.generate()
.expect("unable to generate bindings");
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("couldn't write dispatch bindings");
}

View file

@ -0,0 +1 @@
#import <CoreVideo/CVPixelFormatDescription.h>

View file

@ -0,0 +1,8 @@
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(unused)]
use objc::*;
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));

View file

@ -1,6 +1,8 @@
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
mod bindings;
use core_foundation::{
base::{CFTypeID, TCFType},
declare_TCFType, impl_CFTypeDescription, impl_TCFType,
@ -34,11 +36,13 @@ pub mod core_video {
use std::ptr;
use super::*;
pub use crate::bindings::*;
use core_foundation::{
base::kCFAllocatorDefault, dictionary::CFDictionaryRef, mach_port::CFAllocatorRef,
};
use foreign_types::ForeignTypeRef;
use io_surface::{IOSurface, IOSurfaceRef};
use metal::{MTLDevice, MTLPixelFormat};
use metal::{MTLDevice, MTLPixelFormat, MTLTexture};
#[repr(C)]
pub struct __CVImageBuffer(c_void);
@ -65,13 +69,19 @@ pub mod core_video {
pub fn height(&self) -> usize {
unsafe { CVPixelBufferGetHeight(self.as_concrete_TypeRef()) }
}
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 CVPixelBufferGetPixelFormatType(buffer: CVImageBufferRef) -> OSType;
}
#[repr(C)]
@ -130,6 +140,7 @@ pub mod core_video {
}
}
#[link(name = "CoreVideo", kind = "framework")]
extern "C" {
fn CVMetalTextureCacheGetTypeID() -> CFTypeID;
fn CVMetalTextureCacheCreate(
@ -160,7 +171,18 @@ pub mod core_video {
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;
}
}