diff --git a/src/bwe.rs b/src/bwe.rs index a850a7a8..90d856aa 100644 --- a/src/bwe.rs +++ b/src/bwe.rs @@ -4,7 +4,7 @@ use crate::{rtp_::Mid, Rtc}; pub use crate::rtp_::Bitrate; -#[derive(Debug)] +#[derive(Debug, PartialEq)] /// Bandwidth estimation kind. pub enum BweKind { /// Transport wide congestion control. diff --git a/src/rtp/rtcp/mod.rs b/src/rtp/rtcp/mod.rs index b62b543d..1b933656 100644 --- a/src/rtp/rtcp/mod.rs +++ b/src/rtp/rtcp/mod.rs @@ -437,7 +437,15 @@ impl<'a> TryFrom<&'a [u8]> for Rtcp { } PayloadType::FullIntraRequest => Rtcp::Fir(buf.try_into()?), PayloadType::ApplicationLayer => { - return Err("Ignore PayloadType: ApplicationLayer") + match header.rtcp_type() { + RtcpType::PayloadSpecificFeedback => { + if let Ok(remb) = Remb::try_from(buf) { + return Ok(Rtcp::Remb(remb)); + } + } + _ => {} + } + return Err("Ignore PayloadType: ApplicationLayer"); } } } diff --git a/src/rtp/rtcp/rtcpfb.rs b/src/rtp/rtcp/rtcpfb.rs index 4bf79811..b025ea0a 100644 --- a/src/rtp/rtcp/rtcpfb.rs +++ b/src/rtp/rtcp/rtcpfb.rs @@ -89,7 +89,7 @@ impl RtcpFb { RtcpFb::Pli(v) => *v, RtcpFb::Fir(v) => v.ssrc, RtcpFb::Twcc(v) => v.ssrc, - RtcpFb::Remb(v) => v.ssrc, + RtcpFb::Remb(v) => v.ssrcs.first().map(|ssrc| (*ssrc).into()).unwrap_or(v.ssrc), } } } diff --git a/tests/remb.rs b/tests/remb.rs new file mode 100644 index 00000000..04c06b49 --- /dev/null +++ b/tests/remb.rs @@ -0,0 +1,76 @@ +use std::net::Ipv4Addr; +use std::time::Duration; + +use str0m::bwe::{Bitrate, BweKind}; +use str0m::media::{Direction, MediaKind}; +use str0m::{Candidate, Event, Rtc, RtcError}; +use tracing::{info, info_span}; + +mod common; +use common::{init_log, negotiate, progress, TestRtc}; + +#[test] +pub fn remb() -> Result<(), RtcError> { + init_log(); + let l_rtc = Rtc::builder().build(); + let r_rtc = Rtc::builder().build(); + + let mut l = TestRtc::new_with_rtc(info_span!("L"), l_rtc); + let mut r = TestRtc::new_with_rtc(info_span!("R"), r_rtc); + + let host1 = Candidate::host((Ipv4Addr::new(1, 1, 1, 1), 1000).into(), "udp")?; + let host2 = Candidate::host((Ipv4Addr::new(2, 2, 2, 2), 2000).into(), "udp")?; + l.add_local_candidate(host1); + r.add_local_candidate(host2); + + let mid = negotiate(&mut l, &mut r, |change| { + change.add_media(MediaKind::Video, Direction::SendOnly, None, None) + }); + + loop { + if l.is_connected() || r.is_connected() { + break; + } + progress(&mut l, &mut r)?; + } + + //wait for srtp success + let settle_time = l.duration() + Duration::from_millis(20); + loop { + progress(&mut l, &mut r)?; + + if l.duration() > settle_time { + break; + } + } + + r.direct_api() + .stream_rx_by_mid(mid, None) + .expect("Should has rx") + .request_remb(Bitrate::bps(123456)); + + let settle_time = l.duration() + Duration::from_millis(20); + loop { + progress(&mut l, &mut r)?; + + if l.duration() > settle_time { + break; + } + } + + let l_remb: Vec<_> = l + .events + .iter() + .filter_map(|(_, e)| { + if let Event::EgressBitrateEstimate(event) = e { + Some(event) + } else { + None + } + }) + .collect(); + + assert_eq!(l_remb, vec![&BweKind::Remb(mid, Bitrate::bps(123456))]); + + Ok(()) +}