g_main_loop_run阻止Qthread并且不允许停止视频

sam*_*rat 12 c++ qt multithreading gstreamer qthread

我为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.
}
Run Code Online (Sandbox Code Playgroud)

//主线程中的某个地方

 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();
Run Code Online (Sandbox Code Playgroud)

Tho*_*dSO 0

免责声明:我对 GLib/GTK 一无所知,但我很快就在 google 上搜索到了一些灵​​感——一些灵感来自于这篇文章为单独的 g_main_loop 添加回调https://developer.gnome.org/glib/stable/glib-The- Main-Event-Loop.html#g-timeout-add

问题是,您正在处理两个事件循环 - 线程的 Qt 事件循环(隐式输入到 内部)QThread::run ()和 GLib 循环(您手动输入到slotStartStream (). 从主线程发送的所有 Qt 信号都必须经过 Qt 调度程序——因此您必须给 Qt 一些处理它们的机会,这意味着 GLib 循环需要定期将控制权移交给 Qt。所以想法是:安装一个 GLib 将定期调用的回调(例如一个简单的计时器),并从该回调发出一个processEvents ()函数让 Qt 完成其工作。

我会尝试这样的事情:

gboolean myCallback (gpointer user_data)
{
  // The Qt thread is passed as a parameter during callback installation

  QThread* workerThread = reinterpret_cast<QThread*> (user_data);

  // Access the Qt thread's event dispatcher...

  QAbstractEventDispatcher* disp = workerThread->eventDispatcher ();

  // ...and let it do its work

  disp->processEvents (QEventLoop::AllEvents);

  return G_SOURCE_CONTINUE;
}

void StreamingVideo::slotStartStream ()
{
  [...]

  g_print ("Running...\n");

  // Install callback to intertwine Qt's thread-local eventloop with our GLib loop
  g_timeout_add (50, myCallback, QThread::currentThread ());

  emit sigStartStream(); // signal to main thread to issue success command . works fine

  g_main_loop_run( gloop );
  g_print ("Returned, stopping playback\n");

  [...]
Run Code Online (Sandbox Code Playgroud)

现在,我不知道这是否解决了您的所有问题(事实上我很确定它没有:-)),但我认为您至少会看到您的slotStopStream ()意愿实际上被称为(在范围内)工作线程)在这些修改之后。

总而言之,这是一个相当糟糕的设置,但它可能会起作用。