[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