<div dir="ltr"><div>RE: memory leak in vaapisink</div><div><br></div>I think, this leak is somewhere in vaapisink.<div><br></div><div>Indeed, when I installed video acceleration packages for AMD Radeon (with the latest fglrx proprietary driver):</div><div><br></div><div>apt-get install vainfo xvba-va-driver libvba-glx1 libva-egl1</div><div><br></div><div>the same program I posted yesterday started to leak memory with vaapisink and autovideosink (which I guess falls back to vaapisink) on AMD Radeon the same way as previously on Intel's HD IGP with video acceleration.</div><div><br></div><div>It's highly unlikely that two independent companies produce similarly leaking drivers. Plausible conclusion: vaapisink is to be blamed.</div><div><br></div><div>(note that my program with ximagesink DOES NOT leak memory)</div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Nov 7, 2014 at 5:26 PM, Sergei Vorobyov <span dir="ltr"><<a href="mailto:sergei.vorobyov@facilitylabs.com" target="_blank">sergei.vorobyov@facilitylabs.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><span class=""><div><span style="font-family:arial,sans-serif;font-size:13px">> Regarding my comment to simplify your pipeline... try to reproduce the</span><br style="font-family:arial,sans-serif;font-size:13px"><span style="font-family:arial,sans-serif;font-size:13px">> leak without rendering video to the screen and just a fakesink. And try</span><br style="font-family:arial,sans-serif;font-size:13px"><span style="font-family:arial,sans-serif;font-size:13px">> to reproduce the leak with a much simpler source but displaying on the</span><br style="font-family:arial,sans-serif;font-size:13px"><span style="font-family:arial,sans-serif;font-size:13px">> screen. Dividing a problem into subproblems does not only help with</span><br style="font-family:arial,sans-serif;font-size:13px"><span style="font-family:arial,sans-serif;font-size:13px">> quicksort ;)</span><br></div><div><br></div></span><div>1. > try to reproduce the leak <span style="font-family:arial,sans-serif;font-size:13px">without rendering video to the screen and just a fakesink...</span></div><div><span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><div><span style="font-family:arial,sans-serif;font-size:13px">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.</span></div><div><span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><div><span style="font-family:arial,sans-serif;font-size:13px">2.  > try to reproduce with a much simpler source</span></div><div><span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><div><span style="font-family:arial,sans-serif;font-size:13px">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.</span></div><div><span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><div><span style="font-family:arial,sans-serif;font-size:13px">3. > </span><span style="font-family:arial,sans-serif;font-size:13px">simplify your pipeline...</span></div><div><span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><div><span style="font-family:arial,sans-serif;font-size:13px">Can't be any simpler: filesrc location=...! decodebin ! imagefreeze ! videodecode ! vaapisink (implemented in C; see below),  </span><span style="font-family:arial,sans-serif;font-size:13px">just dynamically changing the location of a .jpg or .png file.</span></div><div><br></div><div>4. > Dividing...</div><div><br></div>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?<div><br></div><div>Here's a simple program in question. Try it like this</div><div><br></div><div>test vaapisink</div><div><br></div><div>(or test <whateversink> for comparison)</div><div><br></div><div>on Intel's (I tried Bay Trail and HD4400 IGPs) and watch with top or htop, for 10-30 minutes or a few hours.</div><div><br></div><div>test without arguments defaults to autovideosink</div><div><br></div><div><div>test ximagesink does not leak on Intel.</div></div><div><br></div><div>test <whateversink> does not leak on NVidia nor AMD Radeon</div><div><br></div><div><div>/*</div><div> * Adjust the MEDIA_DIR constant as explained below</div><div> * Compile with:</div><div> * 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`</div><div> * Run, giving a sink factory name as an argument, like "test vaapisink" and enjoy</div><div> */</div><div>#include <stdio.h></div><div>#include <stdlib.h></div><div>#include <glib.h></div><div>#include <gst/gst.h></div><div>/*</div><div> * This program implements cyclically playing all image files in MEDIA_DIR</div><div> * through the pipeline</div><div> * filesrc location=... ! decodebin ! imagefreeze ! videoconvert | <sink></div><div> * by setting the location property to different files in MEDIA_DIR</div><div> */</div><div>// Modify as needed. Directory should contain only image files: .jpg, .png, ..., one or more.</div><div>#define MEDIA_DIR "/home/fl/ads"</div><div><br></div><div>static GstBus *bus;</div><div>static GstMessage *message;</div><div>static GstElement *pipeline, *filesrc, *decodebin, *videoconvert, *imagefreeze, *sink;</div><div>static gchar const *videosink;</div><div><br></div><div>static void dynamic_pad_link_cb (GstElement *decbin, GstPad *srcpad, gpointer imgfreeze)  {</div><div>    gchar *pad_name = gst_pad_get_name (srcpad);</div><div>    g_print ("dynamically linking %s on pad %s to %s ...\n", </div><div>            GST_OBJECT_NAME (decbin), pad_name, GST_OBJECT_NAME (imgfreeze));</div><div>    g_free (pad_name);</div><div>    GstCaps *caps = gst_pad_query_caps (srcpad, NULL);</div><div>    GstPad *sinkpad = gst_element_get_compatible_pad ((GstElement*) imgfreeze, srcpad, caps);</div><div>    GstPadLinkReturn pad_link_outcome =  gst_pad_link (srcpad, sinkpad);</div><div>    if (pad_link_outcome == GST_PAD_LINK_OK)</div><div><span style="white-space:pre-wrap">      </span>g_print ("dynamic link succeeded!\n");</div><div>    else {</div><div><span style="white-space:pre-wrap">      </span>g_print ("dynamic link failed with code %d\n", pad_link_outcome);</div><div>        exit (-1);</div><div>    }</div><div>    gst_object_unref (sinkpad);</div><div>    gst_caps_unref (caps);</div><div>}</div><div><br></div><div>static void build_pipeline () {</div><div>    pipeline = gst_pipeline_new ("main_pipeline");</div><div>    filesrc = gst_element_factory_make ("filesrc", "filesrc");</div><div>    decodebin = gst_element_factory_make ("decodebin", "decodebin");</div><div>    videoconvert = gst_element_factory_make ("videoconvert", "videoconvert");</div><div>    imagefreeze = gst_element_factory_make ("imagefreeze", "imagefreeze");</div><div>    sink = gst_element_factory_make (videosink, videosink);</div><div>    if (!sink) {</div><div>        g_print ("failed to create %s\n", videosink);</div><div>        exit (-1);</div><div>    }</div><div>    gst_bin_add_many (GST_BIN (pipeline), filesrc, decodebin, imagefreeze, videoconvert, sink, NULL);</div><div>    gst_element_link (filesrc, decodebin);</div><div>    g_signal_connect (decodebin, // instance to connect signal to</div><div><span style="white-space:pre-wrap">          </span>      "pad-added", // detailed signal</div><div><span style="white-space:pre-wrap">               </span>      G_CALLBACK (dynamic_pad_link_cb), // assoc callback</div><div><span style="white-space:pre-wrap">             </span>      imagefreeze); // passed as the 3rd arg to the callback</div><div>    gst_element_link (imagefreeze, videoconvert);</div><div>    gst_element_link (videoconvert, sink);</div><div>    bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));</div><div>}</div><div><br></div><div>static void play_media_file (gchar const *fname) {</div><div>    gchar *full_file_name = g_strdup_printf (MEDIA_DIR G_DIR_SEPARATOR_S "%s", fname);</div><div>    g_object_set (filesrc, "location", full_file_name, NULL);</div><div>    g_print ("playing %s\n", full_file_name);</div><div>    if (gst_element_set_state (pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {</div><div>        g_print ("failed to set pipeline to PLAYING\n");</div><div>        exit (-1);</div><div>    }</div><div>    message = gst_bus_timed_pop_filtered (bus, 5 * GST_SECOND,</div><div>                                      (GstMessageType)(GST_MESSAGE_EOS |</div><div>                                                       GST_MESSAGE_SEGMENT_DONE |</div><div>                                                       GST_MESSAGE_ERROR));</div><div>    if (message == NULL)</div><div>        g_print ("play time fully expired!\n");</div><div>    else {</div><div>        GstMessageType msg_type = GST_MESSAGE_TYPE (message);</div><div>        gchar const *name = gst_message_type_get_name (msg_type); // a reference to the static name of the message, don't free</div><div>        g_print ("received message type=%d, name=%s\n", msg_type, name);</div><div>        if (msg_type & GST_MESSAGE_EOS)</div><div>            g_print ("GST_MESSAGE_EOS\n");</div><div>        else if (msg_type & GST_MESSAGE_ERROR)</div><div>            g_print ("GST_MESSAGE_ERROR, bad %s\n", full_file_name);</div><div>        else</div><div>            g_print ("UNEXPECTED message type %s\n", name);</div><div>        gst_message_unref (message); // only when != NULL !!!</div><div>        message = NULL;</div><div>    }</div><div>    if (gst_element_set_state (pipeline, GST_STATE_READY) == GST_STATE_CHANGE_FAILURE) {</div><div>        g_print ("failed to set pipeline to state READY\n");</div><div>        exit (-1);</div><div>    }</div><div>    g_free (full_file_name);</div><div>    gst_element_unlink (decodebin, imagefreeze); // dynamically linked each time, independently of this unlink</div><div>}</div><div><br></div><div>gint main (gint argc, gchar** argv) {</div><div>    gst_init (&argc, &argv);</div><div>    guint major, minor, micro, nano;</div><div>    gst_version (&major, &minor, &micro, &nano);</div><div>    g_print ("GStreamer v%d.%d.%d.%d\n", major, minor, micro, nano);</div><div>    videosink = (argc > 1)? argv[1] : "autovideosink";</div><div>    g_print ("using %s\n", videosink);</div><div>    build_pipeline ();</div><div>    for (gint i=1; ; i++) {</div><div>        g_print ("*** Cycle #%d through all media files in %s\n", i, MEDIA_DIR);</div><div>        GDir *dir = g_dir_open (MEDIA_DIR, 0, NULL);</div><div>        gchar const *file_name;</div><div>        while ((file_name = g_dir_read_name(dir))) // file_name must not be modified or freed</div><div>            play_media_file (file_name);</div><div>        g_dir_close(dir);</div><div>    }</div><div>}</div></div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="h5">On Thu, Nov 6, 2014 at 11:47 AM, Sebastian Dröge <span dir="ltr"><<a href="mailto:sebastian@centricular.com" target="_blank">sebastian@centricular.com</a>></span> wrote:<br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5"><span>On Do, 2014-11-06 at 11:33 +0100, Sergei Vorobyov wrote:<br>
> Sorry to say but the universal (on this list) recipe to use valgrind is<br>
> useless, like a hammer to drive screws.<br>
><br>
> Point is, to see "leaks", you need to stop your application, in which case<br>
> GStreamer produces thousands (miles) of messages of the kind:<br>
</span>> [...]<br>
<span>><br>
> even though you make a clean exit with _unrefs of all kinds and gst_deinit<br>
> (), and the application does not leak at all (if you don't stop it and run<br>
> indefinitely).<br>
><br>
> Sure (by the end of the day) you can suppress any kind of messages you want<br>
> to ignore, but this hardly approaches you to the solution of the problem.<br>
> Should you take the above message seriously or ignore? Can you ask<br>
> GStreamer developers "take seriously or ignore?" about each of 100.000 such<br>
> messages?<br>
<br>
</span>The big leaks will be at the top, the small ones at the bottom. If<br>
there's nothing big at the top you have a problem and valgrind's<br>
memcheck tool won't be useful for you. And as I said last time already,<br>
valgrind is not solving all problems but it's a good start... and if it<br>
doesn't help (it does help in like 90% of the cases!) it still gives you<br>
hints at where *not* to waste your time looking. Debugging memory leaks<br>
is not trivial, use any help that you can get.<br>
<br>
Also try to simplify your pipeline to get a minimal testcase that<br>
reproduces the problem. And also see my mention of massif, which will be<br>
useful while the application is running.<br>
<span><br>
> I observed (without valgrind) a curious thing: the same application leaks<br>
> as hell on Intel's HD4400 IGP (NUC) with Intel's driver, but does not leak<br>
> at all on AMD Radeon, nor on NVidia. As I said, in all three cases valgrind<br>
> uselessly reports miles of possibly and definitely lost blocks, which makes<br>
> all three different cases completely indistinguishable.<br>
><br>
> Check if you are using Intel's graphics HW. Maybe this is the reason.<br>
> Despite the developers claim that GStreamer runs equally good on any<br>
> hardware.<br>
<br>
</span>Sure there might be a driver bug in the Intel driver. Like there can<br>
also be driver bugs in the others. Apart from those things GStreamer<br>
does not care at all what hardware you use, and in general most of us<br>
are using Intel hardware.<br>
<br>
Regarding my comment to simplify your pipeline... try to reproduce the<br>
leak without rendering video to the screen and just a fakesink. And try<br>
to reproduce the leak with a much simpler source but displaying on the<br>
screen. Dividing a problem into subproblems does not only help with<br>
quicksort ;)<br>
<div><div><br>
--<br>
Sebastian Dröge, Centricular Ltd · <a href="http://www.centricular.com" target="_blank">http://www.centricular.com</a><br>
</div></div><br></div></div><span class="">_______________________________________________<br>
gstreamer-devel mailing list<br>
<a href="mailto:gstreamer-devel@lists.freedesktop.org" target="_blank">gstreamer-devel@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel</a><br>
<br></span></blockquote></div><br></div>
</blockquote></div><br></div>