From 74c0d5fdd2db60c21e419989228095791f64f19c Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Wed, 13 Jul 2016 23:00:51 -0400 Subject: [PATCH] webrtcdsp: Add delay-agnostic property In this mode, we let WebRTC Audio Processing figure-out the delay. This is useful when the latency reported by the stack cannot be trusted. Note that in this mode, the leaking of echo during packet lost is much worst. It is recommanded to use PLC (e.g. spanplc, or opus built-in plc). In this mode, we don't do any synchronization. Instead, we simply process all the available reverse stream data as it comes. --- ext/webrtcdsp/gstwebrtcdsp.cpp | 29 +++++++++++++++++++++++++--- ext/webrtcdsp/gstwebrtcechoprobe.cpp | 15 ++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/ext/webrtcdsp/gstwebrtcdsp.cpp b/ext/webrtcdsp/gstwebrtcdsp.cpp index f64b623d53..b6b8660f5b 100644 --- a/ext/webrtcdsp/gstwebrtcdsp.cpp +++ b/ext/webrtcdsp/gstwebrtcdsp.cpp @@ -156,7 +156,8 @@ enum PROP_NOISE_SUPPRESSION_LEVEL, PROP_GAIN_CONTROL, PROP_EXPERIMENTAL_AGC, - PROP_EXTENDED_FILTER + PROP_EXTENDED_FILTER, + PROP_DELAY_AGNOSTIC }; /** @@ -189,6 +190,7 @@ struct _GstWebrtcDsp gboolean gain_control; gboolean experimental_agc; gboolean extended_filter; + gboolean delay_agnostic; }; G_DEFINE_TYPE (GstWebrtcDsp, gst_webrtc_dsp, GST_TYPE_AUDIO_FILTER); @@ -290,8 +292,11 @@ gst_webrtc_dsp_analyze_reverse_stream (GstWebrtcDsp * self, apm = self->apm; - delay = gst_webrtc_echo_probe_read (probe, rec_time, (gpointer) &frame); + if (self->delay_agnostic) + rec_time = GST_CLOCK_TIME_NONE; +again: + delay = gst_webrtc_echo_probe_read (probe, rec_time, (gpointer) &frame); apm->set_stream_delay_ms (delay); if (delay < 0) @@ -310,13 +315,16 @@ gst_webrtc_dsp_analyze_reverse_stream (GstWebrtcDsp * self, GST_WARNING_OBJECT (self, "Reverse stream analyses failed: %s.", webrtc_error_to_string (err)); + if (self->delay_agnostic) + goto again; + done: gst_object_unref (probe); return ret; } -static GstFlowReturn +static GstFlowReturn gst_webrtc_dsp_process_stream (GstWebrtcDsp * self, GstBuffer * buffer) { @@ -401,6 +409,8 @@ gst_webrtc_dsp_start (GstBaseTransform * btrans) (new webrtc::ExtendedFilter (self->extended_filter)); config.Set < webrtc::ExperimentalAgc > (new webrtc::ExperimentalAgc (self->experimental_agc)); + config.Set < webrtc::DelayAgnostic > + (new webrtc::DelayAgnostic (self->delay_agnostic)); /* TODO Intelligibility enhancer, Beamforming, etc. */ @@ -590,6 +600,9 @@ gst_webrtc_dsp_set_property (GObject * object, case PROP_EXTENDED_FILTER: self->extended_filter = g_value_get_boolean (value); break; + case PROP_DELAY_AGNOSTIC: + self->delay_agnostic = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -632,6 +645,9 @@ gst_webrtc_dsp_get_property (GObject * object, case PROP_EXTENDED_FILTER: g_value_set_boolean (value, self->extended_filter); break; + case PROP_DELAY_AGNOSTIC: + g_value_set_boolean (value, self->delay_agnostic); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -761,6 +777,13 @@ gst_webrtc_dsp_class_init (GstWebrtcDspClass * klass) "Enable or disable the extended filter.", TRUE, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT))); + + g_object_class_install_property (gobject_class, + PROP_DELAY_AGNOSTIC, + g_param_spec_boolean ("delay-agnostic", "Delay Agnostic", + "Enable or disable the delay agnostic mode.", + FALSE, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + G_PARAM_CONSTRUCT))); } static gboolean diff --git a/ext/webrtcdsp/gstwebrtcechoprobe.cpp b/ext/webrtcdsp/gstwebrtcechoprobe.cpp index ebc35c1828..5b811b6b33 100644 --- a/ext/webrtcdsp/gstwebrtcechoprobe.cpp +++ b/ext/webrtcdsp/gstwebrtcechoprobe.cpp @@ -280,6 +280,20 @@ gst_webrtc_echo_probe_read (GstWebrtcEchoProbe * self, GstClockTime rec_time, if (!GST_CLOCK_TIME_IS_VALID (self->latency)) goto done; + /* In delay agnostic mode, just return 10ms of data */ + if (!GST_CLOCK_TIME_IS_VALID (rec_time)) { + avail = gst_adapter_available (self->adapter); + + if (avail < self->period_size) + goto done; + + size = self->period_size; + skip = 0; + offset = 0; + + goto copy; + } + if (gst_adapter_available (self->adapter) == 0) { diff = G_MAXINT64; } else { @@ -317,6 +331,7 @@ gst_webrtc_echo_probe_read (GstWebrtcEchoProbe * self, GstClockTime rec_time, if (size < self->period_size) memset (frame->data_, 0, self->period_size); +copy: if (size) { gst_adapter_copy (self->adapter, (guint8 *) frame->data_ + skip, offset, size);