Introduce ACMGenericCodecWrapper
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 R=tina.legrand@webrtc.org Review URL: https://webrtc-codereview.appspot.com/34939004 Cr-Commit-Position: refs/heads/master@{#8248} git-svn-id: http://webrtc.googlecode.com/svn/trunk@8248 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
5d32f43219
commit
af8c13f2a1
@ -12,15 +12,59 @@
|
|||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include "webrtc/base/checks.h"
|
||||||
#include "webrtc/common_audio/vad/include/webrtc_vad.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/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_codec_database.h"
|
||||||
#include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
|
#include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
|
||||||
#include "webrtc/system_wrappers/interface/trace.h"
|
#include "webrtc/system_wrappers/interface/trace.h"
|
||||||
|
|
||||||
namespace webrtc {
|
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 {
|
namespace acm2 {
|
||||||
|
|
||||||
// Enum for CNG
|
// Enum for CNG
|
||||||
@ -216,7 +260,8 @@ bool ACMGenericCodec::ExternalRedNeeded() {
|
|||||||
int16_t ACMGenericCodec::Encode(uint8_t* bitstream,
|
int16_t ACMGenericCodec::Encode(uint8_t* bitstream,
|
||||||
int16_t* bitstream_len_byte,
|
int16_t* bitstream_len_byte,
|
||||||
uint32_t* timestamp,
|
uint32_t* timestamp,
|
||||||
WebRtcACMEncodingType* encoding_type) {
|
WebRtcACMEncodingType* encoding_type,
|
||||||
|
AudioEncoder::EncodedInfo* /*encoded_info*/) {
|
||||||
if (!HasFrameToEncode()) {
|
if (!HasFrameToEncode()) {
|
||||||
// There is not enough audio
|
// There is not enough audio
|
||||||
*timestamp = 0;
|
*timestamp = 0;
|
||||||
@ -651,6 +696,9 @@ int16_t ACMGenericCodec::SetVAD(bool* enable_dtx,
|
|||||||
return SetVADSafe(enable_dtx, enable_vad, mode);
|
return SetVADSafe(enable_dtx, enable_vad, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ACMGenericCodec::SetCngPt(int sample_rate_hz, int payload_type) {
|
||||||
|
}
|
||||||
|
|
||||||
int16_t ACMGenericCodec::SetVADSafe(bool* enable_dtx,
|
int16_t ACMGenericCodec::SetVADSafe(bool* enable_dtx,
|
||||||
bool* enable_vad,
|
bool* enable_vad,
|
||||||
ACMVADMode* mode) {
|
ACMVADMode* mode) {
|
||||||
@ -1022,6 +1070,663 @@ int ACMGenericCodec::SetOpusMaxPlaybackRate(int /* frequency_hz */) {
|
|||||||
return -1;
|
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 acm2
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -11,12 +11,17 @@
|
|||||||
#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_ACM_GENERIC_CODEC_H_
|
#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_ACM_GENERIC_CODEC_H_
|
||||||
#define 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/base/thread_annotations.h"
|
||||||
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.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_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/main/acm2/acm_common_defs.h"
|
||||||
#include "webrtc/modules/audio_coding/neteq/interface/neteq.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/rw_lock_wrapper.h"
|
||||||
|
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||||
#include "webrtc/system_wrappers/interface/trace.h"
|
#include "webrtc/system_wrappers/interface/trace.h"
|
||||||
|
|
||||||
#define MAX_FRAME_SIZE_10MSEC 6
|
#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
|
// -1 if error is occurred, otherwise the length of the bit-stream in
|
||||||
// bytes.
|
// bytes.
|
||||||
//
|
//
|
||||||
int16_t Encode(uint8_t* bitstream,
|
virtual int16_t Encode(uint8_t* bitstream,
|
||||||
int16_t* bitstream_len_byte,
|
int16_t* bitstream_len_byte,
|
||||||
uint32_t* timestamp,
|
uint32_t* timestamp,
|
||||||
WebRtcACMEncodingType* encoding_type);
|
WebRtcACMEncodingType* encoding_type,
|
||||||
|
AudioEncoder::EncodedInfo* encoded_info);
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// bool EncoderInitialized();
|
// bool EncoderInitialized();
|
||||||
@ -118,7 +124,7 @@ class ACMGenericCodec {
|
|||||||
// True if the encoder is successfully initialized,
|
// True if the encoder is successfully initialized,
|
||||||
// false otherwise.
|
// false otherwise.
|
||||||
//
|
//
|
||||||
bool EncoderInitialized();
|
virtual bool EncoderInitialized();
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// int16_t EncoderParams()
|
// int16_t EncoderParams()
|
||||||
@ -134,7 +140,7 @@ class ACMGenericCodec {
|
|||||||
// -1 if the encoder is not initialized,
|
// -1 if the encoder is not initialized,
|
||||||
// 0 otherwise.
|
// 0 otherwise.
|
||||||
//
|
//
|
||||||
int16_t EncoderParams(WebRtcACMCodecParams* enc_params);
|
virtual int16_t EncoderParams(WebRtcACMCodecParams* enc_params);
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// int16_t InitEncoder(...)
|
// int16_t InitEncoder(...)
|
||||||
@ -152,7 +158,7 @@ class ACMGenericCodec {
|
|||||||
// -1 if failed to initialize.
|
// -1 if failed to initialize.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
int16_t InitEncoder(WebRtcACMCodecParams* codec_params,
|
virtual int16_t InitEncoder(WebRtcACMCodecParams* codec_params,
|
||||||
bool force_initialization);
|
bool force_initialization);
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
@ -174,7 +180,7 @@ class ACMGenericCodec {
|
|||||||
// -1 if failed
|
// -1 if failed
|
||||||
// 0 otherwise.
|
// 0 otherwise.
|
||||||
//
|
//
|
||||||
int32_t Add10MsData(const uint32_t timestamp,
|
virtual int32_t Add10MsData(const uint32_t timestamp,
|
||||||
const int16_t* data,
|
const int16_t* data,
|
||||||
const uint16_t length,
|
const uint16_t length,
|
||||||
const uint8_t audio_channel);
|
const uint8_t audio_channel);
|
||||||
@ -189,14 +195,14 @@ class ACMGenericCodec {
|
|||||||
// Return Value:
|
// Return Value:
|
||||||
// Number of samples which are overwritten.
|
// Number of samples which are overwritten.
|
||||||
//
|
//
|
||||||
uint32_t NoMissedSamples() const;
|
virtual uint32_t NoMissedSamples() const;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// void ResetNoMissedSamples()
|
// void ResetNoMissedSamples()
|
||||||
// This function resets the number of overwritten samples to zero.
|
// This function resets the number of overwritten samples to zero.
|
||||||
// (We might remove this function if we remove NoMissedSamples())
|
// (We might remove this function if we remove NoMissedSamples())
|
||||||
//
|
//
|
||||||
void ResetNoMissedSamples();
|
virtual void ResetNoMissedSamples();
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// int16_t SetBitRate()
|
// int16_t SetBitRate()
|
||||||
@ -210,7 +216,7 @@ class ACMGenericCodec {
|
|||||||
// codec is not rate-adjustable.
|
// codec is not rate-adjustable.
|
||||||
// 0 if the rate is adjusted successfully
|
// 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()
|
// uint32_t EarliestTimestamp()
|
||||||
@ -220,7 +226,7 @@ class ACMGenericCodec {
|
|||||||
// Return value:
|
// Return value:
|
||||||
// timestamp of the first 10 ms audio in the audio buffer.
|
// timestamp of the first 10 ms audio in the audio buffer.
|
||||||
//
|
//
|
||||||
uint32_t EarliestTimestamp() const;
|
virtual uint32_t EarliestTimestamp() const;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// int16_t SetVAD()
|
// int16_t SetVAD()
|
||||||
@ -249,7 +255,10 @@ class ACMGenericCodec {
|
|||||||
// -1 if failed to set DTX & VAD as specified,
|
// -1 if failed to set DTX & VAD as specified,
|
||||||
// 0 if succeeded.
|
// 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()
|
// int32_t ReplaceInternalDTX()
|
||||||
@ -264,7 +273,7 @@ class ACMGenericCodec {
|
|||||||
// -1 if failed to replace internal DTX,
|
// -1 if failed to replace internal DTX,
|
||||||
// 0 if succeeded.
|
// 0 if succeeded.
|
||||||
//
|
//
|
||||||
int32_t ReplaceInternalDTX(const bool replace_internal_dtx);
|
virtual int32_t ReplaceInternalDTX(const bool replace_internal_dtx);
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// int32_t IsInternalDTXReplaced()
|
// int32_t IsInternalDTXReplaced()
|
||||||
@ -303,7 +312,7 @@ class ACMGenericCodec {
|
|||||||
// -1 if fails to get decoder estimated bandwidth,
|
// -1 if fails to get decoder estimated bandwidth,
|
||||||
// >0 estimated bandwidth in bits/sec.
|
// >0 estimated bandwidth in bits/sec.
|
||||||
//
|
//
|
||||||
int32_t GetEstimatedBandwidth();
|
virtual int32_t GetEstimatedBandwidth();
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// int32_t SetEstimatedBandwidth()
|
// int32_t SetEstimatedBandwidth()
|
||||||
@ -317,7 +326,7 @@ class ACMGenericCodec {
|
|||||||
// -1 if fails to set estimated bandwidth,
|
// -1 if fails to set estimated bandwidth,
|
||||||
// 0 on success.
|
// 0 on success.
|
||||||
//
|
//
|
||||||
int32_t SetEstimatedBandwidth(int32_t estimated_bandwidth);
|
virtual int32_t SetEstimatedBandwidth(int32_t estimated_bandwidth);
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// int32_t GetRedPayload()
|
// int32_t GetRedPayload()
|
||||||
@ -332,7 +341,7 @@ class ACMGenericCodec {
|
|||||||
// -1 if fails to get codec specific RED,
|
// -1 if fails to get codec specific RED,
|
||||||
// 0 if succeeded.
|
// 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()
|
// int16_t ResetEncoder()
|
||||||
@ -344,7 +353,7 @@ class ACMGenericCodec {
|
|||||||
// -1 if failed,
|
// -1 if failed,
|
||||||
// 0 if succeeded.
|
// 0 if succeeded.
|
||||||
//
|
//
|
||||||
int16_t ResetEncoder();
|
virtual int16_t ResetEncoder();
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// void DestructEncoder()
|
// void DestructEncoder()
|
||||||
@ -353,7 +362,7 @@ class ACMGenericCodec {
|
|||||||
// instance we cannot delete the encoder and instead we will initialize the
|
// instance we cannot delete the encoder and instead we will initialize the
|
||||||
// encoder. We also delete VAD and DTX if they have been created.
|
// encoder. We also delete VAD and DTX if they have been created.
|
||||||
//
|
//
|
||||||
void DestructEncoder();
|
virtual void DestructEncoder();
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// int16_t SamplesLeftToEncode()
|
// int16_t SamplesLeftToEncode()
|
||||||
@ -362,7 +371,7 @@ class ACMGenericCodec {
|
|||||||
// Return value:
|
// Return value:
|
||||||
// Number of samples.
|
// Number of samples.
|
||||||
//
|
//
|
||||||
int16_t SamplesLeftToEncode();
|
virtual int16_t SamplesLeftToEncode();
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// SetUniqueID()
|
// SetUniqueID()
|
||||||
@ -371,7 +380,7 @@ class ACMGenericCodec {
|
|||||||
// Input
|
// Input
|
||||||
// -id : A number to identify the codec.
|
// -id : A number to identify the codec.
|
||||||
//
|
//
|
||||||
void SetUniqueID(const uint32_t id);
|
virtual void SetUniqueID(const uint32_t id);
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// UpdateDecoderSampFreq()
|
// UpdateDecoderSampFreq()
|
||||||
@ -560,7 +569,7 @@ class ACMGenericCodec {
|
|||||||
// Returns true if there is enough audio buffered for encoding, such that
|
// Returns true if there is enough audio buffered for encoding, such that
|
||||||
// calling Encode() will return a payload.
|
// 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
|
// Returns pointer to the AudioDecoder class of this codec. A codec which
|
||||||
@ -972,6 +981,181 @@ class ACMGenericCodec {
|
|||||||
uint32_t unique_id_;
|
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 acm2
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -258,9 +258,9 @@ int32_t AudioCodingModuleImpl::Process() {
|
|||||||
if (!HaveValidEncoder("Process")) {
|
if (!HaveValidEncoder("Process")) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
status = codecs_[current_send_codec_idx_]->Encode(stream, &length_bytes,
|
AudioEncoder::EncodedInfo encoded_info;
|
||||||
&rtp_timestamp,
|
status = codecs_[current_send_codec_idx_]->Encode(
|
||||||
&encoding_type);
|
stream, &length_bytes, &rtp_timestamp, &encoding_type, &encoded_info);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
// Encode failed.
|
// Encode failed.
|
||||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user