Reland r8248 "Introduce ACMGenericCodecWrapper"
This effectively reverts r8249.
This new class inherits from ACMGenericCodec. The purpose is to wrap
AudioEncoder objects into an ACMGenericCodec interface. This is a
temporary construction that will be used during the ACM redesign work.
BUG=4228
COAUTHOR=kwiberg@webrtc.org
TBR=tina.legrand@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/38919004
Cr-Commit-Position: refs/heads/master@{#8255}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8255 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/audio_coding/codecs/audio_encoder.cc b/webrtc/modules/audio_coding/codecs/audio_encoder.cc
index 20e5953..ae1bce1 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() {
}
+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<size_t>(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 9b0c11b..6fc5827 100644
--- a/webrtc/modules/audio_coding/codecs/audio_encoder.h
+++ b/webrtc/modules/audio_coding/codecs/audio_encoder.h
@@ -14,7 +14,6 @@
#include <algorithm>
#include <vector>
-#include "webrtc/base/checks.h"
#include "webrtc/typedefs.h"
namespace webrtc {
@@ -63,14 +62,7 @@
size_t num_samples_per_channel,
size_t max_encoded_bytes,
uint8_t* encoded,
- EncodedInfo* info) {
- CHECK_EQ(num_samples_per_channel,
- static_cast<size_t>(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 5b072e4..c2f6424 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 <limits>
+#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 4982e5a..2727611 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 41ed490..4ab88b6 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 c3d5601..2b0fb91 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 <string.h>
+#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 35a8b2f..de1339d 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 209d589..c65e053 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 <assert.h>
#include <string.h>
+#include <algorithm>
+#include <utility>
+#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<int, std::pair<int, WebRtcACMEncodingType>>* 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 @@
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 @@
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 @@
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<int16_t>(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<uint32_t>(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<AudioEncoderDecoderIsac*>(audio_encoder_.get())
+ ->UpdateDecoderSampleRate(16000);
+ return 0;
+ case ACMCodecDB::kISACSWB:
+ case ACMCodecDB::kISACFB:
+ static_cast<AudioEncoderDecoderIsac*>(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 9d04510..d2caea7 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 <map>
+
#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 @@
// -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 @@
// True if the encoder is successfully initialized,
// false otherwise.
//
- bool EncoderInitialized();
+ virtual bool EncoderInitialized();
///////////////////////////////////////////////////////////////////////////
// int16_t EncoderParams()
@@ -134,7 +140,7 @@
// -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 @@
// -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 @@
// -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 @@
// 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 @@
// 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 @@
// 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 @@
// -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 @@
// -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 @@
// -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 @@
// -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 @@
// -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 @@
// -1 if failed,
// 0 if succeeded.
//
- int16_t ResetEncoder();
+ virtual int16_t ResetEncoder();
///////////////////////////////////////////////////////////////////////////
// void DestructEncoder()
@@ -353,7 +362,7 @@
// 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 @@
// Return value:
// Number of samples.
//
- int16_t SamplesLeftToEncode();
+ virtual int16_t SamplesLeftToEncode();
///////////////////////////////////////////////////////////////////////////
// SetUniqueID()
@@ -371,7 +380,7 @@
// 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 @@
// 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 @@
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<CriticalSectionWrapper> 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<AudioEncoder> audio_encoder_ GUARDED_BY(codec_wrapper_lock_);
+ scoped_ptr<AudioEncoder> cng_encoder_ GUARDED_BY(codec_wrapper_lock_);
+ scoped_ptr<AudioEncoder> red_encoder_ GUARDED_BY(codec_wrapper_lock_);
+ AudioEncoder* encoder_ GUARDED_BY(codec_wrapper_lock_);
+ AudioDecoderProxy decoder_proxy_ GUARDED_BY(codec_wrapper_lock_);
+ std::vector<int16_t> 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<int, std::pair<int, WebRtcACMEncodingType>> 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 b59d301..4098889 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 @@
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_,