Discussion:
[gst-devel] how to make gstreamer run in separate thread
4ernov
2010-04-16 07:31:30 UTC
Permalink
Hi,

I try to make whole gstreamer pipeline live in separate thread. I need
it generally because I work with very slow v4l2 device driver and it
takes considerable time for to change state of pipeline (init driver
etc.). So I create special QThread in Qt4 app and make all the
construction work (i.e. create all the elements, the pipeline itself
etc.) in its run() method. I also connect to the bus of the pipeline
to get some info:

GstBus* bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_bus_add_watch (bus, audio_bus_call, this);
gst_object_unref (bus);

But I eventually found that all the message dispatching is processed
in the main thread of the app. I.e. if I call thread() function which
returns a pointer to a running thread in bus callback:
void audio_bus_call()
{
qDebug()<<"thread:"<<thread();
}
it returns a pointer to the main thread in spite of that all the
GStreamer objects are created in different thread.

Is there any way to make message dispatching process run in different
thread other than main? Or somehow bind GStreamer event loop to Qt's
event loop of some QThread object?

Thank you very much,

Alexey Chernov
wl2776
2010-04-16 07:53:38 UTC
Permalink
I try to make whole gstreamer pipeline live in a separate thread.
...
Is there any way to make message dispatching process run in different
thread other than main? Or somehow bind GStreamer event loop to Qt's
event loop of some QThread object?
Two variants.
1. Poll a message bus in your application's main loop
http://n4.nabble.com/How-can-I-have-two-main-loops-in-my-program-tt1594663.html#a1594734
http://n4.nabble.com/running-g-main-loop-run-in-separate-thread-question-tt1680629.html#a1680629

2. Run a GThread. GStreamer uses glib, so it's anyway included.

I do this way.

class gst_player{
public:
....
void main_loop_thread(void) ///< функция для запуска g_main_loop_run в
отдельном потоке
g_main_loop_run(m_loop);
g_thread_exit(0);
};
void open(char *filename) ;
....
protected:
GMainLoop *m_loop; ///< экземпляр mainloop
GThread *m_loop_thread; ///< Поток, в котором будет работать mainloop
...
};

....

static void main_loop_run(gpointer data)
{
if(!data)
return;
gst_player *player = (gst_player *)data;
player->main_loop_thread();
}

...
void gst_player::open(char * filename)
{
close();
m_loop = g_main_loop_new(NULL,FALSE);
...

if((m_loop_thread=g_thread_create((GThreadFunc)main_loop_run,this,FALSE,NULL))==NULL){
close();
report_error();
}
...
}
--
View this message in context: http://n4.nabble.com/how-to-make-gstreamer-run-in-separate-thread-tp1960435p1963116.html
Sent from the GStreamer-devel mailing list archive at Nabble.com.
Stefan Kost
2010-04-16 09:21:22 UTC
Permalink
Post by 4ernov
Hi,
I try to make whole gstreamer pipeline live in separate thread.
GStreamer already run the data processing in separate threads.
Post by 4ernov
I need
it generally because I work with very slow v4l2 device driver and it
takes considerable time for to change state of pipeline (init driver
etc.).
Are you synchronously waiting for the state change to happen? I wonder
if you just use things a bit sub optimal.

Stefan
Post by 4ernov
So I create special QThread in Qt4 app and make all the
construction work (i.e. create all the elements, the pipeline itself
etc.) in its run() method. I also connect to the bus of the pipeline
GstBus* bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_bus_add_watch (bus, audio_bus_call, this);
gst_object_unref (bus);
But I eventually found that all the message dispatching is processed
in the main thread of the app. I.e. if I call thread() function which
void audio_bus_call()
{
qDebug()<<"thread:"<<thread();
}
it returns a pointer to the main thread in spite of that all the
GStreamer objects are created in different thread.
Is there any way to make message dispatching process run in different
thread other than main? Or somehow bind GStreamer event loop to Qt's
event loop of some QThread object?
Thank you very much,
Alexey Chernov
------------------------------------------------------------------------------
Download Intel&#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
_______________________________________________
gstreamer-devel mailing list
https://lists.sourceforge.net/lists/listinfo/gstreamer-devel
Alexey Chernov
2010-04-16 19:32:32 UTC
Permalink
Post by Stefan Kost
GStreamer already run the data processing in separate threads.
Yes, I've read about it but in my case I would like to make callback functions
live in a separate thread.
Post by Stefan Kost
Post by 4ernov
I need
it generally because I work with very slow v4l2 device driver and it
takes considerable time for to change state of pipeline (init driver
etc.).
Are you synchronously waiting for the state change to happen? I wonder
if you just use things a bit sub optimal.
No, my case is a little complicated. I run two pipelines, one just for v4l2src
and ximagesink (video pipeline) and another for alsasrc and pulsesink (audio
pipeline). The aim is to inform user if he entered wrong /dev/videoX device
(i.e. he entered /dev/video1 but the device is /dev/video0). I start both
pipelines and try to switch them to READY. v4l2src says that he has a wrong
device and throws error on the bus. In this case I try to switch both
pipelines to NULL and print a message to user. But the problem is that audio
pipeline hasn't completed its switch to READY (because of slow tuner driver).
But I try to change it to NULL and it blocks everything until it gets READY
state and then switch back to NULL.

Stefan, it seems that Qt event loop has g_main_loop_run() call somewhere
inside of it. For example, I don't call g_main_loop_run anywhere in my program
at all and even don't create GMainLoop object, I don't have while(true) pseudo
event loop but all the gstreamer stuff works just ok except this issue with
threads. Do you know if it's true? If so, maybe there's some way to bind
gstreamer's event loop to other QThread's Qt event loop..

Thanks for your help
wl2776
2010-04-19 06:39:06 UTC
Permalink
Post by Alexey Chernov
Stefan, it seems that Qt event loop has g_main_loop_run() call somewhere
inside of it. For example, I don't call g_main_loop_run anywhere in my program
at all and even don't create GMainLoop object, I don't have while(true) pseudo
event loop but all the gstreamer stuff works just ok except this issue with
threads. Do you know if it's true? If so, maybe there's some way to bind
gstreamer's event loop to other QThread's Qt event loop..
Does "all the gstreamer stuff" include your-defined bus watch?

It's very easy to check, who calls this function - just run your app in gdb
and put a breakpoint inside the function. Then use the 'bt' command to
display the backtrace.

Googleing for the "Qt polls glib main loop" shows some messages, suggesting
that the work on uniting main loops or QT and GLib were on their way in
2004.
--
View this message in context: http://n4.nabble.com/how-to-make-gstreamer-run-in-separate-thread-tp1960435p2015457.html
Sent from the GStreamer-devel mailing list archive at Nabble.com.
Tim-Philipp Müller
2010-04-19 12:09:05 UTC
Permalink
Post by Alexey Chernov
Stefan, it seems that Qt event loop has g_main_loop_run() call somewhere
inside of it. For example, I don't call g_main_loop_run anywhere in my program
at all and even don't create GMainLoop object, I don't have while(true) pseudo
event loop but all the gstreamer stuff works just ok except this issue with
threads. Do you know if it's true? If so, maybe there's some way to bind
gstreamer's event loop to other QThread's Qt event loop..
Thanks for your help
If you want to process bus messages in a specific thread context that's
not the main application thread, then I would recommend just using
gst_bus_(timed)_pop_(filtered)() for this, either blocking in a while
loop with a small timeout, or hooked into whatever other event/loop
mechanism there is already. You don't need to use a GMainLoop to get to
the bus messages.

Cheers
-Tim
Alexey Chernov
2010-04-19 20:24:06 UTC
Permalink
Thank you, Tim, you're right, tying bus to Qt's event loop is what I really
want. The problem is that although Qt has separate event loops for its threads
(QThreads) all of these loops seem to interact with the only GMainLoop
somewhere deep inside. And the aim is to switch the bus dispatching to its
QThread's event loop.

One of solutions is to set bus handler with gst_bus_set_sync_handler() instead
of gst_bus_add_watch() how wl2776 proposed.
Post by Tim-Philipp Müller
Post by Alexey Chernov
Stefan, it seems that Qt event loop has g_main_loop_run() call somewhere
inside of it. For example, I don't call g_main_loop_run anywhere in my
program at all and even don't create GMainLoop object, I don't have
while(true) pseudo event loop but all the gstreamer stuff works just ok
except this issue with threads. Do you know if it's true? If so, maybe
there's some way to bind gstreamer's event loop to other QThread's Qt
event loop..
Thanks for your help
If you want to process bus messages in a specific thread context that's
not the main application thread, then I would recommend just using
gst_bus_(timed)_pop_(filtered)() for this, either blocking in a while
loop with a small timeout, or hooked into whatever other event/loop
mechanism there is already. You don't need to use a GMainLoop to get to
the bus messages.
Cheers
-Tim
4ernov
2010-04-16 12:06:56 UTC
Permalink
Thank you. And could you please give some details on how to start main
loop with g_main_loop_run to run in a separate thread? Maybe code
sample of main_loop_thread(). Thank you in advance!
wl2776
2010-04-16 13:47:51 UTC
Permalink
Post by 4ernov
Thank you. And could you please give some details on how to start main
loop with g_main_loop_run to run in a separate thread? Maybe code
sample of main_loop_thread(). Thank you in advance!
No more details, my main_loop_thread() is the inliner, declared inside the
class declaration:

class gst_player{
public:
...
void main_loop_thread(void){
g_main_loop_run(m_loop);
g_thread_exit(0);
};
...
};

I've accidentally deleted { in my previous post.
--
View this message in context: http://n4.nabble.com/how-to-make-gstreamer-run-in-separate-thread-tp1960435p2001719.html
Sent from the GStreamer-devel mailing list archive at Nabble.com.
Wes Miller
2010-04-16 15:31:15 UTC
Permalink
I was just working on this :-)

I put my callback routines in friend functions of the class that I run in
the separate thread. I am not sure which thread they run in, guess I can
check that, but it works great. You do have to pass "this" as the data to
the callbacks so you can manipulate the class members.

Wes
--
View this message in context: http://n4.nabble.com/how-to-make-gstreamer-run-in-separate-thread-tp1960435p2012409.html
Sent from the GStreamer-devel mailing list archive at Nabble.com.
Alexey Chernov
2010-04-16 19:13:07 UTC
Permalink
Yeah, Wes, I did the same except callbacks are global functions instead of
threads. And in my variant I found that callbacks run in main thread. Seems Qt
somewhere runs g_main_loop_run() inside of its event loop and all the message
dispatching goes to main thread.

Could you please detect which thread your callbacks run in? Maybe friend
functions is the solution...
Post by Wes Miller
I was just working on this :-)
I put my callback routines in friend functions of the class that I run in
the separate thread. I am not sure which thread they run in, guess I can
check that, but it works great. You do have to pass "this" as the data to
the callbacks so you can manipulate the class members.
Wes
wl2776
2010-04-19 11:42:54 UTC
Permalink
Post by Alexey Chernov
Could you please detect which thread your callbacks run in? Maybe friend
functions is the solution...
Bus watch, set with gst_bus_add_watch, is called from the Glib main loop.
Sync signal handler, set with gst_bus_set_sync_handler, is called from the
elements' thread contexts.
There is no difference, how functions are defined.
A callback function anyway won't be a C++ class member (except static class
members), because you have to pass its address to the registration routine,
and you can't determine the address of a C++ class member if its not static.

You can also be interested in the queue elements
(http://www.gstreamer.net/data/doc/gstreamer/head/manual/html/chapter-threads.html).
--
View this message in context: http://n4.nabble.com/how-to-make-gstreamer-run-in-separate-thread-tp1960435p2015774.html
Sent from the GStreamer-devel mailing list archive at Nabble.com.
Alexey Chernov
2010-04-19 20:15:40 UTC
Permalink
Thank you.

I've read some of those articles about Qt vs. Glib main loop, too. With the
main loop everything is ok. The question is how QThread and GLib's context and
threads are connected to each other and how different QThread's event loop
interacts with Glib stuff.

I said about all the message dispatching in GStreamer, but of course the main
problem is concerning my callback call by bus.

Also, thanks for info about gst_bus_set_sync_handler, I'll try it, too.
Post by wl2776
Post by Alexey Chernov
Could you please detect which thread your callbacks run in? Maybe friend
functions is the solution...
Bus watch, set with gst_bus_add_watch, is called from the Glib main loop.
Sync signal handler, set with gst_bus_set_sync_handler, is called from the
elements' thread contexts.
There is no difference, how functions are defined.
A callback function anyway won't be a C++ class member (except static class
members), because you have to pass its address to the registration routine,
and you can't determine the address of a C++ class member if its not static.
You can also be interested in the queue elements
(http://www.gstreamer.net/data/doc/gstreamer/head/manual/html/chapter-threa
ds.html).
vineeth
2010-05-11 16:08:56 UTC
Permalink
Hi ,
You do not need to create a separate thread while working on Qt.
AFAIK the gst helloworld
<http://www.gstreamer.net/data/doc/gstreamer/head/manual/html/chapter-helloworld.html>has
a g_main_loop so that the main thread does not exit while gstreamer runs in
its own thread.
But we don't have this problem while working with Qt GUI apps.
I have attached a simple gst-launch style Qt gui app using gstreamer to
demo this.
Hope it saves time of someone :)
Post by 4ernov
Hi,
I try to make whole gstreamer pipeline live in separate thread. I need
it generally because I work with very slow v4l2 device driver and it
takes considerable time for to change state of pipeline (init driver
etc.). So I create special QThread in Qt4 app and make all the
construction work (i.e. create all the elements, the pipeline itself
etc.) in its run() method. I also connect to the bus of the pipeline
GstBus* bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_bus_add_watch (bus, audio_bus_call, this);
gst_object_unref (bus);
But I eventually found that all the message dispatching is processed
in the main thread of the app. I.e. if I call thread() function which
void audio_bus_call()
{
qDebug()<<"thread:"<<thread();
}
it returns a pointer to the main thread in spite of that all the
GStreamer objects are created in different thread.
Is there any way to make message dispatching process run in different
thread other than main? Or somehow bind GStreamer event loop to Qt's
event loop of some QThread object?
Thank you very much,
Alexey Chernov
------------------------------------------------------------------------------
Download Intel&#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
_______________________________________________
gstreamer-devel mailing list
https://lists.sourceforge.net/lists/listinfo/gstreamer-devel
Loading...