Merge branch 'master' into 0.11
[platform/upstream/gst-plugins-base.git] / tests / examples / app / appsink-src.c
1 #include <gst/gst.h>
2
3 #include <string.h>
4
5 #include <gst/app/gstappsrc.h>
6 #include <gst/app/gstappsink.h>
7
8 /* these are the caps we are going to pass through the appsink and appsrc */
9 const gchar *audio_caps =
10     "audio/x-raw-int,channels=1,rate=8000,signed=(boolean)true,width=16,depth=16,endianness=1234";
11
12 typedef struct
13 {
14   GMainLoop *loop;
15   GstElement *source;
16   GstElement *sink;
17 } ProgramData;
18
19 /* called when the appsink notifies us that there is a new buffer ready for
20  * processing */
21 static void
22 on_new_buffer_from_source (GstElement * elt, ProgramData * data)
23 {
24   guint size;
25   GstBuffer *app_buffer, *buffer;
26   GstElement *source;
27
28   /* get the buffer from appsink */
29   buffer = gst_app_sink_pull_buffer (GST_APP_SINK (elt));
30
31   /* turn it into an app buffer, it's not really needed, we could simply push
32    * the retrieved buffer from appsink into appsrc just fine.  */
33   size = gst_buffer_get_size (buffer);
34   g_print ("Pushing a buffer of size %d\n", size);
35   app_buffer = gst_buffer_new_and_alloc (size);
36
37   gst_buffer_copy_into (app_buffer, buffer, GST_BUFFER_COPY_MEMORY, 0, size);
38
39   /* we don't need the appsink buffer anymore */
40   gst_buffer_unref (buffer);
41
42   /* get source an push new buffer */
43   source = gst_bin_get_by_name (GST_BIN (data->sink), "testsource");
44   gst_app_src_push_buffer (GST_APP_SRC (source), app_buffer);
45 }
46
47 /* called when we get a GstMessage from the source pipeline when we get EOS, we
48  * notify the appsrc of it. */
49 static gboolean
50 on_source_message (GstBus * bus, GstMessage * message, ProgramData * data)
51 {
52   GstElement *source;
53
54   switch (GST_MESSAGE_TYPE (message)) {
55     case GST_MESSAGE_EOS:
56       g_print ("The source got dry\n");
57       source = gst_bin_get_by_name (GST_BIN (data->sink), "testsource");
58       gst_app_src_end_of_stream (GST_APP_SRC (source));
59       break;
60     case GST_MESSAGE_ERROR:
61       g_print ("Received error\n");
62       g_main_loop_quit (data->loop);
63       break;
64     default:
65       break;
66   }
67   return TRUE;
68 }
69
70 /* called when we get a GstMessage from the sink pipeline when we get EOS, we
71  * exit the mainloop and this testapp. */
72 static gboolean
73 on_sink_message (GstBus * bus, GstMessage * message, ProgramData * data)
74 {
75   /* nil */
76   switch (GST_MESSAGE_TYPE (message)) {
77     case GST_MESSAGE_EOS:
78       g_print ("Finished playback\n");
79       g_main_loop_quit (data->loop);
80       break;
81     case GST_MESSAGE_ERROR:
82       g_print ("Received error\n");
83       g_main_loop_quit (data->loop);
84       break;
85     default:
86       break;
87   }
88   return TRUE;
89 }
90
91 int
92 main (int argc, char *argv[])
93 {
94   gchar *filename = NULL;
95   ProgramData *data = NULL;
96   gchar *string = NULL;
97   GstBus *bus = NULL;
98   GstElement *testsink = NULL;
99   GstElement *testsource = NULL;
100
101   gst_init (&argc, &argv);
102
103   if (argc == 2)
104     filename = g_strdup (argv[1]);
105   else
106     filename = g_strdup ("/usr/share/sounds/ekiga/ring.wav");
107
108   data = g_new0 (ProgramData, 1);
109
110   data->loop = g_main_loop_new (NULL, FALSE);
111
112   /* setting up source pipeline, we read from a file and convert to our desired
113    * caps. */
114   string =
115       g_strdup_printf
116       ("filesrc location=\"%s\" ! wavparse ! audioconvert ! audioresample ! appsink caps=\"%s\" name=testsink",
117       filename, audio_caps);
118   g_free (filename);
119   data->source = gst_parse_launch (string, NULL);
120   g_free (string);
121
122   if (data->source == NULL) {
123     g_print ("Bad source\n");
124     return -1;
125   }
126
127   /* to be notified of messages from this pipeline, mostly EOS */
128   bus = gst_element_get_bus (data->source);
129   gst_bus_add_watch (bus, (GstBusFunc) on_source_message, data);
130   gst_object_unref (bus);
131
132   /* we use appsink in push mode, it sends us a signal when data is available
133    * and we pull out the data in the signal callback. We want the appsink to
134    * push as fast as it can, hence the sync=false */
135   testsink = gst_bin_get_by_name (GST_BIN (data->source), "testsink");
136   g_object_set (G_OBJECT (testsink), "emit-signals", TRUE, "sync", FALSE, NULL);
137   g_signal_connect (testsink, "new-buffer",
138       G_CALLBACK (on_new_buffer_from_source), data);
139   gst_object_unref (testsink);
140
141   /* setting up sink pipeline, we push audio data into this pipeline that will
142    * then play it back using the default audio sink. We have no blocking
143    * behaviour on the src which means that we will push the entire file into
144    * memory. */
145   string =
146       g_strdup_printf ("appsrc name=testsource caps=\"%s\" ! autoaudiosink",
147       audio_caps);
148   data->sink = gst_parse_launch (string, NULL);
149   g_free (string);
150
151   if (data->sink == NULL) {
152     g_print ("Bad sink\n");
153     return -1;
154   }
155
156   testsource = gst_bin_get_by_name (GST_BIN (data->sink), "testsource");
157   /* configure for time-based format */
158   g_object_set (testsource, "format", GST_FORMAT_TIME, NULL);
159   /* uncomment the next line to block when appsrc has buffered enough */
160   /* g_object_set (testsource, "block", TRUE, NULL); */
161   gst_object_unref (testsource);
162
163   bus = gst_element_get_bus (data->sink);
164   gst_bus_add_watch (bus, (GstBusFunc) on_sink_message, data);
165   gst_object_unref (bus);
166
167   /* launching things */
168   gst_element_set_state (data->sink, GST_STATE_PLAYING);
169   gst_element_set_state (data->source, GST_STATE_PLAYING);
170
171   /* let's run !, this loop will quit when the sink pipeline goes EOS or when an
172    * error occurs in the source or sink pipelines. */
173   g_print ("Let's run!\n");
174   g_main_loop_run (data->loop);
175   g_print ("Going out\n");
176
177   gst_element_set_state (data->source, GST_STATE_NULL);
178   gst_element_set_state (data->sink, GST_STATE_NULL);
179
180   gst_object_unref (data->source);
181   gst_object_unref (data->sink);
182   g_main_loop_unref (data->loop);
183   g_free (data);
184
185   return 0;
186 }