diff --git a/Cargo.lock b/Cargo.lock index 6b34c02f0d..60e54aeb9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -757,6 +757,7 @@ dependencies = [ "anyhow", "bindgen", "block", + "byteorder", "bytes", "cocoa", "core-foundation", diff --git a/crates/capture/Cargo.toml b/crates/capture/Cargo.toml index c2bee8312a..cdae75fc2b 100644 --- a/crates/capture/Cargo.toml +++ b/crates/capture/Cargo.toml @@ -4,10 +4,6 @@ version = "0.1.0" edition = "2021" description = "An example of screen capture" -[package.metadata.bundle] -name = "Capture" -identifier = "dev.zed.Capture" - [dependencies] gpui = { path = "../gpui" } media = { path = "../media" } @@ -15,6 +11,7 @@ media = { path = "../media" } anyhow = "1.0.38" block = "0.1" bytes = "1.2" +byteorder = "1.4" cocoa = "0.24" core-foundation = "0.9.3" core-graphics = "0.22.3" diff --git a/crates/capture/script/capture b/crates/capture/script/capture deleted file mode 100755 index 0e6cf1f409..0000000000 --- a/crates/capture/script/capture +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -cargo bundle -TTY=`tty` -open ../../target/debug/bundle/osx/Capture.app --stdout $TTY --stderr $TTY diff --git a/crates/capture/src/main.rs b/crates/capture/src/main.rs index b1d8f11795..97a5557c66 100644 --- a/crates/capture/src/main.rs +++ b/crates/capture/src/main.rs @@ -3,6 +3,7 @@ mod compression_session; use crate::{bindings::SCStreamOutputType, compression_session::CompressionSession}; use block::ConcreteBlock; +use byteorder::{BigEndian, ReadBytesExt}; use bytes::BytesMut; use cocoa::{ base::{id, nil, YES}, @@ -128,6 +129,25 @@ impl ScreenCaptureView { let nal_unit = compression_buffer.split(); } } + + let data = sample_buffer.data(); + let mut data = data.bytes(); + + const AVCC_HEADER_LENGTH: usize = 4; + while data.len() - AVCC_HEADER_LENGTH > 0 { + let nal_unit_len = match data.read_u32::() { + Ok(len) => len as usize, + Err(error) => { + log::error!("error decoding nal unit length: {}", error); + return; + } + }; + compression_buffer.extend_from_slice(&START_CODE); + compression_buffer.extend_from_slice(&data[..nal_unit_len as usize]); + data = &data[nal_unit_len..]; + + let nal_unit = compression_buffer.split(); + } }, ) .unwrap(); diff --git a/crates/media/src/media.rs b/crates/media/src/media.rs index 5c5f43af9d..ebe3ef7f4d 100644 --- a/crates/media/src/media.rs +++ b/crates/media/src/media.rs @@ -269,6 +269,14 @@ pub mod core_media { )) } } + + pub fn data(&self) -> CMBlockBuffer { + unsafe { + CMBlockBuffer::wrap_under_get_rule(CMSampleBufferGetDataBuffer( + self.as_concrete_TypeRef(), + )) + } + } } #[link(name = "CoreMedia", kind = "framework")] @@ -285,11 +293,11 @@ pub mod core_media { timing_info_out: *mut CMSampleTimingInfo, ) -> OSStatus; fn CMSampleBufferGetFormatDescription(buffer: CMSampleBufferRef) -> CMFormatDescriptionRef; + fn CMSampleBufferGetDataBuffer(sample_buffer: CMSampleBufferRef) -> CMBlockBufferRef; } #[repr(C)] pub struct __CMFormatDescription(c_void); - // The ref type must be a pointer to the underlying struct. pub type CMFormatDescriptionRef = *const __CMFormatDescription; declare_TCFType!(CMFormatDescription, CMFormatDescriptionRef); @@ -350,6 +358,44 @@ pub mod core_media { NALUnitHeaderLengthOut: *mut isize, ) -> OSStatus; } + + #[repr(C)] + pub struct __CMBlockBuffer(c_void); + pub type CMBlockBufferRef = *const __CMBlockBuffer; + + declare_TCFType!(CMBlockBuffer, CMBlockBufferRef); + impl_TCFType!(CMBlockBuffer, CMBlockBufferRef, CMBlockBufferGetTypeID); + impl_CFTypeDescription!(CMBlockBuffer); + + impl CMBlockBuffer { + pub fn bytes(&self) -> &[u8] { + unsafe { + let mut bytes = ptr::null(); + let mut len = 0; + let result = CMBlockBufferGetDataPointer( + self.as_concrete_TypeRef(), + 0, + &mut 0, + &mut len, + &mut bytes, + ); + assert!(result == 0, "could not get block buffer data"); + std::slice::from_raw_parts(bytes, len) + } + } + } + + #[link(name = "CoreMedia", kind = "framework")] + extern "C" { + fn CMBlockBufferGetTypeID() -> CFTypeID; + fn CMBlockBufferGetDataPointer( + buffer: CMBlockBufferRef, + offset: usize, + length_at_offset_out: *mut usize, + total_length_out: *mut usize, + data_pointer_out: *mut *const u8, + ) -> OSStatus; + } } pub mod video_toolbox {