@@ -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 } ;
1212use pw:: {
1313 context:: Context ,
1414 main_loop:: MainLoop ,
@@ -31,7 +31,7 @@ use pw::{
3131
3232use crate :: {
3333 capturer:: Options ,
34- frame:: { BGRxFrame , Frame , RGBFrame , RGBxFrame , XBGRFrame } ,
34+ frame:: { BGRxFrame , Frame , RGBFrame , RGBxFrame , VideoFrame , XBGRFrame } ,
3535} ;
3636
3737use 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+
113141fn 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
0 commit comments