Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

g_main_loop_run blocks the Qthread and does not allow to stop video

I have created a separate class for gstreamer to stream videos.
This class runs on separate thread by using moveToThread().
I am using Qt5.5 for development.
When I issue startcommand on main thread , Qthread starts and gstreamer uses g_main_loop_run to stream videos. This works absolutely fine. But somehow g_main_loop_run blocks the thread and when I issue signal to stop video from main thread , it doesnt execute slot in gstreamer class.

Can someone please advice me how to resolve that issue? Either I can replace g_main_loop_run with someother command or may be use g_main_loop_quit( gloop ); in another way.

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.
}

// somewhere in main thread

 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();
like image 602
samprat Avatar asked Dec 17 '15 01:12

samprat


1 Answers

There is no need to rely on aGMainLoop. The pipeline should run just fine without a g_main_loop_run().

The one thing you have to note here is that your main Qt application loop will either have to poll the pipeline's bus for messages OR use gst_bus_set_sync_handler to set a callback function for the bus to be called as messages arrive. For the later you have to be aware that this function is then called from the pipeline's thread and not the application's one. Emitting signals here should be fine though.

If you want to go the thread way you would have to manually create a thread in your application which runs the GMainLoop. Also possible - the above looks like the easier and cleaner way to me though.

like image 162
Florian Zwoch Avatar answered Sep 27 '22 20:09

Florian Zwoch