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语句也未被打印。