feat: add publishing & audio to ffi (#46)
- Divide FFI protocol into multiple files
- Audio support
- AV Streams/Sources
- Create tracks
- Use Dashmap to store handles
- Add a capture test
- Ignored by GHA atm
This commit is contained in:
@@ -1,7 +1,18 @@
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AudioFrame {
|
||||
pub data: Vec<i16>,
|
||||
pub sample_rate_hz: u32,
|
||||
pub num_channels: usize,
|
||||
pub samples_per_channel: usize,
|
||||
pub sample_rate: u32,
|
||||
pub num_channels: u32,
|
||||
pub samples_per_channel: u32,
|
||||
}
|
||||
|
||||
impl AudioFrame {
|
||||
pub fn new(sample_rate: u32, num_channels: u32, samples_per_channel: u32) -> Self {
|
||||
Self {
|
||||
data: vec![0; (num_channels * samples_per_channel) as usize],
|
||||
sample_rate,
|
||||
num_channels,
|
||||
samples_per_channel,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ pub mod native {
|
||||
}
|
||||
|
||||
impl NativeAudioSource {
|
||||
pub fn capture_frame(&self, frame: AudioFrame) {
|
||||
pub fn capture_frame(&self, frame: &AudioFrame) {
|
||||
self.handle.capture_frame(frame)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,14 +20,14 @@ impl NativeAudioSource {
|
||||
self.sys_handle.clone()
|
||||
}
|
||||
|
||||
pub fn capture_frame(&self, frame: AudioFrame) {
|
||||
pub fn capture_frame(&self, frame: &AudioFrame) {
|
||||
// TODO(theomonnom): Should we check for 10ms worth of data here?
|
||||
unsafe {
|
||||
self.sys_handle.on_captured_frame(
|
||||
frame.data.as_ptr(),
|
||||
frame.sample_rate_hz as i32,
|
||||
frame.num_channels,
|
||||
frame.samples_per_channel,
|
||||
frame.sample_rate as i32,
|
||||
frame.num_channels as usize,
|
||||
frame.samples_per_channel as usize,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,9 +72,9 @@ impl sys_ms::AudioSink for AudioTrackObserver {
|
||||
// TODO(theomonnom): Should we avoid copy here?
|
||||
let _ = self.frame_tx.send(AudioFrame {
|
||||
data: data.to_owned(),
|
||||
sample_rate_hz: sample_rate as u32,
|
||||
num_channels: nb_channels,
|
||||
samples_per_channel: nb_frames,
|
||||
sample_rate: sample_rate as u32,
|
||||
num_channels: nb_channels as u32,
|
||||
samples_per_channel: nb_frames as u32,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,11 +149,11 @@ impl NativeBuffer {
|
||||
&*self.sys_handle
|
||||
}
|
||||
|
||||
pub fn width(&self) -> i32 {
|
||||
pub fn width(&self) -> u32 {
|
||||
self.sys_handle.width()
|
||||
}
|
||||
|
||||
pub fn height(&self) -> i32 {
|
||||
pub fn height(&self) -> u32 {
|
||||
self.sys_handle.height()
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ impl NativeBuffer {
|
||||
&self,
|
||||
format: VideoFormatType,
|
||||
dst: &mut [u8],
|
||||
dst_stride: i32,
|
||||
dst_stride: u32,
|
||||
dst_width: i32,
|
||||
dst_height: i32,
|
||||
) -> Result<(), ConvertError> {
|
||||
@@ -192,49 +192,49 @@ impl I420Buffer {
|
||||
unsafe { &*recursive_cast!(&*self.sys_handle, i420_to_yuv8, yuv8_to_yuv, yuv_to_vfb) }
|
||||
}
|
||||
|
||||
pub fn width(&self) -> i32 {
|
||||
pub fn width(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i420_to_yuv8, yuv8_to_yuv, yuv_to_vfb);
|
||||
(*ptr).width()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn height(&self) -> i32 {
|
||||
pub fn height(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i420_to_yuv8, yuv8_to_yuv, yuv_to_vfb);
|
||||
(*ptr).height()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn chroma_width(&self) -> i32 {
|
||||
pub fn chroma_width(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i420_to_yuv8, yuv8_to_yuv);
|
||||
(*ptr).chroma_width()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn chroma_height(&self) -> i32 {
|
||||
pub fn chroma_height(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i420_to_yuv8, yuv8_to_yuv);
|
||||
(*ptr).chroma_height()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stride_y(&self) -> i32 {
|
||||
pub fn stride_y(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i420_to_yuv8, yuv8_to_yuv);
|
||||
(*ptr).stride_y()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stride_u(&self) -> i32 {
|
||||
pub fn stride_u(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i420_to_yuv8, yuv8_to_yuv);
|
||||
(*ptr).stride_u()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stride_v(&self) -> i32 {
|
||||
pub fn stride_v(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i420_to_yuv8, yuv8_to_yuv);
|
||||
(*ptr).stride_v()
|
||||
@@ -258,7 +258,7 @@ impl I420Buffer {
|
||||
&self,
|
||||
format: VideoFormatType,
|
||||
dst: &mut [u8],
|
||||
dst_stride: i32,
|
||||
dst_stride: u32,
|
||||
dst_width: i32,
|
||||
dst_height: i32,
|
||||
) -> Result<(), ConvertError> {
|
||||
@@ -292,56 +292,56 @@ impl I420ABuffer {
|
||||
unsafe { &*recursive_cast!(&*self.sys_handle, i420a_to_yuv8, yuv8_to_yuv, yuv_to_vfb) }
|
||||
}
|
||||
|
||||
pub fn width(&self) -> i32 {
|
||||
pub fn width(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i420a_to_yuv8, yuv8_to_yuv, yuv_to_vfb);
|
||||
(*ptr).width()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn height(&self) -> i32 {
|
||||
pub fn height(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i420a_to_yuv8, yuv8_to_yuv, yuv_to_vfb);
|
||||
(*ptr).height()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn chroma_width(&self) -> i32 {
|
||||
pub fn chroma_width(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i420a_to_yuv8, yuv8_to_yuv);
|
||||
(*ptr).chroma_width()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn chroma_height(&self) -> i32 {
|
||||
pub fn chroma_height(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i420a_to_yuv8, yuv8_to_yuv);
|
||||
(*ptr).chroma_height()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stride_y(&self) -> i32 {
|
||||
pub fn stride_y(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i420a_to_yuv8, yuv8_to_yuv);
|
||||
(*ptr).stride_y()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stride_u(&self) -> i32 {
|
||||
pub fn stride_u(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i420a_to_yuv8, yuv8_to_yuv);
|
||||
(*ptr).stride_u()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stride_v(&self) -> i32 {
|
||||
pub fn stride_v(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i420a_to_yuv8, yuv8_to_yuv);
|
||||
(*ptr).stride_v()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stride_a(&self) -> i32 {
|
||||
pub fn stride_a(&self) -> u32 {
|
||||
self.sys_handle.stride_a()
|
||||
}
|
||||
|
||||
@@ -359,7 +359,7 @@ impl I420ABuffer {
|
||||
&self,
|
||||
format: VideoFormatType,
|
||||
dst: &mut [u8],
|
||||
dst_stride: i32,
|
||||
dst_stride: u32,
|
||||
dst_width: i32,
|
||||
dst_height: i32,
|
||||
) -> Result<(), ConvertError> {
|
||||
@@ -391,49 +391,49 @@ impl I422Buffer {
|
||||
unsafe { &*recursive_cast!(&*self.sys_handle, i422_to_yuv8, yuv8_to_yuv, yuv_to_vfb) }
|
||||
}
|
||||
|
||||
pub fn width(&self) -> i32 {
|
||||
pub fn width(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i422_to_yuv8, yuv8_to_yuv, yuv_to_vfb);
|
||||
(*ptr).width()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn height(&self) -> i32 {
|
||||
pub fn height(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i422_to_yuv8, yuv8_to_yuv, yuv_to_vfb);
|
||||
(*ptr).height()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn chroma_width(&self) -> i32 {
|
||||
pub fn chroma_width(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i422_to_yuv8, yuv8_to_yuv);
|
||||
(*ptr).chroma_width()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn chroma_height(&self) -> i32 {
|
||||
pub fn chroma_height(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i422_to_yuv8, yuv8_to_yuv);
|
||||
(*ptr).chroma_height()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stride_y(&self) -> i32 {
|
||||
pub fn stride_y(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i422_to_yuv8, yuv8_to_yuv);
|
||||
(*ptr).stride_y()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stride_u(&self) -> i32 {
|
||||
pub fn stride_u(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i422_to_yuv8, yuv8_to_yuv);
|
||||
(*ptr).stride_u()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stride_v(&self) -> i32 {
|
||||
pub fn stride_v(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i422_to_yuv8, yuv8_to_yuv);
|
||||
(*ptr).stride_v()
|
||||
@@ -453,7 +453,7 @@ impl I422Buffer {
|
||||
&self,
|
||||
format: VideoFormatType,
|
||||
dst: &mut [u8],
|
||||
dst_stride: i32,
|
||||
dst_stride: u32,
|
||||
dst_width: i32,
|
||||
dst_height: i32,
|
||||
) -> Result<(), ConvertError> {
|
||||
@@ -477,49 +477,49 @@ impl I444Buffer {
|
||||
unsafe { &*recursive_cast!(&*self.sys_handle, i444_to_yuv8, yuv8_to_yuv, yuv_to_vfb) }
|
||||
}
|
||||
|
||||
pub fn width(&self) -> i32 {
|
||||
pub fn width(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i444_to_yuv8, yuv8_to_yuv, yuv_to_vfb);
|
||||
(*ptr).width()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn height(&self) -> i32 {
|
||||
pub fn height(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i444_to_yuv8, yuv8_to_yuv, yuv_to_vfb);
|
||||
(*ptr).height()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn chroma_width(&self) -> i32 {
|
||||
pub fn chroma_width(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i444_to_yuv8, yuv8_to_yuv);
|
||||
(*ptr).chroma_width()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn chroma_height(&self) -> i32 {
|
||||
pub fn chroma_height(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i444_to_yuv8, yuv8_to_yuv);
|
||||
(*ptr).chroma_height()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stride_y(&self) -> i32 {
|
||||
pub fn stride_y(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i444_to_yuv8, yuv8_to_yuv);
|
||||
(*ptr).stride_y()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stride_u(&self) -> i32 {
|
||||
pub fn stride_u(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i444_to_yuv8, yuv8_to_yuv);
|
||||
(*ptr).stride_u()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stride_v(&self) -> i32 {
|
||||
pub fn stride_v(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i444_to_yuv8, yuv8_to_yuv);
|
||||
(*ptr).stride_v()
|
||||
@@ -539,7 +539,7 @@ impl I444Buffer {
|
||||
&self,
|
||||
format: VideoFormatType,
|
||||
dst: &mut [u8],
|
||||
dst_stride: i32,
|
||||
dst_stride: u32,
|
||||
dst_width: i32,
|
||||
dst_height: i32,
|
||||
) -> Result<(), ConvertError> {
|
||||
@@ -564,49 +564,49 @@ impl I010Buffer {
|
||||
unsafe { &*recursive_cast!(&*self.sys_handle, i010_to_yuv16b, yuv16b_to_yuv, yuv_to_vfb) }
|
||||
}
|
||||
|
||||
pub fn width(&self) -> i32 {
|
||||
pub fn width(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i010_to_yuv16b, yuv16b_to_yuv, yuv_to_vfb);
|
||||
(*ptr).width()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn height(&self) -> i32 {
|
||||
pub fn height(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i010_to_yuv16b, yuv16b_to_yuv, yuv_to_vfb);
|
||||
(*ptr).height()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn chroma_width(&self) -> i32 {
|
||||
pub fn chroma_width(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i010_to_yuv16b, yuv16b_to_yuv);
|
||||
(*ptr).chroma_width()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn chroma_height(&self) -> i32 {
|
||||
pub fn chroma_height(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i010_to_yuv16b, yuv16b_to_yuv);
|
||||
(*ptr).chroma_height()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stride_y(&self) -> i32 {
|
||||
pub fn stride_y(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i010_to_yuv16b, yuv16b_to_yuv);
|
||||
(*ptr).stride_y()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stride_u(&self) -> i32 {
|
||||
pub fn stride_u(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i010_to_yuv16b, yuv16b_to_yuv);
|
||||
(*ptr).stride_u()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stride_v(&self) -> i32 {
|
||||
pub fn stride_v(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, i010_to_yuv16b, yuv16b_to_yuv);
|
||||
(*ptr).stride_v()
|
||||
@@ -627,7 +627,7 @@ impl I010Buffer {
|
||||
&self,
|
||||
format: VideoFormatType,
|
||||
dst: &mut [u8],
|
||||
dst_stride: i32,
|
||||
dst_stride: u32,
|
||||
dst_width: i32,
|
||||
dst_height: i32,
|
||||
) -> Result<(), ConvertError> {
|
||||
@@ -669,7 +669,7 @@ impl NV12Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn width(&self) -> i32 {
|
||||
pub fn width(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(
|
||||
&*self.sys_handle,
|
||||
@@ -681,7 +681,7 @@ impl NV12Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn height(&self) -> i32 {
|
||||
pub fn height(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(
|
||||
&*self.sys_handle,
|
||||
@@ -693,28 +693,28 @@ impl NV12Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn chroma_width(&self) -> i32 {
|
||||
pub fn chroma_width(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, nv12_to_biyuv8, biyuv8_to_biyuv);
|
||||
(*ptr).chroma_width()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn chroma_height(&self) -> i32 {
|
||||
pub fn chroma_height(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, nv12_to_biyuv8, biyuv8_to_biyuv);
|
||||
(*ptr).chroma_height()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stride_y(&self) -> i32 {
|
||||
pub fn stride_y(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, nv12_to_biyuv8, biyuv8_to_biyuv);
|
||||
(*ptr).stride_y()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stride_uv(&self) -> i32 {
|
||||
pub fn stride_uv(&self) -> u32 {
|
||||
unsafe {
|
||||
let ptr = recursive_cast!(&*self.sys_handle, nv12_to_biyuv8, biyuv8_to_biyuv);
|
||||
(*ptr).stride_uv()
|
||||
@@ -739,7 +739,7 @@ impl NV12Buffer {
|
||||
&self,
|
||||
format: VideoFormatType,
|
||||
dst: &mut [u8],
|
||||
dst_stride: i32,
|
||||
dst_stride: u32,
|
||||
dst_width: i32,
|
||||
dst_height: i32,
|
||||
) -> Result<(), ConvertError> {
|
||||
|
||||
@@ -21,12 +21,12 @@ impl NativeVideoSource {
|
||||
self.sys_handle.clone()
|
||||
}
|
||||
|
||||
pub fn capture_frame<T: VideoFrameBuffer>(&self, frame: &VideoFrame<T>) {
|
||||
pub fn capture_frame<T: AsRef<dyn VideoFrameBuffer>>(&self, frame: &VideoFrame<T>) {
|
||||
let mut builder = vf_sys::ffi::new_video_frame_builder();
|
||||
builder.pin_mut().set_rotation(frame.rotation.into());
|
||||
builder
|
||||
.pin_mut()
|
||||
.set_video_frame_buffer(frame.buffer.sys_handle());
|
||||
.set_video_frame_buffer(frame.buffer.as_ref().sys_handle());
|
||||
|
||||
let frame = builder.pin_mut().build();
|
||||
self.sys_handle.on_captured_frame(&frame);
|
||||
|
||||
@@ -10,11 +10,12 @@ pub enum ConvertError {
|
||||
#[inline]
|
||||
fn argb_assert_safety(
|
||||
src: &[u8],
|
||||
src_stride: i32,
|
||||
src_stride: u32,
|
||||
_width: i32,
|
||||
height: i32,
|
||||
) -> Result<(), ConvertError> {
|
||||
let min = (src_stride * height) as usize;
|
||||
let height_abs = height.abs() as u32;
|
||||
let min = (src_stride * height_abs) as usize;
|
||||
|
||||
if src.len() < min {
|
||||
return Err(ConvertError::Convert("dst isn't large enough"));
|
||||
@@ -26,16 +27,17 @@ fn argb_assert_safety(
|
||||
#[inline]
|
||||
fn i420_assert_safety(
|
||||
src_y: &[u8],
|
||||
src_stride_y: i32,
|
||||
src_stride_y: u32,
|
||||
src_u: &[u8],
|
||||
src_stride_u: i32,
|
||||
src_stride_u: u32,
|
||||
src_v: &[u8],
|
||||
src_stride_v: i32,
|
||||
src_stride_v: u32,
|
||||
_width: i32,
|
||||
height: i32,
|
||||
) -> Result<(), ConvertError> {
|
||||
let chroma_height = (height + 1) / 2;
|
||||
let min_y = (src_stride_y * height) as usize;
|
||||
let height_abs = height.abs() as u32;
|
||||
let chroma_height = (height_abs + 1) / 2;
|
||||
let min_y = (src_stride_y * height_abs) as usize;
|
||||
let min_u = (src_stride_u * chroma_height) as usize;
|
||||
let min_v = (src_stride_v * chroma_height) as usize;
|
||||
|
||||
@@ -58,13 +60,13 @@ macro_rules! i420_to_x {
|
||||
($x:ident) => {
|
||||
pub fn $x(
|
||||
src_y: &[u8],
|
||||
src_stride_y: i32,
|
||||
src_stride_y: u32,
|
||||
src_u: &[u8],
|
||||
src_stride_u: i32,
|
||||
src_stride_u: u32,
|
||||
src_v: &[u8],
|
||||
src_stride_v: i32,
|
||||
src_stride_v: u32,
|
||||
dst: &mut [u8],
|
||||
dst_stride: i32,
|
||||
dst_stride: u32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
) -> Result<(), ConvertError> {
|
||||
@@ -83,13 +85,13 @@ macro_rules! i420_to_x {
|
||||
unsafe {
|
||||
yuv_sys::ffi::$x(
|
||||
src_y.as_ptr(),
|
||||
src_stride_y,
|
||||
src_stride_y as i32,
|
||||
src_u.as_ptr(),
|
||||
src_stride_u,
|
||||
src_stride_u as i32,
|
||||
src_v.as_ptr(),
|
||||
src_stride_v,
|
||||
src_stride_v as i32,
|
||||
dst.as_mut_ptr(),
|
||||
dst_stride,
|
||||
dst_stride as i32,
|
||||
width,
|
||||
height,
|
||||
)
|
||||
@@ -105,13 +107,13 @@ macro_rules! x_to_i420 {
|
||||
($x:ident) => {
|
||||
pub fn $x(
|
||||
src_argb: &[u8],
|
||||
src_stride_argb: i32,
|
||||
src_stride_argb: u32,
|
||||
dst_y: &mut [u8],
|
||||
dst_stride_y: i32,
|
||||
dst_stride_y: u32,
|
||||
dst_u: &mut [u8],
|
||||
dst_stride_u: i32,
|
||||
dst_stride_u: u32,
|
||||
dst_v: &mut [u8],
|
||||
dst_stride_v: i32,
|
||||
dst_stride_v: u32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
) -> Result<(), ConvertError> {
|
||||
@@ -130,13 +132,13 @@ macro_rules! x_to_i420 {
|
||||
unsafe {
|
||||
yuv_sys::ffi::$x(
|
||||
src_argb.as_ptr(),
|
||||
src_stride_argb,
|
||||
src_stride_argb as i32,
|
||||
dst_y.as_mut_ptr(),
|
||||
dst_stride_y,
|
||||
dst_stride_y as i32,
|
||||
dst_u.as_mut_ptr(),
|
||||
dst_stride_u,
|
||||
dst_stride_u as i32,
|
||||
dst_v.as_mut_ptr(),
|
||||
dst_stride_v,
|
||||
dst_stride_v as i32,
|
||||
width,
|
||||
height,
|
||||
)
|
||||
@@ -150,9 +152,9 @@ macro_rules! x_to_i420 {
|
||||
|
||||
pub fn argb_to_rgb24(
|
||||
src_argb: &[u8],
|
||||
src_stride_argb: i32,
|
||||
src_stride_argb: u32,
|
||||
dst_rgb24: &mut [u8],
|
||||
dst_stride_rgb24: i32,
|
||||
dst_stride_rgb24: u32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
) -> Result<(), ConvertError> {
|
||||
@@ -162,9 +164,9 @@ pub fn argb_to_rgb24(
|
||||
unsafe {
|
||||
yuv_sys::ffi::argb_to_rgb24(
|
||||
src_argb.as_ptr(),
|
||||
src_stride_argb,
|
||||
src_stride_argb as i32,
|
||||
dst_rgb24.as_mut_ptr(),
|
||||
dst_stride_rgb24,
|
||||
dst_stride_rgb24 as i32,
|
||||
width,
|
||||
height,
|
||||
)
|
||||
|
||||
+122
-178
@@ -40,80 +40,20 @@ pub enum VideoFrameBufferType {
|
||||
#[derive(Debug)]
|
||||
pub struct VideoFrame<T>
|
||||
where
|
||||
T: VideoFrameBuffer,
|
||||
T: AsRef<dyn VideoFrameBuffer>,
|
||||
{
|
||||
pub rotation: VideoRotation,
|
||||
pub timestamp: i64, // When the frame was captured
|
||||
pub buffer: T,
|
||||
}
|
||||
|
||||
pub type BoxVideoFrame = VideoFrame<Box<dyn VideoFrameBuffer + Send + Sync>>;
|
||||
|
||||
macro_rules! new_buffer_type {
|
||||
($type:ident, $variant:ident, $as:ident) => {
|
||||
pub struct $type {
|
||||
pub(crate) handle: vf_imp::$type,
|
||||
}
|
||||
|
||||
impl $crate::video_frame::internal::BufferInternal for $type {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn sys_handle(&self) -> &webrtc_sys::video_frame_buffer::ffi::VideoFrameBuffer {
|
||||
self.handle.sys_handle()
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn to_i420(&self) -> I420Buffer {
|
||||
I420Buffer {
|
||||
handle: self.handle.to_i420(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn to_argb(
|
||||
&self,
|
||||
format: VideoFormatType,
|
||||
dst: &mut [u8],
|
||||
stride: i32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
) -> Result<(), $crate::video_frame::native::ConvertError> {
|
||||
self.handle.to_argb(format, dst, stride, width, height)
|
||||
}
|
||||
}
|
||||
|
||||
impl VideoFrameBuffer for $type {
|
||||
fn width(&self) -> i32 {
|
||||
self.handle.width()
|
||||
}
|
||||
|
||||
fn height(&self) -> i32 {
|
||||
self.handle.height()
|
||||
}
|
||||
|
||||
fn buffer_type(&self) -> VideoFrameBufferType {
|
||||
VideoFrameBufferType::$variant
|
||||
}
|
||||
|
||||
fn $as(&self) -> Option<&$type> {
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for $type {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct(stringify!($type))
|
||||
.field("width", &self.width())
|
||||
.field("height", &self.height())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
pub type BoxVideoFrameBuffer = Box<dyn VideoFrameBuffer>;
|
||||
pub type BoxVideoFrame = VideoFrame<BoxVideoFrameBuffer>;
|
||||
|
||||
pub(crate) mod internal {
|
||||
use super::{I420Buffer, VideoFormatType};
|
||||
|
||||
pub trait BufferInternal {
|
||||
pub trait BufferSealed: Send + Sync {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn sys_handle(&self) -> &webrtc_sys::video_frame_buffer::ffi::VideoFrameBuffer;
|
||||
|
||||
@@ -125,16 +65,16 @@ pub(crate) mod internal {
|
||||
&self,
|
||||
format: VideoFormatType,
|
||||
dst: &mut [u8],
|
||||
dst_stride: i32,
|
||||
dst_stride: u32,
|
||||
dst_width: i32,
|
||||
dst_height: i32,
|
||||
) -> Result<(), super::native::ConvertError>;
|
||||
}
|
||||
}
|
||||
|
||||
pub trait VideoFrameBuffer: internal::BufferInternal + Debug {
|
||||
fn width(&self) -> i32;
|
||||
fn height(&self) -> i32;
|
||||
pub trait VideoFrameBuffer: internal::BufferSealed + Debug {
|
||||
fn width(&self) -> u32;
|
||||
fn height(&self) -> u32;
|
||||
fn buffer_type(&self) -> VideoFrameBufferType;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
@@ -167,6 +107,73 @@ pub trait VideoFrameBuffer: internal::BufferInternal + Debug {
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! new_buffer_type {
|
||||
($type:ident, $variant:ident, $as:ident) => {
|
||||
pub struct $type {
|
||||
pub(crate) handle: vf_imp::$type,
|
||||
}
|
||||
|
||||
impl $crate::video_frame::internal::BufferSealed for $type {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn sys_handle(&self) -> &webrtc_sys::video_frame_buffer::ffi::VideoFrameBuffer {
|
||||
self.handle.sys_handle()
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn to_i420(&self) -> I420Buffer {
|
||||
I420Buffer {
|
||||
handle: self.handle.to_i420(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn to_argb(
|
||||
&self,
|
||||
format: VideoFormatType,
|
||||
dst: &mut [u8],
|
||||
stride: u32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
) -> Result<(), $crate::video_frame::native::ConvertError> {
|
||||
self.handle.to_argb(format, dst, stride, width, height)
|
||||
}
|
||||
}
|
||||
|
||||
impl VideoFrameBuffer for $type {
|
||||
fn width(&self) -> u32 {
|
||||
self.handle.width()
|
||||
}
|
||||
|
||||
fn height(&self) -> u32 {
|
||||
self.handle.height()
|
||||
}
|
||||
|
||||
fn buffer_type(&self) -> VideoFrameBufferType {
|
||||
VideoFrameBufferType::$variant
|
||||
}
|
||||
|
||||
fn $as(&self) -> Option<&$type> {
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for $type {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct(stringify!($type))
|
||||
.field("width", &self.width())
|
||||
.field("height", &self.height())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<dyn VideoFrameBuffer> for $type {
|
||||
fn as_ref(&self) -> &(dyn VideoFrameBuffer + 'static) {
|
||||
self
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
new_buffer_type!(I420Buffer, I420, as_i420);
|
||||
new_buffer_type!(I420ABuffer, I420A, as_i420a);
|
||||
new_buffer_type!(I422Buffer, I422, as_i422);
|
||||
@@ -175,24 +182,20 @@ new_buffer_type!(I010Buffer, I010, as_i010);
|
||||
new_buffer_type!(NV12Buffer, NV12, as_nv12);
|
||||
|
||||
impl I420Buffer {
|
||||
pub fn chroma_width(&self) -> i32 {
|
||||
pub fn chroma_width(&self) -> u32 {
|
||||
self.handle.chroma_width()
|
||||
}
|
||||
|
||||
pub fn chroma_height(&self) -> i32 {
|
||||
pub fn chroma_height(&self) -> u32 {
|
||||
self.handle.chroma_height()
|
||||
}
|
||||
|
||||
pub fn stride_y(&self) -> i32 {
|
||||
self.handle.stride_y()
|
||||
}
|
||||
|
||||
pub fn stride_u(&self) -> i32 {
|
||||
self.handle.stride_u()
|
||||
}
|
||||
|
||||
pub fn stride_v(&self) -> i32 {
|
||||
self.handle.stride_v()
|
||||
pub fn strides(&self) -> (u32, u32, u32) {
|
||||
(
|
||||
self.handle.stride_y(),
|
||||
self.handle.stride_u(),
|
||||
self.handle.stride_v(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn data(&self) -> (&[u8], &[u8], &[u8]) {
|
||||
@@ -212,28 +215,21 @@ impl I420Buffer {
|
||||
}
|
||||
|
||||
impl I420ABuffer {
|
||||
pub fn chroma_width(&self) -> i32 {
|
||||
pub fn chroma_width(&self) -> u32 {
|
||||
self.handle.chroma_width()
|
||||
}
|
||||
|
||||
pub fn chroma_height(&self) -> i32 {
|
||||
pub fn chroma_height(&self) -> u32 {
|
||||
self.handle.chroma_height()
|
||||
}
|
||||
|
||||
pub fn stride_y(&self) -> i32 {
|
||||
self.handle.stride_y()
|
||||
}
|
||||
|
||||
pub fn stride_u(&self) -> i32 {
|
||||
self.handle.stride_u()
|
||||
}
|
||||
|
||||
pub fn stride_v(&self) -> i32 {
|
||||
self.handle.stride_v()
|
||||
}
|
||||
|
||||
pub fn stride_a(&self) -> i32 {
|
||||
self.handle.stride_a()
|
||||
pub fn strides(&self) -> (u32, u32, u32, u32) {
|
||||
(
|
||||
self.handle.stride_y(),
|
||||
self.handle.stride_u(),
|
||||
self.handle.stride_v(),
|
||||
self.handle.stride_a(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn data(&self) -> (&[u8], &[u8], &[u8], Option<&[u8]>) {
|
||||
@@ -256,24 +252,20 @@ impl I420ABuffer {
|
||||
}
|
||||
|
||||
impl I422Buffer {
|
||||
pub fn chroma_width(&self) -> i32 {
|
||||
pub fn chroma_width(&self) -> u32 {
|
||||
self.handle.chroma_width()
|
||||
}
|
||||
|
||||
pub fn chroma_height(&self) -> i32 {
|
||||
pub fn chroma_height(&self) -> u32 {
|
||||
self.handle.chroma_height()
|
||||
}
|
||||
|
||||
pub fn stride_y(&self) -> i32 {
|
||||
self.handle.stride_y()
|
||||
}
|
||||
|
||||
pub fn stride_u(&self) -> i32 {
|
||||
self.handle.stride_u()
|
||||
}
|
||||
|
||||
pub fn stride_v(&self) -> i32 {
|
||||
self.handle.stride_v()
|
||||
pub fn strides(&self) -> (u32, u32, u32) {
|
||||
(
|
||||
self.handle.stride_y(),
|
||||
self.handle.stride_u(),
|
||||
self.handle.stride_v(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn data(&self) -> (&[u8], &[u8], &[u8]) {
|
||||
@@ -293,24 +285,20 @@ impl I422Buffer {
|
||||
}
|
||||
|
||||
impl I444Buffer {
|
||||
pub fn chroma_width(&self) -> i32 {
|
||||
pub fn chroma_width(&self) -> u32 {
|
||||
self.handle.chroma_width()
|
||||
}
|
||||
|
||||
pub fn chroma_height(&self) -> i32 {
|
||||
pub fn chroma_height(&self) -> u32 {
|
||||
self.handle.chroma_height()
|
||||
}
|
||||
|
||||
pub fn stride_y(&self) -> i32 {
|
||||
self.handle.stride_y()
|
||||
}
|
||||
|
||||
pub fn stride_u(&self) -> i32 {
|
||||
self.handle.stride_u()
|
||||
}
|
||||
|
||||
pub fn stride_v(&self) -> i32 {
|
||||
self.handle.stride_v()
|
||||
pub fn strides(&self) -> (u32, u32, u32) {
|
||||
(
|
||||
self.handle.stride_y(),
|
||||
self.handle.stride_u(),
|
||||
self.handle.stride_v(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn data(&self) -> (&[u8], &[u8], &[u8]) {
|
||||
@@ -330,24 +318,20 @@ impl I444Buffer {
|
||||
}
|
||||
|
||||
impl I010Buffer {
|
||||
pub fn chroma_width(&self) -> i32 {
|
||||
pub fn chroma_width(&self) -> u32 {
|
||||
self.handle.chroma_width()
|
||||
}
|
||||
|
||||
pub fn chroma_height(&self) -> i32 {
|
||||
pub fn chroma_height(&self) -> u32 {
|
||||
self.handle.chroma_height()
|
||||
}
|
||||
|
||||
pub fn stride_y(&self) -> i32 {
|
||||
self.handle.stride_y()
|
||||
}
|
||||
|
||||
pub fn stride_u(&self) -> i32 {
|
||||
self.handle.stride_u()
|
||||
}
|
||||
|
||||
pub fn stride_v(&self) -> i32 {
|
||||
self.handle.stride_v()
|
||||
pub fn strides(&self) -> (u32, u32, u32) {
|
||||
(
|
||||
self.handle.stride_y(),
|
||||
self.handle.stride_u(),
|
||||
self.handle.stride_v(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn data(&self) -> (&[u16], &[u16], &[u16]) {
|
||||
@@ -367,20 +351,16 @@ impl I010Buffer {
|
||||
}
|
||||
|
||||
impl NV12Buffer {
|
||||
pub fn chroma_width(&self) -> i32 {
|
||||
pub fn chroma_width(&self) -> u32 {
|
||||
self.handle.chroma_width()
|
||||
}
|
||||
|
||||
pub fn chroma_height(&self) -> i32 {
|
||||
pub fn chroma_height(&self) -> u32 {
|
||||
self.handle.chroma_height()
|
||||
}
|
||||
|
||||
pub fn stride_y(&self) -> i32 {
|
||||
self.handle.stride_y()
|
||||
}
|
||||
|
||||
pub fn stride_uv(&self) -> i32 {
|
||||
self.handle.stride_uv()
|
||||
pub fn strides(&self) -> (u32, u32) {
|
||||
(self.handle.stride_y(), self.handle.stride_uv())
|
||||
}
|
||||
|
||||
pub fn data(&self) -> (&[u8], &[u8]) {
|
||||
@@ -423,7 +403,7 @@ pub mod native {
|
||||
&self,
|
||||
format: VideoFormatType,
|
||||
dst: &mut [u8],
|
||||
dst_stride: i32,
|
||||
dst_stride: u32,
|
||||
dst_width: i32,
|
||||
dst_height: i32,
|
||||
) -> Result<(), ConvertError>;
|
||||
@@ -438,7 +418,7 @@ pub mod native {
|
||||
&self,
|
||||
format: VideoFormatType,
|
||||
dst: &mut [u8],
|
||||
dst_stride: i32,
|
||||
dst_stride: u32,
|
||||
dst_width: i32,
|
||||
dst_height: i32,
|
||||
) -> Result<(), ConvertError> {
|
||||
@@ -447,42 +427,6 @@ pub mod native {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: VideoFrameBuffer + ?Sized> internal::BufferInternal for Box<T> {
|
||||
fn sys_handle(&self) -> &webrtc_sys::video_frame_buffer::ffi::VideoFrameBuffer {
|
||||
self.as_ref().sys_handle()
|
||||
}
|
||||
|
||||
fn to_i420(&self) -> I420Buffer {
|
||||
self.as_ref().to_i420()
|
||||
}
|
||||
|
||||
fn to_argb(
|
||||
&self,
|
||||
format: VideoFormatType,
|
||||
dst: &mut [u8],
|
||||
dst_stride: i32,
|
||||
dst_width: i32,
|
||||
dst_height: i32,
|
||||
) -> Result<(), self::native::ConvertError> {
|
||||
self.as_ref()
|
||||
.to_argb(format, dst, dst_stride, dst_width, dst_height)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: VideoFrameBuffer + ?Sized> VideoFrameBuffer for Box<T> {
|
||||
fn width(&self) -> i32 {
|
||||
self.as_ref().width()
|
||||
}
|
||||
|
||||
fn height(&self) -> i32 {
|
||||
self.as_ref().height()
|
||||
}
|
||||
|
||||
fn buffer_type(&self) -> VideoFrameBufferType {
|
||||
self.as_ref().buffer_type()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub mod web {
|
||||
use super::VideoFrameBuffer;
|
||||
|
||||
@@ -18,7 +18,7 @@ pub mod native {
|
||||
}
|
||||
|
||||
impl NativeVideoSource {
|
||||
pub fn capture_frame<T: VideoFrameBuffer>(&self, frame: &VideoFrame<T>) {
|
||||
pub fn capture_frame<T: AsRef<dyn VideoFrameBuffer>>(&self, frame: &VideoFrame<T>) {
|
||||
self.handle.capture_frame(frame)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user