You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GStreamer RTSP服务器推送数据异常:断言错误与流无法播放排查

GStreamer RTSP推送问题排查与修复

问题概况

作为GStreamer/RTSP新手,需要搭建两条流水线:

  1. videotestsrc -> x264enc -> appsink:将采集编码后的视频数据主动推送给RTSP服务器的appsrc
  2. appsrc -> rtph264pay:RTSP服务器端的流处理流水线

放弃官方示例的need-data拉取模式,改为从appsink主动推送,但遇到以下问题:

  • 首次推送数据给appsrc时触发断言错误:GStreamer-CRITICAL **: 17:20:43.792: gst_segment_to_running_time: assertion 'segment->format == format' failed
  • 后续推送无警告,但gst-launch、ffplay无法读取流,ffplay执行ffplay rtsp://127.0.0.1:8554/test时卡在nan : 0.000 fd= 0 aq= 0KB vq= 0KB sq= 0B f=0/0
  • 运行环境为WSL2

错误原因分析

  1. 断言错误根源:RTSP端的appsrc未初始化时间片段(Segment),推送数据时GStreamer无法将缓冲区时间戳转换为运行时间,导致格式不匹配断言失败。
  2. 流无法播放原因:H264流格式不兼容、Sample引用计数错误、RTSP流水线状态未同步等多重问题叠加,导致客户端无法解析流数据。

代码修复要点

1. 初始化AppSrc的时间Segment

在MediaConfigure函数中,添加segment初始化代码,确保appsrc有有效的时间基准:

void GStreamer_RTSP::MediaConfigure( GstRTSPMediaFactory *factory, GstRTSPMedia *media, void *aParent )
{
    GStreamer_RTSP *lThis = (GStreamer_RTSP *)aParent;

    GstElement *lElement    = gst_rtsp_media_get_element( media );
    GstElement *lRTSPSource = gst_bin_get_by_name( GST_BIN( lElement ), "rtspsrc" );
    
    // 初始化时间Segment
    GstSegment segment;
    gst_segment_init(&segment, GST_FORMAT_TIME);
    gst_app_src_start_segment(GST_APP_SRC(lRTSPSource), &segment);
    
    gst_app_src_set_stream_type( GST_APP_SRC( lRTSPSource ), GST_APP_STREAM_TYPE_STREAM );
    // 修正caps,添加H264流格式参数
    auto caps = gst_caps_new_simple( "video/x-h264", 
        "width", G_TYPE_INT, 1000, 
        "height", G_TYPE_INT, 500, 
        "framerate", GST_TYPE_FRACTION, 10, 1,
        "stream-format", G_TYPE_STRING, "byte-stream",
        "alignment", G_TYPE_STRING, "au",
        NULL );
    gst_app_src_set_caps( GST_APP_SRC( lRTSPSource ), caps );
    gst_caps_unref( caps );

    // 启动RTSP流水线
    gst_element_set_state(lElement, GST_STATE_PLAYING);

    gst_object_unref( lElement );
    gst_object_unref( lRTSPSource );

    const std::lock_guard<std::mutex> lock( lThis->mMediaMutex );
    lThis->mRTSPStreams.insert( media );
    g_signal_connect( media, "unprepared", (GCallback)&GStreamer_RTSP::MediaUnconfigure, aParent );
}

2. 配置x264enc输出字节流格式

修改InitPipeline中x264enc的参数,确保输出符合rtph264pay要求的字节流:

void GStreamer_RTSP::InitPipeline()
{
    // ... 其他代码 ...
    g_object_set( lEncoder, "tune", 4, "byte-stream", TRUE, NULL ); // 4 = zerolatency + 输出字节流
    // ... 其他代码 ...
}

3. 修复Sample推送的引用计数问题

在NewFrameFromSink中,为每个RTSP流复制独立的Sample,避免引用计数冲突:

GstFlowReturn GStreamer_RTSP::NewFrameFromSink( GstElement *aElement, void *aParent )
{
    GStreamer_RTSP *lThis = (GStreamer_RTSP *)aParent;
    if( lThis->mRTSPStreams.empty() )
    {
        return GST_FLOW_OK;
    }

    const std::lock_guard<std::mutex> lock( lThis->mMediaMutex );
    GstSample *aSample = gst_app_sink_pull_sample( GST_APP_SINK( aElement ) );

    for( const auto &lOutgoingStream : lThis->mRTSPStreams )
    {
        GstElement *lElement    = gst_rtsp_media_get_element( lOutgoingStream );
        GstElement *lRTSPSource = gst_bin_get_by_name( GST_BIN( lElement ), "rtspsrc" );
        
        // 为每个流复制Sample,避免引用计数错误
        GstSample* sample_copy = gst_sample_copy(aSample);
        gst_app_src_push_sample( GST_APP_SRC( lRTSPSource ), sample_copy );
        gst_sample_unref(sample_copy);

        gst_object_unref( lElement );
        gst_object_unref( lRTSPSource );
    }

    gst_sample_unref( aSample );
    return GST_FLOW_OK;
}

4. 可选:添加缓冲区时间戳处理(若仍有同步问题)

如果客户端播放仍有卡顿或不同步,可确保推送的缓冲区带有正确的时间戳。在NewFrameFromSink中,可手动设置时间戳(若原始Sample时间戳无效):

GstBuffer* buffer = gst_sample_get_buffer(aSample);
GstClockTime timestamp = gst_clock_get_time(gst_element_get_clock(lPipeline));
gst_buffer_set_pts(buffer, timestamp);
gst_buffer_set_dts(buffer, timestamp);

修改后验证

  1. 重新编译运行代码,首次推送不再出现断言错误
  2. 使用ffplay或gst-launch测试流:
    ffplay rtsp://127.0.0.1:8554/test
    
    或
    gst-launch-1.0 rtspsrc location=rtsp://127.0.0.1:8554/test ! rtph264depay ! h264parse ! avdec_h264 ! autovideosink
    

内容的提问来源于stack exchange,提问作者David Levy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 05:39:51