Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Unified Diff: webrtc/modules/audio_coding/acm2/audio_coding_module_impl.cc

Issue 1702943002: Pass ownership of external encoders to the ACM (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/modules/audio_coding/acm2/audio_coding_module_impl.cc
diff --git a/webrtc/modules/audio_coding/acm2/audio_coding_module_impl.cc b/webrtc/modules/audio_coding/acm2/audio_coding_module_impl.cc
index ff779a28b182afaa4831c75c6ac29e110b168420..59a604937d62adf9da23a9bd26c291a875e76959 100644
--- a/webrtc/modules/audio_coding/acm2/audio_coding_module_impl.cc
+++ b/webrtc/modules/audio_coding/acm2/audio_coding_module_impl.cc
@@ -31,6 +31,12 @@ namespace webrtc {
namespace acm2 {
+struct EncoderFactory {
+ AudioEncoder* external_speech_encoder = nullptr;
+ CodecManager codec_manager;
+ RentACodec rent_a_codec;
+};
+
namespace {
// TODO(turajs): the same functionality is used in NetEq. If both classes
@@ -90,6 +96,79 @@ void ConvertEncodedInfoToFragmentationHeader(
frag->fragmentationPlType[i] = info.redundant[i].payload_type;
}
}
+
+// Wraps a raw AudioEncoder pointer. The idea is that you can put one of these
+// in a unique_ptr, to protect the contained raw pointer from being deleted
+// when the unique_ptr expires. (This is of course a bad idea in general, but
+// backwards compatibility.)
+class RawAudioEncoderWrapper final : public AudioEncoder {
+ public:
+ RawAudioEncoderWrapper(AudioEncoder* enc) : enc_(enc) {}
+ size_t MaxEncodedBytes() const override { return enc_->MaxEncodedBytes(); }
+ int SampleRateHz() const override { return enc_->SampleRateHz(); }
+ size_t NumChannels() const override { return enc_->NumChannels(); }
+ int RtpTimestampRateHz() const override { return enc_->RtpTimestampRateHz(); }
+ size_t Num10MsFramesInNextPacket() const override {
+ return enc_->Num10MsFramesInNextPacket();
+ }
+ size_t Max10MsFramesInAPacket() const override {
+ return enc_->Max10MsFramesInAPacket();
+ }
+ int GetTargetBitrate() const override { return enc_->GetTargetBitrate(); }
+ EncodedInfo EncodeImpl(uint32_t rtp_timestamp,
+ rtc::ArrayView<const int16_t> audio,
+ rtc::Buffer* encoded) override {
+ return enc_->Encode(rtp_timestamp, audio, encoded);
+ }
+ EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
+ rtc::ArrayView<const int16_t> audio,
+ size_t max_encoded_bytes,
+ uint8_t* encoded) override {
+ return enc_->EncodeInternal(rtp_timestamp, audio, max_encoded_bytes,
+ encoded);
+ }
+ void Reset() override { return enc_->Reset(); }
+ bool SetFec(bool enable) override { return enc_->SetFec(enable); }
+ bool SetDtx(bool enable) override { return enc_->SetDtx(enable); }
+ bool SetApplication(Application application) override {
+ return enc_->SetApplication(application);
+ }
+ void SetMaxPlaybackRate(int frequency_hz) override {
+ return enc_->SetMaxPlaybackRate(frequency_hz);
+ }
+ void SetProjectedPacketLossRate(double fraction) override {
+ return enc_->SetProjectedPacketLossRate(fraction);
+ }
+ void SetTargetBitrate(int target_bps) override {
+ return enc_->SetTargetBitrate(target_bps);
+ }
+
+ private:
+ 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;
+}
+
} // namespace
void AudioCodingModuleImpl::ChangeLogger::MaybeLog(int value) {
@@ -200,15 +279,13 @@ int AudioCodingModuleImpl::RegisterSendCodec(const CodecInst& send_codec) {
if (!encoder_factory_->codec_manager.RegisterEncoder(send_codec)) {
return -1;
}
- auto* sp = encoder_factory_->codec_manager.GetStackParams();
- if (!sp->speech_encoder && encoder_factory_->codec_manager.GetCodecInst()) {
- // We have no speech encoder, but we have a specification for making one.
- AudioEncoder* enc = encoder_factory_->rent_a_codec.RentEncoder(
- *encoder_factory_->codec_manager.GetCodecInst());
- if (!enc)
- return -1;
- sp->speech_encoder = enc;
+ 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;
@@ -217,8 +294,11 @@ int AudioCodingModuleImpl::RegisterSendCodec(const CodecInst& send_codec) {
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();
- sp->speech_encoder = external_speech_encoder;
+ RTC_CHECK(sp->speech_encoder);
encoder_stack_ = encoder_factory_->rent_a_codec.RentEncoderStack(sp);
}
@@ -229,9 +309,11 @@ rtc::Optional<CodecInst> AudioCodingModuleImpl::SendCodec() const {
if (ci) {
return rtc::Optional<CodecInst>(*ci);
}
- auto* enc = encoder_factory_->codec_manager.GetStackParams()->speech_encoder;
+ CreateSpeechEncoderIfNecessary(encoder_factory_.get());
+ const std::unique_ptr<AudioEncoder>& enc =
+ encoder_factory_->codec_manager.GetStackParams()->speech_encoder;
if (enc) {
- return rtc::Optional<CodecInst>(CodecManager::ForgeCodecInst(enc));
+ return rtc::Optional<CodecInst>(CodecManager::ForgeCodecInst(enc.get()));
}
return rtc::Optional<CodecInst>();
}
@@ -451,6 +533,7 @@ bool AudioCodingModuleImpl::REDStatus() const {
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;
}
@@ -476,6 +559,7 @@ bool AudioCodingModuleImpl::CodecFEC() const {
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;
}
@@ -507,6 +591,7 @@ int AudioCodingModuleImpl::SetVAD(bool enable_dtx,
// 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;
}

Powered by Google App Engine
This is Rietveld 408576698