1 /* GStreamer
2  *
3  * appsink-src.c: example for using appsink and appsrc.
4  *
5  * Copyright (C) 2008 Wim Taymans <wim.taymans@gmail.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #include <gst/gst.h>
24 
25 #include <string.h>
26 
27 #include <gst/app/gstappsrc.h>
28 #include <gst/app/gstappsink.h>
29 
30 /* these are the caps we are going to pass through the appsink and appsrc */
31 const gchar *audio_caps =
32     "audio/x-raw,format=S16LE,channels=1,rate=8000, layout=interleaved";
33 
34 typedef struct
35 {
36   GMainLoop *loop;
37   GstElement *source;
38   GstElement *sink;
39 } ProgramData;
40 
41 /* called when the appsink notifies us that there is a new buffer ready for
42  * processing */
43 static GstFlowReturn
on_new_sample_from_sink(GstElement * elt,ProgramData * data)44 on_new_sample_from_sink (GstElement * elt, ProgramData * data)
45 {
46   GstSample *sample;
47   GstBuffer *app_buffer, *buffer;
48   GstElement *source;
49   GstFlowReturn ret;
50 
51   /* get the sample from appsink */
52   sample = gst_app_sink_pull_sample (GST_APP_SINK (elt));
53   buffer = gst_sample_get_buffer (sample);
54 
55   /* make a copy */
56   app_buffer = gst_buffer_copy (buffer);
57 
58   /* we don't need the appsink sample anymore */
59   gst_sample_unref (sample);
60 
61   /* get source an push new buffer */
62   source = gst_bin_get_by_name (GST_BIN (data->sink), "testsource");
63   ret = gst_app_src_push_buffer (GST_APP_SRC (source), app_buffer);
64   gst_object_unref (source);
65 
66   return ret;
67 }
68 
69 /* called when we get a GstMessage from the source pipeline when we get EOS, we
70  * notify the appsrc of it. */
71 static gboolean
on_source_message(GstBus * bus,GstMessage * message,ProgramData * data)72 on_source_message (GstBus * bus, GstMessage * message, ProgramData * data)
73 {
74   GstElement *source;
75 
76   switch (GST_MESSAGE_TYPE (message)) {
77     case GST_MESSAGE_EOS:
78       g_print ("The source got dry\n");
79       source = gst_bin_get_by_name (GST_BIN (data->sink), "testsource");
80       gst_app_src_end_of_stream (GST_APP_SRC (source));
81       gst_object_unref (source);
82       break;
83     case GST_MESSAGE_ERROR:
84       g_print ("Received error\n");
85       g_main_loop_quit (data->loop);
86       break;
87     default:
88       break;
89   }
90   return TRUE;
91 }
92 
93 /* called when we get a GstMessage from the sink pipeline when we get EOS, we
94  * exit the mainloop and this testapp. */
95 static gboolean
on_sink_message(GstBus * bus,GstMessage * message,ProgramData * data)96 on_sink_message (GstBus * bus, GstMessage * message, ProgramData * data)
97 {
98   /* nil */
99   switch (GST_MESSAGE_TYPE (message)) {
100     case GST_MESSAGE_EOS:
101       g_print ("Finished playback\n");
102       g_main_loop_quit (data->loop);
103       break;
104     case GST_MESSAGE_ERROR:
105       g_print ("Received error\n");
106       g_main_loop_quit (data->loop);
107       break;
108     default:
109       break;
110   }
111   return TRUE;
112 }
113 
114 int
main(int argc,char * argv[])115 main (int argc, char *argv[])
116 {
117   gchar *filename = NULL;
118   ProgramData *data = NULL;
119   gchar *string = NULL;
120   GstBus *bus = NULL;
121   GstElement *testsink = NULL;
122   GstElement *testsource = NULL;
123 
124   gst_init (&argc, &argv);
125 
126   if (argc == 2)
127     filename = g_strdup (argv[1]);
128   else
129     filename = g_strdup ("/usr/share/sounds/ekiga/ring.wav");
130 
131   if (!g_file_test (filename, G_FILE_TEST_EXISTS)) {
132     g_print ("File %s does not exist\n", filename);
133     g_free (filename);
134     return -1;
135   }
136 
137   data = g_new0 (ProgramData, 1);
138 
139   data->loop = g_main_loop_new (NULL, FALSE);
140 
141   /* setting up source pipeline, we read from a file and convert to our desired
142    * caps. */
143   string =
144       g_strdup_printf
145       ("filesrc location=\"%s\" ! wavparse ! audioconvert ! audioresample ! appsink caps=\"%s\" name=testsink",
146       filename, audio_caps);
147   g_free (filename);
148   data->source = gst_parse_launch (string, NULL);
149   g_free (string);
150 
151   if (data->source == NULL) {
152     g_print ("Bad source\n");
153     g_main_loop_unref (data->loop);
154     g_free (data);
155     return -1;
156   }
157 
158   /* to be notified of messages from this pipeline, mostly EOS */
159   bus = gst_element_get_bus (data->source);
160   gst_bus_add_watch (bus, (GstBusFunc) on_source_message, data);
161   gst_object_unref (bus);
162 
163   /* we use appsink in push mode, it sends us a signal when data is available
164    * and we pull out the data in the signal callback. We want the appsink to
165    * push as fast as it can, hence the sync=false */
166   testsink = gst_bin_get_by_name (GST_BIN (data->source), "testsink");
167   g_object_set (G_OBJECT (testsink), "emit-signals", TRUE, "sync", FALSE, NULL);
168   g_signal_connect (testsink, "new-sample",
169       G_CALLBACK (on_new_sample_from_sink), data);
170   gst_object_unref (testsink);
171 
172   /* setting up sink pipeline, we push audio data into this pipeline that will
173    * then play it back using the default audio sink. We have no blocking
174    * behaviour on the src which means that we will push the entire file into
175    * memory. */
176   string =
177       g_strdup_printf ("appsrc name=testsource caps=\"%s\" ! autoaudiosink",
178       audio_caps);
179   data->sink = gst_parse_launch (string, NULL);
180   g_free (string);
181 
182   if (data->sink == NULL) {
183     g_print ("Bad sink\n");
184     gst_object_unref (data->source);
185     g_main_loop_unref (data->loop);
186     g_free (data);
187     return -1;
188   }
189 
190   testsource = gst_bin_get_by_name (GST_BIN (data->sink), "testsource");
191   /* configure for time-based format */
192   g_object_set (testsource, "format", GST_FORMAT_TIME, NULL);
193   /* uncomment the next line to block when appsrc has buffered enough */
194   /* g_object_set (testsource, "block", TRUE, NULL); */
195   gst_object_unref (testsource);
196 
197   bus = gst_element_get_bus (data->sink);
198   gst_bus_add_watch (bus, (GstBusFunc) on_sink_message, data);
199   gst_object_unref (bus);
200 
201   /* launching things */
202   gst_element_set_state (data->sink, GST_STATE_PLAYING);
203   gst_element_set_state (data->source, GST_STATE_PLAYING);
204 
205   /* let's run !, this loop will quit when the sink pipeline goes EOS or when an
206    * error occurs in the source or sink pipelines. */
207   g_print ("Let's run!\n");
208   g_main_loop_run (data->loop);
209   g_print ("Going out\n");
210 
211   gst_element_set_state (data->source, GST_STATE_NULL);
212   gst_element_set_state (data->sink, GST_STATE_NULL);
213 
214   gst_object_unref (data->source);
215   gst_object_unref (data->sink);
216   g_main_loop_unref (data->loop);
217   g_free (data);
218 
219   return 0;
220 }
221