summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2008-06-12 15:47:03 +0000
committerWim Taymans <wim.taymans@gmail.com>2008-06-12 15:47:03 +0000
commit56e01a0365c374049b5aee25c55a8859413093b8 (patch)
tree8831d3f8eac9050d5728e00cc0df06fa42d4f1d8 /examples
parent917583d75a676d77ba8f28da5279a987ae3e81bd (diff)
downloadgstreamer-plugins-bad-56e01a0365c374049b5aee25c55a8859413093b8.tar.gz
examples/app/: Add beefed up example app from bug #413418. It now also uses appsink instead of fakesink for more ulti...
Original commit message from CVS: * examples/app/.cvsignore: * examples/app/Makefile.am: * examples/app/appsink-src.c: (on_new_buffer_from_source), (on_source_message), (on_sink_message), (main): Add beefed up example app from bug #413418. It now also uses appsink instead of fakesink for more ultimate coolness. * gst-libs/gst/app/gstappsrc.c: (gst_app_src_class_init), (gst_app_src_init), (gst_app_src_set_property), (gst_app_src_get_property), (gst_app_src_unlock), (gst_app_src_unlock_stop), (gst_app_src_create), (gst_app_src_set_max_bytes), (gst_app_src_push_buffer), (gst_app_src_end_of_stream): * gst-libs/gst/app/gstappsrc.h: Add block property to allow push based implementation to block when we fill up the appsrc queues. Emit the enough-data signal while releasing our lock.
Diffstat (limited to 'examples')
-rw-r--r--examples/app/.gitignore1
-rw-r--r--examples/app/Makefile.am9
-rw-r--r--examples/app/appsink-src.c190
3 files changed, 199 insertions, 1 deletions
diff --git a/examples/app/.gitignore b/examples/app/.gitignore
index eeae0e65e..8a2c76152 100644
--- a/examples/app/.gitignore
+++ b/examples/app/.gitignore
@@ -3,3 +3,4 @@ appsrc-ra
appsrc-seekable
appsrc-stream
appsrc-stream2
+appsink-src
diff --git a/examples/app/Makefile.am b/examples/app/Makefile.am
index fc4b9419d..4f3df7779 100644
--- a/examples/app/Makefile.am
+++ b/examples/app/Makefile.am
@@ -1,6 +1,6 @@
noinst_PROGRAMS = appsrc_ex appsrc-stream appsrc-stream2 appsrc-ra \
- appsrc-seekable
+ appsrc-seekable appsink-src
appsrc_ex_SOURCES = appsrc_ex.c
appsrc_ex_CFLAGS = $(GST_CFLAGS) $(GCONF_CFLAGS)
@@ -23,3 +23,10 @@ appsrc_ra_LDFLAGS = $(GST_LIBS)
appsrc_seekable_SOURCES = appsrc-seekable.c
appsrc_seekable_CFLAGS = $(GST_CFLAGS) $(GCONF_CFLAGS)
appsrc_seekable_LDFLAGS = $(GST_LIBS)
+
+appsink_src_SOURCES = appsink-src.c
+appsink_src_CFLAGS = $(GST_CFLAGS) $(GCONF_CFLAGS)
+appsink_src_LDFLAGS = \
+ $(GST_LIBS) \
+ $(top_builddir)/gst-libs/gst/app/libgstapp-@GST_MAJORMINOR@.la
+
diff --git a/examples/app/appsink-src.c b/examples/app/appsink-src.c
new file mode 100644
index 000000000..6472af30a
--- /dev/null
+++ b/examples/app/appsink-src.c
@@ -0,0 +1,190 @@
+#include <gst/gst.h>
+
+#include <string.h>
+
+#include <gst/app/gstappsrc.h>
+#include <gst/app/gstappsink.h>
+#include <gst/app/gstappbuffer.h>
+
+/* these are the caps we are going to pass through the appsink and appsrc */
+const gchar *audio_caps =
+ "audio/x-raw-int,channels=1,rate=8000,signed=(boolean)true,width=16,depth=16,endianness=1234";
+
+typedef struct
+{
+ GMainLoop *loop;
+ GstElement *source;
+ GstElement *sink;
+} ProgramData;
+
+/* called when the appsink notifies us that there is a new buffer ready for
+ * processing */
+static void
+on_new_buffer_from_source (GstElement * elt, ProgramData * data)
+{
+ guint size;
+ gpointer raw_buffer;
+ GstBuffer *app_buffer, *buffer;
+ GstElement *source;
+
+ /* get the buffer from appsink */
+ buffer = gst_app_sink_pull_buffer (GST_APP_SINK (elt));
+
+ /* turn it into an app buffer, it's not really needed, we could simply push
+ * the retrieved buffer from appsink into appsrc just fine. */
+ size = GST_BUFFER_SIZE (buffer);
+ g_print ("Pushing a buffer of size %d\n", size);
+ raw_buffer = g_malloc0 (size);
+ memcpy (raw_buffer, GST_BUFFER_DATA (buffer), size);
+ app_buffer = gst_app_buffer_new (raw_buffer, size, g_free, raw_buffer);
+
+ /* we don't need the appsink buffer anymore */
+ gst_buffer_unref (buffer);
+
+ /* newer basesrc will set caps for use automatically but it does not really
+ * hurt to set it on the buffer again */
+ gst_buffer_set_caps (app_buffer, GST_BUFFER_CAPS (buffer));
+ source = gst_bin_get_by_name (GST_BIN (data->sink), "testsource");
+ gst_app_src_push_buffer (GST_APP_SRC (source), app_buffer);
+}
+
+/* called when we get a GstMessage from the source pipeline when we get EOS, we
+ * notify the appsrc of it. */
+static gboolean
+on_source_message (GstBus * bus, GstMessage * message, ProgramData * data)
+{
+ GstElement *source;
+
+ switch (GST_MESSAGE_TYPE (message)) {
+ case GST_MESSAGE_EOS:
+ g_print ("The source got dry\n");
+ source = gst_bin_get_by_name (GST_BIN (data->sink), "testsource");
+ gst_app_src_end_of_stream (GST_APP_SRC (source));
+ break;
+ case GST_MESSAGE_ERROR:
+ g_print ("Received error\n");
+ g_main_loop_quit (data->loop);
+ break;
+ default:
+ break;
+ }
+ return TRUE;
+}
+
+/* called when we get a GstMessage from the sink pipeline when we get EOS, we
+ * exit the mainloop and this testapp. */
+static gboolean
+on_sink_message (GstBus * bus, GstMessage * message, ProgramData * data)
+{
+ /* nil */
+ switch (GST_MESSAGE_TYPE (message)) {
+ case GST_MESSAGE_EOS:
+ g_print ("Finished playback\n");
+ g_main_loop_quit (data->loop);
+ break;
+ case GST_MESSAGE_ERROR:
+ g_print ("Received error\n");
+ g_main_loop_quit (data->loop);
+ break;
+ default:
+ break;
+ }
+ return TRUE;
+}
+
+int
+main (int argc, char *argv[])
+{
+ gchar *filename = NULL;
+ ProgramData *data = NULL;
+ gchar *string = NULL;
+ GstBus *bus = NULL;
+ GstElement *testsink = NULL;
+ GstElement *testsource = NULL;
+
+ gst_init (&argc, &argv);
+
+ if (argc == 2)
+ filename = g_strdup (argv[1]);
+ else
+ filename = g_strdup ("/usr/share/sounds/ekiga/ring.wav");
+
+ data = g_new0 (ProgramData, 1);
+
+ data->loop = g_main_loop_new (NULL, FALSE);
+
+ /* setting up source pipeline, we read from a file and convert to our desired
+ * caps. */
+ string =
+ g_strdup_printf
+ ("filesrc location=\"%s\" ! wavparse ! audioconvert ! audioresample ! appsink caps=\"%s\" name=testsink",
+ filename, audio_caps);
+ g_free (filename);
+ data->source = gst_parse_launch (string, NULL);
+ g_free (string);
+
+ if (data->source == NULL) {
+ g_print ("Bad source\n");
+ return -1;
+ }
+
+ /* to be notified of messages from this pipeline, mostly EOS */
+ bus = gst_element_get_bus (data->source);
+ gst_bus_add_watch (bus, (GstBusFunc) on_source_message, data);
+ gst_object_unref (bus);
+
+ /* we use appsink in push mode, it sends us a signal when data is available
+ * and we pull out the data in the signal callback. We want the appsink to
+ * push as fast as it can, hence the sync=false */
+ testsink = gst_bin_get_by_name (GST_BIN (data->source), "testsink");
+ g_object_set (G_OBJECT (testsink), "emit-signals", TRUE, "sync", FALSE, NULL);
+ g_signal_connect (testsink, "new-buffer",
+ G_CALLBACK (on_new_buffer_from_source), data);
+ gst_object_unref (testsink);
+
+ /* setting up sink pipeline, we push audio data into this pipeline that will
+ * then play it back using the default audio sink. We have no blocking
+ * behaviour on the src which means that we will push the entire file into
+ * memory. */
+ string =
+ g_strdup_printf ("appsrc name=testsource caps=\"%s\" ! autoaudiosink",
+ audio_caps);
+ data->sink = gst_parse_launch (string, NULL);
+ g_free (string);
+
+ if (data->sink == NULL) {
+ g_print ("Bad sink\n");
+ return -1;
+ }
+
+ testsource = gst_bin_get_by_name (GST_BIN (data->sink), "testsource");
+ /* configure for time-based format */
+ g_object_set (testsource, "format", GST_FORMAT_TIME, NULL);
+ /* uncomment the next line to block when appsrc has buffered enough */
+ /* g_object_set (testsource, "block", TRUE, NULL); */
+ gst_object_unref (testsource);
+
+ bus = gst_element_get_bus (data->sink);
+ gst_bus_add_watch (bus, (GstBusFunc) on_sink_message, data);
+ gst_object_unref (bus);
+
+ /* launching things */
+ gst_element_set_state (data->sink, GST_STATE_PLAYING);
+ gst_element_set_state (data->source, GST_STATE_PLAYING);
+
+ /* let's run !, this loop will quit when the sink pipeline goes EOS or when an
+ * error occurs in the source or sink pipelines. */
+ g_print ("Let's run!\n");
+ g_main_loop_run (data->loop);
+ g_print ("Going out\n");
+
+ gst_element_set_state (data->source, GST_STATE_NULL);
+ gst_element_set_state (data->sink, GST_STATE_NULL);
+
+ gst_object_unref (data->source);
+ gst_object_unref (data->sink);
+ g_main_loop_unref (data->loop);
+ g_free (data);
+
+ return 0;
+}