blob: 43f684ec7f55fd0e86bfca097a43afa13fea4a50 [file] [log] [blame]
/*
* 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 "webrtc/modules/audio_coding/main/acm2/codec_owner.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
#include "webrtc/engine_configurations.h"
#include "webrtc/modules/audio_coding/codecs/cng/include/audio_encoder_cng.h"
#ifdef WEBRTC_CODEC_RED
#include "webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h"
#endif
namespace webrtc {
namespace acm2 {
CodecOwner::CodecOwner() : speech_encoder_(nullptr) {
}
CodecOwner::~CodecOwner() = default;
namespace {
AudioEncoder* CreateRedEncoder(int red_payload_type,
AudioEncoder* encoder,
rtc::scoped_ptr<AudioEncoder>* red_encoder) {
#ifdef WEBRTC_CODEC_RED
if (red_payload_type != -1) {
AudioEncoderCopyRed::Config config;
config.payload_type = red_payload_type;
config.speech_encoder = encoder;
red_encoder->reset(new AudioEncoderCopyRed(config));
return red_encoder->get();
}
#endif
red_encoder->reset();
return encoder;
}
void CreateCngEncoder(int cng_payload_type,
ACMVADMode vad_mode,
AudioEncoder* encoder,
rtc::scoped_ptr<AudioEncoder>* cng_encoder) {
if (cng_payload_type == -1) {
cng_encoder->reset();
return;
}
AudioEncoderCng::Config config;
config.num_channels = encoder->NumChannels();
config.payload_type = cng_payload_type;
config.speech_encoder = 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();
}
cng_encoder->reset(new AudioEncoderCng(config));
}
} // namespace
bool CodecOwner::SetEncoders(const CodecInst& speech_inst,
int cng_payload_type,
ACMVADMode vad_mode,
int red_payload_type) {
AudioEncoder* speech_encoder = rent_a_codec_.RentEncoder(speech_inst);
if (!speech_encoder)
return false;
SetEncoders(speech_encoder, cng_payload_type, vad_mode, red_payload_type);
return true;
}
void CodecOwner::SetEncoders(AudioEncoder* external_speech_encoder,
int cng_payload_type,
ACMVADMode vad_mode,
int red_payload_type) {
speech_encoder_ = external_speech_encoder;
ChangeCngAndRed(cng_payload_type, vad_mode, red_payload_type);
}
void CodecOwner::ChangeCngAndRed(int cng_payload_type,
ACMVADMode vad_mode,
int red_payload_type) {
RTC_DCHECK(speech_encoder_);
if (cng_payload_type != -1 || red_payload_type != -1) {
// The RED and CNG encoders need to be in sync with the speech encoder, so
// reset the latter to ensure its buffer is empty.
speech_encoder_->Reset();
}
AudioEncoder* encoder = CreateRedEncoder(
red_payload_type, speech_encoder_, &red_encoder_);
CreateCngEncoder(cng_payload_type, vad_mode, encoder, &cng_encoder_);
}
AudioDecoder* CodecOwner::GetIsacDecoder() {
return rent_a_codec_.RentIsacDecoder();
}
AudioEncoder* CodecOwner::Encoder() {
const auto& const_this = *this;
return const_cast<AudioEncoder*>(const_this.Encoder());
}
const AudioEncoder* CodecOwner::Encoder() const {
if (cng_encoder_)
return cng_encoder_.get();
if (red_encoder_)
return red_encoder_.get();
return speech_encoder_;
}
} // namespace acm2
} // namespace webrtc