Let NetEq use the PLC output from a decoder
This change enables NetEq to use the packet concealment audio (aka PLC) produced by a decoder. The change also includes a new API to the AudioDecoder interface, which lets the decoder implementation generate and deliver concealment audio. Bug: webrtc:9180 Change-Id: Icaacebccf645d4694b0d2d6310f6f2c7132881c4 Reviewed-on: https://webrtc-review.googlesource.com/96340 Commit-Queue: Henrik Lundin <henrik.lundin@webrtc.org> Reviewed-by: Minyue Li <minyue@webrtc.org> Reviewed-by: Karl Wiberg <kwiberg@webrtc.org> Cr-Commit-Position: refs/heads/master@{#24738}
This commit is contained in:
committed by
Commit Bot
parent
e899629be4
commit
00eb12a20c
@ -885,7 +885,12 @@ int NetEqImpl::GetAudioInternal(AudioFrame* audio_frame,
|
||||
break;
|
||||
}
|
||||
case kExpand: {
|
||||
return_value = DoExpand(play_dtmf);
|
||||
RTC_DCHECK_EQ(return_value, 0);
|
||||
if (!current_rtp_payload_type_ || !DoCodecPlc()) {
|
||||
return_value = DoExpand(play_dtmf);
|
||||
}
|
||||
RTC_DCHECK_GE(sync_buffer_->FutureLength() - expand_->overlap_length(),
|
||||
output_size_samples_);
|
||||
break;
|
||||
}
|
||||
case kAccelerate:
|
||||
@ -997,7 +1002,7 @@ int NetEqImpl::GetAudioInternal(AudioFrame* audio_frame,
|
||||
sync_buffer_->set_dtmf_index(sync_buffer_->Size());
|
||||
}
|
||||
|
||||
if (last_mode_ != kModeExpand) {
|
||||
if (last_mode_ != kModeExpand && last_mode_ != kModeCodecPlc) {
|
||||
// If last operation was not expand, calculate the |playout_timestamp_| from
|
||||
// the |sync_buffer_|. However, do not update the |playout_timestamp_| if it
|
||||
// would be moved "backwards".
|
||||
@ -1022,7 +1027,7 @@ int NetEqImpl::GetAudioInternal(AudioFrame* audio_frame,
|
||||
static_cast<uint32_t>(audio_frame->samples_per_channel_);
|
||||
|
||||
if (!(last_mode_ == kModeRfc3389Cng || last_mode_ == kModeCodecInternalCng ||
|
||||
last_mode_ == kModeExpand)) {
|
||||
last_mode_ == kModeExpand || last_mode_ == kModeCodecPlc)) {
|
||||
generated_noise_stopwatch_.reset();
|
||||
}
|
||||
|
||||
@ -1541,6 +1546,48 @@ void NetEqImpl::DoMerge(int16_t* decoded_buffer,
|
||||
}
|
||||
}
|
||||
|
||||
bool NetEqImpl::DoCodecPlc() {
|
||||
AudioDecoder* decoder = decoder_database_->GetActiveDecoder();
|
||||
if (!decoder) {
|
||||
return false;
|
||||
}
|
||||
const size_t channels = algorithm_buffer_->Channels();
|
||||
const size_t requested_samples_per_channel =
|
||||
output_size_samples_ -
|
||||
(sync_buffer_->FutureLength() - expand_->overlap_length());
|
||||
concealment_audio_.Clear();
|
||||
decoder->GeneratePlc(requested_samples_per_channel, &concealment_audio_);
|
||||
if (concealment_audio_.empty()) {
|
||||
// Nothing produced. Resort to regular expand.
|
||||
return false;
|
||||
}
|
||||
RTC_CHECK_GE(concealment_audio_.size(),
|
||||
requested_samples_per_channel * channels);
|
||||
sync_buffer_->PushBackInterleaved(concealment_audio_);
|
||||
RTC_DCHECK_NE(algorithm_buffer_->Channels(), 0);
|
||||
const size_t concealed_samples_per_channel =
|
||||
concealment_audio_.size() / channels;
|
||||
|
||||
// Update in-call and post-call statistics.
|
||||
const bool is_new_concealment_event = (last_mode_ != kModeCodecPlc);
|
||||
if (std::all_of(concealment_audio_.cbegin(), concealment_audio_.cend(),
|
||||
[](int16_t i) { return i == 0; })) {
|
||||
// Expand operation generates only noise.
|
||||
stats_.ExpandedNoiseSamples(concealed_samples_per_channel,
|
||||
is_new_concealment_event);
|
||||
} else {
|
||||
// Expand operation generates more than only noise.
|
||||
stats_.ExpandedVoiceSamples(concealed_samples_per_channel,
|
||||
is_new_concealment_event);
|
||||
}
|
||||
last_mode_ = kModeCodecPlc;
|
||||
if (!generated_noise_stopwatch_) {
|
||||
// Start a new stopwatch since we may be covering for a lost CNG packet.
|
||||
generated_noise_stopwatch_ = tick_timer_->GetNewStopwatch();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int NetEqImpl::DoExpand(bool play_dtmf) {
|
||||
while ((sync_buffer_->FutureLength() - expand_->overlap_length()) <
|
||||
output_size_samples_) {
|
||||
|
||||
Reference in New Issue
Block a user