[gst-devel] running g_main_loop_run in separate thread question.
wanting2learn
wanting2learn at hotmail.co.uk
Wed Mar 24 15:29:35 CET 2010
I have the following code:
GstBus *g_bus; //GStreamer bus to watch for stream errors
GMainLoop *g_Loop;
static gboolean
bus_call (GstBus *bus,
GstMessage *msg,
gpointer data)
{
GMainLoop *loop = (GMainLoop *) data;
switch (GST_MESSAGE_TYPE (msg))
{
case GST_MESSAGE_ERROR: {
g_print ("ERROR\n");
break;
}
default:
g_print ("default\n");
break;
}
return TRUE;
}
static void on_rtsppad_added(GstElement *element,
GstPad *pad,
gpointer data)
{
GstElement *linkElement = (GstElement *) data;
GstPad *sinkpad = gst_element_get_static_pad (linkElement, "sink");
gst_pad_link (pad, sinkpad);
gst_object_unref(GST_OBJECT (sinkpad));
}
static void on_pad_added(GstElement *element,
GstPad *pad,
gboolean last,
gpointer data)
{
GstElement *linkElement = (GstElement *) data;
GstPad *sinkpad = gst_element_get_static_pad (linkElement, "sink");
gst_pad_link (pad, sinkpad);
gst_object_unref(GST_OBJECT (sinkpad));
}
void task_gstreamer()//This is a new boost thread - see bottom of
MyPipeLineClass constructor
{
g_main_loop_run (g_Loop);
}
class MyPipeLineClass
{
public:
MyPipeLineClass( );
~MyPipeLineClass();
bool startPlaying();
void stopPlaying();
private:
GstPipeline *m_pPipeline;
GstElement *m_pHtmlElem;
};
MyPipeLineClass::MyPipeLineClass( ) :
{
g_Loop = g_main_loop_new (NULL, FALSE);
// Create pipeline
m_pPipeline = GST_PIPELINE(gst_pipeline_new("livemjpg-player"));
if (!m_pPipeline ) {
vecgi::LOGMSG( vecgi::VELOG_ERROR, "Failure to create pipeline fo
livemjpg." );
return;
}
//Get the pipeline bus so we can watch it
g_bus = gst_pipeline_get_bus (GST_PIPELINE(m_pPipeline));
gst_object_unref (g_bus);
// Create source elements
GstElement *source = gst_element_factory_make("rtspsrc", "source");
if (!source) {
vecgi::LOGMSG( vecgi::VELOG_ERROR, "Failure to create rtspsrc element
for MotionJpeg bin." );
return;
}
// Set the source video file */
char zervIP[32];
GetPrivateProfileString("bootaddr","ip_addr","", zervIP, sizeof(zervIP),
"apache");
std::string rtspUrl = boost::str(
boost::format("rtsp://%1%@%2%/media/%3%/video/%4%/#npt-now")
% auth.c_str()
% zervIP
% (camIndex+1)
% 1);
//Sometimes the rtspsrc element blocks for up to 20secs when its state is
changed
//so change its default tcp-timeout to 5secs
g_object_set(source, "location", rtspUrl.c_str(), "tcp-timeout", TIMEOUT,
NULL );
// Create decode element
GstElement *decode = gst_element_factory_make("decodebin2", "decode");
if (!decode) {
vecgi::LOGMSG( vecgi::VELOG_ERROR, "Failure to create decode element for
MotionJpeg bin." );
return;
}
// Create jpeg encoder element
GstElement *encoder = gst_element_factory_make("jpegenc", "jpegenc");
if (!encoder) {
vecgi::LOGMSG( vecgi::VELOG_ERROR, "Failure to create jpegenc element
for MotionJpeg bin." );
return;
}
// Create sink format element
GstElement *sink = gst_element_factory_make("fdsink", "sink");
if (!sink) {
vecgi::LOGMSG( vecgi::VELOG_ERROR, "Failure to create sink element for
MotionJpeg bin." );
return;
}
// Add elements to the pipeline
gst_bin_add_many( GST_BIN(m_pPipeline),
source, decode, encoder, sink, NULL);
// Link all elements except source and decoder
// The rtspsrc and decoder will automatically determine the appropriate
pad
// at run time and then they will link accordingly
if (!gst_element_link_many(encoder, sink, NULL))
{
vecgi::LOGMSG( vecgi::VELOG_ERROR, "Failed to link elements in
MotionJpeg pipeline." );
}
g_signal_connect(source, "pad-added", G_CALLBACK(on_rtsppad_added),
decode );
g_signal_connect(decode, "new-decoded-pad", G_CALLBACK (on_pad_added),
encoder );
boost::thread thread_gstreamer2(task_gstreamer); <------New thread
}
MyPipeLineClass::~MyPipeLineClass()
{
stopPlaying();
}
bool MyPipeLineClass::startPlaying()
{
gst_element_set_state( GST_ELEMENT(m_pPipeline),GST_STATE_PLAYING ) ;
return true;
}
void MyPipeLineClass::stopPlaying()
{
gst_element_set_state( GST_ELEMENT(m_pPipeline),GST_STATE_NULL )
gst_object_unref( m_pPipeline );
}
static MyPipeLineClass *g_pMyPipelineClass = NULL; <--global pipeline
variable
int start_pipeline()
{
g_pMyPipelineClass = new MyPipeLineClass( );
g_pMyPipelineClass->startPlaying())
return 1;
}
int main()
{
start_pipeline();
while(1)
{
//do stuff here
}
//blah blah
}
Now my pipeline runs fine but I have kicked off a new thread to handle the
bus messages:
boost::thread thread_gstreamer2(task_gstreamer);
void task_gstreamer()
{
g_main_loop_run (g_Loop);
}
The reason I have added this in a new thread is because of the while(1) loop
in my main() function. If I put the g_main_loop_run in my main() before my
while(1) loop then it would block.
But the problem is that I do not receive any bus messages at all when I
implement it like this.
Can I do it this way??
--
View this message in context: http://n4.nabble.com/running-g-main-loop-run-in-separate-thread-question-tp1680629p1680629.html
Sent from the GStreamer-devel mailing list archive at Nabble.com.
More information about the gstreamer-devel
mailing list