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

GStreamer中gst_parse_launch无法拼接std::string变量的问题求助

问题解决:GStreamer中RTSP地址变量拼接报错

错误原因

gst_parse_launch() 要求第一个参数是C风格字符串(const gchar*),但你拼接字符串后得到的是std::string对象,C++不会自动完成这种类型转换,因此触发了类型不匹配的错误。

解决方案一:字符串拼接后转C风格字符串

先把所有部分拼接成完整的std::string,再通过c_str()方法获取其底层的C风格字符串指针,传给gst_parse_launch():

/*Url Cams*/
std::string URL_RTSP = "rtsp://user:pass@protocol:port/cam/realmonitor?channel=1&subtype=0";

/* 拼接完整的管道描述字符串 */
std::string pipeline_str = "rtspsrc protocols=tcp location=" + URL_RTSP + " latency=300 ! decodebin3 ! autovideosink";

/* Build the pipeline */
pipeline = gst_parse_launch(pipeline_str.c_str(), NULL);

/* Start playing */
gst_element_set_state(pipeline, GST_STATE_PLAYING);

解决方案二:分步创建元素并设置属性(更推荐)

相比字符串拼接,直接创建rtspsrc元素并设置location等属性,可读性和灵活性更强,也能避免字符串拼接可能出现的转义问题:

/*Url Cams*/
std::string URL_RTSP = "rtsp://user:pass@protocol:port/cam/realmonitor?channel=1&subtype=0";

// 创建管道和各个元素
GstElement *pipeline = gst_pipeline_new("rtsp-pipeline");
GstElement *rtspsrc = gst_element_factory_make("rtspsrc", "source");
GstElement *decodebin = gst_element_factory_make("decodebin3", "decoder");
GstElement *videosink = gst_element_factory_make("autovideosink", "sink");

if (!pipeline || !rtspsrc || !decodebin || !videosink) {
    g_printerr("无法创建所有GStreamer元素!\n");
    return -1;
}

// 设置rtspsrc的属性
g_object_set(rtspsrc, "protocols", GST_RTSP_LOWER_TRANS_TCP, "location", URL_RTSP.c_str(), "latency", 300, NULL);

// 将元素添加到管道
gst_bin_add_many(GST_BIN(pipeline), rtspsrc, decodebin, videosink, NULL);

// 链接元素(decodebin需要动态链接,因为它的输出pad是动态创建的)
if (!gst_element_link(rtspsrc, decodebin)) {
    g_printerr("无法链接rtspsrc和decodebin!\n");
    gst_object_unref(pipeline);
    return -1;
}

// 处理decodebin的pad-added信号,动态链接到videosink
g_signal_connect(decodebin, "pad-added", G_CALLBACK(on_pad_added), videosink);

/* Start playing */
gst_element_set_state(pipeline, GST_STATE_PLAYING);

需要额外实现on_pad_added回调函数:

static void on_pad_added(GstElement *element, GstPad *pad, gpointer data) {
    GstElement *sink = (GstElement *)data;
    GstPad *sink_pad = gst_element_get_static_pad(sink, "sink");

    if (gst_pad_is_linked(sink_pad)) {
        g_object_unref(sink_pad);
        return;
    }

    GstCaps *caps = gst_pad_get_current_caps(pad);
    GstStructure *str = gst_caps_get_structure(caps, 0);
    const gchar *media_type = gst_structure_get_name(str);

    // 只链接视频流
    if (g_str_has_prefix(media_type, "video/")) {
        gst_pad_link(pad, sink_pad);
    }

    gst_caps_unref(caps);
    g_object_unref(sink_pad);
}

说明

  • 方案一适合简单场景,快速修改现有代码即可生效;
  • 方案二更符合GStreamer的最佳实践,尤其是需要动态处理媒体流(比如同时包含音视频的RTSP流)时,能更灵活地处理不同类型的流。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 03:40:21