From b83da5911520425dc312b6056eb8f08e5a73fa88 Mon Sep 17 00:00:00 2001 From: toorux Date: Fri, 9 Oct 2026 23:46:13 +0800 Subject: [PATCH] Correct hardware HEVC frame timing without re-encoding --- src/cast/runtime.rs | 7 +++++++ src/session.rs | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/cast/runtime.rs b/src/cast/runtime.rs index e4789c4..08e2dca 100644 --- a/src/cast/runtime.rs +++ b/src/cast/runtime.rs @@ -98,6 +98,8 @@ impl Casting { } /// Negotiate with browsers that omit H.264 (including the bundled CEF). /// All VP8 viewers share one on-demand compatibility encoder. + #[cfg(test)] + pub(crate) fn test_rtsp_port(&self) -> u16 {self.rtsp_port} pub fn codec(&self) -> Codec { self.active_settings.as_ref().map(|s|s.codec).unwrap_or_default() } pub fn ensure_vp8(&mut self) -> Result<()> { ensure!(self.status()["running"] == true, "请先开始头显串流"); @@ -472,6 +474,11 @@ impl Casting { } if s.source == Source::Screen { ffmpeg.args(["-c:v", "copy"]); + if s.codec==Codec::H265 { + // Iris HEVC headers omit reliable frame timing. Write the requested + // timing without decoding/re-encoding, avoiding false 50 fps playback. + ffmpeg.args(["-bsf:v",&format!("hevc_metadata=tick_rate={}:num_ticks_poc_diff_one=1",s.fps)]); + } } else { ffmpeg.args(["-vf", &format!("fps={},scale={}:{}:force_original_aspect_ratio=decrease,pad={}:{}:(ow-iw)/2:(oh-ih)/2,format=yuv420p",s.fps,s.width,s.height,s.width,s.height), "-c:v", if s.codec==Codec::H265 {"libx265"} else {"libx264"}, "-preset", "ultrafast", "-tune", "zerolatency", "-bf", "0", "-g", &s.fps.to_string(), "-b:v", &format!("{}M",s.bitrate_mbps)]); diff --git a/src/session.rs b/src/session.rs index bddf961..0bf6223 100644 --- a/src/session.rs +++ b/src/session.rs @@ -2133,7 +2133,7 @@ mod tests { std::thread::sleep(Duration::from_millis(200));assert_eq!(agent.casting.lock().unwrap().status()["running"],true); if std::env::var_os("FRAMELY_CAST_TEST_DLNA").is_some() { let mut cast=agent.casting.lock().unwrap();cast.ensure_dlna().unwrap(); - let rtsp=cast.rtsp_port; + let rtsp=cast.test_rtsp_port(); for (path,codec) in [("headset",if settings.codec==crate::cast::settings::Codec::H265 {"hevc"}else{"h264"}),("dlna","h264")] { std::thread::sleep(Duration::from_millis(500)); let output=Command::new("timeout").args(["15","ffprobe","-v","error","-rtsp_transport","tcp","-show_entries","stream=codec_name,width,height,r_frame_rate","-of","json",&format!("rtsp://127.0.0.1:{rtsp}/{path}")]).output().unwrap();