Skip to content

Commit 30cf156

Browse files
committed
fix/feat: SystemTime instead of timestamp
Added sequence numbers as well. Created function to grab latest buffer instead of latest ready one.
1 parent c03f15a commit 30cf156

File tree

2 files changed

+84
-35
lines changed

2 files changed

+84
-35
lines changed

src/capturer/engine/linux/mod.rs

Lines changed: 72 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ use std::{
55
mpsc::{self, sync_channel, SyncSender},
66
},
77
thread::JoinHandle,
8-
time::Duration,
8+
time::{Duration, SystemTime},
99
};
1010

11-
use pipewire as pw;
11+
use pipewire::{self as pw, spa::sys::spa_meta_type, sys::pw_buffer};
1212
use pw::{
1313
context::Context,
1414
main_loop::MainLoop,
@@ -31,7 +31,7 @@ use pw::{
3131

3232
use crate::{
3333
capturer::Options,
34-
frame::{BGRxFrame, Frame, RGBFrame, RGBxFrame, XBGRFrame},
34+
frame::{BGRxFrame, Frame, RGBFrame, RGBxFrame, VideoFrame, XBGRFrame},
3535
};
3636

3737
use self::{error::LinCapError, portal::ScreenCastPortal};
@@ -91,38 +91,68 @@ fn state_changed_callback(
9191
}
9292
}
9393

94-
unsafe fn get_timestamp(buffer: *mut spa_buffer) -> i64 {
94+
unsafe fn find_meta_in_buffer<T: Copy>(buffer: *mut spa_buffer, type_: spa_meta_type) -> Option<T> {
9595
let n_metas = (*buffer).n_metas;
96-
if n_metas > 0 {
97-
let mut meta_ptr = (*buffer).metas;
98-
let metas_end = (*buffer).metas.wrapping_add(n_metas as usize);
99-
while meta_ptr != metas_end {
100-
if (*meta_ptr).type_ == SPA_META_Header {
101-
let meta_header: &mut spa_meta_header =
102-
&mut *((*meta_ptr).data as *mut spa_meta_header);
103-
return meta_header.pts;
104-
}
105-
meta_ptr = meta_ptr.wrapping_add(1);
96+
let mut meta_ptr = (*buffer).metas;
97+
let metas_end = (*buffer).metas.wrapping_add(n_metas as usize);
98+
99+
while meta_ptr != metas_end {
100+
if (*meta_ptr).type_ == type_ {
101+
let target: T = *((*meta_ptr).data as *mut T);
102+
103+
return Some(target);
106104
}
107-
0
105+
106+
meta_ptr = meta_ptr.wrapping_add(1);
107+
}
108+
109+
None
110+
}
111+
112+
unsafe fn get_timestamp_and_sequence(buffer: *mut spa_buffer) -> (i64, u64) {
113+
let meta_header: Option<spa_meta_header> = find_meta_in_buffer(buffer, SPA_META_Header);
114+
115+
if let Some(meta_header) = meta_header {
116+
(meta_header.pts, meta_header.seq)
108117
} else {
109-
0
118+
(0, 0)
110119
}
111120
}
112121

122+
unsafe fn find_most_recent_buffer(stream: &StreamRef) -> *mut pw_buffer {
123+
let mut buffer: *mut pw_buffer = std::ptr::null_mut();
124+
125+
loop {
126+
let tmp = stream.dequeue_raw_buffer();
127+
if tmp.is_null() {
128+
break;
129+
}
130+
131+
if !buffer.is_null() {
132+
stream.queue_raw_buffer(buffer);
133+
}
134+
135+
buffer = tmp;
136+
}
137+
138+
buffer
139+
}
140+
113141
fn process_callback(stream: &StreamRef, user_data: &mut ListenerUserData) {
114-
let buffer = unsafe { stream.dequeue_raw_buffer() };
115-
if !buffer.is_null() {
142+
let pw_buffer = unsafe { find_most_recent_buffer(stream) };
143+
if !pw_buffer.is_null() {
116144
'outside: {
117-
let buffer = unsafe { (*buffer).buffer };
145+
let buffer = unsafe { (*pw_buffer).buffer };
118146
if buffer.is_null() {
119147
break 'outside;
120148
}
121-
let timestamp = unsafe { get_timestamp(buffer) };
149+
150+
let (timestamp, sequence) = unsafe { get_timestamp_and_sequence(buffer) };
151+
let timestamp = SystemTime::UNIX_EPOCH + Duration::from_nanos(timestamp as u64);
122152

123153
let n_datas = unsafe { (*buffer).n_datas };
124154
if n_datas < 1 {
125-
return;
155+
break 'outside;
126156
}
127157
let frame_size = user_data.format.size();
128158
let frame_data: Vec<u8> = unsafe {
@@ -134,30 +164,38 @@ fn process_callback(stream: &StreamRef, user_data: &mut ListenerUserData) {
134164
};
135165

136166
if let Err(e) = match user_data.format.format() {
137-
VideoFormat::RGBx => user_data.tx.send(Frame::RGBx(RGBxFrame {
138-
display_time: timestamp as u64,
167+
VideoFormat::RGBx => user_data.tx.send(Frame::Video(VideoFrame::RGBx(RGBxFrame {
168+
display_time: timestamp,
169+
processed_time: SystemTime::now(),
170+
sequence,
139171
width: frame_size.width as i32,
140172
height: frame_size.height as i32,
141173
data: frame_data,
142-
})),
143-
VideoFormat::RGB => user_data.tx.send(Frame::RGB(RGBFrame {
144-
display_time: timestamp as u64,
174+
}))),
175+
VideoFormat::RGB => user_data.tx.send(Frame::Video(VideoFrame::RGB(RGBFrame {
176+
display_time: timestamp,
177+
processed_time: SystemTime::now(),
178+
sequence,
145179
width: frame_size.width as i32,
146180
height: frame_size.height as i32,
147181
data: frame_data,
148-
})),
149-
VideoFormat::xBGR => user_data.tx.send(Frame::XBGR(XBGRFrame {
150-
display_time: timestamp as u64,
182+
}))),
183+
VideoFormat::xBGR => user_data.tx.send(Frame::Video(VideoFrame::XBGR(XBGRFrame {
184+
display_time: timestamp,
185+
processed_time: SystemTime::now(),
186+
sequence,
151187
width: frame_size.width as i32,
152188
height: frame_size.height as i32,
153189
data: frame_data,
154-
})),
155-
VideoFormat::BGRx => user_data.tx.send(Frame::BGRx(BGRxFrame {
156-
display_time: timestamp as u64,
190+
}))),
191+
VideoFormat::BGRx => user_data.tx.send(Frame::Video(VideoFrame::BGRx(BGRxFrame {
192+
display_time: timestamp,
193+
processed_time: SystemTime::now(),
194+
sequence,
157195
width: frame_size.width as i32,
158196
height: frame_size.height as i32,
159197
data: frame_data,
160-
})),
198+
}))),
161199
_ => panic!("Unsupported frame format received"),
162200
} {
163201
eprintln!("{e}");
@@ -166,8 +204,7 @@ fn process_callback(stream: &StreamRef, user_data: &mut ListenerUserData) {
166204
} else {
167205
eprintln!("Out of buffers");
168206
}
169-
170-
unsafe { stream.queue_raw_buffer(buffer) };
207+
unsafe { stream.queue_raw_buffer(pw_buffer) };
171208
}
172209

173210
// TODO: Format negotiation

src/frame/video.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ pub struct YUVFrame {
1414
#[derive(Debug, Clone)]
1515
pub struct RGBFrame {
1616
pub display_time: SystemTime,
17+
pub processed_time: SystemTime,
18+
pub sequence: u64,
1719
pub width: i32,
1820
pub height: i32,
1921
pub data: Vec<u8>,
@@ -29,6 +31,8 @@ pub struct RGB8Frame {
2931
#[derive(Debug, Clone)]
3032
pub struct RGBxFrame {
3133
pub display_time: SystemTime,
34+
pub processed_time: SystemTime,
35+
pub sequence: u64,
3236
pub width: i32,
3337
pub height: i32,
3438
pub data: Vec<u8>,
@@ -37,6 +41,8 @@ pub struct RGBxFrame {
3741
#[derive(Debug, Clone)]
3842
pub struct XBGRFrame {
3943
pub display_time: SystemTime,
44+
pub processed_time: SystemTime,
45+
pub sequence: u64,
4046
pub width: i32,
4147
pub height: i32,
4248
pub data: Vec<u8>,
@@ -45,6 +51,8 @@ pub struct XBGRFrame {
4551
#[derive(Debug, Clone)]
4652
pub struct BGRxFrame {
4753
pub display_time: SystemTime,
54+
pub processed_time: SystemTime,
55+
pub sequence: u64,
4856
pub width: i32,
4957
pub height: i32,
5058
pub data: Vec<u8>,
@@ -53,6 +61,8 @@ pub struct BGRxFrame {
5361
#[derive(Debug, Clone)]
5462
pub struct BGRFrame {
5563
pub display_time: SystemTime,
64+
pub processed_time: SystemTime,
65+
pub sequence: u64,
5666
pub width: i32,
5767
pub height: i32,
5868
pub data: Vec<u8>,
@@ -61,6 +71,8 @@ pub struct BGRFrame {
6171
#[derive(Debug, Clone)]
6272
pub struct BGRAFrame {
6373
pub display_time: SystemTime,
74+
pub processed_time: SystemTime,
75+
pub sequence: u64,
6476
pub width: i32,
6577
pub height: i32,
6678
pub data: Vec<u8>,

0 commit comments

Comments
 (0)