使用非静态消息处理程序获取 gstreamer 总线消息
Get gstreamer bus messages using non-static message handler
我使用 gstreamer 创建了一个程序,它监听不同的端口 (比如 5) 用于 rtp 数据包。
现在我创建了一个 class (比如说 GstClass) 来创建管道,并且有一个回调函数监听总线消息(我需要这个消息系统在一定超时后关闭管道).
主函数如下所示 - 使用 2 个对象创建 2 个线程,并在两个线程中调用 GstFunc。第一个函数将监听端口 5000,第二个函数将监听端口 5008
int main() {
char filepath1[ ]= "/home/rohan/Tornado1.raw";
char filepath2[ ]= "/home/rohan/Tornado2.raw";
unsigned int port1 = 5000;
unsigned int port2 = 5008;
GstClass GstObj1;
GstClass GstObj2;
boost::thread thrd1 { &GstClass::GstFunc, &GstObj1, filepath1, &port1 };
boost::thread thrd2 { &GstClass::GstFunc, &GstObj2, filepath2, &port2 };
thrd1.join();
thrd2.join();
return 0;
}
class GstClass
看起来像这样 -
class GstClass {
protected:
//some other variables...
GMainLoop *msLoop;
public:
gboolean bus_call(GstBus *bus, GstMessage *message,
gpointer data);
void GstFunc(char *filepath, unsigned int *port);
};
详细功能查看请看this example。将函数 int main (int argc, char *argv[])
替换为 void GstFunc(char *filepath, unsigned int *port)
并进行适当的更改。
GstFunc
长得像
void GstFunc(char *filepath, unsigned int *port)
GMainLoop *loop;
GstElement *pipeline, *source, *conv, *sink;
GstBus *bus;
guint bus_watch_id;
gst_init (NULL, NULL);
loop = g_main_loop_new (NULL, FALSE);
/* Create gstreamer elements */
pipeline = gst_pipeline_new ("audio-player");
source = gst_element_factory_make ("autoaudiosrc", "audiosource");
conv = gst_element_factory_make ("audioconvert", "converter");
sink = gst_element_factory_make ("autoaudiosink", "audio-output");
if (!pipeline || !source || !conv || !sink) {
g_printerr ("One element could not be created. Exiting.\n");
return -1;
}
/* we add a message handler */
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
bus_watch_id = gst_bus_add_watch (bus, bus_call, NULL);
gst_object_unref (bus);
gst_bin_add_many (GST_BIN (pipeline), source, conv, sink, NULL);
gst_element_link_many (GST_BIN (pipeline), source, conv, sink, NULL);
g_main_loop_run (loop);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (GST_OBJECT (pipeline));
g_source_remove (bus_watch_id);
g_main_loop_unref (loop);
return 0;
}
现在我面临的困境是静态函数 (示例) bus_call(...)
.
因为我在 2 个不同的线程中创建了 2 个管道,它们正在侦听 2 个不同的端口,所以我不能将此函数作为静态函数(在对象之间共享)。我怎样才能使这两条管道相互分离?或者我怎样才能让这个静态 bus_call(...)
变成非静态?
简单地删除 static 关键字没有帮助并出现此错误
error: invalid use of non-static member function ‘gboolean GstClass::bus_call(GstBus*, GstMessage*, gpointer)‘
小Imp点数
我已经提到 this document 说 要使用总线,请使用 gst_bus_add_watch()
[=29 将消息处理程序附加到管道总线=]
GstClass::GstFunc()
中的gst_bus_add_watch()
(回调bus_call)映射到头文件gstbus.h 声明只是
GST_API
guint gst_bus_add_watch(GstBus * bus, GstBusFunc func, gpointer user_data);
我最初的猜测是 gst_bus_add_watch
期望第二个参数是静态函数。我不确定为什么。这里可以做什么?
*********************** 问题编辑 2 ********* **************
是否可以像 gboolean bus_call(GstBus *bus, GstMessage *message,gpointer data,**SOME POINTER TO THE OBJECT**)
一样向 bus_call
添加参数?
这样函数将保持静态,同时有一个指向调用它的对象的指针,并作用于对象(比如关闭该对象的管道) .
我认为你无法随心所欲。 GstBusFunc() 的签名(回调)是指向函数的指针,而不是指向成员函数的指针。他们是 different things。 (我也失败了 std::bind,fwiw)。
我做了一些与您描述的非常相似的事情,虽然不完全相同,但我采用了一种可能对您有所帮助的不同方法。您 可以 使用静态方法,但您必须将指向管道 class 的指针传递给 gst_bus_add_watch。在您的 busCallback 中,您取消对指针的引用,然后就可以了!您可能还需要实施某种锁定方案。
class MyPipeline {
GstElement *m_pipeline;
public:
MyPipeline(...);
static void gboolean busCallback(GstBus *bus, GstMessage *msg, gpointer p);
}
MyPipeline::MyPipeline(...)
{
// create pipeline...
m_pipeline = ...;
// bus callback, pass 'this' as arg for callback
GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(m_pipeline));
gst_bus_add_watch(bus, &MyPipeline::busCallback, this);
gst_object_unref(bus);
// ...
}
gboolean MyPipeline::busCallback(GstBus *, GstMessage *msg, gpointer p)
{
// get lock if needed...
// recover your class instance
MyPipeline *myPipeline = (MyPipeline *)p;
// do what you need to, free lock
return TRUE;
}
我使用 gstreamer 创建了一个程序,它监听不同的端口 (比如 5) 用于 rtp 数据包。
现在我创建了一个 class (比如说 GstClass) 来创建管道,并且有一个回调函数监听总线消息(我需要这个消息系统在一定超时后关闭管道).
主函数如下所示 - 使用 2 个对象创建 2 个线程,并在两个线程中调用 GstFunc。第一个函数将监听端口 5000,第二个函数将监听端口 5008
int main() {
char filepath1[ ]= "/home/rohan/Tornado1.raw";
char filepath2[ ]= "/home/rohan/Tornado2.raw";
unsigned int port1 = 5000;
unsigned int port2 = 5008;
GstClass GstObj1;
GstClass GstObj2;
boost::thread thrd1 { &GstClass::GstFunc, &GstObj1, filepath1, &port1 };
boost::thread thrd2 { &GstClass::GstFunc, &GstObj2, filepath2, &port2 };
thrd1.join();
thrd2.join();
return 0;
}
class GstClass
看起来像这样 -
class GstClass {
protected:
//some other variables...
GMainLoop *msLoop;
public:
gboolean bus_call(GstBus *bus, GstMessage *message,
gpointer data);
void GstFunc(char *filepath, unsigned int *port);
};
详细功能查看请看this example。将函数 int main (int argc, char *argv[])
替换为 void GstFunc(char *filepath, unsigned int *port)
并进行适当的更改。
GstFunc
长得像
void GstFunc(char *filepath, unsigned int *port)
GMainLoop *loop;
GstElement *pipeline, *source, *conv, *sink;
GstBus *bus;
guint bus_watch_id;
gst_init (NULL, NULL);
loop = g_main_loop_new (NULL, FALSE);
/* Create gstreamer elements */
pipeline = gst_pipeline_new ("audio-player");
source = gst_element_factory_make ("autoaudiosrc", "audiosource");
conv = gst_element_factory_make ("audioconvert", "converter");
sink = gst_element_factory_make ("autoaudiosink", "audio-output");
if (!pipeline || !source || !conv || !sink) {
g_printerr ("One element could not be created. Exiting.\n");
return -1;
}
/* we add a message handler */
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
bus_watch_id = gst_bus_add_watch (bus, bus_call, NULL);
gst_object_unref (bus);
gst_bin_add_many (GST_BIN (pipeline), source, conv, sink, NULL);
gst_element_link_many (GST_BIN (pipeline), source, conv, sink, NULL);
g_main_loop_run (loop);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (GST_OBJECT (pipeline));
g_source_remove (bus_watch_id);
g_main_loop_unref (loop);
return 0;
}
现在我面临的困境是静态函数 (示例) bus_call(...)
.
因为我在 2 个不同的线程中创建了 2 个管道,它们正在侦听 2 个不同的端口,所以我不能将此函数作为静态函数(在对象之间共享)。我怎样才能使这两条管道相互分离?或者我怎样才能让这个静态 bus_call(...)
变成非静态?
简单地删除 static 关键字没有帮助并出现此错误
error: invalid use of non-static member function ‘gboolean GstClass::bus_call(GstBus*, GstMessage*, gpointer)‘
小Imp点数
我已经提到 this document 说 要使用总线,请使用 gst_bus_add_watch()
[=29 将消息处理程序附加到管道总线=]
GstClass::GstFunc()
中的gst_bus_add_watch()
(回调bus_call)映射到头文件gstbus.h 声明只是
GST_API
guint gst_bus_add_watch(GstBus * bus, GstBusFunc func, gpointer user_data);
我最初的猜测是 gst_bus_add_watch
期望第二个参数是静态函数。我不确定为什么。这里可以做什么?
*********************** 问题编辑 2 ********* **************
是否可以像 gboolean bus_call(GstBus *bus, GstMessage *message,gpointer data,**SOME POINTER TO THE OBJECT**)
一样向 bus_call
添加参数?
这样函数将保持静态,同时有一个指向调用它的对象的指针,并作用于对象(比如关闭该对象的管道) .
我认为你无法随心所欲。 GstBusFunc() 的签名(回调)是指向函数的指针,而不是指向成员函数的指针。他们是 different things。 (我也失败了 std::bind,fwiw)。
我做了一些与您描述的非常相似的事情,虽然不完全相同,但我采用了一种可能对您有所帮助的不同方法。您 可以 使用静态方法,但您必须将指向管道 class 的指针传递给 gst_bus_add_watch。在您的 busCallback 中,您取消对指针的引用,然后就可以了!您可能还需要实施某种锁定方案。
class MyPipeline {
GstElement *m_pipeline;
public:
MyPipeline(...);
static void gboolean busCallback(GstBus *bus, GstMessage *msg, gpointer p);
}
MyPipeline::MyPipeline(...)
{
// create pipeline...
m_pipeline = ...;
// bus callback, pass 'this' as arg for callback
GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(m_pipeline));
gst_bus_add_watch(bus, &MyPipeline::busCallback, this);
gst_object_unref(bus);
// ...
}
gboolean MyPipeline::busCallback(GstBus *, GstMessage *msg, gpointer p)
{
// get lock if needed...
// recover your class instance
MyPipeline *myPipeline = (MyPipeline *)p;
// do what you need to, free lock
return TRUE;
}