diff --git a/webrtc/modules/audio_coding/BUILD.gn b/webrtc/modules/audio_coding/BUILD.gn index 8a27900edf..d98d9c35d3 100644 --- a/webrtc/modules/audio_coding/BUILD.gn +++ b/webrtc/modules/audio_coding/BUILD.gn @@ -380,6 +380,15 @@ source_set("ilbc") { ] } +source_set("isac_common") { + sources = [ + "codecs/isac/audio_encoder_isac_t.h", + "codecs/isac/audio_encoder_isac_t_impl.h", + "codecs/isac/locked_bandwidth_info.cc", + "codecs/isac/locked_bandwidth_info.h", + ] +} + config("isac_config") { include_dirs = [ "../../..", @@ -389,8 +398,6 @@ config("isac_config") { 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", @@ -458,6 +465,7 @@ source_set("isac") { deps = [ ":audio_decoder_interface", ":audio_encoder_interface", + ":isac_common", "../../common_audio", ] } @@ -471,8 +479,6 @@ config("isac_fix_config") { source_set("isac_fix") { 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", @@ -533,6 +539,7 @@ source_set("isac_fix") { deps = [ ":audio_encoder_interface", + ":isac_common", "../../common_audio", "../../system_wrappers", ] diff --git a/webrtc/modules/audio_coding/audio_coding.gypi b/webrtc/modules/audio_coding/audio_coding.gypi index 90a6f39f35..bc3c48d075 100644 --- a/webrtc/modules/audio_coding/audio_coding.gypi +++ b/webrtc/modules/audio_coding/audio_coding.gypi @@ -15,6 +15,7 @@ 'codecs/g722/g722.gypi', 'codecs/ilbc/ilbc.gypi', 'codecs/isac/isac.gypi', + 'codecs/isac/isac_common.gypi', 'codecs/isac/isacfix.gypi', 'codecs/pcm16b/pcm16b.gypi', 'codecs/red/red.gypi', 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 index 49df3c68be..7093304264 100644 --- a/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h +++ b/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h @@ -13,17 +13,14 @@ #include -#include "webrtc/base/scoped_ptr.h" -#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/locked_bandwidth_info.h" namespace webrtc { -class CriticalSectionWrapper; - template -class AudioEncoderDecoderIsacT : public AudioEncoder, public AudioDecoder { +class AudioEncoderIsacT final : public AudioEncoder { public: // Allowed combinations of sample rate, frame size, and bit rate are // - 16000 Hz, 30 ms, 10000-32000 bps @@ -34,6 +31,8 @@ class AudioEncoderDecoderIsacT : public AudioEncoder, public AudioDecoder { Config(); bool IsOk() const; + LockedIsacBandwidthInfo* bwinfo; + int payload_type; int sample_rate_hz; int frame_size_ms; @@ -50,18 +49,50 @@ class AudioEncoderDecoderIsacT : public AudioEncoder, public AudioDecoder { bool enforce_frame_size; }; - explicit AudioEncoderDecoderIsacT(const Config& config); - ~AudioEncoderDecoderIsacT() override; + explicit AudioEncoderIsacT(const Config& config); + ~AudioEncoderIsacT() override; - // AudioEncoder public methods. int SampleRateHz() const override; int NumChannels() const override; size_t MaxEncodedBytes() const override; int Num10MsFramesInNextPacket() const override; int Max10MsFramesInAPacket() const override; int GetTargetBitrate() const override; + EncodedInfo EncodeInternal(uint32_t rtp_timestamp, + const int16_t* audio, + size_t max_encoded_bytes, + uint8_t* encoded) override; + + private: + // This value is taken from STREAM_SIZE_MAX_60 for iSAC float (60 ms) and + // STREAM_MAXW16_60MS for iSAC fix (60 ms). + static const size_t kSufficientEncodeBufferSizeBytes = 400; + + const int payload_type_; + typename T::instance_type* isac_state_; + LockedIsacBandwidthInfo* bwinfo_; + + // 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_; + + // Timestamp of the previously encoded packet. + uint32_t last_encoded_timestamp_; + + const int target_bitrate_bps_; + + DISALLOW_COPY_AND_ASSIGN(AudioEncoderIsacT); +}; + +template +class AudioDecoderIsacT final : public AudioDecoder { + public: + AudioDecoderIsacT(); + explicit AudioDecoderIsacT(LockedIsacBandwidthInfo* bwinfo); + ~AudioDecoderIsacT() override; - // AudioDecoder methods. bool HasDecodePlc() const override; int DecodePlc(int num_frames, int16_t* decoded) override; int Init() override; @@ -71,15 +102,7 @@ class AudioEncoderDecoderIsacT : public AudioEncoder, public AudioDecoder { uint32_t rtp_timestamp, uint32_t arrival_timestamp) override; int ErrorCode() override; - size_t Channels() const override { return 1; } - - // AudioEncoder protected method. - EncodedInfo EncodeInternal(uint32_t rtp_timestamp, - const int16_t* audio, - size_t max_encoded_bytes, - uint8_t* encoded) override; - - // AudioDecoder protected method. + size_t Channels() const override; int DecodeInternal(const uint8_t* encoded, size_t encoded_len, int sample_rate_hz, @@ -87,44 +110,11 @@ class AudioEncoderDecoderIsacT : public AudioEncoder, public AudioDecoder { SpeechType* speech_type) override; private: - // This value is taken from STREAM_SIZE_MAX_60 for iSAC float (60 ms) and - // STREAM_MAXW16_60MS for iSAC fix (60 ms). - static const size_t kSufficientEncodeBufferSizeBytes = 400; + typename T::instance_type* isac_state_; + LockedIsacBandwidthInfo* bwinfo_; + int decoder_sample_rate_hz_; - 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. - // Note: PT_GUARDED_BY is disabled since it is not yet supported by clang. - const rtc::scoped_ptr state_lock_; - 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 rtc::scoped_ptr lock_; - - // Have we accepted input but not yet emitted it in a packet? - bool packet_in_progress_ GUARDED_BY(lock_); - - // Timestamp of the first input of the currently in-progress packet. - uint32_t packet_timestamp_ GUARDED_BY(lock_); - - // Timestamp of the previously encoded packet. - uint32_t last_encoded_timestamp_ GUARDED_BY(lock_); - - const int target_bitrate_bps_; - - DISALLOW_COPY_AND_ASSIGN(AudioEncoderDecoderIsacT); -}; - -struct CodecInst; - -class AudioEncoderDecoderMutableIsac : public AudioEncoderMutable, - public AudioDecoder { - public: - virtual void UpdateSettings(const CodecInst& codec_inst) = 0; + DISALLOW_COPY_AND_ASSIGN(AudioDecoderIsacT); }; } // namespace webrtc 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 index d2b20e3b94..ce70db455b 100644 --- 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 @@ -17,7 +17,6 @@ #include "webrtc/base/checks.h" #include "webrtc/modules/audio_coding/codecs/isac/main/interface/isac.h" -#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" namespace webrtc { @@ -25,8 +24,9 @@ const int kIsacPayloadType = 103; const int kDefaultBitRate = 32000; template -AudioEncoderDecoderIsacT::Config::Config() - : payload_type(kIsacPayloadType), +AudioEncoderIsacT::Config::Config() + : bwinfo(nullptr), + payload_type(kIsacPayloadType), sample_rate_hz(16000), frame_size_ms(30), bit_rate(kDefaultBitRate), @@ -37,11 +37,13 @@ AudioEncoderDecoderIsacT::Config::Config() } template -bool AudioEncoderDecoderIsacT::Config::IsOk() const { +bool AudioEncoderIsacT::Config::IsOk() const { if (max_bit_rate < 32000 && max_bit_rate != -1) return false; if (max_payload_size_bytes < 120 && max_payload_size_bytes != -1) return false; + if (adaptive_mode && !bwinfo) + return false; switch (sample_rate_hz) { case 16000: if (max_bit_rate > 53400) @@ -65,11 +67,9 @@ bool AudioEncoderDecoderIsacT::Config::IsOk() const { } template -AudioEncoderDecoderIsacT::AudioEncoderDecoderIsacT(const Config& config) +AudioEncoderIsacT::AudioEncoderIsacT(const Config& config) : payload_type_(config.payload_type), - state_lock_(CriticalSectionWrapper::CreateCriticalSection()), - decoder_sample_rate_hz_(0), - lock_(CriticalSectionWrapper::CreateCriticalSection()), + bwinfo_(config.bwinfo), packet_in_progress_(false), target_bitrate_bps_(config.adaptive_mode ? -1 : (config.bit_rate == 0 ? kDefaultBitRate @@ -85,80 +85,82 @@ AudioEncoderDecoderIsacT::AudioEncoderDecoderIsacT(const Config& config) } else { CHECK_EQ(0, T::Control(isac_state_, bit_rate, config.frame_size_ms)); } - // When config.sample_rate_hz is set to 48000 Hz (iSAC-fb), the decoder is - // still set to 32000 Hz, since there is no full-band mode in the decoder. - CHECK_EQ(0, T::SetDecSampRate(isac_state_, - std::min(config.sample_rate_hz, 32000))); if (config.max_payload_size_bytes != -1) CHECK_EQ(0, T::SetMaxPayloadSize(isac_state_, config.max_payload_size_bytes)); if (config.max_bit_rate != -1) CHECK_EQ(0, T::SetMaxRate(isac_state_, config.max_bit_rate)); - CHECK_EQ(0, T::DecoderInit(isac_state_)); + + // When config.sample_rate_hz is set to 48000 Hz (iSAC-fb), the decoder is + // still set to 32000 Hz, since there is no full-band mode in the decoder. + const int decoder_sample_rate_hz = std::min(config.sample_rate_hz, 32000); + + // Set the decoder sample rate even though we just use the encoder. This + // doesn't appear to be necessary to produce a valid encoding, but without it + // we get an encoding that isn't bit-for-bit identical with what a combined + // encoder+decoder object produces. + CHECK_EQ(0, T::SetDecSampRate(isac_state_, decoder_sample_rate_hz)); } template -AudioEncoderDecoderIsacT::~AudioEncoderDecoderIsacT() { +AudioEncoderIsacT::~AudioEncoderIsacT() { CHECK_EQ(0, T::Free(isac_state_)); } template -int AudioEncoderDecoderIsacT::SampleRateHz() const { - CriticalSectionScoped cs(state_lock_.get()); +int AudioEncoderIsacT::SampleRateHz() const { return T::EncSampRate(isac_state_); } template -int AudioEncoderDecoderIsacT::NumChannels() const { +int AudioEncoderIsacT::NumChannels() const { return 1; } template -size_t AudioEncoderDecoderIsacT::MaxEncodedBytes() const { +size_t AudioEncoderIsacT::MaxEncodedBytes() const { return kSufficientEncodeBufferSizeBytes; } template -int AudioEncoderDecoderIsacT::Num10MsFramesInNextPacket() const { - CriticalSectionScoped cs(state_lock_.get()); +int AudioEncoderIsacT::Num10MsFramesInNextPacket() const { const int samples_in_next_packet = T::GetNewFrameLen(isac_state_); return rtc::CheckedDivExact(samples_in_next_packet, rtc::CheckedDivExact(SampleRateHz(), 100)); } template -int AudioEncoderDecoderIsacT::Max10MsFramesInAPacket() const { +int AudioEncoderIsacT::Max10MsFramesInAPacket() const { return 6; // iSAC puts at most 60 ms in a packet. } template -int AudioEncoderDecoderIsacT::GetTargetBitrate() const { +int AudioEncoderIsacT::GetTargetBitrate() const { return target_bitrate_bps_; } template -AudioEncoder::EncodedInfo AudioEncoderDecoderIsacT::EncodeInternal( +AudioEncoder::EncodedInfo AudioEncoderIsacT::EncodeInternal( uint32_t rtp_timestamp, const int16_t* audio, size_t max_encoded_bytes, uint8_t* encoded) { - CriticalSectionScoped cs_lock(lock_.get()); if (!packet_in_progress_) { // Starting a new packet; remember the timestamp for later. packet_in_progress_ = true; packet_timestamp_ = rtp_timestamp; } - int r; - { - CriticalSectionScoped cs(state_lock_.get()); - r = T::Encode(isac_state_, audio, encoded); - CHECK_GE(r, 0) << "Encode failed (error code " - << T::GetErrorCode(isac_state_) << ")"; + if (bwinfo_) { + IsacBandwidthInfo bwinfo = bwinfo_->Get(); + T::SetBandwidthInfo(isac_state_, &bwinfo); } + int r = T::Encode(isac_state_, audio, encoded); + CHECK_GE(r, 0) << "Encode failed (error code " << T::GetErrorCode(isac_state_) + << ")"; // 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(r) <= max_encoded_bytes); + CHECK_LE(static_cast(r), max_encoded_bytes); if (r == 0) return EncodedInfo(); @@ -174,12 +176,33 @@ AudioEncoder::EncodedInfo AudioEncoderDecoderIsacT::EncodeInternal( } template -int AudioEncoderDecoderIsacT::DecodeInternal(const uint8_t* encoded, - size_t encoded_len, - int sample_rate_hz, - int16_t* decoded, - SpeechType* speech_type) { - CriticalSectionScoped cs(state_lock_.get()); +AudioDecoderIsacT::AudioDecoderIsacT() + : AudioDecoderIsacT(nullptr) { +} + +template +AudioDecoderIsacT::AudioDecoderIsacT(LockedIsacBandwidthInfo* bwinfo) + : bwinfo_(bwinfo), decoder_sample_rate_hz_(-1) { + CHECK_EQ(0, T::Create(&isac_state_)); + CHECK_EQ(0, T::DecoderInit(isac_state_)); + if (bwinfo_) { + IsacBandwidthInfo bwinfo; + T::GetBandwidthInfo(isac_state_, &bwinfo); + bwinfo_->Set(bwinfo); + } +} + +template +AudioDecoderIsacT::~AudioDecoderIsacT() { + CHECK_EQ(0, T::Free(isac_state_)); +} + +template +int AudioDecoderIsacT::DecodeInternal(const uint8_t* encoded, + size_t encoded_len, + int sample_rate_hz, + int16_t* decoded, + SpeechType* speech_type) { // We want to crate the illusion that iSAC supports 48000 Hz decoding, while // in fact it outputs 32000 Hz. This is the iSAC fullband mode. if (sample_rate_hz == 48000) @@ -199,40 +222,47 @@ int AudioEncoderDecoderIsacT::DecodeInternal(const uint8_t* encoded, } template -bool AudioEncoderDecoderIsacT::HasDecodePlc() const { +bool AudioDecoderIsacT::HasDecodePlc() const { return false; } template -int AudioEncoderDecoderIsacT::DecodePlc(int num_frames, int16_t* decoded) { - CriticalSectionScoped cs(state_lock_.get()); +int AudioDecoderIsacT::DecodePlc(int num_frames, int16_t* decoded) { return T::DecodePlc(isac_state_, decoded, num_frames); } template -int AudioEncoderDecoderIsacT::Init() { - CriticalSectionScoped cs(state_lock_.get()); +int AudioDecoderIsacT::Init() { return T::DecoderInit(isac_state_); } template -int AudioEncoderDecoderIsacT::IncomingPacket(const uint8_t* payload, - size_t payload_len, - uint16_t rtp_sequence_number, - uint32_t rtp_timestamp, - uint32_t arrival_timestamp) { - CriticalSectionScoped cs(state_lock_.get()); - return T::UpdateBwEstimate( +int AudioDecoderIsacT::IncomingPacket(const uint8_t* payload, + size_t payload_len, + uint16_t rtp_sequence_number, + uint32_t rtp_timestamp, + uint32_t arrival_timestamp) { + int ret = T::UpdateBwEstimate( isac_state_, payload, static_cast(payload_len), rtp_sequence_number, rtp_timestamp, arrival_timestamp); + if (bwinfo_) { + IsacBandwidthInfo bwinfo; + T::GetBandwidthInfo(isac_state_, &bwinfo); + bwinfo_->Set(bwinfo); + } + return ret; } template -int AudioEncoderDecoderIsacT::ErrorCode() { - CriticalSectionScoped cs(state_lock_.get()); +int AudioDecoderIsacT::ErrorCode() { return T::GetErrorCode(isac_state_); } +template +size_t AudioDecoderIsacT::Channels() const { + return 1; +} + } // 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 index 02b5d3cab8..9d51161c31 100644 --- 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 @@ -120,46 +120,18 @@ struct IsacFix { } }; -typedef AudioEncoderDecoderIsacT AudioEncoderDecoderIsacFix; +using AudioEncoderIsacFix = AudioEncoderIsacT; +using AudioDecoderIsacFix = AudioDecoderIsacT; struct CodecInst; -class AudioEncoderDecoderMutableIsacFix - : public AudioEncoderMutableImpl { +class AudioEncoderMutableIsacFix + : public AudioEncoderMutableImpl { public: - explicit AudioEncoderDecoderMutableIsacFix(const CodecInst& codec_inst); - void UpdateSettings(const CodecInst& codec_inst) override; + explicit AudioEncoderMutableIsacFix(const CodecInst& codec_inst, + LockedIsacBandwidthInfo* bwinfo); void SetMaxPayloadSize(int max_payload_size_bytes) override; void SetMaxRate(int max_rate_bps) override; - - // From AudioDecoder. - int Decode(const uint8_t* encoded, - size_t encoded_len, - int sample_rate_hz, - size_t max_decoded_bytes, - int16_t* decoded, - SpeechType* speech_type) override; - int DecodeRedundant(const uint8_t* encoded, - size_t encoded_len, - int sample_rate_hz, - size_t max_decoded_bytes, - int16_t* decoded, - SpeechType* speech_type) override; - bool HasDecodePlc() const override; - int DecodePlc(int num_frames, int16_t* decoded) override; - int Init() override; - int IncomingPacket(const uint8_t* payload, - size_t payload_len, - uint16_t rtp_sequence_number, - uint32_t rtp_timestamp, - uint32_t arrival_timestamp) override; - int ErrorCode() override; - int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override; - int PacketDurationRedundant(const uint8_t* encoded, - size_t encoded_len) const override; - bool PacketHasFec(const uint8_t* encoded, size_t encoded_len) const override; - size_t Channels() const override; }; } // namespace webrtc 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 index c7999b56be..2f8d4b6e5d 100644 --- 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 @@ -17,13 +17,15 @@ namespace webrtc { const uint16_t IsacFix::kFixSampleRate; -// Explicit instantiation of AudioEncoderDecoderIsacT, a.k.a. -// AudioEncoderDecoderIsacFix. -template class AudioEncoderDecoderIsacT; +// Explicit instantiation: +template class AudioEncoderIsacT; +template class AudioDecoderIsacT; namespace { -AudioEncoderDecoderIsacFix::Config CreateConfig(const CodecInst& codec_inst) { - AudioEncoderDecoderIsacFix::Config config; +AudioEncoderIsacFix::Config CreateConfig(const CodecInst& codec_inst, + LockedIsacBandwidthInfo* bwinfo) { + AudioEncoderIsacFix::Config config; + config.bwinfo = bwinfo; config.payload_type = codec_inst.pltype; config.sample_rate_hz = codec_inst.plfreq; config.frame_size_ms = @@ -35,110 +37,22 @@ AudioEncoderDecoderIsacFix::Config CreateConfig(const CodecInst& codec_inst) { } } // namespace -AudioEncoderDecoderMutableIsacFix::AudioEncoderDecoderMutableIsacFix( - const CodecInst& codec_inst) - : AudioEncoderMutableImpl( - CreateConfig(codec_inst)) { -} +AudioEncoderMutableIsacFix::AudioEncoderMutableIsacFix( + const CodecInst& codec_inst, + LockedIsacBandwidthInfo* bwinfo) + : AudioEncoderMutableImpl( + CreateConfig(codec_inst, bwinfo)) {} -void AudioEncoderDecoderMutableIsacFix::UpdateSettings( - const CodecInst& codec_inst) { - bool success = Reconstruct(CreateConfig(codec_inst)); - DCHECK(success); -} - -void AudioEncoderDecoderMutableIsacFix::SetMaxPayloadSize( - int max_payload_size_bytes) { +void AudioEncoderMutableIsacFix::SetMaxPayloadSize(int max_payload_size_bytes) { auto conf = config(); conf.max_payload_size_bytes = max_payload_size_bytes; Reconstruct(conf); } -void AudioEncoderDecoderMutableIsacFix::SetMaxRate(int max_rate_bps) { +void AudioEncoderMutableIsacFix::SetMaxRate(int max_rate_bps) { auto conf = config(); conf.max_bit_rate = max_rate_bps; Reconstruct(conf); } -int AudioEncoderDecoderMutableIsacFix::Decode(const uint8_t* encoded, - size_t encoded_len, - int sample_rate_hz, - size_t max_decoded_bytes, - int16_t* decoded, - SpeechType* speech_type) { - CriticalSectionScoped cs(encoder_lock_.get()); - return encoder()->Decode(encoded, encoded_len, sample_rate_hz, - max_decoded_bytes, decoded, speech_type); -} - -int AudioEncoderDecoderMutableIsacFix::DecodeRedundant( - const uint8_t* encoded, - size_t encoded_len, - int sample_rate_hz, - size_t max_decoded_bytes, - int16_t* decoded, - SpeechType* speech_type) { - CriticalSectionScoped cs(encoder_lock_.get()); - return encoder()->DecodeRedundant(encoded, encoded_len, sample_rate_hz, - max_decoded_bytes, decoded, speech_type); -} - -bool AudioEncoderDecoderMutableIsacFix::HasDecodePlc() const { - CriticalSectionScoped cs(encoder_lock_.get()); - return encoder()->HasDecodePlc(); -} - -int AudioEncoderDecoderMutableIsacFix::DecodePlc(int num_frames, - int16_t* decoded) { - CriticalSectionScoped cs(encoder_lock_.get()); - return encoder()->DecodePlc(num_frames, decoded); -} - -int AudioEncoderDecoderMutableIsacFix::Init() { - CriticalSectionScoped cs(encoder_lock_.get()); - return encoder()->Init(); -} - -int AudioEncoderDecoderMutableIsacFix::IncomingPacket( - const uint8_t* payload, - size_t payload_len, - uint16_t rtp_sequence_number, - uint32_t rtp_timestamp, - uint32_t arrival_timestamp) { - CriticalSectionScoped cs(encoder_lock_.get()); - return encoder()->IncomingPacket(payload, payload_len, rtp_sequence_number, - rtp_timestamp, arrival_timestamp); -} - -int AudioEncoderDecoderMutableIsacFix::ErrorCode() { - CriticalSectionScoped cs(encoder_lock_.get()); - return encoder()->ErrorCode(); -} - -int AudioEncoderDecoderMutableIsacFix::PacketDuration( - const uint8_t* encoded, - size_t encoded_len) const { - CriticalSectionScoped cs(encoder_lock_.get()); - return encoder()->PacketDuration(encoded, encoded_len); -} - -int AudioEncoderDecoderMutableIsacFix::PacketDurationRedundant( - const uint8_t* encoded, - size_t encoded_len) const { - CriticalSectionScoped cs(encoder_lock_.get()); - return encoder()->PacketDurationRedundant(encoded, encoded_len); -} - -bool AudioEncoderDecoderMutableIsacFix::PacketHasFec(const uint8_t* encoded, - size_t encoded_len) const { - CriticalSectionScoped cs(encoder_lock_.get()); - return encoder()->PacketHasFec(encoded, encoded_len); -} - -size_t AudioEncoderDecoderMutableIsacFix::Channels() const { - CriticalSectionScoped cs(encoder_lock_.get()); - return encoder()->Channels(); -} - } // namespace webrtc diff --git a/webrtc/modules/audio_coding/codecs/isac/fix/source/isacfix.c b/webrtc/modules/audio_coding/codecs/isac/fix/source/isacfix.c index ba055ebdf5..9b61d60215 100644 --- a/webrtc/modules/audio_coding/codecs/isac/fix/source/isacfix.c +++ b/webrtc/modules/audio_coding/codecs/isac/fix/source/isacfix.c @@ -241,6 +241,31 @@ static void WebRtcIsacfix_InitMIPS(void) { } #endif +static void InitFunctionPointers(void) { + WebRtcIsacfix_AutocorrFix = WebRtcIsacfix_AutocorrC; + WebRtcIsacfix_FilterMaLoopFix = WebRtcIsacfix_FilterMaLoopC; + WebRtcIsacfix_CalculateResidualEnergy = + WebRtcIsacfix_CalculateResidualEnergyC; + WebRtcIsacfix_AllpassFilter2FixDec16 = WebRtcIsacfix_AllpassFilter2FixDec16C; + WebRtcIsacfix_HighpassFilterFixDec32 = WebRtcIsacfix_HighpassFilterFixDec32C; + WebRtcIsacfix_Time2Spec = WebRtcIsacfix_Time2SpecC; + WebRtcIsacfix_Spec2Time = WebRtcIsacfix_Spec2TimeC; + WebRtcIsacfix_MatrixProduct1 = WebRtcIsacfix_MatrixProduct1C; + WebRtcIsacfix_MatrixProduct2 = WebRtcIsacfix_MatrixProduct2C; + +#ifdef WEBRTC_DETECT_NEON + if ((WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON) != 0) { + WebRtcIsacfix_InitNeon(); + } +#elif defined(WEBRTC_HAS_NEON) + WebRtcIsacfix_InitNeon(); +#endif + +#if defined(MIPS32_LE) + WebRtcIsacfix_InitMIPS(); +#endif +} + /**************************************************************************** * WebRtcIsacfix_EncoderInit(...) * @@ -317,29 +342,7 @@ int16_t WebRtcIsacfix_EncoderInit(ISACFIX_MainStruct *ISAC_main_inst, WebRtcIsacfix_InitPostFilterbank(&ISAC_inst->ISACenc_obj.interpolatorstr_obj); #endif - // Initiaze function pointers. - WebRtcIsacfix_AutocorrFix = WebRtcIsacfix_AutocorrC; - WebRtcIsacfix_FilterMaLoopFix = WebRtcIsacfix_FilterMaLoopC; - WebRtcIsacfix_CalculateResidualEnergy = - WebRtcIsacfix_CalculateResidualEnergyC; - WebRtcIsacfix_AllpassFilter2FixDec16 = WebRtcIsacfix_AllpassFilter2FixDec16C; - WebRtcIsacfix_HighpassFilterFixDec32 = WebRtcIsacfix_HighpassFilterFixDec32C; - WebRtcIsacfix_Time2Spec = WebRtcIsacfix_Time2SpecC; - WebRtcIsacfix_Spec2Time = WebRtcIsacfix_Spec2TimeC; - WebRtcIsacfix_MatrixProduct1 = WebRtcIsacfix_MatrixProduct1C; - WebRtcIsacfix_MatrixProduct2 = WebRtcIsacfix_MatrixProduct2C; - -#ifdef WEBRTC_DETECT_NEON - if ((WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON) != 0) { - WebRtcIsacfix_InitNeon(); - } -#elif defined(WEBRTC_HAS_NEON) - WebRtcIsacfix_InitNeon(); -#endif - -#if defined(MIPS32_LE) - WebRtcIsacfix_InitMIPS(); -#endif + InitFunctionPointers(); return statusInit; } @@ -575,6 +578,8 @@ int16_t WebRtcIsacfix_DecoderInit(ISACFIX_MainStruct *ISAC_main_inst) { ISACFIX_SubStruct *ISAC_inst; + InitFunctionPointers(); + /* typecast pointer to real structure */ ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst; diff --git a/webrtc/modules/audio_coding/codecs/isac/isac.gypi b/webrtc/modules/audio_coding/codecs/isac/isac.gypi index 50cc867b23..8ecc2dc414 100644 --- a/webrtc/modules/audio_coding/codecs/isac/isac.gypi +++ b/webrtc/modules/audio_coding/codecs/isac/isac.gypi @@ -15,6 +15,7 @@ '<(webrtc_root)/common_audio/common_audio.gyp:common_audio', 'audio_decoder_interface', 'audio_encoder_interface', + 'isac_common', ], 'include_dirs': [ 'main/interface', @@ -27,8 +28,6 @@ ], }, 'sources': [ - 'audio_encoder_isac_t.h', - 'audio_encoder_isac_t_impl.h', 'main/interface/audio_encoder_isac.h', 'main/interface/isac.h', 'main/source/arith_routines.c', diff --git a/webrtc/modules/audio_coding/codecs/isac/isac_common.gypi b/webrtc/modules/audio_coding/codecs/isac/isac_common.gypi new file mode 100644 index 0000000000..135ecd27cc --- /dev/null +++ b/webrtc/modules/audio_coding/codecs/isac/isac_common.gypi @@ -0,0 +1,22 @@ +# Copyright (c) 2015 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. + +{ + 'targets': [ + { + 'target_name': 'isac_common', + 'type': 'static_library', + 'sources': [ + 'audio_encoder_isac_t.h', + 'audio_encoder_isac_t_impl.h', + 'locked_bandwidth_info.cc', + 'locked_bandwidth_info.h', + ], + }, + ], +} diff --git a/webrtc/modules/audio_coding/codecs/isac/isacfix.gypi b/webrtc/modules/audio_coding/codecs/isac/isacfix.gypi index e20177c365..81b4375c21 100644 --- a/webrtc/modules/audio_coding/codecs/isac/isacfix.gypi +++ b/webrtc/modules/audio_coding/codecs/isac/isacfix.gypi @@ -14,6 +14,7 @@ 'dependencies': [ '<(webrtc_root)/common_audio/common_audio.gyp:common_audio', '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers', + 'isac_common', ], 'include_dirs': [ 'fix/interface', @@ -26,8 +27,6 @@ ], }, 'sources': [ - 'audio_encoder_isac_t.h', - 'audio_encoder_isac_t_impl.h', 'fix/interface/audio_encoder_isacfix.h', 'fix/interface/isacfix.h', 'fix/source/arith_routines.c', diff --git a/webrtc/modules/audio_coding/codecs/isac/locked_bandwidth_info.cc b/webrtc/modules/audio_coding/codecs/isac/locked_bandwidth_info.cc new file mode 100644 index 0000000000..78b415c4c9 --- /dev/null +++ b/webrtc/modules/audio_coding/codecs/isac/locked_bandwidth_info.cc @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2015 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/locked_bandwidth_info.h" + +namespace webrtc { + +LockedIsacBandwidthInfo::LockedIsacBandwidthInfo() + : lock_(CriticalSectionWrapper::CreateCriticalSection()) { + bwinfo_.in_use = 0; +} + +LockedIsacBandwidthInfo::~LockedIsacBandwidthInfo() = default; + +} // namespace webrtc diff --git a/webrtc/modules/audio_coding/codecs/isac/locked_bandwidth_info.h b/webrtc/modules/audio_coding/codecs/isac/locked_bandwidth_info.h new file mode 100644 index 0000000000..bf39003c12 --- /dev/null +++ b/webrtc/modules/audio_coding/codecs/isac/locked_bandwidth_info.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2015 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_LOCKED_BANDWIDTH_INFO_H_ +#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_LOCKED_BANDWIDTH_INFO_H_ + +#include "webrtc/base/scoped_ptr.h" +#include "webrtc/base/thread_annotations.h" +#include "webrtc/modules/audio_coding/codecs/isac/bandwidth_info.h" +#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" + +namespace webrtc { + +// An IsacBandwidthInfo that's safe to access from multiple threads because +// it's protected by a mutex. +class LockedIsacBandwidthInfo final { + public: + LockedIsacBandwidthInfo(); + ~LockedIsacBandwidthInfo(); + + IsacBandwidthInfo Get() const { + CriticalSectionScoped cs(lock_.get()); + return bwinfo_; + } + + void Set(const IsacBandwidthInfo& bwinfo) { + CriticalSectionScoped cs(lock_.get()); + bwinfo_ = bwinfo; + } + + private: + const rtc::scoped_ptr lock_; + IsacBandwidthInfo bwinfo_ GUARDED_BY(lock_); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_LOCKED_BANDWIDTH_INFO_H_ 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 27998923f0..c0f3b11a09 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 @@ -118,46 +118,18 @@ struct IsacFloat { } }; -typedef AudioEncoderDecoderIsacT AudioEncoderDecoderIsac; +using AudioEncoderIsac = AudioEncoderIsacT; +using AudioDecoderIsac = AudioDecoderIsacT; struct CodecInst; -class AudioEncoderDecoderMutableIsacFloat - : public AudioEncoderMutableImpl { +class AudioEncoderMutableIsacFloat + : public AudioEncoderMutableImpl { public: - explicit AudioEncoderDecoderMutableIsacFloat(const CodecInst& codec_inst); - void UpdateSettings(const CodecInst& codec_inst) override; + AudioEncoderMutableIsacFloat(const CodecInst& codec_inst, + LockedIsacBandwidthInfo* bwinfo); void SetMaxPayloadSize(int max_payload_size_bytes) override; void SetMaxRate(int max_rate_bps) override; - - // From AudioDecoder. - int Decode(const uint8_t* encoded, - size_t encoded_len, - int sample_rate_hz, - size_t max_decoded_bytes, - int16_t* decoded, - SpeechType* speech_type) override; - int DecodeRedundant(const uint8_t* encoded, - size_t encoded_len, - int sample_rate_hz, - size_t max_decoded_bytes, - int16_t* decoded, - SpeechType* speech_type) override; - bool HasDecodePlc() const override; - int DecodePlc(int num_frames, int16_t* decoded) override; - int Init() override; - int IncomingPacket(const uint8_t* payload, - size_t payload_len, - uint16_t rtp_sequence_number, - uint32_t rtp_timestamp, - uint32_t arrival_timestamp) override; - int ErrorCode() override; - int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override; - int PacketDurationRedundant(const uint8_t* encoded, - size_t encoded_len) const override; - bool PacketHasFec(const uint8_t* encoded, size_t encoded_len) const override; - size_t Channels() const override; }; } // namespace webrtc 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 201a2d4bb4..195265dba6 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 @@ -15,13 +15,15 @@ namespace webrtc { -// Explicit instantiation of AudioEncoderDecoderIsacT, a.k.a. -// AudioEncoderDecoderIsac. -template class AudioEncoderDecoderIsacT; +// Explicit instantiation: +template class AudioEncoderIsacT; +template class AudioDecoderIsacT; namespace { -AudioEncoderDecoderIsac::Config CreateConfig(const CodecInst& codec_inst) { - AudioEncoderDecoderIsac::Config config; +AudioEncoderIsac::Config CreateConfig(const CodecInst& codec_inst, + LockedIsacBandwidthInfo* bwinfo) { + AudioEncoderIsac::Config config; + config.bwinfo = bwinfo; config.payload_type = codec_inst.pltype; config.sample_rate_hz = codec_inst.plfreq; config.frame_size_ms = @@ -33,111 +35,24 @@ AudioEncoderDecoderIsac::Config CreateConfig(const CodecInst& codec_inst) { } } // namespace -AudioEncoderDecoderMutableIsacFloat::AudioEncoderDecoderMutableIsacFloat( - const CodecInst& codec_inst) - : AudioEncoderMutableImpl( - CreateConfig(codec_inst)) { +AudioEncoderMutableIsacFloat::AudioEncoderMutableIsacFloat( + const CodecInst& codec_inst, + LockedIsacBandwidthInfo* bwinfo) + : AudioEncoderMutableImpl( + CreateConfig(codec_inst, bwinfo)) { } -void AudioEncoderDecoderMutableIsacFloat::UpdateSettings( - const CodecInst& codec_inst) { - bool success = Reconstruct(CreateConfig(codec_inst)); - DCHECK(success); -} - -void AudioEncoderDecoderMutableIsacFloat::SetMaxPayloadSize( +void AudioEncoderMutableIsacFloat::SetMaxPayloadSize( int max_payload_size_bytes) { auto conf = config(); conf.max_payload_size_bytes = max_payload_size_bytes; Reconstruct(conf); } -void AudioEncoderDecoderMutableIsacFloat::SetMaxRate(int max_rate_bps) { +void AudioEncoderMutableIsacFloat::SetMaxRate(int max_rate_bps) { auto conf = config(); conf.max_bit_rate = max_rate_bps; Reconstruct(conf); } -int AudioEncoderDecoderMutableIsacFloat::Decode(const uint8_t* encoded, - size_t encoded_len, - int sample_rate_hz, - size_t max_decoded_bytes, - int16_t* decoded, - SpeechType* speech_type) { - CriticalSectionScoped cs(encoder_lock_.get()); - return encoder()->Decode(encoded, encoded_len, sample_rate_hz, - max_decoded_bytes, decoded, speech_type); -} - -int AudioEncoderDecoderMutableIsacFloat::DecodeRedundant( - const uint8_t* encoded, - size_t encoded_len, - int sample_rate_hz, - size_t max_decoded_bytes, - int16_t* decoded, - SpeechType* speech_type) { - CriticalSectionScoped cs(encoder_lock_.get()); - return encoder()->DecodeRedundant(encoded, encoded_len, sample_rate_hz, - max_decoded_bytes, decoded, speech_type); -} - -bool AudioEncoderDecoderMutableIsacFloat::HasDecodePlc() const { - CriticalSectionScoped cs(encoder_lock_.get()); - return encoder()->HasDecodePlc(); -} - -int AudioEncoderDecoderMutableIsacFloat::DecodePlc(int num_frames, - int16_t* decoded) { - CriticalSectionScoped cs(encoder_lock_.get()); - return encoder()->DecodePlc(num_frames, decoded); -} - -int AudioEncoderDecoderMutableIsacFloat::Init() { - CriticalSectionScoped cs(encoder_lock_.get()); - return encoder()->Init(); -} - -int AudioEncoderDecoderMutableIsacFloat::IncomingPacket( - const uint8_t* payload, - size_t payload_len, - uint16_t rtp_sequence_number, - uint32_t rtp_timestamp, - uint32_t arrival_timestamp) { - CriticalSectionScoped cs(encoder_lock_.get()); - return encoder()->IncomingPacket(payload, payload_len, rtp_sequence_number, - rtp_timestamp, arrival_timestamp); -} - -int AudioEncoderDecoderMutableIsacFloat::ErrorCode() { - CriticalSectionScoped cs(encoder_lock_.get()); - return encoder()->ErrorCode(); -} - -int AudioEncoderDecoderMutableIsacFloat::PacketDuration( - const uint8_t* encoded, - size_t encoded_len) const { - CriticalSectionScoped cs(encoder_lock_.get()); - return encoder()->PacketDuration(encoded, encoded_len); -} - -int AudioEncoderDecoderMutableIsacFloat::PacketDurationRedundant( - const uint8_t* encoded, - size_t encoded_len) const { - CriticalSectionScoped cs(encoder_lock_.get()); - return encoder()->PacketDurationRedundant(encoded, encoded_len); -} - -bool AudioEncoderDecoderMutableIsacFloat::PacketHasFec( - const uint8_t* encoded, - size_t encoded_len) const { - CriticalSectionScoped cs(encoder_lock_.get()); - return encoder()->PacketHasFec(encoded, encoded_len); -} - -size_t AudioEncoderDecoderMutableIsacFloat::Channels() const { - CriticalSectionScoped cs(encoder_lock_.get()); - return encoder()->Channels(); -} - } // namespace webrtc diff --git a/webrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac_unittest.cc b/webrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac_unittest.cc index ee5c03121b..ff941ea79c 100644 --- a/webrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac_unittest.cc +++ b/webrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac_unittest.cc @@ -17,13 +17,13 @@ namespace webrtc { namespace { -void TestBadConfig(const AudioEncoderDecoderIsac::Config& config) { +void TestBadConfig(const AudioEncoderIsac::Config& config) { EXPECT_FALSE(config.IsOk()); } -void TestGoodConfig(const AudioEncoderDecoderIsac::Config& config) { +void TestGoodConfig(const AudioEncoderIsac::Config& config) { EXPECT_TRUE(config.IsOk()); - AudioEncoderDecoderIsac ed(config); + AudioEncoderIsac aei(config); } // Wrap subroutine calls that test things in this, so that the error messages @@ -34,7 +34,7 @@ void TestGoodConfig(const AudioEncoderDecoderIsac::Config& config) { } // namespace TEST(AudioEncoderIsacTest, TestConfigBitrate) { - AudioEncoderDecoderIsac::Config config; + AudioEncoderIsac::Config config; // The default value is some real, positive value. EXPECT_GT(config.bit_rate, 1); diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc index 568ae1ebe7..71c436b829 100644 --- a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc +++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc @@ -721,9 +721,9 @@ class AcmReRegisterIsacMtTestOldApi : public AudioCodingModuleTestOldApi { receive_packet_count_(0), next_insert_packet_time_ms_(0), fake_clock_(new SimulatedClock(0)) { - AudioEncoderDecoderIsac::Config config; + AudioEncoderIsac::Config config; config.payload_type = kPayloadType; - isac_encoder_.reset(new AudioEncoderDecoderIsac(config)); + isac_encoder_.reset(new AudioEncoderIsac(config)); clock_ = fake_clock_.get(); } @@ -845,7 +845,7 @@ class AcmReRegisterIsacMtTestOldApi : public AudioCodingModuleTestOldApi { bool codec_registered_ GUARDED_BY(crit_sect_); int receive_packet_count_ GUARDED_BY(crit_sect_); int64_t next_insert_packet_time_ms_ GUARDED_BY(crit_sect_); - rtc::scoped_ptr isac_encoder_; + rtc::scoped_ptr isac_encoder_; rtc::scoped_ptr fake_clock_; test::AudioLoop audio_loop_; }; diff --git a/webrtc/modules/audio_coding/main/acm2/codec_owner.cc b/webrtc/modules/audio_coding/main/acm2/codec_owner.cc index 4d214be242..ed23e10b56 100644 --- a/webrtc/modules/audio_coding/main/acm2/codec_owner.cc +++ b/webrtc/modules/audio_coding/main/acm2/codec_owner.cc @@ -75,55 +75,61 @@ bool IsG722(const CodecInst& codec) { } } // namespace -CodecOwner::CodecOwner() - : isac_is_encoder_(false), external_speech_encoder_(nullptr) { +CodecOwner::CodecOwner() : external_speech_encoder_(nullptr) { } CodecOwner::~CodecOwner() = default; namespace { -AudioEncoderDecoderMutableIsac* CreateIsacCodec(const CodecInst& speech_inst) { + +rtc::scoped_ptr CreateIsacDecoder( + LockedIsacBandwidthInfo* bwinfo) { #if defined(WEBRTC_CODEC_ISACFX) - return new AudioEncoderDecoderMutableIsacFix(speech_inst); + return rtc_make_scoped_ptr(new AudioDecoderIsacFix(bwinfo)); #elif defined(WEBRTC_CODEC_ISAC) - return new AudioEncoderDecoderMutableIsacFloat(speech_inst); + return rtc_make_scoped_ptr(new AudioDecoderIsac(bwinfo)); #else FATAL() << "iSAC is not supported."; - return nullptr; + return rtc::scoped_ptr(); #endif } -void CreateSpeechEncoder( +rtc::scoped_ptr CreateIsacEncoder( const CodecInst& speech_inst, - rtc::scoped_ptr* speech_encoder, - rtc::scoped_ptr* isac_codec, - bool* isac_is_encoder) { + LockedIsacBandwidthInfo* bwinfo) { +#if defined(WEBRTC_CODEC_ISACFX) + return rtc_make_scoped_ptr( + new AudioEncoderMutableIsacFix(speech_inst, bwinfo)); +#elif defined(WEBRTC_CODEC_ISAC) + return rtc_make_scoped_ptr( + new AudioEncoderMutableIsacFloat(speech_inst, bwinfo)); +#else + FATAL() << "iSAC is not supported."; + return rtc::scoped_ptr(); +#endif +} + +rtc::scoped_ptr CreateSpeechEncoder( + const CodecInst& speech_inst, + LockedIsacBandwidthInfo* bwinfo) { if (IsIsac(speech_inst)) { - if (*isac_codec) { - (*isac_codec)->UpdateSettings(speech_inst); - } else { - isac_codec->reset(CreateIsacCodec(speech_inst)); - } - *isac_is_encoder = true; - speech_encoder->reset(); - return; - } - if (IsOpus(speech_inst)) { - speech_encoder->reset(new AudioEncoderMutableOpus(speech_inst)); + return CreateIsacEncoder(speech_inst, bwinfo); + } else if (IsOpus(speech_inst)) { + return rtc_make_scoped_ptr(new AudioEncoderMutableOpus(speech_inst)); } else if (IsPcmU(speech_inst)) { - speech_encoder->reset(new AudioEncoderMutablePcmU(speech_inst)); + return rtc_make_scoped_ptr(new AudioEncoderMutablePcmU(speech_inst)); } else if (IsPcmA(speech_inst)) { - speech_encoder->reset(new AudioEncoderMutablePcmA(speech_inst)); + return rtc_make_scoped_ptr(new AudioEncoderMutablePcmA(speech_inst)); } else if (IsPcm16B(speech_inst)) { - speech_encoder->reset(new AudioEncoderMutablePcm16B(speech_inst)); + return rtc_make_scoped_ptr(new AudioEncoderMutablePcm16B(speech_inst)); } else if (IsIlbc(speech_inst)) { - speech_encoder->reset(new AudioEncoderMutableIlbc(speech_inst)); + return rtc_make_scoped_ptr(new AudioEncoderMutableIlbc(speech_inst)); } else if (IsG722(speech_inst)) { - speech_encoder->reset(new AudioEncoderMutableG722(speech_inst)); + return rtc_make_scoped_ptr(new AudioEncoderMutableG722(speech_inst)); } else { FATAL(); + return rtc::scoped_ptr(); } - *isac_is_encoder = false; } AudioEncoder* CreateRedEncoder(int red_payload_type, @@ -176,8 +182,7 @@ void CodecOwner::SetEncoders(const CodecInst& speech_inst, int cng_payload_type, ACMVADMode vad_mode, int red_payload_type) { - CreateSpeechEncoder(speech_inst, &speech_encoder_, &isac_codec_, - &isac_is_encoder_); + speech_encoder_ = CreateSpeechEncoder(speech_inst, &isac_bandwidth_info_); external_speech_encoder_ = nullptr; ChangeCngAndRed(cng_payload_type, vad_mode, red_payload_type); } @@ -188,7 +193,6 @@ void CodecOwner::SetEncoders(AudioEncoderMutable* external_speech_encoder, int red_payload_type) { external_speech_encoder_ = external_speech_encoder; speech_encoder_.reset(); - isac_is_encoder_ = false; ChangeCngAndRed(cng_payload_type, vad_mode, red_payload_type); } @@ -204,24 +208,13 @@ void CodecOwner::ChangeCngAndRed(int cng_payload_type, AudioEncoder* encoder = CreateRedEncoder(red_payload_type, speech_encoder, &red_encoder_); CreateCngEncoder(cng_payload_type, vad_mode, encoder, &cng_encoder_); - int num_true = - !!speech_encoder_ + !!external_speech_encoder_ + isac_is_encoder_; - DCHECK_EQ(num_true, 1); - DCHECK(!isac_is_encoder_ || isac_codec_); + DCHECK_EQ(!!speech_encoder_ + !!external_speech_encoder_, 1); } AudioDecoder* CodecOwner::GetIsacDecoder() { - if (!isac_codec_) { - DCHECK(!isac_is_encoder_); - // None of the parameter values in |speech_inst| matter when the codec is - // used only as a decoder. - CodecInst speech_inst; - speech_inst.plfreq = 16000; - speech_inst.rate = -1; - speech_inst.pacsize = 480; - isac_codec_.reset(CreateIsacCodec(speech_inst)); - } - return isac_codec_.get(); + if (!isac_decoder_) + isac_decoder_ = CreateIsacDecoder(&isac_bandwidth_info_); + return isac_decoder_.get(); } AudioEncoder* CodecOwner::Encoder() { @@ -243,15 +236,9 @@ AudioEncoderMutable* CodecOwner::SpeechEncoder() { } const AudioEncoderMutable* CodecOwner::SpeechEncoder() const { - int num_true = - !!speech_encoder_ + !!external_speech_encoder_ + isac_is_encoder_; - DCHECK_GE(num_true, 0); - DCHECK_LE(num_true, 1); - if (external_speech_encoder_) - return external_speech_encoder_; - if (speech_encoder_) - return speech_encoder_.get(); - return isac_is_encoder_ ? isac_codec_.get() : nullptr; + DCHECK(!speech_encoder_ || !external_speech_encoder_); + return external_speech_encoder_ ? external_speech_encoder_ + : speech_encoder_.get(); } } // namespace acm2 diff --git a/webrtc/modules/audio_coding/main/acm2/codec_owner.h b/webrtc/modules/audio_coding/main/acm2/codec_owner.h index 2468c3ce00..2c5e942ef5 100644 --- a/webrtc/modules/audio_coding/main/acm2/codec_owner.h +++ b/webrtc/modules/audio_coding/main/acm2/codec_owner.h @@ -53,21 +53,17 @@ class CodecOwner { const AudioEncoderMutable* SpeechEncoder() const; private: - // There are three main cases for the state of the encoder members below: - // 1. An external encoder is used. |external_speech_encoder_| points to it. - // |speech_encoder_| is null, and |isac_is_encoder_| is false. - // 2. The internal iSAC codec is used as encoder. |isac_codec_| points to it - // and |isac_is_encoder_| is true. |external_speech_encoder_| and - // |speech_encoder_| are null. - // 3. Another internal encoder is used. |speech_encoder_| points to it. - // |external_speech_encoder_| is null, and |isac_is_encoder_| is false. - // In addition to case 2, |isac_codec_| is valid when GetIsacDecoder has been - // called. + // At most one of these is non-null: rtc::scoped_ptr speech_encoder_; - rtc::scoped_ptr isac_codec_; - bool isac_is_encoder_; AudioEncoderMutable* external_speech_encoder_; + // If we've created an iSAC decoder because someone called GetIsacDecoder, + // store it here. + rtc::scoped_ptr isac_decoder_; + + // iSAC bandwidth estimation info, for use with iSAC encoders and decoders. + LockedIsacBandwidthInfo isac_bandwidth_info_; + // |cng_encoder_| and |red_encoder_| are valid iff CNG or RED, respectively, // are active. rtc::scoped_ptr cng_encoder_; diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc index 6a9b953f23..53dc0335a4 100644 --- a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc +++ b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc @@ -559,22 +559,13 @@ AudioDecoder* CreateAudioDecoder(NetEqDecoder codec_type) { return new AudioDecoderIlbc; #endif #if defined(WEBRTC_CODEC_ISACFX) - case kDecoderISAC: { - AudioEncoderDecoderIsacFix::Config config; - return new AudioEncoderDecoderIsacFix(config); - } + case kDecoderISAC: + return new AudioDecoderIsacFix(); #elif defined(WEBRTC_CODEC_ISAC) - case kDecoderISAC: { - AudioEncoderDecoderIsac::Config config; - config.sample_rate_hz = 16000; - return new AudioEncoderDecoderIsac(config); - } + case kDecoderISAC: case kDecoderISACswb: - case kDecoderISACfb: { - AudioEncoderDecoderIsac::Config config; - config.sample_rate_hz = 32000; - return new AudioEncoderDecoderIsac(config); - } + case kDecoderISACfb: + return new AudioDecoderIsac(); #endif #ifdef WEBRTC_CODEC_PCM16 case kDecoderPCM16B: diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc b/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc index d54fbe9099..3983c07701 100644 --- a/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc @@ -358,17 +358,14 @@ class AudioDecoderIsacFloatTest : public AudioDecoderTest { codec_input_rate_hz_ = 16000; frame_size_ = 480; data_length_ = 10 * frame_size_; - AudioEncoderDecoderIsac::Config config; + AudioEncoderIsac::Config config; config.payload_type = payload_type_; config.sample_rate_hz = codec_input_rate_hz_; config.adaptive_mode = false; config.frame_size_ms = 1000 * static_cast(frame_size_) / codec_input_rate_hz_; - - // 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); + audio_encoder_.reset(new AudioEncoderIsac(config)); + decoder_ = new AudioDecoderIsac(); } }; @@ -378,17 +375,14 @@ class AudioDecoderIsacSwbTest : public AudioDecoderTest { codec_input_rate_hz_ = 32000; frame_size_ = 960; data_length_ = 10 * frame_size_; - AudioEncoderDecoderIsac::Config config; + AudioEncoderIsac::Config config; config.payload_type = payload_type_; config.sample_rate_hz = codec_input_rate_hz_; config.adaptive_mode = false; config.frame_size_ms = 1000 * static_cast(frame_size_) / codec_input_rate_hz_; - - // 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); + audio_encoder_.reset(new AudioEncoderIsac(config)); + decoder_ = new AudioDecoderIsac(); } }; @@ -398,18 +392,14 @@ class AudioDecoderIsacFixTest : public AudioDecoderTest { codec_input_rate_hz_ = 16000; frame_size_ = 480; data_length_ = 10 * frame_size_; - AudioEncoderDecoderIsacFix::Config config; + AudioEncoderIsacFix::Config config; config.payload_type = payload_type_; config.sample_rate_hz = codec_input_rate_hz_; config.adaptive_mode = false; config.frame_size_ms = 1000 * static_cast(frame_size_) / codec_input_rate_hz_; - - // 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); + audio_encoder_.reset(new AudioEncoderIsacFix(config)); + decoder_ = new AudioDecoderIsacFix(); } };