diff --git a/webrtc/modules/audio_coding/main/acm2/acm_isac.cc b/webrtc/modules/audio_coding/main/acm2/acm_isac.cc index 9fbcdd4cd..d7be97155 100644 --- a/webrtc/modules/audio_coding/main/acm2/acm_isac.cc +++ b/webrtc/modules/audio_coding/main/acm2/acm_isac.cc @@ -15,7 +15,6 @@ #include "webrtc/modules/audio_coding/main/acm2/acm_codec_database.h" #include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h" #include "webrtc/modules/audio_coding/neteq/interface/audio_decoder.h" -#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/trace.h" #ifdef WEBRTC_CODEC_ISAC @@ -60,15 +59,14 @@ static const int32_t kIsacRatesSwb[NR_ISAC_BANDWIDTHS] = { #if (!defined(WEBRTC_CODEC_ISAC) && !defined(WEBRTC_CODEC_ISACFX)) ACMISAC::ACMISAC(int16_t /* codec_id */) - : codec_inst_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), - codec_inst_ptr_(NULL), + : codec_inst_ptr_(NULL), is_enc_initialized_(false), isac_coding_mode_(CHANNEL_INDEPENDENT), enforce_frame_size_(false), isac_currentBN_(32000), samples_in10MsAudio_(160), // Initiates to 16 kHz mode. - decoder_initialized_(false) { -} + audio_decoder_(NULL), + decoder_initialized_(false) {} ACMISAC::~ACMISAC() { return; @@ -263,14 +261,81 @@ static uint16_t ACMISACFixGetDecSampRate(ACM_ISAC_STRUCT* /* inst */) { #endif +// Decoder class to be injected into NetEq. +class AcmAudioDecoderIsac : public AudioDecoder { + public: + AcmAudioDecoderIsac(int codec_id, void* state) + : AudioDecoder(ACMCodecDB::neteq_decoders_[codec_id]) { + state_ = state; + } + + // ACMISAC is the owner of the object where |state_| is pointing to. + // Therefore, it should not be deleted in this destructor. + virtual ~AcmAudioDecoderIsac() {} + + virtual int Decode(const uint8_t* encoded, size_t encoded_len, + int16_t* decoded, SpeechType* speech_type) { + int16_t temp_type; + int ret = ACM_ISAC_DECODE_B(static_cast(state_), + reinterpret_cast(encoded), + static_cast(encoded_len), decoded, + &temp_type); + *speech_type = ConvertSpeechType(temp_type); + return ret; + } + + virtual bool HasDecodePlc() const { return true; } + + virtual int DecodePlc(int num_frames, int16_t* decoded) { + return ACM_ISAC_DECODEPLC(static_cast(state_), + decoded, static_cast(num_frames)); + } + + virtual int Init() { + return 0; // We expect that the initialized instance is injected in the + // constructor. + } + + virtual int IncomingPacket(const uint8_t* payload, + size_t payload_len, + uint16_t rtp_sequence_number, + uint32_t rtp_timestamp, + uint32_t arrival_timestamp) { + return ACM_ISAC_DECODE_BWE(static_cast(state_), + reinterpret_cast(payload), + static_cast(payload_len), + rtp_sequence_number, + rtp_timestamp, + arrival_timestamp); + } + + virtual int DecodeRedundant(const uint8_t* encoded, + size_t encoded_len, int16_t* decoded, + SpeechType* speech_type) { + int16_t temp_type = 1; // Default is speech. + int16_t ret = ACM_ISAC_DECODERCU(static_cast(state_), + reinterpret_cast(encoded), + static_cast(encoded_len), decoded, + &temp_type); + *speech_type = ConvertSpeechType(temp_type); + return ret; + } + + virtual int ErrorCode() { + return ACM_ISAC_GETERRORCODE(static_cast(state_)); + } + + private: + DISALLOW_COPY_AND_ASSIGN(AcmAudioDecoderIsac); +}; + ACMISAC::ACMISAC(int16_t codec_id) - : AudioDecoder(ACMCodecDB::neteq_decoders_[codec_id]), - codec_inst_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), - is_enc_initialized_(false), + : is_enc_initialized_(false), isac_coding_mode_(CHANNEL_INDEPENDENT), enforce_frame_size_(false), isac_current_bn_(32000), samples_in_10ms_audio_(160), // Initiates to 16 kHz mode. + audio_decoder_(NULL), decoder_initialized_(false) { codec_id_ = codec_id; @@ -280,10 +345,14 @@ ACMISAC::ACMISAC(int16_t codec_id) return; } codec_inst_ptr_->inst = NULL; - state_ = codec_inst_ptr_; } ACMISAC::~ACMISAC() { + if (audio_decoder_ != NULL) { + delete audio_decoder_; + audio_decoder_ = NULL; + } + if (codec_inst_ptr_ != NULL) { if (codec_inst_ptr_->inst != NULL) { ACM_ISAC_FREE(codec_inst_ptr_->inst); @@ -295,34 +364,6 @@ ACMISAC::~ACMISAC() { return; } -int16_t ACMISAC::InternalInitDecoder(WebRtcACMCodecParams* codec_params) { - // set decoder sampling frequency. - if (codec_params->codec_inst.plfreq == 32000 || - codec_params->codec_inst.plfreq == 48000) { - UpdateDecoderSampFreq(ACMCodecDB::kISACSWB); - } else { - UpdateDecoderSampFreq(ACMCodecDB::kISAC); - } - - // in a one-way communication we may never register send-codec. - // However we like that the BWE to work properly so it has to - // be initialized. The BWE is initialized when iSAC encoder is initialized. - // Therefore, we need this. - if (!encoder_initialized_) { - // Since we don't require a valid rate or a valid packet size when - // initializing the decoder, we set valid values before initializing encoder - codec_params->codec_inst.rate = kIsacWbDefaultRate; - codec_params->codec_inst.pacsize = kIsacPacSize960; - if (InternalInitEncoder(codec_params) < 0) { - return -1; - } - encoder_initialized_ = true; - } - - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); - return ACM_ISAC_DECODERINIT(codec_inst_ptr_->inst); -} - ACMGenericCodec* ACMISAC::CreateInstance(void) { return NULL; } int16_t ACMISAC::InternalEncode(uint8_t* bitstream, @@ -334,7 +375,6 @@ int16_t ACMISAC::InternalEncode(uint8_t* bitstream, // at the first 10ms pushed in to iSAC if the bit-rate is low, this is // sort of a bug in iSAC. to address this we treat iSAC as the // following. - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); if (codec_inst_ptr_ == NULL) { return -1; } @@ -388,7 +428,6 @@ int16_t ACMISAC::InternalInitEncoder(WebRtcACMCodecParams* codec_params) { if (UpdateEncoderSampFreq((uint16_t)codec_params->codec_inst.plfreq) < 0) { return -1; } - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); if (ACM_ISAC_ENCODERINIT(codec_inst_ptr_->inst, isac_coding_mode_) < 0) { return -1; } @@ -411,8 +450,38 @@ int16_t ACMISAC::InternalInitEncoder(WebRtcACMCodecParams* codec_params) { return 0; } +int16_t ACMISAC::InternalInitDecoder(WebRtcACMCodecParams* codec_params) { + if (codec_inst_ptr_ == NULL) { + return -1; + } + + // set decoder sampling frequency. + if (codec_params->codec_inst.plfreq == 32000 || + codec_params->codec_inst.plfreq == 48000) { + UpdateDecoderSampFreq(ACMCodecDB::kISACSWB); + } else { + UpdateDecoderSampFreq(ACMCodecDB::kISAC); + } + + // in a one-way communication we may never register send-codec. + // However we like that the BWE to work properly so it has to + // be initialized. The BWE is initialized when iSAC encoder is initialized. + // Therefore, we need this. + if (!encoder_initialized_) { + // Since we don't require a valid rate or a valid packet size when + // initializing the decoder, we set valid values before initializing encoder + codec_params->codec_inst.rate = kIsacWbDefaultRate; + codec_params->codec_inst.pacsize = kIsacPacSize960; + if (InternalInitEncoder(codec_params) < 0) { + return -1; + } + encoder_initialized_ = true; + } + + return ACM_ISAC_DECODERINIT(codec_inst_ptr_->inst); +} + int16_t ACMISAC::InternalCreateEncoder() { - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); if (codec_inst_ptr_ == NULL) { return -1; } @@ -424,6 +493,19 @@ int16_t ACMISAC::InternalCreateEncoder() { return status; } +void ACMISAC::DestructEncoderSafe() { + // codec with shared instance cannot delete. + encoder_initialized_ = false; + return; +} + +void ACMISAC::InternalDestructEncoderInst(void* ptr_inst) { + if (ptr_inst != NULL) { + ACM_ISAC_FREE(static_cast(ptr_inst)); + } + return; +} + int16_t ACMISAC::Transcode(uint8_t* bitstream, int16_t* bitstream_len_byte, int16_t q_bwe, @@ -431,7 +513,6 @@ int16_t ACMISAC::Transcode(uint8_t* bitstream, bool is_red) { int16_t jitter_info = 0; // transcode from a higher rate to lower rate sanity check - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); if (codec_inst_ptr_ == NULL) { return -1; } @@ -449,27 +530,7 @@ int16_t ACMISAC::Transcode(uint8_t* bitstream, } } -void ACMISAC::UpdateFrameLen() { - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); - frame_len_smpl_ = ACM_ISAC_GETNEWFRAMELEN(codec_inst_ptr_->inst); - encoder_params_.codec_inst.pacsize = frame_len_smpl_; -} - -void ACMISAC::DestructEncoderSafe() { - // codec with shared instance cannot delete. - encoder_initialized_ = false; - return; -} - -void ACMISAC::InternalDestructEncoderInst(void* ptr_inst) { - if (ptr_inst != NULL) { - ACM_ISAC_FREE(static_cast(ptr_inst)); - } - return; -} - int16_t ACMISAC::SetBitRateSafe(int32_t bit_rate) { - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); if (codec_inst_ptr_ == NULL) { return -1; } @@ -533,7 +594,6 @@ int32_t ACMISAC::GetEstimatedBandwidthSafe() { int samp_rate; // Get bandwidth information - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); ACM_ISAC_GETSENDBWE(codec_inst_ptr_->inst, &bandwidth_index, &delay_index); // Validy check of index @@ -555,7 +615,6 @@ int32_t ACMISAC::SetEstimatedBandwidthSafe(int32_t estimated_bandwidth) { int16_t bandwidth_index; // Check sample frequency and choose appropriate table - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); samp_rate = ACM_ISAC_GETENCSAMPRATE(codec_inst_ptr_->inst); if (samp_rate == 16000) { @@ -598,7 +657,6 @@ int32_t ACMISAC::GetRedPayloadSafe( return -1; #else uint8_t* red_payload, int16_t* payload_bytes) { - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); int16_t bytes = WebRtcIsac_GetRedPayload( codec_inst_ptr_->inst, reinterpret_cast(red_payload)); @@ -614,7 +672,6 @@ int16_t ACMISAC::UpdateDecoderSampFreq( #ifdef WEBRTC_CODEC_ISAC int16_t codec_id) { // The decoder supports only wideband and super-wideband. - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); if (ACMCodecDB::kISAC == codec_id) { return WebRtcIsac_SetDecSampRate(codec_inst_ptr_->inst, 16000); } else if (ACMCodecDB::kISACSWB == codec_id || @@ -643,7 +700,6 @@ int16_t ACMISAC::UpdateEncoderSampFreq( in_audio_ix_read_ = 0; in_audio_ix_write_ = 0; in_timestamp_ix_write_ = 0; - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); if (WebRtcIsac_SetEncSampRate(codec_inst_ptr_->inst, encoder_samp_freq_hz) < 0) { return -1; @@ -662,7 +718,6 @@ int16_t ACMISAC::UpdateEncoderSampFreq( } int16_t ACMISAC::EncoderSampFreq(uint16_t* samp_freq_hz) { - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); *samp_freq_hz = ACM_ISAC_GETENCSAMPRATE(codec_inst_ptr_->inst); return 0; } @@ -675,7 +730,6 @@ int32_t ACMISAC::ConfigISACBandwidthEstimator( { uint16_t samp_freq_hz; EncoderSampFreq(&samp_freq_hz); - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); // TODO(turajs): at 32kHz we hardcode calling with 30ms and enforce // the frame-size otherwise we might get error. Revise if // control-bwe is changed. @@ -695,25 +749,26 @@ int32_t ACMISAC::ConfigISACBandwidthEstimator( return -1; } UpdateFrameLen(); - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); ACM_ISAC_GETSENDBITRATE(codec_inst_ptr_->inst, &isac_current_bn_); return 0; } int32_t ACMISAC::SetISACMaxPayloadSize(const uint16_t max_payload_len_bytes) { - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); return ACM_ISAC_SETMAXPAYLOADSIZE(codec_inst_ptr_->inst, max_payload_len_bytes); } int32_t ACMISAC::SetISACMaxRate(const uint32_t max_rate_bit_per_sec) { - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); return ACM_ISAC_SETMAXRATE(codec_inst_ptr_->inst, max_rate_bit_per_sec); } +void ACMISAC::UpdateFrameLen() { + frame_len_smpl_ = ACM_ISAC_GETNEWFRAMELEN(codec_inst_ptr_->inst); + encoder_params_.codec_inst.pacsize = frame_len_smpl_; +} + void ACMISAC::CurrentRate(int32_t* rate_bit_per_sec) { if (isac_coding_mode_ == ADAPTIVE) { - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); ACM_ISAC_GETSENDBITRATE(codec_inst_ptr_->inst, rate_bit_per_sec); } } @@ -729,71 +784,12 @@ int16_t ACMISAC::REDPayloadISAC(const int32_t isac_rate, return status; } -int ACMISAC::Decode(const uint8_t* encoded, - size_t encoded_len, - int16_t* decoded, - SpeechType* speech_type) { - int16_t temp_type; - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); - int ret = - ACM_ISAC_DECODE_B(static_cast(codec_inst_ptr_->inst), - reinterpret_cast(encoded), - static_cast(encoded_len), - decoded, - &temp_type); - *speech_type = ConvertSpeechType(temp_type); - return ret; -} - -int ACMISAC::DecodePlc(int num_frames, int16_t* decoded) { - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); - return ACM_ISAC_DECODEPLC( - static_cast(codec_inst_ptr_->inst), - decoded, - static_cast(num_frames)); -} - -int ACMISAC::IncomingPacket(const uint8_t* payload, - size_t payload_len, - uint16_t rtp_sequence_number, - uint32_t rtp_timestamp, - uint32_t arrival_timestamp) { - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); - return ACM_ISAC_DECODE_BWE( - static_cast(codec_inst_ptr_->inst), - reinterpret_cast(payload), - static_cast(payload_len), - rtp_sequence_number, - rtp_timestamp, - arrival_timestamp); -} - -int ACMISAC::DecodeRedundant(const uint8_t* encoded, - size_t encoded_len, - int16_t* decoded, - SpeechType* speech_type) { - int16_t temp_type = 1; // Default is speech. - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); - int16_t ret = - ACM_ISAC_DECODERCU(static_cast(codec_inst_ptr_->inst), - reinterpret_cast(encoded), - static_cast(encoded_len), - decoded, - &temp_type); - *speech_type = ConvertSpeechType(temp_type); - return ret; -} - -int ACMISAC::ErrorCode() { - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); - return ACM_ISAC_GETERRORCODE( - static_cast(codec_inst_ptr_->inst)); -} - AudioDecoder* ACMISAC::Decoder(int codec_id) { + if (audio_decoder_) + return audio_decoder_; + // Create iSAC instance if it does not exist. if (!encoder_exist_) { - CriticalSectionScoped lock(codec_inst_crit_sect_.get()); assert(codec_inst_ptr_->inst == NULL); encoder_initialized_ = false; decoder_initialized_ = false; @@ -826,7 +822,8 @@ AudioDecoder* ACMISAC::Decoder(int codec_id) { decoder_initialized_ = true; } - return this; + audio_decoder_ = new AcmAudioDecoderIsac(codec_id, codec_inst_ptr_->inst); + return audio_decoder_; } #endif diff --git a/webrtc/modules/audio_coding/main/acm2/acm_isac.h b/webrtc/modules/audio_coding/main/acm2/acm_isac.h index 3249526f7..a3227d5d0 100644 --- a/webrtc/modules/audio_coding/main/acm2/acm_isac.h +++ b/webrtc/modules/audio_coding/main/acm2/acm_isac.h @@ -12,119 +12,86 @@ #define WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_ACM_ISAC_H_ #include "webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h" -#include "webrtc/modules/audio_coding/neteq/interface/audio_decoder.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" -#include "webrtc/system_wrappers/interface/thread_annotations.h" namespace webrtc { -class CriticalSectionWrapper; - namespace acm2 { struct ACMISACInst; +class AcmAudioDecoderIsac; enum IsacCodingMode { ADAPTIVE, CHANNEL_INDEPENDENT }; -class ACMISAC : public ACMGenericCodec, AudioDecoder { +class ACMISAC : public ACMGenericCodec { public: explicit ACMISAC(int16_t codec_id); ~ACMISAC(); + // for FEC + ACMGenericCodec* CreateInstance(void); + + int16_t InternalEncode(uint8_t* bitstream, int16_t* bitstream_len_byte); + + int16_t InternalInitEncoder(WebRtcACMCodecParams* codec_params); + int16_t InternalInitDecoder(WebRtcACMCodecParams* codec_params); - // Methods below are inherited from ACMGenericCodec. - ACMGenericCodec* CreateInstance(void) OVERRIDE; + int16_t UpdateDecoderSampFreq(int16_t codec_id); - int16_t InternalEncode(uint8_t* bitstream, - int16_t* bitstream_len_byte) OVERRIDE; + int16_t UpdateEncoderSampFreq(uint16_t samp_freq_hz); - int16_t InternalInitEncoder(WebRtcACMCodecParams* codec_params) OVERRIDE; - - int16_t UpdateDecoderSampFreq(int16_t codec_id) OVERRIDE; - - int16_t UpdateEncoderSampFreq(uint16_t samp_freq_hz) OVERRIDE; - - int16_t EncoderSampFreq(uint16_t* samp_freq_hz) OVERRIDE; + int16_t EncoderSampFreq(uint16_t* samp_freq_hz); int32_t ConfigISACBandwidthEstimator(const uint8_t init_frame_size_msec, const uint16_t init_rate_bit_per_sec, - const bool enforce_frame_size) OVERRIDE; + const bool enforce_frame_size); - int32_t SetISACMaxPayloadSize(const uint16_t max_payload_len_bytes) OVERRIDE; + int32_t SetISACMaxPayloadSize(const uint16_t max_payload_len_bytes); - int32_t SetISACMaxRate(const uint32_t max_rate_bit_per_sec) OVERRIDE; + int32_t SetISACMaxRate(const uint32_t max_rate_bit_per_sec); int16_t REDPayloadISAC(const int32_t isac_rate, const int16_t isac_bw_estimate, uint8_t* payload, - int16_t* payload_len_bytes) OVERRIDE; - - // Methods below are inherited from AudioDecoder. - virtual int Decode(const uint8_t* encoded, - size_t encoded_len, - int16_t* decoded, - SpeechType* speech_type) OVERRIDE; - - virtual bool HasDecodePlc() const OVERRIDE { return true; } - - virtual int DecodePlc(int num_frames, int16_t* decoded) OVERRIDE; - - virtual int Init() OVERRIDE { return 0; } - - virtual int IncomingPacket(const uint8_t* payload, - size_t payload_len, - uint16_t rtp_sequence_number, - uint32_t rtp_timestamp, - uint32_t arrival_timestamp) OVERRIDE; - - virtual int DecodeRedundant(const uint8_t* encoded, - size_t encoded_len, - int16_t* decoded, - SpeechType* speech_type) OVERRIDE; - - virtual int ErrorCode() OVERRIDE; + int16_t* payload_len_bytes); protected: + void DestructEncoderSafe(); + + int16_t SetBitRateSafe(const int32_t bit_rate); + + int32_t GetEstimatedBandwidthSafe(); + + int32_t SetEstimatedBandwidthSafe(int32_t estimated_bandwidth); + + int32_t GetRedPayloadSafe(uint8_t* red_payload, int16_t* payload_bytes); + + int16_t InternalCreateEncoder(); + + void InternalDestructEncoderInst(void* ptr_inst); + int16_t Transcode(uint8_t* bitstream, int16_t* bitstream_len_byte, int16_t q_bwe, int32_t rate, bool is_red); + void CurrentRate(int32_t* rate_bit_per_sec); + void UpdateFrameLen(); - // Methods below are inherited from ACMGenericCodec. - void DestructEncoderSafe() OVERRIDE; + virtual AudioDecoder* Decoder(int codec_id); - int16_t SetBitRateSafe(const int32_t bit_rate) OVERRIDE; - - int32_t GetEstimatedBandwidthSafe() OVERRIDE; - - int32_t SetEstimatedBandwidthSafe(int32_t estimated_bandwidth) OVERRIDE; - - int32_t GetRedPayloadSafe(uint8_t* red_payload, - int16_t* payload_bytes) OVERRIDE; - - int16_t InternalCreateEncoder() OVERRIDE; - - void InternalDestructEncoderInst(void* ptr_inst) OVERRIDE; - - void CurrentRate(int32_t* rate_bit_per_sec) OVERRIDE; - - virtual AudioDecoder* Decoder(int codec_id) OVERRIDE; - - // |codec_inst_crit_sect_| protects |codec_inst_ptr_|. - const scoped_ptr codec_inst_crit_sect_; - ACMISACInst* codec_inst_ptr_ GUARDED_BY(codec_inst_crit_sect_); + ACMISACInst* codec_inst_ptr_; bool is_enc_initialized_; IsacCodingMode isac_coding_mode_; bool enforce_frame_size_; int32_t isac_current_bn_; uint16_t samples_in_10ms_audio_; + AcmAudioDecoderIsac* audio_decoder_; bool decoder_initialized_; };