我为gstreamer创建了一个单独的类来传输视频
该类使用moveToThread()在单独的线程上运行
我正在使用Qt5.5进行开发
当我在主线程上发出startcommand时,Qthread启动,gstreamer使用g_main_loop_run
来传输视频。这绝对没问题。但不知何故g_main_loop_run
阻塞了线程,当我发出信号从主线程停止视频时,它不会在gstreamer类中执行槽。
有人可以建议我如何解决这个问题吗?要么我可以用其他命令替换g_main_loop_r
un,要么可以使用g_main_loop_quit( gloop )
;另一种方式。
void StreamingVideo::slotStartStream() // this slot called on start of thread from main thread
{
if( !isElementsLinked() )
{
qDebug() << " we are emitting in dummy server ";
//emit sigFailed( "elementsFailed" ); // WILL CONNECT IT WITH MAIN GUI ONXCE CODE IS FINISHED
return;
}
gst_bus_add_watch( bus, busCall, gloop );
gst_object_unref( bus );
//proper adding to pipe
gst_bin_add_many( GST_BIN( pipeline ), source, capsFilter, conv, videoRate, capsFilterRate,
clockDisplay, videoEnc, udpSink, NULL
);
//proper linking:
gst_element_link_many( source, capsFilter, conv, videoRate, capsFilterRate, clockDisplay, videoEnc, udpSink, NULL );
g_print("Linked all the Elements together\n");
gst_element_set_state( pipeline, GST_STATE_PLAYING );
// Iterate
g_print ("Running...\n");
emit sigStartStream(); // signal to main thread to issue success command . works fine
g_main_loop_run( gloop );
g_print ("Returned, stopping playback\n");
//gst_element_set_state (pipeline, GST_STATE_NULL);
if( g_main_loop_is_running( gloop ) )
{
qDebug() << " in g_main_loop_is_runnung emiting signal ";
emit sigStartStream();
}
if( !g_main_loop_is_running( gloop) )
{
qDebug() << "in not gmain running thread id";
qDebug() << QThread::currentThreadId();
}
}
void StreamingVideo::slotStopStream() // THIS SLOT IS NOT CALLED WHEN VIDEO RUNNING
{
qDebug() << " we are planning to stop streaming stramingVideo::slotStopStream ";
g_print ("Returned, stopping playback\n");
g_main_loop_quit( gloop );
gst_element_set_state (pipeline, GST_STATE_NULL);
// g_main_loop_quit( gloop );
releaseMemory();
emit sigStopStream(); // signal to main thread to issue message saying video has stopped.
}
//主线程中的某个地方
threadStreaming = new QThread();
streamVideo = new StreamingVideo( "127.0.0.1"); // we will automate this ip address later on
streamVideo->moveToThread( threadStreaming );
connect( threadStreaming, SIGNAL( started() ), streamVideo, SLOT( slotStartStream() ) );
connect( streamVideo, SIGNAL( sigStopStream() ), threadStreaming, SLOT( quit() ) );
connect( streamVideo, SIGNAL( sigStopStream() ), streamVideo, SLOT(deleteLater() ) );
connect( threadStreaming, SIGNAL( finished() ), threadStreaming, SLOT(deleteLater() ) );
connect( streamVideo, SIGNAL( sigStartStream() ), this, SLOT( slotTrueStreamRun() ) );
connect( streamVideo, SIGNAL( sigStopStream() ), this, SLOT( slotFalseStreamRun() ) );
connect( this, SIGNAL( sigMopsCamStopCmd() ), streamVideo, SLOT(slotStopStream() ) );
threadStreaming->start();
答案 0 :(得分:2)
无需依赖GMainLoop
。管道应该运行得很好而没有g_main_loop_run()
。
你需要注意的一件事是你的主要Qt应用程序循环要么必须轮询管道总线以获取消息,要么使用gst_bus_set_sync_handler
来设置要调用的总线的回调函数消息到达时对于后者,您必须知道此函数然后从管道的线程而不是应用程序的线程调用。这里发出的信号应该没问题。
如果你想采用线程方式,你必须在运行GMainLoop
的应用程序中手动创建一个线程。也可能 - 上面看起来对我来说更简单,更清洁。
答案 1 :(得分:0)
免责声明:我对GLib / GTK一无所知,但我快速搜索了一下 - 一些灵感来自这篇SO add callback for separate g_main_loop和https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-timeout-add
的文档问题在于你正在处理两个事件循环 - 线程的Qt事件循环(隐式输入QThread::run ()
内部)和GLib循环(您在{{1}内手动输入) }。您从主线程发送的所有Qt信号必须通过Qt调度程序 - 因此您必须给Qt一些处理它们的机会,这意味着GLib循环需要定期将控制权移交给Qt。所以我的想法是:安装一个GLib将定期调用的回调(例如一个简单的计时器),并从该回调中发出一个slotStartStream ()
函数,让Qt完成它的工作。
我会尝试这样的事情:
processEvents ()
现在,我不知道这是否能解决你所有的问题(实际上我很确定它不会:-)),但我认为你至少会看到你的{事实上,{1}}将在这些修改之后被调用(在工作线程的范围内)。
总而言之,这是一个相当神奇的设置,但它可能会起作用。
答案 2 :(得分:0)
没有必要在Qt应用程序中使用glib的GMainLoop。 Qt拥有自己的GMainLoop(QEventLoop)版本,您可以将其视为exec()方法。
例如,如果您有一个QGuiApplication类/派生类,则可以调用其exec()方法来启动其主事件循环。 http://doc.qt.io/qt-5/qguiapplication.html#exec
类似地,如果你有一个QThread类/派生类,你可以调用它的exec()方法来启动它的本地事件循环。 http://doc.qt.io/qt-4.8/qthread.html#exec
总结,任何需要事件循环来触发其进程的glib代码(例如g_bus_own_name,在glib中你需要调用GMainLoop才能启动dbus。如果你把它放在Qt代码中,你只需要调用exec()而不是处理GMainLoop。
简而言之,只有一个事件循环,但不同的组织(例如gnome,qt)实现了不同的实现
答案 3 :(得分:0)
感谢OP提出了有关GLib / Qt互操作的重要问题,该问题在Internet上没有充分介绍。 =TRIM(LEFT(SUBSTITUTE(MID(A3,FIND("-",A3,1)+1,99)," ",REPT(" ",99)),40))+0
在GMainLoop
中对我的工作方式如下:
QThread