From 9fc4858e52e17c5fff80f7e2d74d1c042bcb9e25 Mon Sep 17 00:00:00 2001 From: cxh Date: Tue, 25 Nov 2025 09:21:08 +0800 Subject: [PATCH] 1 --- src/rtsp_manager.cpp | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/src/rtsp_manager.cpp b/src/rtsp_manager.cpp index 8a85ccf..590bf6b 100644 --- a/src/rtsp_manager.cpp +++ b/src/rtsp_manager.cpp @@ -35,7 +35,7 @@ bool set_v4l2_format(const std::string &dev, int width, int height) memset(&fmt, 0, sizeof(fmt)); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - // 先读当前格式,避免每次都硬 S_FMT + // 读格式,若相同则略过 if (ioctl(fd, VIDIOC_G_FMT, &fmt) == 0) { bool match = true; @@ -69,7 +69,6 @@ bool set_v4l2_format(const std::string &dev, int width, int height) } LOG_INFO("[RTSP] Set V4L2 format to NV12 " + std::to_string(width) + "x" + std::to_string(height) + " for " + dev); - close(fd); return true; } @@ -95,24 +94,17 @@ GstRTSPMediaFactory *RTSPManager::create_media_factory(const Camera &cam) ",height=" + std::to_string(h) + ",framerate=" + std::to_string(cam.fps) + "/1"; - // 注意几点: - // 1) 给 mpph264enc 起一个名字 name=enc,方便后面在 on_media_created 里拿到 - // 2) option-force-idr / option-idr-interval 依然在这里设置一遍,保证周期 IDR - // 3) config-interval=1 一定要写在 rtph264pay 上 + // 修正后的管线:加 videoconvert,删掉 encoder 不支持的属性 std::string launch_str = "( v4l2src device=" + cam.device + " io-mode=2 is-live=true do-timestamp=true" " ! " + caps + + " ! videoconvert" " ! queue leaky=downstream max-size-time=0 max-size-bytes=0 max-size-buffers=0" - " ! mpph264enc name=enc" - " rc-mode=cbr" - " bps=" + + " ! mpph264enc name=enc rc-mode=cbr bps=" + std::to_string(cam.bitrate) + " gop=" + std::to_string(cam.fps) + - " option-force-idr=true" - " option-idr-interval=" + - std::to_string(cam.fps) + " header-mode=1" " ! h264parse" " ! rtph264pay name=pay0 pt=96 config-interval=1 )"; @@ -122,10 +114,10 @@ GstRTSPMediaFactory *RTSPManager::create_media_factory(const Camera &cam) GstRTSPMediaFactory *factory = gst_rtsp_media_factory_new(); gst_rtsp_media_factory_set_launch(factory, launch_str.c_str()); - // 先保持 shared=TRUE,节省资源 - gst_rtsp_media_factory_set_shared(factory, TRUE); + // ★ 必改:先关掉 shared,避免 VLC 拉流不启动 pipeline + gst_rtsp_media_factory_set_shared(factory, FALSE); - // 客户端断开时不重置 pipeline,防止反复 s_stream(0/1) + // 客户端断开时不 reset pipeline(我们手动处理) gst_rtsp_media_factory_set_suspend_mode(factory, GST_RTSP_SUSPEND_MODE_NONE); g_signal_connect_data(factory, @@ -218,8 +210,9 @@ void RTSPManager::on_media_created(GstRTSPMediaFactory *, GstRTSPMedia *media, g return; } - LOG_INFO("[RTSP] Forcing pipeline reset to generate IDR"); + LOG_INFO("[RTSP] Forcing pipeline reset (READY → PLAYING) to generate IDR"); + // 关键:强制重新启动 pipeline,让 v4l2src/mpph264enc 正式启动 gst_element_set_state(pipeline, GST_STATE_READY); gst_element_set_state(pipeline, GST_STATE_PLAYING);