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        /// Store frame metadata for a given capture timestamp (sender side).
86        fn store_frame_metadata(
87            self: &PacketTrailerHandler,
88            capture_timestamp_us: i64,
89            user_timestamp: u64,
90            frame_id: u32,
91        );
92
93        /// Set a callback for sender-side publish timing events.
94        fn set_publish_timing_observer(
95            self: &PacketTrailerHandler,
96            observer: Box<VideoPublishTimingObserverWrapper>,
97        );
98
99        /// Clear the sender-side publish timing callback.
100        fn clear_publish_timing_observer(self: &PacketTrailerHandler);
101
102        /// Set a callback for receiver-side subscribe timing events.
103        fn set_subscribe_timing_observer(
104            self: &PacketTrailerHandler,
105            observer: Box<VideoSubscribeTimingObserverWrapper>,
106        );
107
108        /// Clear the receiver-side subscribe timing callback.
109        fn clear_subscribe_timing_observer(self: &PacketTrailerHandler);
110
111        /// Emit a receiver-side subscribe timing event.
112        fn emit_subscribe_timing(
113            self: &PacketTrailerHandler,
114            stage: VideoSubscribeTimingStage,
115            user_timestamp: u64,
116            frame_id: u32,
117        );
118
119        /// Create a new packet trailer handler for a sender.
120        fn new_packet_trailer_sender(
121            peer_factory: SharedPtr<PeerConnectionFactory>,
122            sender: SharedPtr<RtpSender>,
123        ) -> SharedPtr<PacketTrailerHandler>;
124
125        /// Create a new packet trailer handler for a receiver.
126        fn new_packet_trailer_receiver(
127            peer_factory: SharedPtr<PeerConnectionFactory>,
128            receiver: SharedPtr<RtpReceiver>,
129        ) -> SharedPtr<PacketTrailerHandler>;
130    }
131
132    extern "Rust" {
133        type VideoPublishTimingObserverWrapper;
134        type VideoSubscribeTimingObserverWrapper;
135
136        fn on_publish_timing(
137            self: &VideoPublishTimingObserverWrapper,
138            event: VideoPublishTimingEvent,
139        );
140
141        fn on_subscribe_timing(
142            self: &VideoSubscribeTimingObserverWrapper,
143            event: VideoSubscribeTimingEvent,
144        );
145    }
146}
147
148impl_thread_safety!(ffi::PacketTrailerHandler, Send + Sync);
149
150pub struct VideoPublishTimingObserverWrapper {
151    observer: OnVideoPublishTiming,
152}
153
154impl VideoPublishTimingObserverWrapper {
155    pub fn new(observer: OnVideoPublishTiming) -> Self {
156        Self { observer }
157    }
158
159    fn on_publish_timing(&self, event: ffi::VideoPublishTimingEvent) {
160        (self.observer)(event);
161    }
162}
163
164pub struct VideoSubscribeTimingObserverWrapper {
165    observer: OnVideoSubscribeTiming,
166}
167
168impl VideoSubscribeTimingObserverWrapper {
169    pub fn new(observer: OnVideoSubscribeTiming) -> Self {
170        Self { observer }
171    }
172
173    fn on_subscribe_timing(&self, event: ffi::VideoSubscribeTimingEvent) {
174        (self.observer)(event);
175    }
176}