1818//! in encoded video frames as trailers. The timestamps are preserved
1919//! through the WebRTC pipeline and can be extracted on the receiver side.
2020//!
21- //! This works independently of e2ee encryption - timestamps can be
22- //! embedded even when encryption is disabled.
21+ //! On the send side, user timestamps are stored in the handler's internal
22+ //! map keyed by capture timestamp. When the encoder produces a frame,
23+ //! the transformer looks up the user timestamp via the frame's CaptureTime().
24+ //!
25+ //! On the receive side, extracted user timestamps are stored in an
26+ //! internal map keyed by RTP timestamp. Decoded frames look up their
27+ //! user timestamp via lookup_user_timestamp(rtp_timestamp).
2328
2429use cxx:: SharedPtr ;
2530use webrtc_sys:: user_timestamp:: ffi as sys_ut;
@@ -30,94 +35,15 @@ use crate::{
3035 rtp_sender:: RtpSender ,
3136} ;
3237
33- /// Thread-safe store for mapping capture timestamps to user timestamps.
34- ///
35- /// Used on the sender side to correlate video frame capture time with
36- /// the user timestamp that should be embedded in the encoded frame.
37- #[ derive( Clone ) ]
38- pub struct UserTimestampStore {
39- sys_handle : SharedPtr < sys_ut:: UserTimestampStore > ,
40- }
41-
42- impl UserTimestampStore {
43- /// Create a new user timestamp store.
44- pub fn new ( ) -> Self {
45- Self {
46- sys_handle : sys_ut:: new_user_timestamp_store ( ) ,
47- }
48- }
49-
50- /// Store a user timestamp associated with a capture timestamp.
51- ///
52- /// Call this when capturing a video frame with a user timestamp.
53- /// The `capture_timestamp_us` should match the `timestamp_us` field
54- /// of the VideoFrame.
55- pub fn store ( & self , capture_timestamp_us : i64 , user_timestamp_us : i64 ) {
56- log:: info!(
57- target: "user_timestamp" ,
58- "store: capture_ts_us={}, user_ts_us={}" ,
59- capture_timestamp_us,
60- user_timestamp_us
61- ) ;
62- self . sys_handle . store ( capture_timestamp_us, user_timestamp_us) ;
63- }
64-
65- /// Lookup a user timestamp by capture timestamp (for debugging).
66- /// Returns None if not found.
67- pub fn lookup ( & self , capture_timestamp_us : i64 ) -> Option < i64 > {
68- let result = self . sys_handle . lookup ( capture_timestamp_us) ;
69- if result < 0 {
70- None
71- } else {
72- Some ( result)
73- }
74- }
75-
76- /// Pop the oldest user timestamp from the queue.
77- /// Returns None if the queue is empty.
78- pub fn pop ( & self ) -> Option < i64 > {
79- let result = self . sys_handle . pop ( ) ;
80- if result < 0 {
81- None
82- } else {
83- Some ( result)
84- }
85- }
86-
87- /// Peek at the oldest user timestamp without removing it.
88- /// Returns None if the queue is empty.
89- pub fn peek ( & self ) -> Option < i64 > {
90- let result = self . sys_handle . peek ( ) ;
91- if result < 0 {
92- None
93- } else {
94- Some ( result)
95- }
96- }
97-
98- /// Clear old entries (older than the given threshold in microseconds).
99- pub fn prune ( & self , max_age_us : i64 ) {
100- self . sys_handle . prune ( max_age_us) ;
101- }
102-
103- pub ( crate ) fn sys_handle ( & self ) -> SharedPtr < sys_ut:: UserTimestampStore > {
104- self . sys_handle . clone ( )
105- }
106- }
107-
108- impl Default for UserTimestampStore {
109- fn default ( ) -> Self {
110- Self :: new ( )
111- }
112- }
113-
11438/// Handler for user timestamp embedding/extraction on RTP streams.
11539///
116- /// For sender side: Embeds user timestamps as 12-byte trailers on
117- /// encoded frames before they are sent.
40+ /// For sender side: Stores user timestamps keyed by capture timestamp
41+ /// and embeds them as 12-byte trailers on encoded frames before they
42+ /// are sent. Use `store_user_timestamp()` to associate a user timestamp
43+ /// with a captured frame.
11844///
11945/// For receiver side: Extracts user timestamps from received frames
120- /// and makes them available for retrieval.
46+ /// and makes them available for retrieval via `lookup_user_timestamp()` .
12147#[ derive( Clone ) ]
12248pub struct UserTimestampHandler {
12349 sys_handle : SharedPtr < sys_ut:: UserTimestampHandler > ,
@@ -164,24 +90,44 @@ impl UserTimestampHandler {
16490 }
16591 }
16692
93+ /// Store a user timestamp for a given capture timestamp (sender side).
94+ ///
95+ /// The `capture_timestamp_us` must be the TimestampAligner-adjusted
96+ /// timestamp (as produced by `VideoTrackSource::on_captured_frame`),
97+ /// NOT the original `timestamp_us` from the VideoFrame. The transformer
98+ /// looks up the user timestamp by the frame's `CaptureTime()` which is
99+ /// derived from the aligned value.
100+ ///
101+ /// In normal usage this is called automatically by the C++ layer —
102+ /// callers should set `user_timestamp_us` on the `VideoFrame` and let
103+ /// `capture_frame` / `on_captured_frame` handle the rest.
104+ pub fn store_user_timestamp ( & self , capture_timestamp_us : i64 , user_timestamp_us : i64 ) {
105+ log:: info!(
106+ target: "user_timestamp" ,
107+ "store: capture_ts_us={}, user_ts_us={}" ,
108+ capture_timestamp_us,
109+ user_timestamp_us
110+ ) ;
111+ self . sys_handle . store_user_timestamp ( capture_timestamp_us, user_timestamp_us) ;
112+ }
113+
167114 pub ( crate ) fn sys_handle ( & self ) -> SharedPtr < sys_ut:: UserTimestampHandler > {
168115 self . sys_handle . clone ( )
169116 }
170117}
171118
172119/// Create a sender-side user timestamp handler.
173120///
174- /// This handler will embed user timestamps from the provided store
175- /// into encoded frames before they are packetized and sent.
121+ /// This handler will embed user timestamps into encoded frames before
122+ /// they are packetized and sent. Use `store_user_timestamp()` to
123+ /// associate a user timestamp with a captured frame's capture timestamp.
176124pub fn create_sender_handler (
177125 peer_factory : & PeerConnectionFactory ,
178- store : & UserTimestampStore ,
179126 sender : & RtpSender ,
180127) -> UserTimestampHandler {
181128 UserTimestampHandler {
182129 sys_handle : sys_ut:: new_user_timestamp_sender (
183130 peer_factory. handle . sys_handle . clone ( ) ,
184- store. sys_handle ( ) ,
185131 sender. handle . sys_handle . clone ( ) ,
186132 ) ,
187133 }
@@ -195,13 +141,11 @@ pub fn create_sender_handler(
195141/// timestamp for a specific decoded frame.
196142pub fn create_receiver_handler (
197143 peer_factory : & PeerConnectionFactory ,
198- store : & UserTimestampStore ,
199144 receiver : & RtpReceiver ,
200145) -> UserTimestampHandler {
201146 UserTimestampHandler {
202147 sys_handle : sys_ut:: new_user_timestamp_receiver (
203148 peer_factory. handle . sys_handle . clone ( ) ,
204- store. sys_handle ( ) ,
205149 receiver. handle . sys_handle . clone ( ) ,
206150 ) ,
207151 }
0 commit comments