Properly freeing resources

Jim restlessmindsstudio at gmail.com
Fri Feb 22 12:43:53 PST 2013


Hi Tim,
Thanks for your reply, please see my responses below, which are prefixed
with "Jim:"

I have also tried a much simpler pipeline that just uses playbin2. The
initialization and cleanup is the same except that I'm not registering a
callback for the pad-added signal. I still see the same results where memory
usage is slowly growing over time. I'm really hoping it's just related to me
not handling GStreamer correctly.

Jim

-----Original Message-----
From:
gstreamer-devel-bounces+restlessmindsstudio=gmail.com at lists.freedesktop.org
[mailto:gstreamer-devel-bounces+restlessmindsstudio=gmail.com at lists.freedesk
top.org] On Behalf Of Tim-Philipp Müller
Sent: Friday, February 22, 2013 12:41 PM
To: gstreamer-devel at lists.freedesktop.org
Subject: Re: Properly freeing resources

On Wed, 2013-02-20 at 07:41 -0700, Jim wrote:

Hi,

your code looks mostly ok.

>   streamData->videoDecoder = gst_element_factory_make("vpudec",
> "videoDecoder");
>   streamData->videoSink = gst_element_factory_make("mfw_v4lsink",
> "videoSink");
>   streamData->audioDecoder =
> gst_element_factory_make("mfw_mp3decoder", "audioDecoder");

I would check these elements first, if they free all resources correctly
when being shut down and/or being shut down during playback.

Jim: How do I verify that these elements are freeing their resources? I
thought by setting the pipeline state to GST_STATE_NULL, it is supposed to
free all of its resources. Are there situations where this may not be the
case?

>   g_object_set(G_OBJECT(streamData->videoQueue), "max-size-time", 0,
NULL);
>   g_object_set(G_OBJECT(streamData->audioQueue), "max-size-time", 0, 
> NULL);

You want (guint64)0 here.

Jim: Thanks, good to know

>   g_signal_connect(streamData->demux, "pad-added", 
> G_CALLBACK(pad_added_handler), streamData);

What do you do in the pad_added_handler? Are you sure you are not leaking
any references there?

Jim: Here is the code for the pad_added_handler:

  GstPad *sink_pad;
  GstPadLinkReturn ret;
  GstCaps *new_pad_caps = NULL;
  GstStructure *new_pad_struct = NULL;
  const gchar *new_pad_type = NULL;

  new_pad_caps = gst_pad_get_caps(new_pad);
  new_pad_struct = gst_caps_get_structure(new_pad_caps, 0);
  new_pad_type = gst_structure_get_name(new_pad_struct);

  g_print("Received new pad '%s' from '%s', pad type: '%s'\n",
GST_PAD_NAME(new_pad), GST_ELEMENT_NAME(src), new_pad_type);

  if (g_str_has_prefix(new_pad_type, "audio"))
  {
    sink_pad = gst_element_get_static_pad(data->audioQueue, "sink");

    // If the queue is already linked, we have nothing to do
    if (gst_pad_is_linked(sink_pad))
    {
      g_print ("We are already linked to the audio queue. Ignoring.\n");
    }
    else
    {
      // Attempt the link
      ret = gst_pad_link(new_pad, sink_pad);
      if (GST_PAD_LINK_FAILED (ret))
      {
        g_print ("Type is '%s' but link failed.\n", new_pad_type);
      }
      else
      {
        g_print ("Link succeeded (type '%s').\n", new_pad_type);
      }
    }
  }

  if (g_str_has_prefix(new_pad_type, "video"))
  {
    sink_pad = gst_element_get_static_pad(data->videoQueue, "sink");

    // If the queue is already linked, we have nothing to do
    if (gst_pad_is_linked(sink_pad))
    {
      g_print ("We are already linked to the video queue. Ignoring.\n");
    }
    else
    {
      // Attempt to link
      ret = gst_pad_link(new_pad, sink_pad);
      if (GST_PAD_LINK_FAILED(ret))
      {
        g_print ("Type is '%s' but link failed.\n", new_pad_type);
      }
      else
      {
        g_print ("Link succeeded (type '%s').\n", new_pad_type);
      }
    }
  }

  // Unreference the new pad's caps, if we got them
  if (new_pad_caps)
    gst_caps_unref(new_pad_caps);

  // Unreference the sink pad
  if (sink_pad)
    gst_object_unref(sink_pad);


>   // Retrieve pipeline signal bus
>   streamData->bus =
> gst_pipeline_get_bus(GST_PIPELINE(streamData->pipeline));
>   streamData->busWatchId = gst_bus_add_watch(streamData->bus,
> (GstBusFunc)handle_message, streamData);

FWIW, you don't have to keep a ref to the bus around if you don't need it,
you can just unref it right here and there after adding the watch if you
want to.

Jim: I went ahead and unreferenced the bus after assigning the bus watch
callback. Bernhard on the mailing list suggested that as well.

> Before switching to a another video, the following cleanup is done:
> 
>   gst_object_unref(streamData->bus);
>   gst_element_set_state(streamData->pipeline, GST_STATE_NULL);
>   gst_object_unref(streamData->pipeline);

You will also need to

  to g_source_remove (streamData->busWatchId)

Jim: Thanks, will do!

Cheers
 -Tim


_______________________________________________
gstreamer-devel mailing list
gstreamer-devel at lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel



More information about the gstreamer-devel mailing list