<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body bgcolor="#ffffff" text="#000000">
Hi,<br>
<br>
I tested to compile the appsink-src example from libgstapp and it seems
to leak an enormous amount of memory (In fact it seems not to free any
of the frames).<br>
<br>
How could this be avoided, please? I would like to use this mechanism
for an application and I think that the concept is very good.<br>
<br>
Thanks a lot,<br>
<br>
Mattias<br>
<br>
Here follows the appsink-src.c example:<br>
<br>
----<br>
<br>
<small><font face="Courier New, Courier, monospace">#include
&lt;gst/gst.h&gt;<br>
<br>
#include &lt;string.h&gt;<br>
<br>
#include &lt;gst/app/gstappsrc.h&gt;<br>
#include &lt;gst/app/gstappsink.h&gt;<br>
#include &lt;gst/app/gstappbuffer.h&gt;<br>
<br>
/* these are the caps we are going to pass through the appsink and
appsrc */<br>
<br>
const gchar *video_caps =<br>
&nbsp; "video/x-raw-yuv,width=640,height=480,framerate=15/1";<br>
<br>
<br>
typedef struct<br>
{<br>
&nbsp; GMainLoop *loop;<br>
&nbsp; GstElement *source;<br>
&nbsp; GstElement *sink;<br>
} ProgramData;<br>
<br>
/* called when the appsink notifies us that there is a new buffer ready
for<br>
&nbsp;* processing */<br>
static void<br>
on_new_buffer_from_source (GstElement * elt, ProgramData * data)<br>
{<br>
&nbsp; guint size;<br>
&nbsp; gpointer raw_buffer;<br>
&nbsp; GstBuffer *app_buffer, *buffer;<br>
&nbsp; GstElement *source;<br>
<br>
&nbsp; /* get the buffer from appsink */<br>
&nbsp; buffer = gst_app_sink_pull_buffer (GST_APP_SINK (elt));<br>
<br>
&nbsp; /* turn it into an app buffer, it's not really needed, we could
simply push<br>
&nbsp;&nbsp; * the retrieved buffer from appsink into appsrc just fine.&nbsp; */<br>
&nbsp; size = GST_BUFFER_SIZE (buffer);<br>
&nbsp; g_print ("Pushing a buffer of size %d\n", size);<br>
&nbsp; raw_buffer = g_malloc0 (size);<br>
&nbsp; memcpy (raw_buffer, GST_BUFFER_DATA (buffer), size);<br>
&nbsp; app_buffer = gst_app_buffer_new (raw_buffer, size, g_free,
raw_buffer);<br>
<br>
&nbsp; /* newer basesrc will set caps for use automatically but it does not
really<br>
&nbsp;&nbsp; * hurt to set it on the buffer again */<br>
&nbsp; gst_buffer_set_caps (app_buffer, GST_BUFFER_CAPS (buffer));<br>
<br>
&nbsp; /* we don't need the appsink buffer anymore */<br>
&nbsp; gst_buffer_unref (buffer);<br>
<br>
&nbsp; /* get source an push new buffer */<br>
&nbsp; source = gst_bin_get_by_name (GST_BIN (data-&gt;sink), "testsource");<br>
&nbsp; gst_app_src_push_buffer (GST_APP_SRC (source), app_buffer);<br>
&nbsp;<br>
}<br>
<br>
/* called when we get a GstMessage from the source pipeline when we get
EOS, we<br>
&nbsp;* notify the appsrc of it. */<br>
static gboolean<br>
on_source_message (GstBus * bus, GstMessage * message, ProgramData *
data)<br>
{<br>
&nbsp; GstElement *source;<br>
<br>
&nbsp; switch (GST_MESSAGE_TYPE (message)) {<br>
&nbsp;&nbsp;&nbsp; case GST_MESSAGE_EOS:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g_print ("The source got dry\n");<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; source = gst_bin_get_by_name (GST_BIN (data-&gt;sink),
"testsource");<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gst_app_src_end_of_stream (GST_APP_SRC (source));<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; case GST_MESSAGE_ERROR:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g_print ("Received error\n");<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g_main_loop_quit (data-&gt;loop);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; default:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>
&nbsp; }<br>
&nbsp; return TRUE;<br>
}<br>
<br>
/* called when we get a GstMessage from the sink pipeline when we get
EOS, we<br>
&nbsp;* exit the mainloop and this testapp. */<br>
static gboolean<br>
on_sink_message (GstBus * bus, GstMessage * message, ProgramData * data)<br>
{<br>
&nbsp; /* nil */<br>
&nbsp; switch (GST_MESSAGE_TYPE (message)) {<br>
&nbsp;&nbsp;&nbsp; case GST_MESSAGE_EOS:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g_print ("Finished playback\n");<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g_main_loop_quit (data-&gt;loop);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; case GST_MESSAGE_ERROR:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g_print ("Received error\n");<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g_main_loop_quit (data-&gt;loop);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; default:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>
&nbsp; }<br>
&nbsp; return TRUE;<br>
}<br>
<br>
int<br>
main (int argc, char *argv[])<br>
{<br>
&nbsp; gchar *filename = NULL;<br>
&nbsp; ProgramData *data = NULL;<br>
&nbsp; gchar *string = NULL;<br>
&nbsp; GstBus *bus = NULL;<br>
&nbsp; GstElement *testsink = NULL;<br>
&nbsp; GstElement *testsource = NULL;<br>
<br>
&nbsp; gst_init (&amp;argc, &amp;argv);<br>
<br>
&nbsp; if (argc == 2)<br>
&nbsp;&nbsp;&nbsp; filename = g_strdup (argv[1]);<br>
&nbsp; else<br>
&nbsp;&nbsp;&nbsp; filename = g_strdup ("/usr/share/sounds/ekiga/ring.wav");<br>
<br>
&nbsp; data = g_new0 (ProgramData, 1);<br>
<br>
&nbsp; data-&gt;loop = g_main_loop_new (NULL, FALSE);<br>
<br>
&nbsp; /* setting up source pipeline, we read from a file and convert to our
desired<br>
&nbsp;&nbsp; * caps. */<br>
&nbsp; string =<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g_strdup_printf<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ("videotestsrc !
video/x-raw-yuv,width=640,height=480,framerate=15/1 ! appsink
caps=\"%s\" name=testsink",<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; filename, video_caps);<br>
&nbsp; g_free (filename);<br>
&nbsp; data-&gt;source = gst_parse_launch (string, NULL);<br>
&nbsp; g_free (string);<br>
<br>
&nbsp; if (data-&gt;source == NULL) {<br>
&nbsp;&nbsp;&nbsp; g_print ("Bad source\n");<br>
&nbsp;&nbsp;&nbsp; return -1;<br>
&nbsp; }<br>
<br>
&nbsp; /* to be notified of messages from this pipeline, mostly EOS */<br>
&nbsp; bus = gst_element_get_bus (data-&gt;source);<br>
&nbsp; gst_bus_add_watch (bus, (GstBusFunc) on_source_message, data);<br>
&nbsp; gst_object_unref (bus);<br>
<br>
&nbsp; /* we use appsink in push mode, it sends us a signal when data is
available<br>
&nbsp;&nbsp; * and we pull out the data in the signal callback. We want the
appsink to<br>
&nbsp;&nbsp; * push as fast as it can, hence the sync=false */<br>
&nbsp; testsink = gst_bin_get_by_name (GST_BIN (data-&gt;source),
"testsink");<br>
&nbsp; g_object_set (G_OBJECT (testsink), "emit-signals", TRUE, "sync",
FALSE, NULL);<br>
&nbsp; g_signal_connect (testsink, "new-buffer",<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; G_CALLBACK (on_new_buffer_from_source), data);<br>
&nbsp; gst_object_unref (testsink);<br>
<br>
&nbsp; /* setting up sink pipeline, we push audio data into this pipeline
that will<br>
&nbsp;&nbsp; * then play it back using the default audio sink. We have no blocking<br>
&nbsp;&nbsp; * behaviour on the src which means that we will push the entire file
into<br>
&nbsp;&nbsp; * memory. */<br>
&nbsp; string =<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g_strdup_printf ("appsrc name=testsource caps=\"%s\" !
xvimagesink",<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; video_caps);<br>
&nbsp; data-&gt;sink = gst_parse_launch (string, NULL);<br>
&nbsp; g_free (string);<br>
<br>
&nbsp; if (data-&gt;sink == NULL) {<br>
&nbsp;&nbsp;&nbsp; g_print ("Bad sink\n");<br>
&nbsp;&nbsp;&nbsp; return -1;<br>
&nbsp; }<br>
<br>
&nbsp; testsource = gst_bin_get_by_name (GST_BIN (data-&gt;sink),
"testsource");<br>
&nbsp; /* configure for time-based format */<br>
&nbsp; g_object_set (testsource, "format", GST_FORMAT_TIME, NULL);<br>
&nbsp; /* uncomment the next line to block when appsrc has buffered enough */<br>
&nbsp; /* g_object_set (testsource, "block", TRUE, NULL); */<br>
&nbsp; gst_object_unref (testsource);<br>
<br>
&nbsp; bus = gst_element_get_bus (data-&gt;sink);<br>
&nbsp; gst_bus_add_watch (bus, (GstBusFunc) on_sink_message, data);<br>
&nbsp; gst_object_unref (bus);<br>
<br>
&nbsp; /* launching things */<br>
&nbsp; gst_element_set_state (data-&gt;sink, GST_STATE_PLAYING);<br>
&nbsp; gst_element_set_state (data-&gt;source, GST_STATE_PLAYING);<br>
<br>
&nbsp; /* let's run !, this loop will quit when the sink pipeline goes EOS
or when an<br>
&nbsp;&nbsp; * error occurs in the source or sink pipelines. */<br>
&nbsp; g_print ("Let's run!\n");<br>
&nbsp; g_main_loop_run (data-&gt;loop);<br>
&nbsp; g_print ("Going out\n");<br>
<br>
&nbsp; gst_element_set_state (data-&gt;source, GST_STATE_NULL);<br>
&nbsp; gst_element_set_state (data-&gt;sink, GST_STATE_NULL);<br>
<br>
&nbsp; gst_object_unref (data-&gt;source);<br>
&nbsp; gst_object_unref (data-&gt;sink);<br>
&nbsp; g_main_loop_unref (data-&gt;loop);<br>
&nbsp; g_free (data);<br>
<br>
&nbsp; return 0;<br>
}<br>
<br>
<br>
</font></small>
<pre class="moz-signature" cols="800">-- 
 Mattias Frank Barthel      
 V&iacute;a Augusta 177 08021 Barcelona (Spain)
 Video &amp; Multimedia technologies
 TELEF&Oacute;NICA R&amp;D
 T. 0034-93-365-3309
</pre>
</body>
</html>