Implement our own theme, yay!
[platform/upstream/gstreamer.git] / sdk-playback-tutorial-short-cutting-the-pipeline.md
1 # Playback tutorial 3: Short-cutting the pipeline
2
3 ## Goal
4
5 [](sdk-basic-tutorial-short-cutting-the-pipeline.md) showed
6 how an application can manually extract or inject data into a pipeline
7 by using two special elements called `appsrc` and `appsink`.
8 `playbin` allows using these elements too, but the method to connect
9 them is different. To connect an `appsink` to `playbin` see [](sdk-playback-tutorial-custom-playbin-sinks.md).
10 This tutorial shows:
11
12   - How to connect `appsrc` with `playbin`
13   - How to configure the `appsrc`
14
15 ## A playbin waveform generator
16
17 Copy this code into a text file named `playback-tutorial-3.c`.
18
19 **playback-tutorial-3.c**
20
21 ``` c
22 #include <gst/gst.h>
23 #include <gst/audio/audio.h>
24 #include <string.h>
25
26 #define CHUNK_SIZE 1024   /* Amount of bytes we are sending in each buffer */
27 #define SAMPLE_RATE 44100 /* Samples per second we are sending */
28
29 /* Structure to contain all our information, so we can pass it to callbacks */
30 typedef struct _CustomData {
31   GstElement *pipeline;
32   GstElement *app_source;
33
34   guint64 num_samples;   /* Number of samples generated so far (for timestamp generation) */
35   gfloat a, b, c, d;     /* For waveform generation */
36
37   guint sourceid;        /* To control the GSource */
38
39   GMainLoop *main_loop;  /* GLib's Main Loop */
40 } CustomData;
41
42 /* This method is called by the idle GSource in the mainloop, to feed CHUNK_SIZE bytes into appsrc.
43  * The ide handler is added to the mainloop when appsrc requests us to start sending data (need-data signal)
44  * and is removed when appsrc has enough data (enough-data signal).
45  */
46 static gboolean push_data (CustomData *data) {
47   GstBuffer *buffer;
48   GstFlowReturn ret;
49   int i;
50   GstMapInfo map;
51   gint16 *raw;
52   gint num_samples = CHUNK_SIZE / 2; /* Because each sample is 16 bits */
53   gfloat freq;
54
55   /* Create a new empty buffer */
56   buffer = gst_buffer_new_and_alloc (CHUNK_SIZE);
57
58   /* Set its timestamp and duration */
59   GST_BUFFER_TIMESTAMP (buffer) = gst_util_uint64_scale (data->num_samples, GST_SECOND, SAMPLE_RATE);
60   GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale (CHUNK_SIZE, GST_SECOND, SAMPLE_RATE);
61
62   /* Generate some psychodelic waveforms */
63   gst_buffer_map (buffer, &map, GST_MAP_WRITE);
64   raw = (gint16 *)map.data;
65   data->c += data->d;
66   data->d -= data->c / 1000;
67   freq = 1100 + 1000 * data->d;
68   for (i = 0; i < num_samples; i++) {
69     data->a += data->b;
70     data->b -= data->a / freq;
71     raw[i] = (gint16)(500 * data->a);
72   }
73   gst_buffer_unmap (buffer, &map);
74   data->num_samples += num_samples;
75
76   /* Push the buffer into the appsrc */
77   g_signal_emit_by_name (data->app_source, "push-buffer", buffer, &ret);
78
79   /* Free the buffer now that we are done with it */
80   gst_buffer_unref (buffer);
81
82   if (ret != GST_FLOW_OK) {
83     /* We got some error, stop sending data */
84     return FALSE;
85   }
86
87   return TRUE;
88 }
89
90 /* This signal callback triggers when appsrc needs data. Here, we add an idle handler
91  * to the mainloop to start pushing data into the appsrc */
92 static void start_feed (GstElement *source, guint size, CustomData *data) {
93   if (data->sourceid == 0) {
94     g_print ("Start feeding\n");
95     data->sourceid = g_idle_add ((GSourceFunc) push_data, data);
96   }
97 }
98
99 /* This callback triggers when appsrc has enough data and we can stop sending.
100  * We remove the idle handler from the mainloop */
101 static void stop_feed (GstElement *source, CustomData *data) {
102   if (data->sourceid != 0) {
103     g_print ("Stop feeding\n");
104     g_source_remove (data->sourceid);
105     data->sourceid = 0;
106   }
107 }
108
109 /* This function is called when an error message is posted on the bus */
110 static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) {
111   GError *err;
112   gchar *debug_info;
113
114   /* Print error details on the screen */
115   gst_message_parse_error (msg, &err, &debug_info);
116   g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message);
117   g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none");
118   g_clear_error (&err);
119   g_free (debug_info);
120
121   g_main_loop_quit (data->main_loop);
122 }
123
124 /* This function is called when playbin has created the appsrc element, so we have
125  * a chance to configure it. */
126 static void source_setup (GstElement *pipeline, GstElement *source, CustomData *data) {
127   GstAudioInfo info;
128   GstCaps *audio_caps;
129
130   g_print ("Source has been created. Configuring.\n");
131   data->app_source = source;
132
133   /* Configure appsrc */
134   gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S16, SAMPLE_RATE, 1, NULL);
135   audio_caps = gst_audio_info_to_caps (&info);
136   g_object_set (source, "caps", audio_caps, "format", GST_FORMAT_TIME, NULL);
137   g_signal_connect (source, "need-data", G_CALLBACK (start_feed), data);
138   g_signal_connect (source, "enough-data", G_CALLBACK (stop_feed), data);
139   gst_caps_unref (audio_caps);
140   g_free (audio_caps_text);
141 }
142
143 int main(int argc, char *argv[]) {
144   CustomData data;
145   GstBus *bus;
146
147   /* Initialize cumstom data structure */
148   memset (&data, 0, sizeof (data));
149   data.b = 1; /* For waveform generation */
150   data.d = 1;
151
152   /* Initialize GStreamer */
153   gst_init (&argc, &argv);
154
155   /* Create the playbin element */
156   data.pipeline = gst_parse_launch ("playbin uri=appsrc://", NULL);
157   g_signal_connect (data.pipeline, "source-setup", G_CALLBACK (source_setup), &data);
158
159   /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */
160   bus = gst_element_get_bus (data.pipeline);
161   gst_bus_add_signal_watch (bus);
162   g_signal_connect (G_OBJECT (bus), "message::error", (GCallback)error_cb, &data);
163   gst_object_unref (bus);
164
165   /* Start playing the pipeline */
166   gst_element_set_state (data.pipeline, GST_STATE_PLAYING);
167
168   /* Create a GLib Main Loop and set it to run */
169   data.main_loop = g_main_loop_new (NULL, FALSE);
170   g_main_loop_run (data.main_loop);
171
172   /* Free resources */
173   gst_element_set_state (data.pipeline, GST_STATE_NULL);
174   gst_object_unref (data.pipeline);
175   return 0;
176 }
177 ```
178
179 To use an `appsrc` as the source for the pipeline, simply instantiate a
180 `playbin` and set its URI to `appsrc://`
181
182 ``` c
183 /* Create the playbin element */
184 data.pipeline = gst_parse_launch ("playbin uri=appsrc://", NULL);
185 ```
186
187 `playbin` will create an internal `appsrc` element and fire the
188 `source-setup` signal to allow the application to configure
189 it:
190
191 ``` c
192 g_signal_connect (data.pipeline, "source-setup", G_CALLBACK (source_setup), &data);
193 ```
194
195 In particular, it is important to set the caps property of `appsrc`,
196 since, once the signal handler returns, `playbin` will instantiate the
197 next element in the pipeline according to these
198 caps:
199
200 ``` c
201 /* This function is called when playbin has created the appsrc element, so we have
202  * a chance to configure it. */
203 static void source_setup (GstElement *pipeline, GstElement *source, CustomData *data) {
204   GstAudioInfo info;
205   GstCaps *audio_caps;
206
207   g_print ("Source has been created. Configuring.\n");
208   data->app_source = source;
209
210   /* Configure appsrc */
211   gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S16, SAMPLE_RATE, 1, NULL);
212   audio_caps = gst_audio_info_to_caps (&info);
213   g_object_set (source, "caps", audio_caps, "format", GST_FORMAT_TIME, NULL);
214   g_signal_connect (source, "need-data", G_CALLBACK (start_feed), data);
215   g_signal_connect (source, "enough-data", G_CALLBACK (stop_feed), data);
216   gst_caps_unref (audio_caps);
217   g_free (audio_caps_text);
218 }
219 ```
220
221 The configuration of the `appsrc` is exactly the same as in
222 [](sdk-basic-tutorial-short-cutting-the-pipeline.md):
223 the caps are set to `audio/x-raw`, and two callbacks are registered,
224 so the element can tell the application when it needs to start and stop
225 pushing data. See [](sdk-basic-tutorial-short-cutting-the-pipeline.md)
226 for more details.
227
228 From this point onwards, `playbin` takes care of the rest of the
229 pipeline, and the application only needs to worry about generating more
230 data when told so.
231
232 To learn how data can be extracted from `playbin` using the
233 `appsink` element, see [](sdk-playback-tutorial-custom-playbin-sinks.md).
234
235 ## Conclusion
236
237 This tutorial applies the concepts shown in
238 [](sdk-basic-tutorial-short-cutting-the-pipeline.md) to
239 `playbin`. In particular, it has shown:
240
241   - How to connect `appsrc` with `playbin` using the special
242     URI `appsrc://`
243   - How to configure the `appsrc` using the `source-setup` signal
244
245 It has been a pleasure having you here, and see you soon!