Skip to main content

rtc/rtp_transceiver/rtp_receiver/
mod.rs

1//! RTP Receiver implementation following the W3C WebRTC specification.
2//!
3//! This module provides the [`RTCRtpReceiver`] which represents an RTP receiver
4//! as defined in the [W3C WebRTC specification](https://www.w3.org/TR/webrtc/#rtcrtpreceiver-interface).
5//!
6//! # Overview
7//!
8//! An RTP receiver manages the reception of media from a remote peer, providing:
9//! - Access to the received media track
10//! - RTP capabilities and receive parameters
11//! - Contributing source (CSRC) and synchronization source (SSRC) information
12//! - Statistics about received media
13//!
14//! # Examples
15//!
16//! ## Accessing the received track
17//!
18//! ```no_run
19//! # use rtc::peer_connection::RTCPeerConnectionBuilder;
20//! # use rtc::media_stream::MediaStreamTrackId;
21//! # use rtc::rtp_transceiver::RTCRtpReceiverId;
22//! # fn example(
23//! #     receiver_id: RTCRtpReceiverId,
24//! #     track_id: MediaStreamTrackId
25//! # ) -> Result<(), Box<dyn std::error::Error>> {
26//! let mut peer_connection = RTCPeerConnectionBuilder::new().build()?;
27//!
28//! // Get the receiver and access its track
29//! if let Some(receiver) = peer_connection.rtp_receiver(receiver_id) {
30//!     let track = receiver.track();
31//!     println!("Track ID: {}", track.track_id());
32//!     println!("Track kind: {:?}", track.kind());
33//!     println!("Track enabled: {}", track.enabled());
34//! }
35//! # Ok(())
36//! # }
37//! ```
38//!
39//! ## Getting receive parameters
40//!
41//! ```no_run
42//! # use rtc::peer_connection::RTCPeerConnectionBuilder;
43//! # use rtc::rtp_transceiver::RTCRtpReceiverId;
44//! # fn example(receiver_id: RTCRtpReceiverId) -> Result<(), Box<dyn std::error::Error>> {
45//! let mut peer_connection = RTCPeerConnectionBuilder::new().build()?;
46//!
47//! if let Some(mut receiver) = peer_connection.rtp_receiver(receiver_id) {
48//!     // Get current receive parameters
49//!     let params = receiver.get_parameters();
50//!     
51//!     println!("Codecs: {:?}", params.rtp_parameters.codecs);
52//!     println!("Header extensions: {:?}", params.rtp_parameters.header_extensions);
53//!     println!("RTCP CNAME: {}", params.rtp_parameters.rtcp.cname);
54//! }
55//! # Ok(())
56//! # }
57//! ```
58//!
59//! ## Checking receiver capabilities
60//!
61//! ```no_run
62//! # use rtc::peer_connection::RTCPeerConnectionBuilder;
63//! # use rtc::rtp_transceiver::rtp_sender::RtpCodecKind;
64//! # use rtc::rtp_transceiver::RTCRtpReceiverId;
65//! # fn example(receiver_id: RTCRtpReceiverId) -> Result<(), Box<dyn std::error::Error>> {
66//! let mut peer_connection = RTCPeerConnectionBuilder::new().build()?;
67//!
68//! if let Some(receiver) = peer_connection.rtp_receiver(receiver_id) {
69//!     // Check video capabilities
70//!     if let Some(capabilities) = receiver.get_capabilities(RtpCodecKind::Video) {
71//!         println!("Supported video codecs:");
72//!         for codec in capabilities.codecs {
73//!             println!("  - {} @ {} Hz", codec.mime_type, codec.clock_rate);
74//!         }
75//!     
76//!         println!("Supported header extensions:");
77//!         for ext in capabilities.header_extensions {
78//!             println!("  - {}", ext.uri);
79//!         }
80//!     }
81//! }
82//! # Ok(())
83//! # }
84//! ```
85//!
86//! ## Getting contributing sources
87//!
88//! ```no_run
89//! # use rtc::peer_connection::RTCPeerConnectionBuilder;
90//! # use rtc::rtp_transceiver::RTCRtpReceiverId;
91//! # fn example(receiver_id: RTCRtpReceiverId) -> Result<(), Box<dyn std::error::Error>> {
92//! let mut peer_connection = RTCPeerConnectionBuilder::new().build()?;
93//!
94//! if let Some(mut receiver) = peer_connection.rtp_receiver(receiver_id) {
95//!     // Get CSRC information for mixed audio
96//!     for csrc in receiver.get_contributing_sources() {
97//!         println!("CSRC: {}, timestamp: {:?}", csrc.source, csrc.timestamp);
98//!         println!("  Audio level: {}", csrc.audio_level);
99//!         println!("  RTP timestamp: {}", csrc.rtp_timestamp);
100//!     }
101//! }
102//! # Ok(())
103//! # }
104//! ```
105//!
106//! ## Getting synchronization sources
107//!
108//! ```no_run
109//! # use rtc::peer_connection::RTCPeerConnectionBuilder;
110//! # use rtc::rtp_transceiver::RTCRtpReceiverId;
111//! # fn example(receiver_id: RTCRtpReceiverId) -> Result<(), Box<dyn std::error::Error>> {
112//! let mut peer_connection = RTCPeerConnectionBuilder::new().build()?;
113//!
114//! if let Some(mut receiver) = peer_connection.rtp_receiver(receiver_id) {
115//!     // Get SSRC information
116//!     for ssrc in receiver.get_synchronization_sources() {
117//!         println!("SSRC: {}, timestamp: {:?}", ssrc.source, ssrc.timestamp);
118//!         println!("  RTP timestamp: {}", ssrc.rtp_timestamp);
119//!     }
120//! }
121//! # Ok(())
122//! # }
123//! ```
124//!
125//! ## Handling incoming receivers
126//!
127//! ```no_run
128//! # use rtc::peer_connection::RTCPeerConnectionBuilder;
129//! # fn example() -> Result<(), Box<dyn std::error::Error>> {
130//! let mut peer_connection = RTCPeerConnectionBuilder::new().build()?;
131//!
132//! // After remote description is set, collect receiver IDs first
133//! let receiver_ids: Vec<_> = peer_connection.get_receivers().collect();
134//!
135//! // Then iterate and process each receiver
136//! for receiver_id in receiver_ids {
137//!     if let Some(receiver) = peer_connection.rtp_receiver(receiver_id) {
138//!         // Access the remote track (track_id would come from signaling)
139//!         // Process the incoming media as needed
140//!     }
141//! }
142//! # Ok(())
143//! # }
144//! ```
145//!
146//! # Specifications
147//!
148//! * [W3C RTCRtpReceiver](https://www.w3.org/TR/webrtc/#rtcrtpreceiver-interface)
149//! * [MDN RTCRtpReceiver](https://developer.mozilla.org/en-US/docs/Web/API/RTCRtpReceiver)
150
151//TODO: #[cfg(test)]
152//mod rtp_receiver_test;
153
154pub(crate) mod internal;
155pub(crate) mod rtp_contributing_source;
156
157use crate::media_stream::track::MediaStreamTrack;
158use crate::peer_connection::RTCPeerConnection;
159use crate::peer_connection::message::RTCMessage;
160use crate::rtp_transceiver::RTCRtpReceiverId;
161use crate::rtp_transceiver::rtp_sender::rtp_capabilities::RTCRtpCapabilities;
162use crate::rtp_transceiver::rtp_sender::rtp_codec::RtpCodecKind;
163use crate::rtp_transceiver::rtp_sender::rtp_receiver_parameters::RTCRtpReceiveParameters;
164use interceptor::{Interceptor, NoopInterceptor};
165use sansio::Protocol;
166use shared::error::Result;
167
168pub use rtp_contributing_source::{RTCRtpContributingSource, RTCRtpSynchronizationSource};
169
170/// Represents an RTP receiver for a media stream track.
171///
172/// The `RTCRtpReceiver` interface allows an application to inspect the receipt of a
173/// [`MediaStreamTrack`] as defined in the [W3C WebRTC specification](https://www.w3.org/TR/webrtc/#rtcrtpreceiver-interface).
174///
175/// # Lifetime
176///
177/// This struct borrows the [`RTCPeerConnection`] mutably, ensuring exclusive access
178/// during RTP receiver operations.
179pub struct RTCRtpReceiver<'a, I = NoopInterceptor>
180where
181    I: Interceptor,
182{
183    pub(crate) id: RTCRtpReceiverId,
184    pub(crate) peer_connection: &'a mut RTCPeerConnection<I>,
185}
186
187impl<I> RTCRtpReceiver<'_, I>
188where
189    I: Interceptor,
190{
191    /// Returns the track associated with this receiver.
192    ///
193    /// The [`track`](RTCRtpReceiver::track) method returns the [`MediaStreamTrack`] that is
194    /// associated with this receiver as specified in the [W3C WebRTC specification](https://www.w3.org/TR/webrtc/#dom-rtcrtpreceiver-track).
195    ///
196    /// # Returns
197    ///
198    /// Returns a reference to the [`MediaStreamTrack`] associated with this receiver.
199    pub fn track(&self) -> &MediaStreamTrack {
200        // peer_connection is mutable borrow, its rtp_transceivers won't be resized and
201        // the direction won't be changed too, so, unwrap() here is safe.
202        self.peer_connection.rtp_transceivers[self.id.0]
203            .receiver
204            .as_ref()
205            .unwrap()
206            .track()
207    }
208
209    /// Returns the RTP capabilities for the specified codec kind.
210    ///
211    /// The static [`get_capabilities`](RTCRtpReceiver::get_capabilities) method returns the most
212    /// optimistic view of the capabilities of the system for receiving media of the given kind
213    /// as defined in the [W3C WebRTC specification](https://www.w3.org/TR/webrtc/#dom-rtcrtpreceiver-getcapabilities).
214    ///
215    /// # Parameters
216    ///
217    /// * `kind` - The codec kind (audio or video)
218    ///
219    /// # Returns
220    ///
221    /// Returns the RTP capabilities supported by this receiver for the specified codec kind.
222    pub fn get_capabilities(&self, kind: RtpCodecKind) -> Option<RTCRtpCapabilities> {
223        // peer_connection is mutable borrow, its rtp_transceivers won't be resized and
224        // the direction won't be changed too, so, unwrap() here is safe.
225        self.peer_connection.rtp_transceivers[self.id.0]
226            .receiver
227            .as_ref()
228            .unwrap()
229            .get_capabilities(kind, &self.peer_connection.media_engine)
230    }
231
232    /// Returns the RTP receive parameters for this receiver.
233    ///
234    /// The [`get_parameters`](RTCRtpReceiver::get_parameters) method returns the current parameters
235    /// for how the receiver's track is decoded as defined in the
236    /// [W3C WebRTC specification](https://www.w3.org/TR/webrtc/#dom-rtcrtpreceiver-getparameters).
237    ///
238    /// # Returns
239    ///
240    /// Returns a reference to the RTP receive parameters.
241    pub fn get_parameters(&mut self) -> &RTCRtpReceiveParameters {
242        // peer_connection is mutable borrow, its rtp_transceivers won't be resized and
243        // the direction won't be changed too, so, unwrap() here is safe.
244        self.peer_connection.rtp_transceivers[self.id.0]
245            .receiver
246            .as_mut()
247            .unwrap()
248            .get_parameters(&self.peer_connection.media_engine)
249    }
250
251    /// Returns an iterator over the contributing sources for this receiver.
252    ///
253    /// The [`get_contributing_sources`](RTCRtpReceiver::get_contributing_sources) method returns
254    /// information about the contributing sources (CSRCs) for the most recent RTP packets
255    /// received by this receiver as defined in the
256    /// [W3C WebRTC specification](https://www.w3.org/TR/webrtc/#dom-rtcrtpreceiver-getcontributingsources).
257    ///
258    /// Contributing sources represent mixers or other entities that have contributed to the
259    /// RTP stream.
260    ///
261    /// # Returns
262    ///
263    /// Returns an iterator over [`RTCRtpContributingSource`] objects.
264    pub fn get_contributing_sources(&self) -> impl Iterator<Item = &RTCRtpContributingSource> {
265        // peer_connection is mutable borrow, its rtp_transceivers won't be resized and
266        // the direction won't be changed too, so, unwrap() here is safe.
267        self.peer_connection.rtp_transceivers[self.id.0]
268            .receiver
269            .as_ref()
270            .unwrap()
271            .get_contributing_sources()
272    }
273
274    /// Returns an iterator over the synchronization sources for this receiver.
275    ///
276    /// The [`get_synchronization_sources`](RTCRtpReceiver::get_synchronization_sources) method
277    /// returns information about the synchronization sources (SSRCs) for the most recent RTP
278    /// packets received by this receiver as defined in the
279    /// [W3C WebRTC specification](https://www.w3.org/TR/webrtc/#dom-rtcrtpreceiver-getsynchronizationsources).
280    ///
281    /// Synchronization sources represent the original sources of the RTP packets.
282    ///
283    /// # Returns
284    ///
285    /// Returns an iterator over [`RTCRtpSynchronizationSource`] objects.
286    pub fn get_synchronization_sources(
287        &self,
288    ) -> impl Iterator<Item = &RTCRtpSynchronizationSource> {
289        // peer_connection is mutable borrow, its rtp_transceivers won't be resized and
290        // the direction won't be changed too, so, unwrap() here is safe.
291        self.peer_connection.rtp_transceivers[self.id.0]
292            .receiver
293            .as_ref()
294            .unwrap()
295            .get_synchronization_sources()
296    }
297
298    /// Writes RTCP feedback packets for this receiver.
299    ///
300    /// This method allows sending receiver-side RTCP feedback such as:
301    /// - Receiver Reports (RR)
302    /// - Picture Loss Indication (PLI)
303    /// - Full Intra Request (FIR)
304    /// - Negative Acknowledgements (NACK)
305    ///
306    /// # Parameters
307    ///
308    /// * `packets` - A vector of RTCP packets to send
309    ///
310    /// # Returns
311    ///
312    /// Returns `Ok(())` if the packets were queued successfully.
313    ///
314    /// # Errors
315    ///
316    /// Returns an error if internal handle_write returns error
317    ///
318    /// # Example
319    ///
320    /// ```ignore
321    /// // Send a Picture Loss Indication to request a keyframe
322    /// use rtcp::picture_loss_indication::PictureLossIndication;
323    ///
324    /// let pli = PictureLossIndication {
325    ///     sender_ssrc: 0,
326    ///     media_ssrc: remote_ssrc,
327    /// };
328    /// receiver.write_rtcp(vec![Box::new(pli)])?;
329    /// ```
330    pub fn write_rtcp(&mut self, packets: Vec<Box<dyn rtcp::Packet>>) -> Result<()> {
331        // peer_connection is mutable borrow, its rtp_transceivers won't be resized and
332        // the direction won't be changed too, so, unwrap() here is safe.
333
334        //TODO: handle rtcp media ssrc, header extension, etc.
335        let receiver = self.peer_connection.rtp_transceivers[self.id.0]
336            .receiver
337            .as_mut()
338            .unwrap();
339
340        let track_id = receiver.track().track_id().to_string();
341        self.peer_connection
342            .handle_write(RTCMessage::RtcpPacket(track_id, packets))
343    }
344}