Huge memory leak sometime after starting a pipeline

Sergei Vorobyov sergei.vorobyov at facilitylabs.com
Fri Nov 7 08:26:53 PST 2014


> Regarding my comment to simplify your pipeline... try to reproduce the
> leak without rendering video to the screen and just a fakesink. And try
> to reproduce the leak with a much simpler source but displaying on the
> screen. Dividing a problem into subproblems does not only help with
> quicksort ;)

1. > try to reproduce the leak without rendering video to the screen and
just a fakesink...

Do you understand that if you render nothing (fakesink) then evidently the
driver does not work and hence does not leak? I checked it nevertheless for
your pleasure (if I misunderstand something) to confirm the obvious: no
leaks with fakesink.

2.  > try to reproduce with a much simpler source

Can't be any simpler: cyclically playing static .jpg and/or .png files
leaks on Intel with vaapisink or autovideosink (but not on NVidia and
Radeon), even repeatedly playing one and the same small randomly chosen
file.

3. > simplify your pipeline...

Can't be any simpler: filesrc location=...! decodebin ! imagefreeze !
videodecode ! vaapisink (implemented in C; see below),  just dynamically
changing the location of a .jpg or .png file.

4. > Dividing...

I even know and use more sophisticated things than divide-and-conquer. But
I think with Intel all of it is pointless. They would never answer or
react. The best thing I figured is to dump Intel's HW altogether. Strange
that none of you (mostly working on Intel's) noticed massive memory leak
problems. Do you ever make endurance testing for a few hours or days?

Here's a simple program in question. Try it like this

test vaapisink

(or test <whateversink> for comparison)

on Intel's (I tried Bay Trail and HD4400 IGPs) and watch with top or htop,
for 10-30 minutes or a few hours.

test without arguments defaults to autovideosink

test ximagesink does not leak on Intel.

test <whateversink> does not leak on NVidia nor AMD Radeon

/*
 * Adjust the MEDIA_DIR constant as explained below
 * Compile with:
 * gcc -std=c11 -Wall -pthread test.c -o test `pkg-config --cflags --libs
glib-2.0 gstreamer-1.0 gstreamer-pbutils-1.0 gstreamer-video-1.0`
 * Run, giving a sink factory name as an argument, like "test vaapisink"
and enjoy
 */
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
#include <gst/gst.h>
/*
 * This program implements cyclically playing all image files in MEDIA_DIR
 * through the pipeline
 * filesrc location=... ! decodebin ! imagefreeze ! videoconvert | <sink>
 * by setting the location property to different files in MEDIA_DIR
 */
// Modify as needed. Directory should contain only image files: .jpg, .png,
..., one or more.
#define MEDIA_DIR "/home/fl/ads"

static GstBus *bus;
static GstMessage *message;
static GstElement *pipeline, *filesrc, *decodebin, *videoconvert,
*imagefreeze, *sink;
static gchar const *videosink;

static void dynamic_pad_link_cb (GstElement *decbin, GstPad *srcpad,
gpointer imgfreeze)  {
    gchar *pad_name = gst_pad_get_name (srcpad);
    g_print ("dynamically linking %s on pad %s to %s ...\n",
            GST_OBJECT_NAME (decbin), pad_name, GST_OBJECT_NAME
(imgfreeze));
    g_free (pad_name);
    GstCaps *caps = gst_pad_query_caps (srcpad, NULL);
    GstPad *sinkpad = gst_element_get_compatible_pad ((GstElement*)
imgfreeze, srcpad, caps);
    GstPadLinkReturn pad_link_outcome =  gst_pad_link (srcpad, sinkpad);
    if (pad_link_outcome == GST_PAD_LINK_OK)
g_print ("dynamic link succeeded!\n");
    else {
g_print ("dynamic link failed with code %d\n", pad_link_outcome);
        exit (-1);
    }
    gst_object_unref (sinkpad);
    gst_caps_unref (caps);
}

static void build_pipeline () {
    pipeline = gst_pipeline_new ("main_pipeline");
    filesrc = gst_element_factory_make ("filesrc", "filesrc");
    decodebin = gst_element_factory_make ("decodebin", "decodebin");
    videoconvert = gst_element_factory_make ("videoconvert",
"videoconvert");
    imagefreeze = gst_element_factory_make ("imagefreeze", "imagefreeze");
    sink = gst_element_factory_make (videosink, videosink);
    if (!sink) {
        g_print ("failed to create %s\n", videosink);
        exit (-1);
    }
    gst_bin_add_many (GST_BIN (pipeline), filesrc, decodebin, imagefreeze,
videoconvert, sink, NULL);
    gst_element_link (filesrc, decodebin);
    g_signal_connect (decodebin, // instance to connect signal to
      "pad-added", // detailed signal
      G_CALLBACK (dynamic_pad_link_cb), // assoc callback
      imagefreeze); // passed as the 3rd arg to the callback
    gst_element_link (imagefreeze, videoconvert);
    gst_element_link (videoconvert, sink);
    bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
}

static void play_media_file (gchar const *fname) {
    gchar *full_file_name = g_strdup_printf (MEDIA_DIR G_DIR_SEPARATOR_S
"%s", fname);
    g_object_set (filesrc, "location", full_file_name, NULL);
    g_print ("playing %s\n", full_file_name);
    if (gst_element_set_state (pipeline, GST_STATE_PLAYING) ==
GST_STATE_CHANGE_FAILURE) {
        g_print ("failed to set pipeline to PLAYING\n");
        exit (-1);
    }
    message = gst_bus_timed_pop_filtered (bus, 5 * GST_SECOND,
                                      (GstMessageType)(GST_MESSAGE_EOS |

 GST_MESSAGE_SEGMENT_DONE |
                                                       GST_MESSAGE_ERROR));
    if (message == NULL)
        g_print ("play time fully expired!\n");
    else {
        GstMessageType msg_type = GST_MESSAGE_TYPE (message);
        gchar const *name = gst_message_type_get_name (msg_type); // a
reference to the static name of the message, don't free
        g_print ("received message type=%d, name=%s\n", msg_type, name);
        if (msg_type & GST_MESSAGE_EOS)
            g_print ("GST_MESSAGE_EOS\n");
        else if (msg_type & GST_MESSAGE_ERROR)
            g_print ("GST_MESSAGE_ERROR, bad %s\n", full_file_name);
        else
            g_print ("UNEXPECTED message type %s\n", name);
        gst_message_unref (message); // only when != NULL !!!
        message = NULL;
    }
    if (gst_element_set_state (pipeline, GST_STATE_READY) ==
GST_STATE_CHANGE_FAILURE) {
        g_print ("failed to set pipeline to state READY\n");
        exit (-1);
    }
    g_free (full_file_name);
    gst_element_unlink (decodebin, imagefreeze); // dynamically linked each
time, independently of this unlink
}

gint main (gint argc, gchar** argv) {
    gst_init (&argc, &argv);
    guint major, minor, micro, nano;
    gst_version (&major, &minor, &micro, &nano);
    g_print ("GStreamer v%d.%d.%d.%d\n", major, minor, micro, nano);
    videosink = (argc > 1)? argv[1] : "autovideosink";
    g_print ("using %s\n", videosink);
    build_pipeline ();
    for (gint i=1; ; i++) {
        g_print ("*** Cycle #%d through all media files in %s\n", i,
MEDIA_DIR);
        GDir *dir = g_dir_open (MEDIA_DIR, 0, NULL);
        gchar const *file_name;
        while ((file_name = g_dir_read_name(dir))) // file_name must not be
modified or freed
            play_media_file (file_name);
        g_dir_close(dir);
    }
}



On Thu, Nov 6, 2014 at 11:47 AM, Sebastian Dröge <sebastian at centricular.com>
wrote:

> On Do, 2014-11-06 at 11:33 +0100, Sergei Vorobyov wrote:
> > Sorry to say but the universal (on this list) recipe to use valgrind is
> > useless, like a hammer to drive screws.
> >
> > Point is, to see "leaks", you need to stop your application, in which
> case
> > GStreamer produces thousands (miles) of messages of the kind:
> > [...]
> >
> > even though you make a clean exit with _unrefs of all kinds and
> gst_deinit
> > (), and the application does not leak at all (if you don't stop it and
> run
> > indefinitely).
> >
> > Sure (by the end of the day) you can suppress any kind of messages you
> want
> > to ignore, but this hardly approaches you to the solution of the problem.
> > Should you take the above message seriously or ignore? Can you ask
> > GStreamer developers "take seriously or ignore?" about each of 100.000
> such
> > messages?
>
> The big leaks will be at the top, the small ones at the bottom. If
> there's nothing big at the top you have a problem and valgrind's
> memcheck tool won't be useful for you. And as I said last time already,
> valgrind is not solving all problems but it's a good start... and if it
> doesn't help (it does help in like 90% of the cases!) it still gives you
> hints at where *not* to waste your time looking. Debugging memory leaks
> is not trivial, use any help that you can get.
>
> Also try to simplify your pipeline to get a minimal testcase that
> reproduces the problem. And also see my mention of massif, which will be
> useful while the application is running.
>
> > I observed (without valgrind) a curious thing: the same application leaks
> > as hell on Intel's HD4400 IGP (NUC) with Intel's driver, but does not
> leak
> > at all on AMD Radeon, nor on NVidia. As I said, in all three cases
> valgrind
> > uselessly reports miles of possibly and definitely lost blocks, which
> makes
> > all three different cases completely indistinguishable.
> >
> > Check if you are using Intel's graphics HW. Maybe this is the reason.
> > Despite the developers claim that GStreamer runs equally good on any
> > hardware.
>
> Sure there might be a driver bug in the Intel driver. Like there can
> also be driver bugs in the others. Apart from those things GStreamer
> does not care at all what hardware you use, and in general most of us
> are using Intel hardware.
>
> Regarding my comment to simplify your pipeline... try to reproduce the
> leak without rendering video to the screen and just a fakesink. And try
> to reproduce the leak with a much simpler source but displaying on the
> screen. Dividing a problem into subproblems does not only help with
> quicksort ;)
>
> --
> Sebastian Dröge, Centricular Ltd · http://www.centricular.com
>
> _______________________________________________
> gstreamer-devel mailing list
> gstreamer-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/gstreamer-devel/attachments/20141107/189ce5e7/attachment.html>


More information about the gstreamer-devel mailing list