将管道设置为播放状态后,Gstreamer 回调未命中
Posted
技术标签:
【中文标题】将管道设置为播放状态后,Gstreamer 回调未命中【英文标题】:Gstreamer call backs are not hitting after setting pipeline to playing state 【发布时间】:2019-07-16 06:33:24 【问题描述】:我正在编写一个媒体应用程序来从视频文件中抓取视频帧。为此,我想在从管道中提取样本之前获取视频属性。因此,我在解码器处添加了auto-plug
信号的回调并尝试获取属性。即使我将管道置于播放状态后也不会调用这些回调,但如果我尝试使用 gst_app_sink_pull_sample
从管道中提取样本,则会调用这些回调。
我在这里遗漏了什么吗?我的理解是,当我们将管道置于播放状态时,这些回调将被调用。
#include <gst/gst.h>
#include <stdio.h>
static void bus_callback (GstBus *bus, GstMessage *msg, gpointer data)
switch (GST_MESSAGE_TYPE (msg))
case GST_MESSAGE_ERROR:
GError *err;
gchar *debug;
gst_message_parse_error (msg, &err, &debug);
g_print ("Error: %s\n", err->message);
g_error_free (err);
g_free (debug);
break;
default:
/* Unhandled message */
break;
static void
on_pad_added (GstElement *element, GstPad *pad, gpointer data)
GstPad *sinkpad;
GstElement *decoder = (GstElement *) data;
/* We can now link this pad with the decoder sink pad */
sinkpad = gst_element_get_static_pad (decoder, "sink");
gst_pad_link (pad, sinkpad);
gst_object_unref (sinkpad);
static void
auto_plug_select (GstElement *decoder, GstPad *pad, GstCaps *caps,
GstElementFactory *factory, int *width )
const gchar *klass = gst_element_factory_get_klass (factory);
/* MW_customData *cdata = (MW_customData*) data;*/
GstCaps *scaps = gst_pad_query_caps (pad, NULL);
GstStructure *str = gst_caps_get_structure (scaps, 0);
const gchar *type = gst_structure_get_name (str);
printf (" Pad cap: %s\n", type);
if (g_strrstr(type,"video"))
gst_structure_get_int (str, "width", width);
printf(" Width: %d\n", *width);
int main (gint argc,
gchar *argv[])
GstElement *pipeline, *filesrc, *decoder, *fakesink;
GstBus *bus;
/* init GStreamer */
gst_init (&argc, &argv);
/* check args */
if (argc != 2)
g_print ("Usage: %s <filename>\n", argv[0]);
return -1;
/* create a new pipeline to hold the elements */
pipeline = gst_pipeline_new ("pipeline");
/* Bus call back*/
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_bus_add_watch (bus, bus_callback, NULL);
gst_object_unref (bus);
/* create file source and typefind element */
filesrc = gst_element_factory_make ("filesrc", "source");
g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
decoder = gst_element_factory_make ("decodebin", NULL);
fakesink = gst_element_factory_make ("fakesink", "sink");
int width = 0;
/* Connect the sink pad when decoder completes the operation */
g_signal_connect (decoder, "pad-added", G_CALLBACK (on_pad_added), &width);
g_signal_connect (decoder, "autoplug-select", G_CALLBACK (auto_plug_select), fakesink);
/* setup */
gst_bin_add_many (GST_BIN (pipeline), filesrc, decoder, fakesink, NULL);
gst_element_link (filesrc, decoder);
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
printf(" Width: %d\n", width);
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
return 0;
【问题讨论】:
能否请您发布您到目前为止编写的代码,以便我们了解需要更正的地方? Virolino - 我试图从auto_plug_select
回调中获取宽度值,但它没有被调用。我将管道置于播放状态。回调中的打印语句也没有被打印出来。
【参考方案1】:
您不会在任何时候离开管道以进行运行。您可能会在数据触发 decodebin 的回调之前停止它。
为了便宜试试:
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
g_usleep(100000000);
printf(" Width: %d\n", width);
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
但更正确的做法是使用真正的 GMainLoop 并对某些事件采取行动以再次停止管道。
编辑:附言。为什么不GstDiscoverer
? https://gstreamer.freedesktop.org/documentation/pbutils/gstdiscoverer.html?gi-language=c
【讨论】:
谢谢,弗洛里安。这真的很有用。以上是关于将管道设置为播放状态后,Gstreamer 回调未命中的主要内容,如果未能解决你的问题,请参考以下文章