diff --git a/webrtc/modules/audio_coding/main/acm2/acm_codec_database.cc b/webrtc/modules/audio_coding/main/acm2/acm_codec_database.cc index 7710046d24..8a9a5de92e 100644 --- a/webrtc/modules/audio_coding/main/acm2/acm_codec_database.cc +++ b/webrtc/modules/audio_coding/main/acm2/acm_codec_database.cc @@ -227,7 +227,7 @@ enum { // Gets the codec id number from the database. If there is some mismatch in // the codec settings, the function will return an error code. // NOTE! The first mismatch found will generate the return value. -int ACMCodecDB::CodecNumber(const CodecInst& codec_inst, int* mirror_id) { +int ACMCodecDB::CodecNumber(const CodecInst& codec_inst) { // Look for a matching codec in the database. int codec_id = CodecId(codec_inst); @@ -243,13 +243,11 @@ int ACMCodecDB::CodecNumber(const CodecInst& codec_inst, int* mirror_id) { // Comfort Noise is special case, packet-size & rate is not checked. if (STR_CASE_CMP(database_[codec_id].plname, "CN") == 0) { - *mirror_id = codec_id; return codec_id; } // RED is special case, packet-size & rate is not checked. if (STR_CASE_CMP(database_[codec_id].plname, "red") == 0) { - *mirror_id = codec_id; return codec_id; } @@ -278,16 +276,8 @@ int ACMCodecDB::CodecNumber(const CodecInst& codec_inst, int* mirror_id) { // Check the validity of rate. Codecs with multiple rates have their own // function for this. - *mirror_id = codec_id; if (STR_CASE_CMP("isac", codec_inst.plname) == 0) { - if (IsISACRateValid(codec_inst.rate)) { - // Set mirrorID to iSAC WB which is only created once to be used both for - // iSAC WB and SWB, because they need to share struct. - *mirror_id = kISAC; - return codec_id; - } else { - return kInvalidRate; - } + return IsISACRateValid(codec_inst.rate) ? codec_id : kInvalidRate; } else if (STR_CASE_CMP("ilbc", codec_inst.plname) == 0) { return IsILBCRateValid(codec_inst.rate, codec_inst.pacsize) ? codec_id : kInvalidRate; @@ -350,22 +340,10 @@ int ACMCodecDB::CodecId(const char* payload_name, int frequency, int channels) { // We didn't find a matching codec. return -1; } -// Gets codec id number, and mirror id, from database for the receiver. -int ACMCodecDB::ReceiverCodecNumber(const CodecInst& codec_inst, - int* mirror_id) { +// Gets codec id number from database for the receiver. +int ACMCodecDB::ReceiverCodecNumber(const CodecInst& codec_inst) { // Look for a matching codec in the database. - int codec_id = CodecId(codec_inst); - - // Set |mirror_id| to |codec_id|, except for iSAC. In case of iSAC we always - // set |mirror_id| to iSAC WB (kISAC) which is only created once to be used - // both for iSAC WB and SWB, because they need to share struct. - if (STR_CASE_CMP(codec_inst.plname, "ISAC") != 0) { - *mirror_id = codec_id; - } else { - *mirror_id = kISAC; - } - - return codec_id; + return CodecId(codec_inst); } // Returns the codec sampling frequency for codec with id = "codec_id" in @@ -394,16 +372,6 @@ const NetEqDecoder* ACMCodecDB::NetEQDecoders() { return neteq_decoders_; } -// Gets mirror id. The Id is used for codecs sharing struct for settings that -// need different payload types. -int ACMCodecDB::MirrorID(int codec_id) { - if (STR_CASE_CMP(database_[codec_id].plname, "isac") == 0) { - return kISAC; - } else { - return codec_id; - } -} - // Creates memory/instance for storing codec state. ACMGenericCodec* ACMCodecDB::CreateCodecInstance(const CodecInst& codec_inst, int cng_pt_nb, diff --git a/webrtc/modules/audio_coding/main/acm2/acm_codec_database.h b/webrtc/modules/audio_coding/main/acm2/acm_codec_database.h index ea7eb23ac0..adfe5c74dd 100644 --- a/webrtc/modules/audio_coding/main/acm2/acm_codec_database.h +++ b/webrtc/modules/audio_coding/main/acm2/acm_codec_database.h @@ -166,36 +166,17 @@ class ACMCodecDB { // 0 if successful, otherwise -1. static int Codec(int codec_id, CodecInst* codec_inst); - // Returns codec id and mirror id from database, given the information - // received in the input [codec_inst]. Mirror id is a number that tells - // where to find the codec's memory (instance). The number is either the - // same as codec id (most common), or a number pointing at a different - // entry in the database, if the codec has several entries with different - // payload types. This is used for codecs that must share one struct even if - // the payload type differs. - // One example is the codec iSAC which has the same struct for both 16 and - // 32 khz, but they have different entries in the database. Let's say the - // function is called with iSAC 32kHz. The function will return 1 as that is - // the entry in the data base, and [mirror_id] = 0, as that is the entry for - // iSAC 16 kHz, which holds the shared memory. + // Returns codec id from database, given the information received in the input + // [codec_inst]. // Input: // [codec_inst] - Information about the codec for which we require the // database id. - // Output: - // [mirror_id] - mirror id, which most often is the same as the return - // value, see above. - // [err_message] - if present, in the event of a mismatch found between the - // input and the database, a descriptive error message is - // written here. - // [err_message] - if present, the length of error message is returned here. // Return: // codec id if successful, otherwise < 0. - static int CodecNumber(const CodecInst& codec_inst, int* mirror_id, - char* err_message, int max_message_len_byte); - static int CodecNumber(const CodecInst& codec_inst, int* mirror_id); + static int CodecNumber(const CodecInst& codec_inst); static int CodecId(const CodecInst& codec_inst); static int CodecId(const char* payload_name, int frequency, int channels); - static int ReceiverCodecNumber(const CodecInst& codec_inst, int* mirror_id); + static int ReceiverCodecNumber(const CodecInst& codec_inst); // Returns the codec sampling frequency for codec with id = "codec_id" in // database. @@ -221,19 +202,6 @@ class ACMCodecDB { // Returns the NetEQ decoder database. static const NetEqDecoder* NetEQDecoders(); - // Returns mirror id, which is a number that tells where to find the codec's - // memory (instance). It is either the same as codec id (most common), or a - // number pointing at a different entry in the database, if the codec have - // several entries with different payload types. This is used for codecs that - // must share struct even if the payload type differs. - // TODO(tlegrand): Check if function is needed, or if we can change - // to access database directly. - // Input: - // [codec_id] - number that specifies codec's position in the database. - // Return: - // Mirror id on success, otherwise -1. - static int MirrorID(int codec_id); - // Creates a codec wrapper containing an AudioEncoder object (or an // ACMGenericCodec subclass during the refactoring time). The type of // AudioEncoder is decided by looking at the information in |codec_inst|. diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module.cc b/webrtc/modules/audio_coding/main/acm2/audio_coding_module.cc index f1d7a5d1ca..fa6349139c 100644 --- a/webrtc/modules/audio_coding/main/acm2/audio_coding_module.cc +++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module.cc @@ -81,9 +81,7 @@ int AudioCodingModule::Codec(const char* payload_name, // Checks the validity of the parameters of the given codec bool AudioCodingModule::IsCodecValid(const CodecInst& codec) { - int mirror_id; - - int codec_number = acm2::ACMCodecDB::CodecNumber(codec, &mirror_id); + int codec_number = acm2::ACMCodecDB::CodecNumber(codec); if (codec_number < 0) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, -1, diff --git a/webrtc/modules/audio_coding/main/acm2/codec_manager.cc b/webrtc/modules/audio_coding/main/acm2/codec_manager.cc index c3e340e0e2..6e80be85bd 100644 --- a/webrtc/modules/audio_coding/main/acm2/codec_manager.cc +++ b/webrtc/modules/audio_coding/main/acm2/codec_manager.cc @@ -34,9 +34,7 @@ bool IsCodecCN(int 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 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, @@ -47,7 +45,7 @@ int IsValidSendCodec(const CodecInst& send_codec, return -1; } - int codec_id = ACMCodecDB::CodecNumber(send_codec, mirror_id); + 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."); @@ -68,7 +66,6 @@ int IsValidSendCodec(const CodecInst& 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; } @@ -77,7 +74,6 @@ int IsValidSendCodec(const CodecInst& send_codec, 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; } @@ -87,20 +83,22 @@ int IsValidSendCodec(const CodecInst& send_codec, 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; } +bool IsIsac(const CodecInst& codec) { + return !STR_CASE_CMP(codec.plname, "isac"); +} + const CodecInst kEmptyCodecInst = {-1, "noCodecRegistered", 0, 0, 0, 0}; } // namespace @@ -119,11 +117,6 @@ CodecManager::CodecManager(AudioCodingModuleImpl* acm) 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--) { @@ -144,25 +137,11 @@ CodecManager::CodecManager(AudioCodingModuleImpl* acm) 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; - } - } -} +CodecManager::~CodecManager() = default; int CodecManager::RegisterSendCodec(const CodecInst& send_codec) { DCHECK(thread_checker_.CalledOnValidThread()); - int mirror_id; - int codec_id = IsValidSendCodec(send_codec, true, &mirror_id); + int codec_id = IsValidSendCodec(send_codec, true); // Check for reported errors from function IsValidSendCodec(). if (codec_id < 0) { @@ -243,36 +222,31 @@ int CodecManager::RegisterSendCodec(const CodecInst& send_codec) { // 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); + int send_codec_id = ACMCodecDB::CodecNumber(send_codec_inst_); assert(send_codec_id >= 0); - is_send_codec = - (send_codec_id == codec_id) || (mirror_id == send_codec_mirror_id); + is_send_codec = send_codec_id == codec_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( + 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_); - if (!codecs_[mirror_id]) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id, - "Cannot Create the codec"); - return -1; + 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_)); } - mirror_codec_idx_[mirror_id] = mirror_id; + new_codec = isac_enc_dec_.get(); } + DCHECK(new_codec); - 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)); @@ -280,7 +254,7 @@ int CodecManager::RegisterSendCodec(const CodecInst& send_codec) { codec_params.enable_dtx = dtx_enabled_; codec_params.vad_mode = vad_mode_; // Force initialization. - if (codec_ptr->InitEncoder(&codec_params, true) < 0) { + if (new_codec->InitEncoder(&codec_params, true) < 0) { // Could not initialize the encoder. // Check if already have a registered codec. @@ -306,18 +280,18 @@ int CodecManager::RegisterSendCodec(const CodecInst& send_codec) { // If we change codec we start fresh with RED. // This is not strictly required by the standard. - if (codec_ptr->SetCopyRed(red_enabled_) < 0) { + 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_; } - codec_ptr->SetVAD(&dtx_enabled_, &vad_enabled_, &vad_mode_); + new_codec->SetVAD(&dtx_enabled_, &vad_enabled_, &vad_mode_); - if (!codec_ptr->HasInternalFEC()) { + if (!new_codec->HasInternalFEC()) { codec_fec_enabled_ = false; } else { - if (codec_ptr->SetFEC(codec_fec_enabled_) < 0) { + if (new_codec->SetFEC(codec_fec_enabled_) < 0) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id, "Cannot set codec FEC"); return -1; @@ -325,7 +299,7 @@ int CodecManager::RegisterSendCodec(const CodecInst& send_codec) { } } - current_encoder_ = codecs_[codec_id]; + current_encoder_ = new_codec; DCHECK(current_encoder_); memcpy(&send_codec_inst_, &send_codec, sizeof(CodecInst)); return 0; @@ -335,11 +309,6 @@ int CodecManager::RegisterSendCodec(const CodecInst& send_codec) { // 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. @@ -396,7 +365,7 @@ int CodecManager::RegisterSendCodec(const CodecInst& send_codec) { // 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) { + if (current_encoder_->SetBitRate(send_codec.rate) < 0) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id, "Could not change the codec rate."); return -1; @@ -404,10 +373,10 @@ int CodecManager::RegisterSendCodec(const CodecInst& send_codec) { send_codec_inst_.rate = send_codec.rate; } - if (!codecs_[codec_id]->HasInternalFEC()) { + if (!current_encoder_->HasInternalFEC()) { codec_fec_enabled_ = false; } else { - if (codecs_[codec_id]->SetFEC(codec_fec_enabled_) < 0) { + if (current_encoder_->SetFEC(codec_fec_enabled_) < 0) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, dummy_id, "Cannot set codec FEC"); return -1; @@ -445,8 +414,7 @@ int CodecManager::RegisterReceiveCodec(const CodecInst& codec) { return -1; } - int mirror_id; - int codec_id = ACMCodecDB::ReceiverCodecNumber(codec, &mirror_id); + int codec_id = ACMCodecDB::ReceiverCodecNumber(codec); if (codec_id < 0 || codec_id >= ACMCodecDB::kNumCodecs) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 0, @@ -464,7 +432,7 @@ int CodecManager::RegisterReceiveCodec(const CodecInst& codec) { 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) { + 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; @@ -554,57 +522,43 @@ int CodecManager::SetCodecFEC(bool enable_codec_fec) { } void CodecManager::SetCngPayloadType(int sample_rate_hz, int payload_type) { - for (auto* codec : codecs_) { - if (codec) { - codec->SetCngPt(sample_rate_hz, 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) { - for (auto* codec : codecs_) { - if (codec) { - codec->SetRedPt(sample_rate_hz, 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, - 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; + 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; } diff --git a/webrtc/modules/audio_coding/main/acm2/codec_manager.h b/webrtc/modules/audio_coding/main/acm2/codec_manager.h index 8d5350d71e..3146467b75 100644 --- a/webrtc/modules/audio_coding/main/acm2/codec_manager.h +++ b/webrtc/modules/audio_coding/main/acm2/codec_manager.h @@ -72,7 +72,6 @@ class CodecManager final { // valid pointer, otherwise it will be NULL. int GetAudioDecoder(const CodecInst& codec, int codec_id, - int mirror_id, AudioDecoder** decoder); AudioCodingModuleImpl* acm_; @@ -90,8 +89,8 @@ class CodecManager final { CodecInst send_codec_inst_; bool red_enabled_; bool codec_fec_enabled_; - ACMGenericCodec* codecs_[ACMCodecDB::kMaxNumCodecs]; - int mirror_codec_idx_[ACMCodecDB::kMaxNumCodecs]; + rtc::scoped_ptr isac_enc_dec_; + rtc::scoped_ptr encoder_; DISALLOW_COPY_AND_ASSIGN(CodecManager); };