
With this change, the currently used encoder is held in a scoped_ptr. iSAC is a special case, since the encoder instance is also a decoder instance, so it may have to be available also if another send codec is used. This is accomplished by having a separate scoped_ptr for iSAC. Remove mirror ID from ACM codec database functions, and remove unused functions from the database. COAUTHOR=kwiberg@webrtc.org BUG=4228 R=tina.legrand@webrtc.org Review URL: https://webrtc-codereview.appspot.com/48729004 Cr-Commit-Position: refs/heads/master@{#8982}
567 lines
19 KiB
C++
567 lines
19 KiB
C++
/*
|
|
* 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_manager.h"
|
|
|
|
#include "webrtc/base/checks.h"
|
|
#include "webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h"
|
|
|
|
namespace webrtc {
|
|
namespace acm2 {
|
|
|
|
namespace {
|
|
bool IsCodecRED(const CodecInst* codec) {
|
|
return (STR_CASE_CMP(codec->plname, "RED") == 0);
|
|
}
|
|
|
|
bool IsCodecRED(int index) {
|
|
return (IsCodecRED(&ACMCodecDB::database_[index]));
|
|
}
|
|
|
|
bool IsCodecCN(const CodecInst* codec) {
|
|
return (STR_CASE_CMP(codec->plname, "CN") == 0);
|
|
}
|
|
|
|
bool IsCodecCN(int index) {
|
|
return (IsCodecCN(&ACMCodecDB::database_[index]));
|
|
}
|
|
|
|
// Check if the given codec is a valid to be registered as send codec.
|
|
int IsValidSendCodec(const CodecInst& send_codec, bool is_primary_encoder) {
|
|
int dummy_id = 0;
|
|
if ((send_codec.channels != 1) && (send_codec.channels != 2)) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
|
|
"Wrong number of channels (%d, only mono and stereo are "
|
|
"supported) for %s encoder",
|
|
send_codec.channels,
|
|
is_primary_encoder ? "primary" : "secondary");
|
|
return -1;
|
|
}
|
|
|
|
int codec_id = ACMCodecDB::CodecNumber(send_codec);
|
|
if (codec_id < 0) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
|
|
"Invalid codec setting for the send codec.");
|
|
return -1;
|
|
}
|
|
|
|
// TODO(tlegrand): Remove this check. Already taken care of in
|
|
// ACMCodecDB::CodecNumber().
|
|
// Check if the payload-type is valid
|
|
if (!ACMCodecDB::ValidPayloadType(send_codec.pltype)) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
|
|
"Invalid payload-type %d for %s.", send_codec.pltype,
|
|
send_codec.plname);
|
|
return -1;
|
|
}
|
|
|
|
// Telephone-event cannot be a send codec.
|
|
if (!STR_CASE_CMP(send_codec.plname, "telephone-event")) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
|
|
"telephone-event cannot be a send codec");
|
|
return -1;
|
|
}
|
|
|
|
if (ACMCodecDB::codec_settings_[codec_id].channel_support <
|
|
send_codec.channels) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
|
|
"%d number of channels not supportedn for %s.",
|
|
send_codec.channels, send_codec.plname);
|
|
return -1;
|
|
}
|
|
|
|
if (!is_primary_encoder) {
|
|
// If registering the secondary encoder, then RED and CN are not valid
|
|
// choices as encoder.
|
|
if (IsCodecRED(&send_codec)) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
|
|
"RED cannot be secondary codec");
|
|
return -1;
|
|
}
|
|
|
|
if (IsCodecCN(&send_codec)) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
|
|
"DTX cannot be secondary codec");
|
|
return -1;
|
|
}
|
|
}
|
|
return codec_id;
|
|
}
|
|
|
|
bool IsIsac(const CodecInst& codec) {
|
|
return !STR_CASE_CMP(codec.plname, "isac");
|
|
}
|
|
|
|
const CodecInst kEmptyCodecInst = {-1, "noCodecRegistered", 0, 0, 0, 0};
|
|
} // namespace
|
|
|
|
CodecManager::CodecManager(AudioCodingModuleImpl* acm)
|
|
: acm_(acm),
|
|
cng_nb_pltype_(255),
|
|
cng_wb_pltype_(255),
|
|
cng_swb_pltype_(255),
|
|
cng_fb_pltype_(255),
|
|
red_nb_pltype_(255),
|
|
stereo_send_(false),
|
|
vad_enabled_(false),
|
|
dtx_enabled_(false),
|
|
vad_mode_(VADNormal),
|
|
current_encoder_(nullptr),
|
|
send_codec_inst_(kEmptyCodecInst),
|
|
red_enabled_(false),
|
|
codec_fec_enabled_(false) {
|
|
// Register the default payload type for RED and for CNG at sampling rates of
|
|
// 8, 16, 32 and 48 kHz.
|
|
for (int i = (ACMCodecDB::kNumCodecs - 1); i >= 0; i--) {
|
|
if (IsCodecRED(i) && ACMCodecDB::database_[i].plfreq == 8000) {
|
|
red_nb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
|
|
} else if (IsCodecCN(i)) {
|
|
if (ACMCodecDB::database_[i].plfreq == 8000) {
|
|
cng_nb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
|
|
} else if (ACMCodecDB::database_[i].plfreq == 16000) {
|
|
cng_wb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
|
|
} else if (ACMCodecDB::database_[i].plfreq == 32000) {
|
|
cng_swb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
|
|
} else if (ACMCodecDB::database_[i].plfreq == 48000) {
|
|
cng_fb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
|
|
}
|
|
}
|
|
}
|
|
thread_checker_.DetachFromThread();
|
|
}
|
|
|
|
CodecManager::~CodecManager() = default;
|
|
|
|
int CodecManager::RegisterSendCodec(const CodecInst& send_codec) {
|
|
DCHECK(thread_checker_.CalledOnValidThread());
|
|
int codec_id = IsValidSendCodec(send_codec, true);
|
|
|
|
// Check for reported errors from function IsValidSendCodec().
|
|
if (codec_id < 0) {
|
|
return -1;
|
|
}
|
|
|
|
int dummy_id = 0;
|
|
// RED can be registered with other payload type. If not registered a default
|
|
// payload type is used.
|
|
if (IsCodecRED(&send_codec)) {
|
|
// TODO(tlegrand): Remove this check. Already taken care of in
|
|
// ACMCodecDB::CodecNumber().
|
|
// Check if the payload-type is valid
|
|
if (!ACMCodecDB::ValidPayloadType(send_codec.pltype)) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
|
|
"Invalid payload-type %d for %s.", send_codec.pltype,
|
|
send_codec.plname);
|
|
return -1;
|
|
}
|
|
// Set RED payload type.
|
|
if (send_codec.plfreq == 8000) {
|
|
red_nb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
|
|
} else {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
|
|
"RegisterSendCodec() failed, invalid frequency for RED "
|
|
"registration");
|
|
return -1;
|
|
}
|
|
SetRedPayloadType(send_codec.plfreq, send_codec.pltype);
|
|
return 0;
|
|
}
|
|
|
|
// CNG can be registered with other payload type. If not registered the
|
|
// default payload types from codec database will be used.
|
|
if (IsCodecCN(&send_codec)) {
|
|
// CNG is registered.
|
|
switch (send_codec.plfreq) {
|
|
case 8000: {
|
|
cng_nb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
|
|
break;
|
|
}
|
|
case 16000: {
|
|
cng_wb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
|
|
break;
|
|
}
|
|
case 32000: {
|
|
cng_swb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
|
|
break;
|
|
}
|
|
case 48000: {
|
|
cng_fb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
|
|
break;
|
|
}
|
|
default: {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
|
|
"RegisterSendCodec() failed, invalid frequency for CNG "
|
|
"registration");
|
|
return -1;
|
|
}
|
|
}
|
|
SetCngPayloadType(send_codec.plfreq, send_codec.pltype);
|
|
return 0;
|
|
}
|
|
|
|
// Set Stereo, and make sure VAD and DTX is turned off.
|
|
if (send_codec.channels == 2) {
|
|
stereo_send_ = true;
|
|
if (vad_enabled_ || dtx_enabled_) {
|
|
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, dummy_id,
|
|
"VAD/DTX is turned off, not supported when sending stereo.");
|
|
}
|
|
vad_enabled_ = false;
|
|
dtx_enabled_ = false;
|
|
} else {
|
|
stereo_send_ = false;
|
|
}
|
|
|
|
// Check if the codec is already registered as send codec.
|
|
bool is_send_codec;
|
|
if (current_encoder_) {
|
|
int send_codec_id = ACMCodecDB::CodecNumber(send_codec_inst_);
|
|
assert(send_codec_id >= 0);
|
|
is_send_codec = send_codec_id == codec_id;
|
|
} else {
|
|
is_send_codec = false;
|
|
}
|
|
|
|
// If new codec, or new settings, register.
|
|
if (!is_send_codec) {
|
|
ACMGenericCodec* new_codec;
|
|
if (!IsIsac(send_codec)) {
|
|
encoder_.reset(ACMCodecDB::CreateCodecInstance(
|
|
send_codec, cng_nb_pltype_, cng_wb_pltype_, cng_swb_pltype_,
|
|
cng_fb_pltype_, red_enabled_, red_nb_pltype_));
|
|
new_codec = encoder_.get();
|
|
} else {
|
|
if (!isac_enc_dec_) {
|
|
isac_enc_dec_.reset(ACMCodecDB::CreateCodecInstance(
|
|
send_codec, cng_nb_pltype_, cng_wb_pltype_, cng_swb_pltype_,
|
|
cng_fb_pltype_, red_enabled_, red_nb_pltype_));
|
|
}
|
|
new_codec = isac_enc_dec_.get();
|
|
}
|
|
DCHECK(new_codec);
|
|
|
|
WebRtcACMCodecParams codec_params;
|
|
|
|
memcpy(&(codec_params.codec_inst), &send_codec, sizeof(CodecInst));
|
|
codec_params.enable_vad = vad_enabled_;
|
|
codec_params.enable_dtx = dtx_enabled_;
|
|
codec_params.vad_mode = vad_mode_;
|
|
// Force initialization.
|
|
if (new_codec->InitEncoder(&codec_params, true) < 0) {
|
|
// Could not initialize the encoder.
|
|
|
|
// Check if already have a registered codec.
|
|
// Depending on that different messages are logged.
|
|
if (!current_encoder_) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
|
|
"Cannot Initialize the encoder No Encoder is registered");
|
|
} else {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
|
|
"Cannot Initialize the encoder, continue encoding with "
|
|
"the previously registered codec");
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
// Update states.
|
|
dtx_enabled_ = codec_params.enable_dtx;
|
|
vad_enabled_ = codec_params.enable_vad;
|
|
vad_mode_ = codec_params.vad_mode;
|
|
|
|
// Everything is fine so we can replace the previous codec with this one.
|
|
if (current_encoder_) {
|
|
// If we change codec we start fresh with RED.
|
|
// This is not strictly required by the standard.
|
|
|
|
if (new_codec->SetCopyRed(red_enabled_) < 0) {
|
|
// We tried to preserve the old red status, if failed, it means the
|
|
// red status has to be flipped.
|
|
red_enabled_ = !red_enabled_;
|
|
}
|
|
|
|
new_codec->SetVAD(&dtx_enabled_, &vad_enabled_, &vad_mode_);
|
|
|
|
if (!new_codec->HasInternalFEC()) {
|
|
codec_fec_enabled_ = false;
|
|
} else {
|
|
if (new_codec->SetFEC(codec_fec_enabled_) < 0) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
|
|
"Cannot set codec FEC");
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
current_encoder_ = new_codec;
|
|
DCHECK(current_encoder_);
|
|
memcpy(&send_codec_inst_, &send_codec, sizeof(CodecInst));
|
|
return 0;
|
|
} else {
|
|
// If codec is the same as already registered check if any parameters
|
|
// has changed compared to the current values.
|
|
// If any parameter is valid then apply it and record.
|
|
bool force_init = false;
|
|
|
|
// Check the payload type.
|
|
if (send_codec.pltype != send_codec_inst_.pltype) {
|
|
// At this point check if the given payload type is valid.
|
|
// Record it later when the sampling frequency is changed
|
|
// successfully.
|
|
if (!ACMCodecDB::ValidPayloadType(send_codec.pltype)) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
|
|
"Out of range payload type");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
// If there is a codec that ONE instance of codec supports multiple
|
|
// sampling frequencies, then we need to take care of it here.
|
|
// one such a codec is iSAC. Both WB and SWB are encoded and decoded
|
|
// with one iSAC instance. Therefore, we need to update the encoder
|
|
// frequency if required.
|
|
if (send_codec_inst_.plfreq != send_codec.plfreq) {
|
|
force_init = true;
|
|
}
|
|
|
|
// If packet size or number of channels has changed, we need to
|
|
// re-initialize the encoder.
|
|
if (send_codec_inst_.pacsize != send_codec.pacsize) {
|
|
force_init = true;
|
|
}
|
|
if (send_codec_inst_.channels != send_codec.channels) {
|
|
force_init = true;
|
|
}
|
|
|
|
if (force_init) {
|
|
WebRtcACMCodecParams codec_params;
|
|
|
|
memcpy(&(codec_params.codec_inst), &send_codec, sizeof(CodecInst));
|
|
codec_params.enable_vad = vad_enabled_;
|
|
codec_params.enable_dtx = dtx_enabled_;
|
|
codec_params.vad_mode = vad_mode_;
|
|
|
|
// Force initialization.
|
|
if (current_encoder_->InitEncoder(&codec_params, true) < 0) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
|
|
"Could not change the codec packet-size.");
|
|
return -1;
|
|
}
|
|
|
|
send_codec_inst_.plfreq = send_codec.plfreq;
|
|
send_codec_inst_.pacsize = send_codec.pacsize;
|
|
send_codec_inst_.channels = send_codec.channels;
|
|
}
|
|
|
|
// If the change of sampling frequency has been successful then
|
|
// we store the payload-type.
|
|
send_codec_inst_.pltype = send_codec.pltype;
|
|
|
|
// Check if a change in Rate is required.
|
|
if (send_codec.rate != send_codec_inst_.rate) {
|
|
if (current_encoder_->SetBitRate(send_codec.rate) < 0) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
|
|
"Could not change the codec rate.");
|
|
return -1;
|
|
}
|
|
send_codec_inst_.rate = send_codec.rate;
|
|
}
|
|
|
|
if (!current_encoder_->HasInternalFEC()) {
|
|
codec_fec_enabled_ = false;
|
|
} else {
|
|
if (current_encoder_->SetFEC(codec_fec_enabled_) < 0) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
|
|
"Cannot set codec FEC");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int CodecManager::SendCodec(CodecInst* current_codec) const {
|
|
int dummy_id = 0;
|
|
WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, dummy_id,
|
|
"SendCodec()");
|
|
|
|
if (!current_encoder_) {
|
|
WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, dummy_id,
|
|
"SendCodec Failed, no codec is registered");
|
|
return -1;
|
|
}
|
|
WebRtcACMCodecParams encoder_param;
|
|
current_encoder_->EncoderParams(&encoder_param);
|
|
encoder_param.codec_inst.pltype = send_codec_inst_.pltype;
|
|
memcpy(current_codec, &(encoder_param.codec_inst), sizeof(CodecInst));
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Register possible receive codecs, can be called multiple times,
|
|
// for codecs, CNG (NB, WB and SWB), DTMF, RED.
|
|
int CodecManager::RegisterReceiveCodec(const CodecInst& codec) {
|
|
if (codec.channels > 2 || codec.channels < 0) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 0,
|
|
"Unsupported number of channels, %d.", codec.channels);
|
|
return -1;
|
|
}
|
|
|
|
int codec_id = ACMCodecDB::ReceiverCodecNumber(codec);
|
|
|
|
if (codec_id < 0 || codec_id >= ACMCodecDB::kNumCodecs) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 0,
|
|
"Wrong codec params to be registered as receive codec");
|
|
return -1;
|
|
}
|
|
|
|
// Check if the payload-type is valid.
|
|
if (!ACMCodecDB::ValidPayloadType(codec.pltype)) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 0,
|
|
"Invalid payload-type %d for %s.", codec.pltype, codec.plname);
|
|
return -1;
|
|
}
|
|
|
|
AudioDecoder* decoder = NULL;
|
|
// Get |decoder| associated with |codec|. |decoder| can be NULL if |codec|
|
|
// does not own its decoder.
|
|
if (GetAudioDecoder(codec, codec_id, &decoder) < 0) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 0,
|
|
"Wrong codec params to be registered as receive codec");
|
|
return -1;
|
|
}
|
|
uint8_t payload_type = static_cast<uint8_t>(codec.pltype);
|
|
return acm_->RegisterDecoder(codec_id, payload_type, codec.channels, decoder);
|
|
}
|
|
|
|
bool CodecManager::SetCopyRed(bool enable) {
|
|
if (enable && codec_fec_enabled_) {
|
|
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0,
|
|
"Codec internal FEC and RED cannot be co-enabled.");
|
|
return false;
|
|
}
|
|
if (current_encoder_ && current_encoder_->SetCopyRed(enable) < 0) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 0,
|
|
"SetCopyRed failed");
|
|
return false;
|
|
}
|
|
red_enabled_ = enable;
|
|
return true;
|
|
}
|
|
|
|
int CodecManager::SetVAD(bool enable_dtx, bool enable_vad, ACMVADMode mode) {
|
|
// Sanity check of the mode.
|
|
if ((mode != VADNormal) && (mode != VADLowBitrate) && (mode != VADAggr) &&
|
|
(mode != VADVeryAggr)) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 0,
|
|
"Invalid VAD Mode %d, no change is made to VAD/DTX status",
|
|
mode);
|
|
return -1;
|
|
}
|
|
|
|
// Check that the send codec is mono. We don't support VAD/DTX for stereo
|
|
// sending.
|
|
if ((enable_dtx || enable_vad) && stereo_send_) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 0,
|
|
"VAD/DTX not supported for stereo sending");
|
|
dtx_enabled_ = false;
|
|
vad_enabled_ = false;
|
|
vad_mode_ = mode;
|
|
return -1;
|
|
}
|
|
|
|
// Store VAD/DTX settings. Values can be changed in the call to "SetVAD"
|
|
// below.
|
|
dtx_enabled_ = enable_dtx;
|
|
vad_enabled_ = enable_vad;
|
|
vad_mode_ = mode;
|
|
|
|
// If a send codec is registered, set VAD/DTX for the codec.
|
|
if (current_encoder_ &&
|
|
current_encoder_->SetVAD(&dtx_enabled_, &vad_enabled_, &vad_mode_) < 0) {
|
|
// SetVAD failed.
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 0,
|
|
"SetVAD failed");
|
|
vad_enabled_ = false;
|
|
dtx_enabled_ = false;
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void CodecManager::VAD(bool* dtx_enabled,
|
|
bool* vad_enabled,
|
|
ACMVADMode* mode) const {
|
|
*dtx_enabled = dtx_enabled_;
|
|
*vad_enabled = vad_enabled_;
|
|
*mode = vad_mode_;
|
|
}
|
|
|
|
int CodecManager::SetCodecFEC(bool enable_codec_fec) {
|
|
if (enable_codec_fec == true && red_enabled_ == true) {
|
|
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, 0,
|
|
"Codec internal FEC and RED cannot be co-enabled.");
|
|
return -1;
|
|
}
|
|
|
|
// Set codec FEC.
|
|
if (current_encoder_ && current_encoder_->SetFEC(enable_codec_fec) < 0) {
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 0,
|
|
"Set codec internal FEC failed.");
|
|
return -1;
|
|
}
|
|
codec_fec_enabled_ = enable_codec_fec;
|
|
return 0;
|
|
}
|
|
|
|
void CodecManager::SetCngPayloadType(int sample_rate_hz, int payload_type) {
|
|
if (isac_enc_dec_)
|
|
isac_enc_dec_->SetCngPt(sample_rate_hz, payload_type);
|
|
if (encoder_)
|
|
encoder_->SetCngPt(sample_rate_hz, payload_type);
|
|
}
|
|
|
|
void CodecManager::SetRedPayloadType(int sample_rate_hz, int payload_type) {
|
|
if (isac_enc_dec_)
|
|
isac_enc_dec_->SetRedPt(sample_rate_hz, payload_type);
|
|
if (encoder_)
|
|
encoder_->SetRedPt(sample_rate_hz, payload_type);
|
|
}
|
|
|
|
int CodecManager::GetAudioDecoder(const CodecInst& codec,
|
|
int codec_id,
|
|
AudioDecoder** decoder) {
|
|
if (!ACMCodecDB::OwnsDecoder(codec_id)) {
|
|
DCHECK(!IsIsac(codec)) << "Codec must not be iSAC at this point.";
|
|
*decoder = nullptr;
|
|
return 0;
|
|
}
|
|
DCHECK(IsIsac(codec)) << "Codec must be iSAC at this point.";
|
|
// This codec has to own its own decoder. Therefore, it should create the
|
|
// corresponding AudioDecoder class and insert it into NetEq. If the codec
|
|
// does not exist create it.
|
|
//
|
|
// TODO(turajs): this part of the code is common with RegisterSendCodec(),
|
|
// make a method for it.
|
|
if (!isac_enc_dec_) {
|
|
isac_enc_dec_.reset(ACMCodecDB::CreateCodecInstance(
|
|
codec, cng_nb_pltype_, cng_wb_pltype_, cng_swb_pltype_, cng_fb_pltype_,
|
|
red_enabled_, red_nb_pltype_));
|
|
if (!isac_enc_dec_)
|
|
return -1;
|
|
}
|
|
*decoder = isac_enc_dec_->Decoder();
|
|
DCHECK(*decoder);
|
|
return 0;
|
|
}
|
|
|
|
} // namespace acm2
|
|
} // namespace webrtc
|