webrtcdsp: Deal with echo probe info not being available

Even if we don't yet know what the echo probe format is, we want to be able to
provide silence for the reverse path, so that when the probe becomes available,
there is no ambiguity around what time period the new set of samples are for.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4849>
This commit is contained in:
Arun Raghavan 2023-06-13 11:41:43 -04:00 committed by GStreamer Marge Bot
parent fade0748d1
commit e1139e740a
3 changed files with 32 additions and 17 deletions

View file

@ -370,6 +370,8 @@ gst_webrtc_dsp_analyze_reverse_stream (GstWebrtcDsp * self,
GstWebrtcEchoProbe *probe = NULL; GstWebrtcEchoProbe *probe = NULL;
webrtc::AudioProcessing *apm; webrtc::AudioProcessing *apm;
GstBuffer *buf = NULL; GstBuffer *buf = NULL;
GstAudioInfo info;
gboolean interleaved = self->interleaved;
GstAudioBuffer abuf; GstAudioBuffer abuf;
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
gint err, delay; gint err, delay;
@ -377,36 +379,38 @@ gst_webrtc_dsp_analyze_reverse_stream (GstWebrtcDsp * self,
GST_OBJECT_LOCK (self); GST_OBJECT_LOCK (self);
if (self->echo_cancel) if (self->echo_cancel)
probe = GST_WEBRTC_ECHO_PROBE (g_object_ref (self->probe)); probe = GST_WEBRTC_ECHO_PROBE (g_object_ref (self->probe));
info = self->info;
GST_OBJECT_UNLOCK (self); GST_OBJECT_UNLOCK (self);
/* If echo cancellation is disabled */ /* If echo cancellation is disabled */
if (!probe) if (!probe)
return GST_FLOW_OK; return GST_FLOW_OK;
webrtc::StreamConfig config (probe->info.rate, probe->info.channels, delay =
false); gst_webrtc_echo_probe_read (probe, rec_time, &buf, &info, &interleaved);
apm = self->apm;
delay = gst_webrtc_echo_probe_read (probe, rec_time, &buf); apm = self->apm;
apm->set_stream_delay_ms (delay); apm->set_stream_delay_ms (delay);
webrtc::StreamConfig config (info.rate, info.channels, false);
g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
if (delay < 0) if (delay < 0)
goto done; goto done;
if (probe->info.rate != self->info.rate) { if (info.rate != self->info.rate) {
GST_ELEMENT_ERROR (self, STREAM, FORMAT, GST_ELEMENT_ERROR (self, STREAM, FORMAT,
("Echo Probe has rate %i , while the DSP is running at rate %i," ("Echo Probe has rate %i , while the DSP is running at rate %i,"
" use a caps filter to ensure those are the same.", " use a caps filter to ensure those are the same.",
probe->info.rate, self->info.rate), (NULL)); info.rate, self->info.rate), (NULL));
ret = GST_FLOW_ERROR; ret = GST_FLOW_ERROR;
goto done; goto done;
} }
gst_audio_buffer_map (&abuf, &probe->info, buf, GST_MAP_READWRITE); gst_audio_buffer_map (&abuf, &info, buf, GST_MAP_READWRITE);
if (probe->interleaved) { if (interleaved) {
int16_t * const data = (int16_t * const) abuf.planes[0]; int16_t * const data = (int16_t * const) abuf.planes[0];
if ((err = apm->ProcessReverseStream (data, config, config, data)) < 0) if ((err = apm->ProcessReverseStream (data, config, config, data)) < 0)

View file

@ -304,7 +304,7 @@ gst_webrtc_release_echo_probe (GstWebrtcEchoProbe * probe)
gint gint
gst_webrtc_echo_probe_read (GstWebrtcEchoProbe * self, GstClockTime rec_time, gst_webrtc_echo_probe_read (GstWebrtcEchoProbe * self, GstClockTime rec_time,
GstBuffer ** buf) GstBuffer ** buf, GstAudioInfo * info, gboolean * interleaved)
{ {
GstClockTimeDiff diff; GstClockTimeDiff diff;
gsize avail, skip, offset, size = 0; gsize avail, skip, offset, size = 0;
@ -315,10 +315,17 @@ gst_webrtc_echo_probe_read (GstWebrtcEchoProbe * self, GstClockTime rec_time,
/* We always return a buffer -- if don't have data (size == 0), we generate a /* We always return a buffer -- if don't have data (size == 0), we generate a
* silence buffer */ * silence buffer */
if (!GST_CLOCK_TIME_IS_VALID (self->latency) || if (!GST_CLOCK_TIME_IS_VALID (self->latency))
!GST_AUDIO_INFO_IS_VALID (&self->info))
goto copy; goto copy;
/* If we have a format, use that, else generate silence in input format */
if (!GST_AUDIO_INFO_IS_VALID (&self->info)) {
goto copy;
} else {
*info = self->info;
*interleaved = self->interleaved;
}
if (self->interleaved) if (self->interleaved)
avail = gst_adapter_available (self->adapter) / self->info.bpf; avail = gst_adapter_available (self->adapter) / self->info.bpf;
else else
@ -375,11 +382,14 @@ gst_webrtc_echo_probe_read (GstWebrtcEchoProbe * self, GstClockTime rec_time,
copy: copy:
if (!size) { if (!size) {
/* No data, provide a period's worth of silence */ /* No data, provide a period's worth of silence, using our format if we have
*buf = gst_buffer_new_allocate (NULL, self->period_size, NULL); * it, or the provided format if we don't */
gst_buffer_memset (*buf, 0, 0, self->period_size); guint period_samples = info->rate / 100;
gst_buffer_add_audio_meta (*buf, &self->info, self->period_samples, guint period_size = period_samples * info->bpf;
NULL);
*buf = gst_buffer_new_allocate (NULL, period_size, NULL);
gst_buffer_memset (*buf, 0, 0, period_size);
gst_buffer_add_audio_meta (*buf, info, period_samples, NULL);
} else { } else {
/* We have some actual data, pop period_samples' worth if have it, else pad /* We have some actual data, pop period_samples' worth if have it, else pad
* with silence and provide what we do have */ * with silence and provide what we do have */

View file

@ -99,7 +99,8 @@ GST_ELEMENT_REGISTER_DECLARE (webrtcechoprobe);
GstWebrtcEchoProbe *gst_webrtc_acquire_echo_probe (const gchar * name); GstWebrtcEchoProbe *gst_webrtc_acquire_echo_probe (const gchar * name);
void gst_webrtc_release_echo_probe (GstWebrtcEchoProbe * probe); void gst_webrtc_release_echo_probe (GstWebrtcEchoProbe * probe);
gint gst_webrtc_echo_probe_read (GstWebrtcEchoProbe * self, gint gst_webrtc_echo_probe_read (GstWebrtcEchoProbe * self,
GstClockTime rec_time, GstBuffer ** buf); GstClockTime rec_time, GstBuffer ** buf, GstAudioInfo * info,
gboolean * interleaved);
G_END_DECLS G_END_DECLS
#endif /* __GST_WEBRTC_ECHO_PROBE_H__ */ #endif /* __GST_WEBRTC_ECHO_PROBE_H__ */