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