GstBuffers from appsrc need-data callback are not getting freed

Nikos Chantziaras realnc at gmail.com
Mon Feb 23 15:24:10 PST 2015


I have a severe memory leak when using gstreamer 1.4.5. (0.10.36 works 
just fine.) The buffers I'm creating in the need-data callback of appsrc 
are not getting freed. My application ends up using whole GBs of RAM as 
videos are played.

I register the callbacks in the source-setup signal handler of playbin:

(All code was reduced to a minimum that still exhibits the memory leak.)

   // ...
   g_signal_connect(pipeline, "source-setup",
                    G_CALLBACK(cbOnSourceSetup), dataSource);
   // ...

   GstAppSrcCallbacks appSrcCbs;

   static void
   cbOnSourceSetup(GstPipeline* pipeline, GstAppSrc* source,
                   gpointer dataSource)
   {
       gst_app_src_set_stream_type(source,
                                   GST_APP_STREAM_TYPE_RANDOM_ACCESS);
       g_object_set(G_OBJECT(source), "format", GST_FORMAT_BYTES, NULL);
       memset(&appSrcCbs, 0, sizeof(appSrcCbs));
       appSrcCbs.need_data = cbAppsrcNeedData;
       appSrcCbs.enough_data = NULL;
       appSrcCbs.seek_data = cbAppSrcSeekData;
       gst_app_src_set_callbacks(source, &appSrcCbs, dataSource,
                                 NULL);
       gst_app_src_set_size(source, dataSourceByteLen);
   }

So far, everything is the same between gstreamer-0.10 and 1.0. The 
need-data callback differs a bit between the two, so there's an #ifdef 
in it:

   static void
   cbAppsrcNeedData(GstAppSrc* src, guint length, gpointer dataSource)
   {
       if (length == (guint)-1) {
           // We're free to push any amount of bytes.
           length = 32768;
       }
       GstBuffer* buffer;
       void* data;

   #if GST_CHECK_VERSION(1, 0, 0)
       // *** This allocation leaks ***
       buffer = gst_buffer_new_allocate(NULL, length, NULL);
       GstMapInfo mapInf;
       if (not gst_buffer_map(buffer, &mapInf, GST_MAP_WRITE)) {
           showError("Can't map GstBuffer memory.");
           gst_app_src_end_of_stream(src);
           return;
       }
       data = mapInf.data;
   #else
       buffer = gst_buffer_new_and_alloc(length);
       data = buffer->data;
   #endif

       long bytesCopied = copyBytesFromDataSource(data, dataSource,
                                                  length);
       gst_app_src_push_buffer(src, buffer);
       if (bytesCopied < length) {
           gst_app_src_end_of_stream(src);
       }
   }

Everything is fine when building against gstreamer-0.10. However, the 
buffer allocated in this line:

   buffer = gst_buffer_new_allocate(NULL, length, NULL);

which only compiles with gstreamer-1.0, is the source of the memory leak 
according to Valgrind.

Aren't the buffers supposed to be freed again by gstreamer automatically 
at some point? Or am I supposed to free them manually? If the latter is 
the case, I can't find any information about where this should be done.

In case it matters, I'm closing the pipeline with the following:

   gst_bus_remove_signal_watch(bus);
   // stop
   gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_NULL);
   // wait for stop
   gst_element_get_state(GST_ELEMENT(pipeline), NULL, NULL,
                         GST_CLOCK_TIME_NONE);
   // due to a gst_pipeline_get_bus() elsewhere
   gst_object_unref(bus);
   // free the pipeline
   gst_object_unref(pipeline);


More information about the gstreamer-devel mailing list