aboutsummaryrefslogtreecommitdiff
path: root/src/conversation/gnunet-helper-audio-playback-gst.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/conversation/gnunet-helper-audio-playback-gst.c')
-rw-r--r--src/conversation/gnunet-helper-audio-playback-gst.c383
1 files changed, 192 insertions, 191 deletions
diff --git a/src/conversation/gnunet-helper-audio-playback-gst.c b/src/conversation/gnunet-helper-audio-playback-gst.c
index 6e16b9791..48f0c5b48 100644
--- a/src/conversation/gnunet-helper-audio-playback-gst.c
+++ b/src/conversation/gnunet-helper-audio-playback-gst.c
@@ -81,144 +81,144 @@ static int abort_read;
81 81
82 82
83static void 83static void
84sink_child_added(GstChildProxy *child_proxy, 84sink_child_added (GstChildProxy *child_proxy,
85 GObject *object, 85 GObject *object,
86 gchar *name, 86 gchar *name,
87 gpointer user_data) 87 gpointer user_data)
88{ 88{
89 if (GST_IS_AUDIO_BASE_SRC(object)) 89 if (GST_IS_AUDIO_BASE_SRC (object))
90 g_object_set(object, 90 g_object_set (object,
91 "buffer-time", (gint64)BUFFER_TIME, 91 "buffer-time", (gint64) BUFFER_TIME,
92 "latency-time", (gint64)LATENCY_TIME, 92 "latency-time", (gint64) LATENCY_TIME,
93 NULL); 93 NULL);
94} 94}
95 95
96 96
97static void 97static void
98ogg_pad_added(GstElement *element, 98ogg_pad_added (GstElement *element,
99 GstPad *pad, 99 GstPad *pad,
100 gpointer data) 100 gpointer data)
101{ 101{
102 GstPad *sinkpad; 102 GstPad *sinkpad;
103 GstElement *decoder = (GstElement *)data; 103 GstElement *decoder = (GstElement *) data;
104 104
105 /* We can now link this pad with the opus-decoder sink pad */ 105 /* We can now link this pad with the opus-decoder sink pad */
106 sinkpad = gst_element_get_static_pad(decoder, "sink"); 106 sinkpad = gst_element_get_static_pad (decoder, "sink");
107 107
108 gst_pad_link(pad, sinkpad); 108 gst_pad_link (pad, sinkpad);
109 109
110 gst_element_link_many(decoder, conv, resampler, sink, NULL); 110 gst_element_link_many (decoder, conv, resampler, sink, NULL);
111 111
112 gst_object_unref(sinkpad); 112 gst_object_unref (sinkpad);
113} 113}
114 114
115 115
116static void 116static void
117quit() 117quit ()
118{ 118{
119 if (NULL != source) 119 if (NULL != source)
120 gst_app_src_end_of_stream(GST_APP_SRC(source)); 120 gst_app_src_end_of_stream (GST_APP_SRC (source));
121 if (NULL != pipeline) 121 if (NULL != pipeline)
122 gst_element_set_state(pipeline, GST_STATE_NULL); 122 gst_element_set_state (pipeline, GST_STATE_NULL);
123 abort_read = 1; 123 abort_read = 1;
124} 124}
125 125
126 126
127static gboolean 127static gboolean
128bus_call(GstBus *bus, GstMessage *msg, gpointer data) 128bus_call (GstBus *bus, GstMessage *msg, gpointer data)
129{ 129{
130 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 130 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
131 "Bus message\n"); 131 "Bus message\n");
132 switch (GST_MESSAGE_TYPE(msg)) 132 switch (GST_MESSAGE_TYPE (msg))
133 { 133 {
134 case GST_MESSAGE_EOS: 134 case GST_MESSAGE_EOS:
135 GNUNET_log(GNUNET_ERROR_TYPE_INFO, 135 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
136 "End of stream\n"); 136 "End of stream\n");
137 quit(); 137 quit ();
138 break; 138 break;
139 139
140 case GST_MESSAGE_ERROR: 140 case GST_MESSAGE_ERROR:
141 { 141 {
142 gchar *debug; 142 gchar *debug;
143 GError *error; 143 GError *error;
144 144
145 gst_message_parse_error(msg, &error, &debug); 145 gst_message_parse_error (msg, &error, &debug);
146 g_free(debug); 146 g_free (debug);
147 147
148 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, 148 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
149 "Error: %s\n", 149 "Error: %s\n",
150 error->message); 150 error->message);
151 g_error_free(error); 151 g_error_free (error);
152 152
153 quit(); 153 quit ();
154 break; 154 break;
155 } 155 }
156 156
157 default: 157 default:
158 break; 158 break;
159 } 159 }
160 160
161 return TRUE; 161 return TRUE;
162} 162}
163 163
164 164
165static void 165static void
166signalhandler(int s) 166signalhandler (int s)
167{ 167{
168 quit(); 168 quit ();
169} 169}
170 170
171 171
172static int 172static int
173feed_buffer_to_gst(const char *audio, size_t b_len) 173feed_buffer_to_gst (const char *audio, size_t b_len)
174{ 174{
175 GstBuffer *b; 175 GstBuffer *b;
176 gchar *bufspace; 176 gchar *bufspace;
177 GstFlowReturn flow; 177 GstFlowReturn flow;
178 178
179 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 179 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
180 "Feeding %u bytes to GStreamer\n", 180 "Feeding %u bytes to GStreamer\n",
181 (unsigned int)b_len); 181 (unsigned int) b_len);
182 182
183 bufspace = g_memdup(audio, b_len); 183 bufspace = g_memdup (audio, b_len);
184 b = gst_buffer_new_wrapped(bufspace, b_len); 184 b = gst_buffer_new_wrapped (bufspace, b_len);
185 if (NULL == b) 185 if (NULL == b)
186 { 186 {
187 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 187 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
188 "Failed to wrap a buffer\n"); 188 "Failed to wrap a buffer\n");
189 g_free(bufspace); 189 g_free (bufspace);
190 return GNUNET_SYSERR; 190 return GNUNET_SYSERR;
191 } 191 }
192 flow = gst_app_src_push_buffer(GST_APP_SRC(source), b); 192 flow = gst_app_src_push_buffer (GST_APP_SRC (source), b);
193 /* They all return GNUNET_OK, because currently player stops when 193 /* They all return GNUNET_OK, because currently player stops when
194 * data stops coming. This might need to be changed for the player 194 * data stops coming. This might need to be changed for the player
195 * to also stop when pipeline breaks. 195 * to also stop when pipeline breaks.
196 */ 196 */
197 switch (flow) 197 switch (flow)
198 { 198 {
199 case GST_FLOW_OK: 199 case GST_FLOW_OK:
200 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 200 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
201 "Fed %u bytes to the pipeline\n", 201 "Fed %u bytes to the pipeline\n",
202 (unsigned int)b_len); 202 (unsigned int) b_len);
203 break; 203 break;
204 204
205 case GST_FLOW_FLUSHING: 205 case GST_FLOW_FLUSHING:
206 /* buffer was dropped, because pipeline state is not PAUSED or PLAYING */ 206 /* buffer was dropped, because pipeline state is not PAUSED or PLAYING */
207 GNUNET_log(GNUNET_ERROR_TYPE_INFO, 207 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
208 "Dropped a buffer\n"); 208 "Dropped a buffer\n");
209 break; 209 break;
210 210
211 case GST_FLOW_EOS: 211 case GST_FLOW_EOS:
212 /* end of stream */ 212 /* end of stream */
213 GNUNET_log(GNUNET_ERROR_TYPE_INFO, 213 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
214 "EOS\n"); 214 "EOS\n");
215 break; 215 break;
216 216
217 default: 217 default:
218 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, 218 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
219 "Unexpected push result\n"); 219 "Unexpected push result\n");
220 break; 220 break;
221 } 221 }
222 return GNUNET_OK; 222 return GNUNET_OK;
223} 223}
224 224
@@ -232,30 +232,30 @@ feed_buffer_to_gst(const char *audio, size_t b_len)
232 * #GNUNET_SYSERR to stop further processing due to error 232 * #GNUNET_SYSERR to stop further processing due to error
233 */ 233 */
234static int 234static int
235stdin_receiver(void *cls, 235stdin_receiver (void *cls,
236 const struct GNUNET_MessageHeader *msg) 236 const struct GNUNET_MessageHeader *msg)
237{ 237{
238 struct AudioMessage *audio; 238 struct AudioMessage *audio;
239 size_t b_len; 239 size_t b_len;
240 240
241 switch (ntohs(msg->type)) 241 switch (ntohs (msg->type))
242 { 242 {
243 case GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO: 243 case GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO:
244 audio = (struct AudioMessage *)msg; 244 audio = (struct AudioMessage *) msg;
245 245
246 b_len = ntohs(audio->header.size) - sizeof(struct AudioMessage); 246 b_len = ntohs (audio->header.size) - sizeof(struct AudioMessage);
247 feed_buffer_to_gst((const char *)&audio[1], b_len); 247 feed_buffer_to_gst ((const char *) &audio[1], b_len);
248 break; 248 break;
249 249
250 default: 250 default:
251 break; 251 break;
252 } 252 }
253 return GNUNET_OK; 253 return GNUNET_OK;
254} 254}
255 255
256 256
257int 257int
258main(int argc, char **argv) 258main (int argc, char **argv)
259{ 259{
260 GstBus *bus; 260 GstBus *bus;
261 guint bus_watch_id; 261 guint bus_watch_id;
@@ -265,140 +265,141 @@ main(int argc, char **argv)
265 265
266 SignalHandlerPointer inthandler, termhandler; 266 SignalHandlerPointer inthandler, termhandler;
267#ifdef DEBUG_READ_PURE_OGG 267#ifdef DEBUG_READ_PURE_OGG
268 int read_pure_ogg = getenv("GNUNET_READ_PURE_OGG") ? 1 : 0; 268 int read_pure_ogg = getenv ("GNUNET_READ_PURE_OGG") ? 1 : 0;
269#endif 269#endif
270 270
271 inthandler = signal(SIGINT, 271 inthandler = signal (SIGINT,
272 &signalhandler);
273 termhandler = signal(SIGTERM,
274 &signalhandler); 272 &signalhandler);
273 termhandler = signal (SIGTERM,
274 &signalhandler);
275 275
276 /* Initialisation */ 276 /* Initialisation */
277 gst_init(&argc, &argv); 277 gst_init (&argc, &argv);
278 278
279 GNUNET_assert(GNUNET_OK == 279 GNUNET_assert (GNUNET_OK ==
280 GNUNET_log_setup("gnunet-helper-audio-playback-gst", 280 GNUNET_log_setup ("gnunet-helper-audio-playback-gst",
281 "WARNING", 281 "WARNING",
282 NULL)); 282 NULL));
283 283
284 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 284 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
285 "Audio sink starts\n"); 285 "Audio sink starts\n");
286 286
287 stdin_mst = GNUNET_MST_create(&stdin_receiver, 287 stdin_mst = GNUNET_MST_create (&stdin_receiver,
288 NULL); 288 NULL);
289 289
290 /* Create gstreamer elements */ 290 /* Create gstreamer elements */
291 pipeline = gst_pipeline_new("audio-player"); 291 pipeline = gst_pipeline_new ("audio-player");
292 source = gst_element_factory_make("appsrc", "audio-input"); 292 source = gst_element_factory_make ("appsrc", "audio-input");
293 demuxer = gst_element_factory_make("oggdemux", "ogg-demuxer"); 293 demuxer = gst_element_factory_make ("oggdemux", "ogg-demuxer");
294 decoder = gst_element_factory_make("opusdec", "opus-decoder"); 294 decoder = gst_element_factory_make ("opusdec", "opus-decoder");
295 conv = gst_element_factory_make("audioconvert", "converter"); 295 conv = gst_element_factory_make ("audioconvert", "converter");
296 resampler = gst_element_factory_make("audioresample", "resampler"); 296 resampler = gst_element_factory_make ("audioresample", "resampler");
297 sink = gst_element_factory_make("autoaudiosink", "audiosink"); 297 sink = gst_element_factory_make ("autoaudiosink", "audiosink");
298 298
299 if (!pipeline || !source || !conv || !resampler || !decoder || !demuxer || !sink) 299 if (! pipeline || ! source || ! conv || ! resampler || ! decoder ||
300 { 300 ! demuxer || ! sink)
301 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, 301 {
302 "One element could not be created. Exiting.\n"); 302 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
303 return -1; 303 "One element could not be created. Exiting.\n");
304 } 304 return -1;
305 305 }
306 g_signal_connect(sink, 306
307 "child-added", 307 g_signal_connect (sink,
308 G_CALLBACK(sink_child_added), 308 "child-added",
309 NULL); 309 G_CALLBACK (sink_child_added),
310 g_signal_connect(demuxer, 310 NULL);
311 "pad-added", 311 g_signal_connect (demuxer,
312 G_CALLBACK(ogg_pad_added), 312 "pad-added",
313 decoder); 313 G_CALLBACK (ogg_pad_added),
314 decoder);
314 315
315 /* Keep a reference to it, we operate on it */ 316 /* Keep a reference to it, we operate on it */
316 gst_object_ref(GST_OBJECT(source)); 317 gst_object_ref (GST_OBJECT (source));
317 318
318 /* Set up the pipeline */ 319 /* Set up the pipeline */
319 320
320 /* we feed appsrc as fast as possible, it just blocks when it's full */ 321 /* we feed appsrc as fast as possible, it just blocks when it's full */
321 g_object_set(G_OBJECT(source), 322 g_object_set (G_OBJECT (source),
322/* "format", GST_FORMAT_TIME,*/ 323/* "format", GST_FORMAT_TIME,*/
323 "block", TRUE, 324 "block", TRUE,
324 "is-live", TRUE, 325 "is-live", TRUE,
325 NULL); 326 NULL);
326 327
327 g_object_set(G_OBJECT(decoder), 328 g_object_set (G_OBJECT (decoder),
328/* "plc", FALSE,*/ 329/* "plc", FALSE,*/
329/* "apply-gain", TRUE,*/ 330/* "apply-gain", TRUE,*/
330 "use-inband-fec", TRUE, 331 "use-inband-fec", TRUE,
331 NULL); 332 NULL);
332 333
333 /* we add a message handler */ 334 /* we add a message handler */
334 bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline)); 335 bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
335 bus_watch_id = gst_bus_add_watch(bus, bus_call, pipeline); 336 bus_watch_id = gst_bus_add_watch (bus, bus_call, pipeline);
336 gst_object_unref(bus); 337 gst_object_unref (bus);
337 338
338 /* we add all elements into the pipeline */ 339 /* we add all elements into the pipeline */
339 /* audio-input | ogg-demuxer | opus-decoder | converter | resampler | audiosink */ 340 /* audio-input | ogg-demuxer | opus-decoder | converter | resampler | audiosink */
340 gst_bin_add_many(GST_BIN(pipeline), source, demuxer, decoder, conv, 341 gst_bin_add_many (GST_BIN (pipeline), source, demuxer, decoder, conv,
341 resampler, sink, NULL); 342 resampler, sink, NULL);
342 343
343 /* we link the elements together */ 344 /* we link the elements together */
344 gst_element_link_many(source, demuxer, NULL); 345 gst_element_link_many (source, demuxer, NULL);
345 346
346 /* Set the pipeline to "playing" state*/ 347 /* Set the pipeline to "playing" state*/
347 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Now playing\n"); 348 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Now playing\n");
348 gst_element_set_state(pipeline, GST_STATE_PLAYING); 349 gst_element_set_state (pipeline, GST_STATE_PLAYING);
349 350
350 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Running...\n"); 351 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Running...\n");
351 /* Iterate */ 352 /* Iterate */
352 toff = 0; 353 toff = 0;
353 while (!abort_read) 354 while (! abort_read)
355 {
356 char readbuf[MAXLINE];
357 int ret;
358
359 ret = read (0, readbuf, sizeof(readbuf));
360 if (0 > ret)
354 { 361 {
355 char readbuf[MAXLINE]; 362 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
356 int ret; 363 _ ("Read error from STDIN: %d %s\n"),
357 364 ret, strerror (errno));
358 ret = read(0, readbuf, sizeof(readbuf)); 365 break;
359 if (0 > ret) 366 }
360 { 367 toff += ret;
361 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, 368 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
362 _("Read error from STDIN: %d %s\n"), 369 "Received %d bytes of audio data (total: %llu)\n",
363 ret, strerror(errno)); 370 (int) ret,
364 break; 371 (unsigned long long) toff);
365 } 372 if (0 == ret)
366 toff += ret; 373 break;
367 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
368 "Received %d bytes of audio data (total: %llu)\n",
369 (int)ret,
370 (unsigned long long)toff);
371 if (0 == ret)
372 break;
373#ifdef DEBUG_READ_PURE_OGG 374#ifdef DEBUG_READ_PURE_OGG
374 if (read_pure_ogg) 375 if (read_pure_ogg)
375 { 376 {
376 feed_buffer_to_gst(readbuf, ret); 377 feed_buffer_to_gst (readbuf, ret);
377 }
378 else
379#endif
380 GNUNET_MST_from_buffer(stdin_mst,
381 readbuf,
382 ret,
383 GNUNET_NO,
384 GNUNET_NO);
385 } 378 }
386 GNUNET_MST_destroy(stdin_mst); 379 else
387 380#endif
388 signal(SIGINT, inthandler); 381 GNUNET_MST_from_buffer (stdin_mst,
389 signal(SIGINT, termhandler); 382 readbuf,
390 383 ret,
391 GNUNET_log(GNUNET_ERROR_TYPE_INFO, 384 GNUNET_NO,
392 "Returned, stopping playback\n"); 385 GNUNET_NO);
393 quit(); 386 }
394 387 GNUNET_MST_destroy (stdin_mst);
395 GNUNET_log(GNUNET_ERROR_TYPE_INFO, 388
396 "Deleting pipeline\n"); 389 signal (SIGINT, inthandler);
397 gst_object_unref(GST_OBJECT(source)); 390 signal (SIGINT, termhandler);
391
392 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
393 "Returned, stopping playback\n");
394 quit ();
395
396 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
397 "Deleting pipeline\n");
398 gst_object_unref (GST_OBJECT (source));
398 source = NULL; 399 source = NULL;
399 gst_object_unref(GST_OBJECT(pipeline)); 400 gst_object_unref (GST_OBJECT (pipeline));
400 pipeline = NULL; 401 pipeline = NULL;
401 g_source_remove(bus_watch_id); 402 g_source_remove (bus_watch_id);
402 403
403 return 0; 404 return 0;
404} 405}