C 将管道设置为播放状态后,Gstreamer回调未命中

C 将管道设置为播放状态后,Gstreamer回调未命中,c,gstreamer,C,Gstreamer,我正在编写一个媒体应用程序,从视频文件中获取视频帧。为此,我希望在从管道中提取样本之前获取视频属性。因此,我在解码器处添加了一个针对auto-plug信号的回调,并尝试获取属性。即使在我将管道置于播放状态后,也不会调用这些回调,但是如果我尝试使用gst\u app\u sink\u pull\u sample从管道中提取样本,就会调用这些回调 我有什么遗漏吗?我的理解是,当我们将管道置于播放状态时,将调用这些回调 #include <gst/gst.h> #include <s

我正在编写一个媒体应用程序,从视频文件中获取视频帧。为此,我希望在从管道中提取样本之前获取视频属性。因此,我在解码器处添加了一个针对
auto-plug
信号的回调,并尝试获取属性。即使在我将管道置于播放状态后,也不会调用这些回调,但是如果我尝试使用
gst\u app\u sink\u pull\u 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;
}
#包括
#包括
静态无效总线回调(GstBus*总线、GstMessage*消息、gpointer数据)
{
开关(GST\信息\类型(msg))
{
案例GST\u消息\u错误:{
GError*err;
gchar*调试;
gst\消息\解析\错误(消息、错误和调试);
g_打印(“错误:%s\n”,错误->消息);
g_无错误(err);
g_自由(调试);
打破
}
违约:
/*未处理的消息*/
打破
}
}
静态空隙
在键盘上添加(GstElement*元素、GstPad*键盘、gpointer数据)
{
GstPad*下沉板;
GstElement*解码器=(GstElement*)数据;
/*我们现在可以将此焊盘链接到解码器接收器焊盘*/
sinkpad=gst_元素_get_静态_pad(译码器,“接收器”);
gst_垫_链接(垫、下沉垫);
gst_object_unref(下沉板);
}
静态空隙
自动插拔选择(GstElement*解码器、GstPad*焊盘、GSTCAP*封盖、,
GstElementFactory*工厂,内部*宽度)
{
const gchar*klass=gst\u元素\u工厂\u获取\u klass(工厂);
/*MW_customData*cdata=(MW_customData*)数据*/
GstCaps*scaps=gst\u pad\u query\u caps(pad,NULL);
gst结构*str=gst结构(scaps,0);
const gchar*type=gst\u结构\u获取\u名称(str);
printf(“焊盘盖:%s\n”,类型);
如果(g_strstrstr(类型,“视频”))
{
gst_结构_get_int(str,“width”,width);
printf(“宽度:%d\n”,*宽度);
}
}
内部主管道(gint argc、,
gchar*argv[]
{
GstElement*管道、*文件RC、*解码器、*fakesink;
GstBus*总线;
/*初始化GStreamer*/
gst_init(&argc,&argv);
/*检查args*/
如果(argc!=2){
g_print(“用法:%s\n”,argv[0]);
返回-1;
}
/*创建一个新管道以容纳图元*/
管道=gst U管道\u新(“管道”);
/*巴士回拨*/
总线=gst_管道_获取_总线(gst_管道(管道));
gst_总线_添加_手表(总线,总线_回调,NULL);
商品及服务税(巴士);
/*创建文件源和类型查找元素*/
filesrc=gst_元素_工厂_制造(“filesrc”,“源”);
g_object_set(g_object(filesrc),“location”,argv[1],NULL);
解码器=gst\u元件\u工厂制造商(“decodebin”,空);
fakesink=gst元素工厂制造(“fakesink”、“水槽”);
整数宽度=0;
/*解码器完成操作后,连接水槽垫*/
g_信号连接(解码器,“添加焊盘”、g_回调(添加焊盘上)和宽度);
g_信号连接(解码器,“自动插拔选择”,g_回调(自动插拔选择),fakesink);
/*设置*/
gst_-bin_-add_-many(gst_-bin(管道)、filesrc、解码器、fakesink、NULL);
gst_元素_链接(文件RC、解码器);
gst_元素_设置_状态(gst_元素(管道)、gst_状态_播放);
printf(“宽度:%d\n”,宽度);
gst\元素\设置\状态(gst\元素(管道),gst\状态\空);
返回0;
}

任何时候都不能离开管道运行。您可能会在数据触发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

请您发布您目前编写的代码,以便我们了解需要更正的内容好吗?Virolino-我正在尝试从
auto\u plug\u select
回调中获取宽度值,但它没有被调用。我将管道置于播放状态。回调中的print语句也未被打印。