From 829a6f4ac20a712a004746e4245086ac622f55df Mon Sep 17 00:00:00 2001 From: "henrik.lundin@webrtc.org" Date: Mon, 23 Feb 2015 16:33:05 +0000 Subject: [PATCH] Merge ACMGenericCodec and ACMGenericCodecWrapper ACMGenericCodecWrapper was the only remaining subclass of ACMGenericCodec, and was the only class that was ever instantiated. This CL merges the two, essentially keeping the function implementations from ACMGenericCodecWrapper except where the base class's code was invoked. As it turns out, a lot of functions were never used, but in some cases they were refernced in AudioCodingModuleImpl. In these cases, the referencing code is commented out and marked FATAL(). This will be further cleaned up in follow-up CLs. BUG=4228 COAUTHOR=kwiberg@webrtc.org R=minyue@webrtc.org Review URL: https://webrtc-codereview.appspot.com/38209004 Cr-Commit-Position: refs/heads/master@{#8463} git-svn-id: http://webrtc.googlecode.com/svn/trunk@8463 4adac7df-926f-26a2-2b94-8c16560cd09d --- .../main/acm2/acm_codec_database.cc | 30 +- .../main/acm2/acm_generic_codec.cc | 1171 +---------------- .../main/acm2/acm_generic_codec.h | 683 ++-------- .../main/acm2/acm_generic_codec_opus_test.cc | 4 +- .../main/acm2/audio_coding_module_impl.cc | 60 +- 5 files changed, 192 insertions(+), 1756 deletions(-) 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 bce8e5cc0d..6e003615df 100644 --- a/webrtc/modules/audio_coding/main/acm2/acm_codec_database.cc +++ b/webrtc/modules/audio_coding/main/acm2/acm_codec_database.cc @@ -415,38 +415,32 @@ ACMGenericCodec* ACMCodecDB::CreateCodecInstance(const CodecInst& codec_inst, // All we have support for right now. if (!STR_CASE_CMP(codec_inst.plname, "ISAC")) { #if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)) - return new ACMGenericCodecWrapper(codec_inst, cng_pt_nb, cng_pt_wb, - cng_pt_swb, cng_pt_fb, enable_red, - red_payload_type); + return new ACMGenericCodec(codec_inst, cng_pt_nb, cng_pt_wb, cng_pt_swb, + cng_pt_fb, enable_red, red_payload_type); #endif } else if (!STR_CASE_CMP(codec_inst.plname, "PCMU") || !STR_CASE_CMP(codec_inst.plname, "PCMA")) { - return new ACMGenericCodecWrapper(codec_inst, cng_pt_nb, cng_pt_wb, - cng_pt_swb, cng_pt_fb, enable_red, - red_payload_type); + return new ACMGenericCodec(codec_inst, cng_pt_nb, cng_pt_wb, cng_pt_swb, + cng_pt_fb, enable_red, red_payload_type); } else if (!STR_CASE_CMP(codec_inst.plname, "ILBC")) { #ifdef WEBRTC_CODEC_ILBC - return new ACMGenericCodecWrapper(codec_inst, cng_pt_nb, cng_pt_wb, - cng_pt_swb, cng_pt_fb, enable_red, - red_payload_type); + return new ACMGenericCodec(codec_inst, cng_pt_nb, cng_pt_wb, cng_pt_swb, + cng_pt_fb, enable_red, red_payload_type); #endif } else if (!STR_CASE_CMP(codec_inst.plname, "G722")) { #ifdef WEBRTC_CODEC_G722 - return new ACMGenericCodecWrapper(codec_inst, cng_pt_nb, cng_pt_wb, - cng_pt_swb, cng_pt_fb, enable_red, - red_payload_type); + return new ACMGenericCodec(codec_inst, cng_pt_nb, cng_pt_wb, cng_pt_swb, + cng_pt_fb, enable_red, red_payload_type); #endif } else if (!STR_CASE_CMP(codec_inst.plname, "opus")) { #ifdef WEBRTC_CODEC_OPUS - return new ACMGenericCodecWrapper(codec_inst, cng_pt_nb, cng_pt_wb, - cng_pt_swb, cng_pt_fb, enable_red, - red_payload_type); + return new ACMGenericCodec(codec_inst, cng_pt_nb, cng_pt_wb, cng_pt_swb, + cng_pt_fb, enable_red, red_payload_type); #endif } else if (!STR_CASE_CMP(codec_inst.plname, "L16")) { #ifdef WEBRTC_CODEC_PCM16 - return new ACMGenericCodecWrapper(codec_inst, cng_pt_nb, cng_pt_wb, - cng_pt_swb, cng_pt_fb, enable_red, - red_payload_type); + return new ACMGenericCodec(codec_inst, cng_pt_nb, cng_pt_wb, cng_pt_swb, + cng_pt_fb, enable_red, red_payload_type); #endif } return NULL; diff --git a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc index 6dd6f3edd5..6925d2a974 100644 --- a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc +++ b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc @@ -96,7 +96,13 @@ enum { // We set some of the variables to invalid values as a check point // if a proper initialization has happened. Another approach is // to initialize to a default codec that we are sure is always included. -ACMGenericCodec::ACMGenericCodec(bool enable_red) +ACMGenericCodec::ACMGenericCodec(const CodecInst& codec_inst, + int cng_pt_nb, + int cng_pt_wb, + int cng_pt_swb, + int cng_pt_fb, + bool enable_red, + int red_payload_type) : in_audio_ix_write_(0), in_audio_ix_read_(0), in_timestamp_ix_write_(0), @@ -122,7 +128,19 @@ ACMGenericCodec::ACMGenericCodec(bool enable_red) copy_red_enabled_(enable_red), codec_wrapper_lock_(*RWLockWrapper::CreateRWLock()), last_timestamp_(0xD87F3F9F), - unique_id_(0) { + unique_id_(0), + encoder_(NULL), + bitrate_bps_(0), + fec_enabled_(false), + loss_rate_(0), + max_playback_rate_hz_(48000), + max_payload_size_bytes_(-1), + max_rate_bps_(-1), + is_opus_(false), + is_isac_(false), + first_frame_(true), + red_payload_type_(red_payload_type), + opus_application_set_(false) { // Initialize VAD vector. for (int i = 0; i < MAX_FRAME_SIZE_10MSEC; i++) { vad_label_[i] = 0; @@ -131,6 +149,17 @@ ACMGenericCodec::ACMGenericCodec(bool enable_red) // invalid value. memset(&encoder_params_, 0, sizeof(WebRtcACMCodecParams)); encoder_params_.codec_inst.pltype = -1; + + acm_codec_params_.codec_inst = codec_inst; + acm_codec_params_.enable_dtx = false; + acm_codec_params_.enable_vad = false; + acm_codec_params_.vad_mode = VADNormal; + SetCngPtInMap(&cng_pt_, 8000, cng_pt_nb); + SetCngPtInMap(&cng_pt_, 16000, cng_pt_wb); + SetCngPtInMap(&cng_pt_, 32000, cng_pt_swb); + SetCngPtInMap(&cng_pt_, 48000, cng_pt_fb); + ResetAudioEncoder(); + CHECK(encoder_); } ACMGenericCodec::~ACMGenericCodec() { @@ -155,936 +184,6 @@ ACMGenericCodec::~ACMGenericCodec() { delete &codec_wrapper_lock_; } -int32_t ACMGenericCodec::Add10MsData(const uint32_t timestamp, - const int16_t* data, - const uint16_t length_smpl, - const uint8_t audio_channel) { - WriteLockScoped wl(codec_wrapper_lock_); - return Add10MsDataSafe(timestamp, data, length_smpl, audio_channel); -} - -int32_t ACMGenericCodec::Add10MsDataSafe(const uint32_t timestamp, - const int16_t* data, - const uint16_t length_smpl, - const uint8_t audio_channel) { - // The codec expects to get data in correct sampling rate. Get the sampling - // frequency of the codec. - uint16_t plfreq_hz; - if (EncoderSampFreq(&plfreq_hz) < 0) { - return -1; - } - - // Sanity check to make sure the length of the input corresponds to 10 ms. - if ((plfreq_hz / 100) != length_smpl) { - // This is not 10 ms of audio, given the sampling frequency of the codec. - return -1; - } - - if (last_timestamp_ == timestamp) { - // Same timestamp as the last time, overwrite. - if ((in_audio_ix_write_ >= length_smpl * audio_channel) && - (in_timestamp_ix_write_ > 0)) { - in_audio_ix_write_ -= length_smpl * audio_channel; - assert(in_timestamp_ix_write_ >= 0); - - in_timestamp_ix_write_--; - assert(in_audio_ix_write_ >= 0); - WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceAudioCoding, unique_id_, - "Adding 10ms with previous timestamp, overwriting the " - "previous 10ms"); - } else { - WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceAudioCoding, unique_id_, - "Adding 10ms with previous timestamp, this will sound bad"); - } - } - - last_timestamp_ = timestamp; - - // If the data exceeds the buffer size, we throw away the oldest data and - // add the newly received 10 msec at the end. - if ((in_audio_ix_write_ + length_smpl * audio_channel) > - AUDIO_BUFFER_SIZE_W16) { - // Get the number of samples to be overwritten. - int16_t missed_samples = in_audio_ix_write_ + length_smpl * audio_channel - - AUDIO_BUFFER_SIZE_W16; - - // Move the data (overwrite the old data). - memmove(in_audio_, in_audio_ + missed_samples, - (AUDIO_BUFFER_SIZE_W16 - length_smpl * audio_channel) * - sizeof(int16_t)); - - // Copy the new data. - memcpy(in_audio_ + (AUDIO_BUFFER_SIZE_W16 - length_smpl * audio_channel), - data, length_smpl * audio_channel * sizeof(int16_t)); - - // Get the number of 10 ms blocks which are overwritten. - int16_t missed_10ms_blocks =static_cast( - (missed_samples / audio_channel * 100) / plfreq_hz); - - // Move the timestamps. - memmove(in_timestamp_, in_timestamp_ + missed_10ms_blocks, - (in_timestamp_ix_write_ - missed_10ms_blocks) * sizeof(uint32_t)); - in_timestamp_ix_write_ -= missed_10ms_blocks; - assert(in_timestamp_ix_write_ >= 0); - - in_timestamp_[in_timestamp_ix_write_] = timestamp; - in_timestamp_ix_write_++; - assert(in_timestamp_ix_write_ < TIMESTAMP_BUFFER_SIZE_W32); - - // Buffer is full. - in_audio_ix_write_ = AUDIO_BUFFER_SIZE_W16; - IncreaseNoMissedSamples(missed_samples); - return -missed_samples; - } - - // Store the input data in our data buffer. - memcpy(in_audio_ + in_audio_ix_write_, data, - length_smpl * audio_channel * sizeof(int16_t)); - in_audio_ix_write_ += length_smpl * audio_channel; - assert(in_timestamp_ix_write_ < TIMESTAMP_BUFFER_SIZE_W32); - - in_timestamp_[in_timestamp_ix_write_] = timestamp; - in_timestamp_ix_write_++; - assert(in_timestamp_ix_write_ < TIMESTAMP_BUFFER_SIZE_W32); - return 0; -} - -bool ACMGenericCodec::HasFrameToEncode() const { - ReadLockScoped lockCodec(codec_wrapper_lock_); - if (in_audio_ix_write_ < frame_len_smpl_ * num_channels_) - return false; - return true; -} - -int ACMGenericCodec::SetFEC(bool enable_fec) { - if (!HasInternalFEC() && enable_fec) - return -1; - return 0; -} - -void ACMGenericCodec::EnableCopyRed(bool enable, int /*red_payload_type*/) { - WriteLockScoped lockCodec(codec_wrapper_lock_); - copy_red_enabled_ = enable; -} - -bool ACMGenericCodec::ExternalRedNeeded() { - ReadLockScoped lockCodec(codec_wrapper_lock_); - return copy_red_enabled_; -} - -int16_t ACMGenericCodec::Encode(uint8_t* bitstream, - int16_t* bitstream_len_byte, - uint32_t* timestamp, - WebRtcACMEncodingType* encoding_type, - AudioEncoder::EncodedInfo* /*encoded_info*/) { - if (!HasFrameToEncode()) { - // There is not enough audio - *timestamp = 0; - *bitstream_len_byte = 0; - // Doesn't really matter what this parameter set to - *encoding_type = kNoEncoding; - return 0; - } - WriteLockScoped lockCodec(codec_wrapper_lock_); - - // Not all codecs accept the whole frame to be pushed into encoder at once. - // Some codecs needs to be feed with a specific number of samples different - // from the frame size. If this is the case, |myBasicCodingBlockSmpl| will - // report a number different from 0, and we will loop over calls to encoder - // further down, until we have encode a complete frame. - const int16_t my_basic_coding_block_smpl = - ACMCodecDB::BasicCodingBlock(codec_id_); - if (my_basic_coding_block_smpl < 0 || !encoder_initialized_ || - !encoder_exist_) { - // This should not happen, but in case it does, report no encoding done. - *timestamp = 0; - *bitstream_len_byte = 0; - *encoding_type = kNoEncoding; - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, - "EncodeSafe: error, basic coding sample block is negative"); - return -1; - } - // This makes the internal encoder read from the beginning of the buffer. - in_audio_ix_read_ = 0; - *timestamp = in_timestamp_[0]; - - // Process the audio through VAD. The function will set |_vad_labels|. - // If VAD is disabled all entries in |_vad_labels| are set to ONE (active). - int16_t status = 0; - int16_t dtx_processed_samples = 0; - status = ProcessFrameVADDTX(bitstream, bitstream_len_byte, - &dtx_processed_samples); - if (status < 0) { - *timestamp = 0; - *bitstream_len_byte = 0; - *encoding_type = kNoEncoding; - } else { - if (dtx_processed_samples > 0) { - // Dtx have processed some samples, and even if a bit-stream is generated - // we should not do any encoding (normally there won't be enough data). - - // Setting the following makes sure that the move of audio data and - // timestamps done correctly. - in_audio_ix_read_ = dtx_processed_samples; - // This will let the owner of ACMGenericCodec to know that the - // generated bit-stream is DTX to use correct payload type. - uint16_t samp_freq_hz; - EncoderSampFreq(&samp_freq_hz); - if (samp_freq_hz == 8000) { - *encoding_type = kPassiveDTXNB; - } else if (samp_freq_hz == 16000) { - *encoding_type = kPassiveDTXWB; - } else if (samp_freq_hz == 32000) { - *encoding_type = kPassiveDTXSWB; - } else if (samp_freq_hz == 48000) { - *encoding_type = kPassiveDTXFB; - } else { - status = -1; - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, - "EncodeSafe: Wrong sampling frequency for DTX."); - } - - // Transport empty frame if we have an empty bitstream. - if ((*bitstream_len_byte == 0) && - (sent_cn_previous_ || - ((in_audio_ix_write_ - in_audio_ix_read_) <= 0))) { - // Makes sure we transmit an empty frame. - *bitstream_len_byte = 1; - *encoding_type = kNoEncoding; - } - sent_cn_previous_ = true; - } else { - // We should encode the audio frame. Either VAD and/or DTX is off, or the - // audio was considered "active". - - sent_cn_previous_ = false; - if (my_basic_coding_block_smpl == 0) { - // This codec can handle all allowed frame sizes as basic coding block. - status = InternalEncode(bitstream, bitstream_len_byte); - if (status < 0) { - // TODO(tlegrand): Maybe reseting the encoder to be fresh for the next - // frame. - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, - unique_id_, "EncodeSafe: error in internal_encode"); - *bitstream_len_byte = 0; - *encoding_type = kNoEncoding; - } - } else { - // A basic-coding-block for this codec is defined so we loop over the - // audio with the steps of the basic-coding-block. - int16_t tmp_bitstream_len_byte; - - // Reset the variables which will be incremented in the loop. - *bitstream_len_byte = 0; - bool done = false; - while (!done) { - status = InternalEncode(&bitstream[*bitstream_len_byte], - &tmp_bitstream_len_byte); - *bitstream_len_byte += tmp_bitstream_len_byte; - - // Guard Against errors and too large payloads. - if ((status < 0) || (*bitstream_len_byte > MAX_PAYLOAD_SIZE_BYTE)) { - // Error has happened, and even if we are in the middle of a full - // frame we have to exit. Before exiting, whatever bits are in the - // buffer are probably corrupted, so we ignore them. - *bitstream_len_byte = 0; - *encoding_type = kNoEncoding; - // We might have come here because of the second condition. - status = -1; - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, - unique_id_, "EncodeSafe: error in InternalEncode"); - // break from the loop - break; - } - done = in_audio_ix_read_ >= frame_len_smpl_ * num_channels_; - } - } - if (status >= 0) { - *encoding_type = (vad_label_[0] == 1) ? kActiveNormalEncoded : - kPassiveNormalEncoded; - // Transport empty frame if we have an empty bitstream. - if ((*bitstream_len_byte == 0) && - ((in_audio_ix_write_ - in_audio_ix_read_) <= 0)) { - // Makes sure we transmit an empty frame. - *bitstream_len_byte = 1; - *encoding_type = kNoEncoding; - } - } - } - } - - // Move the timestamp buffer according to the number of 10 ms blocks - // which are read. - uint16_t samp_freq_hz; - EncoderSampFreq(&samp_freq_hz); - int16_t num_10ms_blocks = static_cast( - (in_audio_ix_read_ / num_channels_ * 100) / samp_freq_hz); - if (in_timestamp_ix_write_ > num_10ms_blocks) { - memmove(in_timestamp_, in_timestamp_ + num_10ms_blocks, - (in_timestamp_ix_write_ - num_10ms_blocks) * sizeof(int32_t)); - } - in_timestamp_ix_write_ -= num_10ms_blocks; - assert(in_timestamp_ix_write_ >= 0); - - // Remove encoded audio and move next audio to be encoded to the beginning - // of the buffer. Accordingly, adjust the read and write indices. - if (in_audio_ix_read_ < in_audio_ix_write_) { - memmove(in_audio_, &in_audio_[in_audio_ix_read_], - (in_audio_ix_write_ - in_audio_ix_read_) * sizeof(int16_t)); - } - in_audio_ix_write_ -= in_audio_ix_read_; - in_audio_ix_read_ = 0; - return (status < 0) ? (-1) : (*bitstream_len_byte); -} - -bool ACMGenericCodec::EncoderInitialized() { - ReadLockScoped rl(codec_wrapper_lock_); - return encoder_initialized_; -} - -int16_t ACMGenericCodec::EncoderParams(WebRtcACMCodecParams* enc_params) { - ReadLockScoped rl(codec_wrapper_lock_); - return EncoderParamsSafe(enc_params); -} - -int16_t ACMGenericCodec::EncoderParamsSafe(WebRtcACMCodecParams* enc_params) { - // Codec parameters are valid only if the encoder is initialized. - if (encoder_initialized_) { - int32_t current_rate; - memcpy(enc_params, &encoder_params_, sizeof(WebRtcACMCodecParams)); - current_rate = enc_params->codec_inst.rate; - CurrentRate(¤t_rate); - enc_params->codec_inst.rate = current_rate; - return 0; - } else { - enc_params->codec_inst.plname[0] = '\0'; - enc_params->codec_inst.pltype = -1; - enc_params->codec_inst.pacsize = 0; - enc_params->codec_inst.rate = 0; - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, - "EncoderParamsSafe: error, encoder not initialized"); - return -1; - } -} - -int16_t ACMGenericCodec::ResetEncoder() { - WriteLockScoped lockCodec(codec_wrapper_lock_); - return ResetEncoderSafe(); -} - -int16_t ACMGenericCodec::ResetEncoderSafe() { - if (!encoder_exist_ || !encoder_initialized_) { - // We don't reset if encoder doesn't exists or isn't initialized yet. - return 0; - } - - in_audio_ix_write_ = 0; - in_audio_ix_read_ = 0; - in_timestamp_ix_write_ = 0; - num_missed_samples_ = 0; - memset(in_audio_, 0, AUDIO_BUFFER_SIZE_W16 * sizeof(int16_t)); - memset(in_timestamp_, 0, TIMESTAMP_BUFFER_SIZE_W32 * sizeof(int32_t)); - - // Store DTX/VAD parameters. - bool enable_vad = vad_enabled_; - bool enable_dtx = dtx_enabled_; - ACMVADMode mode = vad_mode_; - - // Reset the encoder. - if (InternalResetEncoder() < 0) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, - "ResetEncoderSafe: error in reset encoder"); - return -1; - } - - // Disable DTX & VAD to delete the states and have a fresh start. - DisableDTX(); - DisableVAD(); - - // Set DTX/VAD. - int status = SetVADSafe(&enable_dtx, &enable_vad, &mode); - dtx_enabled_ = enable_dtx; - vad_enabled_ = enable_vad; - vad_mode_ = mode; - return status; -} - -int16_t ACMGenericCodec::InternalResetEncoder() { - // Call the codecs internal encoder initialization/reset function. - return InternalInitEncoder(&encoder_params_); -} - -int16_t ACMGenericCodec::InitEncoder(WebRtcACMCodecParams* codec_params, - bool force_initialization) { - WriteLockScoped lockCodec(codec_wrapper_lock_); - return InitEncoderSafe(codec_params, force_initialization); -} - -int16_t ACMGenericCodec::InitEncoderSafe(WebRtcACMCodecParams* codec_params, - bool force_initialization) { - // Check if we got a valid set of parameters. - int mirrorID; - int codec_number = ACMCodecDB::CodecNumber(codec_params->codec_inst, - &mirrorID); - assert(codec_number >= 0); - - // Check if the parameters are for this codec. - if ((codec_id_ >= 0) && (codec_id_ != codec_number) && - (codec_id_ != mirrorID)) { - // The current codec is not the same as the one given by codec_params. - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, - "InitEncoderSafe: current codec is not the same as the one " - "given by codec_params"); - return -1; - } - - if (encoder_initialized_ && !force_initialization) { - // The encoder is already initialized, and we don't want to force - // initialization. - return 0; - } - int16_t status; - if (!encoder_exist_) { - // New encoder, start with creating. - encoder_initialized_ = false; - status = CreateEncoder(); - if (status < 0) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, - "InitEncoderSafe: cannot create encoder"); - return -1; - } else { - encoder_exist_ = true; - } - } - frame_len_smpl_ = codec_params->codec_inst.pacsize; - num_channels_ = codec_params->codec_inst.channels; - status = InternalInitEncoder(codec_params); - if (status < 0) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, - "InitEncoderSafe: error in init encoder"); - encoder_initialized_ = false; - return -1; - } else { - // TODO(turajs): Move these allocations to the constructor issue 2445. - // Store encoder parameters. - memcpy(&encoder_params_, codec_params, sizeof(WebRtcACMCodecParams)); - encoder_initialized_ = true; - if (in_audio_ == NULL) { - in_audio_ = new int16_t[AUDIO_BUFFER_SIZE_W16]; - } - if (in_timestamp_ == NULL) { - in_timestamp_ = new uint32_t[TIMESTAMP_BUFFER_SIZE_W32]; - } - } - - // Fresh start of audio buffer. - memset(in_audio_, 0, sizeof(*in_audio_) * AUDIO_BUFFER_SIZE_W16); - memset(in_timestamp_, 0, sizeof(*in_timestamp_) * TIMESTAMP_BUFFER_SIZE_W32); - in_audio_ix_write_ = 0; - in_audio_ix_read_ = 0; - in_timestamp_ix_write_ = 0; - - return SetVADSafe(&codec_params->enable_dtx, &codec_params->enable_vad, - &codec_params->vad_mode); -} - -void ACMGenericCodec::ResetNoMissedSamples() { - WriteLockScoped cs(codec_wrapper_lock_); - num_missed_samples_ = 0; -} - -void ACMGenericCodec::IncreaseNoMissedSamples(const int16_t num_samples) { - num_missed_samples_ += num_samples; -} - -// Get the number of missed samples, this can be public. -uint32_t ACMGenericCodec::NoMissedSamples() const { - ReadLockScoped cs(codec_wrapper_lock_); - return num_missed_samples_; -} - -void ACMGenericCodec::DestructEncoder() { - WriteLockScoped wl(codec_wrapper_lock_); - - // Disable VAD and delete the instance. - if (ptr_vad_inst_ != NULL) { - WebRtcVad_Free(ptr_vad_inst_); - ptr_vad_inst_ = NULL; - } - vad_enabled_ = false; - vad_mode_ = VADNormal; - - // Disable DTX and delete the instance. - dtx_enabled_ = false; - if (ptr_dtx_inst_ != NULL) { - WebRtcCng_FreeEnc(ptr_dtx_inst_); - ptr_dtx_inst_ = NULL; - } - num_lpc_params_ = kNewCNGNumLPCParams; - - DestructEncoderSafe(); -} - -int16_t ACMGenericCodec::SetBitRate(const int32_t bitrate_bps) { - WriteLockScoped wl(codec_wrapper_lock_); - return SetBitRateSafe(bitrate_bps); -} - -int16_t ACMGenericCodec::SetBitRateSafe(const int32_t bitrate_bps) { - // If the codec can change the bit-rate this function is overloaded. - // Otherwise the only acceptable value is the one that is in the database. - CodecInst codec_params; - if (ACMCodecDB::Codec(codec_id_, &codec_params) < 0) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, - "SetBitRateSafe: error in ACMCodecDB::Codec"); - return -1; - } - if (codec_params.rate != bitrate_bps) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, - "SetBitRateSafe: rate value is not acceptable"); - return -1; - } else { - return 0; - } -} - -// iSAC specific functions: -int32_t ACMGenericCodec::GetEstimatedBandwidth() { - WriteLockScoped wl(codec_wrapper_lock_); - return GetEstimatedBandwidthSafe(); -} - -int32_t ACMGenericCodec::GetEstimatedBandwidthSafe() { - // All codecs but iSAC will return -1. - return -1; -} - -int32_t ACMGenericCodec::SetEstimatedBandwidth(int32_t estimated_bandwidth) { - WriteLockScoped wl(codec_wrapper_lock_); - return SetEstimatedBandwidthSafe(estimated_bandwidth); -} - -int32_t ACMGenericCodec::SetEstimatedBandwidthSafe( - int32_t /*estimated_bandwidth*/) { - // All codecs but iSAC will return -1. - return -1; -} -// End of iSAC specific functions. - -int32_t ACMGenericCodec::GetRedPayload(uint8_t* red_payload, - int16_t* payload_bytes) { - WriteLockScoped wl(codec_wrapper_lock_); - return GetRedPayloadSafe(red_payload, payload_bytes); -} - -int32_t ACMGenericCodec::GetRedPayloadSafe(uint8_t* /* red_payload */, - int16_t* /* payload_bytes */) { - return -1; // Do nothing by default. -} - -int16_t ACMGenericCodec::CreateEncoder() { - int16_t status = 0; - if (!encoder_exist_) { - status = InternalCreateEncoder(); - // We just created the codec and obviously it is not initialized. - encoder_initialized_ = false; - } - if (status < 0) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, - "CreateEncoder: error in internal create encoder"); - encoder_exist_ = false; - } else { - encoder_exist_ = true; - } - return status; -} - -uint32_t ACMGenericCodec::EarliestTimestamp() const { - ReadLockScoped cs(codec_wrapper_lock_); - return in_timestamp_[0]; -} - -int16_t ACMGenericCodec::SetVAD(bool* enable_dtx, - bool* enable_vad, - ACMVADMode* mode) { - WriteLockScoped cs(codec_wrapper_lock_); - return SetVADSafe(enable_dtx, enable_vad, mode); -} - -void ACMGenericCodec::SetCngPt(int sample_rate_hz, int payload_type) { -} - -int16_t ACMGenericCodec::SetVADSafe(bool* enable_dtx, - bool* enable_vad, - ACMVADMode* mode) { - if (!STR_CASE_CMP(encoder_params_.codec_inst.plname, "OPUS") || - encoder_params_.codec_inst.channels == 2 ) { - // VAD/DTX is not supported for Opus (even if sending mono), or other - // stereo codecs. - DisableDTX(); - DisableVAD(); - *enable_dtx = false; - *enable_vad = false; - return 0; - } - - if (*enable_dtx) { - // Make G729 AnnexB a special case. - if (!STR_CASE_CMP(encoder_params_.codec_inst.plname, "G729") - && !has_internal_dtx_) { - if (ACMGenericCodec::EnableDTX() < 0) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, - "SetVADSafe: error in enable DTX"); - *enable_dtx = false; - *enable_vad = vad_enabled_; - return -1; - } - } else { - if (EnableDTX() < 0) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, - "SetVADSafe: error in enable DTX"); - *enable_dtx = false; - *enable_vad = vad_enabled_; - return -1; - } - } - - // If codec does not have internal DTX (normal case) enabling DTX requires - // an active VAD. '*enable_dtx == true' overwrites VAD status. - // If codec has internal DTX, practically we don't need WebRtc VAD, however, - // we let the user to turn it on if they need call-backs on silence. - if (!has_internal_dtx_) { - // DTX is enabled, and VAD will be activated. - *enable_vad = true; - } - } else { - // Make G729 AnnexB a special case. - if (!STR_CASE_CMP(encoder_params_.codec_inst.plname, "G729") - && !has_internal_dtx_) { - ACMGenericCodec::DisableDTX(); - *enable_dtx = false; - } else { - DisableDTX(); - *enable_dtx = false; - } - } - - int16_t status = (*enable_vad) ? EnableVAD(*mode) : DisableVAD(); - if (status < 0) { - // Failed to set VAD, disable DTX. - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, - "SetVADSafe: error in enable VAD"); - DisableDTX(); - *enable_dtx = false; - *enable_vad = false; - } - return status; -} - -int16_t ACMGenericCodec::EnableDTX() { - if (has_internal_dtx_) { - // We should not be here if we have internal DTX this function should be - // overloaded by the derived class in this case. - return -1; - } - if (!dtx_enabled_) { - if (WebRtcCng_CreateEnc(&ptr_dtx_inst_) < 0) { - ptr_dtx_inst_ = NULL; - return -1; - } - uint16_t freq_hz; - EncoderSampFreq(&freq_hz); - if (WebRtcCng_InitEnc(ptr_dtx_inst_, freq_hz, kCngSidIntervalMsec, - num_lpc_params_) < 0) { - // Couldn't initialize, has to return -1, and free the memory. - WebRtcCng_FreeEnc(ptr_dtx_inst_); - ptr_dtx_inst_ = NULL; - return -1; - } - dtx_enabled_ = true; - } - return 0; -} - -int16_t ACMGenericCodec::DisableDTX() { - if (has_internal_dtx_) { - // We should not be here if we have internal DTX this function should be - // overloaded by the derived class in this case. - return -1; - } - if (ptr_dtx_inst_ != NULL) { - WebRtcCng_FreeEnc(ptr_dtx_inst_); - ptr_dtx_inst_ = NULL; - } - dtx_enabled_ = false; - return 0; -} - -int16_t ACMGenericCodec::EnableVAD(ACMVADMode mode) { - if ((mode < VADNormal) || (mode > VADVeryAggr)) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, - "EnableVAD: error in VAD mode range"); - return -1; - } - - if (!vad_enabled_) { - if (WebRtcVad_Create(&ptr_vad_inst_) < 0) { - ptr_vad_inst_ = NULL; - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, - "EnableVAD: error in create VAD"); - return -1; - } - if (WebRtcVad_Init(ptr_vad_inst_) < 0) { - WebRtcVad_Free(ptr_vad_inst_); - ptr_vad_inst_ = NULL; - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, - "EnableVAD: error in init VAD"); - return -1; - } - } - - // Set the VAD mode to the given value. - if (WebRtcVad_set_mode(ptr_vad_inst_, mode) < 0) { - // We failed to set the mode and we have to return -1. If we already have a - // working VAD (vad_enabled_ == true) then we leave it to work. Otherwise, - // the following will be executed. - if (!vad_enabled_) { - // We just created the instance but cannot set the mode we have to free - // the memory. - WebRtcVad_Free(ptr_vad_inst_); - ptr_vad_inst_ = NULL; - } - WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceAudioCoding, unique_id_, - "EnableVAD: failed to set the VAD mode"); - return -1; - } - vad_mode_ = mode; - vad_enabled_ = true; - return 0; -} - -int16_t ACMGenericCodec::DisableVAD() { - if (ptr_vad_inst_ != NULL) { - WebRtcVad_Free(ptr_vad_inst_); - ptr_vad_inst_ = NULL; - } - vad_enabled_ = false; - return 0; -} - -int32_t ACMGenericCodec::ReplaceInternalDTX(const bool replace_internal_dtx) { - WriteLockScoped cs(codec_wrapper_lock_); - return ReplaceInternalDTXSafe(replace_internal_dtx); -} - -int32_t ACMGenericCodec::ReplaceInternalDTXSafe( - const bool /* replace_internal_dtx */) { - return -1; -} - -int32_t ACMGenericCodec::IsInternalDTXReplaced(bool* internal_dtx_replaced) { - WriteLockScoped cs(codec_wrapper_lock_); - return IsInternalDTXReplacedSafe(internal_dtx_replaced); -} - -int32_t ACMGenericCodec::IsInternalDTXReplacedSafe( - bool* internal_dtx_replaced) { - *internal_dtx_replaced = true; - return 0; -} - -int16_t ACMGenericCodec::ProcessFrameVADDTX(uint8_t* bitstream, - int16_t* bitstream_len_byte, - int16_t* samples_processed) { - if (!vad_enabled_) { - // VAD not enabled, set all |vad_lable_[]| to 1 (speech detected). - for (int n = 0; n < MAX_FRAME_SIZE_10MSEC; n++) { - vad_label_[n] = 1; - } - *samples_processed = 0; - return 0; - } - - uint16_t freq_hz; - EncoderSampFreq(&freq_hz); - - // Calculate number of samples in 10 ms blocks, and number ms in one frame. - int16_t samples_in_10ms = static_cast(freq_hz / 100); - int32_t frame_len_ms = static_cast(frame_len_smpl_) * 1000 / freq_hz; - int16_t status = -1; - - // Vector for storing maximum 30 ms of mono audio at 48 kHz. - int16_t audio[1440]; - - // Calculate number of VAD-blocks to process, and number of samples in each - // block. - int num_samples_to_process[2]; - if (frame_len_ms == 40) { - // 20 ms in each VAD block. - num_samples_to_process[0] = num_samples_to_process[1] = 2 * samples_in_10ms; - } else { - // For 10-30 ms framesizes, second VAD block will be size zero ms, - // for 50 and 60 ms first VAD block will be 30 ms. - num_samples_to_process[0] = - (frame_len_ms > 30) ? 3 * samples_in_10ms : frame_len_smpl_; - num_samples_to_process[1] = frame_len_smpl_ - num_samples_to_process[0]; - } - - int offset = 0; - int loops = (num_samples_to_process[1] > 0) ? 2 : 1; - for (int i = 0; i < loops; i++) { - // TODO(turajs): Do we need to care about VAD together with stereo? - // If stereo, calculate mean of the two channels. - if (num_channels_ == 2) { - for (int j = 0; j < num_samples_to_process[i]; j++) { - audio[j] = (in_audio_[(offset + j) * 2] + - in_audio_[(offset + j) * 2 + 1]) / 2; - } - offset = num_samples_to_process[0]; - } else { - // Mono, copy data from in_audio_ to continue work on. - memcpy(audio, in_audio_, sizeof(int16_t) * num_samples_to_process[i]); - } - - // Call VAD. - status = static_cast(WebRtcVad_Process(ptr_vad_inst_, - static_cast(freq_hz), - audio, - num_samples_to_process[i])); - vad_label_[i] = status; - - if (status < 0) { - // This will force that the data be removed from the buffer. - *samples_processed += num_samples_to_process[i]; - return -1; - } - - // If VAD decision non-active, update DTX. NOTE! We only do this if the - // first part of a frame gets the VAD decision "inactive". Otherwise DTX - // might say it is time to transmit SID frame, but we will encode the whole - // frame, because the first part is active. - *samples_processed = 0; - if ((status == 0) && (i == 0) && dtx_enabled_ && !has_internal_dtx_) { - int16_t bitstream_len; - int num_10ms_frames = num_samples_to_process[i] / samples_in_10ms; - *bitstream_len_byte = 0; - for (int n = 0; n < num_10ms_frames; n++) { - // This block is (passive) && (vad enabled). If first CNG after - // speech, force SID by setting last parameter to "1". - status = WebRtcCng_Encode(ptr_dtx_inst_, &audio[n * samples_in_10ms], - samples_in_10ms, bitstream, &bitstream_len, - !prev_frame_cng_); - if (status < 0) { - return -1; - } - - // Update previous frame was CNG. - prev_frame_cng_ = 1; - - *samples_processed += samples_in_10ms * num_channels_; - - // |bitstream_len_byte| will only be > 0 once per 100 ms. - *bitstream_len_byte += bitstream_len; - } - - // Check if all samples got processed by the DTX. - if (*samples_processed != num_samples_to_process[i] * num_channels_) { - // Set to zero since something went wrong. Shouldn't happen. - *samples_processed = 0; - } - } else { - // Update previous frame was not CNG. - prev_frame_cng_ = 0; - } - - if (*samples_processed > 0) { - // The block contains inactive speech, and is processed by DTX. - // Discontinue running VAD. - break; - } - } - - return status; -} - -int16_t ACMGenericCodec::SamplesLeftToEncode() { - ReadLockScoped rl(codec_wrapper_lock_); - return (frame_len_smpl_ <= in_audio_ix_write_) ? 0 : - (frame_len_smpl_ - in_audio_ix_write_); -} - -void ACMGenericCodec::SetUniqueID(const uint32_t id) { - unique_id_ = id; -} - -// This function is replaced by codec specific functions for some codecs. -int16_t ACMGenericCodec::EncoderSampFreq(uint16_t* samp_freq_hz) { - int32_t f; - f = ACMCodecDB::CodecFreq(codec_id_); - if (f < 0) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, - "EncoderSampFreq: codec frequency is negative"); - return -1; - } else { - *samp_freq_hz = static_cast(f); - return 0; - } -} - -int32_t ACMGenericCodec::ConfigISACBandwidthEstimator( - const uint8_t /* init_frame_size_msec */, - const uint16_t /* init_rate_bit_per_sec */, - const bool /* enforce_frame_size */) { - WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_, - "The send-codec is not iSAC, failed to config iSAC bandwidth " - "estimator."); - return -1; -} - -int32_t ACMGenericCodec::SetISACMaxRate( - const uint32_t /* max_rate_bit_per_sec */) { - WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_, - "The send-codec is not iSAC, failed to set iSAC max rate."); - return -1; -} - -int32_t ACMGenericCodec::SetISACMaxPayloadSize( - const uint16_t /* max_payload_len_bytes */) { - WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_, - "The send-codec is not iSAC, failed to set iSAC max " - "payload-size."); - return -1; -} - -int16_t ACMGenericCodec::UpdateEncoderSampFreq( - uint16_t /* samp_freq_hz */) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, - "It is asked for a change in smapling frequency while the " - "current send-codec supports only one sampling rate."); - return -1; -} - -int16_t ACMGenericCodec::REDPayloadISAC(const int32_t /* isac_rate */, - const int16_t /* isac_bw_estimate */, - uint8_t* /* payload */, - int16_t* /* payload_len_bytes */) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_, - "Error: REDPayloadISAC is an iSAC specific function"); - return -1; -} - -int ACMGenericCodec::SetOpusApplication(OpusApplicationMode /*application*/) { - WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_, - "The send-codec is not Opus, failed to set application."); - return -1; -} - -int ACMGenericCodec::SetOpusMaxPlaybackRate(int /* frequency_hz */) { - WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_, - "The send-codec is not Opus, failed to set maximum playback rate."); - return -1; -} - AudioDecoderProxy::AudioDecoderProxy() : decoder_lock_(CriticalSectionWrapper::CreateCriticalSection()), decoder_(nullptr) { @@ -1171,52 +270,11 @@ CNG_dec_inst* AudioDecoderProxy::CngDecoderInstance() { return decoder_->CngDecoderInstance(); } -//////////////////////////////////////// -// ACMGenericCodecWrapper implementation - -ACMGenericCodecWrapper::ACMGenericCodecWrapper(const CodecInst& codec_inst, - int cng_pt_nb, - int cng_pt_wb, - int cng_pt_swb, - int cng_pt_fb, - bool enable_red, - int red_payload_type) - : ACMGenericCodec(enable_red), - encoder_(NULL), - bitrate_bps_(0), - fec_enabled_(false), - loss_rate_(0), - max_playback_rate_hz_(48000), - max_payload_size_bytes_(-1), - max_rate_bps_(-1), - is_opus_(false), - is_isac_(false), - first_frame_(true), - red_payload_type_(red_payload_type), - opus_application_set_(false) { - acm_codec_params_.codec_inst = codec_inst; - acm_codec_params_.enable_dtx = false; - acm_codec_params_.enable_vad = false; - acm_codec_params_.vad_mode = VADNormal; - SetCngPtInMap(&cng_pt_, 8000, cng_pt_nb); - SetCngPtInMap(&cng_pt_, 16000, cng_pt_wb); - SetCngPtInMap(&cng_pt_, 32000, cng_pt_swb); - SetCngPtInMap(&cng_pt_, 48000, cng_pt_fb); - ResetAudioEncoder(); - CHECK(encoder_); -} - -ACMGenericCodec* ACMGenericCodecWrapper::CreateInstance() { - FATAL(); - return 0; -} - -int16_t ACMGenericCodecWrapper::Encode( - uint8_t* bitstream, - int16_t* bitstream_len_byte, - uint32_t* timestamp, - WebRtcACMEncodingType* encoding_type, - AudioEncoder::EncodedInfo* encoded_info) { +int16_t ACMGenericCodec::Encode(uint8_t* bitstream, + int16_t* bitstream_len_byte, + uint32_t* timestamp, + WebRtcACMEncodingType* encoding_type, + AudioEncoder::EncodedInfo* encoded_info) { WriteLockScoped wl(codec_wrapper_lock_); CHECK(!input_.empty()); CHECK(encoder_->Encode(rtp_timestamp_, &input_[0], @@ -1247,20 +305,14 @@ int16_t ACMGenericCodecWrapper::Encode( return *bitstream_len_byte; } -bool ACMGenericCodecWrapper::EncoderInitialized() { - FATAL(); - return 0; -} - -int16_t ACMGenericCodecWrapper::EncoderParams( - WebRtcACMCodecParams* enc_params) { +int16_t ACMGenericCodec::EncoderParams(WebRtcACMCodecParams* enc_params) { ReadLockScoped rl(codec_wrapper_lock_); *enc_params = acm_codec_params_; return 0; } -int16_t ACMGenericCodecWrapper::InitEncoder(WebRtcACMCodecParams* codec_params, - bool force_initialization) { +int16_t ACMGenericCodec::InitEncoder(WebRtcACMCodecParams* codec_params, + bool force_initialization) { WriteLockScoped wl(codec_wrapper_lock_); bitrate_bps_ = 0; loss_rate_ = 0; @@ -1273,7 +325,7 @@ int16_t ACMGenericCodecWrapper::InitEncoder(WebRtcACMCodecParams* codec_params, return 0; } -void ACMGenericCodecWrapper::ResetAudioEncoder() { +void ACMGenericCodec::ResetAudioEncoder() { const CodecInst& codec_inst = acm_codec_params_.codec_inst; bool using_codec_internal_red = false; if (!STR_CASE_CMP(codec_inst.plname, "PCMU")) { @@ -1466,17 +518,17 @@ void ACMGenericCodecWrapper::ResetAudioEncoder() { } } -OpusApplicationMode ACMGenericCodecWrapper::GetOpusApplication( +OpusApplicationMode ACMGenericCodec::GetOpusApplication( int num_channels) const { if (opus_application_set_) return opus_application_; return num_channels == 1 ? kVoip : kAudio; } -int32_t ACMGenericCodecWrapper::Add10MsData(const uint32_t timestamp, - const int16_t* data, - const uint16_t length_per_channel, - const uint8_t audio_channel) { +int32_t ACMGenericCodec::Add10MsData(const uint32_t timestamp, + const int16_t* data, + const uint16_t length_per_channel, + const uint8_t audio_channel) { WriteLockScoped wl(codec_wrapper_lock_); CHECK(input_.empty()); CHECK_EQ(length_per_channel, encoder_->SampleRateHz() / 100); @@ -1499,30 +551,16 @@ int32_t ACMGenericCodecWrapper::Add10MsData(const uint32_t timestamp, return 0; } -uint32_t ACMGenericCodecWrapper::NoMissedSamples() const { - FATAL(); - return 0; -} - -void ACMGenericCodecWrapper::ResetNoMissedSamples() { - FATAL(); -} - -int16_t ACMGenericCodecWrapper::SetBitRate(const int32_t bitrate_bps) { +int16_t ACMGenericCodec::SetBitRate(const int32_t bitrate_bps) { WriteLockScoped wl(codec_wrapper_lock_); encoder_->SetTargetBitrate(bitrate_bps); bitrate_bps_ = bitrate_bps; return 0; } -uint32_t ACMGenericCodecWrapper::EarliestTimestamp() const { - FATAL(); - return 0; -} - -int16_t ACMGenericCodecWrapper::SetVAD(bool* enable_dtx, - bool* enable_vad, - ACMVADMode* mode) { +int16_t ACMGenericCodec::SetVAD(bool* enable_dtx, + bool* enable_vad, + ACMVADMode* mode) { WriteLockScoped wl(codec_wrapper_lock_); if (is_opus_) { *enable_dtx = false; @@ -1550,52 +588,30 @@ int16_t ACMGenericCodecWrapper::SetVAD(bool* enable_dtx, return 0; } -void ACMGenericCodecWrapper::SetCngPt(int sample_rate_hz, int payload_type) { +void ACMGenericCodec::SetCngPt(int sample_rate_hz, int payload_type) { WriteLockScoped wl(codec_wrapper_lock_); SetCngPtInMap(&cng_pt_, sample_rate_hz, payload_type); ResetAudioEncoder(); } -int32_t ACMGenericCodecWrapper::ReplaceInternalDTX( - const bool replace_internal_dtx) { +int32_t ACMGenericCodec::GetRedPayload(uint8_t* red_payload, + int16_t* payload_bytes) { FATAL(); return 0; } -int32_t ACMGenericCodecWrapper::GetEstimatedBandwidth() { - FATAL(); +int16_t ACMGenericCodec::ResetEncoder() { return 0; } -int32_t ACMGenericCodecWrapper::SetEstimatedBandwidth( - int32_t estimated_bandwidth) { - FATAL(); - return 0; +void ACMGenericCodec::DestructEncoder() { } -int32_t ACMGenericCodecWrapper::GetRedPayload(uint8_t* red_payload, - int16_t* payload_bytes) { - FATAL(); - return 0; -} - -int16_t ACMGenericCodecWrapper::ResetEncoder() { - return 0; -} - -void ACMGenericCodecWrapper::DestructEncoder() { -} - -int16_t ACMGenericCodecWrapper::SamplesLeftToEncode() { - FATAL(); - return 0; -} - -void ACMGenericCodecWrapper::SetUniqueID(const uint32_t id) { +void ACMGenericCodec::SetUniqueID(const uint32_t id) { // Do nothing. } -int16_t ACMGenericCodecWrapper::UpdateDecoderSampFreq(int16_t codec_id) { +int16_t ACMGenericCodec::UpdateDecoderSampFreq(int16_t codec_id) { #ifdef WEBRTC_CODEC_ISAC WriteLockScoped wl(codec_wrapper_lock_); if (is_isac_) { @@ -1617,25 +633,7 @@ int16_t ACMGenericCodecWrapper::UpdateDecoderSampFreq(int16_t codec_id) { return 0; } -int16_t ACMGenericCodecWrapper::UpdateEncoderSampFreq(uint16_t samp_freq_hz) { - FATAL(); - return 0; -} - -int16_t ACMGenericCodecWrapper::EncoderSampFreq(uint16_t* samp_freq_hz) { - FATAL(); - return 0; -} - -int32_t ACMGenericCodecWrapper::ConfigISACBandwidthEstimator( - const uint8_t init_frame_size_msec, - const uint16_t init_rate_bps, - const bool enforce_frame_size) { - FATAL(); - return 0; -} - -int32_t ACMGenericCodecWrapper::SetISACMaxPayloadSize( +int32_t ACMGenericCodec::SetISACMaxPayloadSize( const uint16_t max_payload_len_bytes) { WriteLockScoped wl(codec_wrapper_lock_); if (!is_isac_) @@ -1645,7 +643,7 @@ int32_t ACMGenericCodecWrapper::SetISACMaxPayloadSize( return 0; } -int32_t ACMGenericCodecWrapper::SetISACMaxRate(const uint32_t max_rate_bps) { +int32_t ACMGenericCodec::SetISACMaxRate(const uint32_t max_rate_bps) { WriteLockScoped wl(codec_wrapper_lock_); if (!is_isac_) return -1; // Needed for tests to pass. @@ -1654,15 +652,7 @@ int32_t ACMGenericCodecWrapper::SetISACMaxRate(const uint32_t max_rate_bps) { return 0; } -int16_t ACMGenericCodecWrapper::REDPayloadISAC(const int32_t isac_rate, - const int16_t isac_bw_estimate, - uint8_t* payload, - int16_t* payload_len_bytes) { - FATAL(); - return 0; -} - -int ACMGenericCodecWrapper::SetOpusMaxPlaybackRate(int frequency_hz) { +int ACMGenericCodec::SetOpusMaxPlaybackRate(int frequency_hz) { WriteLockScoped wl(codec_wrapper_lock_); if (!is_opus_) return -1; // Needed for tests to pass. @@ -1671,17 +661,12 @@ int ACMGenericCodecWrapper::SetOpusMaxPlaybackRate(int frequency_hz) { return 0; } -bool ACMGenericCodecWrapper::HasFrameToEncode() const { - FATAL(); - return 0; -} - -AudioDecoder* ACMGenericCodecWrapper::Decoder(int /* codec_id */) { +AudioDecoder* ACMGenericCodec::Decoder(int /* codec_id */) { ReadLockScoped rl(codec_wrapper_lock_); return decoder_proxy_.IsSet() ? &decoder_proxy_ : nullptr; } -int ACMGenericCodecWrapper::SetFEC(bool enable_fec) { +int ACMGenericCodec::SetFEC(bool enable_fec) { if (!HasInternalFEC()) return enable_fec ? -1 : 0; WriteLockScoped wl(codec_wrapper_lock_); @@ -1692,8 +677,7 @@ int ACMGenericCodecWrapper::SetFEC(bool enable_fec) { return 0; } -int ACMGenericCodecWrapper::SetOpusApplication( - OpusApplicationMode application) { +int ACMGenericCodec::SetOpusApplication(OpusApplicationMode application) { WriteLockScoped wl(codec_wrapper_lock_); opus_application_ = application; opus_application_set_ = true; @@ -1701,50 +685,29 @@ int ACMGenericCodecWrapper::SetOpusApplication( return 0; } -int ACMGenericCodecWrapper::SetPacketLossRate(int loss_rate) { +int ACMGenericCodec::SetPacketLossRate(int loss_rate) { WriteLockScoped wl(codec_wrapper_lock_); encoder_->SetProjectedPacketLossRate(loss_rate / 100.0); loss_rate_ = loss_rate; return 0; } -void ACMGenericCodecWrapper::EnableCopyRed(bool enable, int red_payload_type) { - ACMGenericCodec::EnableCopyRed(enable, red_payload_type); +void ACMGenericCodec::EnableCopyRed(bool enable, int red_payload_type) { WriteLockScoped wl(codec_wrapper_lock_); + copy_red_enabled_ = enable; red_payload_type_ = red_payload_type; ResetAudioEncoder(); } -bool ACMGenericCodecWrapper::ExternalRedNeeded() { +bool ACMGenericCodec::ExternalRedNeeded() { return false; } -const AudioEncoder* ACMGenericCodecWrapper::GetAudioEncoder() const { +const AudioEncoder* ACMGenericCodec::GetAudioEncoder() const { WriteLockScoped wl(codec_wrapper_lock_); return encoder_; } -void ACMGenericCodecWrapper::DestructEncoderSafe() { - FATAL(); -} - -int16_t ACMGenericCodecWrapper::InternalEncode(uint8_t* bitstream, - int16_t* bitstream_len_byte) { - FATAL(); - return 0; -} - -int16_t ACMGenericCodecWrapper::InternalInitEncoder( - WebRtcACMCodecParams* codec_params) { - FATAL(); - return 0; -} - -int16_t ACMGenericCodecWrapper::InternalCreateEncoder() { - FATAL(); - return 0; -} - } // namespace acm2 } // namespace webrtc diff --git a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h index 5a36a8e285..31dfda53f4 100644 --- a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h +++ b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h @@ -40,23 +40,56 @@ namespace acm2 { // forward declaration class AcmReceiver; +// Proxy for AudioDecoder +class AudioDecoderProxy final : public AudioDecoder { + public: + AudioDecoderProxy(); + void SetDecoder(AudioDecoder* decoder); + bool IsSet() const; + int Decode(const uint8_t* encoded, + size_t encoded_len, + int16_t* decoded, + SpeechType* speech_type) override; + int DecodeRedundant(const uint8_t* encoded, + size_t encoded_len, + int16_t* decoded, + SpeechType* speech_type) override; + bool HasDecodePlc() const override; + int DecodePlc(int num_frames, int16_t* decoded) override; + int Init() override; + int IncomingPacket(const uint8_t* payload, + size_t payload_len, + uint16_t rtp_sequence_number, + uint32_t rtp_timestamp, + uint32_t arrival_timestamp) override; + int ErrorCode() override; + int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override; + int PacketDurationRedundant(const uint8_t* encoded, + size_t encoded_len) const override; + bool PacketHasFec(const uint8_t* encoded, size_t encoded_len) const override; + CNG_dec_inst* CngDecoderInstance() override; + + private: + scoped_ptr decoder_lock_; + AudioDecoder* decoder_ GUARDED_BY(decoder_lock_); +}; + class ACMGenericCodec { public: - /////////////////////////////////////////////////////////////////////////// - // Constructor of the class - // - explicit ACMGenericCodec(bool enable_red); - - /////////////////////////////////////////////////////////////////////////// - // Destructor of the class. - // - virtual ~ACMGenericCodec(); + ACMGenericCodec(const CodecInst& codec_inst, + int cng_pt_nb, + int cng_pt_wb, + int cng_pt_swb, + int cng_pt_fb, + bool enable_red, + int red_payload_type); + ~ACMGenericCodec(); /////////////////////////////////////////////////////////////////////////// // ACMGenericCodec* CreateInstance(); // The function will be used for FEC. It is not implemented yet. // - virtual ACMGenericCodec* CreateInstance() = 0; + ACMGenericCodec* CreateInstance(); /////////////////////////////////////////////////////////////////////////// // int16_t Encode() @@ -111,11 +144,11 @@ class ACMGenericCodec { // -1 if error is occurred, otherwise the length of the bit-stream in // bytes. // - virtual int16_t Encode(uint8_t* bitstream, - int16_t* bitstream_len_byte, - uint32_t* timestamp, - WebRtcACMEncodingType* encoding_type, - AudioEncoder::EncodedInfo* encoded_info); + int16_t Encode(uint8_t* bitstream, + int16_t* bitstream_len_byte, + uint32_t* timestamp, + WebRtcACMEncodingType* encoding_type, + AudioEncoder::EncodedInfo* encoded_info); /////////////////////////////////////////////////////////////////////////// // bool EncoderInitialized(); @@ -124,7 +157,7 @@ class ACMGenericCodec { // True if the encoder is successfully initialized, // false otherwise. // - virtual bool EncoderInitialized(); + bool EncoderInitialized(); /////////////////////////////////////////////////////////////////////////// // int16_t EncoderParams() @@ -140,7 +173,7 @@ class ACMGenericCodec { // -1 if the encoder is not initialized, // 0 otherwise. // - virtual int16_t EncoderParams(WebRtcACMCodecParams* enc_params); + int16_t EncoderParams(WebRtcACMCodecParams* enc_params); /////////////////////////////////////////////////////////////////////////// // int16_t InitEncoder(...) @@ -158,8 +191,8 @@ class ACMGenericCodec { // -1 if failed to initialize. // // - virtual int16_t InitEncoder(WebRtcACMCodecParams* codec_params, - bool force_initialization); + int16_t InitEncoder(WebRtcACMCodecParams* codec_params, + bool force_initialization); /////////////////////////////////////////////////////////////////////////// // int32_t Add10MsData(...) @@ -180,10 +213,10 @@ class ACMGenericCodec { // -1 if failed // 0 otherwise. // - virtual int32_t Add10MsData(const uint32_t timestamp, - const int16_t* data, - const uint16_t length, - const uint8_t audio_channel); + int32_t Add10MsData(const uint32_t timestamp, + const int16_t* data, + const uint16_t length, + const uint8_t audio_channel); /////////////////////////////////////////////////////////////////////////// // uint32_t NoMissedSamples() @@ -195,14 +228,14 @@ class ACMGenericCodec { // Return Value: // Number of samples which are overwritten. // - virtual uint32_t NoMissedSamples() const; + uint32_t NoMissedSamples() const; /////////////////////////////////////////////////////////////////////////// // void ResetNoMissedSamples() // This function resets the number of overwritten samples to zero. // (We might remove this function if we remove NoMissedSamples()) // - virtual void ResetNoMissedSamples(); + void ResetNoMissedSamples(); /////////////////////////////////////////////////////////////////////////// // int16_t SetBitRate() @@ -216,7 +249,7 @@ class ACMGenericCodec { // codec is not rate-adjustable. // 0 if the rate is adjusted successfully // - virtual int16_t SetBitRate(const int32_t bitrate_bps); + int16_t SetBitRate(const int32_t bitrate_bps); /////////////////////////////////////////////////////////////////////////// // uint32_t EarliestTimestamp() @@ -226,7 +259,7 @@ class ACMGenericCodec { // Return value: // timestamp of the first 10 ms audio in the audio buffer. // - virtual uint32_t EarliestTimestamp() const; + uint32_t EarliestTimestamp() const; /////////////////////////////////////////////////////////////////////////// // int16_t SetVAD() @@ -255,40 +288,10 @@ class ACMGenericCodec { // -1 if failed to set DTX & VAD as specified, // 0 if succeeded. // - virtual int16_t SetVAD(bool* enable_dtx, bool* enable_vad, ACMVADMode* mode); + int16_t SetVAD(bool* enable_dtx, bool* enable_vad, ACMVADMode* mode); // Registers comfort noise at |sample_rate_hz| to use |payload_type|. - virtual void SetCngPt(int sample_rate_hz, int payload_type); - - /////////////////////////////////////////////////////////////////////////// - // int32_t ReplaceInternalDTX() - // This is called to replace the codec internal DTX with WebRtc DTX. - // This is only valid for G729 where the user has possibility to replace - // AnnexB with WebRtc DTX. For other codecs this function has no effect. - // - // Input: - // -replace_internal_dtx : if true the internal DTX is replaced with WebRtc. - // - // Return value - // -1 if failed to replace internal DTX, - // 0 if succeeded. - // - virtual int32_t ReplaceInternalDTX(const bool replace_internal_dtx); - - /////////////////////////////////////////////////////////////////////////// - // int32_t IsInternalDTXReplaced() - // This is called to check if the codec internal DTX is replaced by WebRtc - // DTX. This is only valid for G729 where the user has possibility to replace - // AnnexB with WebRtc DTX. For other codecs this function has no effect. - // - // Output: - // -internal_dtx_replaced: if true the internal DTX is replaced with WebRtc. - // - // Return value - // -1 if failed to check - // 0 if succeeded. - // - int32_t IsInternalDTXReplaced(bool* internal_dtx_replaced); + void SetCngPt(int sample_rate_hz, int payload_type); /////////////////////////////////////////////////////////////////////////// // bool HasInternalDTX() @@ -303,31 +306,6 @@ class ACMGenericCodec { return has_internal_dtx_; } - /////////////////////////////////////////////////////////////////////////// - // int32_t GetEstimatedBandwidth() - // Used to get decoder estimated bandwidth. Only iSAC will provide a value. - // - // - // Return value: - // -1 if fails to get decoder estimated bandwidth, - // >0 estimated bandwidth in bits/sec. - // - virtual int32_t GetEstimatedBandwidth(); - - /////////////////////////////////////////////////////////////////////////// - // int32_t SetEstimatedBandwidth() - // Used to set estiamted bandwidth sent out of band from other side. Only - // iSAC will have use for the value. - // - // Input: - // -estimated_bandwidth: estimated bandwidth in bits/sec - // - // Return value: - // -1 if fails to set estimated bandwidth, - // 0 on success. - // - virtual int32_t SetEstimatedBandwidth(int32_t estimated_bandwidth); - /////////////////////////////////////////////////////////////////////////// // int32_t GetRedPayload() // Used to get codec specific RED payload (if such is implemented). @@ -341,7 +319,7 @@ class ACMGenericCodec { // -1 if fails to get codec specific RED, // 0 if succeeded. // - virtual int32_t GetRedPayload(uint8_t* red_payload, int16_t* payload_bytes); + int32_t GetRedPayload(uint8_t* red_payload, int16_t* payload_bytes); /////////////////////////////////////////////////////////////////////////// // int16_t ResetEncoder() @@ -353,7 +331,7 @@ class ACMGenericCodec { // -1 if failed, // 0 if succeeded. // - virtual int16_t ResetEncoder(); + int16_t ResetEncoder(); /////////////////////////////////////////////////////////////////////////// // void DestructEncoder() @@ -362,16 +340,7 @@ class ACMGenericCodec { // instance we cannot delete the encoder and instead we will initialize the // encoder. We also delete VAD and DTX if they have been created. // - virtual void DestructEncoder(); - - /////////////////////////////////////////////////////////////////////////// - // int16_t SamplesLeftToEncode() - // Returns the number of samples required to be able to do encoding. - // - // Return value: - // Number of samples. - // - virtual int16_t SamplesLeftToEncode(); + void DestructEncoder(); /////////////////////////////////////////////////////////////////////////// // SetUniqueID() @@ -380,7 +349,7 @@ class ACMGenericCodec { // Input // -id : A number to identify the codec. // - virtual void SetUniqueID(const uint32_t id); + void SetUniqueID(const uint32_t id); /////////////////////////////////////////////////////////////////////////// // UpdateDecoderSampFreq() @@ -407,7 +376,7 @@ class ACMGenericCodec { // 0 if succeeded in updating the decoder. // -1 if failed to update. // - virtual int16_t UpdateDecoderSampFreq(int16_t /* codec_id */) { return 0; } + int16_t UpdateDecoderSampFreq(int16_t /* codec_id */); /////////////////////////////////////////////////////////////////////////// // UpdateEncoderSampFreq() @@ -425,7 +394,7 @@ class ACMGenericCodec { // -1 if failed, or if this is meaningless for the given codec. // 0 if succeeded. // - virtual int16_t UpdateEncoderSampFreq(uint16_t samp_freq_hz) + int16_t UpdateEncoderSampFreq(uint16_t samp_freq_hz) EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); /////////////////////////////////////////////////////////////////////////// @@ -440,38 +409,9 @@ class ACMGenericCodec { // -1 if failed to output sampling rate. // 0 if the sample rate is returned successfully. // - virtual int16_t EncoderSampFreq(uint16_t* samp_freq_hz) + int16_t EncoderSampFreq(uint16_t* samp_freq_hz) SHARED_LOCKS_REQUIRED(codec_wrapper_lock_); - /////////////////////////////////////////////////////////////////////////// - // int32_t ConfigISACBandwidthEstimator() - // Call this function to configure the bandwidth estimator of ISAC. - // During the adaptation of bit-rate, iSAC automatically adjusts the - // frame-size (either 30 or 60 ms) to save on RTP header. The initial - // frame-size can be specified by the first argument. The configuration also - // regards the initial estimate of bandwidths. The estimator starts from - // this point and converges to the actual bottleneck. This is given by the - // second parameter. Furthermore, it is also possible to control the - // adaptation of frame-size. This is specified by the last parameter. - // - // Input: - // -init_frame_fize_ms : initial frame-size in milliseconds. For iSAC-wb - // 30 ms and 60 ms (default) are acceptable values, - // and for iSAC-swb 30 ms is the only acceptable - // value. Zero indicates default value. - // -init_rate_bps : initial estimate of the bandwidth. Values - // between 10000 and 58000 are acceptable. - // -enforce_frame_size : if true, the frame-size will not be adapted. - // - // Return value: - // -1 if failed to configure the bandwidth estimator, - // 0 if the configuration was successfully applied. - // - virtual int32_t ConfigISACBandwidthEstimator( - const uint8_t init_frame_size_msec, - const uint16_t init_rate_bps, - const bool enforce_frame_size); - /////////////////////////////////////////////////////////////////////////// // SetISACMaxPayloadSize() // Set the maximum payload size of iSAC packets. No iSAC payload, @@ -487,7 +427,7 @@ class ACMGenericCodec { // -1 if failed to set the maximum payload-size. // 0 if the given length is set successfully. // - virtual int32_t SetISACMaxPayloadSize(const uint16_t max_payload_len_bytes); + int32_t SetISACMaxPayloadSize(const uint16_t max_payload_len_bytes); /////////////////////////////////////////////////////////////////////////// // SetISACMaxRate() @@ -504,35 +444,7 @@ class ACMGenericCodec { // -1 if failed to set the maximum rate. // 0 if the maximum rate is set successfully. // - virtual int32_t SetISACMaxRate(const uint32_t max_rate_bps); - - /////////////////////////////////////////////////////////////////////////// - // REDPayloadISAC() - // This is an iSAC-specific function. The function is called to get RED - // payload from a default-encoder. - // - // Inputs: - // -isac_rate : the target rate of the main payload. A RED - // payload is generated according to the rate of - // main payload. Note that we are not specifying the - // rate of RED payload, but the main payload. - // -isac_bw_estimate : bandwidth information should be inserted in - // RED payload. - // - // Output: - // -payload : pointer to a buffer where the RED payload will - // written to. - // -payload_len_bytes : a place-holder to write the length of the RED - // payload in Bytes. - // - // Return value: - // -1 if an error occurs, otherwise the length of the payload (in Bytes) - // is returned. - // - virtual int16_t REDPayloadISAC(const int32_t isac_rate, - const int16_t isac_bw_estimate, - uint8_t* payload, - int16_t* payload_len_bytes); + int32_t SetISACMaxRate(const uint32_t max_rate_bps); /////////////////////////////////////////////////////////////////////////// // int SetOpusApplication() @@ -546,7 +458,7 @@ class ACMGenericCodec { // -1 if failed or on codecs other than Opus. // 0 if succeeded. // - virtual int SetOpusApplication(OpusApplicationMode /*application*/); + int SetOpusApplication(OpusApplicationMode /*application*/); /////////////////////////////////////////////////////////////////////////// // int SetOpusMaxPlaybackRate() @@ -562,14 +474,14 @@ class ACMGenericCodec { // -1 if failed or on codecs other than Opus // 0 if succeeded. // - virtual int SetOpusMaxPlaybackRate(int /* frequency_hz */); + int SetOpusMaxPlaybackRate(int /* frequency_hz */); /////////////////////////////////////////////////////////////////////////// // HasFrameToEncode() // Returns true if there is enough audio buffered for encoding, such that // calling Encode() will return a payload. // - virtual bool HasFrameToEncode() const; + bool HasFrameToEncode() const; // // Returns pointer to the AudioDecoder class of this codec. A codec which @@ -578,7 +490,7 @@ class ACMGenericCodec { // decoder setting) should implement this method. This method is called if // and only if the ACMCodecDB::codec_settings[codec_id].owns_decoder is true. // - virtual AudioDecoder* Decoder(int /* codec_id */) { return NULL; } + AudioDecoder* Decoder(int /* codec_id */); /////////////////////////////////////////////////////////////////////////// // bool HasInternalFEC() @@ -606,7 +518,7 @@ class ACMGenericCodec { // -1 if failed, // 0 if succeeded. // - virtual int SetFEC(bool enable_fec); + int SetFEC(bool enable_fec); /////////////////////////////////////////////////////////////////////////// // int SetPacketLossRate() @@ -621,302 +533,19 @@ class ACMGenericCodec { // -1 if failed, // 0 if succeeded or packet loss rate is ignored. // - virtual int SetPacketLossRate(int /* loss_rate */) { return 0; } + int SetPacketLossRate(int /* loss_rate */); // Sets if CopyRed should be enabled. - virtual void EnableCopyRed(bool enable, int red_payload_type); + void EnableCopyRed(bool enable, int red_payload_type); // Returns true if the caller needs to produce RED data manually (that is, if // RED has been enabled but the codec isn't able to produce the data itself). - virtual bool ExternalRedNeeded(); + bool ExternalRedNeeded(); - protected: - /////////////////////////////////////////////////////////////////////////// - // All the functions with FunctionNameSafe(...) contain the actual - // implementation of FunctionName(...). FunctionName() acquires an - // appropriate lock and calls FunctionNameSafe() to do the actual work. - // Therefore, for the description of functionality, input/output arguments - // and return value we refer to FunctionName() - // - - /////////////////////////////////////////////////////////////////////////// - // See Add10MsSafe() for the description of function, input(s)/output(s) - // and return value. - // - virtual int32_t Add10MsDataSafe(const uint32_t timestamp, - const int16_t* data, - const uint16_t length, - const uint8_t audio_channel) - EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); - - /////////////////////////////////////////////////////////////////////////// - // See EncoderParam() for the description of function, input(s)/output(s) - // and return value. - // - int16_t EncoderParamsSafe(WebRtcACMCodecParams* enc_params) - SHARED_LOCKS_REQUIRED(codec_wrapper_lock_); - - /////////////////////////////////////////////////////////////////////////// - // See ResetEncoder() for the description of function, input(s)/output(s) - // and return value. - // - int16_t ResetEncoderSafe() EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); - - /////////////////////////////////////////////////////////////////////////// - // See InitEncoder() for the description of function, input(s)/output(s) - // and return value. - // - virtual int16_t InitEncoderSafe(WebRtcACMCodecParams* codec_params, - bool force_initialization) - EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); - - /////////////////////////////////////////////////////////////////////////// - // See InitDecoder() for the description of function, input(s)/output(s) - // and return value. - // - int16_t InitDecoderSafe(WebRtcACMCodecParams* codec_params, - bool force_initialization); - - /////////////////////////////////////////////////////////////////////////// - // See DestructEncoder() for the description of function, - // input(s)/output(s) and return value. - // - virtual void DestructEncoderSafe() - EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_) = 0; - - /////////////////////////////////////////////////////////////////////////// - // See SetBitRate() for the description of function, input(s)/output(s) - // and return value. - // - // Any codec that can change the bit-rate has to implement this. - // - virtual int16_t SetBitRateSafe(const int32_t bitrate_bps) - EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); - - /////////////////////////////////////////////////////////////////////////// - // See GetEstimatedBandwidth() for the description of function, - // input(s)/output(s) and return value. - // - virtual int32_t GetEstimatedBandwidthSafe(); - - /////////////////////////////////////////////////////////////////////////// - // See SetEstimatedBandwidth() for the description of function, - // input(s)/output(s) and return value. - // - virtual int32_t SetEstimatedBandwidthSafe(int32_t estimated_bandwidth); - - /////////////////////////////////////////////////////////////////////////// - // See GetRedPayload() for the description of function, input(s)/output(s) - // and return value. - // - virtual int32_t GetRedPayloadSafe(uint8_t* red_payload, - int16_t* payload_bytes); - - /////////////////////////////////////////////////////////////////////////// - // See SetVAD() for the description of function, input(s)/output(s) and - // return value. - // - int16_t SetVADSafe(bool* enable_dtx, bool* enable_vad, ACMVADMode* mode) - EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); - - /////////////////////////////////////////////////////////////////////////// - // See ReplaceInternalDTX() for the description of function, input and - // return value. - // - virtual int32_t ReplaceInternalDTXSafe(const bool replace_internal_dtx); - - /////////////////////////////////////////////////////////////////////////// - // See IsInternalDTXReplaced() for the description of function, input and - // return value. - // - virtual int32_t IsInternalDTXReplacedSafe(bool* internal_dtx_replaced); - - /////////////////////////////////////////////////////////////////////////// - // int16_t CreateEncoder() - // Creates the encoder instance. - // - // Return value: - // -1 if failed, - // 0 if succeeded. - // - int16_t CreateEncoder() EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); - - /////////////////////////////////////////////////////////////////////////// - // int16_t EnableVAD(); - // Enables VAD with the given mode. The VAD instance will be created if - // it does not exists. - // - // Input: - // -mode : VAD mode c.f. audio_coding_module_typedefs.h for - // the options. - // - // Return value: - // -1 if failed, - // 0 if succeeded. - // - int16_t EnableVAD(ACMVADMode mode) - EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); - - /////////////////////////////////////////////////////////////////////////// - // int16_t DisableVAD() - // Disables VAD. - // - // Return value: - // -1 if failed, - // 0 if succeeded. - // - int16_t DisableVAD() EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); - - /////////////////////////////////////////////////////////////////////////// - // int16_t EnableDTX() - // Enables DTX. This method should be overwritten for codecs which have - // internal DTX. - // - // Return value: - // -1 if failed, - // 0 if succeeded. - // - virtual int16_t EnableDTX() EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); - - /////////////////////////////////////////////////////////////////////////// - // int16_t DisableDTX() - // Disables usage of DTX. This method should be overwritten for codecs which - // have internal DTX. - // - // Return value: - // -1 if failed, - // 0 if succeeded. - // - virtual int16_t DisableDTX() EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); - - /////////////////////////////////////////////////////////////////////////// - // int16_t InternalEncode() - // This is a codec-specific function called in EncodeSafe() to actually - // encode a frame of audio. - // - // Outputs: - // -bitstream : pointer to a buffer where the bit-stream is - // written to. - // -bitstream_len_byte : the length of the bit-stream in bytes, - // a negative value indicates error. - // - // Return value: - // -1 if failed, - // otherwise the length of the bit-stream is returned. - // - virtual int16_t InternalEncode(uint8_t* bitstream, - int16_t* bitstream_len_byte) - EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_) = 0; - - /////////////////////////////////////////////////////////////////////////// - // int16_t InternalInitEncoder() - // This is a codec-specific function called in InitEncoderSafe(), it has to - // do all codec-specific operation to initialize the encoder given the - // encoder parameters. - // - // Input: - // -codec_params : pointer to a structure that contains parameters to - // initialize encoder. - // Set codec_params->codec_inst.rate to -1 for - // iSAC to operate in adaptive mode. - // (to do: if frame-length is -1 frame-length will be - // automatically adjusted, otherwise, given - // frame-length is forced) - // - // Return value: - // -1 if failed, - // 0 if succeeded. - // - virtual int16_t InternalInitEncoder(WebRtcACMCodecParams* codec_params) - EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_) = 0; - - /////////////////////////////////////////////////////////////////////////// - // void IncreaseNoMissedSamples() - // This method is called to increase the number of samples that are - // overwritten in the audio buffer. - // - // Input: - // -num_samples : the number of overwritten samples is incremented - // by this value. - // - void IncreaseNoMissedSamples(const int16_t num_samples) - EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); - - /////////////////////////////////////////////////////////////////////////// - // int16_t InternalCreateEncoder() - // This is a codec-specific method called in CreateEncoderSafe() it is - // supposed to perform all codec-specific operations to create encoder - // instance. - // - // Return value: - // -1 if failed, - // 0 if succeeded. - // - virtual int16_t InternalCreateEncoder() = 0; - - /////////////////////////////////////////////////////////////////////////// - // int16_t InternalResetEncoder() - // This method is called to reset the states of encoder. However, the - // current parameters, e.g. frame-length, should remain as they are. For - // most of the codecs a re-initialization of the encoder is what needs to - // be down. But for iSAC we like to keep the BWE history so we cannot - // re-initialize. As soon as such an API is implemented in iSAC this method - // has to be overwritten in ACMISAC class. - // - // Return value: - // -1 if failed, - // 0 if succeeded. - // - virtual int16_t InternalResetEncoder() - EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); - - /////////////////////////////////////////////////////////////////////////// - // int16_t ProcessFrameVADDTX() - // This function is called when a full frame of audio is available. It will - // break the audio frame into blocks such that each block could be processed - // by VAD & CN/DTX. If a frame is divided into two blocks then there are two - // cases. First, the first block is active, the second block will not be - // processed by CN/DTX but only by VAD and return to caller with - // '*samples_processed' set to zero. There, the audio frame will be encoded - // by the encoder. Second, the first block is inactive and is processed by - // CN/DTX, then we stop processing the next block and return to the caller - // which is EncodeSafe(), with "*samples_processed" equal to the number of - // samples in first block. - // - // Output: - // -bitstream : pointer to a buffer where DTX frame, if - // generated, will be written to. - // -bitstream_len_byte : contains the length of bit-stream in bytes, if - // generated. Zero if no bit-stream is generated. - // -samples_processed : contains no of samples that actually CN has - // processed. Those samples processed by CN will not - // be encoded by the encoder, obviously. If - // contains zero, it means that the frame has been - // identified as active by VAD. Note that - // "*samples_processed" might be non-zero but - // "*bitstream_len_byte" be zero. - // - // Return value: - // -1 if failed, - // 0 if succeeded. - // - int16_t ProcessFrameVADDTX(uint8_t* bitstream, - int16_t* bitstream_len_byte, - int16_t* samples_processed) - EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); - - /////////////////////////////////////////////////////////////////////////// - // CurrentRate() - // Call to get the current encoding rate of the encoder. This function - // should be overwritten for codecs which automatically change their - // target rate. One example is iSAC. The output of the function is the - // current target rate. - // - // Output: - // -rate_bps : the current target rate of the codec. - // - virtual void CurrentRate(int32_t* /* rate_bps */) {} + // This method is only for testing. + const AudioEncoder* GetAudioEncoder() const; + private: // &in_audio_[in_audio_ix_write_] always point to where new audio can be // written to int16_t in_audio_ix_write_ GUARDED_BY(codec_wrapper_lock_); @@ -979,155 +608,7 @@ class ACMGenericCodec { uint32_t last_timestamp_ GUARDED_BY(codec_wrapper_lock_); uint32_t unique_id_; -}; -// Proxy for AudioDecoder -class AudioDecoderProxy final : public AudioDecoder { - public: - AudioDecoderProxy(); - void SetDecoder(AudioDecoder* decoder); - bool IsSet() const; - int Decode(const uint8_t* encoded, - size_t encoded_len, - int16_t* decoded, - SpeechType* speech_type) override; - int DecodeRedundant(const uint8_t* encoded, - size_t encoded_len, - int16_t* decoded, - SpeechType* speech_type) override; - bool HasDecodePlc() const override; - int DecodePlc(int num_frames, int16_t* decoded) override; - int Init() override; - int IncomingPacket(const uint8_t* payload, - size_t payload_len, - uint16_t rtp_sequence_number, - uint32_t rtp_timestamp, - uint32_t arrival_timestamp) override; - int ErrorCode() override; - int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override; - int PacketDurationRedundant(const uint8_t* encoded, - size_t encoded_len) const override; - bool PacketHasFec(const uint8_t* encoded, size_t encoded_len) const override; - CNG_dec_inst* CngDecoderInstance() override; - - private: - scoped_ptr decoder_lock_; - AudioDecoder* decoder_ GUARDED_BY(decoder_lock_); -}; - -class ACMGenericCodecWrapper : public ACMGenericCodec { - public: - ACMGenericCodecWrapper(const CodecInst& codec_inst, - int cng_pt_nb, - int cng_pt_wb, - int cng_pt_swb, - int cng_pt_fb, - bool enable_red, - int red_payload_type); - virtual ~ACMGenericCodecWrapper() = default; - - ACMGenericCodec* CreateInstance() override; - - int16_t Encode(uint8_t* bitstream, - int16_t* bitstream_len_byte, - uint32_t* timestamp, - WebRtcACMEncodingType* encoding_type, - AudioEncoder::EncodedInfo* encoded_info) override; - - bool EncoderInitialized() override; - - int16_t EncoderParams(WebRtcACMCodecParams* enc_params) override; - - int16_t InitEncoder(WebRtcACMCodecParams* codec_params, - bool force_initialization) override; - - int32_t Add10MsData(const uint32_t timestamp, - const int16_t* data, - const uint16_t length, - const uint8_t audio_channel) override; - - uint32_t NoMissedSamples() const override; - - void ResetNoMissedSamples() override; - - int16_t SetBitRate(const int32_t bitrate_bps) override; - - uint32_t EarliestTimestamp() const override; - - int16_t SetVAD(bool* enable_dtx, bool* enable_vad, ACMVADMode* mode) override; - - void SetCngPt(int sample_rate_hz, int payload_type) override; - - int32_t ReplaceInternalDTX(const bool replace_internal_dtx) override; - - int32_t GetEstimatedBandwidth() override; - - int32_t SetEstimatedBandwidth(int32_t estimated_bandwidth) override; - - int32_t GetRedPayload(uint8_t* red_payload, int16_t* payload_bytes) override; - - int16_t ResetEncoder() override; - - void DestructEncoder() override; - - int16_t SamplesLeftToEncode() override; - - void SetUniqueID(const uint32_t id) override; - - int16_t UpdateDecoderSampFreq(int16_t codec_id) override; - - int16_t UpdateEncoderSampFreq(uint16_t samp_freq_hz) override - EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); - - int16_t EncoderSampFreq(uint16_t* samp_freq_hz) override - SHARED_LOCKS_REQUIRED(codec_wrapper_lock_); - - int32_t ConfigISACBandwidthEstimator(const uint8_t init_frame_size_msec, - const uint16_t init_rate_bps, - const bool enforce_frame_size) override; - - int32_t SetISACMaxPayloadSize(const uint16_t max_payload_len_bytes) override; - - int32_t SetISACMaxRate(const uint32_t max_rate_bps) override; - - int16_t REDPayloadISAC(const int32_t isac_rate, - const int16_t isac_bw_estimate, - uint8_t* payload, - int16_t* payload_len_bytes) override; - - int SetOpusMaxPlaybackRate(int /* frequency_hz */) override; - - bool HasFrameToEncode() const override; - - AudioDecoder* Decoder(int /* codec_id */) override; - - int SetFEC(bool enable_fec) override; - - int SetOpusApplication(OpusApplicationMode mode) override; - - int SetPacketLossRate(int /* loss_rate */) override; - - void EnableCopyRed(bool enable, int red_payload_type) override; - - bool ExternalRedNeeded() override; - - // This method is only for testing. - const AudioEncoder* GetAudioEncoder() const; - - protected: - void DestructEncoderSafe() override - EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); - - int16_t InternalEncode(uint8_t* bitstream, - int16_t* bitstream_len_byte) override - EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); - - int16_t InternalInitEncoder(WebRtcACMCodecParams* codec_params) override - EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); - - int16_t InternalCreateEncoder() override; - - private: void ResetAudioEncoder() EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); OpusApplicationMode GetOpusApplication(int num_channels) const diff --git a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec_opus_test.cc b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec_opus_test.cc index b7a25226ac..745a15042b 100644 --- a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec_opus_test.cc +++ b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec_opus_test.cc @@ -29,7 +29,7 @@ class AcmGenericCodecOpusTest : public ::testing::Test { } void CreateCodec() { - codec_wrapper_.reset(new ACMGenericCodecWrapper( + codec_wrapper_.reset(new ACMGenericCodec( acm_codec_params_.codec_inst, kCngPt, kCngPt, kCngPt, kCngPt, false /* enable RED */, kRedPt)); ASSERT_TRUE(codec_wrapper_); @@ -43,7 +43,7 @@ class AcmGenericCodecOpusTest : public ::testing::Test { return ptr; } WebRtcACMCodecParams acm_codec_params_; - scoped_ptr codec_wrapper_; + scoped_ptr codec_wrapper_; }; TEST_F(AcmGenericCodecOpusTest, DefaultApplicationModeMono) { diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc index a8c870ac9a..68ec0b937c 100644 --- a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc +++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc @@ -252,8 +252,9 @@ int64_t AudioCodingModuleImpl::TimeUntilNextProcess() { if (!HaveValidEncoder("TimeUntilNextProcess")) { return -1; } - return codecs_[current_send_codec_idx_]->SamplesLeftToEncode() / - (send_codec_inst_.plfreq / 1000); + FATAL() << "Dead code?"; +// return codecs_[current_send_codec_idx_]->SamplesLeftToEncode() / +// (send_codec_inst_.plfreq / 1000); } // Process any pending tasks such as timeouts. @@ -909,7 +910,8 @@ int AudioCodingModuleImpl::SendBitrate() const { // received from the remote party. int AudioCodingModuleImpl::SetReceivedEstimatedBandwidth(int bw) { CriticalSectionScoped lock(acm_crit_sect_); - return codecs_[current_send_codec_idx_]->SetEstimatedBandwidth(bw); + FATAL() << "Dead code?"; +// return codecs_[current_send_codec_idx_]->SetEstimatedBandwidth(bw); } // Register a transport callback which will be called to deliver @@ -1409,7 +1411,8 @@ int AudioCodingModuleImpl::DecoderEstimatedBandwidth() const { if (last_audio_codec_id >= 0 && STR_CASE_CMP("ISAC", ACMCodecDB::database_[last_audio_codec_id].plname)) { CriticalSectionScoped lock(acm_crit_sect_); - return codecs_[last_audio_codec_id]->GetEstimatedBandwidth(); + FATAL() << "Dead code?"; +// return codecs_[last_audio_codec_id]->GetEstimatedBandwidth(); } return -1; } @@ -1496,32 +1499,25 @@ int AudioCodingModuleImpl::ReplaceInternalDTXWithWebRtc(bool use_webrtc_dtx) { return -1; } - int res = codecs_[current_send_codec_idx_]->ReplaceInternalDTX( - use_webrtc_dtx); + FATAL() << "Dead code?"; +// int res = codecs_[current_send_codec_idx_]->ReplaceInternalDTX( +// use_webrtc_dtx); // Check if VAD is turned on, or if there is any error. - if (res == 1) { - vad_enabled_ = true; - } else if (res < 0) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_, - "Failed to set ReplaceInternalDTXWithWebRtc(%d)", - use_webrtc_dtx); - return res; - } +// if (res == 1) { +// vad_enabled_ = true; +// } else if (res < 0) { +// WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_, +// "Failed to set ReplaceInternalDTXWithWebRtc(%d)", +// use_webrtc_dtx); +// return res; +// } return 0; } int AudioCodingModuleImpl::IsInternalDTXReplacedWithWebRtc( bool* uses_webrtc_dtx) { - CriticalSectionScoped lock(acm_crit_sect_); - - if (!HaveValidEncoder("IsInternalDTXReplacedWithWebRtc")) { - return -1; - } - if (codecs_[current_send_codec_idx_]->IsInternalDTXReplaced(uses_webrtc_dtx) - < 0) { - return -1; - } + *uses_webrtc_dtx = true; return 0; } @@ -1556,8 +1552,9 @@ int AudioCodingModuleImpl::ConfigISACBandwidthEstimator( return -1; } - return codecs_[current_send_codec_idx_]->ConfigISACBandwidthEstimator( - frame_size_ms, rate_bit_per_sec, enforce_frame_size); + FATAL() << "Dead code?"; +// return codecs_[current_send_codec_idx_]->ConfigISACBandwidthEstimator( +// frame_size_ms, rate_bit_per_sec, enforce_frame_size); } int AudioCodingModuleImpl::SetOpusApplication(OpusApplicationMode application) { @@ -1616,12 +1613,13 @@ int AudioCodingModuleImpl::REDPayloadISAC(int isac_rate, if (!HaveValidEncoder("EncodeData")) { return -1; } - int status; - status = codecs_[current_send_codec_idx_]->REDPayloadISAC(isac_rate, - isac_bw_estimate, - payload, - length_bytes); - return status; + FATAL() << "Dead code?"; +// int status; +// status = codecs_[current_send_codec_idx_]->REDPayloadISAC(isac_rate, +// isac_bw_estimate, +// payload, +// length_bytes); +// return status; } void AudioCodingModuleImpl::ResetFragmentation(int vector_size) {