| Index: webrtc/modules/audio_coding/neteq/neteq_impl.cc
|
| diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl.cc b/webrtc/modules/audio_coding/neteq/neteq_impl.cc
|
| index 02e9324eee94eebda50b810c530e57da2f270179..7c049b0152bb030aef6098d27142f050498caa74 100644
|
| --- a/webrtc/modules/audio_coding/neteq/neteq_impl.cc
|
| +++ b/webrtc/modules/audio_coding/neteq/neteq_impl.cc
|
| @@ -765,7 +765,7 @@ int NetEqImpl::GetAudioInternal(size_t max_length,
|
| // This handles the case when there is no transmission and the decoder
|
| // should produce internal comfort noise.
|
| // TODO(hlundin): Write test for codec-internal CNG.
|
| - DoCodecInternalCng();
|
| + DoCodecInternalCng(decoded_buffer_.get(), length);
|
| break;
|
| }
|
| case kDtmf: {
|
| @@ -1163,7 +1163,11 @@ int NetEqImpl::Decode(PacketList* packet_list, Operations* operation,
|
| int* decoded_length,
|
| AudioDecoder::SpeechType* speech_type) {
|
| *speech_type = AudioDecoder::kSpeech;
|
| - AudioDecoder* decoder = NULL;
|
| +
|
| + // When packet_list is empty, we may be in kCodecInternalCng mode, and for
|
| + // that we use current active decoder.
|
| + AudioDecoder* decoder = decoder_database_->GetActiveDecoder();
|
| +
|
| if (!packet_list->empty()) {
|
| const Packet* packet = packet_list->front();
|
| uint8_t payload_type = packet->header.payloadType;
|
| @@ -1231,8 +1235,14 @@ int NetEqImpl::Decode(PacketList* packet_list, Operations* operation,
|
| decoder->DecodePlc(1, &decoded_buffer_[*decoded_length]);
|
| }
|
|
|
| - int return_value = DecodeLoop(packet_list, operation, decoder,
|
| - decoded_length, speech_type);
|
| + int return_value;
|
| + if (*operation == kCodecInternalCng) {
|
| + RTC_DCHECK(packet_list->empty());
|
| + return_value = DecodeCng(decoder, decoded_length, speech_type);
|
| + } else {
|
| + return_value = DecodeLoop(packet_list, *operation, decoder,
|
| + decoded_length, speech_type);
|
| + }
|
|
|
| if (*decoded_length < 0) {
|
| // Error returned from the decoder.
|
| @@ -1266,13 +1276,45 @@ int NetEqImpl::Decode(PacketList* packet_list, Operations* operation,
|
| return return_value;
|
| }
|
|
|
| -int NetEqImpl::DecodeLoop(PacketList* packet_list, Operations* operation,
|
| +int NetEqImpl::DecodeCng(AudioDecoder* decoder, int* decoded_length,
|
| + AudioDecoder::SpeechType* speech_type) {
|
| + if (!decoder) {
|
| + // This happens when active decoder is not defined.
|
| + *decoded_length = -1;
|
| + return 0;
|
| + }
|
| +
|
| + while (*decoded_length < rtc::checked_cast<int>(output_size_samples_)) {
|
| + const int length = decoder->Decode(
|
| + nullptr, 0, fs_hz_,
|
| + (decoded_buffer_length_ - *decoded_length) * sizeof(int16_t),
|
| + &decoded_buffer_[*decoded_length], speech_type);
|
| + if (length > 0) {
|
| + *decoded_length += length;
|
| + LOG(LS_VERBOSE) << "Decoded " << length << " CNG samples";
|
| + } else {
|
| + // Error.
|
| + LOG(LS_WARNING) << "Failed to decode CNG";
|
| + *decoded_length = -1;
|
| + break;
|
| + }
|
| + if (*decoded_length > static_cast<int>(decoded_buffer_length_)) {
|
| + // Guard against overflow.
|
| + LOG(LS_WARNING) << "Decoded too much CNG.";
|
| + return kDecodedTooMuch;
|
| + }
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| +int NetEqImpl::DecodeLoop(PacketList* packet_list, const Operations& operation,
|
| AudioDecoder* decoder, int* decoded_length,
|
| AudioDecoder::SpeechType* speech_type) {
|
| Packet* packet = NULL;
|
| if (!packet_list->empty()) {
|
| packet = packet_list->front();
|
| }
|
| +
|
| // Do decoding.
|
| while (packet &&
|
| !decoder_database_->IsComfortNoise(packet->header.payloadType)) {
|
| @@ -1281,9 +1323,9 @@ int NetEqImpl::DecodeLoop(PacketList* packet_list, Operations* operation,
|
| // number decoder channels.
|
| assert(sync_buffer_->Channels() == decoder->Channels());
|
| assert(decoded_buffer_length_ >= kMaxFrameSize * decoder->Channels());
|
| - assert(*operation == kNormal || *operation == kAccelerate ||
|
| - *operation == kFastAccelerate || *operation == kMerge ||
|
| - *operation == kPreemptiveExpand);
|
| + assert(operation == kNormal || operation == kAccelerate ||
|
| + operation == kFastAccelerate || operation == kMerge ||
|
| + operation == kPreemptiveExpand);
|
| packet_list->pop_front();
|
| size_t payload_length = packet->payload_length;
|
| int decode_length;
|
| @@ -1643,21 +1685,12 @@ int NetEqImpl::DoRfc3389Cng(PacketList* packet_list, bool play_dtmf) {
|
| return 0;
|
| }
|
|
|
| -void NetEqImpl::DoCodecInternalCng() {
|
| - int length = 0;
|
| - // TODO(hlundin): Will probably need a longer buffer for multi-channel.
|
| - int16_t decoded_buffer[kMaxFrameSize];
|
| - AudioDecoder* decoder = decoder_database_->GetActiveDecoder();
|
| - if (decoder) {
|
| - const uint8_t* dummy_payload = NULL;
|
| - AudioDecoder::SpeechType speech_type;
|
| - length = decoder->Decode(
|
| - dummy_payload, 0, fs_hz_, kMaxFrameSize * sizeof(int16_t),
|
| - decoded_buffer, &speech_type);
|
| - }
|
| - assert(mute_factor_array_.get());
|
| - normal_->Process(decoded_buffer, length, last_mode_, mute_factor_array_.get(),
|
| - algorithm_buffer_.get());
|
| +void NetEqImpl::DoCodecInternalCng(const int16_t* decoded_buffer,
|
| + size_t decoded_length) {
|
| + RTC_DCHECK(normal_.get());
|
| + RTC_DCHECK(mute_factor_array_.get());
|
| + normal_->Process(decoded_buffer, decoded_length, last_mode_,
|
| + mute_factor_array_.get(), algorithm_buffer_.get());
|
| last_mode_ = kModeCodecInternalCng;
|
| expand_->Reset();
|
| }
|
|
|