diff --git a/modules/audio_coding/BUILD.gn b/modules/audio_coding/BUILD.gn index ec81697dca..b836646624 100644 --- a/modules/audio_coding/BUILD.gn +++ b/modules/audio_coding/BUILD.gn @@ -14,31 +14,6 @@ if (!build_with_mozilla) { visibility = [ ":*" ] -audio_codec_deps = [ - ":g711", - ":pcm16b", -] -if (rtc_include_ilbc) { - audio_codec_deps += [ ":ilbc" ] -} -if (rtc_include_opus) { - audio_codec_deps += [ ":webrtc_opus" ] -} -if (current_cpu == "arm") { - audio_codec_deps += [ ":isac_fix" ] -} else { - audio_codec_deps += [ ":isac" ] -} -audio_codec_deps += [ ":g722" ] -if (!build_with_mozilla && !build_with_chromium) { - audio_codec_deps += [ ":red" ] -} -audio_coding_deps = audio_codec_deps + [ - "../..:webrtc_common", - "../../common_audio", - "../../system_wrappers", - ] - rtc_static_library("audio_format_conversion") { visibility += webrtc_default_visibility sources = [ @@ -63,7 +38,6 @@ rtc_static_library("rent_a_codec") { # TODO(bugs.webrtc.org/9808): Move to private visibility as soon as that # client code gets updated. visibility += [ "*" ] - allow_poison = [ "audio_codecs" ] sources = [ "acm2/acm_codec_database.cc", @@ -72,22 +46,18 @@ rtc_static_library("rent_a_codec") { "acm2/rent_a_codec.h", ] deps = [ - "../../rtc_base:checks", - "../../api:array_view", - "//third_party/abseil-cpp/absl/strings", - "//third_party/abseil-cpp/absl/types:optional", - "../../api/audio_codecs:audio_codecs_api", - "../..:webrtc_common", - "../../rtc_base:protobuf_utils", - "../../rtc_base:rtc_base_approved", - "../../system_wrappers", - ":audio_coding_module_typedefs", - ":isac_common", - ":isac_fix_c", - ":audio_encoder_cng", - ":neteq_decoder_enum", - ] + audio_codec_deps - + ":audio_coding_module_typedefs", + ":neteq_decoder_enum", + "../..:webrtc_common", + "../../api:array_view", + "../../api/audio_codecs:audio_codecs_api", + "../../rtc_base:checks", + "../../rtc_base:protobuf_utils", + "../../rtc_base:rtc_base_approved", + "../../system_wrappers", + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] defines = audio_codec_defines } @@ -102,7 +72,6 @@ rtc_source_set("audio_coding_module_typedefs") { rtc_static_library("audio_coding") { visibility += [ "*" ] - allow_poison = [ "audio_codecs" ] # TODO(bugs.webrtc.org/8396): Remove. sources = [ "acm2/acm_receiver.cc", "acm2/acm_receiver.h", @@ -111,40 +80,34 @@ rtc_static_library("audio_coding") { "acm2/audio_coding_module.cc", "acm2/call_statistics.cc", "acm2/call_statistics.h", - "acm2/codec_manager.cc", - "acm2/codec_manager.h", "include/audio_coding_module.h", ] defines = [] - if (rtc_include_opus) { - public_deps = [ - ":webrtc_opus", - ] - } - - deps = audio_coding_deps + [ - "../../system_wrappers:metrics", - "../../api/audio:audio_frame_api", - "..:module_api", - "..:module_api_public", - "../../common_audio:common_audio_c", - "../../rtc_base:deprecation", - "../../rtc_base:checks", - "../../api:array_view", - "../../api/audio_codecs:audio_codecs_api", - ":audio_coding_module_typedefs", - ":neteq", - ":neteq_decoder_enum", - ":rent_a_codec", - "../../rtc_base:audio_format_to_string", - "../../rtc_base:rtc_base_approved", - "//third_party/abseil-cpp/absl/strings", - "//third_party/abseil-cpp/absl/types:optional", - "../../logging:rtc_event_log_api", - ] - defines = audio_coding_defines + deps = [ + ":audio_coding_module_typedefs", + ":neteq", + ":neteq_decoder_enum", + ":rent_a_codec", + "..:module_api", + "..:module_api_public", + "../..:webrtc_common", + "../../api:array_view", + "../../api/audio:audio_frame_api", + "../../api/audio_codecs:audio_codecs_api", + "../../common_audio:common_audio", + "../../common_audio:common_audio_c", + "../../logging:rtc_event_log_api", + "../../rtc_base:audio_format_to_string", + "../../rtc_base:checks", + "../../rtc_base:deprecation", + "../../rtc_base:rtc_base_approved", + "../../system_wrappers", + "../../system_wrappers:metrics", + "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", + ] } rtc_static_library("legacy_encoded_audio_frame") { @@ -1280,6 +1243,30 @@ if (rtc_enable_protobuf) { } if (rtc_include_tests) { + audio_coding_deps = [ + "../../common_audio", + "../../system_wrappers", + "../..:webrtc_common", + ":audio_encoder_cng", + ":g711", + ":g722", + ":pcm16b", + ] + if (rtc_include_ilbc) { + audio_coding_deps += [ ":ilbc" ] + } + if (rtc_include_opus) { + audio_coding_deps += [ ":webrtc_opus" ] + } + if (current_cpu == "arm") { + audio_coding_deps += [ ":isac_fix" ] + } else { + audio_coding_deps += [ ":isac" ] + } + if (!build_with_mozilla && !build_with_chromium) { + audio_coding_deps += [ ":red" ] + } + rtc_source_set("mocks") { testonly = true sources = [ @@ -1368,6 +1355,7 @@ if (rtc_include_tests) { ":audio_format_conversion", ":pcm16b_c", ":red", + ":webrtc_opus_c", "..:module_api", "../..:webrtc_common", "../../api/audio:audio_frame_api", @@ -2007,8 +1995,6 @@ if (rtc_include_tests) { "acm2/acm_receiver_unittest.cc", "acm2/audio_coding_module_unittest.cc", "acm2/call_statistics_unittest.cc", - "acm2/codec_manager_unittest.cc", - "acm2/rent_a_codec_unittest.cc", "audio_network_adaptor/audio_network_adaptor_impl_unittest.cc", "audio_network_adaptor/bitrate_controller_unittest.cc", "audio_network_adaptor/channel_controller_unittest.cc", diff --git a/modules/audio_coding/acm2/audio_coding_module.cc b/modules/audio_coding/acm2/audio_coding_module.cc index 334c0e0b38..c0aab3a30f 100644 --- a/modules/audio_coding/acm2/audio_coding_module.cc +++ b/modules/audio_coding/acm2/audio_coding_module.cc @@ -18,7 +18,6 @@ #include "api/array_view.h" #include "modules/audio_coding/acm2/acm_receiver.h" #include "modules/audio_coding/acm2/acm_resampler.h" -#include "modules/audio_coding/acm2/codec_manager.h" #include "modules/audio_coding/acm2/rent_a_codec.h" #include "modules/include/module_common_types.h" #include "modules/include/module_common_types_public.h" @@ -34,12 +33,6 @@ namespace webrtc { namespace { -struct EncoderFactory { - AudioEncoder* external_speech_encoder = nullptr; - acm2::CodecManager codec_manager; - acm2::RentACodec rent_a_codec; -}; - class AudioCodingModuleImpl final : public AudioCodingModule { public: explicit AudioCodingModuleImpl(const AudioCodingModule::Config& config); @@ -49,12 +42,6 @@ class AudioCodingModuleImpl final : public AudioCodingModule { // Sender // - // Can be called multiple times for Codec, CNG, RED. - int RegisterSendCodec(const CodecInst& send_codec) override; - - void RegisterExternalSendCodec( - AudioEncoder* external_speech_encoder) override; - void ModifyEncoder(rtc::FunctionView*)> modifier) override; @@ -73,26 +60,10 @@ class AudioCodingModuleImpl final : public AudioCodingModule { // Add 10 ms of raw (PCM) audio data to the encoder. int Add10MsData(const AudioFrame& audio_frame) override; - ///////////////////////////////////////// - // (RED) Redundant Coding - // - - // Configure RED status i.e. on/off. - int SetREDStatus(bool enable_red) override; - - // Get RED status. - bool REDStatus() const override; - ///////////////////////////////////////// // (FEC) Forward Error Correction (codec internal) // - // Configure FEC status i.e. on/off. - int SetCodecFEC(bool enabled_codec_fec) override; - - // Get FEC status. - bool CodecFEC() const override; - // Set target packet loss rate int SetPacketLossRate(int loss_rate) override; @@ -102,14 +73,6 @@ class AudioCodingModuleImpl final : public AudioCodingModule { // (CNG) Comfort Noise Generation // - int SetVAD(bool enable_dtx = true, - bool enable_vad = false, - ACMVADMode mode = VADNormal) override; - - int VAD(bool* dtx_enabled, - bool* vad_enabled, - ACMVADMode* mode) const override; - int RegisterVADCallback(ACMVADCallback* vad_callback) override; ///////////////////////////////////////// @@ -130,11 +93,6 @@ class AudioCodingModuleImpl final : public AudioCodingModule { bool RegisterReceiveCodec(int rtp_payload_type, const SdpAudioFormat& audio_format) override; - int RegisterReceiveCodec(const CodecInst& receive_codec) override; - int RegisterReceiveCodec( - const CodecInst& receive_codec, - rtc::FunctionView()> isac_factory) override; - int RegisterExternalReceiveCodec(int rtp_payload_type, AudioDecoder* external_decoder, int sample_rate_hz, @@ -222,11 +180,6 @@ class AudioCodingModuleImpl final : public AudioCodingModule { const std::string histogram_name_; }; - int RegisterReceiveCodecUnlocked( - const CodecInst& codec, - rtc::FunctionView()> isac_factory) - RTC_EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_); - int Add10MsDataInternal(const AudioFrame& audio_frame, InputData* input_data) RTC_EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_); int Encode(const InputData& input_data) @@ -264,12 +217,7 @@ class AudioCodingModuleImpl final : public AudioCodingModule { acm2::AcmReceiver receiver_; // AcmReceiver has it's own internal lock. ChangeLogger bitrate_logger_ RTC_GUARDED_BY(acm_crit_sect_); - std::unique_ptr encoder_factory_ - RTC_GUARDED_BY(acm_crit_sect_); - - // Current encoder stack, either obtained from - // encoder_factory_->rent_a_codec.RentEncoderStack or provided by a call to - // RegisterEncoder. + // Current encoder stack, provided by a call to RegisterEncoder. std::unique_ptr encoder_stack_ RTC_GUARDED_BY(acm_crit_sect_); std::unique_ptr isac_decoder_16k_ @@ -405,28 +353,6 @@ class RawAudioEncoderWrapper final : public AudioEncoder { AudioEncoder* enc_; }; -// Return false on error. -bool CreateSpeechEncoderIfNecessary(EncoderFactory* ef) { - auto* sp = ef->codec_manager.GetStackParams(); - if (sp->speech_encoder) { - // Do nothing; we already have a speech encoder. - } else if (ef->codec_manager.GetCodecInst()) { - RTC_DCHECK(!ef->external_speech_encoder); - // We have no speech encoder, but we have a specification for making one. - std::unique_ptr enc = - ef->rent_a_codec.RentEncoder(*ef->codec_manager.GetCodecInst()); - if (!enc) - return false; // Encoder spec was bad. - sp->speech_encoder = std::move(enc); - } else if (ef->external_speech_encoder) { - RTC_DCHECK(!ef->codec_manager.GetCodecInst()); - // We have an external speech encoder. - sp->speech_encoder = std::unique_ptr( - new RawAudioEncoderWrapper(ef->external_speech_encoder)); - } - return true; -} - void AudioCodingModuleImpl::ChangeLogger::MaybeLog(int value) { if (value != last_value_ || first_time_) { first_time_ = false; @@ -441,7 +367,6 @@ AudioCodingModuleImpl::AudioCodingModuleImpl( expected_in_ts_(0xD87F3F9F), receiver_(config), bitrate_logger_("WebRTC.Audio.TargetBitrateInKbps"), - encoder_factory_(new EncoderFactory), encoder_stack_(nullptr), previous_pltype_(255), receiver_initialized_(false), @@ -549,69 +474,29 @@ int32_t AudioCodingModuleImpl::Encode(const InputData& input_data) { // Sender // -// Can be called multiple times for Codec, CNG, RED. -int AudioCodingModuleImpl::RegisterSendCodec(const CodecInst& send_codec) { - rtc::CritScope lock(&acm_crit_sect_); - if (!encoder_factory_->codec_manager.RegisterEncoder(send_codec)) { - return -1; - } - if (encoder_factory_->codec_manager.GetCodecInst()) { - encoder_factory_->external_speech_encoder = nullptr; - } - if (!CreateSpeechEncoderIfNecessary(encoder_factory_.get())) { - return -1; - } - auto* sp = encoder_factory_->codec_manager.GetStackParams(); - if (sp->speech_encoder) - encoder_stack_ = encoder_factory_->rent_a_codec.RentEncoderStack(sp); - return 0; -} - -void AudioCodingModuleImpl::RegisterExternalSendCodec( - AudioEncoder* external_speech_encoder) { - rtc::CritScope lock(&acm_crit_sect_); - encoder_factory_->codec_manager.UnsetCodecInst(); - encoder_factory_->external_speech_encoder = external_speech_encoder; - RTC_CHECK(CreateSpeechEncoderIfNecessary(encoder_factory_.get())); - auto* sp = encoder_factory_->codec_manager.GetStackParams(); - RTC_CHECK(sp->speech_encoder); - encoder_stack_ = encoder_factory_->rent_a_codec.RentEncoderStack(sp); -} - void AudioCodingModuleImpl::ModifyEncoder( rtc::FunctionView*)> modifier) { rtc::CritScope lock(&acm_crit_sect_); - - // Wipe the encoder factory, so that everything that relies on it will fail. - // We don't want the complexity of supporting swapping back and forth. - if (encoder_factory_) { - encoder_factory_.reset(); - RTC_CHECK(!encoder_stack_); // Ensure we hadn't started using the factory. - } - modifier(&encoder_stack_); } // Get current send codec. absl::optional AudioCodingModuleImpl::SendCodec() const { rtc::CritScope lock(&acm_crit_sect_); - if (encoder_factory_) { - auto* ci = encoder_factory_->codec_manager.GetCodecInst(); - if (ci) { - return *ci; - } - CreateSpeechEncoderIfNecessary(encoder_factory_.get()); - const std::unique_ptr& enc = - encoder_factory_->codec_manager.GetStackParams()->speech_encoder; - if (enc) { - return acm2::CodecManager::ForgeCodecInst(enc.get()); - } - return absl::nullopt; + if (encoder_stack_) { + CodecInst ci; + ci.channels = encoder_stack_->NumChannels(); + ci.plfreq = encoder_stack_->SampleRateHz(); + ci.pacsize = rtc::CheckedDivExact( + static_cast(encoder_stack_->Max10MsFramesInAPacket() * ci.plfreq), + 100); + ci.pltype = -1; // Not valid. + ci.rate = -1; // Not valid. + static const char kName[] = "external"; + memcpy(ci.plname, kName, sizeof(kName)); + return ci; } else { - return encoder_stack_ - ? absl::optional( - acm2::CodecManager::ForgeCodecInst(encoder_stack_.get())) - : absl::nullopt; + return absl::nullopt; } } @@ -808,59 +693,10 @@ int AudioCodingModuleImpl::PreprocessToAddData(const AudioFrame& in_frame, return 0; } -///////////////////////////////////////// -// (RED) Redundant Coding -// - -bool AudioCodingModuleImpl::REDStatus() const { - rtc::CritScope lock(&acm_crit_sect_); - return encoder_factory_->codec_manager.GetStackParams()->use_red; -} - -// Configure RED status i.e on/off. -int AudioCodingModuleImpl::SetREDStatus(bool enable_red) { -#ifdef WEBRTC_CODEC_RED - rtc::CritScope lock(&acm_crit_sect_); - CreateSpeechEncoderIfNecessary(encoder_factory_.get()); - if (!encoder_factory_->codec_manager.SetCopyRed(enable_red)) { - return -1; - } - auto* sp = encoder_factory_->codec_manager.GetStackParams(); - if (sp->speech_encoder) - encoder_stack_ = encoder_factory_->rent_a_codec.RentEncoderStack(sp); - return 0; -#else - RTC_LOG(LS_WARNING) << " WEBRTC_CODEC_RED is undefined"; - return -1; -#endif -} - ///////////////////////////////////////// // (FEC) Forward Error Correction (codec internal) // -bool AudioCodingModuleImpl::CodecFEC() const { - rtc::CritScope lock(&acm_crit_sect_); - return encoder_factory_->codec_manager.GetStackParams()->use_codec_fec; -} - -int AudioCodingModuleImpl::SetCodecFEC(bool enable_codec_fec) { - rtc::CritScope lock(&acm_crit_sect_); - CreateSpeechEncoderIfNecessary(encoder_factory_.get()); - if (!encoder_factory_->codec_manager.SetCodecFEC(enable_codec_fec)) { - return -1; - } - auto* sp = encoder_factory_->codec_manager.GetStackParams(); - if (sp->speech_encoder) - encoder_stack_ = encoder_factory_->rent_a_codec.RentEncoderStack(sp); - if (enable_codec_fec) { - return sp->use_codec_fec ? 0 : -1; - } else { - RTC_DCHECK(!sp->use_codec_fec); - return 0; - } -} - int AudioCodingModuleImpl::SetPacketLossRate(int loss_rate) { rtc::CritScope lock(&acm_crit_sect_); if (HaveValidEncoder("SetPacketLossRate")) { @@ -869,36 +705,6 @@ int AudioCodingModuleImpl::SetPacketLossRate(int loss_rate) { return 0; } -///////////////////////////////////////// -// (VAD) Voice Activity Detection -// -int AudioCodingModuleImpl::SetVAD(bool enable_dtx, - bool enable_vad, - ACMVADMode mode) { - // Note: |enable_vad| is not used; VAD is enabled based on the DTX setting. - RTC_DCHECK_EQ(enable_dtx, enable_vad); - rtc::CritScope lock(&acm_crit_sect_); - CreateSpeechEncoderIfNecessary(encoder_factory_.get()); - if (!encoder_factory_->codec_manager.SetVAD(enable_dtx, mode)) { - return -1; - } - auto* sp = encoder_factory_->codec_manager.GetStackParams(); - if (sp->speech_encoder) - encoder_stack_ = encoder_factory_->rent_a_codec.RentEncoderStack(sp); - return 0; -} - -// Get VAD/DTX settings. -int AudioCodingModuleImpl::VAD(bool* dtx_enabled, - bool* vad_enabled, - ACMVADMode* mode) const { - rtc::CritScope lock(&acm_crit_sect_); - const auto* sp = encoder_factory_->codec_manager.GetStackParams(); - *dtx_enabled = *vad_enabled = sp->use_cng; - *mode = sp->vad_mode; - return 0; -} - ///////////////////////////////////////// // Receiver // @@ -957,59 +763,6 @@ bool AudioCodingModuleImpl::RegisterReceiveCodec( return receiver_.AddCodec(rtp_payload_type, audio_format); } -int AudioCodingModuleImpl::RegisterReceiveCodec(const CodecInst& codec) { - rtc::CritScope lock(&acm_crit_sect_); - auto* ef = encoder_factory_.get(); - return RegisterReceiveCodecUnlocked( - codec, [&] { return ef->rent_a_codec.RentIsacDecoder(codec.plfreq); }); -} - -int AudioCodingModuleImpl::RegisterReceiveCodec( - const CodecInst& codec, - rtc::FunctionView()> isac_factory) { - rtc::CritScope lock(&acm_crit_sect_); - return RegisterReceiveCodecUnlocked(codec, isac_factory); -} - -int AudioCodingModuleImpl::RegisterReceiveCodecUnlocked( - const CodecInst& codec, - rtc::FunctionView()> isac_factory) { - RTC_DCHECK(receiver_initialized_); - if (codec.channels > 2) { - RTC_LOG_F(LS_ERROR) << "Unsupported number of channels: " << codec.channels; - return -1; - } - - auto codec_id = acm2::RentACodec::CodecIdByParams(codec.plname, codec.plfreq, - codec.channels); - if (!codec_id) { - RTC_LOG_F(LS_ERROR) - << "Wrong codec params to be registered as receive codec"; - return -1; - } - auto codec_index = acm2::RentACodec::CodecIndexFromId(*codec_id); - RTC_CHECK(codec_index) << "Invalid codec ID: " << static_cast(*codec_id); - - // Check if the payload-type is valid. - if (!acm2::RentACodec::IsPayloadTypeValid(codec.pltype)) { - RTC_LOG_F(LS_ERROR) << "Invalid payload type " << codec.pltype << " for " - << codec.plname; - return -1; - } - - AudioDecoder* isac_decoder = nullptr; - if (absl::EqualsIgnoreCase(codec.plname, "isac")) { - std::unique_ptr& saved_isac_decoder = - codec.plfreq == 16000 ? isac_decoder_16k_ : isac_decoder_32k_; - if (!saved_isac_decoder) { - saved_isac_decoder = isac_factory(); - } - isac_decoder = saved_isac_decoder.get(); - } - return receiver_.AddCodec(*codec_index, codec.pltype, codec.channels, - codec.plfreq, isac_decoder, codec.plname); -} - int AudioCodingModuleImpl::RegisterExternalReceiveCodec( int rtp_payload_type, AudioDecoder* external_decoder, diff --git a/modules/audio_coding/acm2/codec_manager.cc b/modules/audio_coding/acm2/codec_manager.cc deleted file mode 100644 index eda6555062..0000000000 --- a/modules/audio_coding/acm2/codec_manager.cc +++ /dev/null @@ -1,253 +0,0 @@ -/* - * 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 "modules/audio_coding/acm2/codec_manager.h" - -#include -#include -#include -#include - -#include "absl/strings/match.h" -#include "api/array_view.h" -#include "api/audio_codecs/audio_encoder.h" -#include "modules/audio_coding/acm2/rent_a_codec.h" -#include "rtc_base/checks.h" -#include "rtc_base/logging.h" - -namespace webrtc { -namespace acm2 { - -namespace { - -// Check if the given codec is a valid to be registered as send codec. -int IsValidSendCodec(const CodecInst& send_codec) { - if ((send_codec.channels != 1) && (send_codec.channels != 2)) { - RTC_LOG(LS_ERROR) << "Wrong number of channels (" << send_codec.channels - << "), only mono and stereo are supported)"; - return -1; - } - - auto maybe_codec_id = RentACodec::CodecIdByInst(send_codec); - if (!maybe_codec_id) { - RTC_LOG(LS_ERROR) << "Invalid codec setting for the send codec."; - return -1; - } - - // Telephone-event cannot be a send codec. - if (absl::EqualsIgnoreCase(send_codec.plname, "telephone-event")) { - RTC_LOG(LS_ERROR) << "telephone-event cannot be a send codec"; - return -1; - } - - if (!RentACodec::IsSupportedNumChannels(*maybe_codec_id, send_codec.channels) - .value_or(false)) { - RTC_LOG(LS_ERROR) << send_codec.channels - << " number of channels not supported for " - << send_codec.plname << "."; - return -1; - } - return RentACodec::CodecIndexFromId(*maybe_codec_id).value_or(-1); -} - -bool IsOpus(const CodecInst& codec) { - return -#ifdef WEBRTC_CODEC_OPUS - absl::EqualsIgnoreCase(codec.plname, "opus") || -#endif - false; -} - -} // namespace - -CodecManager::CodecManager() { - thread_checker_.DetachFromThread(); -} - -CodecManager::~CodecManager() = default; - -bool CodecManager::RegisterEncoder(const CodecInst& send_codec) { - RTC_DCHECK(thread_checker_.CalledOnValidThread()); - int codec_id = IsValidSendCodec(send_codec); - - // Check for reported errors from function IsValidSendCodec(). - if (codec_id < 0) { - return false; - } - - switch (RentACodec::RegisterRedPayloadType( - &codec_stack_params_.red_payload_types, send_codec)) { - case RentACodec::RegistrationResult::kOk: - return true; - case RentACodec::RegistrationResult::kBadFreq: - RTC_LOG(LS_ERROR) - << "RegisterSendCodec() failed, invalid frequency for RED" - " registration"; - return false; - case RentACodec::RegistrationResult::kSkip: - break; - } - switch (RentACodec::RegisterCngPayloadType( - &codec_stack_params_.cng_payload_types, send_codec)) { - case RentACodec::RegistrationResult::kOk: - return true; - case RentACodec::RegistrationResult::kBadFreq: - RTC_LOG(LS_ERROR) - << "RegisterSendCodec() failed, invalid frequency for CNG" - " registration"; - return false; - case RentACodec::RegistrationResult::kSkip: - break; - } - - if (IsOpus(send_codec)) { - // VAD/DTX not supported. - codec_stack_params_.use_cng = false; - } - - send_codec_inst_ = send_codec; - recreate_encoder_ = true; // Caller must recreate it. - return true; -} - -CodecInst CodecManager::ForgeCodecInst( - const AudioEncoder* external_speech_encoder) { - CodecInst ci; - ci.channels = external_speech_encoder->NumChannels(); - ci.plfreq = external_speech_encoder->SampleRateHz(); - ci.pacsize = rtc::CheckedDivExact( - static_cast(external_speech_encoder->Max10MsFramesInAPacket() * - ci.plfreq), - 100); - ci.pltype = -1; // Not valid. - ci.rate = -1; // Not valid. - static const char kName[] = "external"; - memcpy(ci.plname, kName, sizeof(kName)); - return ci; -} - -bool CodecManager::SetCopyRed(bool enable) { - if (enable && codec_stack_params_.use_codec_fec) { - RTC_LOG(LS_WARNING) << "Codec internal FEC and RED cannot be co-enabled."; - return false; - } - if (enable && send_codec_inst_ && - codec_stack_params_.red_payload_types.count(send_codec_inst_->plfreq) < - 1) { - RTC_LOG(LS_WARNING) << "Cannot enable RED at " << send_codec_inst_->plfreq - << " Hz."; - return false; - } - codec_stack_params_.use_red = enable; - return true; -} - -bool CodecManager::SetVAD(bool enable, ACMVADMode mode) { - // Sanity check of the mode. - RTC_DCHECK(mode == VADNormal || mode == VADLowBitrate || mode == VADAggr || - mode == VADVeryAggr); - - // Check that the send codec is mono. We don't support VAD/DTX for stereo - // sending. - const bool stereo_send = - codec_stack_params_.speech_encoder - ? (codec_stack_params_.speech_encoder->NumChannels() != 1) - : false; - if (enable && stereo_send) { - RTC_LOG(LS_ERROR) << "VAD/DTX not supported for stereo sending"; - return false; - } - - // TODO(kwiberg): This doesn't protect Opus when injected as an external - // encoder. - if (send_codec_inst_ && IsOpus(*send_codec_inst_)) { - // VAD/DTX not supported, but don't fail. - enable = false; - } - - codec_stack_params_.use_cng = enable; - codec_stack_params_.vad_mode = mode; - return true; -} - -bool CodecManager::SetCodecFEC(bool enable_codec_fec) { - if (enable_codec_fec && codec_stack_params_.use_red) { - RTC_LOG(LS_WARNING) << "Codec internal FEC and RED cannot be co-enabled."; - return false; - } - - codec_stack_params_.use_codec_fec = enable_codec_fec; - return true; -} - -bool CodecManager::MakeEncoder(RentACodec* rac, AudioCodingModule* acm) { - RTC_DCHECK(rac); - RTC_DCHECK(acm); - - if (!recreate_encoder_) { - bool error = false; - // Try to re-use the speech encoder we've given to the ACM. - acm->ModifyEncoder([&](std::unique_ptr* encoder) { - if (!*encoder) { - // There is no existing encoder. - recreate_encoder_ = true; - return; - } - - // Extract the speech encoder from the ACM. - std::unique_ptr enc = std::move(*encoder); - while (true) { - auto sub_enc = enc->ReclaimContainedEncoders(); - if (sub_enc.empty()) { - break; - } - RTC_CHECK_EQ(1, sub_enc.size()); - - // Replace enc with its sub encoder. We need to put the sub encoder in - // a temporary first, since otherwise the old value of enc would be - // destroyed before the new value got assigned, which would be bad - // since the new value is a part of the old value. - auto tmp_enc = std::move(sub_enc[0]); - enc = std::move(tmp_enc); - } - - // Wrap it in a new encoder stack and put it back. - codec_stack_params_.speech_encoder = std::move(enc); - *encoder = rac->RentEncoderStack(&codec_stack_params_); - if (!*encoder) { - error = true; - } - }); - if (error) { - return false; - } - if (!recreate_encoder_) { - return true; - } - } - - if (!send_codec_inst_) { - // We don't have the information we need to create a new speech encoder. - // (This is not an error.) - return true; - } - - codec_stack_params_.speech_encoder = rac->RentEncoder(*send_codec_inst_); - auto stack = rac->RentEncoderStack(&codec_stack_params_); - if (!stack) { - return false; - } - acm->SetEncoder(std::move(stack)); - recreate_encoder_ = false; - return true; -} - -} // namespace acm2 -} // namespace webrtc diff --git a/modules/audio_coding/acm2/codec_manager.h b/modules/audio_coding/acm2/codec_manager.h deleted file mode 100644 index 22dbf4e72b..0000000000 --- a/modules/audio_coding/acm2/codec_manager.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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 MODULES_AUDIO_CODING_ACM2_CODEC_MANAGER_H_ -#define MODULES_AUDIO_CODING_ACM2_CODEC_MANAGER_H_ - -#include "absl/types/optional.h" -#include "common_types.h" // NOLINT(build/include) -#include "modules/audio_coding/acm2/rent_a_codec.h" -#include "modules/audio_coding/include/audio_coding_module.h" -#include "modules/audio_coding/include/audio_coding_module_typedefs.h" -#include "rtc_base/constructormagic.h" -#include "rtc_base/thread_checker.h" - -namespace webrtc { - -class AudioEncoder; - -namespace acm2 { - -class CodecManager final { - public: - CodecManager(); - ~CodecManager(); - - // Parses the given specification. On success, returns true and updates the - // stored CodecInst and stack parameters; on error, returns false. - bool RegisterEncoder(const CodecInst& send_codec); - - static CodecInst ForgeCodecInst(const AudioEncoder* external_speech_encoder); - - const CodecInst* GetCodecInst() const { - return send_codec_inst_ ? &*send_codec_inst_ : nullptr; - } - - void UnsetCodecInst() { send_codec_inst_ = absl::nullopt; } - - const RentACodec::StackParameters* GetStackParams() const { - return &codec_stack_params_; - } - RentACodec::StackParameters* GetStackParams() { return &codec_stack_params_; } - - bool SetCopyRed(bool enable); - - bool SetVAD(bool enable, ACMVADMode mode); - - bool SetCodecFEC(bool enable_codec_fec); - - // Uses the provided Rent-A-Codec to create a new encoder stack, if we have a - // complete specification; if so, it is then passed to set_encoder. On error, - // returns false. - bool MakeEncoder(RentACodec* rac, AudioCodingModule* acm); - - private: - rtc::ThreadChecker thread_checker_; - absl::optional send_codec_inst_; - RentACodec::StackParameters codec_stack_params_; - bool recreate_encoder_ = true; // Need to recreate encoder? - - RTC_DISALLOW_COPY_AND_ASSIGN(CodecManager); -}; - -} // namespace acm2 -} // namespace webrtc -#endif // MODULES_AUDIO_CODING_ACM2_CODEC_MANAGER_H_ diff --git a/modules/audio_coding/acm2/codec_manager_unittest.cc b/modules/audio_coding/acm2/codec_manager_unittest.cc deleted file mode 100644 index 6a5ea5f52e..0000000000 --- a/modules/audio_coding/acm2/codec_manager_unittest.cc +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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 - -#include "modules/audio_coding/acm2/codec_manager.h" -#include "modules/audio_coding/acm2/rent_a_codec.h" -#include "test/gtest.h" -#include "test/mock_audio_encoder.h" - -namespace webrtc { -namespace acm2 { - -using ::testing::Return; - -namespace { - -// Create a MockAudioEncoder with some reasonable default behavior. -std::unique_ptr CreateMockEncoder() { - auto enc = std::unique_ptr(new MockAudioEncoder); - EXPECT_CALL(*enc, SampleRateHz()).WillRepeatedly(Return(8000)); - EXPECT_CALL(*enc, NumChannels()).WillRepeatedly(Return(1)); - EXPECT_CALL(*enc, Max10MsFramesInAPacket()).WillRepeatedly(Return(1)); - return enc; -} - -} // namespace - -TEST(CodecManagerTest, ExternalEncoderFec) { - auto enc0 = CreateMockEncoder(); - auto enc1 = CreateMockEncoder(); - auto enc2 = CreateMockEncoder(); - { - ::testing::InSequence s; - EXPECT_CALL(*enc0, SetFec(false)).WillOnce(Return(true)); - EXPECT_CALL(*enc1, SetFec(true)).WillOnce(Return(true)); - EXPECT_CALL(*enc2, SetFec(true)).WillOnce(Return(false)); - } - - CodecManager cm; - RentACodec rac; - - // use_codec_fec starts out false. - EXPECT_FALSE(cm.GetStackParams()->use_codec_fec); - cm.GetStackParams()->speech_encoder = std::move(enc0); - EXPECT_TRUE(rac.RentEncoderStack(cm.GetStackParams())); - EXPECT_FALSE(cm.GetStackParams()->use_codec_fec); - - // Set it to true. - EXPECT_EQ(true, cm.SetCodecFEC(true)); - EXPECT_TRUE(cm.GetStackParams()->use_codec_fec); - cm.GetStackParams()->speech_encoder = std::move(enc1); - EXPECT_TRUE(rac.RentEncoderStack(cm.GetStackParams())); - EXPECT_TRUE(cm.GetStackParams()->use_codec_fec); - - // Switch to a codec that doesn't support it. - cm.GetStackParams()->speech_encoder = std::move(enc2); - EXPECT_TRUE(rac.RentEncoderStack(cm.GetStackParams())); - EXPECT_FALSE(cm.GetStackParams()->use_codec_fec); -} - -} // namespace acm2 -} // namespace webrtc diff --git a/modules/audio_coding/acm2/rent_a_codec.cc b/modules/audio_coding/acm2/rent_a_codec.cc index 76015192e0..d7457b8ad7 100644 --- a/modules/audio_coding/acm2/rent_a_codec.cc +++ b/modules/audio_coding/acm2/rent_a_codec.cc @@ -13,35 +13,9 @@ #include #include -#include "absl/strings/match.h" -#include "modules/audio_coding/codecs/cng/audio_encoder_cng.h" -#include "modules/audio_coding/codecs/g711/audio_encoder_pcm.h" -#include "modules/audio_coding/codecs/g722/audio_encoder_g722.h" #include "rtc_base/logging.h" -#ifdef WEBRTC_CODEC_ILBC -#include "modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h" // nogncheck -#endif -#ifdef WEBRTC_CODEC_ISACFX -#include "modules/audio_coding/codecs/isac/fix/include/audio_decoder_isacfix.h" // nogncheck -#include "modules/audio_coding/codecs/isac/fix/include/audio_encoder_isacfix.h" // nogncheck -#endif -#ifdef WEBRTC_CODEC_ISAC -#include "modules/audio_coding/codecs/isac/main/include/audio_decoder_isac.h" // nogncheck -#include "modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h" // nogncheck -#endif -#ifdef WEBRTC_CODEC_OPUS -#include "modules/audio_coding/codecs/opus/audio_encoder_opus.h" -#endif -#include "modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h" -#ifdef WEBRTC_CODEC_RED -#include "modules/audio_coding/codecs/red/audio_encoder_copy_red.h" // nogncheck -#endif #include "modules/audio_coding/acm2/acm_codec_database.h" -#if defined(WEBRTC_CODEC_ISACFX) || defined(WEBRTC_CODEC_ISAC) -#include "modules/audio_coding/codecs/isac/locked_bandwidth_info.h" -#endif - namespace webrtc { namespace acm2 { @@ -107,200 +81,5 @@ absl::optional RentACodec::NetEqDecoderFromCodecId( : ned; } -RentACodec::RegistrationResult RentACodec::RegisterCngPayloadType( - std::map* pt_map, - const CodecInst& codec_inst) { - if (!absl::EqualsIgnoreCase(codec_inst.plname, "CN")) - return RegistrationResult::kSkip; - switch (codec_inst.plfreq) { - case 8000: - case 16000: - case 32000: - case 48000: - (*pt_map)[codec_inst.plfreq] = codec_inst.pltype; - return RegistrationResult::kOk; - default: - return RegistrationResult::kBadFreq; - } -} - -RentACodec::RegistrationResult RentACodec::RegisterRedPayloadType( - std::map* pt_map, - const CodecInst& codec_inst) { - if (!absl::EqualsIgnoreCase(codec_inst.plname, "RED")) - return RegistrationResult::kSkip; - switch (codec_inst.plfreq) { - case 8000: - (*pt_map)[codec_inst.plfreq] = codec_inst.pltype; - return RegistrationResult::kOk; - default: - return RegistrationResult::kBadFreq; - } -} - -namespace { - -// Returns a new speech encoder, or null on error. -// TODO(kwiberg): Don't handle errors here (bug 5033) -std::unique_ptr CreateEncoder( - const CodecInst& speech_inst, - const rtc::scoped_refptr& bwinfo) { -#if defined(WEBRTC_CODEC_ISACFX) - if (absl::EqualsIgnoreCase(speech_inst.plname, "isac")) - return std::unique_ptr( - new AudioEncoderIsacFixImpl(speech_inst, bwinfo)); -#endif -#if defined(WEBRTC_CODEC_ISAC) - if (absl::EqualsIgnoreCase(speech_inst.plname, "isac")) - return std::unique_ptr( - new AudioEncoderIsacFloatImpl(speech_inst, bwinfo)); -#endif -#ifdef WEBRTC_CODEC_OPUS - if (absl::EqualsIgnoreCase(speech_inst.plname, "opus")) - return std::unique_ptr(new AudioEncoderOpusImpl(speech_inst)); -#endif - if (absl::EqualsIgnoreCase(speech_inst.plname, "pcmu")) - return std::unique_ptr(new AudioEncoderPcmU(speech_inst)); - if (absl::EqualsIgnoreCase(speech_inst.plname, "pcma")) - return std::unique_ptr(new AudioEncoderPcmA(speech_inst)); - if (absl::EqualsIgnoreCase(speech_inst.plname, "l16")) - return std::unique_ptr(new AudioEncoderPcm16B(speech_inst)); -#ifdef WEBRTC_CODEC_ILBC - if (absl::EqualsIgnoreCase(speech_inst.plname, "ilbc")) - return std::unique_ptr(new AudioEncoderIlbcImpl(speech_inst)); -#endif - if (absl::EqualsIgnoreCase(speech_inst.plname, "g722")) - return std::unique_ptr(new AudioEncoderG722Impl(speech_inst)); - RTC_LOG_F(LS_ERROR) << "Could not create encoder of type " - << speech_inst.plname; - return std::unique_ptr(); -} - -std::unique_ptr CreateRedEncoder( - std::unique_ptr encoder, - int red_payload_type) { -#ifdef WEBRTC_CODEC_RED - AudioEncoderCopyRed::Config config; - config.payload_type = red_payload_type; - config.speech_encoder = std::move(encoder); - return std::unique_ptr( - new AudioEncoderCopyRed(std::move(config))); -#else - return std::unique_ptr(); -#endif -} - -std::unique_ptr CreateCngEncoder( - std::unique_ptr encoder, - int payload_type, - ACMVADMode vad_mode) { - AudioEncoderCngConfig config; - config.num_channels = encoder->NumChannels(); - config.payload_type = payload_type; - config.speech_encoder = std::move(encoder); - switch (vad_mode) { - case VADNormal: - config.vad_mode = Vad::kVadNormal; - break; - case VADLowBitrate: - config.vad_mode = Vad::kVadLowBitrate; - break; - case VADAggr: - config.vad_mode = Vad::kVadAggressive; - break; - case VADVeryAggr: - config.vad_mode = Vad::kVadVeryAggressive; - break; - default: - FATAL(); - } - return CreateComfortNoiseEncoder(std::move(config)); -} - -std::unique_ptr CreateIsacDecoder( - int sample_rate_hz, - const rtc::scoped_refptr& bwinfo) { -#if defined(WEBRTC_CODEC_ISACFX) - return std::unique_ptr( - new AudioDecoderIsacFixImpl(sample_rate_hz, bwinfo)); -#elif defined(WEBRTC_CODEC_ISAC) - return std::unique_ptr( - new AudioDecoderIsacFloatImpl(sample_rate_hz, bwinfo)); -#else - FATAL() << "iSAC is not supported."; - return std::unique_ptr(); -#endif -} - -} // namespace - -RentACodec::RentACodec() { -#if defined(WEBRTC_CODEC_ISACFX) || defined(WEBRTC_CODEC_ISAC) - isac_bandwidth_info_ = new LockedIsacBandwidthInfo; -#endif -} -RentACodec::~RentACodec() = default; - -std::unique_ptr RentACodec::RentEncoder( - const CodecInst& codec_inst) { - return CreateEncoder(codec_inst, isac_bandwidth_info_); -} - -RentACodec::StackParameters::StackParameters() { - // Register the default payload types for RED and CNG. - for (const CodecInst& ci : RentACodec::Database()) { - RentACodec::RegisterCngPayloadType(&cng_payload_types, ci); - RentACodec::RegisterRedPayloadType(&red_payload_types, ci); - } -} - -RentACodec::StackParameters::~StackParameters() = default; - -std::unique_ptr RentACodec::RentEncoderStack( - StackParameters* param) { - if (!param->speech_encoder) - return nullptr; - - if (param->use_codec_fec) { - // Switch FEC on. On failure, remember that FEC is off. - if (!param->speech_encoder->SetFec(true)) - param->use_codec_fec = false; - } else { - // Switch FEC off. This shouldn't fail. - const bool success = param->speech_encoder->SetFec(false); - RTC_DCHECK(success); - } - - auto pt = [¶m](const std::map& m) { - auto it = m.find(param->speech_encoder->SampleRateHz()); - return it == m.end() ? absl::nullopt : absl::optional(it->second); - }; - auto cng_pt = pt(param->cng_payload_types); - param->use_cng = - param->use_cng && cng_pt && param->speech_encoder->NumChannels() == 1; - auto red_pt = pt(param->red_payload_types); - param->use_red = param->use_red && red_pt; - - if (param->use_cng || param->use_red) { - // The RED and CNG encoders need to be in sync with the speech encoder, so - // reset the latter to ensure its buffer is empty. - param->speech_encoder->Reset(); - } - std::unique_ptr encoder_stack = - std::move(param->speech_encoder); - if (param->use_red) { - encoder_stack = CreateRedEncoder(std::move(encoder_stack), *red_pt); - } - if (param->use_cng) { - encoder_stack = - CreateCngEncoder(std::move(encoder_stack), *cng_pt, param->vad_mode); - } - return encoder_stack; -} - -std::unique_ptr RentACodec::RentIsacDecoder(int sample_rate_hz) { - return CreateIsacDecoder(sample_rate_hz, isac_bandwidth_info_); -} - } // namespace acm2 } // namespace webrtc diff --git a/modules/audio_coding/acm2/rent_a_codec.h b/modules/audio_coding/acm2/rent_a_codec.h index b0ad382d8a..afac3b1774 100644 --- a/modules/audio_coding/acm2/rent_a_codec.h +++ b/modules/audio_coding/acm2/rent_a_codec.h @@ -31,8 +31,7 @@ class LockedIsacBandwidthInfo; namespace acm2 { -class RentACodec { - public: +struct RentACodec { enum class CodecId { #if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX) kISAC, @@ -141,56 +140,6 @@ class RentACodec { static absl::optional NetEqDecoderFromCodecId( CodecId codec_id, size_t num_channels); - - // Parse codec_inst and extract payload types. If the given CodecInst was for - // the wrong sort of codec, return kSkip; otherwise, if the rate was illegal, - // return kBadFreq; otherwise, update the given RTP timestamp rate (Hz) -> - // payload type map and return kOk. - enum class RegistrationResult { kOk, kSkip, kBadFreq }; - static RegistrationResult RegisterCngPayloadType(std::map* pt_map, - const CodecInst& codec_inst); - static RegistrationResult RegisterRedPayloadType(std::map* pt_map, - const CodecInst& codec_inst); - - RentACodec(); - ~RentACodec(); - - // Creates and returns an audio encoder built to the given specification. - // Returns null in case of error. - std::unique_ptr RentEncoder(const CodecInst& codec_inst); - - struct StackParameters { - StackParameters(); - ~StackParameters(); - - std::unique_ptr speech_encoder; - - bool use_codec_fec = false; - bool use_red = false; - bool use_cng = false; - ACMVADMode vad_mode = VADNormal; - - // Maps from RTP timestamp rate (in Hz) to payload type. - std::map cng_payload_types; - std::map red_payload_types; - }; - - // Creates and returns an audio encoder stack constructed to the given - // specification. If the specification isn't compatible with the encoder, it - // will be changed to match (things will be switched off). The speech encoder - // will be stolen. If the specification isn't complete, returns nullptr. - std::unique_ptr RentEncoderStack(StackParameters* param); - - // Creates and returns an iSAC decoder. - std::unique_ptr RentIsacDecoder(int sample_rate_hz); - - private: - std::unique_ptr speech_encoder_; - std::unique_ptr cng_encoder_; - std::unique_ptr red_encoder_; - rtc::scoped_refptr isac_bandwidth_info_; - - RTC_DISALLOW_COPY_AND_ASSIGN(RentACodec); }; } // namespace acm2 diff --git a/modules/audio_coding/acm2/rent_a_codec_unittest.cc b/modules/audio_coding/acm2/rent_a_codec_unittest.cc deleted file mode 100644 index fd3329cfb1..0000000000 --- a/modules/audio_coding/acm2/rent_a_codec_unittest.cc +++ /dev/null @@ -1,228 +0,0 @@ -/* - * 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 - -#include "common_types.h" -#include "modules/audio_coding/acm2/rent_a_codec.h" -#include "rtc_base/arraysize.h" -#include "test/gtest.h" -#include "test/mock_audio_encoder.h" - -namespace webrtc { -namespace acm2 { - -using ::testing::Return; - -namespace { - -const int kDataLengthSamples = 80; -const int kPacketSizeSamples = 2 * kDataLengthSamples; -const int16_t kZeroData[kDataLengthSamples] = {0}; -const CodecInst kDefaultCodecInst = {0, "pcmu", 8000, kPacketSizeSamples, - 1, 64000}; -const int kCngPt = 13; - -class Marker final { - public: - MOCK_METHOD1(Mark, void(std::string desc)); -}; - -} // namespace - -class RentACodecTestF : public ::testing::Test { - protected: - void CreateCodec() { - auto speech_encoder = rent_a_codec_.RentEncoder(kDefaultCodecInst); - ASSERT_TRUE(speech_encoder); - RentACodec::StackParameters param; - param.use_cng = true; - param.speech_encoder = std::move(speech_encoder); - encoder_ = rent_a_codec_.RentEncoderStack(¶m); - } - - void EncodeAndVerify(size_t expected_out_length, - uint32_t expected_timestamp, - int expected_payload_type, - int expected_send_even_if_empty) { - rtc::Buffer out; - AudioEncoder::EncodedInfo encoded_info; - encoded_info = encoder_->Encode(timestamp_, kZeroData, &out); - timestamp_ += kDataLengthSamples; - EXPECT_TRUE(encoded_info.redundant.empty()); - EXPECT_EQ(expected_out_length, encoded_info.encoded_bytes); - EXPECT_EQ(expected_timestamp, encoded_info.encoded_timestamp); - if (expected_payload_type >= 0) - EXPECT_EQ(expected_payload_type, encoded_info.payload_type); - if (expected_send_even_if_empty >= 0) - EXPECT_EQ(static_cast(expected_send_even_if_empty), - encoded_info.send_even_if_empty); - } - - RentACodec rent_a_codec_; - std::unique_ptr encoder_; - uint32_t timestamp_ = 0; -}; - -// This test verifies that CNG frames are delivered as expected. Since the frame -// size is set to 20 ms, we expect the first encode call to produce no output -// (which is signaled as 0 bytes output of type kNoEncoding). The next encode -// call should produce one SID frame of 9 bytes. The third call should not -// result in any output (just like the first one). The fourth and final encode -// call should produce an "empty frame", which is like no output, but with -// AudioEncoder::EncodedInfo::send_even_if_empty set to true. (The reason to -// produce an empty frame is to drive sending of DTMF packets in the RTP/RTCP -// module.) -TEST_F(RentACodecTestF, VerifyCngFrames) { - CreateCodec(); - uint32_t expected_timestamp = timestamp_; - // Verify no frame. - { - SCOPED_TRACE("First encoding"); - EncodeAndVerify(0, expected_timestamp, -1, -1); - } - - // Verify SID frame delivered. - { - SCOPED_TRACE("Second encoding"); - EncodeAndVerify(9, expected_timestamp, kCngPt, 1); - } - - // Verify no frame. - { - SCOPED_TRACE("Third encoding"); - EncodeAndVerify(0, expected_timestamp, -1, -1); - } - - // Verify NoEncoding. - expected_timestamp += 2 * kDataLengthSamples; - { - SCOPED_TRACE("Fourth encoding"); - EncodeAndVerify(0, expected_timestamp, kCngPt, 1); - } -} - -TEST(RentACodecTest, ExternalEncoder) { - const int kSampleRateHz = 8000; - auto* external_encoder = new MockAudioEncoder; - EXPECT_CALL(*external_encoder, SampleRateHz()) - .WillRepeatedly(Return(kSampleRateHz)); - EXPECT_CALL(*external_encoder, NumChannels()).WillRepeatedly(Return(1)); - EXPECT_CALL(*external_encoder, SetFec(false)).WillRepeatedly(Return(true)); - - RentACodec rac; - RentACodec::StackParameters param; - param.speech_encoder = std::unique_ptr(external_encoder); - std::unique_ptr encoder_stack = rac.RentEncoderStack(¶m); - EXPECT_EQ(external_encoder, encoder_stack.get()); - const int kPacketSizeSamples = kSampleRateHz / 100; - int16_t audio[kPacketSizeSamples] = {0}; - rtc::Buffer encoded; - AudioEncoder::EncodedInfo info; - - Marker marker; - { - ::testing::InSequence s; - info.encoded_timestamp = 0; - EXPECT_CALL(*external_encoder, - EncodeImpl(0, rtc::ArrayView(audio), &encoded)) - .WillOnce(Return(info)); - EXPECT_CALL(marker, Mark("A")); - EXPECT_CALL(marker, Mark("B")); - EXPECT_CALL(marker, Mark("C")); - } - - info = encoder_stack->Encode(0, audio, &encoded); - EXPECT_EQ(0u, info.encoded_timestamp); - marker.Mark("A"); - - // Change to internal encoder. - CodecInst codec_inst = kDefaultCodecInst; - codec_inst.pacsize = kPacketSizeSamples; - param.speech_encoder = rac.RentEncoder(codec_inst); - ASSERT_TRUE(param.speech_encoder); - AudioEncoder* enc = param.speech_encoder.get(); - std::unique_ptr stack = rac.RentEncoderStack(¶m); - EXPECT_EQ(enc, stack.get()); - - // Don't expect any more calls to the external encoder. - info = stack->Encode(1, audio, &encoded); - marker.Mark("B"); - encoder_stack.reset(); - marker.Mark("C"); -} - -// Verify that the speech encoder's Reset method is called when CNG or RED -// (or both) are switched on, but not when they're switched off. -void TestCngAndRedResetSpeechEncoder(bool use_cng, bool use_red) { - auto make_enc = [] { - auto speech_encoder = - std::unique_ptr(new MockAudioEncoder); - EXPECT_CALL(*speech_encoder, NumChannels()).WillRepeatedly(Return(1)); - EXPECT_CALL(*speech_encoder, Max10MsFramesInAPacket()) - .WillRepeatedly(Return(2)); - EXPECT_CALL(*speech_encoder, SampleRateHz()).WillRepeatedly(Return(8000)); - EXPECT_CALL(*speech_encoder, SetFec(false)).WillRepeatedly(Return(true)); - return speech_encoder; - }; - auto speech_encoder1 = make_enc(); - auto speech_encoder2 = make_enc(); - Marker marker; - { - ::testing::InSequence s; - EXPECT_CALL(marker, Mark("disabled")); - EXPECT_CALL(marker, Mark("enabled")); - if (use_cng || use_red) - EXPECT_CALL(*speech_encoder2, Reset()); - } - - RentACodec::StackParameters param1, param2; - param1.speech_encoder = std::move(speech_encoder1); - param2.speech_encoder = std::move(speech_encoder2); - param2.use_cng = use_cng; - param2.use_red = use_red; - marker.Mark("disabled"); - RentACodec rac; - rac.RentEncoderStack(¶m1); - marker.Mark("enabled"); - rac.RentEncoderStack(¶m2); -} - -TEST(RentACodecTest, CngResetsSpeechEncoder) { - TestCngAndRedResetSpeechEncoder(true, false); -} - -TEST(RentACodecTest, RedResetsSpeechEncoder) { - TestCngAndRedResetSpeechEncoder(false, true); -} - -TEST(RentACodecTest, CngAndRedResetsSpeechEncoder) { - TestCngAndRedResetSpeechEncoder(true, true); -} - -TEST(RentACodecTest, NoCngAndRedNoSpeechEncoderReset) { - TestCngAndRedResetSpeechEncoder(false, false); -} - -TEST(RentACodecTest, RentEncoderError) { - const CodecInst codec_inst = { - 0, "Robert'); DROP TABLE Students;", 8000, 160, 1, 64000}; - RentACodec rent_a_codec; - EXPECT_FALSE(rent_a_codec.RentEncoder(codec_inst)); -} - -TEST(RentACodecTest, RentEncoderStackWithoutSpeechEncoder) { - RentACodec::StackParameters sp; - EXPECT_EQ(nullptr, sp.speech_encoder); - EXPECT_EQ(nullptr, RentACodec().RentEncoderStack(&sp)); -} - -} // namespace acm2 -} // namespace webrtc diff --git a/modules/audio_coding/include/audio_coding_module.h b/modules/audio_coding/include/audio_coding_module.h index b9f22288fd..f9fdba5f51 100644 --- a/modules/audio_coding/include/audio_coding_module.h +++ b/modules/audio_coding/include/audio_coding_module.h @@ -154,40 +154,6 @@ class AudioCodingModule { // Sender // - /////////////////////////////////////////////////////////////////////////// - // int32_t RegisterSendCodec() - // Registers a codec, specified by |send_codec|, as sending codec. - // This API can be called multiple of times to register Codec. The last codec - // registered overwrites the previous ones. - // The API can also be used to change payload type for CNG and RED, which are - // registered by default to default payload types. - // Note that registering CNG and RED won't overwrite speech codecs. - // This API can be called to set/change the send payload-type, frame-size - // or encoding rate (if applicable for the codec). - // - // Note: If a stereo codec is registered as send codec, VAD/DTX will - // automatically be turned off, since it is not supported for stereo sending. - // - // Note: If a secondary encoder is already registered, and the new send-codec - // has a sampling rate that does not match the secondary encoder, the - // secondary encoder will be unregistered. - // - // Input: - // -send_codec : Parameters of the codec to be registered, c.f. - // common_types.h for the definition of - // CodecInst. - // - // Return value: - // -1 if failed to initialize, - // 0 if succeeded. - // - virtual int32_t RegisterSendCodec(const CodecInst& send_codec) = 0; - - // Registers |external_speech_encoder| as encoder. The new encoder will - // replace any previously registered speech encoder (internal or external). - virtual void RegisterExternalSendCodec( - AudioEncoder* external_speech_encoder) = 0; - // |modifier| is called exactly once with one argument: a pointer to the // unique_ptr that holds the current encoder (which is null if there is no // current encoder). For the duration of the call, |modifier| has exclusive @@ -257,71 +223,6 @@ class AudioCodingModule { // virtual int32_t Add10MsData(const AudioFrame& audio_frame) = 0; - /////////////////////////////////////////////////////////////////////////// - // (RED) Redundant Coding - // - - /////////////////////////////////////////////////////////////////////////// - // int32_t SetREDStatus() - // configure RED status i.e. on/off. - // - // RFC 2198 describes a solution which has a single payload type which - // signifies a packet with redundancy. That packet then becomes a container, - // encapsulating multiple payloads into a single RTP packet. - // Such a scheme is flexible, since any amount of redundancy may be - // encapsulated within a single packet. There is, however, a small overhead - // since each encapsulated payload must be preceded by a header indicating - // the type of data enclosed. - // - // Input: - // -enable_red : if true RED is enabled, otherwise RED is - // disabled. - // - // Return value: - // -1 if failed to set RED status, - // 0 if succeeded. - // - virtual int32_t SetREDStatus(bool enable_red) = 0; - - /////////////////////////////////////////////////////////////////////////// - // bool REDStatus() - // Get RED status - // - // Return value: - // true if RED is enabled, - // false if RED is disabled. - // - virtual bool REDStatus() const = 0; - - /////////////////////////////////////////////////////////////////////////// - // (FEC) Forward Error Correction (codec internal) - // - - /////////////////////////////////////////////////////////////////////////// - // int32_t SetCodecFEC() - // Configures codec internal FEC status i.e. on/off. No effects on codecs that - // do not provide internal FEC. - // - // Input: - // -enable_fec : if true FEC will be enabled otherwise the FEC is - // disabled. - // - // Return value: - // -1 if failed, or the codec does not support FEC - // 0 if succeeded. - // - virtual int SetCodecFEC(bool enable_codec_fec) = 0; - - /////////////////////////////////////////////////////////////////////////// - // bool CodecFEC() - // Gets status of codec internal FEC. - // - // Return value: - // true if FEC is enabled, - // false if FEC is disabled. - // - virtual bool CodecFEC() const = 0; - /////////////////////////////////////////////////////////////////////////// // int SetPacketLossRate() // Sets expected packet loss rate for encoding. Some encoders provide packet @@ -343,55 +244,6 @@ class AudioCodingModule { // (VAD) Voice Activity Detection // - /////////////////////////////////////////////////////////////////////////// - // int32_t SetVAD() - // If DTX is enabled & the codec does not have internal DTX/VAD - // WebRtc VAD will be automatically enabled and |enable_vad| is ignored. - // - // If DTX is disabled but VAD is enabled no DTX packets are send, - // regardless of whether the codec has internal DTX/VAD or not. In this - // case, WebRtc VAD is running to label frames as active/in-active. - // - // NOTE! VAD/DTX is not supported when sending stereo. - // - // Inputs: - // -enable_dtx : if true DTX is enabled, - // otherwise DTX is disabled. - // -enable_vad : if true VAD is enabled, - // otherwise VAD is disabled. - // -vad_mode : determines the aggressiveness of VAD. A more - // aggressive mode results in more frames labeled - // as in-active, c.f. definition of - // ACMVADMode in audio_coding_module_typedefs.h - // for valid values. - // - // Return value: - // -1 if failed to set up VAD/DTX, - // 0 if succeeded. - // - virtual int32_t SetVAD(const bool enable_dtx = true, - const bool enable_vad = false, - const ACMVADMode vad_mode = VADNormal) = 0; - - /////////////////////////////////////////////////////////////////////////// - // int32_t VAD() - // Get VAD status. - // - // Outputs: - // -dtx_enabled : is set to true if DTX is enabled, otherwise - // is set to false. - // -vad_enabled : is set to true if VAD is enabled, otherwise - // is set to false. - // -vad_mode : is set to the current aggressiveness of VAD. - // - // Return value: - // -1 if fails to retrieve the setting of DTX/VAD, - // 0 if succeeded. - // - virtual int32_t VAD(bool* dtx_enabled, - bool* vad_enabled, - ACMVADMode* vad_mode) const = 0; - /////////////////////////////////////////////////////////////////////////// // int32_t RegisterVADCallback() // Call this method to register a callback function which is called @@ -455,29 +307,6 @@ class AudioCodingModule { virtual bool RegisterReceiveCodec(int rtp_payload_type, const SdpAudioFormat& audio_format) = 0; - /////////////////////////////////////////////////////////////////////////// - // int32_t RegisterReceiveCodec() - // Register possible decoders, can be called multiple times for - // codecs, CNG-NB, CNG-WB, CNG-SWB, AVT and RED. - // - // Input: - // -receive_codec : parameters of the codec to be registered, c.f. - // common_types.h for the definition of - // CodecInst. - // - // Return value: - // -1 if failed to register the codec - // 0 if the codec registered successfully. - // - virtual int RegisterReceiveCodec(const CodecInst& receive_codec) = 0; - - // Register a decoder; call repeatedly to register multiple decoders. |df| is - // a decoder factory that returns an iSAC decoder; it will be called once if - // the decoder being registered is iSAC. - virtual int RegisterReceiveCodec( - const CodecInst& receive_codec, - rtc::FunctionView()> isac_factory) = 0; - // Registers an external decoder. The name is only used to provide information // back to the caller about the decoder. Hence, the name is arbitrary, and may // be empty.