diff --git a/webrtc/modules/audio_coding/codecs/audio_encoder.cc b/webrtc/modules/audio_coding/codecs/audio_encoder.cc index 20e59537b..ae1bce179 100644 --- a/webrtc/modules/audio_coding/codecs/audio_encoder.cc +++ b/webrtc/modules/audio_coding/codecs/audio_encoder.cc @@ -9,6 +9,7 @@ */ #include "webrtc/modules/audio_coding/codecs/audio_encoder.h" +#include "webrtc/base/checks.h" namespace webrtc { @@ -18,6 +19,20 @@ AudioEncoder::EncodedInfo::EncodedInfo() : EncodedInfoLeaf() { AudioEncoder::EncodedInfo::~EncodedInfo() { } +bool AudioEncoder::Encode(uint32_t rtp_timestamp, + const int16_t* audio, + size_t num_samples_per_channel, + size_t max_encoded_bytes, + uint8_t* encoded, + EncodedInfo* info) { + CHECK_EQ(num_samples_per_channel, + static_cast(sample_rate_hz() / 100)); + bool ret = + EncodeInternal(rtp_timestamp, audio, max_encoded_bytes, encoded, info); + CHECK_LE(info->encoded_bytes, max_encoded_bytes); + return ret; +} + int AudioEncoder::rtp_timestamp_rate_hz() const { return sample_rate_hz(); } diff --git a/webrtc/modules/audio_coding/codecs/audio_encoder.h b/webrtc/modules/audio_coding/codecs/audio_encoder.h index 9b0c11bb1..6fc5827f0 100644 --- a/webrtc/modules/audio_coding/codecs/audio_encoder.h +++ b/webrtc/modules/audio_coding/codecs/audio_encoder.h @@ -14,7 +14,6 @@ #include #include -#include "webrtc/base/checks.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -63,14 +62,7 @@ class AudioEncoder { size_t num_samples_per_channel, size_t max_encoded_bytes, uint8_t* encoded, - EncodedInfo* info) { - CHECK_EQ(num_samples_per_channel, - static_cast(sample_rate_hz() / 100)); - bool ret = - EncodeInternal(rtp_timestamp, audio, max_encoded_bytes, encoded, info); - CHECK_LE(info->encoded_bytes, max_encoded_bytes); - return ret; - } + EncodedInfo* info); // Return the input sample rate in Hz and the number of input channels. // These are constants set at instantiation time. diff --git a/webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc b/webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc index 5b072e469..c2f642471 100644 --- a/webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc +++ b/webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc @@ -12,6 +12,7 @@ #include +#include "webrtc/base/checks.h" #include "webrtc/modules/audio_coding/codecs/g711/include/g711_interface.h" namespace webrtc { diff --git a/webrtc/modules/audio_coding/codecs/isac/fix/interface/audio_encoder_isacfix.h b/webrtc/modules/audio_coding/codecs/isac/fix/interface/audio_encoder_isacfix.h index 4982e5a8d..2727611cb 100644 --- a/webrtc/modules/audio_coding/codecs/isac/fix/interface/audio_encoder_isacfix.h +++ b/webrtc/modules/audio_coding/codecs/isac/fix/interface/audio_encoder_isacfix.h @@ -11,6 +11,7 @@ #ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INTERFACE_AUDIO_ENCODER_ISACFIX_H_ #define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INTERFACE_AUDIO_ENCODER_ISACFIX_H_ +#include "webrtc/base/checks.h" #include "webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h" #include "webrtc/modules/audio_coding/codecs/isac/fix/interface/isacfix.h" diff --git a/webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h b/webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h index 41ed490d7..4ab88b643 100644 --- a/webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h +++ b/webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h @@ -11,6 +11,7 @@ #ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INTERFACE_AUDIO_ENCODER_ISAC_H_ #define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INTERFACE_AUDIO_ENCODER_ISAC_H_ +#include "webrtc/base/checks.h" #include "webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h" #include "webrtc/modules/audio_coding/codecs/isac/main/interface/isac.h" diff --git a/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc b/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc index c3d5601bb..2b0fb9130 100644 --- a/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc +++ b/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc @@ -12,6 +12,8 @@ #include +#include "webrtc/base/checks.h" + namespace webrtc { AudioEncoderCopyRed::AudioEncoderCopyRed(const Config& config) diff --git a/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red_unittest.cc b/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red_unittest.cc index 35a8b2f3f..de1339dbb 100644 --- a/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red_unittest.cc +++ b/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red_unittest.cc @@ -9,6 +9,7 @@ */ #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/checks.h" #include "webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h" #include "webrtc/modules/audio_coding/codecs/mock/mock_audio_encoder.h" #include "webrtc/system_wrappers/interface/scoped_ptr.h" 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 209d589c9..c65e0530c 100644 --- a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc +++ b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc @@ -12,15 +12,59 @@ #include #include +#include +#include +#include "webrtc/base/checks.h" #include "webrtc/common_audio/vad/include/webrtc_vad.h" +#include "webrtc/modules/audio_coding/codecs/cng/include/audio_encoder_cng.h" #include "webrtc/modules/audio_coding/codecs/cng/include/webrtc_cng.h" +#include "webrtc/modules/audio_coding/codecs/g711/include/audio_encoder_pcm.h" +#include "webrtc/modules/audio_coding/codecs/g722/include/audio_encoder_g722.h" +#include "webrtc/modules/audio_coding/codecs/ilbc/interface/audio_encoder_ilbc.h" +#include "webrtc/modules/audio_coding/codecs/isac/fix/interface/audio_encoder_isacfix.h" +#include "webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h" +#include "webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h" +#include "webrtc/modules/audio_coding/codecs/pcm16b/include/audio_encoder_pcm16b.h" +#include "webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h" #include "webrtc/modules/audio_coding/main/acm2/acm_codec_database.h" #include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h" #include "webrtc/system_wrappers/interface/trace.h" namespace webrtc { +namespace { +static const int kInvalidPayloadType = 255; + +void SetCngPtInMap( + std::map>* cng_pt_map, + int sample_rate_hz, + int payload_type) { + if (payload_type == kInvalidPayloadType) + return; + CHECK_GE(payload_type, 0); + CHECK_LT(payload_type, 128); + WebRtcACMEncodingType encoding_type; + switch (sample_rate_hz) { + case 8000: + encoding_type = kPassiveDTXNB; + break; + case 16000: + encoding_type = kPassiveDTXWB; + break; + case 32000: + encoding_type = kPassiveDTXSWB; + break; + case 48000: + encoding_type = kPassiveDTXFB; + break; + default: + FATAL() << "Unsupported frequency."; + } + (*cng_pt_map)[payload_type] = std::make_pair(sample_rate_hz, encoding_type); +} +} // namespace + namespace acm2 { // Enum for CNG @@ -216,7 +260,8 @@ bool ACMGenericCodec::ExternalRedNeeded() { int16_t ACMGenericCodec::Encode(uint8_t* bitstream, int16_t* bitstream_len_byte, uint32_t* timestamp, - WebRtcACMEncodingType* encoding_type) { + WebRtcACMEncodingType* encoding_type, + AudioEncoder::EncodedInfo* /*encoded_info*/) { if (!HasFrameToEncode()) { // There is not enough audio *timestamp = 0; @@ -651,6 +696,9 @@ int16_t ACMGenericCodec::SetVAD(bool* enable_dtx, 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) { @@ -1022,6 +1070,663 @@ int ACMGenericCodec::SetOpusMaxPlaybackRate(int /* frequency_hz */) { return -1; } +AudioDecoderProxy::AudioDecoderProxy() + : decoder_lock_(CriticalSectionWrapper::CreateCriticalSection()), + decoder_(nullptr) { +} + +void AudioDecoderProxy::SetDecoder(AudioDecoder* decoder) { + CriticalSectionScoped decoder_lock(decoder_lock_.get()); + decoder_ = decoder; + channels_ = decoder->channels(); + CHECK_EQ(decoder_->Init(), 0); +} + +bool AudioDecoderProxy::IsSet() const { + CriticalSectionScoped decoder_lock(decoder_lock_.get()); + return (decoder_ != nullptr); +} + +int AudioDecoderProxy::Decode(const uint8_t* encoded, + size_t encoded_len, + int16_t* decoded, + SpeechType* speech_type) { + CriticalSectionScoped decoder_lock(decoder_lock_.get()); + return decoder_->Decode(encoded, encoded_len, decoded, speech_type); +} + +int AudioDecoderProxy::DecodeRedundant(const uint8_t* encoded, + size_t encoded_len, + int16_t* decoded, + SpeechType* speech_type) { + CriticalSectionScoped decoder_lock(decoder_lock_.get()); + return decoder_->DecodeRedundant(encoded, encoded_len, decoded, speech_type); +} + +bool AudioDecoderProxy::HasDecodePlc() const { + CriticalSectionScoped decoder_lock(decoder_lock_.get()); + return decoder_->HasDecodePlc(); +} + +int AudioDecoderProxy::DecodePlc(int num_frames, int16_t* decoded) { + CriticalSectionScoped decoder_lock(decoder_lock_.get()); + return decoder_->DecodePlc(num_frames, decoded); +} + +int AudioDecoderProxy::Init() { + CriticalSectionScoped decoder_lock(decoder_lock_.get()); + return decoder_->Init(); +} + +int AudioDecoderProxy::IncomingPacket(const uint8_t* payload, + size_t payload_len, + uint16_t rtp_sequence_number, + uint32_t rtp_timestamp, + uint32_t arrival_timestamp) { + CriticalSectionScoped decoder_lock(decoder_lock_.get()); + return decoder_->IncomingPacket(payload, payload_len, rtp_sequence_number, + rtp_timestamp, arrival_timestamp); +} + +int AudioDecoderProxy::ErrorCode() { + CriticalSectionScoped decoder_lock(decoder_lock_.get()); + return decoder_->ErrorCode(); +} + +int AudioDecoderProxy::PacketDuration(const uint8_t* encoded, + size_t encoded_len) { + CriticalSectionScoped decoder_lock(decoder_lock_.get()); + return decoder_->PacketDuration(encoded, encoded_len); +} + +int AudioDecoderProxy::PacketDurationRedundant(const uint8_t* encoded, + size_t encoded_len) const { + CriticalSectionScoped decoder_lock(decoder_lock_.get()); + return decoder_->PacketDurationRedundant(encoded, encoded_len); +} + +bool AudioDecoderProxy::PacketHasFec(const uint8_t* encoded, + size_t encoded_len) const { + CriticalSectionScoped decoder_lock(decoder_lock_.get()); + return decoder_->PacketHasFec(encoded, encoded_len); +} + +CNG_dec_inst* AudioDecoderProxy::CngDecoderInstance() { + CriticalSectionScoped decoder_lock(decoder_lock_.get()); + 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) { + WriteLockScoped wl(codec_wrapper_lock_); + CHECK(!input_.empty()); + CHECK(encoder_->Encode(rtp_timestamp_, &input_[0], + input_.size() / encoder_->num_channels(), + 2 * MAX_PAYLOAD_SIZE_BYTE, bitstream, encoded_info)); + input_.clear(); + *bitstream_len_byte = static_cast(encoded_info->encoded_bytes); + if (encoded_info->encoded_bytes == 0) { + *encoding_type = kNoEncoding; + return 0; + } + *timestamp = encoded_info->encoded_timestamp; + + int payload_type = encoded_info->payload_type; + if (!encoded_info->redundant.empty()) + payload_type = encoded_info->redundant[0].payload_type; + + auto cng_iter = cng_pt_.find(payload_type); + if (cng_iter == cng_pt_.end()) { + *encoding_type = kActiveNormalEncoded; + } else { + *encoding_type = cng_iter->second.second; + } + return *bitstream_len_byte; +} + +bool ACMGenericCodecWrapper::EncoderInitialized() { + FATAL(); + return 0; +} + +int16_t ACMGenericCodecWrapper::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) { + WriteLockScoped wl(codec_wrapper_lock_); + bitrate_bps_ = 0; + loss_rate_ = 0; + acm_codec_params_ = *codec_params; + if (force_initialization) + opus_application_set_ = false; + opus_application_ = GetOpusApplication(codec_params->codec_inst.channels); + opus_application_set_ = true; + ResetAudioEncoder(); + return 0; +} + +void ACMGenericCodecWrapper::ResetAudioEncoder() { + const CodecInst& codec_inst = acm_codec_params_.codec_inst; + bool using_codec_internal_red = false; + if (!STR_CASE_CMP(codec_inst.plname, "PCMU")) { + AudioEncoderPcmU::Config config; + config.num_channels = codec_inst.channels; + config.frame_size_ms = codec_inst.pacsize / 8; + config.payload_type = codec_inst.pltype; + audio_encoder_.reset(new AudioEncoderPcmU(config)); + } else if (!STR_CASE_CMP(codec_inst.plname, "PCMA")) { + AudioEncoderPcmA::Config config; + config.num_channels = codec_inst.channels; + config.frame_size_ms = codec_inst.pacsize / 8; + config.payload_type = codec_inst.pltype; + audio_encoder_.reset(new AudioEncoderPcmA(config)); +#ifdef WEBRTC_CODEC_PCM16 + } else if (!STR_CASE_CMP(codec_inst.plname, "L16")) { + AudioEncoderPcm16B::Config config; + config.num_channels = codec_inst.channels; + config.sample_rate_hz = codec_inst.plfreq; + config.frame_size_ms = codec_inst.pacsize / (config.sample_rate_hz / 1000); + config.payload_type = codec_inst.pltype; + audio_encoder_.reset(new AudioEncoderPcm16B(config)); +#endif +#ifdef WEBRTC_CODEC_ILBC + } else if (!STR_CASE_CMP(codec_inst.plname, "ILBC")) { + AudioEncoderIlbc::Config config; + config.frame_size_ms = codec_inst.pacsize / 8; + config.payload_type = codec_inst.pltype; + audio_encoder_.reset(new AudioEncoderIlbc(config)); +#endif +#ifdef WEBRTC_CODEC_OPUS + } else if (!STR_CASE_CMP(codec_inst.plname, "opus")) { + is_opus_ = true; + has_internal_fec_ = true; + AudioEncoderOpus::Config config; + config.frame_size_ms = codec_inst.pacsize / 48; + config.num_channels = codec_inst.channels; + config.fec_enabled = fec_enabled_; + config.bitrate_bps = codec_inst.rate; + config.max_playback_rate_hz = max_playback_rate_hz_; + config.payload_type = codec_inst.pltype; + switch (GetOpusApplication(config.num_channels)) { + case kVoip: + config.application = AudioEncoderOpus::ApplicationMode::kVoip; + break; + case kAudio: + config.application = AudioEncoderOpus::ApplicationMode::kAudio; + break; + } + audio_encoder_.reset(new AudioEncoderOpus(config)); +#endif +#ifdef WEBRTC_CODEC_G722 + } else if (!STR_CASE_CMP(codec_inst.plname, "G722")) { + AudioEncoderG722::Config config; + config.num_channels = codec_inst.channels; + config.frame_size_ms = codec_inst.pacsize / 16; + config.payload_type = codec_inst.pltype; + audio_encoder_.reset(new AudioEncoderG722(config)); +#endif +#ifdef WEBRTC_CODEC_ISACFX + } else if (!STR_CASE_CMP(codec_inst.plname, "ISAC")) { + DCHECK_EQ(codec_inst.plfreq, 16000); + is_isac_ = true; + AudioEncoderDecoderIsacFix* enc_dec; + if (codec_inst.rate == -1) { + // Adaptive mode. + AudioEncoderDecoderIsacFix::ConfigAdaptive config; + config.payload_type = codec_inst.pltype; + enc_dec = new AudioEncoderDecoderIsacFix(config); + } else { + // Channel independent mode. + AudioEncoderDecoderIsacFix::Config config; + config.bit_rate = codec_inst.rate; + config.frame_size_ms = codec_inst.pacsize / 16; + config.payload_type = codec_inst.pltype; + enc_dec = new AudioEncoderDecoderIsacFix(config); + } + audio_encoder_.reset(enc_dec); + decoder_proxy_.SetDecoder(enc_dec); +#endif +#ifdef WEBRTC_CODEC_ISAC + } else if (!STR_CASE_CMP(codec_inst.plname, "ISAC")) { + is_isac_ = true; + if (copy_red_enabled_) { + using_codec_internal_red = true; + AudioEncoderDecoderIsacRed* enc_dec; + if (codec_inst.rate == -1) { + // Adaptive mode. + AudioEncoderDecoderIsacRed::ConfigAdaptive config; + config.sample_rate_hz = codec_inst.plfreq; + config.initial_frame_size_ms = rtc::CheckedDivExact( + 1000 * codec_inst.pacsize, config.sample_rate_hz); + config.max_payload_size_bytes = max_payload_size_bytes_; + config.max_bit_rate = max_rate_bps_; + config.payload_type = codec_inst.pltype; + config.red_payload_type = red_payload_type_; + enc_dec = new AudioEncoderDecoderIsacRed(config); + } else { + // Channel independent mode. + AudioEncoderDecoderIsacRed::Config config; + config.sample_rate_hz = codec_inst.plfreq; + config.bit_rate = codec_inst.rate; + config.frame_size_ms = rtc::CheckedDivExact(1000 * codec_inst.pacsize, + config.sample_rate_hz); + config.max_payload_size_bytes = max_payload_size_bytes_; + config.max_bit_rate = max_rate_bps_; + config.payload_type = codec_inst.pltype; + config.red_payload_type = red_payload_type_; + enc_dec = new AudioEncoderDecoderIsacRed(config); + } + audio_encoder_.reset(enc_dec); + decoder_proxy_.SetDecoder(enc_dec); + } else { + AudioEncoderDecoderIsac* enc_dec; + if (codec_inst.rate == -1) { + // Adaptive mode. + AudioEncoderDecoderIsac::ConfigAdaptive config; + config.sample_rate_hz = codec_inst.plfreq; + config.initial_frame_size_ms = rtc::CheckedDivExact( + 1000 * codec_inst.pacsize, config.sample_rate_hz); + config.max_payload_size_bytes = max_payload_size_bytes_; + config.max_bit_rate = max_rate_bps_; + config.payload_type = codec_inst.pltype; + enc_dec = new AudioEncoderDecoderIsac(config); + } else { + // Channel independent mode. + AudioEncoderDecoderIsac::Config config; + config.sample_rate_hz = codec_inst.plfreq; + config.bit_rate = codec_inst.rate; + config.frame_size_ms = rtc::CheckedDivExact(1000 * codec_inst.pacsize, + config.sample_rate_hz); + config.max_payload_size_bytes = max_payload_size_bytes_; + config.max_bit_rate = max_rate_bps_; + config.payload_type = codec_inst.pltype; + enc_dec = new AudioEncoderDecoderIsac(config); + } + audio_encoder_.reset(enc_dec); + decoder_proxy_.SetDecoder(enc_dec); + } +#endif + } else { + FATAL(); + } + if (bitrate_bps_ != 0) + audio_encoder_->SetTargetBitrate(bitrate_bps_); + audio_encoder_->SetProjectedPacketLossRate(loss_rate_ / 100.0); + encoder_ = audio_encoder_.get(); + + // Attach RED if needed. + if (copy_red_enabled_ && !using_codec_internal_red) { + CHECK_NE(red_payload_type_, kInvalidPayloadType); + AudioEncoderCopyRed::Config config; + config.payload_type = red_payload_type_; + config.speech_encoder = encoder_; + red_encoder_.reset(new AudioEncoderCopyRed(config)); + encoder_ = red_encoder_.get(); + } else { + red_encoder_.reset(); + } + + // Attach CNG if needed. + // Reverse-lookup from sample rate to complete key-value pair. + const int sample_rate_hz = audio_encoder_->sample_rate_hz(); + // Create a local const reference to cng_pt_. The reason is that GCC doesn't + // accept using "const decltype(...)" for the argument in the lambda below. + const auto& cng_pt = cng_pt_; + auto pt_iter = find_if(cng_pt.begin(), cng_pt.end(), + [sample_rate_hz](decltype(*cng_pt.begin()) p) { + return p.second.first == sample_rate_hz; + }); + if (acm_codec_params_.enable_dtx && pt_iter != cng_pt_.end()) { + AudioEncoderCng::Config config; + config.num_channels = acm_codec_params_.codec_inst.channels; + config.payload_type = pt_iter->first; + config.speech_encoder = encoder_; + switch (acm_codec_params_.vad_mode) { + case VADNormal: + config.vad_mode = Vad::kVadNormal; + break; + case VADLowBitrate: + config.vad_mode = Vad::kVadLowBitrate; + break; + case VADAggr: + config.vad_mode = Vad::kVadAggressive; + break; + case VADVeryAggr: + config.vad_mode = Vad::kVadVeryAggressive; + break; + default: + FATAL(); + } + cng_encoder_.reset(new AudioEncoderCng(config)); + encoder_ = cng_encoder_.get(); + } else { + cng_encoder_.reset(); + } +} + +OpusApplicationMode ACMGenericCodecWrapper::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) { + WriteLockScoped wl(codec_wrapper_lock_); + CHECK(input_.empty()); + CHECK_EQ(length_per_channel, encoder_->sample_rate_hz() / 100); + for (int i = 0; i < length_per_channel * encoder_->num_channels(); ++i) { + input_.push_back(data[i]); + } + rtp_timestamp_ = first_frame_ + ? timestamp + : last_rtp_timestamp_ + + rtc::CheckedDivExact( + timestamp - last_timestamp_, + static_cast(rtc::CheckedDivExact( + audio_encoder_->sample_rate_hz(), + audio_encoder_->rtp_timestamp_rate_hz()))); + last_timestamp_ = timestamp; + last_rtp_timestamp_ = rtp_timestamp_; + first_frame_ = false; + + CHECK_EQ(audio_channel, encoder_->num_channels()); + return 0; +} + +uint32_t ACMGenericCodecWrapper::NoMissedSamples() const { + FATAL(); + return 0; +} + +void ACMGenericCodecWrapper::ResetNoMissedSamples() { + FATAL(); +} + +int16_t ACMGenericCodecWrapper::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) { + WriteLockScoped wl(codec_wrapper_lock_); + if (is_opus_) { + *enable_dtx = false; + *enable_vad = false; + return 0; + } + // Note: |enable_vad| is not used; VAD is enabled based on the DTX setting and + // the |enable_vad| is set equal to |enable_dtx|. + // The case when VAD is enabled but DTX is disabled may result in a + // kPassiveNormalEncoded frame type, but this is not a case that VoE + // distinguishes from the cases where DTX is in fact used. In the case where + // DTX is enabled but VAD is disabled, the comment in the ACM interface states + // that VAD will be enabled anyway. + DCHECK_EQ(*enable_dtx, *enable_vad); + *enable_vad = *enable_dtx; + acm_codec_params_.enable_dtx = *enable_dtx; + acm_codec_params_.enable_vad = *enable_vad; + acm_codec_params_.vad_mode = *mode; + if (acm_codec_params_.enable_dtx && !cng_encoder_) { + ResetAudioEncoder(); + } else if (!acm_codec_params_.enable_dtx && cng_encoder_) { + cng_encoder_.reset(); + encoder_ = audio_encoder_.get(); + } + return 0; +} + +void ACMGenericCodecWrapper::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) { + FATAL(); + return 0; +} + +int32_t ACMGenericCodecWrapper::GetEstimatedBandwidth() { + FATAL(); + return 0; +} + +int32_t ACMGenericCodecWrapper::SetEstimatedBandwidth( + int32_t estimated_bandwidth) { + FATAL(); + return 0; +} + +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) { + // Do nothing. +} + +int16_t ACMGenericCodecWrapper::UpdateDecoderSampFreq(int16_t codec_id) { +#ifdef WEBRTC_CODEC_ISAC + WriteLockScoped wl(codec_wrapper_lock_); + if (is_isac_) { + switch (codec_id) { + case ACMCodecDB::kISAC: + static_cast(audio_encoder_.get()) + ->UpdateDecoderSampleRate(16000); + return 0; + case ACMCodecDB::kISACSWB: + case ACMCodecDB::kISACFB: + static_cast(audio_encoder_.get()) + ->UpdateDecoderSampleRate(32000); + return 0; + default: + FATAL() << "Unexpected codec id."; + } + } +#endif + 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( + const uint16_t max_payload_len_bytes) { + WriteLockScoped wl(codec_wrapper_lock_); + if (!is_isac_) + return -1; // Needed for tests to pass. + max_payload_size_bytes_ = max_payload_len_bytes; + ResetAudioEncoder(); + return 0; +} + +int32_t ACMGenericCodecWrapper::SetISACMaxRate(const uint32_t max_rate_bps) { + WriteLockScoped wl(codec_wrapper_lock_); + if (!is_isac_) + return -1; // Needed for tests to pass. + max_rate_bps_ = max_rate_bps; + ResetAudioEncoder(); + 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) { + WriteLockScoped wl(codec_wrapper_lock_); + if (!is_opus_) + return -1; // Needed for tests to pass. + max_playback_rate_hz_ = frequency_hz; + ResetAudioEncoder(); + return 0; +} + +bool ACMGenericCodecWrapper::HasFrameToEncode() const { + FATAL(); + return 0; +} + +AudioDecoder* ACMGenericCodecWrapper::Decoder(int /* codec_id */) { + ReadLockScoped rl(codec_wrapper_lock_); + return decoder_proxy_.IsSet() ? &decoder_proxy_ : nullptr; +} + +int ACMGenericCodecWrapper::SetFEC(bool enable_fec) { + if (!HasInternalFEC()) + return enable_fec ? -1 : 0; + WriteLockScoped wl(codec_wrapper_lock_); + if (fec_enabled_ != enable_fec) { + fec_enabled_ = enable_fec; + ResetAudioEncoder(); + } + return 0; +} + +int ACMGenericCodecWrapper::SetOpusApplication( + OpusApplicationMode application) { + WriteLockScoped wl(codec_wrapper_lock_); + opus_application_ = application; + opus_application_set_ = true; + ResetAudioEncoder(); + return 0; +} + +int ACMGenericCodecWrapper::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); + WriteLockScoped wl(codec_wrapper_lock_); + red_payload_type_ = red_payload_type; + ResetAudioEncoder(); +} + +bool ACMGenericCodecWrapper::ExternalRedNeeded() { + return false; +} + +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 9d045109f..d2caea792 100644 --- a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h +++ b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h @@ -11,12 +11,17 @@ #ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_ACM_GENERIC_CODEC_H_ #define WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_ACM_GENERIC_CODEC_H_ +#include + #include "webrtc/base/thread_annotations.h" #include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h" #include "webrtc/modules/audio_coding/codecs/audio_decoder.h" +#include "webrtc/modules/audio_coding/codecs/audio_encoder.h" #include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h" #include "webrtc/modules/audio_coding/neteq/interface/neteq.h" +#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/rw_lock_wrapper.h" +#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/system_wrappers/interface/trace.h" #define MAX_FRAME_SIZE_10MSEC 6 @@ -106,10 +111,11 @@ class ACMGenericCodec { // -1 if error is occurred, otherwise the length of the bit-stream in // bytes. // - int16_t Encode(uint8_t* bitstream, - int16_t* bitstream_len_byte, - uint32_t* timestamp, - WebRtcACMEncodingType* encoding_type); + virtual int16_t Encode(uint8_t* bitstream, + int16_t* bitstream_len_byte, + uint32_t* timestamp, + WebRtcACMEncodingType* encoding_type, + AudioEncoder::EncodedInfo* encoded_info); /////////////////////////////////////////////////////////////////////////// // bool EncoderInitialized(); @@ -118,7 +124,7 @@ class ACMGenericCodec { // True if the encoder is successfully initialized, // false otherwise. // - bool EncoderInitialized(); + virtual bool EncoderInitialized(); /////////////////////////////////////////////////////////////////////////// // int16_t EncoderParams() @@ -134,7 +140,7 @@ class ACMGenericCodec { // -1 if the encoder is not initialized, // 0 otherwise. // - int16_t EncoderParams(WebRtcACMCodecParams* enc_params); + virtual int16_t EncoderParams(WebRtcACMCodecParams* enc_params); /////////////////////////////////////////////////////////////////////////// // int16_t InitEncoder(...) @@ -152,8 +158,8 @@ class ACMGenericCodec { // -1 if failed to initialize. // // - int16_t InitEncoder(WebRtcACMCodecParams* codec_params, - bool force_initialization); + virtual int16_t InitEncoder(WebRtcACMCodecParams* codec_params, + bool force_initialization); /////////////////////////////////////////////////////////////////////////// // int32_t Add10MsData(...) @@ -174,10 +180,10 @@ class ACMGenericCodec { // -1 if failed // 0 otherwise. // - int32_t Add10MsData(const uint32_t timestamp, - const int16_t* data, - const uint16_t length, - const uint8_t audio_channel); + virtual int32_t Add10MsData(const uint32_t timestamp, + const int16_t* data, + const uint16_t length, + const uint8_t audio_channel); /////////////////////////////////////////////////////////////////////////// // uint32_t NoMissedSamples() @@ -189,14 +195,14 @@ class ACMGenericCodec { // Return Value: // Number of samples which are overwritten. // - uint32_t NoMissedSamples() const; + virtual 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()) // - void ResetNoMissedSamples(); + virtual void ResetNoMissedSamples(); /////////////////////////////////////////////////////////////////////////// // int16_t SetBitRate() @@ -210,7 +216,7 @@ class ACMGenericCodec { // codec is not rate-adjustable. // 0 if the rate is adjusted successfully // - int16_t SetBitRate(const int32_t bitrate_bps); + virtual int16_t SetBitRate(const int32_t bitrate_bps); /////////////////////////////////////////////////////////////////////////// // uint32_t EarliestTimestamp() @@ -220,7 +226,7 @@ class ACMGenericCodec { // Return value: // timestamp of the first 10 ms audio in the audio buffer. // - uint32_t EarliestTimestamp() const; + virtual uint32_t EarliestTimestamp() const; /////////////////////////////////////////////////////////////////////////// // int16_t SetVAD() @@ -249,7 +255,10 @@ class ACMGenericCodec { // -1 if failed to set DTX & VAD as specified, // 0 if succeeded. // - int16_t SetVAD(bool* enable_dtx, bool* enable_vad, ACMVADMode* mode); + virtual 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() @@ -264,7 +273,7 @@ class ACMGenericCodec { // -1 if failed to replace internal DTX, // 0 if succeeded. // - int32_t ReplaceInternalDTX(const bool replace_internal_dtx); + virtual int32_t ReplaceInternalDTX(const bool replace_internal_dtx); /////////////////////////////////////////////////////////////////////////// // int32_t IsInternalDTXReplaced() @@ -303,7 +312,7 @@ class ACMGenericCodec { // -1 if fails to get decoder estimated bandwidth, // >0 estimated bandwidth in bits/sec. // - int32_t GetEstimatedBandwidth(); + virtual int32_t GetEstimatedBandwidth(); /////////////////////////////////////////////////////////////////////////// // int32_t SetEstimatedBandwidth() @@ -317,7 +326,7 @@ class ACMGenericCodec { // -1 if fails to set estimated bandwidth, // 0 on success. // - int32_t SetEstimatedBandwidth(int32_t estimated_bandwidth); + virtual int32_t SetEstimatedBandwidth(int32_t estimated_bandwidth); /////////////////////////////////////////////////////////////////////////// // int32_t GetRedPayload() @@ -332,7 +341,7 @@ class ACMGenericCodec { // -1 if fails to get codec specific RED, // 0 if succeeded. // - int32_t GetRedPayload(uint8_t* red_payload, int16_t* payload_bytes); + virtual int32_t GetRedPayload(uint8_t* red_payload, int16_t* payload_bytes); /////////////////////////////////////////////////////////////////////////// // int16_t ResetEncoder() @@ -344,7 +353,7 @@ class ACMGenericCodec { // -1 if failed, // 0 if succeeded. // - int16_t ResetEncoder(); + virtual int16_t ResetEncoder(); /////////////////////////////////////////////////////////////////////////// // void DestructEncoder() @@ -353,7 +362,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. // - void DestructEncoder(); + virtual void DestructEncoder(); /////////////////////////////////////////////////////////////////////////// // int16_t SamplesLeftToEncode() @@ -362,7 +371,7 @@ class ACMGenericCodec { // Return value: // Number of samples. // - int16_t SamplesLeftToEncode(); + virtual int16_t SamplesLeftToEncode(); /////////////////////////////////////////////////////////////////////////// // SetUniqueID() @@ -371,7 +380,7 @@ class ACMGenericCodec { // Input // -id : A number to identify the codec. // - void SetUniqueID(const uint32_t id); + virtual void SetUniqueID(const uint32_t id); /////////////////////////////////////////////////////////////////////////// // UpdateDecoderSampFreq() @@ -560,7 +569,7 @@ class ACMGenericCodec { // Returns true if there is enough audio buffered for encoding, such that // calling Encode() will return a payload. // - bool HasFrameToEncode() const; + virtual bool HasFrameToEncode() const; // // Returns pointer to the AudioDecoder class of this codec. A codec which @@ -972,6 +981,181 @@ class ACMGenericCodec { 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) 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; + + 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 + EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); + + scoped_ptr audio_encoder_ GUARDED_BY(codec_wrapper_lock_); + scoped_ptr cng_encoder_ GUARDED_BY(codec_wrapper_lock_); + scoped_ptr red_encoder_ GUARDED_BY(codec_wrapper_lock_); + AudioEncoder* encoder_ GUARDED_BY(codec_wrapper_lock_); + AudioDecoderProxy decoder_proxy_ GUARDED_BY(codec_wrapper_lock_); + std::vector input_ GUARDED_BY(codec_wrapper_lock_); + WebRtcACMCodecParams acm_codec_params_ GUARDED_BY(codec_wrapper_lock_); + int bitrate_bps_ GUARDED_BY(codec_wrapper_lock_); + bool fec_enabled_ GUARDED_BY(codec_wrapper_lock_); + int loss_rate_ GUARDED_BY(codec_wrapper_lock_); + int max_playback_rate_hz_ GUARDED_BY(codec_wrapper_lock_); + int max_payload_size_bytes_ GUARDED_BY(codec_wrapper_lock_); + int max_rate_bps_ GUARDED_BY(codec_wrapper_lock_); + bool is_opus_ GUARDED_BY(codec_wrapper_lock_); + bool is_isac_ GUARDED_BY(codec_wrapper_lock_); + bool first_frame_ GUARDED_BY(codec_wrapper_lock_); + uint32_t rtp_timestamp_ GUARDED_BY(codec_wrapper_lock_); + uint32_t last_rtp_timestamp_ GUARDED_BY(codec_wrapper_lock_); + // Map from payload type to sample rate (Hz) and encoding type. + std::map> cng_pt_ + GUARDED_BY(codec_wrapper_lock_); + int red_payload_type_ GUARDED_BY(codec_wrapper_lock_); + OpusApplicationMode opus_application_ GUARDED_BY(codec_wrapper_lock_); + bool opus_application_set_ GUARDED_BY(codec_wrapper_lock_); +}; + } // namespace acm2 } // namespace webrtc 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 b59d30146..4098889ad 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 @@ -258,9 +258,9 @@ int32_t AudioCodingModuleImpl::Process() { if (!HaveValidEncoder("Process")) { return -1; } - status = codecs_[current_send_codec_idx_]->Encode(stream, &length_bytes, - &rtp_timestamp, - &encoding_type); + AudioEncoder::EncodedInfo encoded_info; + status = codecs_[current_send_codec_idx_]->Encode( + stream, &length_bytes, &rtp_timestamp, &encoding_type, &encoded_info); if (status < 0) { // Encode failed. WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,