[gstreamer-bugs] [Bug 570144] [ffdec] decodes unlinked streams

GStreamer (bugzilla.gnome.org) bugzilla-daemon at bugzilla.gnome.org
Thu Mar 5 01:22:37 PST 2009


If you have any questions why you received this email, please see the text at
the end of this email. Replies to this email are NOT read, please see the text
at the end of this email. You can add comments to this bug at:
  http://bugzilla.gnome.org/show_bug.cgi?id=570144

  GStreamer | gst-ffmpeg | Ver: git




------- Comment #2 from LRN  2009-03-05 09:23 UTC -------

Here's my code that suffers from unwanted decoding phenomena.
The fix is in GStreamerAutoplugSelectCallback() function - it prevents
autoplugger from constructing video factories. If you comment the check and let
it always return 0, video streams will be decoded (despite the fact that they
are not linked in OnNewStream handler).

What's wrong with it?

Also, what kind of logging would uncover whether or not the video data is
decoded? Debug log (which level?)? Or message bus log would be enough?

class MyApplicationClass : public foobar
{
public:
  MyApplicationClass(char *filename); 

  bool importinit();

  int import();

  void OnNewStream(GstElement *uridecodebin, GstPad *pad);
  int WriteData(GstBuffer *buffer);

  ...<cut> a bunch of functions

private:

   GstElement           *mPipeline;
   GstBus               *mBus;
   GstElement           *mDec;

   GstStaticCaps         mStaticCaps;

   char                 *mName;

   ...<cut> internal stuff
}

MyApplicationClass::MyApplicationClass(char *filename)
:  foobar(filename)
{
   mName = filename;

   mPipeline = mDec = NULL;

   memset(&mStaticCaps,0,sizeof(mStaticCaps));
   mStaticCaps.string = (               
     "audio/x-raw-int, "             
     "signed = (boolean) { TRUE }, "
     "width = (int) { 16, 32 }, "    
     "depth = (int) { 16, 24 }, "    
     "rate = (int) [ 1, MAX ], "     
     "channels = (int) [ 1, MAX ], " 
     "endianness = (int) BYTE_ORDER" 
     );
}

bool MyApplicationClass::importinit()
{
   GstPad *audiopad = NULL;

   // Create a pipeline
   mPipeline = gst_pipeline_new("pipeline");
   // Get it's bus an add a message watch to it
   mBus = gst_pipeline_get_bus(GST_PIPELINE(mPipeline));   

   // Set up source location
   gchar *name_utf8 = g_strdup(mName);
   gchar *name_with_proto_utf8 = g_strdup_printf("file:///%s",name_utf8);
   g_free(name_utf8);

   // Create uridecodebin and set up signal handlers
   mDec = gst_element_factory_make("uridecodebin", "decoder");
   g_signal_connect(mDec, "pad-added", G_CALLBACK(GStreamerNewStreamCallback),
(gpointer)this);
   g_signal_connect(mDec, "autoplug-select",
G_CALLBACK(GStreamerAutoplugSelectCallback), (gpointer)this);

   g_object_set(G_OBJECT(mDec), "uri", name_with_proto_utf8, NULL);

   // Add everythin into the pipeline
   gst_bin_add_many(GST_BIN(mPipeline), mDec, NULL);

   // Run the pipeline
   GstStateChangeReturn statechange = gst_element_set_state(mPipeline,
GST_STATE_PAUSED);

   while (true)
   {
      GstMessage *msg = gst_bus_pop(mBus);
      if (msg)
      {
        //OnBusMessage returns FALSE on GST_MESSAGE_ASYNC_DONE or
GST_MESSAGE_EOS and does message logging.
        if (!OnBusMessage(mBus,msg)) 
          break;
      }
   }

   return true; //After some more pondering application will call import()
method
}

gint GStreamerAutoplugSelectCallback(GstElement *element, GstPad *pad, GstCaps
*caps, GstElementFactory *factory, gpointer data)
{
   // Check factory class
   const gchar *fclass = gst_element_factory_get_klass(factory);
   // Skip video decoding
   if (g_strrstr(fclass,"Video"))
      return 2;
   return 0;
}

void GStreamerNewStreamCallback(GstElement *uridecodebin, GstPad *pad, gpointer
data)
{
   MyApplicationClass *handle = (MyApplicationClass*)data;
   handle->OnNewStream(uridecodebin, pad);
}

void MyApplicationClass::OnNewStream(GstElement *uridecodebin, GstPad *pad)
{
   GstCaps *caps;
   GstStructure *str;

   caps = gst_pad_get_caps(pad);
   str = gst_caps_get_structure(caps, 0);

   // Check stream type
   const gchar *name = gst_structure_get_name(str);
   gboolean quit = FALSE;
   if (!g_strrstr(name, "audio"))
   {
      g_string_free(strinfo, TRUE);
      quit = TRUE;
   }
   gst_caps_unref (caps);
   if (quit)
     return;

   // Create unique name
   gchar *mAConvName = g_strdup_printf("aconv-%d",mScs->len);
   // Create an audioconv   
   GstElement *mConv = gst_element_factory_make("audioconvert", mAConvName);
   // Get it's sink pad
   GstPad *convpad = gst_element_get_static_pad(mConv, "sink");
   // Add it to the pipeline
   gst_bin_add(GST_BIN(mPipeline), mConv);

   GstPadLinkReturn ret = gst_pad_link(pad, convpad);
   gst_object_unref(convpad);
   if (ret)
   {
      g_print("Failed to link uridecodebin to audioconvert - %d\n",ret);
      g_free(mAConvName);
      gst_bin_remove(GST_BIN(mPipeline), mConv);
      gst_object_unref(mConv);
      g_string_free(strinfo, TRUE);
      return;
   }

   gchar *mASinkName = g_strdup_printf("asink-%d",mScs->len);
   GstElement *mSink = gst_element_factory_make("appsink", mASinkName);
   // Set up sink properties
   caps = gst_static_caps_get(&mStaticCaps);
   gst_app_sink_set_caps(GST_APP_SINK(mSink), caps);
   gst_caps_unref(caps);
   gst_base_sink_set_sync(GST_BASE_SINK(mSink), FALSE);
   gst_app_sink_set_drop(GST_APP_SINK(mSink), FALSE);
   gst_app_sink_set_emit_signals(GST_APP_SINK(mSink), FALSE);
   gst_app_sink_set_max_buffers(GST_APP_SINK(mSink), 10);

   gst_bin_add(GST_BIN(mPipeline), mSink);

   if (!gst_element_link(mConv, mSink))
   {
      g_free(mAConvName);
      gst_bin_remove(GST_BIN(mPipeline), mConv);
      gst_object_unref(mConv);
      g_free(mASinkName);
      gst_bin_remove(GST_BIN(mPipeline), mSink);
      gst_object_unref(mSink);
      g_string_free(strinfo, TRUE);
   }

   // Run newly added elements
   GstStateChangeReturn statechange;
   statechange = gst_element_set_state(mConv, GST_STATE_PAUSED);
   statechange = gst_element_set_state(mSink, GST_STATE_PAUSED);

   // Next it stores mSink internally, nothing interesting.
   ...
}

int MyApplicationClass::import()
{
  GstStateChangeReturn statechange = gst_element_set_state(mPipeline,
GST_STATE_PLAYING);

  gboolean doit = TRUE;
  while (doit)
  {
    doit = FALSE;
    GstMessage *msg = gst_bus_pop(mBus);
    while (msg != NULL)
    {
      OnBusMessage(mBus,msg);
      msg = gst_bus_pop(mBus);
    }
    ...<cut> for each stream found in source and for which we've made sink and
audioconv (see OnNewStream) do
    {
      ...<cut> get mSink for that stream from internal storage
      GstBuffer *incbuf = gst_app_sink_pull_buffer(GST_APP_SINK(mSink));
      if (incbuf)
      {
        doIt = TRUE;
        res = WriteData(incbuf);
        gst_buffer_unref(incbuf);
      }
    }
  }
}


-- 
See http://bugzilla.gnome.org/page.cgi?id=email.html for more info about why you received
this email, why you can't respond via email, how to stop receiving
emails (or reduce the number you receive), and how to contact someone
if you are having problems with the system.

You can add comments to this bug at http://bugzilla.gnome.org/show_bug.cgi?id=570144.




More information about the Gstreamer-bugs mailing list