Introduce CodecManager and move code from AudioCodingModuleImpl
This change essentially divides AudioCodingModuleImpl into two parts:
one is the code related to managing codecs, now moved into CodecManager,
and the other is what remains in AudioCodingModuleImpl.
This change also removes AudioCodingModuleImpl::InitializeSender. The
function was essentially no-op, since it was always called immediately
after construction.
COAUTHOR=kwiberg@webrtc.org
BUG=4228
R=minyue@webrtc.org, tina.legrand@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/51469004
Cr-Original-Commit-Position: refs/heads/master@{#8893}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: 45c6449114ab69cab755410f69567fa7e20f8106
diff --git a/modules/audio_coding/main/acm2/acm_generic_codec.cc b/modules/audio_coding/main/acm2/acm_generic_codec.cc
index c472a4a..6d7b095 100644
--- a/modules/audio_coding/main/acm2/acm_generic_codec.cc
+++ b/modules/audio_coding/main/acm2/acm_generic_codec.cc
@@ -209,7 +209,7 @@
return decoder_->Channels();
}
-int16_t ACMGenericCodec::EncoderParams(WebRtcACMCodecParams* enc_params) {
+int16_t ACMGenericCodec::EncoderParams(WebRtcACMCodecParams* enc_params) const {
*enc_params = acm_codec_params_;
return 0;
}
@@ -540,6 +540,10 @@
return encoder_;
}
+const AudioEncoder* ACMGenericCodec::GetAudioEncoder() const {
+ return encoder_;
+}
+
} // namespace acm2
} // namespace webrtc
diff --git a/modules/audio_coding/main/acm2/acm_generic_codec.h b/modules/audio_coding/main/acm2/acm_generic_codec.h
index 6a5a04a..d491dfd 100644
--- a/modules/audio_coding/main/acm2/acm_generic_codec.h
+++ b/modules/audio_coding/main/acm2/acm_generic_codec.h
@@ -120,7 +120,7 @@
// -1 if the encoder is not initialized,
// 0 otherwise.
//
- int16_t EncoderParams(WebRtcACMCodecParams* enc_params);
+ int16_t EncoderParams(WebRtcACMCodecParams* enc_params) const;
///////////////////////////////////////////////////////////////////////////
// int16_t InitEncoder(...)
@@ -410,6 +410,8 @@
AudioEncoder* GetAudioEncoder();
+ const AudioEncoder* GetAudioEncoder() const;
+
private:
bool has_internal_fec_;
diff --git a/modules/audio_coding/main/acm2/acm_receiver_unittest_oldapi.cc b/modules/audio_coding/main/acm2/acm_receiver_unittest_oldapi.cc
index d2b7746..269d19c 100644
--- a/modules/audio_coding/main/acm2/acm_receiver_unittest_oldapi.cc
+++ b/modules/audio_coding/main/acm2/acm_receiver_unittest_oldapi.cc
@@ -62,7 +62,6 @@
}
acm_->InitializeReceiver();
- acm_->InitializeSender();
acm_->RegisterTransportCallback(this);
rtp_header_.header.sequenceNumber = 0;
diff --git a/modules/audio_coding/main/acm2/audio_coding_module.gypi b/modules/audio_coding/main/acm2/audio_coding_module.gypi
index edbcaa9..6b938b6 100644
--- a/modules/audio_coding/main/acm2/audio_coding_module.gypi
+++ b/modules/audio_coding/main/acm2/audio_coding_module.gypi
@@ -70,6 +70,8 @@
'audio_coding_module_impl.h',
'call_statistics.cc',
'call_statistics.h',
+ 'codec_manager.cc',
+ 'codec_manager.h',
'initial_delay_manager.cc',
'initial_delay_manager.h',
'nack.cc',
diff --git a/modules/audio_coding/main/acm2/audio_coding_module_impl.cc b/modules/audio_coding/main/acm2/audio_coding_module_impl.cc
index c4ab6a9..d78af65 100644
--- a/modules/audio_coding/main/acm2/audio_coding_module_impl.cc
+++ b/modules/audio_coding/main/acm2/audio_coding_module_impl.cc
@@ -18,7 +18,6 @@
#include "webrtc/base/safe_conversions.h"
#include "webrtc/engine_configurations.h"
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
-#include "webrtc/modules/audio_coding/main/acm2/acm_codec_database.h"
#include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
#include "webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h"
#include "webrtc/modules/audio_coding/main/acm2/acm_resampler.h"
@@ -126,20 +125,8 @@
id_(config.id),
expected_codec_ts_(0xD87F3F9F),
expected_in_ts_(0xD87F3F9F),
- send_codec_inst_(),
- cng_nb_pltype_(255),
- cng_wb_pltype_(255),
- cng_swb_pltype_(255),
- cng_fb_pltype_(255),
- red_nb_pltype_(255),
- vad_enabled_(false),
- dtx_enabled_(false),
- vad_mode_(VADNormal),
- current_encoder_(nullptr),
- stereo_send_(false),
receiver_(config),
- red_enabled_(false),
- codec_fec_enabled_(false),
+ codec_manager_(this),
previous_pltype_(255),
aux_rtp_header_(NULL),
receiver_initialized_(false),
@@ -148,35 +135,6 @@
callback_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
packetization_callback_(NULL),
vad_callback_(NULL) {
- // Nullify send codec memory, set payload type and set codec name to
- // invalid values.
- const char no_name[] = "noCodecRegistered";
- strncpy(send_codec_inst_.plname, no_name, RTP_PAYLOAD_NAME_SIZE - 1);
- send_codec_inst_.pltype = -1;
-
- for (int i = 0; i < ACMCodecDB::kMaxNumCodecs; i++) {
- codecs_[i] = NULL;
- mirror_codec_idx_[i] = -1;
- }
-
- // 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);
- }
- }
- }
-
if (InitializeReceiverSafe() < 0) {
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
"Cannot initialize receiver");
@@ -185,23 +143,6 @@
}
AudioCodingModuleImpl::~AudioCodingModuleImpl() {
- {
- CriticalSectionScoped lock(acm_crit_sect_);
-
- for (int i = 0; i < ACMCodecDB::kMaxNumCodecs; i++) {
- if (codecs_[i] != NULL) {
- // Mirror index holds the address of the codec memory.
- assert(mirror_codec_idx_[i] > -1);
- if (codecs_[mirror_codec_idx_[i]] != NULL) {
- delete codecs_[mirror_codec_idx_[i]];
- codecs_[mirror_codec_idx_[i]] = NULL;
- }
-
- codecs_[i] = NULL;
- }
- }
- }
-
if (aux_rtp_header_ != NULL) {
delete aux_rtp_header_;
aux_rtp_header_ = NULL;
@@ -229,7 +170,8 @@
return -1;
}
- AudioEncoder* audio_encoder = current_encoder_->GetAudioEncoder();
+ AudioEncoder* audio_encoder =
+ codec_manager_.current_encoder()->GetAudioEncoder();
// Scale the timestamp to the codec's RTP timestamp rate.
uint32_t rtp_timestamp =
first_frame_ ? input_data.input_timestamp
@@ -271,7 +213,7 @@
frame_type, encoded_info.payload_type, encoded_info.encoded_timestamp,
stream, encoded_info.encoded_bytes,
my_fragmentation.fragmentationVectorSize > 0 ? &my_fragmentation
- : nullptr);
+ : nullptr);
}
if (vad_callback_) {
@@ -290,17 +232,6 @@
// Sender
//
-// Initialize send codec.
-int AudioCodingModuleImpl::InitializeSender() {
- CriticalSectionScoped lock(acm_crit_sect_);
-
- // Start with invalid values.
- current_encoder_ = nullptr;
- send_codec_inst_.plname[0] = '\0';
-
- return 0;
-}
-
// TODO(henrik.lundin): Remove this method; only used in tests.
int AudioCodingModuleImpl::ResetEncoder() {
CriticalSectionScoped lock(acm_crit_sect_);
@@ -310,365 +241,16 @@
return 0;
}
-ACMGenericCodec* AudioCodingModuleImpl::CreateCodec(const CodecInst& codec) {
- ACMGenericCodec* my_codec = NULL;
- CriticalSectionScoped lock(acm_crit_sect_);
- my_codec = ACMCodecDB::CreateCodecInstance(
- codec, cng_nb_pltype_, cng_wb_pltype_, cng_swb_pltype_, cng_fb_pltype_,
- red_enabled_, red_nb_pltype_);
- if (my_codec == NULL) {
- // Error, could not create the codec.
- WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
- "ACMCodecDB::CreateCodecInstance() failed in CreateCodec()");
- return my_codec;
- }
-
- return my_codec;
-}
-
-// Check if the given codec is a valid to be registered as send codec.
-static int IsValidSendCodec(const CodecInst& send_codec,
- bool is_primary_encoder,
- int acm_id,
- int* mirror_id) {
- if ((send_codec.channels != 1) && (send_codec.channels != 2)) {
- WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, acm_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, mirror_id);
- if (codec_id < 0) {
- WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, acm_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, acm_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, acm_id,
- "telephone-event cannot be a send codec");
- *mirror_id = -1;
- return -1;
- }
-
- if (ACMCodecDB::codec_settings_[codec_id].channel_support
- < send_codec.channels) {
- WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, acm_id,
- "%d number of channels not supportedn for %s.",
- send_codec.channels, send_codec.plname);
- *mirror_id = -1;
- 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, acm_id,
- "RED cannot be secondary codec");
- *mirror_id = -1;
- return -1;
- }
-
- if (IsCodecCN(&send_codec)) {
- WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, acm_id,
- "DTX cannot be secondary codec");
- *mirror_id = -1;
- return -1;
- }
- }
- return codec_id;
-}
-
// Can be called multiple times for Codec, CNG, RED.
int AudioCodingModuleImpl::RegisterSendCodec(const CodecInst& send_codec) {
- int mirror_id;
- int codec_id = IsValidSendCodec(send_codec, true, id_, &mirror_id);
-
CriticalSectionScoped lock(acm_crit_sect_);
-
- // Check for reported errors from function IsValidSendCodec().
- if (codec_id < 0) {
- return -1;
- }
-
- // 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, 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, 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, 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, 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_mirror_id;
- int send_codec_id = ACMCodecDB::CodecNumber(send_codec_inst_,
- &send_codec_mirror_id);
- assert(send_codec_id >= 0);
- is_send_codec = (send_codec_id == codec_id) ||
- (mirror_id == send_codec_mirror_id);
- } else {
- is_send_codec = false;
- }
-
- // If new codec, or new settings, register.
- if (!is_send_codec) {
- if (codecs_[mirror_id] == NULL) {
- codecs_[mirror_id] = CreateCodec(send_codec);
- if (codecs_[mirror_id] == NULL) {
- WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
- "Cannot Create the codec");
- return -1;
- }
- mirror_codec_idx_[mirror_id] = mirror_id;
- }
-
- if (mirror_id != codec_id) {
- codecs_[codec_id] = codecs_[mirror_id];
- mirror_codec_idx_[codec_id] = mirror_id;
- }
-
- ACMGenericCodec* codec_ptr = codecs_[codec_id];
- 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 (codec_ptr->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, id_,
- "Cannot Initialize the encoder No Encoder is registered");
- } else {
- WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 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(codec_ptr->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_;
- }
-
- codec_ptr->SetVAD(&dtx_enabled_, &vad_enabled_, &vad_mode_);
-
- if (!codec_ptr->HasInternalFEC()) {
- codec_fec_enabled_ = false;
- } else {
- if (codec_ptr->SetFEC(codec_fec_enabled_) < 0) {
- WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
- "Cannot set codec FEC");
- return -1;
- }
- }
- }
-
- current_encoder_ = codecs_[codec_id];
- 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;
-
- if (mirror_id != codec_id) {
- codecs_[codec_id] = codecs_[mirror_id];
- mirror_codec_idx_[codec_id] = mirror_id;
- }
-
- // 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, 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, 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 (codecs_[codec_id]->SetBitRate(send_codec.rate) < 0) {
- WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
- "Could not change the codec rate.");
- return -1;
- }
- send_codec_inst_.rate = send_codec.rate;
- }
-
- if (!codecs_[codec_id]->HasInternalFEC()) {
- codec_fec_enabled_ = false;
- } else {
- if (codecs_[codec_id]->SetFEC(codec_fec_enabled_) < 0) {
- WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
- "Cannot set codec FEC");
- return -1;
- }
- }
-
- return 0;
- }
+ return codec_manager_.RegisterSendCodec(send_codec);
}
// Get current send codec.
-int AudioCodingModuleImpl::SendCodec(
- CodecInst* current_codec) const {
- WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, id_,
- "SendCodec()");
+int AudioCodingModuleImpl::SendCodec(CodecInst* current_codec) const {
CriticalSectionScoped lock(acm_crit_sect_);
-
- if (!current_encoder_) {
- WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, 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;
+ return codec_manager_.SendCodec(current_codec);
}
// Get current send frequency.
@@ -677,13 +259,13 @@
"SendFrequency()");
CriticalSectionScoped lock(acm_crit_sect_);
- if (!current_encoder_) {
+ if (!codec_manager_.current_encoder()) {
WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, id_,
"SendFrequency Failed, no codec is registered");
return -1;
}
- return send_codec_inst_.plfreq;
+ return codec_manager_.current_encoder()->GetAudioEncoder()->SampleRateHz();
}
// Get encode bitrate.
@@ -693,14 +275,14 @@
int AudioCodingModuleImpl::SendBitrate() const {
CriticalSectionScoped lock(acm_crit_sect_);
- if (!current_encoder_) {
+ if (!codec_manager_.current_encoder()) {
WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, id_,
"SendBitrate Failed, no codec is registered");
return -1;
}
WebRtcACMCodecParams encoder_param;
- current_encoder_->EncoderParams(&encoder_param);
+ codec_manager_.current_encoder()->EncoderParams(&encoder_param);
return encoder_param.codec_inst.rate;
}
@@ -779,7 +361,9 @@
}
// Check whether we need an up-mix or down-mix?
- bool remix = ptr_frame->num_channels_ != send_codec_inst_.channels;
+ bool remix =
+ ptr_frame->num_channels_ !=
+ codec_manager_.current_encoder()->GetAudioEncoder()->NumChannels();
if (remix) {
if (ptr_frame->num_channels_ == 1) {
@@ -796,13 +380,15 @@
const int16_t* ptr_audio = ptr_frame->data_;
// For pushing data to primary, point the |ptr_audio| to correct buffer.
- if (send_codec_inst_.channels != ptr_frame->num_channels_)
+ if (codec_manager_.current_encoder()->GetAudioEncoder()->NumChannels() !=
+ ptr_frame->num_channels_)
ptr_audio = input_data->buffer;
input_data->input_timestamp = ptr_frame->timestamp_;
input_data->audio = ptr_audio;
input_data->length_per_channel = ptr_frame->samples_per_channel_;
- input_data->audio_channel = send_codec_inst_.channels;
+ input_data->audio_channel =
+ codec_manager_.current_encoder()->GetAudioEncoder()->NumChannels();
return 0;
}
@@ -814,12 +400,15 @@
// is required, |*ptr_out| points to |in_frame|.
int AudioCodingModuleImpl::PreprocessToAddData(const AudioFrame& in_frame,
const AudioFrame** ptr_out) {
- bool resample = (in_frame.sample_rate_hz_ != send_codec_inst_.plfreq);
+ bool resample =
+ (in_frame.sample_rate_hz_ !=
+ codec_manager_.current_encoder()->GetAudioEncoder()->SampleRateHz());
// This variable is true if primary codec and secondary codec (if exists)
// are both mono and input is stereo.
bool down_mix =
- (in_frame.num_channels_ == 2) && (send_codec_inst_.channels == 1);
+ (in_frame.num_channels_ == 2) &&
+ (codec_manager_.current_encoder()->GetAudioEncoder()->NumChannels() == 1);
if (!first_10ms_data_) {
expected_in_ts_ = in_frame.timestamp_;
@@ -827,9 +416,13 @@
first_10ms_data_ = true;
} else if (in_frame.timestamp_ != expected_in_ts_) {
// TODO(turajs): Do we need a warning here.
- expected_codec_ts_ += (in_frame.timestamp_ - expected_in_ts_) *
- static_cast<uint32_t>((static_cast<double>(send_codec_inst_.plfreq) /
- static_cast<double>(in_frame.sample_rate_hz_)));
+ expected_codec_ts_ +=
+ (in_frame.timestamp_ - expected_in_ts_) *
+ static_cast<uint32_t>(
+ (static_cast<double>(codec_manager_.current_encoder()
+ ->GetAudioEncoder()
+ ->SampleRateHz()) /
+ static_cast<double>(in_frame.sample_rate_hz_)));
expected_in_ts_ = in_frame.timestamp_;
}
@@ -867,20 +460,19 @@
// The result of the resampler is written to output frame.
dest_ptr_audio = preprocess_frame_.data_;
- preprocess_frame_.samples_per_channel_ =
- resampler_.Resample10Msec(src_ptr_audio,
- in_frame.sample_rate_hz_,
- send_codec_inst_.plfreq,
- preprocess_frame_.num_channels_,
- AudioFrame::kMaxDataSizeSamples,
- dest_ptr_audio);
+ preprocess_frame_.samples_per_channel_ = resampler_.Resample10Msec(
+ src_ptr_audio, in_frame.sample_rate_hz_,
+ codec_manager_.current_encoder()->GetAudioEncoder()->SampleRateHz(),
+ preprocess_frame_.num_channels_, AudioFrame::kMaxDataSizeSamples,
+ dest_ptr_audio);
if (preprocess_frame_.samples_per_channel_ < 0) {
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
"Cannot add 10 ms audio, resampling failed");
return -1;
}
- preprocess_frame_.sample_rate_hz_ = send_codec_inst_.plfreq;
+ preprocess_frame_.sample_rate_hz_ =
+ codec_manager_.current_encoder()->GetAudioEncoder()->SampleRateHz();
}
expected_codec_ts_ += preprocess_frame_.samples_per_channel_;
@@ -895,8 +487,7 @@
bool AudioCodingModuleImpl::REDStatus() const {
CriticalSectionScoped lock(acm_crit_sect_);
-
- return red_enabled_;
+ return codec_manager_.red_enabled();
}
// Configure RED status i.e on/off.
@@ -904,23 +495,7 @@
#ifdef WEBRTC_CODEC_RED
bool enable_red) {
CriticalSectionScoped lock(acm_crit_sect_);
-
- if (enable_red == true && codec_fec_enabled_ == true) {
- WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, id_,
- "Codec internal FEC and RED cannot be co-enabled.");
- return -1;
- }
-
- // If a send codec is registered, set RED for the codec. We now only support
- // copy red.
- if (HaveValidEncoder("SetCopyRed") &&
- current_encoder_->SetCopyRed(enable_red) < 0) {
- WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
- "SetREDStatus failed");
- return -1;
- }
- red_enabled_ = enable_red;
- return 0;
+ return codec_manager_.SetCopyRed(enable_red) ? 0 : -1;
#else
bool /* enable_red */) {
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, id_,
@@ -935,33 +510,18 @@
bool AudioCodingModuleImpl::CodecFEC() const {
CriticalSectionScoped lock(acm_crit_sect_);
- return codec_fec_enabled_;
+ return codec_manager_.codec_fec_enabled();
}
int AudioCodingModuleImpl::SetCodecFEC(bool enable_codec_fec) {
CriticalSectionScoped lock(acm_crit_sect_);
-
- if (enable_codec_fec == true && red_enabled_ == true) {
- WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, id_,
- "Codec internal FEC and RED cannot be co-enabled.");
- return -1;
- }
-
- // Set codec FEC.
- if (HaveValidEncoder("SetCodecFEC") &&
- current_encoder_->SetFEC(enable_codec_fec) < 0) {
- WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
- "Set codec internal FEC failed.");
- return -1;
- }
- codec_fec_enabled_ = enable_codec_fec;
- return 0;
+ return codec_manager_.SetCodecFEC(enable_codec_fec);
}
int AudioCodingModuleImpl::SetPacketLossRate(int loss_rate) {
CriticalSectionScoped lock(acm_crit_sect_);
if (HaveValidEncoder("SetPacketLossRate") &&
- current_encoder_->SetPacketLossRate(loss_rate) < 0) {
+ codec_manager_.current_encoder()->SetPacketLossRate(loss_rate) < 0) {
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
"Set packet loss rate failed.");
return -1;
@@ -976,60 +536,14 @@
bool enable_vad,
ACMVADMode mode) {
CriticalSectionScoped lock(acm_crit_sect_);
- return SetVADSafe(enable_dtx, enable_vad, mode);
-}
-
-int AudioCodingModuleImpl::SetVADSafe(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, id_,
- "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, id_,
- "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 (HaveValidEncoder("SetVAD") &&
- current_encoder_->SetVAD(&dtx_enabled_, &vad_enabled_, &vad_mode_) < 0) {
- // SetVAD failed.
- WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
- "SetVAD failed");
- vad_enabled_ = false;
- dtx_enabled_ = false;
- return -1;
- }
- return 0;
+ return codec_manager_.SetVAD(enable_dtx, enable_vad, mode);
}
// Get VAD/DTX settings.
int AudioCodingModuleImpl::VAD(bool* dtx_enabled, bool* vad_enabled,
ACMVADMode* mode) const {
CriticalSectionScoped lock(acm_crit_sect_);
-
- *dtx_enabled = dtx_enabled_;
- *vad_enabled = vad_enabled_;
- *mode = vad_mode_;
-
+ codec_manager_.VAD(dtx_enabled, vad_enabled, mode);
return 0;
}
@@ -1108,56 +622,24 @@
// for codecs, CNG (NB, WB and SWB), DTMF, RED.
int AudioCodingModuleImpl::RegisterReceiveCodec(const CodecInst& codec) {
CriticalSectionScoped lock(acm_crit_sect_);
-
- if (codec.channels > 2 || codec.channels < 0) {
- WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
- "Unsupported number of channels, %d.", codec.channels);
- return -1;
- }
-
- // TODO(turajs) do we need this for NetEq 4?
- if (!receiver_initialized_) {
- if (InitializeReceiverSafe() < 0) {
- WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
- "Cannot initialize receiver, failed registering codec.");
- return -1;
- }
- }
-
- int mirror_id;
- int codec_id = ACMCodecDB::ReceiverCodecNumber(codec, &mirror_id);
-
- if (codec_id < 0 || codec_id >= ACMCodecDB::kNumCodecs) {
- WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
- "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, id_,
- "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, mirror_id, &decoder) < 0) {
- WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
- "Wrong codec params to be registered as receive codec");
- return -1;
- }
- uint8_t payload_type = static_cast<uint8_t>(codec.pltype);
- return receiver_.AddCodec(codec_id, payload_type, codec.channels, decoder);
+ DCHECK(receiver_initialized_);
+ return codec_manager_.RegisterReceiveCodec(codec);
}
// Get current received codec.
int AudioCodingModuleImpl::ReceiveCodec(CodecInst* current_codec) const {
+ CriticalSectionScoped lock(acm_crit_sect_);
return receiver_.LastAudioCodec(current_codec);
}
+int AudioCodingModuleImpl::RegisterDecoder(int acm_codec_id,
+ uint8_t payload_type,
+ int channels,
+ AudioDecoder* audio_decoder) {
+ return receiver_.AddCodec(acm_codec_id, payload_type, channels,
+ audio_decoder);
+}
+
// Incoming packet from network parsed and ready for decode.
int AudioCodingModuleImpl::IncomingPacket(const uint8_t* incoming_payload,
const size_t payload_length,
@@ -1312,7 +794,7 @@
return -1;
}
- return current_encoder_->SetISACMaxRate(max_bit_per_sec);
+ return codec_manager_.current_encoder()->SetISACMaxRate(max_bit_per_sec);
}
// TODO(henrik.lundin): Remove? Only used in tests. Deprecated in VoiceEngine.
@@ -1323,7 +805,8 @@
return -1;
}
- return current_encoder_->SetISACMaxPayloadSize(max_size_bytes);
+ return codec_manager_.current_encoder()->SetISACMaxPayloadSize(
+ max_size_bytes);
}
// TODO(henrik.lundin): Remove? Only used in tests.
@@ -1349,8 +832,8 @@
if (!HaveValidEncoder("SetOpusApplication")) {
return -1;
}
- return current_encoder_->SetOpusApplication(application,
- disable_dtx_if_needed);
+ return codec_manager_.current_encoder()->SetOpusApplication(
+ application, disable_dtx_if_needed);
}
// Informs Opus encoder of the maximum playback rate the receiver will render.
@@ -1359,7 +842,7 @@
if (!HaveValidEncoder("SetOpusMaxPlaybackRate")) {
return -1;
}
- return current_encoder_->SetOpusMaxPlaybackRate(frequency_hz);
+ return codec_manager_.current_encoder()->SetOpusMaxPlaybackRate(frequency_hz);
}
int AudioCodingModuleImpl::EnableOpusDtx(bool force_voip) {
@@ -1367,7 +850,7 @@
if (!HaveValidEncoder("EnableOpusDtx")) {
return -1;
}
- return current_encoder_->EnableOpusDtx(force_voip);
+ return codec_manager_.current_encoder()->EnableOpusDtx(force_voip);
}
int AudioCodingModuleImpl::DisableOpusDtx() {
@@ -1375,7 +858,7 @@
if (!HaveValidEncoder("DisableOpusDtx")) {
return -1;
}
- return current_encoder_->DisableOpusDtx();
+ return codec_manager_.current_encoder()->DisableOpusDtx();
}
int AudioCodingModuleImpl::PlayoutTimestamp(uint32_t* timestamp) {
@@ -1383,7 +866,7 @@
}
bool AudioCodingModuleImpl::HaveValidEncoder(const char* caller_name) const {
- if (!current_encoder_) {
+ if (!codec_manager_.current_encoder()) {
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
"%s failed: No send codec is registered.", caller_name);
return false;
@@ -1415,60 +898,6 @@
// return status;
}
-int AudioCodingModuleImpl::GetAudioDecoder(const CodecInst& codec, int codec_id,
- int mirror_id,
- AudioDecoder** decoder) {
- if (ACMCodecDB::OwnsDecoder(codec_id)) {
- // 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 (codecs_[mirror_id] == NULL) {
- codecs_[mirror_id] = CreateCodec(codec);
- if (codecs_[mirror_id] == NULL) {
- WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
- "Cannot Create the codec");
- return -1;
- }
- mirror_codec_idx_[mirror_id] = mirror_id;
- }
-
- if (mirror_id != codec_id) {
- codecs_[codec_id] = codecs_[mirror_id];
- mirror_codec_idx_[codec_id] = mirror_id;
- }
- *decoder = codecs_[codec_id]->Decoder();
- if (!*decoder) {
- assert(false);
- return -1;
- }
- } else {
- *decoder = NULL;
- }
-
- return 0;
-}
-
-void AudioCodingModuleImpl::SetCngPayloadType(int sample_rate_hz,
- int payload_type) {
- for (auto* codec : codecs_) {
- if (codec) {
- codec->SetCngPt(sample_rate_hz, payload_type);
- }
- }
-}
-
-void AudioCodingModuleImpl::SetRedPayloadType(int sample_rate_hz,
- int payload_type) {
- for (auto* codec : codecs_) {
- if (codec) {
- codec->SetRedPt(sample_rate_hz, payload_type);
- }
- }
-}
-
int AudioCodingModuleImpl::SetInitialPlayoutDelay(int delay_ms) {
{
CriticalSectionScoped lock(acm_crit_sect_);
diff --git a/modules/audio_coding/main/acm2/audio_coding_module_impl.h b/modules/audio_coding/main/acm2/audio_coding_module_impl.h
index 04a2059..1e9cbb9 100644
--- a/modules/audio_coding/main/acm2/audio_coding_module_impl.h
+++ b/modules/audio_coding/main/acm2/audio_coding_module_impl.h
@@ -20,6 +20,7 @@
#include "webrtc/modules/audio_coding/main/acm2/acm_codec_database.h"
#include "webrtc/modules/audio_coding/main/acm2/acm_receiver.h"
#include "webrtc/modules/audio_coding/main/acm2/acm_resampler.h"
+#include "webrtc/modules/audio_coding/main/acm2/codec_manager.h"
namespace webrtc {
@@ -42,9 +43,6 @@
// Sender
//
- // Initialize send codec.
- int InitializeSender() override;
-
// Reset send codec.
int ResetEncoder() override;
@@ -135,6 +133,11 @@
// Get current received codec.
int ReceiveCodec(CodecInst* current_codec) const override;
+ int RegisterDecoder(int acm_codec_id,
+ uint8_t payload_type,
+ int channels,
+ AudioDecoder* audio_decoder);
+
// Incoming packet from network parsed and ready for decode.
int IncomingPacket(const uint8_t* incoming_payload,
const size_t payload_length,
@@ -249,18 +252,11 @@
int Add10MsDataInternal(const AudioFrame& audio_frame, InputData* input_data);
int Encode(const InputData& input_data);
- ACMGenericCodec* CreateCodec(const CodecInst& codec);
-
int InitializeReceiverSafe() EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_);
bool HaveValidEncoder(const char* caller_name) const
EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_);
- // Set VAD/DTX status. This function does not acquire a lock, and it is
- // created to be called only from inside a critical section.
- int SetVADSafe(bool enable_dtx, bool enable_vad, ACMVADMode mode)
- EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_);
-
// Preprocessing of input audio, including resampling and down-mixing if
// required, before pushing audio into encoder's buffer.
//
@@ -280,54 +276,13 @@
// to |index|.
int UpdateUponReceivingCodec(int index);
- // Get a pointer to AudioDecoder of the given codec. For some codecs, e.g.
- // iSAC, encoding and decoding have to be performed on a shared
- // codec-instance. By calling this method, we get the codec-instance that ACM
- // owns, then pass that to NetEq. This way, we perform both encoding and
- // decoding on the same codec-instance. Furthermore, ACM would have control
- // over decoder functionality if required. If |codec| does not share an
- // instance between encoder and decoder, the |*decoder| is set NULL.
- // The field ACMCodecDB::CodecSettings.owns_decoder indicates that if a
- // codec owns the decoder-instance. For such codecs |*decoder| should be a
- // valid pointer, otherwise it will be NULL.
- int GetAudioDecoder(const CodecInst& codec, int codec_id,
- int mirror_id, AudioDecoder** decoder)
- EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_);
-
- void SetCngPayloadType(int sample_rate_hz, int payload_type)
- EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_);
-
- void SetRedPayloadType(int sample_rate_hz, int payload_type)
- EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_);
-
CriticalSectionWrapper* acm_crit_sect_;
int id_; // TODO(henrik.lundin) Make const.
uint32_t expected_codec_ts_ GUARDED_BY(acm_crit_sect_);
uint32_t expected_in_ts_ GUARDED_BY(acm_crit_sect_);
- CodecInst send_codec_inst_ GUARDED_BY(acm_crit_sect_);
-
- uint8_t cng_nb_pltype_ GUARDED_BY(acm_crit_sect_);
- uint8_t cng_wb_pltype_ GUARDED_BY(acm_crit_sect_);
- uint8_t cng_swb_pltype_ GUARDED_BY(acm_crit_sect_);
- uint8_t cng_fb_pltype_ GUARDED_BY(acm_crit_sect_);
-
- uint8_t red_nb_pltype_ GUARDED_BY(acm_crit_sect_);
- bool vad_enabled_ GUARDED_BY(acm_crit_sect_);
- bool dtx_enabled_ GUARDED_BY(acm_crit_sect_);
- ACMVADMode vad_mode_ GUARDED_BY(acm_crit_sect_);
- ACMGenericCodec* codecs_[ACMCodecDB::kMaxNumCodecs]
- GUARDED_BY(acm_crit_sect_);
- ACMGenericCodec* current_encoder_ GUARDED_BY(acm_crit_sect_);
- int mirror_codec_idx_[ACMCodecDB::kMaxNumCodecs] GUARDED_BY(acm_crit_sect_);
- bool stereo_send_ GUARDED_BY(acm_crit_sect_);
ACMResampler resampler_ GUARDED_BY(acm_crit_sect_);
AcmReceiver receiver_; // AcmReceiver has it's own internal lock.
-
- // RED.
- bool red_enabled_ GUARDED_BY(acm_crit_sect_);
-
- // Codec internal FEC
- bool codec_fec_enabled_ GUARDED_BY(acm_crit_sect_);
+ CodecManager codec_manager_ GUARDED_BY(acm_crit_sect_);
// This is to keep track of CN instances where we can send DTMFs.
uint8_t previous_pltype_ GUARDED_BY(acm_crit_sect_);
diff --git a/modules/audio_coding/main/acm2/codec_manager.cc b/modules/audio_coding/main/acm2/codec_manager.cc
new file mode 100644
index 0000000..c3e340e
--- /dev/null
+++ b/modules/audio_coding/main/acm2/codec_manager.cc
@@ -0,0 +1,612 @@
+/*
+ * 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* mirror_id) {
+ 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, mirror_id);
+ 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");
+ *mirror_id = -1;
+ 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);
+ *mirror_id = -1;
+ 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");
+ *mirror_id = -1;
+ return -1;
+ }
+
+ if (IsCodecCN(&send_codec)) {
+ WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
+ "DTX cannot be secondary codec");
+ *mirror_id = -1;
+ return -1;
+ }
+ }
+ return codec_id;
+}
+
+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) {
+ for (int i = 0; i < ACMCodecDB::kMaxNumCodecs; i++) {
+ codecs_[i] = nullptr;
+ mirror_codec_idx_[i] = -1;
+ }
+
+ // 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() {
+ for (int i = 0; i < ACMCodecDB::kMaxNumCodecs; i++) {
+ if (codecs_[i] != NULL) {
+ // Mirror index holds the address of the codec memory.
+ assert(mirror_codec_idx_[i] > -1);
+ if (codecs_[mirror_codec_idx_[i]] != NULL) {
+ delete codecs_[mirror_codec_idx_[i]];
+ codecs_[mirror_codec_idx_[i]] = NULL;
+ }
+
+ codecs_[i] = NULL;
+ }
+ }
+}
+
+int CodecManager::RegisterSendCodec(const CodecInst& send_codec) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ int mirror_id;
+ int codec_id = IsValidSendCodec(send_codec, true, &mirror_id);
+
+ // 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_mirror_id;
+ int send_codec_id =
+ ACMCodecDB::CodecNumber(send_codec_inst_, &send_codec_mirror_id);
+ assert(send_codec_id >= 0);
+ is_send_codec =
+ (send_codec_id == codec_id) || (mirror_id == send_codec_mirror_id);
+ } else {
+ is_send_codec = false;
+ }
+
+ // If new codec, or new settings, register.
+ if (!is_send_codec) {
+ if (!codecs_[mirror_id]) {
+ codecs_[mirror_id] = ACMCodecDB::CreateCodecInstance(
+ send_codec, cng_nb_pltype_, cng_wb_pltype_, cng_swb_pltype_,
+ cng_fb_pltype_, red_enabled_, red_nb_pltype_);
+ if (!codecs_[mirror_id]) {
+ WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
+ "Cannot Create the codec");
+ return -1;
+ }
+ mirror_codec_idx_[mirror_id] = mirror_id;
+ }
+
+ if (mirror_id != codec_id) {
+ codecs_[codec_id] = codecs_[mirror_id];
+ mirror_codec_idx_[codec_id] = mirror_id;
+ }
+
+ ACMGenericCodec* codec_ptr = codecs_[codec_id];
+ 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 (codec_ptr->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 (codec_ptr->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_;
+ }
+
+ codec_ptr->SetVAD(&dtx_enabled_, &vad_enabled_, &vad_mode_);
+
+ if (!codec_ptr->HasInternalFEC()) {
+ codec_fec_enabled_ = false;
+ } else {
+ if (codec_ptr->SetFEC(codec_fec_enabled_) < 0) {
+ WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id,
+ "Cannot set codec FEC");
+ return -1;
+ }
+ }
+ }
+
+ current_encoder_ = codecs_[codec_id];
+ 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;
+
+ if (mirror_id != codec_id) {
+ codecs_[codec_id] = codecs_[mirror_id];
+ mirror_codec_idx_[codec_id] = mirror_id;
+ }
+
+ // 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 (codecs_[codec_id]->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 (!codecs_[codec_id]->HasInternalFEC()) {
+ codec_fec_enabled_ = false;
+ } else {
+ if (codecs_[codec_id]->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 mirror_id;
+ int codec_id = ACMCodecDB::ReceiverCodecNumber(codec, &mirror_id);
+
+ 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, mirror_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) {
+ for (auto* codec : codecs_) {
+ if (codec) {
+ codec->SetCngPt(sample_rate_hz, payload_type);
+ }
+ }
+}
+
+void CodecManager::SetRedPayloadType(int sample_rate_hz, int payload_type) {
+ for (auto* codec : codecs_) {
+ if (codec) {
+ codec->SetRedPt(sample_rate_hz, payload_type);
+ }
+ }
+}
+
+int CodecManager::GetAudioDecoder(const CodecInst& codec,
+ int codec_id,
+ int mirror_id,
+ AudioDecoder** decoder) {
+ if (ACMCodecDB::OwnsDecoder(codec_id)) {
+ // 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 (codecs_[mirror_id] == NULL) {
+ codecs_[mirror_id] = ACMCodecDB::CreateCodecInstance(
+ codec, cng_nb_pltype_, cng_wb_pltype_, cng_swb_pltype_,
+ cng_fb_pltype_, red_enabled_, red_nb_pltype_);
+ if (codecs_[mirror_id] == NULL) {
+ WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 0,
+ "Cannot Create the codec");
+ return -1;
+ }
+ mirror_codec_idx_[mirror_id] = mirror_id;
+ }
+
+ if (mirror_id != codec_id) {
+ codecs_[codec_id] = codecs_[mirror_id];
+ mirror_codec_idx_[codec_id] = mirror_id;
+ }
+ *decoder = codecs_[codec_id]->Decoder();
+ if (!*decoder) {
+ assert(false);
+ return -1;
+ }
+ } else {
+ *decoder = NULL;
+ }
+
+ return 0;
+}
+
+} // namespace acm2
+} // namespace webrtc
diff --git a/modules/audio_coding/main/acm2/codec_manager.h b/modules/audio_coding/main/acm2/codec_manager.h
new file mode 100644
index 0000000..8d5350d
--- /dev/null
+++ b/modules/audio_coding/main/acm2/codec_manager.h
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_CODEC_MANAGER_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_CODEC_MANAGER_H_
+
+#include "webrtc/base/constructormagic.h"
+#include "webrtc/base/thread_checker.h"
+#include "webrtc/modules/audio_coding/main/acm2/acm_codec_database.h"
+#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
+#include "webrtc/common_types.h"
+
+namespace webrtc {
+
+class AudioDecoder;
+
+namespace acm2 {
+
+class ACMGenericCodec;
+class AudioCodingModuleImpl;
+
+class CodecManager final {
+ public:
+ explicit CodecManager(AudioCodingModuleImpl* acm);
+ ~CodecManager();
+
+ int RegisterSendCodec(const CodecInst& send_codec);
+
+ int SendCodec(CodecInst* current_codec) const;
+
+ int RegisterReceiveCodec(const CodecInst& receive_codec);
+
+ bool SetCopyRed(bool enable);
+
+ int SetVAD(bool enable_dtx, bool enable_vad, ACMVADMode mode);
+
+ void VAD(bool* dtx_enabled, bool* vad_enabled, ACMVADMode* mode) const;
+
+ int SetCodecFEC(bool enable_codec_fec);
+
+ bool stereo_send() const { return stereo_send_; }
+
+ bool red_enabled() const { return red_enabled_; }
+
+ bool codec_fec_enabled() const { return codec_fec_enabled_; }
+
+ ACMGenericCodec* current_encoder() { return current_encoder_; }
+
+ const ACMGenericCodec* current_encoder() const { return current_encoder_; }
+
+ private:
+ void SetCngPayloadType(int sample_rate_hz, int payload_type);
+
+ void SetRedPayloadType(int sample_rate_hz, int payload_type);
+
+ // Get a pointer to AudioDecoder of the given codec. For some codecs, e.g.
+ // iSAC, encoding and decoding have to be performed on a shared
+ // codec-instance. By calling this method, we get the codec-instance that ACM
+ // owns, then pass that to NetEq. This way, we perform both encoding and
+ // decoding on the same codec-instance. Furthermore, ACM would have control
+ // over decoder functionality if required. If |codec| does not share an
+ // instance between encoder and decoder, the |*decoder| is set NULL.
+ // The field ACMCodecDB::CodecSettings.owns_decoder indicates that if a
+ // codec owns the decoder-instance. For such codecs |*decoder| should be a
+ // valid pointer, otherwise it will be NULL.
+ int GetAudioDecoder(const CodecInst& codec,
+ int codec_id,
+ int mirror_id,
+ AudioDecoder** decoder);
+
+ AudioCodingModuleImpl* acm_;
+ rtc::ThreadChecker thread_checker_;
+ uint8_t cng_nb_pltype_;
+ uint8_t cng_wb_pltype_;
+ uint8_t cng_swb_pltype_;
+ uint8_t cng_fb_pltype_;
+ uint8_t red_nb_pltype_;
+ bool stereo_send_;
+ bool vad_enabled_;
+ bool dtx_enabled_;
+ ACMVADMode vad_mode_;
+ ACMGenericCodec* current_encoder_;
+ CodecInst send_codec_inst_;
+ bool red_enabled_;
+ bool codec_fec_enabled_;
+ ACMGenericCodec* codecs_[ACMCodecDB::kMaxNumCodecs];
+ int mirror_codec_idx_[ACMCodecDB::kMaxNumCodecs];
+
+ DISALLOW_COPY_AND_ASSIGN(CodecManager);
+};
+
+} // namespace acm2
+} // namespace webrtc
+#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_CODEC_MANAGER_H_
diff --git a/modules/audio_coding/main/interface/audio_coding_module.h b/modules/audio_coding/main/interface/audio_coding_module.h
index 014b9f3..796444e 100644
--- a/modules/audio_coding/main/interface/audio_coding_module.h
+++ b/modules/audio_coding/main/interface/audio_coding_module.h
@@ -191,20 +191,6 @@
//
///////////////////////////////////////////////////////////////////////////
- // int32_t InitializeSender()
- // Any encoder-related state of ACM will be initialized to the
- // same state when ACM is created. This will not interrupt or
- // effect decoding functionality of ACM. ACM will lose all the
- // encoding-related settings by calling this function.
- // For instance, a send codec has to be registered again.
- //
- // Return value:
- // -1 if failed to initialize,
- // 0 if succeeded.
- //
- virtual int32_t InitializeSender() = 0;
-
- ///////////////////////////////////////////////////////////////////////////
// int32_t ResetEncoder()
// This API resets the states of encoder. All the encoder settings, such as
// send-codec or VAD/DTX, will be preserved.
diff --git a/modules/audio_coding/main/test/APITest.cc b/modules/audio_coding/main/test/APITest.cc
index ccb5c59..1cdf6c7 100644
--- a/modules/audio_coding/main/test/APITest.cc
+++ b/modules/audio_coding/main/test/APITest.cc
@@ -1144,9 +1144,6 @@
WriteLockScoped wl(_apiTestRWLock);
*thereIsEncoder = false;
}
- CHECK_ERROR_MT(myACM->InitializeSender());
- Wait(1000);
-
// After Initialization CN is lost, re-register them
if (AudioCodingModule::Codec("CN", &myCodec, 8000, 1) >= 0) {
CHECK_ERROR_MT(myACM->RegisterSendCodec(myCodec));
diff --git a/modules/audio_coding/main/test/EncodeDecodeTest.cc b/modules/audio_coding/main/test/EncodeDecodeTest.cc
index b785cc3..8394bc0 100644
--- a/modules/audio_coding/main/test/EncodeDecodeTest.cc
+++ b/modules/audio_coding/main/test/EncodeDecodeTest.cc
@@ -53,7 +53,6 @@
void Sender::Setup(AudioCodingModule *acm, RTPStream *rtpStream,
std::string in_file_name, int sample_rate, int channels) {
- acm->InitializeSender();
struct CodecInst sendCodec;
int noOfCodecs = acm->NumberOfCodecs();
int codecNo;
diff --git a/modules/audio_coding/main/test/TwoWayCommunication.cc b/modules/audio_coding/main/test/TwoWayCommunication.cc
index f4db1db..1014fc9 100644
--- a/modules/audio_coding/main/test/TwoWayCommunication.cc
+++ b/modules/audio_coding/main/test/TwoWayCommunication.cc
@@ -281,7 +281,6 @@
// In the middle of a session with data flowing between two sides, called A
// and B, APIs will be called, like ResetEncoder(), and the code should
// continue to run, and be able to recover.
- bool expect_error_add = false;
while (!_inFileA.EndOfFile() && !_inFileB.EndOfFile()) {
msecPassed += 10;
EXPECT_GT(_inFileA.Read10MsData(audioFrame), 0);
@@ -290,12 +289,7 @@
EXPECT_GT(_inFileB.Read10MsData(audioFrame), 0);
- // Expect call to pass except for the time when no send codec is registered.
- if (!expect_error_add) {
- EXPECT_GE(_acmB->Add10MsData(audioFrame), 0);
- } else {
- EXPECT_EQ(-1, _acmB->Add10MsData(audioFrame));
- }
+ EXPECT_GE(_acmB->Add10MsData(audioFrame), 0);
EXPECT_GE(_acmRefB->Add10MsData(audioFrame), 0);
EXPECT_EQ(0, _acmA->PlayoutData10Ms(outFreqHzA, &audioFrame));
_outFileA.Write10MsData(audioFrame);
@@ -315,14 +309,11 @@
// side B.
if (((secPassed % 5) == 4) && (msecPassed == 0)) {
EXPECT_EQ(0, _acmA->ResetEncoder());
- EXPECT_EQ(0, _acmB->InitializeSender());
- expect_error_add = true;
}
// Re-register send codec on side B.
if (((secPassed % 5) == 4) && (msecPassed >= 990)) {
EXPECT_EQ(0, _acmB->RegisterSendCodec(codecInst_B));
EXPECT_EQ(0, _acmB->SendCodec(&dummy));
- expect_error_add = false;
}
// Reset decoder on side B, and initialize receiver on side A.
if (((secPassed % 7) == 6) && (msecPassed == 0)) {