Cargo.lock 🔗
@@ -757,6 +757,7 @@ dependencies = [
"anyhow",
"bindgen",
"block",
+ "byteorder",
"bytes",
"cocoa",
"core-foundation",
Nathan Sobo created
Still not sending it anywhere, but think I'm reading it correctly.
Cargo.lock | 1
crates/capture/Cargo.toml | 5 ---
crates/capture/script/capture | 5 ---
crates/capture/src/main.rs | 20 +++++++++++++++
crates/media/src/media.rs | 48 ++++++++++++++++++++++++++++++++++++
5 files changed, 69 insertions(+), 10 deletions(-)
@@ -757,6 +757,7 @@ dependencies = [
"anyhow",
"bindgen",
"block",
+ "byteorder",
"bytes",
"cocoa",
"core-foundation",
@@ -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"
@@ -1,5 +0,0 @@
-#!/bin/bash
-
-cargo bundle
-TTY=`tty`
-open ../../target/debug/bundle/osx/Capture.app --stdout $TTY --stderr $TTY
@@ -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::<BigEndian>() {
+ 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();
@@ -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 {