AudioCodingModule: Remove support for creating encoders
After this CL, all audio encoders have to be injected by the caller.
This means that there is no special "built-in" set of codecs, and
users won't have to pay the binary size and security costs of codecs
they aren't using.
Bug: webrtc:8396
Change-Id: Idb0959ce395940c8bb3bbb49256cdcd84fc87bb6
Reviewed-on: https://webrtc-review.googlesource.com/c/103821
Commit-Queue: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Ivo Creusen <ivoc@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25600}
diff --git a/modules/audio_coding/BUILD.gn b/modules/audio_coding/BUILD.gn
index ec81697..b836646 100644
--- a/modules/audio_coding/BUILD.gn
+++ b/modules/audio_coding/BUILD.gn
@@ -14,31 +14,6 @@
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 @@
# 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 @@
"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_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 @@
"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_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 @@
":audio_format_conversion",
":pcm16b_c",
":red",
+ ":webrtc_opus_c",
"..:module_api",
"../..:webrtc_common",
"../../api/audio:audio_frame_api",
@@ -2007,8 +1995,6 @@
"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 334c0e0..c0aab3a 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 {
-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 @@
// 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<void(std::unique_ptr<AudioEncoder>*)>
modifier) override;
@@ -74,25 +61,9 @@
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 @@
// (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 @@
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<std::unique_ptr<AudioDecoder>()> isac_factory) override;
-
int RegisterExternalReceiveCodec(int rtp_payload_type,
AudioDecoder* external_decoder,
int sample_rate_hz,
@@ -222,11 +180,6 @@
const std::string histogram_name_;
};
- int RegisterReceiveCodecUnlocked(
- const CodecInst& codec,
- rtc::FunctionView<std::unique_ptr<AudioDecoder>()> 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 @@
acm2::AcmReceiver receiver_; // AcmReceiver has it's own internal lock.
ChangeLogger bitrate_logger_ RTC_GUARDED_BY(acm_crit_sect_);
- std::unique_ptr<EncoderFactory> 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<AudioEncoder> encoder_stack_ RTC_GUARDED_BY(acm_crit_sect_);
std::unique_ptr<AudioDecoder> isac_decoder_16k_
@@ -405,28 +353,6 @@
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<AudioEncoder> 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<AudioEncoder>(
- 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 @@
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 @@
// 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<void(std::unique_ptr<AudioEncoder>*)> 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<CodecInst> 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<AudioEncoder>& 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<int>(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<CodecInst>(
- acm2::CodecManager::ForgeCodecInst(encoder_stack_.get()))
- : absl::nullopt;
+ return absl::nullopt;
}
}
@@ -809,58 +694,9 @@
}
/////////////////////////////////////////
-// (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")) {
@@ -870,36 +706,6 @@
}
/////////////////////////////////////////
-// (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 @@
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<std::unique_ptr<AudioDecoder>()> isac_factory) {
- rtc::CritScope lock(&acm_crit_sect_);
- return RegisterReceiveCodecUnlocked(codec, isac_factory);
-}
-
-int AudioCodingModuleImpl::RegisterReceiveCodecUnlocked(
- const CodecInst& codec,
- rtc::FunctionView<std::unique_ptr<AudioDecoder>()> 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<int>(*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<AudioDecoder>& 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 eda6555..0000000
--- 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 <string.h>
-#include <map>
-#include <memory>
-#include <utility>
-
-#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<int>(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<AudioEncoder>* encoder) {
- if (!*encoder) {
- // There is no existing encoder.
- recreate_encoder_ = true;
- return;
- }
-
- // Extract the speech encoder from the ACM.
- std::unique_ptr<AudioEncoder> 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 22dbf4e..0000000
--- 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<CodecInst> 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 6a5ea5f..0000000
--- 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 <memory>
-
-#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<MockAudioEncoder> CreateMockEncoder() {
- auto enc = std::unique_ptr<MockAudioEncoder>(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 7601519..d7457b8 100644
--- a/modules/audio_coding/acm2/rent_a_codec.cc
+++ b/modules/audio_coding/acm2/rent_a_codec.cc
@@ -13,35 +13,9 @@
#include <memory>
#include <utility>
-#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 @@
: ned;
}
-RentACodec::RegistrationResult RentACodec::RegisterCngPayloadType(
- std::map<int, int>* 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<int, int>* 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<AudioEncoder> CreateEncoder(
- const CodecInst& speech_inst,
- const rtc::scoped_refptr<LockedIsacBandwidthInfo>& bwinfo) {
-#if defined(WEBRTC_CODEC_ISACFX)
- if (absl::EqualsIgnoreCase(speech_inst.plname, "isac"))
- return std::unique_ptr<AudioEncoder>(
- new AudioEncoderIsacFixImpl(speech_inst, bwinfo));
-#endif
-#if defined(WEBRTC_CODEC_ISAC)
- if (absl::EqualsIgnoreCase(speech_inst.plname, "isac"))
- return std::unique_ptr<AudioEncoder>(
- new AudioEncoderIsacFloatImpl(speech_inst, bwinfo));
-#endif
-#ifdef WEBRTC_CODEC_OPUS
- if (absl::EqualsIgnoreCase(speech_inst.plname, "opus"))
- return std::unique_ptr<AudioEncoder>(new AudioEncoderOpusImpl(speech_inst));
-#endif
- if (absl::EqualsIgnoreCase(speech_inst.plname, "pcmu"))
- return std::unique_ptr<AudioEncoder>(new AudioEncoderPcmU(speech_inst));
- if (absl::EqualsIgnoreCase(speech_inst.plname, "pcma"))
- return std::unique_ptr<AudioEncoder>(new AudioEncoderPcmA(speech_inst));
- if (absl::EqualsIgnoreCase(speech_inst.plname, "l16"))
- return std::unique_ptr<AudioEncoder>(new AudioEncoderPcm16B(speech_inst));
-#ifdef WEBRTC_CODEC_ILBC
- if (absl::EqualsIgnoreCase(speech_inst.plname, "ilbc"))
- return std::unique_ptr<AudioEncoder>(new AudioEncoderIlbcImpl(speech_inst));
-#endif
- if (absl::EqualsIgnoreCase(speech_inst.plname, "g722"))
- return std::unique_ptr<AudioEncoder>(new AudioEncoderG722Impl(speech_inst));
- RTC_LOG_F(LS_ERROR) << "Could not create encoder of type "
- << speech_inst.plname;
- return std::unique_ptr<AudioEncoder>();
-}
-
-std::unique_ptr<AudioEncoder> CreateRedEncoder(
- std::unique_ptr<AudioEncoder> 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<AudioEncoder>(
- new AudioEncoderCopyRed(std::move(config)));
-#else
- return std::unique_ptr<AudioEncoder>();
-#endif
-}
-
-std::unique_ptr<AudioEncoder> CreateCngEncoder(
- std::unique_ptr<AudioEncoder> 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<AudioDecoder> CreateIsacDecoder(
- int sample_rate_hz,
- const rtc::scoped_refptr<LockedIsacBandwidthInfo>& bwinfo) {
-#if defined(WEBRTC_CODEC_ISACFX)
- return std::unique_ptr<AudioDecoder>(
- new AudioDecoderIsacFixImpl(sample_rate_hz, bwinfo));
-#elif defined(WEBRTC_CODEC_ISAC)
- return std::unique_ptr<AudioDecoder>(
- new AudioDecoderIsacFloatImpl(sample_rate_hz, bwinfo));
-#else
- FATAL() << "iSAC is not supported.";
- return std::unique_ptr<AudioDecoder>();
-#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<AudioEncoder> 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<AudioEncoder> 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<int, int>& m) {
- auto it = m.find(param->speech_encoder->SampleRateHz());
- return it == m.end() ? absl::nullopt : absl::optional<int>(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<AudioEncoder> 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<AudioDecoder> 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 b0ad382..afac3b1 100644
--- a/modules/audio_coding/acm2/rent_a_codec.h
+++ b/modules/audio_coding/acm2/rent_a_codec.h
@@ -31,8 +31,7 @@
namespace acm2 {
-class RentACodec {
- public:
+struct RentACodec {
enum class CodecId {
#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
kISAC,
@@ -141,56 +140,6 @@
static absl::optional<NetEqDecoder> 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<int, int>* pt_map,
- const CodecInst& codec_inst);
- static RegistrationResult RegisterRedPayloadType(std::map<int, int>* 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<AudioEncoder> RentEncoder(const CodecInst& codec_inst);
-
- struct StackParameters {
- StackParameters();
- ~StackParameters();
-
- std::unique_ptr<AudioEncoder> 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<int, int> cng_payload_types;
- std::map<int, int> 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<AudioEncoder> RentEncoderStack(StackParameters* param);
-
- // Creates and returns an iSAC decoder.
- std::unique_ptr<AudioDecoder> RentIsacDecoder(int sample_rate_hz);
-
- private:
- std::unique_ptr<AudioEncoder> speech_encoder_;
- std::unique_ptr<AudioEncoder> cng_encoder_;
- std::unique_ptr<AudioEncoder> red_encoder_;
- rtc::scoped_refptr<LockedIsacBandwidthInfo> 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 fd3329c..0000000
--- 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 <memory>
-
-#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<bool>(expected_send_even_if_empty),
- encoded_info.send_even_if_empty);
- }
-
- RentACodec rent_a_codec_;
- std::unique_ptr<AudioEncoder> 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<AudioEncoder>(external_encoder);
- std::unique_ptr<AudioEncoder> 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<const int16_t>(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<AudioEncoder> 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<MockAudioEncoder>(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 b9f2228..f9fdba5 100644
--- a/modules/audio_coding/include/audio_coding_module.h
+++ b/modules/audio_coding/include/audio_coding_module.h
@@ -154,40 +154,6 @@
// 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
@@ -258,71 +224,6 @@
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
// loss gnostic encoding to make stream less sensitive to packet losses,
@@ -344,55 +245,6 @@
//
///////////////////////////////////////////////////////////////////////////
- // 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
// any time that ACM encounters an empty frame. That is a frame which is
@@ -455,29 +307,6 @@
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<std::unique_ptr<AudioDecoder>()> 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.