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

GStreamer UDP推流正常但TCP推流失败,求问题排查

问题分析与解决

你的TCP推流失败核心原因是RTP over TCP需要特定的封装格式,而代码直接将RTP负载输出到tcpclientsink,缺少必要的TCP封装处理。UDP是无连接的数据包传输,RTP包可以直接发送;但TCP是字节流,需要给每个RTP包加上边界标识(如RFC 2326定义的$+长度头),否则服务器无法正确拆分RTP包。同时你遗漏了rtpbin元素的使用,它是GStreamer中处理RTP会话(包括TCP封装)的核心组件。

具体修改点

1. 添加rtpbin元素并调整链路

当使用TCP推流时,必须引入rtpbin来处理RTP的TCP封装。修改GST_RTP_Init中的元素创建和检查逻辑:

// 在全局元素声明中添加rtpbin
GstElement *pipeline, *appsrc, *h264parse, *mpegtsmux, *payloader, *sink, *queue, *rtpbin;
User_RTP_Config main_rtp_config;

// 在GST_RTP_Init函数中创建rtpbin
if(config->rtp_type == RTP_TYPE_TCP_ACTIVE) {
    sink = gst_element_factory_make("tcpclientsink", "tcpclient-sink");
    rtpbin = gst_element_factory_make("rtpbin", "rtp-bin");
}
// ... 其他代码 ...

// 检查元素创建成功,TCP模式下必须包含rtpbin
if(config->rtp_payload == RTP_PAYLOAD_H264) {
    payloader = gst_element_factory_make("rtph264pay", "h264-payloader");
    if (!pipeline ||!appsrc ||!payloader ||!sink ||!queue || (config->rtp_type == RTP_TYPE_TCP_ACTIVE && !rtpbin)) {
        GST_ERROR("Failed to create elements");
        return -1;
    }
}

注:你代码中mpegpsmux变量实际创建的是mpegtsmux,建议统一变量名为mpegtsmux避免混淆

2. 动态连接rtpbin的Pad

rtpbin的Pad是动态生成的,不能用gst_element_link_many直接连接,需要通过信号回调处理:

// 添加回调函数,用于连接rtpbin的输出Pad到tcpclientsink
static void on_rtpbin_send_rtp_src_created(GstElement *rtpbin, GstPad *src, GstElement *sink) {
    GstPad *sink_pad = gst_element_get_static_pad(sink, "sink");
    gst_pad_link(src, sink_pad);
    gst_object_unref(sink_pad);
}

// 在GST_RTP_Init中,TCP模式下连接payloader到rtpbin,并绑定信号
if(config->rtp_type == RTP_TYPE_TCP_ACTIVE) {
    // 请求rtpbin的RTP接收Pad,连接到payloader的输出
    GstPad *rtp_sink_pad = gst_element_get_request_pad(rtpbin, "send_rtp_sink_0");
    GstPad *payloader_src_pad = gst_element_get_static_pad(payloader, "src");
    gst_pad_link(payloader_src_pad, rtp_sink_pad);
    gst_object_unref(payloader_src_pad);
    gst_object_unref(rtp_sink_pad);

    // 监听rtpbin的动态Pad创建信号,自动连接到tcpclientsink
    g_signal_connect(rtpbin, "send-rtp-src-created", G_CALLBACK(on_rtpbin_send_rtp_src_created), sink);
}

3. 调整链路连接逻辑

TCP模式下,链路应为:appsrc -> queue -> (h264parse -> mpegtsmux -> payloader) / payloader -> rtpbin -> tcpclientsink,修改链路连接代码:

if(config->rtp_payload == RTP_PAYLOAD_PS) {
    if(config->rtp_type == RTP_TYPE_TCP_ACTIVE) {
        gst_bin_add_many(GST_BIN(pipeline), appsrc, queue, h264parse, mpegtsmux, payloader, rtpbin, sink, NULL);
        gst_element_link_many(appsrc, queue, h264parse, mpegtsmux, payloader, NULL);
    } else {
        gst_bin_add_many(GST_BIN(pipeline), appsrc, queue, h264parse, mpegtsmux, payloader, sink, NULL);
        gst_element_link_many(appsrc, queue, h264parse, mpegtsmux, payloader, sink, NULL);
    }
}
else if(config->rtp_payload == RTP_PAYLOAD_H264) {
    if(config->rtp_type == RTP_TYPE_TCP_ACTIVE) {
        gst_bin_add_many(GST_BIN(pipeline), appsrc, queue, payloader, rtpbin, sink, NULL);
        gst_element_link_many(appsrc, queue, payloader, NULL);
    } else {
        gst_bin_add_many(GST_BIN(pipeline), appsrc, queue, payloader, sink, NULL);
        gst_element_link_many(appsrc, queue, payloader, sink, NULL);
    }
}

4. 补充tcpclientsink的必要配置

添加TCP连接优化参数,避免同步阻塞问题:

g_object_set(sink, "host", config->rtp_ip, "port", config->rtp_port, 
             "sync", FALSE, "async", FALSE, NULL);
  • sync=FALSE:避免TCP流因为时钟同步问题阻塞
  • async=FALSE:确保数据立即发送,适合直播场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 12:57:01