AudioCodingModule: Add methods for injecting external encoder stacks
BUG=webrtc:5028 Review URL: https://codereview.webrtc.org/1673213002 Cr-Commit-Position: refs/heads/master@{#12158}
This commit is contained in:
@ -302,9 +302,24 @@ void AudioCodingModuleImpl::RegisterExternalSendCodec(
|
|||||||
encoder_stack_ = encoder_factory_->rent_a_codec.RentEncoderStack(sp);
|
encoder_stack_ = encoder_factory_->rent_a_codec.RentEncoderStack(sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioCodingModuleImpl::ModifyEncoder(
|
||||||
|
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.
|
// Get current send codec.
|
||||||
rtc::Optional<CodecInst> AudioCodingModuleImpl::SendCodec() const {
|
rtc::Optional<CodecInst> AudioCodingModuleImpl::SendCodec() const {
|
||||||
rtc::CritScope lock(&acm_crit_sect_);
|
rtc::CritScope lock(&acm_crit_sect_);
|
||||||
|
if (encoder_factory_) {
|
||||||
auto* ci = encoder_factory_->codec_manager.GetCodecInst();
|
auto* ci = encoder_factory_->codec_manager.GetCodecInst();
|
||||||
if (ci) {
|
if (ci) {
|
||||||
return rtc::Optional<CodecInst>(*ci);
|
return rtc::Optional<CodecInst>(*ci);
|
||||||
@ -316,6 +331,12 @@ rtc::Optional<CodecInst> AudioCodingModuleImpl::SendCodec() const {
|
|||||||
return rtc::Optional<CodecInst>(CodecManager::ForgeCodecInst(enc.get()));
|
return rtc::Optional<CodecInst>(CodecManager::ForgeCodecInst(enc.get()));
|
||||||
}
|
}
|
||||||
return rtc::Optional<CodecInst>();
|
return rtc::Optional<CodecInst>();
|
||||||
|
} else {
|
||||||
|
return encoder_stack_
|
||||||
|
? rtc::Optional<CodecInst>(
|
||||||
|
CodecManager::ForgeCodecInst(encoder_stack_.get()))
|
||||||
|
: rtc::Optional<CodecInst>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get current send frequency.
|
// Get current send frequency.
|
||||||
@ -665,10 +686,23 @@ int AudioCodingModuleImpl::PlayoutFrequency() const {
|
|||||||
return receiver_.last_output_sample_rate_hz();
|
return receiver_.last_output_sample_rate_hz();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register possible receive codecs, can be called multiple times,
|
|
||||||
// for codecs, CNG (NB, WB and SWB), DTMF, RED.
|
|
||||||
int AudioCodingModuleImpl::RegisterReceiveCodec(const CodecInst& codec) {
|
int AudioCodingModuleImpl::RegisterReceiveCodec(const CodecInst& codec) {
|
||||||
rtc::CritScope lock(&acm_crit_sect_);
|
rtc::CritScope lock(&acm_crit_sect_);
|
||||||
|
auto* ef = encoder_factory_.get();
|
||||||
|
return RegisterReceiveCodecUnlocked(
|
||||||
|
codec, [ef] { return ef->rent_a_codec.RentIsacDecoder(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
int AudioCodingModuleImpl::RegisterReceiveCodec(
|
||||||
|
const CodecInst& codec,
|
||||||
|
FunctionView<std::unique_ptr<AudioDecoder>()> isac_factory) {
|
||||||
|
rtc::CritScope lock(&acm_crit_sect_);
|
||||||
|
return RegisterReceiveCodecUnlocked(codec, isac_factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
int AudioCodingModuleImpl::RegisterReceiveCodecUnlocked(
|
||||||
|
const CodecInst& codec,
|
||||||
|
FunctionView<std::unique_ptr<AudioDecoder>()> isac_factory) {
|
||||||
RTC_DCHECK(receiver_initialized_);
|
RTC_DCHECK(receiver_initialized_);
|
||||||
if (codec.channels > 2) {
|
if (codec.channels > 2) {
|
||||||
LOG_F(LS_ERROR) << "Unsupported number of channels: " << codec.channels;
|
LOG_F(LS_ERROR) << "Unsupported number of channels: " << codec.channels;
|
||||||
@ -691,14 +725,15 @@ int AudioCodingModuleImpl::RegisterReceiveCodec(const CodecInst& codec) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get |decoder| associated with |codec|. |decoder| is NULL if |codec| does
|
AudioDecoder* isac_decoder = nullptr;
|
||||||
// not own its decoder.
|
if (STR_CASE_CMP(codec.plname, "isac") == 0) {
|
||||||
return receiver_.AddCodec(
|
if (!isac_decoder_) {
|
||||||
*codec_index, codec.pltype, codec.channels, codec.plfreq,
|
isac_decoder_ = isac_factory();
|
||||||
STR_CASE_CMP(codec.plname, "isac") == 0
|
}
|
||||||
? encoder_factory_->rent_a_codec.RentIsacDecoder()
|
isac_decoder = isac_decoder_.get();
|
||||||
: nullptr,
|
}
|
||||||
codec.plname);
|
return receiver_.AddCodec(*codec_index, codec.pltype, codec.channels,
|
||||||
|
codec.plfreq, isac_decoder, codec.plname);
|
||||||
}
|
}
|
||||||
|
|
||||||
int AudioCodingModuleImpl::RegisterExternalReceiveCodec(
|
int AudioCodingModuleImpl::RegisterExternalReceiveCodec(
|
||||||
|
|||||||
@ -49,6 +49,9 @@ class AudioCodingModuleImpl final : public AudioCodingModule {
|
|||||||
void RegisterExternalSendCodec(
|
void RegisterExternalSendCodec(
|
||||||
AudioEncoder* external_speech_encoder) override;
|
AudioEncoder* external_speech_encoder) override;
|
||||||
|
|
||||||
|
void ModifyEncoder(
|
||||||
|
FunctionView<void(std::unique_ptr<AudioEncoder>*)> modifier) override;
|
||||||
|
|
||||||
// Get current send codec.
|
// Get current send codec.
|
||||||
rtc::Optional<CodecInst> SendCodec() const override;
|
rtc::Optional<CodecInst> SendCodec() const override;
|
||||||
|
|
||||||
@ -119,9 +122,10 @@ class AudioCodingModuleImpl final : public AudioCodingModule {
|
|||||||
// Get current playout frequency.
|
// Get current playout frequency.
|
||||||
int PlayoutFrequency() const override;
|
int PlayoutFrequency() const override;
|
||||||
|
|
||||||
// Register possible receive codecs, can be called multiple times,
|
|
||||||
// for codecs, CNG, DTMF, RED.
|
|
||||||
int RegisterReceiveCodec(const CodecInst& receive_codec) override;
|
int RegisterReceiveCodec(const CodecInst& receive_codec) override;
|
||||||
|
int RegisterReceiveCodec(
|
||||||
|
const CodecInst& receive_codec,
|
||||||
|
FunctionView<std::unique_ptr<AudioDecoder>()> isac_factory) override;
|
||||||
|
|
||||||
int RegisterExternalReceiveCodec(int rtp_payload_type,
|
int RegisterExternalReceiveCodec(int rtp_payload_type,
|
||||||
AudioDecoder* external_decoder,
|
AudioDecoder* external_decoder,
|
||||||
@ -213,6 +217,11 @@ class AudioCodingModuleImpl final : public AudioCodingModule {
|
|||||||
const std::string histogram_name_;
|
const std::string histogram_name_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int RegisterReceiveCodecUnlocked(
|
||||||
|
const CodecInst& codec,
|
||||||
|
FunctionView<std::unique_ptr<AudioDecoder>()> isac_factory)
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_);
|
||||||
|
|
||||||
int Add10MsDataInternal(const AudioFrame& audio_frame, InputData* input_data)
|
int Add10MsDataInternal(const AudioFrame& audio_frame, InputData* input_data)
|
||||||
EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_);
|
EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_);
|
||||||
int Encode(const InputData& input_data)
|
int Encode(const InputData& input_data)
|
||||||
@ -258,6 +267,8 @@ class AudioCodingModuleImpl final : public AudioCodingModule {
|
|||||||
// RegisterEncoder.
|
// RegisterEncoder.
|
||||||
std::unique_ptr<AudioEncoder> encoder_stack_ GUARDED_BY(acm_crit_sect_);
|
std::unique_ptr<AudioEncoder> encoder_stack_ GUARDED_BY(acm_crit_sect_);
|
||||||
|
|
||||||
|
std::unique_ptr<AudioDecoder> isac_decoder_ GUARDED_BY(acm_crit_sect_);
|
||||||
|
|
||||||
// This is to keep track of CN instances where we can send DTMFs.
|
// This is to keep track of CN instances where we can send DTMFs.
|
||||||
uint8_t previous_pltype_ GUARDED_BY(acm_crit_sect_);
|
uint8_t previous_pltype_ GUARDED_BY(acm_crit_sect_);
|
||||||
|
|
||||||
|
|||||||
@ -294,10 +294,8 @@ std::unique_ptr<AudioEncoder> RentACodec::RentEncoderStack(
|
|||||||
return encoder_stack;
|
return encoder_stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioDecoder* RentACodec::RentIsacDecoder() {
|
std::unique_ptr<AudioDecoder> RentACodec::RentIsacDecoder() {
|
||||||
if (!isac_decoder_)
|
return CreateIsacDecoder(&isac_bandwidth_info_);
|
||||||
isac_decoder_ = CreateIsacDecoder(&isac_bandwidth_info_);
|
|
||||||
return isac_decoder_.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace acm2
|
} // namespace acm2
|
||||||
|
|||||||
@ -222,16 +222,13 @@ class RentACodec {
|
|||||||
// will be stolen.
|
// will be stolen.
|
||||||
std::unique_ptr<AudioEncoder> RentEncoderStack(StackParameters* param);
|
std::unique_ptr<AudioEncoder> RentEncoderStack(StackParameters* param);
|
||||||
|
|
||||||
// Creates and returns an iSAC decoder, which will remain live until the
|
// Creates and returns an iSAC decoder.
|
||||||
// Rent-A-Codec is destroyed. Subsequent calls will simply return the same
|
std::unique_ptr<AudioDecoder> RentIsacDecoder();
|
||||||
// object.
|
|
||||||
AudioDecoder* RentIsacDecoder();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<AudioEncoder> speech_encoder_;
|
std::unique_ptr<AudioEncoder> speech_encoder_;
|
||||||
std::unique_ptr<AudioEncoder> cng_encoder_;
|
std::unique_ptr<AudioEncoder> cng_encoder_;
|
||||||
std::unique_ptr<AudioEncoder> red_encoder_;
|
std::unique_ptr<AudioEncoder> red_encoder_;
|
||||||
std::unique_ptr<AudioDecoder> isac_decoder_;
|
|
||||||
LockedIsacBandwidthInfo isac_bandwidth_info_;
|
LockedIsacBandwidthInfo isac_bandwidth_info_;
|
||||||
|
|
||||||
RTC_DISALLOW_COPY_AND_ASSIGN(RentACodec);
|
RTC_DISALLOW_COPY_AND_ASSIGN(RentACodec);
|
||||||
|
|||||||
@ -207,6 +207,52 @@ class AudioCodingModule {
|
|||||||
virtual void RegisterExternalSendCodec(
|
virtual void RegisterExternalSendCodec(
|
||||||
AudioEncoder* external_speech_encoder) = 0;
|
AudioEncoder* external_speech_encoder) = 0;
|
||||||
|
|
||||||
|
// Just like std::function, FunctionView will wrap any callable and hide its
|
||||||
|
// actual type, exposing only its signature. But unlike std::function,
|
||||||
|
// FunctionView doesn't own its callable---it just points to it. Thus, it's a
|
||||||
|
// good choice mainly as a function argument when the callable argument will
|
||||||
|
// not be called again once the function has returned.
|
||||||
|
template <typename T>
|
||||||
|
class FunctionView; // Undefined.
|
||||||
|
|
||||||
|
template <typename RetT, typename... ArgT>
|
||||||
|
class FunctionView<RetT(ArgT...)> final {
|
||||||
|
public:
|
||||||
|
// This constructor is implicit, so that callers won't have to convert
|
||||||
|
// lambdas to FunctionView<Blah(Blah, Blah)> explicitly. This is safe
|
||||||
|
// because FunctionView is only a reference to the real callable.
|
||||||
|
template <typename F>
|
||||||
|
FunctionView(F&& f)
|
||||||
|
: f_(&f), call_(Call<typename std::remove_reference<F>::type>) {}
|
||||||
|
|
||||||
|
RetT operator()(ArgT... args) const {
|
||||||
|
return call_(f_, std::forward<ArgT>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename F>
|
||||||
|
static RetT Call(void* f, ArgT... args) {
|
||||||
|
return (*static_cast<F*>(f))(std::forward<ArgT>(args)...);
|
||||||
|
}
|
||||||
|
void* f_;
|
||||||
|
RetT (*call_)(void* f, ArgT... args);
|
||||||
|
};
|
||||||
|
|
||||||
|
// |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
|
||||||
|
// access to the unique_ptr; it may call the encoder, steal the encoder and
|
||||||
|
// replace it with another encoder or with nullptr, etc.
|
||||||
|
virtual void ModifyEncoder(
|
||||||
|
FunctionView<void(std::unique_ptr<AudioEncoder>*)> modifier) = 0;
|
||||||
|
|
||||||
|
// Utility method for simply replacing the existing encoder with a new one.
|
||||||
|
void SetEncoder(std::unique_ptr<AudioEncoder> new_encoder) {
|
||||||
|
ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
|
||||||
|
*encoder = std::move(new_encoder);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// int32_t SendCodec()
|
// int32_t SendCodec()
|
||||||
// Get parameters for the codec currently registered as send codec.
|
// Get parameters for the codec currently registered as send codec.
|
||||||
@ -472,6 +518,13 @@ class AudioCodingModule {
|
|||||||
//
|
//
|
||||||
virtual int RegisterReceiveCodec(const CodecInst& receive_codec) = 0;
|
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,
|
||||||
|
FunctionView<std::unique_ptr<AudioDecoder>()> isac_factory) = 0;
|
||||||
|
|
||||||
// Registers an external decoder. The name is only used to provide information
|
// 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
|
// back to the caller about the decoder. Hence, the name is arbitrary, and may
|
||||||
// be empty.
|
// be empty.
|
||||||
|
|||||||
Reference in New Issue
Block a user