diff --git a/assets/i_have_a_dream.mp3 b/assets/i_have_a_dream.mp3 new file mode 100644 index 0000000..df0dd29 Binary files /dev/null and b/assets/i_have_a_dream.mp3 differ diff --git a/src/dcall.c b/src/dcall.c index 8ac01bf..c719be1 100644 --- a/src/dcall.c +++ b/src/dcall.c @@ -6,11 +6,12 @@ #include #include #include +#include struct dcall_elements { GstElement *pipeline; - GstElement *rx_tap, *rx_jitterbuffer, *rx_depay, *rx_opusdec, *rx_resample, *rx_echocancel, *rx_sink; - GstElement *tx_tap, *tx_echocancel, *tx_queue, *tx_resample, *tx_opusenc, *tx_pay, *tx_sink; + GstElement *rx_tap, *rx_jitterbuffer, *rx_depay, *rx_opusdec, *rx_resample, *rx_echocancel, *rx_pulse, *rx_fakesink; + GstElement *tx_pulse, *tx_filesrc, *tx_mpegaudioparse, *tx_mpgaudiodec, *tx_audioconvert, *tx_echocancel, *tx_queue, *tx_resample, *tx_opusenc, *tx_pay, *tx_sink; char *remote_host, *audio_tap, *audio_sink, *audio_file, *gstreamer_log_path; int remote_port, latency; guint64 grtppktlost; @@ -23,9 +24,10 @@ int create_rx_chain(struct dcall_elements* de) { de->rx_opusdec = gst_element_factory_make("opusdec", "rx-opusdec"); de->rx_resample = gst_element_factory_make("audioresample", "rx-audioresample"); de->rx_echocancel = gst_element_factory_make("webrtcechoprobe", "rx-echocancel"); - de->rx_sink = gst_element_factory_make(de->audio_sink, "rx-sink"); + de->rx_pulse = gst_element_factory_make("pulsesink", "rx-pulse"); + de->rx_fakesink = gst_element_factory_make("fakesink", "rx-fakesink"); - if (!de->rx_tap || !de->rx_jitterbuffer || !de->rx_depay || !de->rx_opusdec || !de->rx_resample || !de->rx_echocancel || !de->rx_sink) { + if (!de->rx_tap || !de->rx_jitterbuffer || !de->rx_depay || !de->rx_opusdec || !de->rx_resample || !de->rx_echocancel || !de->rx_pulse || !de->rx_fakesink) { g_printerr ("One element of the rx chain could not be created. Exiting.\n"); return -1; } @@ -43,21 +45,32 @@ int create_rx_chain(struct dcall_elements* de) { g_object_set(G_OBJECT (de->rx_opusdec), "plc", TRUE, NULL); g_object_set(G_OBJECT (de->rx_opusdec), "use-inband-fec", FALSE, NULL); - if (strcmp(de->audio_sink, "pulsesrc") == 0) { - GstStructure *props; - props = gst_structure_from_string ("props,media.role=phone", NULL); - g_object_set (de->rx_sink, "stream-properties", props, NULL); - gst_structure_free (props); - } - gst_bin_add_many (GST_BIN (de->pipeline), de->rx_tap, de->rx_jitterbuffer, de->rx_depay, de->rx_opusdec, de->rx_resample, de->rx_echocancel, de->rx_sink, NULL); - gst_element_link_many (de->rx_tap, de->rx_jitterbuffer, de->rx_depay, de->rx_opusdec, de->rx_resample, de->rx_echocancel, de->rx_sink, NULL); + GstStructure *props; + props = gst_structure_from_string ("props,media.role=phone", NULL); + g_object_set (de->rx_pulse, "stream-properties", props, NULL); + gst_structure_free (props); + + if (strcmp(de->audio_sink, "pulsesink") == 0) { + gst_bin_add_many (GST_BIN (de->pipeline), de->rx_tap, de->rx_jitterbuffer, de->rx_depay, de->rx_opusdec, de->rx_resample, de->rx_echocancel, de->rx_pulse, NULL); + gst_element_link_many (de->rx_tap, de->rx_jitterbuffer, de->rx_depay, de->rx_opusdec, de->rx_resample, de->rx_echocancel, de->rx_pulse, NULL); + } else if (strcmp(de->audio_sink, "fakesink") == 0) { + gst_bin_add_many (GST_BIN (de->pipeline), de->rx_tap, de->rx_jitterbuffer, de->rx_depay, de->rx_opusdec, de->rx_resample, de->rx_echocancel, de->rx_fakesink, NULL); + gst_element_link_many (de->rx_tap, de->rx_jitterbuffer, de->rx_depay, de->rx_opusdec, de->rx_resample, de->rx_echocancel, de->rx_fakesink, NULL); + } else { + fprintf(stderr, "Wrong audio sink %s, exiting...\n", de->audio_sink); + exit(EXIT_FAILURE); + } return 0; } int create_tx_chain(struct dcall_elements* de) { - de->tx_tap = gst_element_factory_make(de->audio_tap, "tx-tap"); + de->tx_pulse = gst_element_factory_make("pulsesrc", "tx-pulse"); + de->tx_filesrc = gst_element_factory_make("filesrc", "tx-filesrc"); + de->tx_mpegaudioparse = gst_element_factory_make("mpegaudioparse", "tx-mpegaudioparse"); + de->tx_mpgaudiodec = gst_element_factory_make("mpg123audiodec", "tx-mpgaudiodec"); + de->tx_audioconvert = gst_element_factory_make("audioconvert", "tx-audioconvert"); de->tx_resample = gst_element_factory_make("audioresample", "tx-resample"); de->tx_echocancel = gst_element_factory_make("webrtcdsp", "tx-echocancel"); de->tx_queue = gst_element_factory_make("queue", "tx-queue"); @@ -65,7 +78,7 @@ int create_tx_chain(struct dcall_elements* de) { de->tx_pay = gst_element_factory_make("rtpopuspay", "tx-rtpopuspay"); de->tx_sink = gst_element_factory_make("udpsink", "tx-sink"); - if (!de->tx_tap || !de->tx_echocancel || !de->tx_queue || !de->tx_resample || !de->tx_opusenc || !de->tx_pay || !de->tx_sink) { + if (!de->tx_pulse || !de->tx_filesrc || !de->tx_mpegaudioparse || !de->tx_mpgaudiodec || !de->tx_audioconvert || !de->tx_echocancel || !de->tx_queue || !de->tx_resample || !de->tx_opusenc || !de->tx_pay || !de->tx_sink) { g_printerr("One element of the tx chain could not be created. Exiting.\n"); return -1; } @@ -89,15 +102,23 @@ int create_tx_chain(struct dcall_elements* de) { g_object_set(G_OBJECT(de->tx_echocancel), "probe", "rx-echocancel", NULL); g_object_set(G_OBJECT(de->tx_echocancel), "voice-detection", FALSE, NULL); - if (strcmp(de->audio_tap, "pulsesrc") == 0) { - GstStructure *props; - props = gst_structure_from_string ("props,media.role=phone", NULL); - g_object_set (de->tx_tap, "stream-properties", props, NULL); - gst_structure_free (props); - } + GstStructure *props; + props = gst_structure_from_string ("props,media.role=phone", NULL); + g_object_set (de->tx_pulse, "stream-properties", props, NULL); + gst_structure_free (props); - gst_bin_add_many(GST_BIN(de->pipeline), de->tx_tap, de->tx_echocancel, de->tx_queue, de->tx_resample, de->tx_opusenc, de->tx_pay, de->tx_sink, NULL); - gst_element_link_many( de->tx_tap, de->tx_resample, de->tx_echocancel, de->tx_queue, de->tx_opusenc, de->tx_pay, de->tx_sink, NULL); + g_object_set(de->tx_filesrc, "location", de->audio_file, NULL); + + if (strcmp(de->audio_tap, "pulsesrc") == 0) { + gst_bin_add_many(GST_BIN(de->pipeline), de->tx_pulse, de->tx_echocancel, de->tx_queue, de->tx_resample, de->tx_opusenc, de->tx_pay, de->tx_sink, NULL); + gst_element_link_many(de->tx_pulse, de->tx_resample, de->tx_echocancel, de->tx_queue, de->tx_opusenc, de->tx_pay, de->tx_sink, NULL); + } else if (strcmp(de->audio_tap, "filesrc") == 0) { + gst_bin_add_many(GST_BIN(de->pipeline), de->tx_filesrc, de->tx_mpegaudioparse, de->tx_mpgaudiodec, de->tx_audioconvert, de->tx_queue, de->tx_resample, de->tx_opusenc, de->tx_pay, de->tx_sink, NULL); + gst_element_link_many(de->tx_filesrc, de->tx_mpegaudioparse, de->tx_mpgaudiodec, de->tx_audioconvert, de->tx_resample, de->tx_queue, de->tx_opusenc, de->tx_pay, de->tx_sink, NULL); + } else { + fprintf(stderr, "Wrong audio tap %s, exiting...\n", de->audio_tap); + exit(EXIT_FAILURE); + } return 0; }