-
Notifications
You must be signed in to change notification settings - Fork 131
try setting x-google-start-bitrate for vp9 #820
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,6 +26,12 @@ use super::EngineResult; | |
|
|
||
| pub type OnOfferCreated = Box<dyn FnMut(SessionDescription) + Send + Sync>; | ||
|
|
||
| #[cfg(any(target_os = "windows", target_os = "macos", target_os = "linux"))] | ||
| const DEFAULT_VP9_START_BITRATE_KBPS: u32 = 2500; | ||
|
|
||
| #[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))] | ||
| const DEFAULT_VP9_START_BITRATE_KBPS: u32 = 0; // 0 means “don’t apply” | ||
|
|
||
| struct TransportInner { | ||
| pending_candidates: Vec<IceCandidate>, | ||
| renegotiate: bool, | ||
|
|
@@ -127,6 +133,52 @@ impl PeerTransport { | |
| Ok(answer) | ||
| } | ||
|
|
||
| fn munge_x_google_start_bitrate(sdp: &str, start_bitrate_kbps: u32) -> String { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should we use a proper sdp parser/rewriter? instead of string changes? https://crates.io/crates/sdp in case we'd need to do more munging for other things |
||
| // 1) Find payload types (PTs) for VP9 / AV1 from a=rtpmap:<pt> VP9/90000 etc | ||
| let mut target_pts: Vec<String> = Vec::new(); | ||
| for line in sdp.lines() { | ||
| let l = line.trim(); | ||
| if let Some(rest) = l.strip_prefix("a=rtpmap:") { | ||
| // rest looks like: "<pt> VP9/90000" | ||
| let mut it = rest.split_whitespace(); | ||
| let pt = it.next().unwrap_or(""); | ||
| let codec = it.next().unwrap_or(""); | ||
| if codec.starts_with("VP9/90000") || codec.starts_with("AV1/90000") { | ||
| if !pt.is_empty() { | ||
| target_pts.push(pt.to_string()); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| if target_pts.is_empty() { | ||
| return sdp.to_string(); | ||
| } | ||
|
|
||
| // 2) For each PT, ensure a=fmtp:<pt> has x-google-start-bitrate=... | ||
| // We do a line-by-line rewrite. If there is no fmtp line for that PT, we leave it alone | ||
| // (safer; avoids adding new fmtp that might not be accepted). | ||
| let mut out: Vec<String> = Vec::with_capacity(sdp.lines().count()); | ||
| for line in sdp.lines() { | ||
| let mut rewritten = line.to_string(); | ||
|
|
||
| for pt in &target_pts { | ||
| let prefix = format!("a=fmtp:{pt} "); | ||
| if rewritten.starts_with(&prefix) { | ||
| // Only append if not already present | ||
| if !rewritten.contains("x-google-start-bitrate=") { | ||
| rewritten | ||
| .push_str(&format!(";x-google-start-bitrate={start_bitrate_kbps}")); | ||
| } | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| out.push(rewritten); | ||
| } | ||
|
|
||
| out.join("\r\n") | ||
| } | ||
|
|
||
| pub async fn create_and_send_offer(&self, options: OfferOptions) -> EngineResult<()> { | ||
| let mut inner = self.inner.lock().await; | ||
|
|
||
|
|
@@ -151,7 +203,25 @@ impl PeerTransport { | |
| return Ok(()); | ||
| } | ||
|
|
||
| let offer = self.peer_connection.create_offer(options).await?; | ||
| let mut offer = self.peer_connection.create_offer(options).await?; | ||
| let start_bitrate_kbps = DEFAULT_VP9_START_BITRATE_KBPS; | ||
| let sdp = offer.to_string(); | ||
| // TODO, we should extend the codec support to AV1 ? | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. worth testing if AV1 has this issue or not.. the JS logic is applying to AV1 as well |
||
| if start_bitrate_kbps > 0 && sdp.contains(" VP9/90000") { | ||
| let munged = Self::munge_x_google_start_bitrate(&sdp, start_bitrate_kbps); | ||
| if munged != sdp { | ||
| match SessionDescription::parse(&munged, offer.sdp_type()) { | ||
| Ok(parsed) => { | ||
| offer = parsed; | ||
| } | ||
| Err(e) => { | ||
| log::warn!( | ||
| "Failed to parse munged SDP, falling back to original offer: {e}" | ||
| ); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| self.peer_connection.set_local_description(offer.clone()).await?; | ||
|
|
||
| if let Some(handler) = self.on_offer_handler.lock().as_mut() { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should use the currently negotiated bitrate? instead of a fixed amount? the JS logic uses 80% of ultimate bitrate. I think it's ok to go to 100% as well