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}
This commit is contained in:
@ -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<void(std::unique_ptr<AudioEncoder>*)>
|
||||
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<std::unique_ptr<AudioDecoder>()> 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<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 @@ 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<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 @@ 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<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 @@ 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<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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<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,
|
||||
|
Reference in New Issue
Block a user