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