Make an AudioEncoder subclass for iSAC
BUG=3926
Previously committed: https://code.google.com/p/webrtc/source/detail?r=7675
and reverted: https://code.google.com/p/webrtc/source/detail?r=7676
R=henrik.lundin@webrtc.org, kjellander@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/25359004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@7871 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/audio_coding/BUILD.gn b/webrtc/modules/audio_coding/BUILD.gn
index d680d6f..ec28431 100644
--- a/webrtc/modules/audio_coding/BUILD.gn
+++ b/webrtc/modules/audio_coding/BUILD.gn
@@ -369,11 +369,13 @@
source_set("isac") {
sources = [
+ "codecs/isac/main/interface/audio_encoder_isac.h",
"codecs/isac/main/interface/isac.h",
"codecs/isac/main/source/arith_routines.c",
"codecs/isac/main/source/arith_routines.h",
"codecs/isac/main/source/arith_routines_hist.c",
"codecs/isac/main/source/arith_routines_logist.c",
+ "codecs/isac/main/source/audio_encoder_isac.cc",
"codecs/isac/main/source/bandwidth_estimator.c",
"codecs/isac/main/source/bandwidth_estimator.h",
"codecs/isac/main/source/codec.h",
@@ -420,6 +422,12 @@
"codecs/isac/main/source/transform.c",
]
+ if (is_clang) {
+ # Suppress warnings from Chrome's Clang plugins.
+ # See http://code.google.com/p/webrtc/issues/detail?id=163 for details.
+ configs -= [ "//build/config/clang:find_bad_constructs" ]
+ }
+
if (is_linux) {
libs = [ "m" ]
}
@@ -431,7 +439,10 @@
":isac_config",
]
- deps = [ "../../common_audio" ]
+ deps = [
+ ":audio_decoder_interface",
+ "../../common_audio",
+ ]
}
config("isac_fix_config") {
diff --git a/webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h b/webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h
new file mode 100644
index 0000000..bf53b28
--- /dev/null
+++ b/webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INTERFACE_AUDIO_ENCODER_ISAC_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INTERFACE_AUDIO_ENCODER_ISAC_H_
+
+#include <vector>
+
+#include "webrtc/base/thread_annotations.h"
+#include "webrtc/modules/audio_coding/codecs/audio_decoder.h"
+#include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
+#include "webrtc/modules/audio_coding/codecs/isac/main/interface/isac.h"
+#include "webrtc/system_wrappers/interface/scoped_ptr.h"
+
+namespace webrtc {
+
+class CriticalSectionWrapper;
+
+class AudioEncoderDecoderIsac : public AudioEncoder, public AudioDecoder {
+ public:
+ // For constructing an encoder in instantaneous mode. Allowed combinations
+ // are
+ // - 16000 Hz, 30 ms, 10000-32000 bps
+ // - 16000 Hz, 60 ms, 10000-32000 bps
+ // - 32000 Hz, 30 ms, 10000-56000 bps
+ struct Config {
+ Config();
+ bool IsOk() const;
+ int payload_type;
+ int sample_rate_hz;
+ int frame_size_ms;
+ int bit_rate; // Limit on the short-term average bit rate, in bits/second.
+ };
+
+ // For constructing an encoder in channel-adaptive mode. The sample rate must
+ // be 16000 Hz; the initial frame size can be 30 or 60 ms; and the initial bit
+ // rate can be 10000-56000 bps.
+ struct ConfigAdaptive {
+ ConfigAdaptive();
+ bool IsOk() const;
+ int payload_type;
+ int sample_rate_hz;
+ int initial_frame_size_ms;
+ int initial_bit_rate;
+ bool enforce_frame_size; // Prevent adaptive changes to the frame size?
+ };
+
+ explicit AudioEncoderDecoderIsac(const Config& config);
+ explicit AudioEncoderDecoderIsac(const ConfigAdaptive& config);
+ virtual ~AudioEncoderDecoderIsac() OVERRIDE;
+
+ // AudioEncoder public methods.
+ virtual int sample_rate_hz() const OVERRIDE;
+ virtual int num_channels() const OVERRIDE;
+ virtual int Num10MsFramesInNextPacket() const OVERRIDE;
+ virtual int Max10MsFramesInAPacket() const OVERRIDE;
+
+ // AudioDecoder methods.
+ virtual int Decode(const uint8_t* encoded,
+ size_t encoded_len,
+ int16_t* decoded,
+ SpeechType* speech_type) OVERRIDE;
+ virtual int DecodeRedundant(const uint8_t* encoded,
+ size_t encoded_len,
+ int16_t* decoded,
+ SpeechType* speech_type) OVERRIDE;
+ virtual bool HasDecodePlc() const OVERRIDE;
+ virtual int DecodePlc(int num_frames, int16_t* decoded) OVERRIDE;
+ virtual int Init() OVERRIDE;
+ virtual int IncomingPacket(const uint8_t* payload,
+ size_t payload_len,
+ uint16_t rtp_sequence_number,
+ uint32_t rtp_timestamp,
+ uint32_t arrival_timestamp) OVERRIDE;
+ virtual int ErrorCode() OVERRIDE;
+
+ protected:
+ // AudioEncoder protected method.
+ virtual bool EncodeInternal(uint32_t timestamp,
+ const int16_t* audio,
+ size_t max_encoded_bytes,
+ uint8_t* encoded,
+ size_t* encoded_bytes,
+ EncodedInfo* info) OVERRIDE;
+
+ private:
+ const int payload_type_;
+
+ // iSAC encoder/decoder state, guarded by a mutex to ensure that encode calls
+ // from one thread won't clash with decode calls from another thread.
+ const scoped_ptr<CriticalSectionWrapper> lock_;
+ ISACStruct* isac_state_ GUARDED_BY(lock_);
+
+ // Have we accepted input but not yet emitted it in a packet?
+ bool packet_in_progress_;
+
+ // Timestamp of the first input of the currently in-progress packet.
+ uint32_t packet_timestamp_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioEncoderDecoderIsac);
+};
+
+} // namespace webrtc
+#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INTERFACE_AUDIO_ENCODER_ISAC_H_
diff --git a/webrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac.cc b/webrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac.cc
new file mode 100644
index 0000000..79e75e2
--- /dev/null
+++ b/webrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac.cc
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h"
+
+#include "webrtc/modules/audio_coding/codecs/isac/main/interface/isac.h"
+#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
+
+namespace webrtc {
+
+namespace {
+
+const int kIsacPayloadType = 103;
+
+int DivExact(int a, int b) {
+ CHECK_EQ(a % b, 0);
+ return a / b;
+}
+
+} // namespace
+
+AudioEncoderDecoderIsac::Config::Config()
+ : payload_type(kIsacPayloadType),
+ sample_rate_hz(16000),
+ frame_size_ms(30),
+ bit_rate(32000) {}
+
+bool AudioEncoderDecoderIsac::Config::IsOk() const {
+ switch (sample_rate_hz) {
+ case 16000:
+ return (frame_size_ms == 30 || frame_size_ms == 60) &&
+ bit_rate >= 10000 && bit_rate <= 32000;
+ case 32000:
+ return frame_size_ms == 30 && bit_rate >= 10000 && bit_rate <= 56000;
+ default:
+ return false;
+ }
+}
+
+AudioEncoderDecoderIsac::ConfigAdaptive::ConfigAdaptive()
+ : payload_type(kIsacPayloadType),
+ sample_rate_hz(16000),
+ initial_frame_size_ms(30),
+ initial_bit_rate(32000),
+ enforce_frame_size(false) {}
+
+bool AudioEncoderDecoderIsac::ConfigAdaptive::IsOk() const {
+ return sample_rate_hz == 16000 &&
+ (initial_frame_size_ms == 30 || initial_frame_size_ms == 60) &&
+ initial_bit_rate >= 10000 && initial_bit_rate <= 56000;
+}
+
+AudioEncoderDecoderIsac::AudioEncoderDecoderIsac(const Config& config)
+ : payload_type_(config.payload_type),
+ lock_(CriticalSectionWrapper::CreateCriticalSection()),
+ packet_in_progress_(false) {
+ CHECK(config.IsOk());
+ CHECK_EQ(0, WebRtcIsac_Create(&isac_state_));
+ CHECK_EQ(0, WebRtcIsac_EncoderInit(isac_state_, 1));
+ CHECK_EQ(0, WebRtcIsac_SetEncSampRate(isac_state_, config.sample_rate_hz));
+ CHECK_EQ(0, WebRtcIsac_Control(isac_state_, config.bit_rate,
+ config.frame_size_ms));
+ CHECK_EQ(0, WebRtcIsac_SetDecSampRate(isac_state_, config.sample_rate_hz));
+}
+
+AudioEncoderDecoderIsac::AudioEncoderDecoderIsac(const ConfigAdaptive& config)
+ : payload_type_(config.payload_type),
+ lock_(CriticalSectionWrapper::CreateCriticalSection()),
+ packet_in_progress_(false) {
+ CHECK(config.IsOk());
+ CHECK_EQ(0, WebRtcIsac_Create(&isac_state_));
+ CHECK_EQ(0, WebRtcIsac_EncoderInit(isac_state_, 0));
+ CHECK_EQ(0, WebRtcIsac_SetEncSampRate(isac_state_, config.sample_rate_hz));
+ CHECK_EQ(0, WebRtcIsac_ControlBwe(isac_state_, config.initial_bit_rate,
+ config.initial_frame_size_ms,
+ config.enforce_frame_size));
+ CHECK_EQ(0, WebRtcIsac_SetDecSampRate(isac_state_, config.sample_rate_hz));
+}
+
+AudioEncoderDecoderIsac::~AudioEncoderDecoderIsac() {
+ CHECK_EQ(0, WebRtcIsac_Free(isac_state_));
+}
+
+int AudioEncoderDecoderIsac::sample_rate_hz() const {
+ CriticalSectionScoped cs(lock_.get());
+ return WebRtcIsac_EncSampRate(isac_state_);
+}
+
+int AudioEncoderDecoderIsac::num_channels() const {
+ return 1;
+}
+
+int AudioEncoderDecoderIsac::Num10MsFramesInNextPacket() const {
+ CriticalSectionScoped cs(lock_.get());
+ const int samples_in_next_packet = WebRtcIsac_GetNewFrameLen(isac_state_);
+ return DivExact(samples_in_next_packet, DivExact(sample_rate_hz(), 100));
+}
+
+int AudioEncoderDecoderIsac::Max10MsFramesInAPacket() const {
+ return 6; // iSAC puts at most 60 ms in a packet.
+}
+
+bool AudioEncoderDecoderIsac::EncodeInternal(uint32_t timestamp,
+ const int16_t* audio,
+ size_t max_encoded_bytes,
+ uint8_t* encoded,
+ size_t* encoded_bytes,
+ EncodedInfo* info) {
+ if (!packet_in_progress_) {
+ // Starting a new packet; remember the timestamp for later.
+ packet_in_progress_ = true;
+ packet_timestamp_ = timestamp;
+ }
+ int r;
+ {
+ CriticalSectionScoped cs(lock_.get());
+ r = WebRtcIsac_Encode(isac_state_, audio, encoded);
+ }
+ if (r < 0) {
+ // An error occurred; propagate it to the caller.
+ packet_in_progress_ = false;
+ return false;
+ }
+
+ // WebRtcIsac_Encode doesn't allow us to tell it the size of the output
+ // buffer. All we can do is check for an overrun after the fact.
+ CHECK(static_cast<size_t>(r) <= max_encoded_bytes);
+
+ *encoded_bytes = r;
+ if (r > 0) {
+ // Got enough input to produce a packet. Return the saved timestamp from
+ // the first chunk of input that went into the packet.
+ packet_in_progress_ = false;
+ info->encoded_timestamp = packet_timestamp_;
+ info->payload_type = payload_type_;
+ }
+ return true;
+}
+
+int AudioEncoderDecoderIsac::Decode(const uint8_t* encoded,
+ size_t encoded_len,
+ int16_t* decoded,
+ SpeechType* speech_type) {
+ CriticalSectionScoped cs(lock_.get());
+ int16_t temp_type = 1; // Default is speech.
+ int16_t ret =
+ WebRtcIsac_Decode(isac_state_, encoded, static_cast<int16_t>(encoded_len),
+ decoded, &temp_type);
+ *speech_type = ConvertSpeechType(temp_type);
+ return ret;
+}
+
+int AudioEncoderDecoderIsac::DecodeRedundant(const uint8_t* encoded,
+ size_t encoded_len,
+ int16_t* decoded,
+ SpeechType* speech_type) {
+ CriticalSectionScoped cs(lock_.get());
+ int16_t temp_type = 1; // Default is speech.
+ int16_t ret = WebRtcIsac_DecodeRcu(isac_state_, encoded,
+ static_cast<int16_t>(encoded_len), decoded,
+ &temp_type);
+ *speech_type = ConvertSpeechType(temp_type);
+ return ret;
+}
+
+bool AudioEncoderDecoderIsac::HasDecodePlc() const { return true; }
+
+int AudioEncoderDecoderIsac::DecodePlc(int num_frames, int16_t* decoded) {
+ CriticalSectionScoped cs(lock_.get());
+ return WebRtcIsac_DecodePlc(isac_state_, decoded, num_frames);
+}
+
+int AudioEncoderDecoderIsac::Init() {
+ CriticalSectionScoped cs(lock_.get());
+ return WebRtcIsac_DecoderInit(isac_state_);
+}
+
+int AudioEncoderDecoderIsac::IncomingPacket(const uint8_t* payload,
+ size_t payload_len,
+ uint16_t rtp_sequence_number,
+ uint32_t rtp_timestamp,
+ uint32_t arrival_timestamp) {
+ CriticalSectionScoped cs(lock_.get());
+ return WebRtcIsac_UpdateBwEstimate(
+ isac_state_, payload, static_cast<int32_t>(payload_len),
+ rtp_sequence_number, rtp_timestamp, arrival_timestamp);
+}
+
+int AudioEncoderDecoderIsac::ErrorCode() {
+ CriticalSectionScoped cs(lock_.get());
+ return WebRtcIsac_GetErrorCode(isac_state_);
+}
+
+} // namespace webrtc
diff --git a/webrtc/modules/audio_coding/codecs/isac/main/source/isac.gypi b/webrtc/modules/audio_coding/codecs/isac/main/source/isac.gypi
index 5ed6d44..8f8cd35 100644
--- a/webrtc/modules/audio_coding/codecs/isac/main/source/isac.gypi
+++ b/webrtc/modules/audio_coding/codecs/isac/main/source/isac.gypi
@@ -13,6 +13,7 @@
'type': 'static_library',
'dependencies': [
'<(webrtc_root)/common_audio/common_audio.gyp:common_audio',
+ 'audio_decoder_interface',
],
'include_dirs': [
'../interface',
@@ -25,10 +26,12 @@
],
},
'sources': [
+ '../interface/audio_encoder_isac.h',
'../interface/isac.h',
'arith_routines.c',
'arith_routines_hist.c',
'arith_routines_logist.c',
+ 'audio_encoder_isac.cc',
'bandwidth_estimator.c',
'crc.c',
'decode.c',
diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc
index 4c0bd31..f565faf 100644
--- a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc
+++ b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc
@@ -26,7 +26,7 @@
#include "webrtc/modules/audio_coding/codecs/isac/fix/interface/isacfix.h"
#endif
#ifdef WEBRTC_CODEC_ISAC
-#include "webrtc/modules/audio_coding/codecs/isac/main/interface/isac.h"
+#include "webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h"
#endif
#ifdef WEBRTC_CODEC_OPUS
#include "webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h"
@@ -127,67 +127,6 @@
}
#endif
-// iSAC float
-#ifdef WEBRTC_CODEC_ISAC
-AudioDecoderIsac::AudioDecoderIsac(int decode_sample_rate_hz) {
- DCHECK(decode_sample_rate_hz == 16000 || decode_sample_rate_hz == 32000);
- WebRtcIsac_Create(&isac_state_);
- WebRtcIsac_SetDecSampRate(isac_state_, decode_sample_rate_hz);
-}
-
-AudioDecoderIsac::~AudioDecoderIsac() {
- WebRtcIsac_Free(isac_state_);
-}
-
-int AudioDecoderIsac::Decode(const uint8_t* encoded, size_t encoded_len,
- int16_t* decoded, SpeechType* speech_type) {
- int16_t temp_type = 1; // Default is speech.
- int16_t ret = WebRtcIsac_Decode(isac_state_,
- encoded,
- static_cast<int16_t>(encoded_len), decoded,
- &temp_type);
- *speech_type = ConvertSpeechType(temp_type);
- return ret;
-}
-
-int AudioDecoderIsac::DecodeRedundant(const uint8_t* encoded,
- size_t encoded_len, int16_t* decoded,
- SpeechType* speech_type) {
- int16_t temp_type = 1; // Default is speech.
- int16_t ret = WebRtcIsac_DecodeRcu(isac_state_,
- encoded,
- static_cast<int16_t>(encoded_len), decoded,
- &temp_type);
- *speech_type = ConvertSpeechType(temp_type);
- return ret;
-}
-
-int AudioDecoderIsac::DecodePlc(int num_frames, int16_t* decoded) {
- return WebRtcIsac_DecodePlc(isac_state_, decoded, num_frames);
-}
-
-int AudioDecoderIsac::Init() {
- return WebRtcIsac_DecoderInit(isac_state_);
-}
-
-int AudioDecoderIsac::IncomingPacket(const uint8_t* payload,
- size_t payload_len,
- uint16_t rtp_sequence_number,
- uint32_t rtp_timestamp,
- uint32_t arrival_timestamp) {
- return WebRtcIsac_UpdateBwEstimate(isac_state_,
- payload,
- static_cast<int32_t>(payload_len),
- rtp_sequence_number,
- rtp_timestamp,
- arrival_timestamp);
-}
-
-int AudioDecoderIsac::ErrorCode() {
- return WebRtcIsac_GetErrorCode(isac_state_);
-}
-#endif
-
// iSAC fix
#ifdef WEBRTC_CODEC_ISACFX
AudioDecoderIsacFix::AudioDecoderIsacFix() {
@@ -549,11 +488,17 @@
case kDecoderISAC:
return new AudioDecoderIsacFix;
#elif defined(WEBRTC_CODEC_ISAC)
- case kDecoderISAC:
- return new AudioDecoderIsac(16000);
+ case kDecoderISAC: {
+ AudioEncoderDecoderIsac::Config config;
+ config.sample_rate_hz = 16000;
+ return new AudioEncoderDecoderIsac(config);
+ }
case kDecoderISACswb:
- case kDecoderISACfb:
- return new AudioDecoderIsac(32000);
+ case kDecoderISACfb: {
+ AudioEncoderDecoderIsac::Config config;
+ config.sample_rate_hz = 32000;
+ return new AudioEncoderDecoderIsac(config);
+ }
#endif
#ifdef WEBRTC_CODEC_PCM16
case kDecoderPCM16B:
diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h
index 68d3627..7d1172c 100644
--- a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h
+++ b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h
@@ -130,31 +130,6 @@
};
#endif
-#ifdef WEBRTC_CODEC_ISAC
-class AudioDecoderIsac : public AudioDecoder {
- public:
- explicit AudioDecoderIsac(int decode_sample_rate_hz);
- virtual ~AudioDecoderIsac();
- 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 bool HasDecodePlc() const { return true; }
- virtual int DecodePlc(int num_frames, int16_t* decoded);
- virtual int Init();
- virtual int IncomingPacket(const uint8_t* payload,
- size_t payload_len,
- uint16_t rtp_sequence_number,
- uint32_t rtp_timestamp,
- uint32_t arrival_timestamp);
- virtual int ErrorCode();
-
- private:
- ISACStruct* isac_state_;
- DISALLOW_COPY_AND_ASSIGN(AudioDecoderIsac);
-};
-#endif
-
#ifdef WEBRTC_CODEC_ISACFX
class AudioDecoderIsacFix : public AudioDecoder {
public:
diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc b/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc
index 417e458..056bc5a 100644
--- a/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc
+++ b/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc
@@ -22,7 +22,7 @@
#include "webrtc/modules/audio_coding/codecs/g722/include/audio_encoder_g722.h"
#include "webrtc/modules/audio_coding/codecs/ilbc/interface/audio_encoder_ilbc.h"
#include "webrtc/modules/audio_coding/codecs/isac/fix/interface/isacfix.h"
-#include "webrtc/modules/audio_coding/codecs/isac/main/interface/isac.h"
+#include "webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h"
#include "webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h"
#include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h"
#include "webrtc/modules/audio_coding/neteq/tools/resample_input_audio_file.h"
@@ -354,76 +354,38 @@
protected:
AudioDecoderIsacFloatTest() : AudioDecoderTest() {
codec_input_rate_hz_ = 16000;
- input_size_ = 160;
frame_size_ = 480;
data_length_ = 10 * frame_size_;
- decoder_ = new AudioDecoderIsac(16000);
- assert(decoder_);
- WebRtcIsac_Create(&encoder_);
- WebRtcIsac_SetEncSampRate(encoder_, 16000);
- }
+ AudioEncoderDecoderIsac::Config config;
+ config.payload_type = payload_type_;
+ config.sample_rate_hz = codec_input_rate_hz_;
+ config.frame_size_ms =
+ 1000 * static_cast<int>(frame_size_) / codec_input_rate_hz_;
- ~AudioDecoderIsacFloatTest() {
- WebRtcIsac_Free(encoder_);
+ // We need to create separate AudioEncoderDecoderIsac objects for encoding
+ // and decoding, because the test class destructor destroys them both.
+ audio_encoder_.reset(new AudioEncoderDecoderIsac(config));
+ decoder_ = new AudioEncoderDecoderIsac(config);
}
-
- virtual void InitEncoder() {
- ASSERT_EQ(0, WebRtcIsac_EncoderInit(encoder_, 1)); // Fixed mode.
- ASSERT_EQ(0, WebRtcIsac_Control(encoder_, 32000, 30)); // 32 kbps, 30 ms.
- }
-
- virtual int EncodeFrame(const int16_t* input, size_t input_len_samples,
- uint8_t* output) {
- // Insert 3 * 10 ms. Expect non-zero output on third call.
- EXPECT_EQ(0, WebRtcIsac_Encode(encoder_, input, output));
- input += input_size_;
- EXPECT_EQ(0, WebRtcIsac_Encode(encoder_, input, output));
- input += input_size_;
- int enc_len_bytes = WebRtcIsac_Encode(encoder_, input, output);
- EXPECT_GT(enc_len_bytes, 0);
- return enc_len_bytes;
- }
-
- ISACStruct* encoder_;
- int input_size_;
};
class AudioDecoderIsacSwbTest : public AudioDecoderTest {
protected:
AudioDecoderIsacSwbTest() : AudioDecoderTest() {
codec_input_rate_hz_ = 32000;
- input_size_ = 320;
frame_size_ = 960;
data_length_ = 10 * frame_size_;
- decoder_ = new AudioDecoderIsac(32000);
- assert(decoder_);
- WebRtcIsac_Create(&encoder_);
- WebRtcIsac_SetEncSampRate(encoder_, 32000);
- }
+ AudioEncoderDecoderIsac::Config config;
+ config.payload_type = payload_type_;
+ config.sample_rate_hz = codec_input_rate_hz_;
+ config.frame_size_ms =
+ 1000 * static_cast<int>(frame_size_) / codec_input_rate_hz_;
- ~AudioDecoderIsacSwbTest() {
- WebRtcIsac_Free(encoder_);
+ // We need to create separate AudioEncoderDecoderIsac objects for encoding
+ // and decoding, because the test class destructor destroys them both.
+ audio_encoder_.reset(new AudioEncoderDecoderIsac(config));
+ decoder_ = new AudioEncoderDecoderIsac(config);
}
-
- virtual void InitEncoder() {
- ASSERT_EQ(0, WebRtcIsac_EncoderInit(encoder_, 1)); // Fixed mode.
- ASSERT_EQ(0, WebRtcIsac_Control(encoder_, 32000, 30)); // 32 kbps, 30 ms.
- }
-
- virtual int EncodeFrame(const int16_t* input, size_t input_len_samples,
- uint8_t* output) {
- // Insert 3 * 10 ms. Expect non-zero output on third call.
- EXPECT_EQ(0, WebRtcIsac_Encode(encoder_, input, output));
- input += input_size_;
- EXPECT_EQ(0, WebRtcIsac_Encode(encoder_, input, output));
- input += input_size_;
- int enc_len_bytes = WebRtcIsac_Encode(encoder_, input, output);
- EXPECT_GT(enc_len_bytes, 0);
- return enc_len_bytes;
- }
-
- ISACStruct* encoder_;
- int input_size_;
};
class AudioDecoderIsacFixTest : public AudioDecoderTest {