GNUnet  0.19.5
gnunet_gst.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2016 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
25 #include "platform.h"
26 #include "gnunet_gst_def.h"
27 
32 
33 
34 void
35 dump_buffer (unsigned n, const unsigned char*buf)
36 {
37  const unsigned char *p, *end;
38  unsigned i, j;
39 
40  end = buf + n;
41 
42  for (i = 0;; i += 16)
43  {
44  p = buf + i;
45  for (j = 0; j < 16; j++)
46  {
47  fprintf (stderr, "%02X ", p[j]);
48  if (p + j >= end)
49  goto BREAKOUT;
50  }
51  fprintf (stderr, " ");
52  p = buf + i;
53  for (j = 0; j < 16; j++)
54  {
55  fprintf (stderr, "%c", isprint (p[j]) ? p[j] :
56  '.');
57  if (p + j >= end)
58  goto BREAKOUT;
59  }
60  fprintf (stderr, "\n");
61  }
62 BREAKOUT:
63  return;
64 }
65 
66 
67 /***
68  * load gnunet configuration
69  */
70 void
72 {
73  char *audiobackend_string;
74 
76  GNUNET_CONFIGURATION_load (cfg, "mediahelper.conf");
77 
78  GNUNET_CONFIGURATION_get_value_string (cfg, "MEDIAHELPER", "JACK_PP_IN",
79  &d->jack_pp_in);
80  GNUNET_CONFIGURATION_get_value_string (cfg, "MEDIAHELPER", "JACK_PP_OUT",
81  &d->jack_pp_out);
82 
83  GNUNET_CONFIGURATION_get_value_string (cfg, "MEDIAHELPER", "AUDIOBACKEND",
84  &audiobackend_string);
85 
86  // printf("abstring: %s \n", audiobackend_string);
87 
88  if (0 == strcasecmp (audiobackend_string, "AUTO"))
89  {
90  d->audiobackend = AUTO;
91  }
92  else if (0 == strcasecmp (audiobackend_string, "JACK"))
93  {
94  d->audiobackend = JACK;
95  }
96  else if (0 == strcasecmp (audiobackend_string, "ALSA"))
97  {
98  d->audiobackend = ALSA;
99  }
100  else if (0 == strcasecmp (audiobackend_string, "FAKE"))
101  {
102  d->audiobackend = FAKE;
103  }
104  else if (0 == strcasecmp (audiobackend_string, "TEST"))
105  {
106  d->audiobackend = TEST;
107  }
108  else
109  {
110  d->audiobackend = AUTO;
111  }
112 
113  if (GNUNET_CONFIGURATION_get_value_yesno (cfg, "MEDIAHELPER",
114  "REMOVESILENCE") == GNUNET_YES)
115  {
116  d->dropsilence = TRUE;
117  }
118  else
119  {
120  d->dropsilence = FALSE;
121  }
122 
123  if (GNUNET_CONFIGURATION_get_value_yesno (cfg, "MEDIAHELPER",
124  "NO_GN_HEADERS") == GNUNET_YES)
125  {
126  d->pure_ogg = TRUE;
127  }
128  else
129  {
130  d->pure_ogg = FALSE;
131  }
132 
133 
134  if (GNUNET_CONFIGURATION_get_value_yesno (cfg, "MEDIAHELPER", "USERTP") ==
135  GNUNET_YES)
136  {
137  d->usertp = TRUE;
138  }
139  else
140  {
141  d->usertp = FALSE;
142  }
143 
144 // GNUNET_CONFIGURATION_write(cfg, "mediahelper.conf");
145 }
146 
147 
148 static void
149 write_data (const char *ptr, size_t msg_size)
150 {
151  ssize_t ret;
152  size_t off;
153 
154  off = 0;
155  while (off < msg_size)
156  {
157  ret = write (1, &ptr[off], msg_size - off);
158  if (0 >= ret)
159  {
160  if (-1 == ret)
162 // quit (2);
163  }
164  off += ret;
165  }
166 }
167 
168 
169 extern GstFlowReturn
170 on_appsink_new_sample (GstElement *element, GNUNET_gstData *d)
171 {
172  // size of message including gnunet header
173  size_t msg_size;
174 
175  GstSample *s;
176  GstBuffer *b;
177  GstMapInfo map;
178 
179 /*
180  const GstStructure *si;
181  char *si_str;
182  GstCaps *s_caps;
183  char *caps_str;
184  */if (gst_app_sink_is_eos (GST_APP_SINK (element)))
185  return GST_FLOW_OK;
186 
187  // pull sample from appsink
188  s = gst_app_sink_pull_sample (GST_APP_SINK (element));
189 
190  if (s == NULL)
191  return GST_FLOW_OK;
192 
193  if (! GST_IS_SAMPLE (s))
194  return GST_FLOW_OK;
195 
196  b = gst_sample_get_buffer (s);
197 
198  GST_WARNING ("caps are %" GST_PTR_FORMAT, gst_sample_get_caps (s));
199 
200 
201  gst_buffer_map (b, &map, GST_MAP_READ);
202 
203  size_t len;
204  len = map.size;
205  if (len > UINT16_MAX - sizeof(struct AudioMessage))
206  {
207  // this should never happen?
208  printf ("GSTREAMER sample too big! \n");
209  exit (20);
210  len = UINT16_MAX - sizeof(struct AudioMessage);
211  }
212 
213  msg_size = sizeof(struct AudioMessage) + len;
214 
215  // copy the data into audio_message
216  GNUNET_memcpy (((char *) &(d->audio_message)[1]), map.data, len);
217  (d->audio_message)->header.size = htons ((uint16_t) msg_size);
218  if (d->pure_ogg)
219  // write the audio_message without the gnunet headers
220  write_data ((const char *) &(d->audio_message)[1], len);
221  else
222  write_data ((const char *) d->audio_message, msg_size);
223 
224  gst_sample_unref (s);
225  return GST_FLOW_OK;
226 }
227 
228 
229 /***
230  * Dump a pipeline graph
231  */
232 extern void
233 pl_graph (GstElement *pipeline)
234 {
235 #ifdef IS_SPEAKER
236  gst_debug_bin_to_dot_file_with_ts (GST_BIN (pipeline),
237  GST_DEBUG_GRAPH_SHOW_ALL,
238  "playback_helper.dot");
239 #endif
240 #ifdef IS_MIC
241  gst_debug_bin_to_dot_file_with_ts (GST_BIN (pipeline),
242  GST_DEBUG_GRAPH_SHOW_ALL,
243  "record_helper.dot");
244 #endif
245 
246 
247  // load_configuration();
248 }
249 
250 
251 extern gboolean
252 gnunet_gst_bus_call (GstBus *bus, GstMessage *msg, gpointer data)
253 {
255  "Bus message\n");
256  switch (GST_MESSAGE_TYPE (msg))
257  {
258  case GST_MESSAGE_EOS:
260  "End of stream\n");
261  exit (10);
262  break;
263 
264  case GST_MESSAGE_ERROR:
265  {
266  gchar *debug;
267  GError *error;
268 
269  gst_message_parse_error (msg, &error, &debug);
270  g_free (debug);
271 
273  "Error: %s\n",
274  error->message);
275  g_error_free (error);
276 
277  exit (10);
278  break;
279  }
280 
281  default:
282  break;
283  }
284 
285  return TRUE;
286 }
287 
288 
289 /* called when pipeline changes state */
290 extern void
291 state_changed_cb (GstBus *bus, GstMessage *msg, GNUNET_gstData *d)
292 {
293  GstState old_state, new_state, pending_state;
294 
295  gst_message_parse_state_changed (msg, &old_state, &new_state,
296  &pending_state);
297  switch (new_state)
298  {
299  case GST_STATE_READY:
300 // printf("ready.... \n");
301  // pl_graph(GST_ELEMENT(d->pipeline));
302  break;
303 
304  case GST_STATE_PLAYING:
305 
306  // GST_LOG ("caps are %" GST_PTR_FORMAT, caps);
307 
308  // printf("Playing.... \n");
309  pl_graph (GST_ELEMENT (d->pipeline));
310  break;
311 
312  case GST_STATE_VOID_PENDING:
313  // printf("void_pending.... \n");
314  // pl_graph(GST_ELEMENT(d->pipeline));
315  break;
316 
317  case GST_STATE_NULL:
318  // printf("null.... \n");
319  // pl_graph(GST_ELEMENT(d->pipeline));
320  break;
321 
322  case GST_STATE_PAUSED:
323  // printf("paused.... \n");
324  // pl_graph(GST_ELEMENT(d->pipeline));
325  break;
326  }
327 }
328 
329 
330 static void
331 application_cb (GstBus *bus, GstMessage *msg, GNUNET_gstData *data)
332 {
333  // printf("application cb");
334  return;
335 }
336 
337 
338 static void
339 error_cb (GstBus *bus, GstMessage *msg, GNUNET_gstData *data)
340 {
341  // printf("error cb");
342  return;
343 }
344 
345 
346 static void
347 eos_cb (GstBus *bus, GstMessage *msg, GNUNET_gstData *data)
348 {
349  // printf("eos cb");
350  return;
351 }
352 
353 
354 extern void
356 {
357  GstBus *bus;
358 
359  bus = gst_element_get_bus (GST_ELEMENT (d->pipeline));
360  gst_bus_add_signal_watch (bus);
361  g_signal_connect (G_OBJECT (bus), "message::error", (GCallback) error_cb,
362  d);
363  g_signal_connect (G_OBJECT (bus), "message::eos", (GCallback) eos_cb,
364  d);
365  g_signal_connect (G_OBJECT (bus), "message::state-changed",
366  (GCallback) state_changed_cb, d);
367  g_signal_connect (G_OBJECT (bus), "message::application",
368  (GCallback) application_cb, d);
369  g_signal_connect (G_OBJECT (bus), "message::about-to-finish",
370  (GCallback) application_cb, d);
371  gst_object_unref (bus);
372 }
373 
374 
375 /*
376  * take buffer from gstreamer and feed it to gnunet
377  */
378 /*
379  extern int
380  feed_buffer_to_gnunet (GNUNET_gstData * d)
381  {
382  GstSample *s;
383  GstBuffer *b;
384  GstMapInfo m;
385  size_t len, msg_size;
386  const char *ptr;
387  int phase;
388 
389  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pulling...\n");
390  s = gst_app_sink_pull_sample (GST_APP_SINK(d->appsink));
391  if (NULL == s)
392  {
393  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pulled NULL\n");
394  return OK;
395  }
396  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "...pulled!\n");
397 
398  const GstStructure *si;
399  char *si_str;
400  GstCaps *s_caps;
401  char *caps_str;
402  si = gst_sample_get_info (s);
403  if (si)
404  {
405  si_str = gst_structure_to_string (si);
406  if (si_str)
407  {
408  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample %s\n", si_str);
409  g_free (si_str);
410  }
411  }
412  else
413  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample with no info\n");
414  s_caps = gst_sample_get_caps (s);
415  if (s_caps)
416  {
417  caps_str = gst_caps_to_string (s_caps);
418  if (caps_str)
419  {
420  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample with caps %s\n", caps_str);
421  g_free (caps_str);
422  }
423  }
424  else
425  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample with no caps\n");
426 
427  b = gst_sample_get_buffer (s);
428  if (NULL == b || !gst_buffer_map (b, &m, GST_MAP_READ))
429  {
430  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got NULL buffer %p or failed to map the buffer\n", b);
431  gst_sample_unref (s);
432  return FAIL;
433  }
434 
435  len = m.size;
436  if (len > UINT16_MAX - sizeof (struct AudioMessage))
437  {
438  GNUNET_break (0);
439  len = UINT16_MAX - sizeof (struct AudioMessage);
440  }
441  msg_size = sizeof (struct AudioMessage) + len;
442  audio_message.header.size = htons ((uint16_t) msg_size);
443 
444 
445  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
446  "Sending %u bytes of audio data\n", (unsigned int) msg_size);
447  for (phase = 0; phase < 2; phase++)
448  {
449  size_t offset;
450  size_t to_send;
451  ssize_t ret;
452  if (0 == phase && !d->pure_ogg)
453  {
454  //#ifdef DEBUG_RECORD_PURE_OGG
455 
456  // if (d->pure_ogg)
457  // break;
458 
459  //#endif
460  ptr = (const char *) &audio_message;
461  to_send = sizeof (audio_message);
462  }
463  else
464  {
465  ptr = (const char *) m.data;
466  to_send = len;
467  }
468  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
469  "Sending %u bytes on phase %d\n", (unsigned int) to_send, phase);
470  for (offset = 0; offset < to_send; offset += ret)
471  {
472  ret = write (1, &ptr[offset], to_send - offset);
473  if (0 >= ret)
474  {
475  if (-1 == ret)
476  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
477  "Failed to write %u bytes at offset %u (total %u) in phase %d: %s\n",
478  (unsigned int) to_send - offset, (unsigned int) offset,
479  (unsigned int) (to_send + offset), phase, strerror (errno));
480  // abort_send = 1;
481  return FAIL;
482  }
483  }
484 
485  // if (abort_send)
486  // break;
487 
488  }
489  gst_buffer_unmap (b, &m);
490  gst_sample_unref (s);
491  }
492  */
493 
494 
495 extern int
496 feed_buffer_to_gst (const char *audio, size_t b_len, GNUNET_gstData *d)
497 {
498  GstBuffer *b;
499  gchar *bufspace;
500  GstFlowReturn flow;
501 
503  "Feeding %u bytes to GStreamer\n",
504  (unsigned int) b_len);
505 
506  bufspace = g_memdup (audio, b_len);
507  b = gst_buffer_new_wrapped (bufspace, b_len);
508  if (NULL == b)
509  {
511  "Failed to wrap a buffer\n");
512  g_free (bufspace);
513  return GNUNET_SYSERR;
514  }
515  if (GST_APP_SRC (d->appsrc) == NULL)
516  exit (10);
517  flow = gst_app_src_push_buffer (GST_APP_SRC (d->appsrc), b);
518  /* They all return GNUNET_OK, because currently player stops when
519  * data stops coming. This might need to be changed for the player
520  * to also stop when pipeline breaks.
521  */
522  switch (flow)
523  {
524  case GST_FLOW_OK:
526  "Fed %u bytes to the pipeline\n",
527  (unsigned int) b_len);
528  break;
529 
530  case GST_FLOW_FLUSHING:
531  /* buffer was dropped, because pipeline state is not PAUSED or PLAYING */
533  "Dropped a buffer\n");
534  break;
535 
536  case GST_FLOW_EOS:
537  /* end of stream */
539  "EOS\n");
540  break;
541 
542  default:
544  "Unexpected push result\n");
545  break;
546  }
547  return GNUNET_OK;
548 }
549 
550 
554 extern GstElement *
555 gst_element_factory_make_debug (gchar *factoryname, gchar *name)
556 {
557  GstElement *element;
558 
559  element = gst_element_factory_make (factoryname, name);
560 
561  if (element == NULL)
562  {
563  printf ("\n Failed to create element - type: %s name: %s \n", factoryname,
564  name);
565  exit (10);
566  return element;
567  }
568  else
569  {
570  return element;
571  }
572 }
573 
574 
575 /*
576  static gboolean
577  gst_element_link_many_debug(...)
578  {
579  va_list arguments;
580  gst_element_link_many(argptr);
581  }
582 
583  #define gst_element_link_many(...) \
584  gst_element_link_many_debug(__VA_ARGS__)
585  */
586 extern void
587 lf (char *msg)
588 {
589  printf ("linking elements failed: %s", msg);
590  exit (10);
591 }
592 
593 
594 /***
595  * used to set properties on autoaudiosink's chosen sink
596  */
597 static void
598 autoaudiosink_child_added (GstChildProxy *child_proxy,
599  GObject *object,
600  gchar *name,
601  gpointer user_data)
602 {
603  if (GST_IS_AUDIO_BASE_SRC (object))
604  g_object_set (object,
605  "buffer-time", (gint64) BUFFER_TIME,
606  "latency-time", (gint64) LATENCY_TIME,
607  NULL);
608 }
609 
610 
611 /***
612  * used to set properties on autoaudiosource's chosen sink
613  */
614 static void
615 autoaudiosource_child_added (GstChildProxy *child_proxy, GObject *object,
616  gchar *name, gpointer user_data)
617 {
618  if (GST_IS_AUDIO_BASE_SRC (object))
619  g_object_set (object, "buffer-time", (gint64) BUFFER_TIME, "latency-time",
620  (gint64) LATENCY_TIME, NULL);
621 }
622 
623 
624 GstElement *
625 get_pipeline (GstElement *element)
626 {
627  GstPipeline *p;
628 
629  p = GST_PIPELINE (gst_object_get_parent (GST_OBJECT (element)));
630 
631  return GST_ELEMENT (p);
632 }
633 
634 
635 static void
636 decoder_ogg_pad_added (GstElement *element,
637  GstPad *pad,
638  gpointer data)
639 {
640  GstPad *sinkpad;
641  GstElement *decoder = (GstElement *) data;
642 
643  printf ("==== ogg pad added callback \n");
644  /* We can now link this pad with the opus-decoder sink pad */
645 // pl_graph(get_pipeline(element));
646  sinkpad = gst_element_get_static_pad (decoder, "sink");
647 
648  gst_pad_link (pad, sinkpad);
649  gst_element_link_many (element, decoder, NULL);
650  gst_object_unref (sinkpad);
651 }
652 
653 
654 int
656 {
657  char readbuf[MAXLINE];
658  int ret;
659 
660  printf ("read \n");
661  ret = read (0, readbuf, sizeof(readbuf));
662  if (0 > ret)
663  {
665  _ ("Read error from STDIN: %d %s\n"),
666  ret, strerror (errno));
667  return FAIL;
668  }
669  // toff += ret;
671  "Received %d bytes of audio data\n",
672  (int) ret);
673  if (0 == ret)
674  return FAIL;
675  // #ifdef DEBUG_READ_PURE_OGG
676 
677  if (d->pure_ogg)
678  {
679  feed_buffer_to_gst (readbuf, ret, d);
680  }
681  else
682  {
683  // #endif
685  readbuf,
686  ret,
687  GNUNET_NO,
688  GNUNET_NO);
689  }
690  return 0;
691 }
692 
693 
702 static int
703 stdin_receiver (void *cls,
704  const struct GNUNET_MessageHeader *msg)
705 {
706  struct AudioMessage *audio;
707  size_t b_len;
708 
709  printf ("stdin receiver \n ");
710  dump_buffer (sizeof(msg),
711  (const unsigned char *) msg);
712 
713  switch (ntohs (msg->type))
714  {
716  audio = (struct AudioMessage *) msg;
717 
718  b_len = ntohs (audio->header.size) - sizeof(struct AudioMessage);
719  printf ("feeding buffer to gst \n ");
720  feed_buffer_to_gst ((const char *) &audio[1], b_len, cls);
721  break;
722 
723  default:
724  printf ("No audio message: %u \n ", ntohs (msg->type));
725  break;
726  }
727  return GNUNET_OK;
728 }
729 
730 
731 GstBin *
733 {
734  GstBin *bin;
735  GstPad *pad, *ghostpad;
736 
737  if (type == SOURCE)
738  {
739  bin = GST_BIN (gst_bin_new ("Gnunet appsrc"));
740 
741 
743  GNUNET_log_setup ("gnunet-helper-audio-playback",
744  "WARNING",
745  NULL));
746 
748  "Audio playback starts\n");
749  printf (" creating appsrc \n ");
750  // d->audio_message.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO);
751 
752 // d->audio_message = GNUNET_malloc (UINT16_MAX);
753 // d->audio_message = (AudioMessage*)malloc(sizeof(struct AudioMessage));
754 // d->audio_message = GNUNET_malloc(sizeof(struct AudioMessage));
755 
756 
757  // d->audio_message.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO);
758 
759 
761 
762  if (d->stdin_mst == NULL)
763  printf ("stdin_mst = NULL");
764 
765  d->appsrc = gst_element_factory_make ("appsrc", "appsrc");
766 
767  gst_bin_add_many (bin, d->appsrc, NULL);
768 // gst_element_link_many ( encoder, muxer, NULL);
769 
770  pad = gst_element_get_static_pad (d->appsrc, "src");
771  ghostpad = gst_ghost_pad_new ("src", pad);
772  }
773  if (type == SINK)
774  {
775  bin = GST_BIN (gst_bin_new ("Gnunet appsink"));
776 
777 
779  GNUNET_log_setup ("gnunet-helper-audio-record",
780  "WARNING",
781  NULL));
782 
784  "Audio source starts\n");
785 
786  d->appsink = gst_element_factory_make ("appsink", "appsink");
787 
788  // Move this out of here!
789  d->audio_message = GNUNET_malloc (UINT16_MAX);
790  (d->audio_message)->header.type = htons (
792  g_object_set (G_OBJECT (d->appsink), "emit-signals", TRUE, "sync", TRUE,
793  NULL);
794 
795  g_signal_connect (d->appsink, "new-sample",
796  G_CALLBACK (on_appsink_new_sample), &d);
797 
798  gst_bin_add_many (bin, d->appsink, NULL);
799 // gst_element_link_many ( encoder, muxer, NULL);
800 
801  pad = gst_element_get_static_pad (d->appsink, "sink");
802  ghostpad = gst_ghost_pad_new ("sink", pad);
803  }
804 
805  /* set the bin pads */
806  gst_pad_set_active (ghostpad, TRUE);
807  gst_element_add_pad (GST_ELEMENT (bin), ghostpad);
808 
809  gst_object_unref (pad);
810 
811  return bin;
812 }
813 
814 
815 extern GstBin *
817 {
818  GstBin *bin;
819  GstPad *srcpad, *sinkpad, *srcghostpad, *sinkghostpad;
820  GstCaps *rtpcaps;
821  GstElement *encoder, *muxer, *decoder, *demuxer, *jitterbuffer,
822  *rtpcapsfilter;
823 
824  if (d->usertp == TRUE)
825  {
826  /*
827  * application/x-rtp, media=(string)audio, clock-rate=(int)48000, encoding-name=(string)OPUS, sprop-maxcapturerate=(string)48000, sprop-stereo=(string)0, payload=(int)96, encoding-params=(string)2, ssrc=(uint)630297634, timestamp-offset=(uint)678334141, seqnum-offset=(uint)16938 */
828 /*
829  rtpcaps = gst_caps_new_simple ("application/x-rtp",
830  "media", G_TYPE_STRING, "audio",
831  "clock-rate", G_TYPE_INT, SAMPLING_RATE,
832  "encoding-name", G_TYPE_STRING, "OPUS",
833  "payload", G_TYPE_INT, 96,
834  "sprop-stereo", G_TYPE_STRING, "0",
835  "encoding-params", G_TYPE_STRING, "2",
836  NULL);
837  */ rtpcaps = gst_caps_new_simple ("application/x-rtp",
838  "media", G_TYPE_STRING, "audio",
839  "clock-rate", G_TYPE_INT, SAMPLING_RATE,
840  "encoding-name", G_TYPE_STRING, "OPUS",
841  "payload", G_TYPE_INT, 96,
842  "sprop-stereo", G_TYPE_STRING, "0",
843  "encoding-params", G_TYPE_STRING, "2",
844  NULL);
845 
846 
847  rtpcapsfilter = gst_element_factory_make ("capsfilter", "rtpcapsfilter");
848 
849  g_object_set (G_OBJECT (rtpcapsfilter),
850  "caps", rtpcaps,
851  NULL);
852  gst_caps_unref (rtpcaps);
853  }
854 
855 
856  if (type == ENCODER)
857  {
858  bin = GST_BIN (gst_bin_new ("Gnunet audioencoder"));
859 
860  encoder = gst_element_factory_make ("opusenc", "opus-encoder");
861  if (d->usertp == TRUE)
862  {
863  muxer = gst_element_factory_make ("rtpopuspay", "rtp-payloader");
864  }
865  else
866  {
867  muxer = gst_element_factory_make ("oggmux", "ogg-muxer");
868  }
869  g_object_set (G_OBJECT (encoder),
870  /* "bitrate", 64000, */
871  /* "bandwidth", OPUS_BANDWIDTH_FULLBAND, */
872  "inband-fec", INBAND_FEC_MODE,
873  "packet-loss-percentage", PACKET_LOSS_PERCENTAGE,
874  "max-payload-size", MAX_PAYLOAD_SIZE,
875  "audio", TRUE, /* VoIP, not audio */
876  "frame-size", OPUS_FRAME_SIZE,
877  NULL);
878 
879  if (d->usertp != TRUE)
880  {
881  g_object_set (G_OBJECT (muxer),
882  "max-delay", OGG_MAX_DELAY,
883  "max-page-delay", OGG_MAX_PAGE_DELAY,
884  NULL);
885  }
886 
887  gst_bin_add_many (bin, encoder, muxer, NULL);
888  gst_element_link_many (encoder, muxer, NULL);
889  sinkpad = gst_element_get_static_pad (encoder, "sink");
890  sinkghostpad = gst_ghost_pad_new ("sink", sinkpad);
891 
892  srcpad = gst_element_get_static_pad (muxer, "src");
893  srcghostpad = gst_ghost_pad_new ("src", srcpad);
894  }
895  if (type == DECODER)
896  {
897  bin = GST_BIN (gst_bin_new ("Gnunet audiodecoder"));
898 
899  // decoder
900  if (d->usertp == TRUE)
901  {
902  demuxer = gst_element_factory_make ("rtpopusdepay", "ogg-demuxer");
903  jitterbuffer = gst_element_factory_make ("rtpjitterbuffer",
904  "rtpjitterbuffer");
905  }
906  else
907  {
908  demuxer = gst_element_factory_make ("oggdemux", "ogg-demuxer");
909  }
910  decoder = gst_element_factory_make ("opusdec", "opus-decoder");
911 
912  if (d->usertp == TRUE)
913  {
914  gst_bin_add_many (bin, rtpcapsfilter, jitterbuffer, demuxer, decoder,
915  NULL);
916  gst_element_link_many (rtpcapsfilter, jitterbuffer, demuxer, decoder,
917  NULL);
918  sinkpad = gst_element_get_static_pad (rtpcapsfilter, "sink");
919  }
920  else
921  {
922  gst_bin_add_many (bin, demuxer, decoder, NULL);
923 
924  g_signal_connect (demuxer,
925  "pad-added",
926  G_CALLBACK (decoder_ogg_pad_added),
927  decoder);
928 
929  sinkpad = gst_element_get_static_pad (demuxer, "sink");
930  }
931  sinkghostpad = gst_ghost_pad_new ("sink", sinkpad);
932 
933  srcpad = gst_element_get_static_pad (decoder, "src");
934  srcghostpad = gst_ghost_pad_new ("src", srcpad);
935  }
936 
937  // add pads to the bin
938  gst_pad_set_active (sinkghostpad, TRUE);
939  gst_element_add_pad (GST_ELEMENT (bin), sinkghostpad);
940 
941  gst_pad_set_active (srcghostpad, TRUE);
942  gst_element_add_pad (GST_ELEMENT (bin), srcghostpad);
943 
944 
945  return bin;
946 }
947 
948 
949 extern GstBin *
951 {
952  GstBin *bin;
953  GstElement *sink, *source, *queue, *conv, *resampler, *removesilence, *filter;
954  GstPad *pad, *ghostpad;
955  GstCaps *caps;
956 
957  if (type == SINK)
958  {
959  bin = GST_BIN (gst_bin_new ("Gnunet audiosink"));
960 
961  /* Create all the elements */
962  if (d->dropsilence == TRUE)
963  {
964  queue = gst_element_factory_make ("queue", "queue");
965  removesilence = gst_element_factory_make ("removesilence",
966  "removesilence");
967  }
968 
969  conv = gst_element_factory_make ("audioconvert", "converter");
970  resampler = gst_element_factory_make ("audioresample", "resampler");
971 
972  if (d->audiobackend == AUTO)
973  {
974  sink = gst_element_factory_make ("autoaudiosink", "audiosink");
975  g_signal_connect (sink, "child-added", G_CALLBACK (
977  }
978 
979  if (d->audiobackend == ALSA)
980  {
981  sink = gst_element_factory_make ("alsaaudiosink", "audiosink");
982  }
983 
984  if (d->audiobackend == JACK)
985  {
986  sink = gst_element_factory_make ("jackaudiosink", "audiosink");
987 
988  g_object_set (G_OBJECT (sink), "client-name", "gnunet", NULL);
989 
990  if (g_object_class_find_property
991  (G_OBJECT_GET_CLASS (sink), "port-pattern"))
992  {
993 // char *portpattern = "system";
994 
995  g_object_set (G_OBJECT (sink), "port-pattern", d->jack_pp_out,
996  NULL);
997  }
998  }
999 
1000  if (d->audiobackend == FAKE)
1001  {
1002  sink = gst_element_factory_make ("fakesink", "audiosink");
1003  }
1004 
1005  g_object_set (sink,
1006  "buffer-time", (gint64) BUFFER_TIME,
1007  "latency-time", (gint64) LATENCY_TIME,
1008  NULL);
1009 
1010  if (d->dropsilence == TRUE)
1011  {
1012  // Do not remove silence by default
1013  g_object_set (removesilence, "remove", FALSE, NULL);
1014  g_object_set (queue, "max-size-buffers", 12, NULL);
1015  /*
1016  g_signal_connect (source,
1017  "need-data",
1018  G_CALLBACK(appsrc_need_data),
1019  NULL);
1020 
1021  g_signal_connect (source,
1022  "enough-data",
1023  G_CALLBACK(appsrc_enough_data),
1024  NULL);
1025  *//*
1026  g_signal_connect (queue,
1027  "notify::current-level-bytes",
1028  G_CALLBACK(queue_current_level),
1029  NULL);
1030 
1031  g_signal_connect (queue,
1032  "underrun",
1033  G_CALLBACK(queue_underrun),
1034  NULL);
1035 
1036  g_signal_connect (queue,
1037  "running",
1038  G_CALLBACK(queue_running),
1039  NULL);
1040 
1041  g_signal_connect (queue,
1042  "overrun",
1043  G_CALLBACK(queue_overrun),
1044  NULL);
1045 
1046  g_signal_connect (queue,
1047  "pushing",
1048  G_CALLBACK(queue_pushing),
1049  NULL);
1050  */ }
1051 
1052 
1053  gst_bin_add_many (bin, conv, resampler, sink, NULL);
1054  gst_element_link_many (conv, resampler, sink, NULL);
1055 
1056  if (d->dropsilence == TRUE)
1057  {
1058  gst_bin_add_many (bin, queue, removesilence, NULL);
1059 
1060  if (! gst_element_link_many (queue, removesilence, conv, NULL))
1061  lf ("queue, removesilence, conv ");
1062 
1063  pad = gst_element_get_static_pad (queue, "sink");
1064  }
1065  else
1066  {
1067  pad = gst_element_get_static_pad (conv, "sink");
1068  }
1069 
1070  ghostpad = gst_ghost_pad_new ("sink", pad);
1071  }
1072  else
1073  {
1074  // SOURCE
1075 
1076  bin = GST_BIN (gst_bin_new ("Gnunet audiosource"));
1077 
1078  // source = gst_element_factory_make("audiotestsrc", "audiotestsrcbla");
1079 
1080  if (d->audiobackend == AUTO)
1081  {
1082  source = gst_element_factory_make ("autoaudiosrc", "audiosource");
1083  }
1084  if (d->audiobackend == ALSA)
1085  {
1086  source = gst_element_factory_make ("alsasrc", "audiosource");
1087  }
1088  if (d->audiobackend == JACK)
1089  {
1090  source = gst_element_factory_make ("jackaudiosrc", "audiosource");
1091  }
1092  if (d->audiobackend == TEST)
1093  {
1094  source = gst_element_factory_make ("audiotestsrc", "audiosource");
1095  }
1096 
1097  filter = gst_element_factory_make ("capsfilter", "filter");
1098  conv = gst_element_factory_make ("audioconvert", "converter");
1099  resampler = gst_element_factory_make ("audioresample", "resampler");
1100 
1101  if (d->audiobackend == AUTO)
1102  {
1103  g_signal_connect (source, "child-added", G_CALLBACK (
1105  }
1106  else
1107  {
1108  if (GST_IS_AUDIO_BASE_SRC (source))
1109  g_object_set (source, "buffer-time", (gint64) BUFFER_TIME,
1110  "latency-time", (gint64) LATENCY_TIME, NULL);
1111  if (d->audiobackend == JACK)
1112  {
1113  g_object_set (G_OBJECT (source), "client-name", "gnunet", NULL);
1114  if (g_object_class_find_property
1115  (G_OBJECT_GET_CLASS (source), "port-pattern"))
1116  {
1117  char *portpattern = "moc";
1118 
1119  g_object_set (G_OBJECT (source), "port-pattern", portpattern,
1120  NULL);
1121  }
1122  }
1123  }
1124 
1125  caps = gst_caps_new_simple ("audio/x-raw",
1126  /* "format", G_TYPE_STRING, "S16LE", */
1127  /* "rate", G_TYPE_INT, SAMPLING_RATE,*/
1128  "channels", G_TYPE_INT, OPUS_CHANNELS,
1129  /* "layout", G_TYPE_STRING, "interleaved",*/
1130  NULL);
1131 
1132  g_object_set (G_OBJECT (filter),
1133  "caps", caps,
1134  NULL);
1135  gst_caps_unref (caps);
1136 
1137  gst_bin_add_many (bin, source, filter, conv, resampler, NULL);
1138  gst_element_link_many (source, filter, conv, resampler, NULL);
1139 
1140  pad = gst_element_get_static_pad (resampler, "src");
1141 
1142 
1143  /* pads */
1144  ghostpad = gst_ghost_pad_new ("src", pad);
1145  }
1146 
1147  /* set the bin pads */
1148  gst_pad_set_active (ghostpad, TRUE);
1149  gst_element_add_pad (GST_ELEMENT (bin), ghostpad);
1150 
1151  gst_object_unref (pad);
1152 
1153  return bin;
1154 }
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
static struct GNUNET_CONTAINER_MultiPeerMap * map
Handle to the map used to store old latency values for peers.
static GstElement * source
Appsrc instance into which we write data for the pipeline.
#define LATENCY_TIME
Min number of microseconds to buffer in audiosink.
static GstElement * pipeline
Main pipeline.
#define MAXLINE
How much data to read in one go.
static GstElement * decoder
static GstElement * resampler
static GstElement * sink
static GstElement * demuxer
static GstElement * conv
#define BUFFER_TIME
Max number of microseconds to buffer in audiosink.
#define SAMPLING_RATE
#define MAX_PAYLOAD_SIZE
Maximal size of a single opus packet.
#define OGG_MAX_DELAY
Maximum delay in multiplexing streams, in ns.
#define INBAND_FEC_MODE
Set to 1 to enable forward error correction.
#define OPUS_FRAME_SIZE
Size of a single frame fed to the encoder, in ms.
#define OGG_MAX_PAGE_DELAY
Maximum delay for sending out a page, in ns.
#define OPUS_CHANNELS
Number of channels.
#define PACKET_LOSS_PERCENTAGE
Expected packet loss to prepare for, in percents.
uint32_t data
The data value.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
static struct GNUNET_CONTAINER_BloomFilter * filter
Bloomfilter to quickly tell if we don't have the content.
static char buf[2048]
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-uri.c:38
static void queue(const char *hostname)
Add hostname to the list of requests to be made.
static void autoaudiosource_child_added(GstChildProxy *child_proxy, GObject *object, gchar *name, gpointer user_data)
Definition: gnunet_gst.c:615
static void eos_cb(GstBus *bus, GstMessage *msg, GNUNET_gstData *data)
Definition: gnunet_gst.c:347
void gg_load_configuration(GNUNET_gstData *d)
Definition: gnunet_gst.c:71
void state_changed_cb(GstBus *bus, GstMessage *msg, GNUNET_gstData *d)
Definition: gnunet_gst.c:291
static void application_cb(GstBus *bus, GstMessage *msg, GNUNET_gstData *data)
Definition: gnunet_gst.c:331
void pl_graph(GstElement *pipeline)
Definition: gnunet_gst.c:233
void gg_setup_gst_bus(GNUNET_gstData *d)
Definition: gnunet_gst.c:355
int gnunet_read(GNUNET_gstData *d)
Definition: gnunet_gst.c:655
static int stdin_receiver(void *cls, const struct GNUNET_MessageHeader *msg)
Message callback.
Definition: gnunet_gst.c:703
GstElement * gst_element_factory_make_debug(gchar *factoryname, gchar *name)
debug making elements
Definition: gnunet_gst.c:555
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet_gst.c:31
void dump_buffer(unsigned n, const unsigned char *buf)
Definition: gnunet_gst.c:35
gboolean gnunet_gst_bus_call(GstBus *bus, GstMessage *msg, gpointer data)
Definition: gnunet_gst.c:252
GstBin * get_coder(GNUNET_gstData *d, int type)
Definition: gnunet_gst.c:816
GstBin * get_audiobin(GNUNET_gstData *d, int type)
Definition: gnunet_gst.c:950
GstFlowReturn on_appsink_new_sample(GstElement *element, GNUNET_gstData *d)
Definition: gnunet_gst.c:170
GstBin * get_app(GNUNET_gstData *d, int type)
Definition: gnunet_gst.c:732
static void write_data(const char *ptr, size_t msg_size)
Definition: gnunet_gst.c:149
int feed_buffer_to_gst(const char *audio, size_t b_len, GNUNET_gstData *d)
Definition: gnunet_gst.c:496
static void decoder_ogg_pad_added(GstElement *element, GstPad *pad, gpointer data)
Definition: gnunet_gst.c:636
static void error_cb(GstBus *bus, GstMessage *msg, GNUNET_gstData *data)
Definition: gnunet_gst.c:339
void lf(char *msg)
Definition: gnunet_gst.c:587
static void autoaudiosink_child_added(GstChildProxy *child_proxy, GObject *object, gchar *name, gpointer user_data)
Definition: gnunet_gst.c:598
GstElement * get_pipeline(GstElement *element)
Definition: gnunet_gst.c:625
#define gst_element_factory_make(element, name)
Definition: gnunet_gst.h:36
@ FAIL
@ ALSA
@ JACK
@ TEST
@ FAKE
@ AUTO
@ SOURCE
@ SINK
@ ENCODER
@ DECODER
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_create(void)
Create a new configuration object.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_load(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Load configuration.
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
int GNUNET_log_setup(const char *comp, const char *loglevel, const char *logfile)
Setup logging.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO
Message to transmit the audio between helper and speaker/microphone library.
enum GNUNET_GenericReturnValue GNUNET_MST_from_buffer(struct GNUNET_MessageStreamTokenizer *mst, const char *buf, size_t size, int purge, int one_shot)
Add incoming data to the receive buffer and call the callback for all complete messages.
Definition: mst.c:101
struct GNUNET_MessageStreamTokenizer * GNUNET_MST_create(GNUNET_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
Definition: mst.c:86
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
const char * name
Message to transmit the audio (between client and helpers).
Definition: conversation.h:59
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO.
Definition: conversation.h:63
unsigned int size
Number of entries in the map.
Header for all communications.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
struct AudioMessage * audio_message
GstElement * appsrc
GstElement * appsink
GstPipeline * pipeline
struct GNUNET_MessageStreamTokenizer * stdin_mst
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model