如何在GStreamer运行时获取srtserversink的stats属性并打印
获取GStreamer srtserversink运行时统计数据的实现方案
核心思路
srtserversink的stats属性是GstValueArray类型,内部存储多个GstStructure结构(每个结构对应一个客户端连接的统计数据)。要在管道运行时持续获取并打印这些数据,需要:
- 编写统计读取回调函数,解析GstValueArray和GstStructure
- 使用Glib定时器周期性触发回调,避免阻塞主循环
修正后的完整代码
#include <glib.h> #include <gst/gst.h> // 统计数据打印回调函数 static gboolean print_srt_stats(gpointer user_data) { GstElement *sink = GST_ELEMENT(user_data); GValueArray *stats_array = NULL; // 获取stats属性 g_object_get(G_OBJECT(sink), "stats", &stats_array, NULL); if (stats_array && stats_array->n_values > 0) { g_print("\n=== SRT Server Sink Statistics ===\n"); // 遍历每个客户端连接的统计结构 for (guint i = 0; i < stats_array->n_values; i++) { GValue *val = g_value_array_get_nth(stats_array, i); if (GST_VALUE_HOLDS_STRUCTURE(val)) { GstStructure *stats_struct = gst_value_get_structure(val); // 打印完整统计结构(也可按需提取特定字段) g_print("Connection %u:\n%s\n", i, gst_structure_to_string(stats_struct)); // 示例:提取特定字段(如发送字节、丢包数) guint64 bytes_sent; guint32 pkt_lost; if (gst_structure_get_uint64(stats_struct, "bytes-sent", &bytes_sent)) { g_print("Bytes Sent: %" G_GUINT64_FORMAT " bytes\n", bytes_sent); } if (gst_structure_get_uint32(stats_struct, "pkt-lost", &pkt_lost)) { g_print("Packets Lost: %u\n", pkt_lost); } } } g_print("===================================\n"); } // 释放资源 if (stats_array) { g_value_array_unref(stats_array); } // 返回TRUE保持定时器运行,返回FALSE停止 return TRUE; } int main(int argc, char **argv) { // Initialize GStreamer gst_init(&argc, &argv); //Creating GStreamer elements GstElement *pipeline = gst_pipeline_new("my-pipeline"); GstElement *src = gst_element_factory_make("nvarguscamerasrc", "src"); GstElement *encoder = gst_element_factory_make("omxh264enc", "encoder"); GstElement *muxer = gst_element_factory_make("mpegtsmux", "muxer"); GstElement *sink = gst_element_factory_make("srtserversink", "sink"); // 修正:添加变量类型声明 //Check if all elements are successfully created if (!pipeline || !src || !encoder || !muxer || !sink) { g_printerr("Failed to create elements. Exiting.\n"); return -1; } //Setting parameters for elements g_object_set(src, "sensor-id", 0, NULL); // 修正:C语言用NULL代替nullptr g_object_set(src, "sensor-mode", 0, NULL); g_object_set(G_OBJECT(encoder), "insert_sps_pps", TRUE, NULL); g_object_set(encoder, "bitrate", 25000, NULL); g_object_set(G_OBJECT(sink), "uri", "srt://:7008", "latency", 100, NULL); //Add elements to the pipeline gst_bin_add_many(GST_BIN(pipeline), src, encoder, muxer, sink, NULL); //Check if all elements are successfully added to the pipeline if (!gst_element_link_many(src, encoder, muxer, sink, NULL)) { g_printerr("Failed to link elements. Exiting.\n"); gst_object_unref(pipeline); return -1; } //Start the pipeline gst_element_set_state(pipeline, GST_STATE_PLAYING); // 添加定时器:每隔1秒触发一次统计打印(单位:毫秒) guint timer_id = g_timeout_add(1000, print_srt_stats, sink); //Wait until error or EOS GstBus *bus = gst_element_get_bus(pipeline); GstMessage *msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, (GstMessageType)(GST_MESSAGE_ERROR | GST_MESSAGE_EOS)); // 停止定时器 g_source_remove(timer_id); //Stop the pipeline gst_element_set_state(pipeline, GST_STATE_NULL); //Clean up GStreamer gst_object_unref(bus); // 修正:添加bus的释放 gst_object_unref(pipeline); return 0; }
关键细节说明
- 属性读取:通过
g_object_get获取stats属性,得到GValueArray后必须用g_value_array_unref释放,避免内存泄漏 - 结构解析:用
gst_value_get_structure将GValue转换为GstStructure,可通过gst_structure_to_string直接打印所有字段,或用gst_structure_get_*系列函数提取特定统计项(如bytes-sent、pkt-lost、rtt等) - 定时器管理:
g_timeout_add会将回调加入Glib主循环,管道停止时需调用g_source_remove销毁定时器 - 代码修正:原代码中
sink变量未声明类型,且C语言需用NULL代替C++的nullptr,同时添加了bus的释放逻辑
内容的提问来源于stack exchange,提问作者H_R
相关产品推荐
相关产品推荐

