如何在C++代码中使用GStreamer Discoverer检测流类型以生成对应GStreamer管道?
如何在C++代码中使用GStreamer Discoverer检测流类型以生成对应GStreamer管道?
嘿,刚好我之前做过类似的需求,给你梳理下在C++里用GStreamer Discoverer检测流类型的具体步骤,这样你就能动态生成适配H264或MJPEG的管道啦!
核心思路
你在命令行用的gst-discoverer-1.0工具本身有对应的C API,我们可以直接在代码里调用它来分析流的媒体信息,拿到编码类型后再拼接对应的管道字符串就行。
具体步骤&代码示例
- 初始化GStreamer
这是所有GStreamer程序的第一步,必须先初始化库:
#include <gst/gst.h> #include <gst/discoverer/gstdiscoverer.h> int main(int argc, char *argv[]) { gst_init(&argc, &argv); // 后续代码... }
- 创建Discoverer实例并设置回调
我们需要创建一个Discoverer对象,设置超时时间(比如5秒,足够应对大多数网络流),然后绑定一个回调函数——当Discoverer完成流分析后,就会触发这个回调来处理结果:
static void on_discoverer_finished(GstDiscoverer *discoverer, GstDiscovererInfo *info, GError *error, gpointer user_data) { gchar *uri = gst_discoverer_info_get_uri(info); GstDiscovererResult result = gst_discoverer_info_get_result(info); if (error != NULL) { g_printerr("Error discovering %s: %s\n", uri, error->message); g_error_free(error); g_free(uri); g_main_loop_quit((GMainLoop*)user_data); return; } // 解析视频流的编码信息 GstDiscovererStreamInfo *stream_info = gst_discoverer_info_get_stream_info(info); if (stream_info != NULL && GST_IS_DISCOVERER_VIDEO_INFO(stream_info)) { GstDiscovererVideoInfo *video_info = GST_DISCOVERER_VIDEO_INFO(stream_info); const GstCaps *caps = gst_discoverer_video_info_get_caps(video_info); gchar *caps_str = gst_caps_to_string(caps); // 判断是H264还是MJPEG gboolean is_h264 = g_strrstr(caps_str, "H264") != NULL; gboolean is_mjpeg = g_strrstr(caps_str, "MJPEG") != NULL; g_print("Detected stream type for %s: ", uri); if (is_h264) { g_print("H264\n"); // 生成H264对应的管道(这里以RTSP流为例) gchar *h264_pipeline = g_strdup_printf( "rtspsrc location=%s ! rtph264depay ! h264parse ! avdec_h264 ! autovideosink sync=false", uri ); g_print("Generated H264 pipeline: %s\n", h264_pipeline); g_free(h264_pipeline); } else if (is_mjpeg) { g_print("MJPEG\n"); // 生成MJPEG对应的管道(这里以RTSP流为例) gchar *mjpeg_pipeline = g_strdup_printf( "rtspsrc location=%s ! rtpjpegdepay ! jpegparse ! jpegdec ! autovideosink sync=false", uri ); g_print("Generated MJPEG pipeline: %s\n", mjpeg_pipeline); g_free(mjpeg_pipeline); } else { g_print("Unknown video type\n"); } g_free(caps_str); gst_discoverer_stream_info_unref(stream_info); } g_free(uri); g_main_loop_quit((GMainLoop*)user_data); }
- 启动Discoverer并等待结果
因为Discoverer是异步工作的,所以我们需要用GMainLoop来阻塞等待分析完成:
int main(int argc, char *argv[]) { gst_init(&argc, &argv); if (argc != 2) { g_printerr("Usage: %s <uri>\n", argv[0]); return 1; } GMainLoop *loop = g_main_loop_new(NULL, FALSE); GstDiscoverer *discoverer = gst_discoverer_new(5 * GST_SECOND, NULL); // 设置5秒超时 // 绑定回调函数 g_signal_connect(discoverer, "discovered", G_CALLBACK(on_discoverer_finished), loop); // 启动Discoverer并开始分析指定URI if (!gst_discoverer_start(discoverer)) { g_printerr("Failed to start discoverer\n"); gst_object_unref(discoverer); g_main_loop_unref(loop); return 1; } gst_discoverer_discover_uri_async(discoverer, argv[1]); // 阻塞等待分析完成 g_main_loop_run(loop); // 清理资源 gst_discoverer_stop(discoverer); gst_object_unref(discoverer); g_main_loop_unref(loop); return 0; }
编译注意事项
编译的时候要链接GStreamer的Discoverer库,用pkg-config来自动处理依赖:
g++ your_code.cpp -o stream_detector $(pkg-config --cflags --libs gstreamer-1.0 gstreamer-discoverer-1.0)
小提示
- 如果是本地文件流,直接把URI换成
file:///path/to/your/file格式就行 - 你可以扩展回调里的逻辑,比如处理音频流或者其他编码类型
- 超时时间可以根据你的网络情况调整,弱网环境下可以设长一点
备注:内容来源于stack exchange,提问作者JFF
相关产品推荐
相关产品推荐

