Reland r8476 "Set decoder output frequency in AudioDecoder::Decode call"
This should be safe to land now that issue 4143 was resolved (in r8492).
This change effectively reverts 8488.
TBR=kwiberg@webrtc.org
Original commit message:
This CL changes the way the decoder sample rate is set and updated. In
practice, it only concerns the iSAC (float) codec.
One single iSAC decoder instance is used for both wideband and
super-wideband decoding, and the instance must be told to switch
output frequency if the payload type changes. This used to be done
through a call to UpdateDecoderSampleRate, but is now instead done in
the Decode call as an extra parameter.
Review URL: https://webrtc-codereview.appspot.com/39289004
Cr-Original-Commit-Position: refs/heads/master@{#8496}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: 1eda4e3db60f484d179cee359e150c4f0c9c7c67
diff --git a/modules/audio_coding/codecs/audio_decoder.cc b/modules/audio_coding/codecs/audio_decoder.cc
index bc6b9c5..0817873 100644
--- a/modules/audio_coding/codecs/audio_decoder.cc
+++ b/modules/audio_coding/codecs/audio_decoder.cc
@@ -18,9 +18,10 @@
int AudioDecoder::DecodeRedundant(const uint8_t* encoded,
size_t encoded_len,
+ int sample_rate_hz,
int16_t* decoded,
SpeechType* speech_type) {
- return Decode(encoded, encoded_len, decoded, speech_type);
+ return Decode(encoded, encoded_len, sample_rate_hz, decoded, speech_type);
}
bool AudioDecoder::HasDecodePlc() const { return false; }
diff --git a/modules/audio_coding/codecs/audio_decoder.h b/modules/audio_coding/codecs/audio_decoder.h
index 30fdc44..8c83e61 100644
--- a/modules/audio_coding/codecs/audio_decoder.h
+++ b/modules/audio_coding/codecs/audio_decoder.h
@@ -37,14 +37,22 @@
// Decodes |encode_len| bytes from |encoded| and writes the result in
// |decoded|. The number of samples from all channels produced is in
// the return value. If the decoder produced comfort noise, |speech_type|
- // is set to kComfortNoise, otherwise it is kSpeech.
- virtual int Decode(const uint8_t* encoded, size_t encoded_len,
- int16_t* decoded, SpeechType* speech_type) = 0;
+ // is set to kComfortNoise, otherwise it is kSpeech. The desired output
+ // sample rate is provided in |sample_rate_hz|, which must be valid for the
+ // codec at hand.
+ virtual int Decode(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) = 0;
// Same as Decode(), but interfaces to the decoders redundant decode function.
// The default implementation simply calls the regular Decode() method.
- virtual int DecodeRedundant(const uint8_t* encoded, size_t encoded_len,
- int16_t* decoded, SpeechType* speech_type);
+ virtual int DecodeRedundant(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type);
// Indicates if the decoder implements the DecodePlc method.
virtual bool HasDecodePlc() const;
diff --git a/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h b/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h
index 994d21b..668f491 100644
--- a/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h
+++ b/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h
@@ -66,8 +66,6 @@
explicit AudioEncoderDecoderIsacT(const ConfigAdaptive& config);
virtual ~AudioEncoderDecoderIsacT() OVERRIDE;
- void UpdateDecoderSampleRate(int sample_rate_hz);
-
// AudioEncoder public methods.
virtual int SampleRateHz() const OVERRIDE;
virtual int NumChannels() const OVERRIDE;
@@ -77,10 +75,12 @@
// AudioDecoder methods.
virtual int Decode(const uint8_t* encoded,
size_t encoded_len,
+ int sample_rate_hz,
int16_t* decoded,
SpeechType* speech_type) OVERRIDE;
virtual int DecodeRedundant(const uint8_t* encoded,
size_t encoded_len,
+ int sample_rate_hz,
int16_t* decoded,
SpeechType* speech_type) OVERRIDE;
virtual bool HasDecodePlc() const OVERRIDE;
@@ -116,6 +116,8 @@
typename T::instance_type* isac_state_
GUARDED_BY(state_lock_) /* PT_GUARDED_BY(lock_)*/;
+ int decoder_sample_rate_hz_ GUARDED_BY(state_lock_);
+
// Must be acquired before state_lock_.
const scoped_ptr<CriticalSectionWrapper> lock_;
diff --git a/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h b/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h
index 095bb7b..d9cec82 100644
--- a/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h
+++ b/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h
@@ -109,6 +109,7 @@
: payload_type_(config.payload_type),
red_payload_type_(config.red_payload_type),
state_lock_(CriticalSectionWrapper::CreateCriticalSection()),
+ decoder_sample_rate_hz_(0),
lock_(CriticalSectionWrapper::CreateCriticalSection()),
packet_in_progress_(false),
redundant_length_bytes_(0) {
@@ -136,6 +137,7 @@
: payload_type_(config.payload_type),
red_payload_type_(config.red_payload_type),
state_lock_(CriticalSectionWrapper::CreateCriticalSection()),
+ decoder_sample_rate_hz_(0),
lock_(CriticalSectionWrapper::CreateCriticalSection()),
packet_in_progress_(false),
redundant_length_bytes_(0) {
@@ -160,12 +162,6 @@
}
template <typename T>
-void AudioEncoderDecoderIsacT<T>::UpdateDecoderSampleRate(int sample_rate_hz) {
- CriticalSectionScoped cs(state_lock_.get());
- CHECK_EQ(0, T::SetDecSampRate(isac_state_, sample_rate_hz));
-}
-
-template <typename T>
int AudioEncoderDecoderIsacT<T>::SampleRateHz() const {
CriticalSectionScoped cs(state_lock_.get());
return T::EncSampRate(isac_state_);
@@ -270,9 +266,16 @@
template <typename T>
int AudioEncoderDecoderIsacT<T>::Decode(const uint8_t* encoded,
size_t encoded_len,
+ int sample_rate_hz,
int16_t* decoded,
SpeechType* speech_type) {
CriticalSectionScoped cs(state_lock_.get());
+ CHECK(sample_rate_hz == 16000 || sample_rate_hz == 32000)
+ << "Unsupported sample rate " << sample_rate_hz;
+ if (sample_rate_hz != decoder_sample_rate_hz_) {
+ CHECK_EQ(0, T::SetDecSampRate(isac_state_, sample_rate_hz));
+ decoder_sample_rate_hz_ = sample_rate_hz;
+ }
int16_t temp_type = 1; // Default is speech.
int16_t ret =
T::Decode(isac_state_, encoded, static_cast<int16_t>(encoded_len),
@@ -284,6 +287,7 @@
template <typename T>
int AudioEncoderDecoderIsacT<T>::DecodeRedundant(const uint8_t* encoded,
size_t encoded_len,
+ int /*sample_rate_hz*/,
int16_t* decoded,
SpeechType* speech_type) {
CriticalSectionScoped cs(state_lock_.get());
diff --git a/modules/audio_coding/main/acm2/acm_generic_codec.cc b/modules/audio_coding/main/acm2/acm_generic_codec.cc
index 1a0e483..71df8a3 100644
--- a/modules/audio_coding/main/acm2/acm_generic_codec.cc
+++ b/modules/audio_coding/main/acm2/acm_generic_codec.cc
@@ -158,18 +158,22 @@
int AudioDecoderProxy::Decode(const uint8_t* encoded,
size_t encoded_len,
+ int sample_rate_hz,
int16_t* decoded,
SpeechType* speech_type) {
CriticalSectionScoped decoder_lock(decoder_lock_.get());
- return decoder_->Decode(encoded, encoded_len, decoded, speech_type);
+ return decoder_->Decode(encoded, encoded_len, sample_rate_hz, decoded,
+ speech_type);
}
int AudioDecoderProxy::DecodeRedundant(const uint8_t* encoded,
size_t encoded_len,
+ int sample_rate_hz,
int16_t* decoded,
SpeechType* speech_type) {
CriticalSectionScoped decoder_lock(decoder_lock_.get());
- return decoder_->DecodeRedundant(encoded, encoded_len, decoded, speech_type);
+ return decoder_->DecodeRedundant(encoded, encoded_len, sample_rate_hz,
+ decoded, speech_type);
}
bool AudioDecoderProxy::HasDecodePlc() const {
@@ -549,28 +553,6 @@
ResetAudioEncoder();
}
-int16_t ACMGenericCodec::UpdateDecoderSampFreq(int16_t codec_id) {
-#ifdef WEBRTC_CODEC_ISAC
- WriteLockScoped wl(codec_wrapper_lock_);
- if (is_isac_) {
- switch (codec_id) {
- case ACMCodecDB::kISAC:
- static_cast<AudioEncoderDecoderIsac*>(audio_encoder_.get())
- ->UpdateDecoderSampleRate(16000);
- return 0;
- case ACMCodecDB::kISACSWB:
- case ACMCodecDB::kISACFB:
- static_cast<AudioEncoderDecoderIsac*>(audio_encoder_.get())
- ->UpdateDecoderSampleRate(32000);
- return 0;
- default:
- FATAL() << "Unexpected codec id.";
- }
- }
-#endif
- return 0;
-}
-
int32_t ACMGenericCodec::SetISACMaxPayloadSize(
const uint16_t max_payload_len_bytes) {
WriteLockScoped wl(codec_wrapper_lock_);
diff --git a/modules/audio_coding/main/acm2/acm_generic_codec.h b/modules/audio_coding/main/acm2/acm_generic_codec.h
index 933306d..fd3fbab 100644
--- a/modules/audio_coding/main/acm2/acm_generic_codec.h
+++ b/modules/audio_coding/main/acm2/acm_generic_codec.h
@@ -48,10 +48,12 @@
bool IsSet() const;
int Decode(const uint8_t* encoded,
size_t encoded_len,
+ int sample_rate_hz,
int16_t* decoded,
SpeechType* speech_type) override;
int DecodeRedundant(const uint8_t* encoded,
size_t encoded_len,
+ int sample_rate_hz,
int16_t* decoded,
SpeechType* speech_type) override;
bool HasDecodePlc() const override;
@@ -294,33 +296,6 @@
void SetCngPt(int sample_rate_hz, int payload_type);
///////////////////////////////////////////////////////////////////////////
- // UpdateDecoderSampFreq()
- // For most of the codecs this function does nothing. It must be
- // implemented for those codecs that one codec instance serves as the
- // decoder for different flavors of the codec. One example is iSAC. there,
- // iSAC 16 kHz and iSAC 32 kHz are treated as two different codecs with
- // different payload types, however, there is only one iSAC instance to
- // decode. The reason for that is we would like to decode and encode with
- // the same codec instance for bandwidth estimator to work.
- //
- // Each time that we receive a new payload type, we call this function to
- // prepare the decoder associated with the new payload. Normally, decoders
- // doesn't have to do anything. For iSAC the decoder has to change it's
- // sampling rate. The input parameter specifies the current flavor of the
- // codec in codec database. For instance, if we just got a SWB payload then
- // the input parameter is ACMCodecDB::isacswb.
- //
- // Input:
- // -codec_id : the ID of the codec associated with the
- // payload type that we just received.
- //
- // Return value:
- // 0 if succeeded in updating the decoder.
- // -1 if failed to update.
- //
- int16_t UpdateDecoderSampFreq(int16_t /* codec_id */);
-
- ///////////////////////////////////////////////////////////////////////////
// UpdateEncoderSampFreq()
// Call this function to update the encoder sampling frequency. This
// is for codecs where one payload-name supports several encoder sampling
diff --git a/modules/audio_coding/main/acm2/acm_receiver.cc b/modules/audio_coding/main/acm2/acm_receiver.cc
index 7acb45a..5041eb7 100644
--- a/modules/audio_coding/main/acm2/acm_receiver.cc
+++ b/modules/audio_coding/main/acm2/acm_receiver.cc
@@ -609,14 +609,6 @@
return last_audio_decoder_;
}
-int AcmReceiver::last_audio_payload_type() const {
- CriticalSectionScoped lock(crit_sect_.get());
- if (last_audio_decoder_ < 0)
- return -1;
- assert(decoders_[last_audio_decoder_].registered);
- return decoders_[last_audio_decoder_].payload_type;
-}
-
int AcmReceiver::RedPayloadType() const {
CriticalSectionScoped lock(crit_sect_.get());
if (ACMCodecDB::kRED < 0 ||
diff --git a/modules/audio_coding/main/acm2/acm_receiver.h b/modules/audio_coding/main/acm2/acm_receiver.h
index f3ef16f..43f304a 100644
--- a/modules/audio_coding/main/acm2/acm_receiver.h
+++ b/modules/audio_coding/main/acm2/acm_receiver.h
@@ -248,12 +248,6 @@
int last_audio_codec_id() const; // TODO(turajs): can be inline.
//
- // Return the payload-type of the last non-CNG/non-DTMF RTP packet. If no
- // non-CNG/non-DTMF packet is received -1 is returned.
- //
- int last_audio_payload_type() const; // TODO(turajs): can be inline.
-
- //
// Get the audio codec associated with the last non-CNG/non-DTMF received
// payload. If no non-CNG/non-DTMF packet is received -1 is returned,
// otherwise return 0.
diff --git a/modules/audio_coding/main/acm2/acm_receiver_unittest.cc b/modules/audio_coding/main/acm2/acm_receiver_unittest.cc
index 273bb5a..6b15718 100644
--- a/modules/audio_coding/main/acm2/acm_receiver_unittest.cc
+++ b/modules/audio_coding/main/acm2/acm_receiver_unittest.cc
@@ -321,7 +321,6 @@
// Has received, only, DTX. Last Audio codec is undefined.
EXPECT_EQ(-1, receiver_->LastAudioCodec(&codec));
EXPECT_EQ(-1, receiver_->last_audio_codec_id());
- EXPECT_EQ(-1, receiver_->last_audio_payload_type());
n = 0;
while (kCodecId[n] >= 0) { // Loop over codecs.
@@ -347,8 +346,6 @@
ASSERT_TRUE(packet_sent_);
}
EXPECT_EQ(kCodecId[n], receiver_->last_audio_codec_id());
- EXPECT_EQ(codecs_[kCodecId[n]].pltype,
- receiver_->last_audio_payload_type());
EXPECT_EQ(0, receiver_->LastAudioCodec(&codec));
EXPECT_TRUE(CodecsEqual(codecs_[kCodecId[n]], codec));
++n;
diff --git a/modules/audio_coding/main/acm2/acm_receiver_unittest_oldapi.cc b/modules/audio_coding/main/acm2/acm_receiver_unittest_oldapi.cc
index 5b2c3cb..d57d511 100644
--- a/modules/audio_coding/main/acm2/acm_receiver_unittest_oldapi.cc
+++ b/modules/audio_coding/main/acm2/acm_receiver_unittest_oldapi.cc
@@ -325,7 +325,6 @@
// Has received, only, DTX. Last Audio codec is undefined.
EXPECT_EQ(-1, receiver_->LastAudioCodec(&codec));
EXPECT_EQ(-1, receiver_->last_audio_codec_id());
- EXPECT_EQ(-1, receiver_->last_audio_payload_type());
n = 0;
while (kCodecId[n] >= 0) { // Loop over codecs.
@@ -351,8 +350,6 @@
ASSERT_TRUE(packet_sent_);
}
EXPECT_EQ(kCodecId[n], receiver_->last_audio_codec_id());
- EXPECT_EQ(codecs_[kCodecId[n]].pltype,
- receiver_->last_audio_payload_type());
EXPECT_EQ(0, receiver_->LastAudioCodec(&codec));
EXPECT_TRUE(CodecsEqual(codecs_[kCodecId[n]], codec));
++n;
diff --git a/modules/audio_coding/main/acm2/audio_coding_module_impl.cc b/modules/audio_coding/main/acm2/audio_coding_module_impl.cc
index 41e8d4d..bf9bb01 100644
--- a/modules/audio_coding/main/acm2/audio_coding_module_impl.cc
+++ b/modules/audio_coding/main/acm2/audio_coding_module_impl.cc
@@ -1185,24 +1185,7 @@
int AudioCodingModuleImpl::IncomingPacket(const uint8_t* incoming_payload,
const size_t payload_length,
const WebRtcRTPHeader& rtp_header) {
- int last_audio_pltype = receiver_.last_audio_payload_type();
- if (receiver_.InsertPacket(rtp_header, incoming_payload, payload_length) <
- 0) {
- return -1;
- }
- if (receiver_.last_audio_payload_type() != last_audio_pltype) {
- int index = receiver_.last_audio_codec_id();
- assert(index >= 0);
- CriticalSectionScoped lock(acm_crit_sect_);
-
- // |codec_[index]| might not be even created, simply because it is not
- // yet registered as send codec. Even if it is registered, unless the
- // codec shares same instance for encoder and decoder, this call is
- // useless.
- if (codecs_[index] != NULL)
- codecs_[index]->UpdateDecoderSampFreq(index);
- }
- return 0;
+ return receiver_.InsertPacket(rtp_header, incoming_payload, payload_length);
}
// Minimum playout delay (Used for lip-sync).
diff --git a/modules/audio_coding/neteq/audio_decoder_impl.cc b/modules/audio_coding/neteq/audio_decoder_impl.cc
index 43ba241..f77dead 100644
--- a/modules/audio_coding/neteq/audio_decoder_impl.cc
+++ b/modules/audio_coding/neteq/audio_decoder_impl.cc
@@ -38,8 +38,12 @@
namespace webrtc {
// PCMu
-int AudioDecoderPcmU::Decode(const uint8_t* encoded, size_t encoded_len,
- int16_t* decoded, SpeechType* speech_type) {
+int AudioDecoderPcmU::Decode(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) {
+ DCHECK_EQ(sample_rate_hz, 8000);
int16_t temp_type = 1; // Default is speech.
int16_t ret = WebRtcG711_DecodeU(encoded, static_cast<int16_t>(encoded_len),
decoded, &temp_type);
@@ -54,8 +58,12 @@
}
// PCMa
-int AudioDecoderPcmA::Decode(const uint8_t* encoded, size_t encoded_len,
- int16_t* decoded, SpeechType* speech_type) {
+int AudioDecoderPcmA::Decode(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) {
+ DCHECK_EQ(sample_rate_hz, 8000);
int16_t temp_type = 1; // Default is speech.
int16_t ret = WebRtcG711_DecodeA(encoded, static_cast<int16_t>(encoded_len),
decoded, &temp_type);
@@ -73,8 +81,14 @@
#ifdef WEBRTC_CODEC_PCM16
AudioDecoderPcm16B::AudioDecoderPcm16B() {}
-int AudioDecoderPcm16B::Decode(const uint8_t* encoded, size_t encoded_len,
- int16_t* decoded, SpeechType* speech_type) {
+int AudioDecoderPcm16B::Decode(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) {
+ DCHECK(sample_rate_hz == 8000 || sample_rate_hz == 16000 ||
+ sample_rate_hz == 32000 || sample_rate_hz == 48000)
+ << "Unsupported sample rate " << sample_rate_hz;
int16_t ret =
WebRtcPcm16b_Decode(encoded, static_cast<int16_t>(encoded_len), decoded);
*speech_type = ConvertSpeechType(1);
@@ -103,8 +117,12 @@
WebRtcIlbcfix_DecoderFree(dec_state_);
}
-int AudioDecoderIlbc::Decode(const uint8_t* encoded, size_t encoded_len,
- int16_t* decoded, SpeechType* speech_type) {
+int AudioDecoderIlbc::Decode(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) {
+ DCHECK_EQ(sample_rate_hz, 8000);
int16_t temp_type = 1; // Default is speech.
int16_t ret = WebRtcIlbcfix_Decode(dec_state_, encoded,
static_cast<int16_t>(encoded_len), decoded,
@@ -132,8 +150,12 @@
WebRtcG722_FreeDecoder(dec_state_);
}
-int AudioDecoderG722::Decode(const uint8_t* encoded, size_t encoded_len,
- int16_t* decoded, SpeechType* speech_type) {
+int AudioDecoderG722::Decode(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) {
+ DCHECK_EQ(sample_rate_hz, 16000);
int16_t temp_type = 1; // Default is speech.
int16_t ret =
WebRtcG722_Decode(dec_state_, encoded, static_cast<int16_t>(encoded_len),
@@ -163,8 +185,12 @@
WebRtcG722_FreeDecoder(dec_state_right_);
}
-int AudioDecoderG722Stereo::Decode(const uint8_t* encoded, size_t encoded_len,
- int16_t* decoded, SpeechType* speech_type) {
+int AudioDecoderG722Stereo::Decode(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) {
+ DCHECK_EQ(sample_rate_hz, 16000);
int16_t temp_type = 1; // Default is speech.
// De-interleave the bit-stream into two separate payloads.
uint8_t* encoded_deinterleaved = new uint8_t[encoded_len];
@@ -244,8 +270,12 @@
WebRtcOpus_DecoderFree(dec_state_);
}
-int AudioDecoderOpus::Decode(const uint8_t* encoded, size_t encoded_len,
- int16_t* decoded, SpeechType* speech_type) {
+int AudioDecoderOpus::Decode(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) {
+ DCHECK_EQ(sample_rate_hz, 48000);
int16_t temp_type = 1; // Default is speech.
int16_t ret = WebRtcOpus_Decode(dec_state_, encoded,
static_cast<int16_t>(encoded_len), decoded,
@@ -257,11 +287,13 @@
}
int AudioDecoderOpus::DecodeRedundant(const uint8_t* encoded,
- size_t encoded_len, int16_t* decoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
SpeechType* speech_type) {
if (!PacketHasFec(encoded, encoded_len)) {
// This packet is a RED packet.
- return Decode(encoded, encoded_len, decoded, speech_type);
+ return Decode(encoded, encoded_len, sample_rate_hz, decoded, speech_type);
}
int16_t temp_type = 1; // Default is speech.
diff --git a/modules/audio_coding/neteq/audio_decoder_impl.h b/modules/audio_coding/neteq/audio_decoder_impl.h
index 57bd522..7d36a39 100644
--- a/modules/audio_coding/neteq/audio_decoder_impl.h
+++ b/modules/audio_coding/neteq/audio_decoder_impl.h
@@ -37,8 +37,11 @@
class AudioDecoderPcmU : public AudioDecoder {
public:
AudioDecoderPcmU() {}
- virtual int Decode(const uint8_t* encoded, size_t encoded_len,
- int16_t* decoded, SpeechType* speech_type);
+ virtual int Decode(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type);
virtual int Init() { return 0; }
virtual int PacketDuration(const uint8_t* encoded, size_t encoded_len) const;
@@ -49,8 +52,11 @@
class AudioDecoderPcmA : public AudioDecoder {
public:
AudioDecoderPcmA() {}
- virtual int Decode(const uint8_t* encoded, size_t encoded_len,
- int16_t* decoded, SpeechType* speech_type);
+ virtual int Decode(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type);
virtual int Init() { return 0; }
virtual int PacketDuration(const uint8_t* encoded, size_t encoded_len) const;
@@ -86,8 +92,11 @@
class AudioDecoderPcm16B : public AudioDecoder {
public:
AudioDecoderPcm16B();
- virtual int Decode(const uint8_t* encoded, size_t encoded_len,
- int16_t* decoded, SpeechType* speech_type);
+ virtual int Decode(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type);
virtual int Init() { return 0; }
virtual int PacketDuration(const uint8_t* encoded, size_t encoded_len) const;
@@ -112,8 +121,11 @@
public:
AudioDecoderIlbc();
virtual ~AudioDecoderIlbc();
- virtual int Decode(const uint8_t* encoded, size_t encoded_len,
- int16_t* decoded, SpeechType* speech_type);
+ virtual int Decode(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type);
virtual bool HasDecodePlc() const { return true; }
virtual int DecodePlc(int num_frames, int16_t* decoded);
virtual int Init();
@@ -129,8 +141,11 @@
public:
AudioDecoderG722();
virtual ~AudioDecoderG722();
- virtual int Decode(const uint8_t* encoded, size_t encoded_len,
- int16_t* decoded, SpeechType* speech_type);
+ virtual int Decode(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type);
virtual bool HasDecodePlc() const { return false; }
virtual int Init();
virtual int PacketDuration(const uint8_t* encoded, size_t encoded_len) const;
@@ -144,8 +159,11 @@
public:
AudioDecoderG722Stereo();
virtual ~AudioDecoderG722Stereo();
- virtual int Decode(const uint8_t* encoded, size_t encoded_len,
- int16_t* decoded, SpeechType* speech_type);
+ virtual int Decode(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type);
virtual int Init();
private:
@@ -169,10 +187,16 @@
public:
explicit AudioDecoderOpus(int num_channels);
virtual ~AudioDecoderOpus();
- virtual int Decode(const uint8_t* encoded, size_t encoded_len,
- int16_t* decoded, SpeechType* speech_type);
- virtual int DecodeRedundant(const uint8_t* encoded, size_t encoded_len,
- int16_t* decoded, SpeechType* speech_type);
+ virtual int Decode(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type);
+ virtual int DecodeRedundant(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type);
virtual int Init();
virtual int PacketDuration(const uint8_t* encoded, size_t encoded_len) const;
virtual int PacketDurationRedundant(const uint8_t* encoded,
@@ -195,8 +219,13 @@
public:
explicit AudioDecoderCng();
virtual ~AudioDecoderCng();
- virtual int Decode(const uint8_t* encoded, size_t encoded_len,
- int16_t* decoded, SpeechType* speech_type) { return -1; }
+ virtual int Decode(const uint8_t* encoded,
+ size_t encoded_len,
+ int /*sample_rate_hz*/,
+ int16_t* decoded,
+ SpeechType* speech_type) {
+ return -1;
+ }
virtual int Init();
virtual int IncomingPacket(const uint8_t* payload,
size_t payload_len,
diff --git a/modules/audio_coding/neteq/audio_decoder_unittest.cc b/modules/audio_coding/neteq/audio_decoder_unittest.cc
index 95805d3..1f0e881 100644
--- a/modules/audio_coding/neteq/audio_decoder_unittest.cc
+++ b/modules/audio_coding/neteq/audio_decoder_unittest.cc
@@ -186,10 +186,9 @@
// Make sure that frame_size_ * channels_ samples are allocated and free.
decoded.resize((processed_samples + frame_size_) * channels_, 0);
AudioDecoder::SpeechType speech_type;
- size_t dec_len = decoder_->Decode(&encoded_[encoded_bytes_],
- enc_len,
- &decoded[processed_samples * channels_],
- &speech_type);
+ size_t dec_len = decoder_->Decode(
+ &encoded_[encoded_bytes_], enc_len, codec_input_rate_hz_,
+ &decoded[processed_samples * channels_], &speech_type);
EXPECT_EQ(frame_size_ * channels_, dec_len);
encoded_bytes_ += enc_len;
processed_samples += frame_size_;
@@ -222,13 +221,15 @@
AudioDecoder::SpeechType speech_type1, speech_type2;
EXPECT_EQ(0, decoder_->Init());
scoped_ptr<int16_t[]> output1(new int16_t[frame_size_ * channels_]);
- dec_len = decoder_->Decode(encoded_, enc_len, output1.get(), &speech_type1);
+ dec_len = decoder_->Decode(encoded_, enc_len, codec_input_rate_hz_,
+ output1.get(), &speech_type1);
ASSERT_LE(dec_len, frame_size_ * channels_);
EXPECT_EQ(frame_size_ * channels_, dec_len);
// Re-init decoder and decode again.
EXPECT_EQ(0, decoder_->Init());
scoped_ptr<int16_t[]> output2(new int16_t[frame_size_ * channels_]);
- dec_len = decoder_->Decode(encoded_, enc_len, output2.get(), &speech_type2);
+ dec_len = decoder_->Decode(encoded_, enc_len, codec_input_rate_hz_,
+ output2.get(), &speech_type2);
ASSERT_LE(dec_len, frame_size_ * channels_);
EXPECT_EQ(frame_size_ * channels_, dec_len);
for (unsigned int n = 0; n < frame_size_; ++n) {
@@ -247,8 +248,8 @@
AudioDecoder::SpeechType speech_type;
EXPECT_EQ(0, decoder_->Init());
scoped_ptr<int16_t[]> output(new int16_t[frame_size_ * channels_]);
- size_t dec_len =
- decoder_->Decode(encoded_, enc_len, output.get(), &speech_type);
+ size_t dec_len = decoder_->Decode(encoded_, enc_len, codec_input_rate_hz_,
+ output.get(), &speech_type);
EXPECT_EQ(frame_size_ * channels_, dec_len);
// Call DecodePlc and verify that we get one frame of data.
// (Overwrite the output from the above Decode call, but that does not
@@ -338,8 +339,8 @@
AudioDecoder::SpeechType speech_type;
EXPECT_EQ(0, decoder_->Init());
scoped_ptr<int16_t[]> output(new int16_t[frame_size_ * channels_]);
- size_t dec_len =
- decoder_->Decode(encoded_, enc_len, output.get(), &speech_type);
+ size_t dec_len = decoder_->Decode(encoded_, enc_len, codec_input_rate_hz_,
+ output.get(), &speech_type);
EXPECT_EQ(frame_size_, dec_len);
// Simply call DecodePlc and verify that we get 0 as return value.
EXPECT_EQ(0, decoder_->DecodePlc(1, output.get()));
diff --git a/modules/audio_coding/neteq/mock/mock_audio_decoder.h b/modules/audio_coding/neteq/mock/mock_audio_decoder.h
index 503e46f..7288f11 100644
--- a/modules/audio_coding/neteq/mock/mock_audio_decoder.h
+++ b/modules/audio_coding/neteq/mock/mock_audio_decoder.h
@@ -22,8 +22,9 @@
MockAudioDecoder() {}
virtual ~MockAudioDecoder() { Die(); }
MOCK_METHOD0(Die, void());
- MOCK_METHOD4(Decode, int(const uint8_t*, size_t, int16_t*,
- AudioDecoder::SpeechType*));
+ MOCK_METHOD5(
+ Decode,
+ int(const uint8_t*, size_t, int, int16_t*, AudioDecoder::SpeechType*));
MOCK_CONST_METHOD0(HasDecodePlc, bool());
MOCK_METHOD2(DecodePlc, int(int, int16_t*));
MOCK_METHOD0(Init, int());
diff --git a/modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h b/modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h
index 19f069a..22d2816 100644
--- a/modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h
+++ b/modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h
@@ -29,8 +29,11 @@
public:
ExternalPcm16B() {}
- virtual int Decode(const uint8_t* encoded, size_t encoded_len,
- int16_t* decoded, SpeechType* speech_type) {
+ virtual int Decode(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) {
int16_t ret = WebRtcPcm16b_Decode(
encoded, static_cast<int16_t>(encoded_len), decoded);
*speech_type = ConvertSpeechType(1);
@@ -49,7 +52,7 @@
public:
MockExternalPcm16B() {
// By default, all calls are delegated to the real object.
- ON_CALL(*this, Decode(_, _, _, _))
+ ON_CALL(*this, Decode(_, _, _, _, _))
.WillByDefault(Invoke(&real_, &ExternalPcm16B::Decode));
ON_CALL(*this, HasDecodePlc())
.WillByDefault(Invoke(&real_, &ExternalPcm16B::HasDecodePlc));
@@ -65,9 +68,12 @@
virtual ~MockExternalPcm16B() { Die(); }
MOCK_METHOD0(Die, void());
- MOCK_METHOD4(Decode,
- int(const uint8_t* encoded, size_t encoded_len, int16_t* decoded,
- SpeechType* speech_type));
+ MOCK_METHOD5(Decode,
+ int(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type));
MOCK_CONST_METHOD0(HasDecodePlc,
bool());
MOCK_METHOD2(DecodePlc,
diff --git a/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc b/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc
index a3dd271..0449044 100644
--- a/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc
@@ -100,7 +100,8 @@
next_arrival_time = GetArrivalTime(next_send_time);
} while (Lost()); // If lost, immediately read the next packet.
- EXPECT_CALL(*external_decoder_, Decode(_, payload_size_bytes_, _, _))
+ EXPECT_CALL(*external_decoder_,
+ Decode(_, payload_size_bytes_, 1000 * samples_per_ms_, _, _))
.Times(NumExpectedDecodeCalls(num_loops));
uint32_t time_now = 0;
diff --git a/modules/audio_coding/neteq/neteq_impl.cc b/modules/audio_coding/neteq/neteq_impl.cc
index f1a3a90..7370825 100644
--- a/modules/audio_coding/neteq/neteq_impl.cc
+++ b/modules/audio_coding/neteq/neteq_impl.cc
@@ -1266,7 +1266,7 @@
", ssrc=" << packet->header.ssrc <<
", len=" << packet->payload_length;
decode_length = decoder->DecodeRedundant(
- packet->payload, packet->payload_length,
+ packet->payload, packet->payload_length, fs_hz_,
&decoded_buffer_[*decoded_length], speech_type);
} else {
LOG(LS_VERBOSE) << "Decoding packet: ts=" << packet->header.timestamp <<
@@ -1274,10 +1274,9 @@
", pt=" << static_cast<int>(packet->header.payloadType) <<
", ssrc=" << packet->header.ssrc <<
", len=" << packet->payload_length;
- decode_length = decoder->Decode(packet->payload,
- packet->payload_length,
- &decoded_buffer_[*decoded_length],
- speech_type);
+ decode_length =
+ decoder->Decode(packet->payload, packet->payload_length, fs_hz_,
+ &decoded_buffer_[*decoded_length], speech_type);
}
delete[] packet->payload;
@@ -1607,7 +1606,8 @@
if (decoder) {
const uint8_t* dummy_payload = NULL;
AudioDecoder::SpeechType speech_type;
- length = decoder->Decode(dummy_payload, 0, decoded_buffer, &speech_type);
+ length =
+ decoder->Decode(dummy_payload, 0, fs_hz_, decoded_buffer, &speech_type);
}
assert(mute_factor_array_.get());
normal_->Process(decoded_buffer, length, last_mode_, mute_factor_array_.get(),
diff --git a/modules/audio_coding/neteq/neteq_impl_unittest.cc b/modules/audio_coding/neteq/neteq_impl_unittest.cc
index 36ed35a..54b393b 100644
--- a/modules/audio_coding/neteq/neteq_impl_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_impl_unittest.cc
@@ -430,6 +430,7 @@
// Produce as many samples as input bytes (|encoded_len|).
virtual int Decode(const uint8_t* encoded,
size_t encoded_len,
+ int /*sample_rate_hz*/,
int16_t* decoded,
SpeechType* speech_type) {
for (size_t i = 0; i < encoded_len; ++i) {
@@ -521,10 +522,11 @@
int16_t dummy_output[kPayloadLengthSamples] = {0};
// The below expectation will make the mock decoder write
// |kPayloadLengthSamples| zeros to the output array, and mark it as speech.
- EXPECT_CALL(mock_decoder, Decode(Pointee(0), kPayloadLengthBytes, _, _))
- .WillOnce(DoAll(SetArrayArgument<2>(dummy_output,
+ EXPECT_CALL(mock_decoder,
+ Decode(Pointee(0), kPayloadLengthBytes, kSampleRateHz, _, _))
+ .WillOnce(DoAll(SetArrayArgument<3>(dummy_output,
dummy_output + kPayloadLengthSamples),
- SetArgPointee<3>(AudioDecoder::kSpeech),
+ SetArgPointee<4>(AudioDecoder::kSpeech),
Return(kPayloadLengthSamples)));
EXPECT_EQ(NetEq::kOK,
neteq_->RegisterExternalDecoder(
@@ -566,10 +568,11 @@
// Expect only the second packet to be decoded (the one with "2" as the first
// payload byte).
- EXPECT_CALL(mock_decoder, Decode(Pointee(2), kPayloadLengthBytes, _, _))
- .WillOnce(DoAll(SetArrayArgument<2>(dummy_output,
+ EXPECT_CALL(mock_decoder,
+ Decode(Pointee(2), kPayloadLengthBytes, kSampleRateHz, _, _))
+ .WillOnce(DoAll(SetArrayArgument<3>(dummy_output,
dummy_output + kPayloadLengthSamples),
- SetArgPointee<3>(AudioDecoder::kSpeech),
+ SetArgPointee<4>(AudioDecoder::kSpeech),
Return(kPayloadLengthSamples)));
// Pull audio once.
@@ -682,28 +685,31 @@
// Pointee(x) verifies that first byte of the payload equals x, this makes it
// possible to verify that the correct payload is fed to Decode().
- EXPECT_CALL(mock_decoder, Decode(Pointee(0), kPayloadLengthBytes, _, _))
- .WillOnce(DoAll(SetArrayArgument<2>(dummy_output,
+ EXPECT_CALL(mock_decoder, Decode(Pointee(0), kPayloadLengthBytes,
+ kSampleRateKhz * 1000, _, _))
+ .WillOnce(DoAll(SetArrayArgument<3>(dummy_output,
dummy_output + kPayloadLengthSamples),
- SetArgPointee<3>(AudioDecoder::kSpeech),
+ SetArgPointee<4>(AudioDecoder::kSpeech),
Return(kPayloadLengthSamples)));
- EXPECT_CALL(mock_decoder, Decode(Pointee(1), kPayloadLengthBytes, _, _))
- .WillOnce(DoAll(SetArrayArgument<2>(dummy_output,
+ EXPECT_CALL(mock_decoder, Decode(Pointee(1), kPayloadLengthBytes,
+ kSampleRateKhz * 1000, _, _))
+ .WillOnce(DoAll(SetArrayArgument<3>(dummy_output,
dummy_output + kPayloadLengthSamples),
- SetArgPointee<3>(AudioDecoder::kComfortNoise),
+ SetArgPointee<4>(AudioDecoder::kComfortNoise),
Return(kPayloadLengthSamples)));
- EXPECT_CALL(mock_decoder, Decode(IsNull(), 0, _, _))
- .WillOnce(DoAll(SetArrayArgument<2>(dummy_output,
+ EXPECT_CALL(mock_decoder, Decode(IsNull(), 0, kSampleRateKhz * 1000, _, _))
+ .WillOnce(DoAll(SetArrayArgument<3>(dummy_output,
dummy_output + kPayloadLengthSamples),
- SetArgPointee<3>(AudioDecoder::kComfortNoise),
+ SetArgPointee<4>(AudioDecoder::kComfortNoise),
Return(kPayloadLengthSamples)));
- EXPECT_CALL(mock_decoder, Decode(Pointee(2), kPayloadLengthBytes, _, _))
- .WillOnce(DoAll(SetArrayArgument<2>(dummy_output,
+ EXPECT_CALL(mock_decoder, Decode(Pointee(2), kPayloadLengthBytes,
+ kSampleRateKhz * 1000, _, _))
+ .WillOnce(DoAll(SetArrayArgument<3>(dummy_output,
dummy_output + kPayloadLengthSamples),
- SetArgPointee<3>(AudioDecoder::kSpeech),
+ SetArgPointee<4>(AudioDecoder::kSpeech),
Return(kPayloadLengthSamples)));
EXPECT_EQ(NetEq::kOK,
diff --git a/modules/audio_coding/neteq/neteq_network_stats_unittest.cc b/modules/audio_coding/neteq/neteq_network_stats_unittest.cc
index b61bf83..cdcf0b3 100644
--- a/modules/audio_coding/neteq/neteq_network_stats_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_network_stats_unittest.cc
@@ -36,16 +36,22 @@
MOCK_METHOD0(Init, int());
// Override the following methods such that no actual payload is needed.
- int Decode(const uint8_t* encoded, size_t encoded_len, int16_t* decoded,
+ int Decode(const uint8_t* encoded,
+ size_t encoded_len,
+ int /*sample_rate_hz*/,
+ int16_t* decoded,
SpeechType* speech_type) override {
*speech_type = kSpeech;
memset(decoded, 0, sizeof(int16_t) * kPacketDuration * channels_);
return kPacketDuration * channels_;
}
- int DecodeRedundant(const uint8_t* encoded, size_t encoded_len,
- int16_t* decoded, SpeechType* speech_type) override {
- return Decode(encoded, encoded_len, decoded, speech_type);
+ int DecodeRedundant(const uint8_t* encoded,
+ size_t encoded_len,
+ int sample_rate_hz,
+ int16_t* decoded,
+ SpeechType* speech_type) override {
+ return Decode(encoded, encoded_len, sample_rate_hz, decoded, speech_type);
}
int PacketDuration(const uint8_t* encoded,