NetEq: Fixing a corner case with depleted sync buffer
In some cases, the number of samples (per channel) in NetEq's sync
buffer could fall below the allowed minimum (5 samples for narrowband,
scaling for other rates). If the number of samples extracted from the
buffer was smaller than the desired number, an error is
returned. However, if the decoder returns fewer samples than expected,
it could happen that the sync buffer level falls under the minimum,
but enough samples are extracted. This triggered an assert. With this
change, the minimum level of the sync buffer is always enforced.
A test is implemented to trigger the problem. It made the assert fire
without this fix, but it now passes.
BUG=webrtc:4840
R=minyue@webrtc.org
Review URL: https://codereview.webrtc.org/1324453002 .
Cr-Commit-Position: refs/heads/master@{#9828}
diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl.cc b/webrtc/modules/audio_coding/neteq/neteq_impl.cc
index beadeda..e6f7e60 100644
--- a/webrtc/modules/audio_coding/neteq/neteq_impl.cc
+++ b/webrtc/modules/audio_coding/neteq/neteq_impl.cc
@@ -834,6 +834,16 @@
LOG(LS_VERBOSE) << "Sync buffer (" << *num_channels << " channel(s)):" <<
" insert " << algorithm_buffer_->Size() << " samples, extract " <<
samples_from_sync << " samples";
+ if (sync_buffer_->FutureLength() < expand_->overlap_length()) {
+ // The sync buffer should always contain |overlap_length| samples, but now
+ // too many samples have been extracted. Reinstall the |overlap_length|
+ // lookahead by moving the index.
+ const size_t missing_lookahead_samples =
+ expand_->overlap_length() - sync_buffer_->FutureLength();
+ DCHECK_GE(sync_buffer_->next_index(), missing_lookahead_samples);
+ sync_buffer_->set_next_index(sync_buffer_->next_index() -
+ missing_lookahead_samples);
+ }
if (samples_from_sync != output_size_samples_) {
LOG(LS_ERROR) << "samples_from_sync (" << samples_from_sync
<< ") != output_size_samples_ (" << output_size_samples_
@@ -846,7 +856,7 @@
*samples_per_channel = output_size_samples_;
// Should always have overlap samples left in the |sync_buffer_|.
- assert(sync_buffer_->FutureLength() >= expand_->overlap_length());
+ DCHECK_GE(sync_buffer_->FutureLength(), expand_->overlap_length());
if (play_dtmf) {
return_value = DtmfOverdub(dtmf_event, sync_buffer_->Channels(), output);