Skip to main content

webrtc_sys/
packet_trailer.rs

1// Copyright 2026 LiveKit, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::impl_thread_safety;
16
17/// Callback invoked for native video publish pipeline timing events.
18pub type OnVideoPublishTiming = Box<dyn Fn(ffi::VideoPublishTimingEvent) + Send + Sync + 'static>;
19/// Callback invoked for native video subscribe pipeline timing events.
20pub type OnVideoSubscribeTiming =
21    Box<dyn Fn(ffi::VideoSubscribeTimingEvent) + Send + Sync + 'static>;
22
23#[cxx::bridge(namespace = "livekit_ffi")]
24pub mod ffi {
25    #[repr(i32)]
26    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
27    pub enum VideoPublishTimingStage {
28        EncoderUpload,
29        EncoderOutput,
30        WebrtcPacketize,
31    }
32
33    #[repr(i32)]
34    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
35    pub enum VideoSubscribeTimingStage {
36        WebrtcReceive,
37        DecoderUpload,
38        DecoderOutput,
39    }
40
41    #[derive(Debug, Clone, Copy)]
42    pub struct VideoPublishTimingEvent {
43        pub stage: VideoPublishTimingStage,
44        pub timestamp_us: u64,
45        pub capture_timestamp_us: u64,
46        pub frame_id: u32,
47    }
48
49    #[derive(Debug, Clone, Copy)]
50    pub struct VideoSubscribeTimingEvent {
51        pub stage: VideoSubscribeTimingStage,
52        pub timestamp_us: u64,
53        pub capture_timestamp_us: u64,
54        pub frame_id: u32,
55    }
56
57    unsafe extern "C++" {
58        include!("livekit/packet_trailer.h");
59        include!("livekit/rtp_sender.h");
60        include!("livekit/rtp_receiver.h");
61        include!("livekit/peer_connection_factory.h");
62
63        type RtpSender = crate::rtp_sender::ffi::RtpSender;
64        type RtpReceiver = crate::rtp_receiver::ffi::RtpReceiver;
65        type PeerConnectionFactory = crate::peer_connection_factory::ffi::PeerConnectionFactory;
66
67        /// Handler for packet trailer embedding/extraction on RTP streams.
68        pub type PacketTrailerHandler;
69
70        /// Enable/disable timestamp embedding.
71        fn set_enabled(self: &PacketTrailerHandler, enabled: bool);
72
73        /// Check if timestamp embedding is enabled.
74        fn enabled(self: &PacketTrailerHandler) -> bool;
75
76        /// Lookup the user timestamp for a given RTP timestamp (receiver side).
77        /// Returns -1 if not found. The entry is removed after lookup.
78        /// Also caches the frame_id for retrieval via last_lookup_frame_id().
79        fn lookup_timestamp(self: &PacketTrailerHandler, rtp_timestamp: u32) -> u64;
80
81        /// Returns the frame_id from the most recent successful
82        /// lookup_timestamp() call.
83        fn last_lookup_frame_id(self: &PacketTrailerHandler) -> u32;
84
85        /// Returns the user_data from the most recent successful
86        /// lookup_timestamp() call. Empty if none.
87        fn last_lookup_user_data(self: &PacketTrailerHandler) -> Vec<u8>;
88
89        /// Store frame metadata for a given capture timestamp (sender side).
90        fn store_frame_metadata(
91            self: &PacketTrailerHandler,
92            capture_timestamp_us: i64,
93            user_timestamp: u64,
94            frame_id: u32,
95            user_data: &[u8],
96        );
97
98        /// Set a callback for sender-side publish timing events.
99        fn set_publish_timing_observer(
100            self: &PacketTrailerHandler,
101            observer: Box<VideoPublishTimingObserverWrapper>,
102        );
103
104        /// Clear the sender-side publish timing callback.
105        fn clear_publish_timing_observer(self: &PacketTrailerHandler);
106
107        /// Set a callback for receiver-side subscribe timing events.
108        fn set_subscribe_timing_observer(
109            self: &PacketTrailerHandler,
110            observer: Box<VideoSubscribeTimingObserverWrapper>,
111        );
112
113        /// Clear the receiver-side subscribe timing callback.
114        fn clear_subscribe_timing_observer(self: &PacketTrailerHandler);
115
116        /// Emit a receiver-side subscribe timing event.
117        fn emit_subscribe_timing(
118            self: &PacketTrailerHandler,
119            stage: VideoSubscribeTimingStage,
120            user_timestamp: u64,
121            frame_id: u32,
122        );
123
124        /// Create a new packet trailer handler for a sender.
125        fn new_packet_trailer_sender(
126            peer_factory: SharedPtr<PeerConnectionFactory>,
127            sender: SharedPtr<RtpSender>,
128        ) -> SharedPtr<PacketTrailerHandler>;
129
130        /// Create a new packet trailer handler for a receiver.
131        fn new_packet_trailer_receiver(
132            peer_factory: SharedPtr<PeerConnectionFactory>,
133            receiver: SharedPtr<RtpReceiver>,
134        ) -> SharedPtr<PacketTrailerHandler>;
135    }
136
137    extern "Rust" {
138        type VideoPublishTimingObserverWrapper;
139        type VideoSubscribeTimingObserverWrapper;
140
141        fn on_publish_timing(
142            self: &VideoPublishTimingObserverWrapper,
143            event: VideoPublishTimingEvent,
144        );
145
146        fn on_subscribe_timing(
147            self: &VideoSubscribeTimingObserverWrapper,
148            event: VideoSubscribeTimingEvent,
149        );
150    }
151}
152
153impl_thread_safety!(ffi::PacketTrailerHandler, Send + Sync);
154
155pub struct VideoPublishTimingObserverWrapper {
156    observer: OnVideoPublishTiming,
157}
158
159impl VideoPublishTimingObserverWrapper {
160    pub fn new(observer: OnVideoPublishTiming) -> Self {
161        Self { observer }
162    }
163
164    fn on_publish_timing(&self, event: ffi::VideoPublishTimingEvent) {
165        (self.observer)(event);
166    }
167}
168
169pub struct VideoSubscribeTimingObserverWrapper {
170    observer: OnVideoSubscribeTiming,
171}
172
173impl VideoSubscribeTimingObserverWrapper {
174    pub fn new(observer: OnVideoSubscribeTiming) -> Self {
175        Self { observer }
176    }
177
178    fn on_subscribe_timing(&self, event: ffi::VideoSubscribeTimingEvent) {
179        (self.observer)(event);
180    }
181}