fix(webrtc): force IDR on KeyframeRequest via forced-idr=1 + pict_type (closes #16)
WebRTC KeyframeRequest 响应延迟 2.1s(152 P 帧丢弃)→ 端到端 5-20ms。 - BitrateCommand::ForceKeyframe variant over existing bitrate_tx channel - SwEncEncode.force_keyframe_pending: bypass dedup, set AV_PICTURE_TYPE_I, clear only after avcodec_send_frame succeeds - libx264 forced-idr=1 via av_opt_set (FFmpeg-level option, not x264-native) - pict_type reset to NONE per frame (reused AVFrame leak guard) - WebRtcInner.force_keyframe_to_encode + take_force_keyframe() drain API - recreate_encoder sets force_keyframe_pending (resolution change → IDR) Verification: skipping non-IDR frame 152→0, ForceKeyframe→IDR 4-5ms stable.
This commit is contained in:
@@ -200,6 +200,7 @@ struct WebRtcInner {
|
||||
video_pt: Option<Pt>,
|
||||
connected: bool,
|
||||
need_keyframe: bool,
|
||||
force_keyframe_to_encode: bool,
|
||||
current_bwe_estimate: Option<Bitrate>,
|
||||
rtp_clock: u32,
|
||||
buf: Vec<u8>,
|
||||
@@ -353,6 +354,17 @@ impl WebRtcState {
|
||||
pub fn set_need_keyframe(&mut self) {
|
||||
if let Some(inner) = self.inner.as_mut() {
|
||||
inner.need_keyframe = true;
|
||||
inner.force_keyframe_to_encode = true;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn take_force_keyframe(&mut self) -> bool {
|
||||
if let Some(inner) = self.inner.as_mut() {
|
||||
let v = inner.force_keyframe_to_encode;
|
||||
inner.force_keyframe_to_encode = false;
|
||||
v
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -429,6 +441,7 @@ impl WebRtcInner {
|
||||
video_pt: None,
|
||||
connected: false,
|
||||
need_keyframe: false,
|
||||
force_keyframe_to_encode: false,
|
||||
current_bwe_estimate: None,
|
||||
rtp_clock: 0,
|
||||
buf: vec![0u8; 65535],
|
||||
@@ -446,6 +459,7 @@ impl WebRtcInner {
|
||||
.map_err(|e| anyhow::anyhow!("accept_offer: {e}"))?;
|
||||
|
||||
self.need_keyframe = true;
|
||||
self.force_keyframe_to_encode = true;
|
||||
tracing::info!("SDP exchange complete, waiting for ICE/DTLS...");
|
||||
|
||||
self.discover_video_params();
|
||||
@@ -503,6 +517,7 @@ impl WebRtcInner {
|
||||
tracing::info!("WebRTC connected!");
|
||||
self.connected = true;
|
||||
self.need_keyframe = true;
|
||||
self.force_keyframe_to_encode = true;
|
||||
self.discover_video_params();
|
||||
}
|
||||
Event::IceConnectionStateChange(IceConnectionState::Disconnected) => {
|
||||
@@ -525,6 +540,7 @@ impl WebRtcInner {
|
||||
Event::KeyframeRequest(_) => {
|
||||
tracing::info!("received keyframe request from viewer");
|
||||
self.need_keyframe = true;
|
||||
self.force_keyframe_to_encode = true;
|
||||
}
|
||||
Event::EgressBitrateEstimate(est) => {
|
||||
let bitrate = match est {
|
||||
|
||||
Reference in New Issue
Block a user