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_r
un 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();
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With