一、Gstreamer总线(bus)

本文介绍了GStreamer中三种监听Bus总线消息的方法:阻塞监听、事件监听及信号监听。阻塞监听通过调用`gst_bus_timed_pop_filtered`等待特定类型的消息;事件监听通过`gst_bus_add_watch`注册回调函数;信号监听则通过`gst_bus_add_signal_watch`并连接到指定信号。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  以下总结三种监听Bus总线消息的方式。

1 Gst阻塞监听

[..]
bus = gst_element_get_bus (pipeline);
/*阻塞,一直等到出现error和eos消息*/
GstMessage *  gst_bus_timed_pop_filtered (GstBus * bus, 
                                          GstClockTime timeout, /*超时时间*/
                                          GstMessageType types);/*消息类型*/
[..]

2 事件

  我认为这类似于Glib主循环中添加Source事件源。

[..]
bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
guint    gst_bus_add_watch   (GstBus * bus,
                              GstBusFunc func, /*回调函数*/
                              gpointer user_data);
[..]
/*回调函数定义*/
typedef gboolean (*GstBusFunc)  (GstBus * bus, 
                                 GstMessage * message, 
                                 gpointer user_data);

3 信号

  连接到所需要的信号格式为"message::< type >",如

  • message::error
  • message::eos
  • message::state-changed
  • message::application
  bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));

  gst_bus_add_signal_watch(bus);
  g_signal_connect(G_OBJECT(bus), 
                   "message::state-changed", 
                    G_CALLBACK(eos_cb), pipeline);
/*回调函数*/
static void eos_cb 
(GstBus *bus, GstMessage *msg, gpointer pipeline);

参考1: 官方手册如何使用Bus

手动构建GStreamer管道涉及以下几个步骤: 1. **初始化GStreamer**:在使用GStreamer之前,需要先初始化它。 2. **创建元素**:根据需要的功能创建不同的GStreamer元素,例如源、解码器、过滤器、接收器等。 3. **组装管道**:将创建的元素按顺序连接起来,形成个完整的管道。 4. **设置管道状态**:将管道设置为播放状态,开始处理数据。 5. **运行主循环**:启动GStreamer的主循环,等待事件发生。 6. **清理资源**:在程序结束时,释放所有资源。 以下是个简单的示例代码,展示了如何手动构建GStreamer管道来播放视频文件: ```c #include <gst/gst.h> int main(int argc, char *argv[]) { GstElement *pipeline; GstBus *bus; GstMessage *msg; // 初始化GStreamer gst_init(&argc, &argv); // 创建元素 GstElement *source = gst_element_factory_make("filesrc", "file-source"); GstElement *demuxer = gst_element_factory_make("oggdemux", "demuxer"); GstElement *decoder = gst_element_factory_make("theoradec", "decoder"); GstElement *conv = gst_element_factory_make("videoconvert", "converter"); GstElement *sink = gst_element_factory_make("autovideosink", "video-output"); // 检查元素是否创建成功 if (!source || !demuxer || !decoder || !conv || !sink) { g_printerr("Not all elements could be created.\n"); return -1; } // 设置文件源路径 g_object_set(G_OBJECT(source), "location", "/path/to/video.ogv", NULL); // 创建管道 pipeline = gst_pipeline_new("video-player"); if (!pipeline) { g_printerr("Pipeline could not be created.\n"); return -1; } // 组装管道 gst_bin_add_many(GST_BIN(pipeline), source, demuxer, decoder, conv, sink, NULL); gst_element_link(source, demuxer); gst_element_link_many(decoder, conv, sink, NULL); // 设置demuxer的pad-added回调 g_signal_connect(demuxer, "pad-added", G_CALLBACK(on_pad_added), decoder); // 设置管道状态为播放 gst_element_set_state(pipeline, GST_STATE_PLAYING); // 获取管道总线 bus = gst_element_get_bus(pipeline); // 监听消息 msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS); // 处理消息 if (msg != NULL) { GError *err; gchar *debug_info; switch (GST_MESSAGE_TYPE(msg)) { case GST_MESSAGE_ERROR: gst_message_parse_error(msg, &err, &debug_info); g_printerr("Error received from element %s: %s\n", GST_OBJECT_NAME(msg->src), err->message); g_printerr("Debugging information: %s\n", debug_info ? debug_info : "none"); g_clear_error(&err); g_free(debug_info); break; case GST_MESSAGE_EOS: g_print("End-Of-Stream reached.\n"); break; default: g_printerr("Unexpected message received.\n"); break; } gst_message_unref(msg); } // 释放资源 gst_object_unref(bus); gst_element_set_state(pipeline, GST_STATE_NULL); gst_object_unref(pipeline); return 0; } void on_pad_added(GstElement *element, GstPad *pad, gpointer data) { GstPad *sink_pad = gst_element_get_static_pad((GstElement *)data, "sink"); GstPadLinkReturn ret; GstCaps *new_pad_caps = NULL; GstStructure *new_pad_struct = NULL; const gchar *new_pad_type = NULL; g_print("Received new pad '%s' from '%s':\n", GST_PAD_NAME(pad), GST_ELEMENT_NAME(element)); new_pad_caps = gst_pad_get_current_caps(pad); new_pad_struct = gst_caps_get_structure(new_pad_caps, 0); new_pad_type = gst_structure_get_name(new_pad_struct); if (g_str_has_prefix(new_pad_type, "video/x-theora")) { ret = gst_pad_link(pad, sink_pad); if (GST_PAD_LINK_FAILED(ret)) { g_print("Type is '%s' but link failed.\n", new_pad_type); } else { g_print("Link succeeded (type '%s').\n", new_pad_type); } } gst_caps_unref(new_pad_caps); gst_object_unref(sink_pad); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值