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) {