AudioEncoder subclass for iSACfix
This patch refactors AudioEncoderDecoderIsac so that it can share
almost all code with the very similar AudioEncoderDecoderIsacFix.
BUG=3926
R=henrik.lundin@webrtc.org, kjellander@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/29259004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@7912 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/audio_coding/BUILD.gn b/webrtc/modules/audio_coding/BUILD.gn
index 2a9087c..97b432d 100644
--- a/webrtc/modules/audio_coding/BUILD.gn
+++ b/webrtc/modules/audio_coding/BUILD.gn
@@ -369,6 +369,8 @@
source_set("isac") {
sources = [
+ "codecs/isac/audio_encoder_isac_t.h",
+ "codecs/isac/audio_encoder_isac_t_impl.h",
"codecs/isac/main/interface/audio_encoder_isac.h",
"codecs/isac/main/interface/isac.h",
"codecs/isac/main/source/arith_routines.c",
@@ -454,11 +456,15 @@
source_set("isacfix") {
sources = [
+ "codecs/isac/audio_encoder_isac_t.h",
+ "codecs/isac/audio_encoder_isac_t_impl.h",
+ "codecs/isac/fix/interface/audio_encoder_isacfix.h",
"codecs/isac/fix/interface/isacfix.h",
"codecs/isac/fix/source/arith_routines.c",
"codecs/isac/fix/source/arith_routines_hist.c",
"codecs/isac/fix/source/arith_routines_logist.c",
"codecs/isac/fix/source/arith_routins.h",
+ "codecs/isac/fix/source/audio_encoder_isacfix.cc",
"codecs/isac/fix/source/bandwidth_estimator.c",
"codecs/isac/fix/source/bandwidth_estimator.h",
"codecs/isac/fix/source/codec.h",
@@ -496,6 +502,12 @@
"codecs/isac/fix/source/transform_tables.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_win) {
defines = [ "WEBRTC_LINUX" ]
}
diff --git a/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h b/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h
new file mode 100644
index 0000000..a20da9d
--- /dev/null
+++ b/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.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_AUDIO_ENCODER_ISAC_T_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_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/system_wrappers/interface/scoped_ptr.h"
+
+namespace webrtc {
+
+class CriticalSectionWrapper;
+
+template <typename T>
+class AudioEncoderDecoderIsacT : 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 (if T has 32 kHz support)
+ 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 if T has 32 kHz support, 10000-32000 bps
+ // otherwise.
+ 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 AudioEncoderDecoderIsacT(const Config& config);
+ explicit AudioEncoderDecoderIsacT(const ConfigAdaptive& config);
+ virtual ~AudioEncoderDecoderIsacT() 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,
+ 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_;
+ typename T::instance_type* 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(AudioEncoderDecoderIsacT);
+};
+
+} // namespace webrtc
+#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_H_
diff --git a/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h b/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h
new file mode 100644
index 0000000..7c13e87
--- /dev/null
+++ b/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h
@@ -0,0 +1,226 @@
+/*
+ * 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_AUDIO_ENCODER_ISAC_T_IMPL_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_
+
+#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 {
+
+const int kIsacPayloadType = 103;
+
+inline int DivExact(int a, int b) {
+ CHECK_EQ(a % b, 0);
+ return a / b;
+}
+
+template <typename T>
+AudioEncoderDecoderIsacT<T>::Config::Config()
+ : payload_type(kIsacPayloadType),
+ sample_rate_hz(16000),
+ frame_size_ms(30),
+ bit_rate(32000) {
+}
+
+template <typename T>
+bool AudioEncoderDecoderIsacT<T>::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 T::has_32kHz &&
+ (frame_size_ms == 30 && bit_rate >= 10000 && bit_rate <= 56000);
+ default:
+ return false;
+ }
+}
+
+template <typename T>
+AudioEncoderDecoderIsacT<T>::ConfigAdaptive::ConfigAdaptive()
+ : payload_type(kIsacPayloadType),
+ sample_rate_hz(16000),
+ initial_frame_size_ms(30),
+ initial_bit_rate(32000),
+ enforce_frame_size(false) {
+}
+
+template <typename T>
+bool AudioEncoderDecoderIsacT<T>::ConfigAdaptive::IsOk() const {
+ static const int max_rate = T::has_32kHz ? 56000 : 32000;
+ return sample_rate_hz == 16000 &&
+ (initial_frame_size_ms == 30 || initial_frame_size_ms == 60) &&
+ initial_bit_rate >= 10000 && initial_bit_rate <= max_rate;
+}
+
+template <typename T>
+AudioEncoderDecoderIsacT<T>::AudioEncoderDecoderIsacT(const Config& config)
+ : payload_type_(config.payload_type),
+ lock_(CriticalSectionWrapper::CreateCriticalSection()),
+ packet_in_progress_(false) {
+ CHECK(config.IsOk());
+ CHECK_EQ(0, T::Create(&isac_state_));
+ CHECK_EQ(0, T::EncoderInit(isac_state_, 1));
+ CHECK_EQ(0, T::SetEncSampRate(isac_state_, config.sample_rate_hz));
+ CHECK_EQ(0, T::Control(isac_state_, config.bit_rate, config.frame_size_ms));
+ CHECK_EQ(0, T::SetDecSampRate(isac_state_, config.sample_rate_hz));
+}
+
+template <typename T>
+AudioEncoderDecoderIsacT<T>::AudioEncoderDecoderIsacT(
+ const ConfigAdaptive& config)
+ : payload_type_(config.payload_type),
+ lock_(CriticalSectionWrapper::CreateCriticalSection()),
+ packet_in_progress_(false) {
+ CHECK(config.IsOk());
+ CHECK_EQ(0, T::Create(&isac_state_));
+ CHECK_EQ(0, T::EncoderInit(isac_state_, 0));
+ CHECK_EQ(0, T::SetEncSampRate(isac_state_, config.sample_rate_hz));
+ CHECK_EQ(0, T::ControlBwe(isac_state_, config.initial_bit_rate,
+ config.initial_frame_size_ms,
+ config.enforce_frame_size));
+ CHECK_EQ(0, T::SetDecSampRate(isac_state_, config.sample_rate_hz));
+}
+
+template <typename T>
+AudioEncoderDecoderIsacT<T>::~AudioEncoderDecoderIsacT() {
+ CHECK_EQ(0, T::Free(isac_state_));
+}
+
+template <typename T>
+int AudioEncoderDecoderIsacT<T>::sample_rate_hz() const {
+ CriticalSectionScoped cs(lock_.get());
+ return T::EncSampRate(isac_state_);
+}
+
+template <typename T>
+int AudioEncoderDecoderIsacT<T>::num_channels() const {
+ return 1;
+}
+
+template <typename T>
+int AudioEncoderDecoderIsacT<T>::Num10MsFramesInNextPacket() const {
+ CriticalSectionScoped cs(lock_.get());
+ const int samples_in_next_packet = T::GetNewFrameLen(isac_state_);
+ return DivExact(samples_in_next_packet, DivExact(sample_rate_hz(), 100));
+}
+
+template <typename T>
+int AudioEncoderDecoderIsacT<T>::Max10MsFramesInAPacket() const {
+ return 6; // iSAC puts at most 60 ms in a packet.
+}
+
+template <typename T>
+bool AudioEncoderDecoderIsacT<T>::EncodeInternal(uint32_t timestamp,
+ const int16_t* audio,
+ size_t max_encoded_bytes,
+ uint8_t* encoded,
+ 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 = T::Encode(isac_state_, audio, encoded);
+ }
+ if (r < 0) {
+ // An error occurred; propagate it to the caller.
+ packet_in_progress_ = false;
+ return false;
+ }
+
+ // T::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);
+
+ info->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;
+}
+
+template <typename T>
+int AudioEncoderDecoderIsacT<T>::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 =
+ T::Decode(isac_state_, encoded, static_cast<int16_t>(encoded_len),
+ decoded, &temp_type);
+ *speech_type = ConvertSpeechType(temp_type);
+ return ret;
+}
+
+template <typename T>
+int AudioEncoderDecoderIsacT<T>::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 =
+ T::DecodeRcu(isac_state_, encoded, static_cast<int16_t>(encoded_len),
+ decoded, &temp_type);
+ *speech_type = ConvertSpeechType(temp_type);
+ return ret;
+}
+
+template <typename T>
+bool AudioEncoderDecoderIsacT<T>::HasDecodePlc() const {
+ return true;
+}
+
+template <typename T>
+int AudioEncoderDecoderIsacT<T>::DecodePlc(int num_frames, int16_t* decoded) {
+ CriticalSectionScoped cs(lock_.get());
+ return T::DecodePlc(isac_state_, decoded, num_frames);
+}
+
+template <typename T>
+int AudioEncoderDecoderIsacT<T>::Init() {
+ CriticalSectionScoped cs(lock_.get());
+ return T::DecoderInit(isac_state_);
+}
+
+template <typename T>
+int AudioEncoderDecoderIsacT<T>::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 T::UpdateBwEstimate(
+ isac_state_, payload, static_cast<int32_t>(payload_len),
+ rtp_sequence_number, rtp_timestamp, arrival_timestamp);
+}
+
+template <typename T>
+int AudioEncoderDecoderIsacT<T>::ErrorCode() {
+ CriticalSectionScoped cs(lock_.get());
+ return T::GetErrorCode(isac_state_);
+}
+
+} // namespace webrtc
+
+#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_
diff --git a/webrtc/modules/audio_coding/codecs/isac/fix/interface/audio_encoder_isacfix.h b/webrtc/modules/audio_coding/codecs/isac/fix/interface/audio_encoder_isacfix.h
new file mode 100644
index 0000000..06722b1
--- /dev/null
+++ b/webrtc/modules/audio_coding/codecs/isac/fix/interface/audio_encoder_isacfix.h
@@ -0,0 +1,108 @@
+/*
+ * 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_FIX_INTERFACE_AUDIO_ENCODER_ISACFIX_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INTERFACE_AUDIO_ENCODER_ISACFIX_H_
+
+#include "webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h"
+#include "webrtc/modules/audio_coding/codecs/isac/fix/interface/isacfix.h"
+
+namespace webrtc {
+
+struct IsacFix {
+ typedef ISACFIX_MainStruct instance_type;
+ static const bool has_32kHz = false;
+ static const uint16_t kFixSampleRate = 16000;
+ static inline int16_t Control(instance_type* inst,
+ int32_t rate,
+ int16_t framesize) {
+ return WebRtcIsacfix_Control(inst, rate, framesize);
+ }
+ static inline int16_t ControlBwe(instance_type* inst,
+ int32_t rate_bps,
+ int16_t frame_size_ms,
+ int16_t enforce_frame_size) {
+ return WebRtcIsacfix_ControlBwe(inst, rate_bps, frame_size_ms,
+ enforce_frame_size);
+ }
+ static inline int16_t Create(instance_type** inst) {
+ return WebRtcIsacfix_Create(inst);
+ }
+ static inline int16_t Decode(instance_type* inst,
+ const uint8_t* encoded,
+ int16_t len,
+ int16_t* decoded,
+ int16_t* speech_type) {
+ return WebRtcIsacfix_Decode(inst, encoded, len, decoded, speech_type);
+ }
+ static inline int16_t DecodePlc(instance_type* inst,
+ int16_t* decoded,
+ int16_t num_lost_frames) {
+ return WebRtcIsacfix_DecodePlc(inst, decoded, num_lost_frames);
+ }
+ static inline int16_t DecodeRcu(instance_type* inst,
+ const uint8_t* encoded,
+ int16_t len,
+ int16_t* decoded,
+ int16_t* speech_type) {
+ // iSACfix has no DecodeRcu; just call the normal Decode.
+ return WebRtcIsacfix_Decode(inst, encoded, len, decoded, speech_type);
+ }
+ static inline int16_t DecoderInit(instance_type* inst) {
+ return WebRtcIsacfix_DecoderInit(inst);
+ }
+ static inline int16_t Encode(instance_type* inst,
+ const int16_t* speech_in,
+ uint8_t* encoded) {
+ return WebRtcIsacfix_Encode(inst, speech_in, encoded);
+ }
+ static inline int16_t EncoderInit(instance_type* inst, int16_t coding_mode) {
+ return WebRtcIsacfix_EncoderInit(inst, coding_mode);
+ }
+ static inline uint16_t EncSampRate(instance_type* inst) {
+ return kFixSampleRate;
+ }
+
+ static inline int16_t Free(instance_type* inst) {
+ return WebRtcIsacfix_Free(inst);
+ }
+ static inline int16_t GetErrorCode(instance_type* inst) {
+ return WebRtcIsacfix_GetErrorCode(inst);
+ }
+
+ static inline int16_t GetNewFrameLen(instance_type* inst) {
+ return WebRtcIsacfix_GetNewFrameLen(inst);
+ }
+
+ static inline int16_t SetDecSampRate(instance_type* inst,
+ uint16_t sample_rate_hz) {
+ DCHECK_EQ(sample_rate_hz, kFixSampleRate);
+ return 0;
+ }
+ static inline int16_t SetEncSampRate(instance_type* inst,
+ uint16_t sample_rate_hz) {
+ DCHECK_EQ(sample_rate_hz, kFixSampleRate);
+ return 0;
+ }
+ static inline int16_t UpdateBwEstimate(instance_type* inst,
+ const uint8_t* encoded,
+ int32_t packet_size,
+ uint16_t rtp_seq_number,
+ uint32_t send_ts,
+ uint32_t arr_ts) {
+ return WebRtcIsacfix_UpdateBwEstimate(inst, encoded, packet_size,
+ rtp_seq_number, send_ts, arr_ts);
+ }
+};
+
+typedef AudioEncoderDecoderIsacT<IsacFix> AudioEncoderDecoderIsacFix;
+
+} // namespace webrtc
+#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INTERFACE_AUDIO_ENCODER_ISACFIX_H_
diff --git a/webrtc/modules/audio_coding/codecs/isac/fix/source/audio_encoder_isacfix.cc b/webrtc/modules/audio_coding/codecs/isac/fix/source/audio_encoder_isacfix.cc
new file mode 100644
index 0000000..d0aea26
--- /dev/null
+++ b/webrtc/modules/audio_coding/codecs/isac/fix/source/audio_encoder_isacfix.cc
@@ -0,0 +1,23 @@
+/*
+ * 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/fix/interface/audio_encoder_isacfix.h"
+
+#include "webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h"
+
+namespace webrtc {
+
+const uint16_t IsacFix::kFixSampleRate;
+
+// Explicit instantiation of AudioEncoderDecoderIsacT<IsacFix>, a.k.a.
+// AudioEncoderDecoderIsacFix.
+template class AudioEncoderDecoderIsacT<IsacFix>;
+
+} // namespace webrtc
diff --git a/webrtc/modules/audio_coding/codecs/isac/fix/source/isacfix.gypi b/webrtc/modules/audio_coding/codecs/isac/fix/source/isacfix.gypi
index 54ff9df..d3ab883 100644
--- a/webrtc/modules/audio_coding/codecs/isac/fix/source/isacfix.gypi
+++ b/webrtc/modules/audio_coding/codecs/isac/fix/source/isacfix.gypi
@@ -26,10 +26,14 @@
],
},
'sources': [
+ '../../audio_encoder_isac_t.h',
+ '../../audio_encoder_isac_t_impl.h',
+ '../interface/audio_encoder_isacfix.h',
'../interface/isacfix.h',
'arith_routines.c',
'arith_routines_hist.c',
'arith_routines_logist.c',
+ 'audio_encoder_isacfix.cc',
'bandwidth_estimator.c',
'decode.c',
'decode_bwe.c',
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
index e111a57..091b775 100644
--- 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
@@ -11,100 +11,95 @@
#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/audio_encoder_isac_t.h"
#include "webrtc/modules/audio_coding/codecs/isac/main/interface/isac.h"
-#include "webrtc/system_wrappers/interface/scoped_ptr.h"
namespace webrtc {
-class CriticalSectionWrapper;
+struct IsacFloat {
+ typedef ISACStruct instance_type;
+ static const bool has_32kHz = true;
+ static inline int16_t Control(instance_type* inst,
+ int32_t rate,
+ int16_t framesize) {
+ return WebRtcIsac_Control(inst, rate, framesize);
+ }
+ static inline int16_t ControlBwe(instance_type* inst,
+ int32_t rate_bps,
+ int16_t frame_size_ms,
+ int16_t enforce_frame_size) {
+ return WebRtcIsac_ControlBwe(inst, rate_bps, frame_size_ms,
+ enforce_frame_size);
+ }
+ static inline int16_t Create(instance_type** inst) {
+ return WebRtcIsac_Create(inst);
+ }
+ static inline int16_t Decode(instance_type* inst,
+ const uint8_t* encoded,
+ int16_t len,
+ int16_t* decoded,
+ int16_t* speech_type) {
+ return WebRtcIsac_Decode(inst, encoded, len, decoded, speech_type);
+ }
+ static inline int16_t DecodePlc(instance_type* inst,
+ int16_t* decoded,
+ int16_t num_lost_frames) {
+ return WebRtcIsac_DecodePlc(inst, decoded, num_lost_frames);
+ }
-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.
- };
+ static inline int16_t DecodeRcu(instance_type* inst,
+ const uint8_t* encoded,
+ int16_t len,
+ int16_t* decoded,
+ int16_t* speech_type) {
+ return WebRtcIsac_DecodeRcu(inst, encoded, len, decoded, speech_type);
+ }
+ static inline int16_t DecoderInit(instance_type* inst) {
+ return WebRtcIsac_DecoderInit(inst);
+ }
+ static inline int16_t Encode(instance_type* inst,
+ const int16_t* speech_in,
+ uint8_t* encoded) {
+ return WebRtcIsac_Encode(inst, speech_in, encoded);
+ }
+ static inline int16_t EncoderInit(instance_type* inst, int16_t coding_mode) {
+ return WebRtcIsac_EncoderInit(inst, coding_mode);
+ }
+ static inline uint16_t EncSampRate(instance_type* inst) {
+ return WebRtcIsac_EncSampRate(inst);
+ }
- // 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?
- };
+ static inline int16_t Free(instance_type* inst) {
+ return WebRtcIsac_Free(inst);
+ }
+ static inline int16_t GetErrorCode(instance_type* inst) {
+ return WebRtcIsac_GetErrorCode(inst);
+ }
- explicit AudioEncoderDecoderIsac(const Config& config);
- explicit AudioEncoderDecoderIsac(const ConfigAdaptive& config);
- virtual ~AudioEncoderDecoderIsac() OVERRIDE;
+ static inline int16_t GetNewFrameLen(instance_type* inst) {
+ return WebRtcIsac_GetNewFrameLen(inst);
+ }
- // 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,
- 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);
+ static inline int16_t SetDecSampRate(instance_type* inst,
+ uint16_t sample_rate_hz) {
+ return WebRtcIsac_SetDecSampRate(inst, sample_rate_hz);
+ }
+ static inline int16_t SetEncSampRate(instance_type* inst,
+ uint16_t sample_rate_hz) {
+ return WebRtcIsac_SetEncSampRate(inst, sample_rate_hz);
+ }
+ static inline int16_t UpdateBwEstimate(instance_type* inst,
+ const uint8_t* encoded,
+ int32_t packet_size,
+ uint16_t rtp_seq_number,
+ uint32_t send_ts,
+ uint32_t arr_ts) {
+ return WebRtcIsac_UpdateBwEstimate(inst, encoded, packet_size,
+ rtp_seq_number, send_ts, arr_ts);
+ }
};
+typedef AudioEncoderDecoderIsacT<IsacFloat> 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
index c80104a..ba08603 100644
--- 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
@@ -10,191 +10,12 @@
#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"
+#include "webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.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,
- 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);
-
- info->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_);
-}
+// Explicit instantiation of AudioEncoderDecoderIsacT<IsacFloat>, a.k.a.
+// AudioEncoderDecoderIsac.
+template class AudioEncoderDecoderIsacT<IsacFloat>;
} // 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 8f8cd35..0b0c070 100644
--- a/webrtc/modules/audio_coding/codecs/isac/main/source/isac.gypi
+++ b/webrtc/modules/audio_coding/codecs/isac/main/source/isac.gypi
@@ -26,6 +26,8 @@
],
},
'sources': [
+ '../../audio_encoder_isac_t.h',
+ '../../audio_encoder_isac_t_impl.h',
'../interface/audio_encoder_isac.h',
'../interface/isac.h',
'arith_routines.c',
diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc
index f565faf..b8c5976 100644
--- a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc
+++ b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc
@@ -23,7 +23,7 @@
#include "webrtc/modules/audio_coding/codecs/ilbc/interface/ilbc.h"
#endif
#ifdef WEBRTC_CODEC_ISACFX
-#include "webrtc/modules/audio_coding/codecs/isac/fix/interface/isacfix.h"
+#include "webrtc/modules/audio_coding/codecs/isac/fix/interface/audio_encoder_isacfix.h"
#endif
#ifdef WEBRTC_CODEC_ISAC
#include "webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h"
@@ -127,48 +127,6 @@
}
#endif
-// iSAC fix
-#ifdef WEBRTC_CODEC_ISACFX
-AudioDecoderIsacFix::AudioDecoderIsacFix() {
- WebRtcIsacfix_Create(&isac_state_);
-}
-
-AudioDecoderIsacFix::~AudioDecoderIsacFix() {
- WebRtcIsacfix_Free(isac_state_);
-}
-
-int AudioDecoderIsacFix::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 = WebRtcIsacfix_Decode(isac_state_,
- encoded,
- static_cast<int16_t>(encoded_len), decoded,
- &temp_type);
- *speech_type = ConvertSpeechType(temp_type);
- return ret;
-}
-
-int AudioDecoderIsacFix::Init() {
- return WebRtcIsacfix_DecoderInit(isac_state_);
-}
-
-int AudioDecoderIsacFix::IncomingPacket(const uint8_t* payload,
- size_t payload_len,
- uint16_t rtp_sequence_number,
- uint32_t rtp_timestamp,
- uint32_t arrival_timestamp) {
- return WebRtcIsacfix_UpdateBwEstimate(
- isac_state_,
- payload,
- static_cast<int32_t>(payload_len),
- rtp_sequence_number, rtp_timestamp, arrival_timestamp);
-}
-
-int AudioDecoderIsacFix::ErrorCode() {
- return WebRtcIsacfix_GetErrorCode(isac_state_);
-}
-#endif
-
// G.722
#ifdef WEBRTC_CODEC_G722
AudioDecoderG722::AudioDecoderG722() {
@@ -485,8 +443,10 @@
return new AudioDecoderIlbc;
#endif
#if defined(WEBRTC_CODEC_ISACFX)
- case kDecoderISAC:
- return new AudioDecoderIsacFix;
+ case kDecoderISAC: {
+ AudioEncoderDecoderIsacFix::Config config;
+ return new AudioEncoderDecoderIsacFix(config);
+ }
#elif defined(WEBRTC_CODEC_ISAC)
case kDecoderISAC: {
AudioEncoderDecoderIsac::Config config;
diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h
index 7d1172c..3659726 100644
--- a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h
+++ b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h
@@ -27,12 +27,6 @@
#ifdef WEBRTC_CODEC_ILBC
#include "webrtc/modules/audio_coding/codecs/ilbc/interface/ilbc.h"
#endif
-#ifdef WEBRTC_CODEC_ISACFX
-#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"
-#endif
#ifdef WEBRTC_CODEC_OPUS
#include "webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h"
#endif
@@ -130,27 +124,6 @@
};
#endif
-#ifdef WEBRTC_CODEC_ISACFX
-class AudioDecoderIsacFix : public AudioDecoder {
- public:
- AudioDecoderIsacFix();
- virtual ~AudioDecoderIsacFix();
- virtual int Decode(const uint8_t* encoded, size_t encoded_len,
- int16_t* decoded, SpeechType* speech_type);
- 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:
- ISACFIX_MainStruct* isac_state_;
- DISALLOW_COPY_AND_ASSIGN(AudioDecoderIsacFix);
-};
-#endif
-
#ifdef WEBRTC_CODEC_G722
class AudioDecoderG722 : 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 5a2c4ba..927c30b 100644
--- a/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc
+++ b/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc
@@ -20,7 +20,7 @@
#include "webrtc/modules/audio_coding/codecs/g711/include/audio_encoder_pcm.h"
#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/fix/interface/audio_encoder_isacfix.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/audio_encoder_pcm16b.h"
@@ -388,38 +388,20 @@
protected:
AudioDecoderIsacFixTest() : AudioDecoderTest() {
codec_input_rate_hz_ = 16000;
- input_size_ = 160;
frame_size_ = 480;
data_length_ = 10 * frame_size_;
- decoder_ = new AudioDecoderIsacFix;
- assert(decoder_);
- WebRtcIsacfix_Create(&encoder_);
- }
+ AudioEncoderDecoderIsacFix::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_;
- ~AudioDecoderIsacFixTest() {
- WebRtcIsacfix_Free(encoder_);
+ // We need to create separate AudioEncoderDecoderIsacFix objects for
+ // encoding and decoding, because the test class destructor destroys them
+ // both.
+ audio_encoder_.reset(new AudioEncoderDecoderIsacFix(config));
+ decoder_ = new AudioEncoderDecoderIsacFix(config);
}
-
- virtual void InitEncoder() {
- ASSERT_EQ(0, WebRtcIsacfix_EncoderInit(encoder_, 1)); // Fixed mode.
- ASSERT_EQ(0,
- WebRtcIsacfix_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, WebRtcIsacfix_Encode(encoder_, input, output));
- input += input_size_;
- EXPECT_EQ(0, WebRtcIsacfix_Encode(encoder_, input, output));
- input += input_size_;
- int enc_len_bytes = WebRtcIsacfix_Encode(encoder_, input, output);
- EXPECT_GT(enc_len_bytes, 0);
- return enc_len_bytes;
- }
-
- ISACFIX_MainStruct* encoder_;
- int input_size_;
};
class AudioDecoderG722Test : public AudioDecoderTest {