4141//! 3. The bridge's WebRTC side connects to the WebRTC client
4242//! 4. The bridge's RTP side connects to the SIP/RTP endpoint
4343
44+ use crate :: media:: ReceiveTimestampClock ;
4445use crate :: media:: recorder:: { Leg as RecLeg , Recorder } ;
4546use crate :: media:: transcoder:: { RtpTiming , Transcoder , rewrite_dtmf_duration} ;
4647use anyhow:: Result ;
@@ -340,7 +341,8 @@ pub struct BridgePeer {
340341 /// When true, the bridge skips writing to the recorder (recording paused).
341342 recording_paused : Arc < AtomicBool > ,
342343 /// Non-blocking RTP capture tee for SipFlow.
343- sipflow_tx : Option < mpsc:: Sender < ( RecLeg , MediaSample ) > > ,
344+ sipflow_tx : Option < mpsc:: Sender < ( RecLeg , MediaSample , u64 ) > > ,
345+ receive_clock : ReceiveTimestampClock ,
344346 dtmf_sink : Arc < parking_lot:: RwLock < Option < BridgeDtmfSink > > > ,
345347 /// Audio sender channels for forwarding — fast-path aliases
346348 caller_send : Arc < AsyncMutex < Option < MediaSender > > > ,
@@ -411,6 +413,7 @@ impl BridgePeer {
411413 recorder : None ,
412414 recording_paused : Arc :: new ( AtomicBool :: new ( false ) ) ,
413415 sipflow_tx : None ,
416+ receive_clock : ReceiveTimestampClock :: new ( ) ,
414417 dtmf_sink : Arc :: new ( parking_lot:: RwLock :: new ( None ) ) ,
415418 caller_send : Arc :: new ( AsyncMutex :: new ( None ) ) ,
416419 callee_send : Arc :: new ( AsyncMutex :: new ( None ) ) ,
@@ -1314,6 +1317,7 @@ impl BridgePeer {
13141317 let recorder = self . recorder . clone ( ) ;
13151318 let recording_paused = self . recording_paused . clone ( ) ;
13161319 let sipflow_tx = self . sipflow_tx . clone ( ) ;
1320+ let receive_clock = self . receive_clock . clone ( ) ;
13171321 let dtmf_sink = Arc :: clone ( & self . dtmf_sink ) ;
13181322 let caller_to_callee_transcoder = Arc :: clone ( & self . caller_to_callee_transcoder ) ;
13191323 let caller_to_callee_timing = Arc :: clone ( & self . caller_to_callee_timing ) ;
@@ -1432,6 +1436,7 @@ impl BridgePeer {
14321436 if !is_video { recorder. clone( ) } else { None } ,
14331437 if !is_video { Some ( RecLeg :: A ) } else { None } ,
14341438 if !is_video { sipflow_tx. clone( ) } else { None } ,
1439+ receive_clock. clone( ) ,
14351440 recording_paused. clone( ) ,
14361441 Arc :: clone( & dtmf_sink) ,
14371442 Some ( Arc :: clone( & caller_to_callee_transcoder) ) ,
@@ -1556,6 +1561,7 @@ impl BridgePeer {
15561561 if !is_video { recorder. clone( ) } else { None } ,
15571562 if !is_video { Some ( RecLeg :: B ) } else { None } ,
15581563 if !is_video { sipflow_tx. clone( ) } else { None } ,
1564+ receive_clock. clone( ) ,
15591565 recording_paused. clone( ) ,
15601566 Arc :: clone( & dtmf_sink) ,
15611567 Some ( Arc :: clone( & callee_to_caller_transcoder) ) ,
@@ -1603,7 +1609,8 @@ impl BridgePeer {
16031609 leg_stats : Arc < LegStats > ,
16041610 recorder : Option < Arc < parking_lot:: RwLock < Option < Recorder > > > > ,
16051611 recorder_leg : Option < RecLeg > ,
1606- sipflow_tx : Option < mpsc:: Sender < ( RecLeg , MediaSample ) > > ,
1612+ sipflow_tx : Option < mpsc:: Sender < ( RecLeg , MediaSample , u64 ) > > ,
1613+ receive_clock : ReceiveTimestampClock ,
16071614 recording_paused : Arc < AtomicBool > ,
16081615 dtmf_sink : Arc < parking_lot:: RwLock < Option < BridgeDtmfSink > > > ,
16091616 transcoder : Option < Arc < parking_lot:: Mutex < Option < Transcoder > > > > ,
@@ -1661,6 +1668,7 @@ impl BridgePeer {
16611668 match sample_result {
16621669 Ok ( sample) => {
16631670 packet_count += 1 ;
1671+ let received_at_micros = receive_clock. now_micros( ) ;
16641672 if !is_video {
16651673 if let ( Some ( rec) , Some ( leg) ) = ( & recorder, recorder_leg)
16661674 && !recording_paused. load( std:: sync:: atomic:: Ordering :: Relaxed )
@@ -1677,7 +1685,7 @@ impl BridgePeer {
16771685 }
16781686
16791687 if let ( Some ( tx) , Some ( leg) ) = ( & sipflow_tx, recorder_leg) {
1680- let _ = tx. try_send( ( leg, sample. clone( ) ) ) ;
1688+ let _ = tx. try_send( ( leg, sample. clone( ) , received_at_micros ) ) ;
16811689 }
16821690 }
16831691 if !is_video {
@@ -2005,7 +2013,8 @@ impl BridgePeer {
20052013 leg_stats : Arc < LegStats > ,
20062014 recorder : Option < Arc < parking_lot:: RwLock < Option < Recorder > > > > ,
20072015 recorder_leg : Option < RecLeg > ,
2008- sipflow_tx : Option < mpsc:: Sender < ( RecLeg , MediaSample ) > > ,
2016+ sipflow_tx : Option < mpsc:: Sender < ( RecLeg , MediaSample , u64 ) > > ,
2017+ receive_clock : ReceiveTimestampClock ,
20092018 recording_paused : Arc < AtomicBool > ,
20102019 dtmf_sink : Arc < parking_lot:: RwLock < Option < BridgeDtmfSink > > > ,
20112020 transcoder : Option < Arc < parking_lot:: Mutex < Option < Transcoder > > > > ,
@@ -2025,6 +2034,7 @@ impl BridgePeer {
20252034 recorder,
20262035 recorder_leg,
20272036 sipflow_tx,
2037+ receive_clock,
20282038 recording_paused,
20292039 dtmf_sink,
20302040 transcoder,
@@ -2102,7 +2112,7 @@ pub struct BridgePeerBuilder {
21022112 ice_servers : Vec < IceServer > ,
21032113 recorder : Option < Arc < parking_lot:: RwLock < Option < Recorder > > > > ,
21042114 recording_paused : Arc < AtomicBool > ,
2105- sipflow_tx : Option < mpsc:: Sender < ( RecLeg , MediaSample ) > > ,
2115+ sipflow_tx : Option < mpsc:: Sender < ( RecLeg , MediaSample , u64 ) > > ,
21062116 cname : Option < String > ,
21072117}
21082118
@@ -2251,7 +2261,7 @@ impl BridgePeerBuilder {
22512261
22522262 pub fn with_sipflow_capture (
22532263 mut self ,
2254- sipflow_tx : mpsc:: Sender < ( RecLeg , MediaSample ) > ,
2264+ sipflow_tx : mpsc:: Sender < ( RecLeg , MediaSample , u64 ) > ,
22552265 ) -> Self {
22562266 self . sipflow_tx = Some ( sipflow_tx) ;
22572267 self
@@ -3632,6 +3642,7 @@ mod tests {
36323642 None , // no recorder
36333643 None , // no recorder leg
36343644 None , // no sipflow capture
3645+ ReceiveTimestampClock :: new ( ) ,
36353646 Arc :: new ( AtomicBool :: new ( false ) ) , // not paused
36363647 ds,
36373648 tr,
@@ -3736,6 +3747,7 @@ mod tests {
37363747 None ,
37373748 None ,
37383749 None ,
3750+ ReceiveTimestampClock :: new ( ) ,
37393751 Arc :: new ( AtomicBool :: new ( false ) ) ,
37403752 ds,
37413753 tr,
@@ -4051,6 +4063,7 @@ mod tests {
40514063 None ,
40524064 None ,
40534065 None ,
4066+ ReceiveTimestampClock :: new ( ) ,
40544067 Arc :: new ( AtomicBool :: new ( false ) ) ,
40554068 ds,
40564069 None , // no transcoder
0 commit comments