iSAC: Make separate AudioEncoder and AudioDecoder objects

The only shared state is now the bandwidth estimation info.
This reduces the amount and complexity of the locking
substantially.

Review URL: https://codereview.webrtc.org/1208993010

Cr-Commit-Position: refs/heads/master@{#9762}
This commit is contained in:
kwiberg
2015-08-24 02:03:23 -07:00
committed by Commit bot
parent 2159b89fa2
commit 608c3cfe77
20 changed files with 367 additions and 510 deletions

View File

@ -13,17 +13,14 @@
#include <vector>
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/thread_annotations.h"
#include "webrtc/modules/audio_coding/codecs/audio_decoder.h"
#include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
#include "webrtc/modules/audio_coding/codecs/isac/locked_bandwidth_info.h"
namespace webrtc {
class CriticalSectionWrapper;
template <typename T>
class AudioEncoderDecoderIsacT : public AudioEncoder, public AudioDecoder {
class AudioEncoderIsacT final : public AudioEncoder {
public:
// Allowed combinations of sample rate, frame size, and bit rate are
// - 16000 Hz, 30 ms, 10000-32000 bps
@ -34,6 +31,8 @@ class AudioEncoderDecoderIsacT : public AudioEncoder, public AudioDecoder {
Config();
bool IsOk() const;
LockedIsacBandwidthInfo* bwinfo;
int payload_type;
int sample_rate_hz;
int frame_size_ms;
@ -50,18 +49,50 @@ class AudioEncoderDecoderIsacT : public AudioEncoder, public AudioDecoder {
bool enforce_frame_size;
};
explicit AudioEncoderDecoderIsacT(const Config& config);
~AudioEncoderDecoderIsacT() override;
explicit AudioEncoderIsacT(const Config& config);
~AudioEncoderIsacT() override;
// AudioEncoder public methods.
int SampleRateHz() const override;
int NumChannels() const override;
size_t MaxEncodedBytes() const override;
int Num10MsFramesInNextPacket() const override;
int Max10MsFramesInAPacket() const override;
int GetTargetBitrate() const override;
EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
const int16_t* audio,
size_t max_encoded_bytes,
uint8_t* encoded) override;
private:
// This value is taken from STREAM_SIZE_MAX_60 for iSAC float (60 ms) and
// STREAM_MAXW16_60MS for iSAC fix (60 ms).
static const size_t kSufficientEncodeBufferSizeBytes = 400;
const int payload_type_;
typename T::instance_type* isac_state_;
LockedIsacBandwidthInfo* bwinfo_;
// Have we accepted input but not yet emitted it in a packet?
bool packet_in_progress_;
// Timestamp of the first input of the currently in-progress packet.
uint32_t packet_timestamp_;
// Timestamp of the previously encoded packet.
uint32_t last_encoded_timestamp_;
const int target_bitrate_bps_;
DISALLOW_COPY_AND_ASSIGN(AudioEncoderIsacT);
};
template <typename T>
class AudioDecoderIsacT final : public AudioDecoder {
public:
AudioDecoderIsacT();
explicit AudioDecoderIsacT(LockedIsacBandwidthInfo* bwinfo);
~AudioDecoderIsacT() override;
// AudioDecoder methods.
bool HasDecodePlc() const override;
int DecodePlc(int num_frames, int16_t* decoded) override;
int Init() override;
@ -71,15 +102,7 @@ class AudioEncoderDecoderIsacT : public AudioEncoder, public AudioDecoder {
uint32_t rtp_timestamp,
uint32_t arrival_timestamp) override;
int ErrorCode() override;
size_t Channels() const override { return 1; }
// AudioEncoder protected method.
EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
const int16_t* audio,
size_t max_encoded_bytes,
uint8_t* encoded) override;
// AudioDecoder protected method.
size_t Channels() const override;
int DecodeInternal(const uint8_t* encoded,
size_t encoded_len,
int sample_rate_hz,
@ -87,44 +110,11 @@ class AudioEncoderDecoderIsacT : public AudioEncoder, public AudioDecoder {
SpeechType* speech_type) override;
private:
// This value is taken from STREAM_SIZE_MAX_60 for iSAC float (60 ms) and
// STREAM_MAXW16_60MS for iSAC fix (60 ms).
static const size_t kSufficientEncodeBufferSizeBytes = 400;
typename T::instance_type* isac_state_;
LockedIsacBandwidthInfo* bwinfo_;
int decoder_sample_rate_hz_;
const int payload_type_;
// iSAC encoder/decoder state, guarded by a mutex to ensure that encode calls
// from one thread won't clash with decode calls from another thread.
// Note: PT_GUARDED_BY is disabled since it is not yet supported by clang.
const rtc::scoped_ptr<CriticalSectionWrapper> state_lock_;
typename T::instance_type* isac_state_
GUARDED_BY(state_lock_) /* PT_GUARDED_BY(lock_)*/;
int decoder_sample_rate_hz_ GUARDED_BY(state_lock_);
// Must be acquired before state_lock_.
const rtc::scoped_ptr<CriticalSectionWrapper> lock_;
// Have we accepted input but not yet emitted it in a packet?
bool packet_in_progress_ GUARDED_BY(lock_);
// Timestamp of the first input of the currently in-progress packet.
uint32_t packet_timestamp_ GUARDED_BY(lock_);
// Timestamp of the previously encoded packet.
uint32_t last_encoded_timestamp_ GUARDED_BY(lock_);
const int target_bitrate_bps_;
DISALLOW_COPY_AND_ASSIGN(AudioEncoderDecoderIsacT);
};
struct CodecInst;
class AudioEncoderDecoderMutableIsac : public AudioEncoderMutable,
public AudioDecoder {
public:
virtual void UpdateSettings(const CodecInst& codec_inst) = 0;
DISALLOW_COPY_AND_ASSIGN(AudioDecoderIsacT);
};
} // namespace webrtc

View File

@ -17,7 +17,6 @@
#include "webrtc/base/checks.h"
#include "webrtc/modules/audio_coding/codecs/isac/main/interface/isac.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
namespace webrtc {
@ -25,8 +24,9 @@ const int kIsacPayloadType = 103;
const int kDefaultBitRate = 32000;
template <typename T>
AudioEncoderDecoderIsacT<T>::Config::Config()
: payload_type(kIsacPayloadType),
AudioEncoderIsacT<T>::Config::Config()
: bwinfo(nullptr),
payload_type(kIsacPayloadType),
sample_rate_hz(16000),
frame_size_ms(30),
bit_rate(kDefaultBitRate),
@ -37,11 +37,13 @@ AudioEncoderDecoderIsacT<T>::Config::Config()
}
template <typename T>
bool AudioEncoderDecoderIsacT<T>::Config::IsOk() const {
bool AudioEncoderIsacT<T>::Config::IsOk() const {
if (max_bit_rate < 32000 && max_bit_rate != -1)
return false;
if (max_payload_size_bytes < 120 && max_payload_size_bytes != -1)
return false;
if (adaptive_mode && !bwinfo)
return false;
switch (sample_rate_hz) {
case 16000:
if (max_bit_rate > 53400)
@ -65,11 +67,9 @@ bool AudioEncoderDecoderIsacT<T>::Config::IsOk() const {
}
template <typename T>
AudioEncoderDecoderIsacT<T>::AudioEncoderDecoderIsacT(const Config& config)
AudioEncoderIsacT<T>::AudioEncoderIsacT(const Config& config)
: payload_type_(config.payload_type),
state_lock_(CriticalSectionWrapper::CreateCriticalSection()),
decoder_sample_rate_hz_(0),
lock_(CriticalSectionWrapper::CreateCriticalSection()),
bwinfo_(config.bwinfo),
packet_in_progress_(false),
target_bitrate_bps_(config.adaptive_mode ? -1 : (config.bit_rate == 0
? kDefaultBitRate
@ -85,80 +85,82 @@ AudioEncoderDecoderIsacT<T>::AudioEncoderDecoderIsacT(const Config& config)
} else {
CHECK_EQ(0, T::Control(isac_state_, bit_rate, config.frame_size_ms));
}
// When config.sample_rate_hz is set to 48000 Hz (iSAC-fb), the decoder is
// still set to 32000 Hz, since there is no full-band mode in the decoder.
CHECK_EQ(0, T::SetDecSampRate(isac_state_,
std::min(config.sample_rate_hz, 32000)));
if (config.max_payload_size_bytes != -1)
CHECK_EQ(0,
T::SetMaxPayloadSize(isac_state_, config.max_payload_size_bytes));
if (config.max_bit_rate != -1)
CHECK_EQ(0, T::SetMaxRate(isac_state_, config.max_bit_rate));
CHECK_EQ(0, T::DecoderInit(isac_state_));
// When config.sample_rate_hz is set to 48000 Hz (iSAC-fb), the decoder is
// still set to 32000 Hz, since there is no full-band mode in the decoder.
const int decoder_sample_rate_hz = std::min(config.sample_rate_hz, 32000);
// Set the decoder sample rate even though we just use the encoder. This
// doesn't appear to be necessary to produce a valid encoding, but without it
// we get an encoding that isn't bit-for-bit identical with what a combined
// encoder+decoder object produces.
CHECK_EQ(0, T::SetDecSampRate(isac_state_, decoder_sample_rate_hz));
}
template <typename T>
AudioEncoderDecoderIsacT<T>::~AudioEncoderDecoderIsacT() {
AudioEncoderIsacT<T>::~AudioEncoderIsacT() {
CHECK_EQ(0, T::Free(isac_state_));
}
template <typename T>
int AudioEncoderDecoderIsacT<T>::SampleRateHz() const {
CriticalSectionScoped cs(state_lock_.get());
int AudioEncoderIsacT<T>::SampleRateHz() const {
return T::EncSampRate(isac_state_);
}
template <typename T>
int AudioEncoderDecoderIsacT<T>::NumChannels() const {
int AudioEncoderIsacT<T>::NumChannels() const {
return 1;
}
template <typename T>
size_t AudioEncoderDecoderIsacT<T>::MaxEncodedBytes() const {
size_t AudioEncoderIsacT<T>::MaxEncodedBytes() const {
return kSufficientEncodeBufferSizeBytes;
}
template <typename T>
int AudioEncoderDecoderIsacT<T>::Num10MsFramesInNextPacket() const {
CriticalSectionScoped cs(state_lock_.get());
int AudioEncoderIsacT<T>::Num10MsFramesInNextPacket() const {
const int samples_in_next_packet = T::GetNewFrameLen(isac_state_);
return rtc::CheckedDivExact(samples_in_next_packet,
rtc::CheckedDivExact(SampleRateHz(), 100));
}
template <typename T>
int AudioEncoderDecoderIsacT<T>::Max10MsFramesInAPacket() const {
int AudioEncoderIsacT<T>::Max10MsFramesInAPacket() const {
return 6; // iSAC puts at most 60 ms in a packet.
}
template <typename T>
int AudioEncoderDecoderIsacT<T>::GetTargetBitrate() const {
int AudioEncoderIsacT<T>::GetTargetBitrate() const {
return target_bitrate_bps_;
}
template <typename T>
AudioEncoder::EncodedInfo AudioEncoderDecoderIsacT<T>::EncodeInternal(
AudioEncoder::EncodedInfo AudioEncoderIsacT<T>::EncodeInternal(
uint32_t rtp_timestamp,
const int16_t* audio,
size_t max_encoded_bytes,
uint8_t* encoded) {
CriticalSectionScoped cs_lock(lock_.get());
if (!packet_in_progress_) {
// Starting a new packet; remember the timestamp for later.
packet_in_progress_ = true;
packet_timestamp_ = rtp_timestamp;
}
int r;
{
CriticalSectionScoped cs(state_lock_.get());
r = T::Encode(isac_state_, audio, encoded);
CHECK_GE(r, 0) << "Encode failed (error code "
<< T::GetErrorCode(isac_state_) << ")";
if (bwinfo_) {
IsacBandwidthInfo bwinfo = bwinfo_->Get();
T::SetBandwidthInfo(isac_state_, &bwinfo);
}
int r = T::Encode(isac_state_, audio, encoded);
CHECK_GE(r, 0) << "Encode failed (error code " << T::GetErrorCode(isac_state_)
<< ")";
// T::Encode doesn't allow us to tell it the size of the output
// buffer. All we can do is check for an overrun after the fact.
CHECK(static_cast<size_t>(r) <= max_encoded_bytes);
CHECK_LE(static_cast<size_t>(r), max_encoded_bytes);
if (r == 0)
return EncodedInfo();
@ -174,12 +176,33 @@ AudioEncoder::EncodedInfo AudioEncoderDecoderIsacT<T>::EncodeInternal(
}
template <typename T>
int AudioEncoderDecoderIsacT<T>::DecodeInternal(const uint8_t* encoded,
size_t encoded_len,
int sample_rate_hz,
int16_t* decoded,
SpeechType* speech_type) {
CriticalSectionScoped cs(state_lock_.get());
AudioDecoderIsacT<T>::AudioDecoderIsacT()
: AudioDecoderIsacT(nullptr) {
}
template <typename T>
AudioDecoderIsacT<T>::AudioDecoderIsacT(LockedIsacBandwidthInfo* bwinfo)
: bwinfo_(bwinfo), decoder_sample_rate_hz_(-1) {
CHECK_EQ(0, T::Create(&isac_state_));
CHECK_EQ(0, T::DecoderInit(isac_state_));
if (bwinfo_) {
IsacBandwidthInfo bwinfo;
T::GetBandwidthInfo(isac_state_, &bwinfo);
bwinfo_->Set(bwinfo);
}
}
template <typename T>
AudioDecoderIsacT<T>::~AudioDecoderIsacT() {
CHECK_EQ(0, T::Free(isac_state_));
}
template <typename T>
int AudioDecoderIsacT<T>::DecodeInternal(const uint8_t* encoded,
size_t encoded_len,
int sample_rate_hz,
int16_t* decoded,
SpeechType* speech_type) {
// We want to crate the illusion that iSAC supports 48000 Hz decoding, while
// in fact it outputs 32000 Hz. This is the iSAC fullband mode.
if (sample_rate_hz == 48000)
@ -199,40 +222,47 @@ int AudioEncoderDecoderIsacT<T>::DecodeInternal(const uint8_t* encoded,
}
template <typename T>
bool AudioEncoderDecoderIsacT<T>::HasDecodePlc() const {
bool AudioDecoderIsacT<T>::HasDecodePlc() const {
return false;
}
template <typename T>
int AudioEncoderDecoderIsacT<T>::DecodePlc(int num_frames, int16_t* decoded) {
CriticalSectionScoped cs(state_lock_.get());
int AudioDecoderIsacT<T>::DecodePlc(int num_frames, int16_t* decoded) {
return T::DecodePlc(isac_state_, decoded, num_frames);
}
template <typename T>
int AudioEncoderDecoderIsacT<T>::Init() {
CriticalSectionScoped cs(state_lock_.get());
int AudioDecoderIsacT<T>::Init() {
return T::DecoderInit(isac_state_);
}
template <typename T>
int AudioEncoderDecoderIsacT<T>::IncomingPacket(const uint8_t* payload,
size_t payload_len,
uint16_t rtp_sequence_number,
uint32_t rtp_timestamp,
uint32_t arrival_timestamp) {
CriticalSectionScoped cs(state_lock_.get());
return T::UpdateBwEstimate(
int AudioDecoderIsacT<T>::IncomingPacket(const uint8_t* payload,
size_t payload_len,
uint16_t rtp_sequence_number,
uint32_t rtp_timestamp,
uint32_t arrival_timestamp) {
int ret = T::UpdateBwEstimate(
isac_state_, payload, static_cast<int32_t>(payload_len),
rtp_sequence_number, rtp_timestamp, arrival_timestamp);
if (bwinfo_) {
IsacBandwidthInfo bwinfo;
T::GetBandwidthInfo(isac_state_, &bwinfo);
bwinfo_->Set(bwinfo);
}
return ret;
}
template <typename T>
int AudioEncoderDecoderIsacT<T>::ErrorCode() {
CriticalSectionScoped cs(state_lock_.get());
int AudioDecoderIsacT<T>::ErrorCode() {
return T::GetErrorCode(isac_state_);
}
template <typename T>
size_t AudioDecoderIsacT<T>::Channels() const {
return 1;
}
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_

View File

@ -120,46 +120,18 @@ struct IsacFix {
}
};
typedef AudioEncoderDecoderIsacT<IsacFix> AudioEncoderDecoderIsacFix;
using AudioEncoderIsacFix = AudioEncoderIsacT<IsacFix>;
using AudioDecoderIsacFix = AudioDecoderIsacT<IsacFix>;
struct CodecInst;
class AudioEncoderDecoderMutableIsacFix
: public AudioEncoderMutableImpl<AudioEncoderDecoderIsacFix,
AudioEncoderDecoderMutableIsac> {
class AudioEncoderMutableIsacFix
: public AudioEncoderMutableImpl<AudioEncoderIsacFix> {
public:
explicit AudioEncoderDecoderMutableIsacFix(const CodecInst& codec_inst);
void UpdateSettings(const CodecInst& codec_inst) override;
explicit AudioEncoderMutableIsacFix(const CodecInst& codec_inst,
LockedIsacBandwidthInfo* bwinfo);
void SetMaxPayloadSize(int max_payload_size_bytes) override;
void SetMaxRate(int max_rate_bps) override;
// From AudioDecoder.
int Decode(const uint8_t* encoded,
size_t encoded_len,
int sample_rate_hz,
size_t max_decoded_bytes,
int16_t* decoded,
SpeechType* speech_type) override;
int DecodeRedundant(const uint8_t* encoded,
size_t encoded_len,
int sample_rate_hz,
size_t max_decoded_bytes,
int16_t* decoded,
SpeechType* speech_type) override;
bool HasDecodePlc() const override;
int DecodePlc(int num_frames, int16_t* decoded) override;
int Init() override;
int IncomingPacket(const uint8_t* payload,
size_t payload_len,
uint16_t rtp_sequence_number,
uint32_t rtp_timestamp,
uint32_t arrival_timestamp) override;
int ErrorCode() override;
int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override;
int PacketDurationRedundant(const uint8_t* encoded,
size_t encoded_len) const override;
bool PacketHasFec(const uint8_t* encoded, size_t encoded_len) const override;
size_t Channels() const override;
};
} // namespace webrtc

View File

@ -17,13 +17,15 @@ namespace webrtc {
const uint16_t IsacFix::kFixSampleRate;
// Explicit instantiation of AudioEncoderDecoderIsacT<IsacFix>, a.k.a.
// AudioEncoderDecoderIsacFix.
template class AudioEncoderDecoderIsacT<IsacFix>;
// Explicit instantiation:
template class AudioEncoderIsacT<IsacFix>;
template class AudioDecoderIsacT<IsacFix>;
namespace {
AudioEncoderDecoderIsacFix::Config CreateConfig(const CodecInst& codec_inst) {
AudioEncoderDecoderIsacFix::Config config;
AudioEncoderIsacFix::Config CreateConfig(const CodecInst& codec_inst,
LockedIsacBandwidthInfo* bwinfo) {
AudioEncoderIsacFix::Config config;
config.bwinfo = bwinfo;
config.payload_type = codec_inst.pltype;
config.sample_rate_hz = codec_inst.plfreq;
config.frame_size_ms =
@ -35,110 +37,22 @@ AudioEncoderDecoderIsacFix::Config CreateConfig(const CodecInst& codec_inst) {
}
} // namespace
AudioEncoderDecoderMutableIsacFix::AudioEncoderDecoderMutableIsacFix(
const CodecInst& codec_inst)
: AudioEncoderMutableImpl<AudioEncoderDecoderIsacFix,
AudioEncoderDecoderMutableIsac>(
CreateConfig(codec_inst)) {
}
AudioEncoderMutableIsacFix::AudioEncoderMutableIsacFix(
const CodecInst& codec_inst,
LockedIsacBandwidthInfo* bwinfo)
: AudioEncoderMutableImpl<AudioEncoderIsacFix>(
CreateConfig(codec_inst, bwinfo)) {}
void AudioEncoderDecoderMutableIsacFix::UpdateSettings(
const CodecInst& codec_inst) {
bool success = Reconstruct(CreateConfig(codec_inst));
DCHECK(success);
}
void AudioEncoderDecoderMutableIsacFix::SetMaxPayloadSize(
int max_payload_size_bytes) {
void AudioEncoderMutableIsacFix::SetMaxPayloadSize(int max_payload_size_bytes) {
auto conf = config();
conf.max_payload_size_bytes = max_payload_size_bytes;
Reconstruct(conf);
}
void AudioEncoderDecoderMutableIsacFix::SetMaxRate(int max_rate_bps) {
void AudioEncoderMutableIsacFix::SetMaxRate(int max_rate_bps) {
auto conf = config();
conf.max_bit_rate = max_rate_bps;
Reconstruct(conf);
}
int AudioEncoderDecoderMutableIsacFix::Decode(const uint8_t* encoded,
size_t encoded_len,
int sample_rate_hz,
size_t max_decoded_bytes,
int16_t* decoded,
SpeechType* speech_type) {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->Decode(encoded, encoded_len, sample_rate_hz,
max_decoded_bytes, decoded, speech_type);
}
int AudioEncoderDecoderMutableIsacFix::DecodeRedundant(
const uint8_t* encoded,
size_t encoded_len,
int sample_rate_hz,
size_t max_decoded_bytes,
int16_t* decoded,
SpeechType* speech_type) {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->DecodeRedundant(encoded, encoded_len, sample_rate_hz,
max_decoded_bytes, decoded, speech_type);
}
bool AudioEncoderDecoderMutableIsacFix::HasDecodePlc() const {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->HasDecodePlc();
}
int AudioEncoderDecoderMutableIsacFix::DecodePlc(int num_frames,
int16_t* decoded) {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->DecodePlc(num_frames, decoded);
}
int AudioEncoderDecoderMutableIsacFix::Init() {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->Init();
}
int AudioEncoderDecoderMutableIsacFix::IncomingPacket(
const uint8_t* payload,
size_t payload_len,
uint16_t rtp_sequence_number,
uint32_t rtp_timestamp,
uint32_t arrival_timestamp) {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->IncomingPacket(payload, payload_len, rtp_sequence_number,
rtp_timestamp, arrival_timestamp);
}
int AudioEncoderDecoderMutableIsacFix::ErrorCode() {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->ErrorCode();
}
int AudioEncoderDecoderMutableIsacFix::PacketDuration(
const uint8_t* encoded,
size_t encoded_len) const {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->PacketDuration(encoded, encoded_len);
}
int AudioEncoderDecoderMutableIsacFix::PacketDurationRedundant(
const uint8_t* encoded,
size_t encoded_len) const {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->PacketDurationRedundant(encoded, encoded_len);
}
bool AudioEncoderDecoderMutableIsacFix::PacketHasFec(const uint8_t* encoded,
size_t encoded_len) const {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->PacketHasFec(encoded, encoded_len);
}
size_t AudioEncoderDecoderMutableIsacFix::Channels() const {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->Channels();
}
} // namespace webrtc

View File

@ -241,6 +241,31 @@ static void WebRtcIsacfix_InitMIPS(void) {
}
#endif
static void InitFunctionPointers(void) {
WebRtcIsacfix_AutocorrFix = WebRtcIsacfix_AutocorrC;
WebRtcIsacfix_FilterMaLoopFix = WebRtcIsacfix_FilterMaLoopC;
WebRtcIsacfix_CalculateResidualEnergy =
WebRtcIsacfix_CalculateResidualEnergyC;
WebRtcIsacfix_AllpassFilter2FixDec16 = WebRtcIsacfix_AllpassFilter2FixDec16C;
WebRtcIsacfix_HighpassFilterFixDec32 = WebRtcIsacfix_HighpassFilterFixDec32C;
WebRtcIsacfix_Time2Spec = WebRtcIsacfix_Time2SpecC;
WebRtcIsacfix_Spec2Time = WebRtcIsacfix_Spec2TimeC;
WebRtcIsacfix_MatrixProduct1 = WebRtcIsacfix_MatrixProduct1C;
WebRtcIsacfix_MatrixProduct2 = WebRtcIsacfix_MatrixProduct2C;
#ifdef WEBRTC_DETECT_NEON
if ((WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON) != 0) {
WebRtcIsacfix_InitNeon();
}
#elif defined(WEBRTC_HAS_NEON)
WebRtcIsacfix_InitNeon();
#endif
#if defined(MIPS32_LE)
WebRtcIsacfix_InitMIPS();
#endif
}
/****************************************************************************
* WebRtcIsacfix_EncoderInit(...)
*
@ -317,29 +342,7 @@ int16_t WebRtcIsacfix_EncoderInit(ISACFIX_MainStruct *ISAC_main_inst,
WebRtcIsacfix_InitPostFilterbank(&ISAC_inst->ISACenc_obj.interpolatorstr_obj);
#endif
// Initiaze function pointers.
WebRtcIsacfix_AutocorrFix = WebRtcIsacfix_AutocorrC;
WebRtcIsacfix_FilterMaLoopFix = WebRtcIsacfix_FilterMaLoopC;
WebRtcIsacfix_CalculateResidualEnergy =
WebRtcIsacfix_CalculateResidualEnergyC;
WebRtcIsacfix_AllpassFilter2FixDec16 = WebRtcIsacfix_AllpassFilter2FixDec16C;
WebRtcIsacfix_HighpassFilterFixDec32 = WebRtcIsacfix_HighpassFilterFixDec32C;
WebRtcIsacfix_Time2Spec = WebRtcIsacfix_Time2SpecC;
WebRtcIsacfix_Spec2Time = WebRtcIsacfix_Spec2TimeC;
WebRtcIsacfix_MatrixProduct1 = WebRtcIsacfix_MatrixProduct1C;
WebRtcIsacfix_MatrixProduct2 = WebRtcIsacfix_MatrixProduct2C;
#ifdef WEBRTC_DETECT_NEON
if ((WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON) != 0) {
WebRtcIsacfix_InitNeon();
}
#elif defined(WEBRTC_HAS_NEON)
WebRtcIsacfix_InitNeon();
#endif
#if defined(MIPS32_LE)
WebRtcIsacfix_InitMIPS();
#endif
InitFunctionPointers();
return statusInit;
}
@ -575,6 +578,8 @@ int16_t WebRtcIsacfix_DecoderInit(ISACFIX_MainStruct *ISAC_main_inst)
{
ISACFIX_SubStruct *ISAC_inst;
InitFunctionPointers();
/* typecast pointer to real structure */
ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;

View File

@ -15,6 +15,7 @@
'<(webrtc_root)/common_audio/common_audio.gyp:common_audio',
'audio_decoder_interface',
'audio_encoder_interface',
'isac_common',
],
'include_dirs': [
'main/interface',
@ -27,8 +28,6 @@
],
},
'sources': [
'audio_encoder_isac_t.h',
'audio_encoder_isac_t_impl.h',
'main/interface/audio_encoder_isac.h',
'main/interface/isac.h',
'main/source/arith_routines.c',

View File

@ -0,0 +1,22 @@
# Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
{
'targets': [
{
'target_name': 'isac_common',
'type': 'static_library',
'sources': [
'audio_encoder_isac_t.h',
'audio_encoder_isac_t_impl.h',
'locked_bandwidth_info.cc',
'locked_bandwidth_info.h',
],
},
],
}

View File

@ -14,6 +14,7 @@
'dependencies': [
'<(webrtc_root)/common_audio/common_audio.gyp:common_audio',
'<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers',
'isac_common',
],
'include_dirs': [
'fix/interface',
@ -26,8 +27,6 @@
],
},
'sources': [
'audio_encoder_isac_t.h',
'audio_encoder_isac_t_impl.h',
'fix/interface/audio_encoder_isacfix.h',
'fix/interface/isacfix.h',
'fix/source/arith_routines.c',

View File

@ -0,0 +1,22 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/modules/audio_coding/codecs/isac/locked_bandwidth_info.h"
namespace webrtc {
LockedIsacBandwidthInfo::LockedIsacBandwidthInfo()
: lock_(CriticalSectionWrapper::CreateCriticalSection()) {
bwinfo_.in_use = 0;
}
LockedIsacBandwidthInfo::~LockedIsacBandwidthInfo() = default;
} // namespace webrtc

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_LOCKED_BANDWIDTH_INFO_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_LOCKED_BANDWIDTH_INFO_H_
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/thread_annotations.h"
#include "webrtc/modules/audio_coding/codecs/isac/bandwidth_info.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
namespace webrtc {
// An IsacBandwidthInfo that's safe to access from multiple threads because
// it's protected by a mutex.
class LockedIsacBandwidthInfo final {
public:
LockedIsacBandwidthInfo();
~LockedIsacBandwidthInfo();
IsacBandwidthInfo Get() const {
CriticalSectionScoped cs(lock_.get());
return bwinfo_;
}
void Set(const IsacBandwidthInfo& bwinfo) {
CriticalSectionScoped cs(lock_.get());
bwinfo_ = bwinfo;
}
private:
const rtc::scoped_ptr<CriticalSectionWrapper> lock_;
IsacBandwidthInfo bwinfo_ GUARDED_BY(lock_);
};
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_LOCKED_BANDWIDTH_INFO_H_

View File

@ -118,46 +118,18 @@ struct IsacFloat {
}
};
typedef AudioEncoderDecoderIsacT<IsacFloat> AudioEncoderDecoderIsac;
using AudioEncoderIsac = AudioEncoderIsacT<IsacFloat>;
using AudioDecoderIsac = AudioDecoderIsacT<IsacFloat>;
struct CodecInst;
class AudioEncoderDecoderMutableIsacFloat
: public AudioEncoderMutableImpl<AudioEncoderDecoderIsac,
AudioEncoderDecoderMutableIsac> {
class AudioEncoderMutableIsacFloat
: public AudioEncoderMutableImpl<AudioEncoderIsac> {
public:
explicit AudioEncoderDecoderMutableIsacFloat(const CodecInst& codec_inst);
void UpdateSettings(const CodecInst& codec_inst) override;
AudioEncoderMutableIsacFloat(const CodecInst& codec_inst,
LockedIsacBandwidthInfo* bwinfo);
void SetMaxPayloadSize(int max_payload_size_bytes) override;
void SetMaxRate(int max_rate_bps) override;
// From AudioDecoder.
int Decode(const uint8_t* encoded,
size_t encoded_len,
int sample_rate_hz,
size_t max_decoded_bytes,
int16_t* decoded,
SpeechType* speech_type) override;
int DecodeRedundant(const uint8_t* encoded,
size_t encoded_len,
int sample_rate_hz,
size_t max_decoded_bytes,
int16_t* decoded,
SpeechType* speech_type) override;
bool HasDecodePlc() const override;
int DecodePlc(int num_frames, int16_t* decoded) override;
int Init() override;
int IncomingPacket(const uint8_t* payload,
size_t payload_len,
uint16_t rtp_sequence_number,
uint32_t rtp_timestamp,
uint32_t arrival_timestamp) override;
int ErrorCode() override;
int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override;
int PacketDurationRedundant(const uint8_t* encoded,
size_t encoded_len) const override;
bool PacketHasFec(const uint8_t* encoded, size_t encoded_len) const override;
size_t Channels() const override;
};
} // namespace webrtc

View File

@ -15,13 +15,15 @@
namespace webrtc {
// Explicit instantiation of AudioEncoderDecoderIsacT<IsacFloat>, a.k.a.
// AudioEncoderDecoderIsac.
template class AudioEncoderDecoderIsacT<IsacFloat>;
// Explicit instantiation:
template class AudioEncoderIsacT<IsacFloat>;
template class AudioDecoderIsacT<IsacFloat>;
namespace {
AudioEncoderDecoderIsac::Config CreateConfig(const CodecInst& codec_inst) {
AudioEncoderDecoderIsac::Config config;
AudioEncoderIsac::Config CreateConfig(const CodecInst& codec_inst,
LockedIsacBandwidthInfo* bwinfo) {
AudioEncoderIsac::Config config;
config.bwinfo = bwinfo;
config.payload_type = codec_inst.pltype;
config.sample_rate_hz = codec_inst.plfreq;
config.frame_size_ms =
@ -33,111 +35,24 @@ AudioEncoderDecoderIsac::Config CreateConfig(const CodecInst& codec_inst) {
}
} // namespace
AudioEncoderDecoderMutableIsacFloat::AudioEncoderDecoderMutableIsacFloat(
const CodecInst& codec_inst)
: AudioEncoderMutableImpl<AudioEncoderDecoderIsac,
AudioEncoderDecoderMutableIsac>(
CreateConfig(codec_inst)) {
AudioEncoderMutableIsacFloat::AudioEncoderMutableIsacFloat(
const CodecInst& codec_inst,
LockedIsacBandwidthInfo* bwinfo)
: AudioEncoderMutableImpl<AudioEncoderIsac>(
CreateConfig(codec_inst, bwinfo)) {
}
void AudioEncoderDecoderMutableIsacFloat::UpdateSettings(
const CodecInst& codec_inst) {
bool success = Reconstruct(CreateConfig(codec_inst));
DCHECK(success);
}
void AudioEncoderDecoderMutableIsacFloat::SetMaxPayloadSize(
void AudioEncoderMutableIsacFloat::SetMaxPayloadSize(
int max_payload_size_bytes) {
auto conf = config();
conf.max_payload_size_bytes = max_payload_size_bytes;
Reconstruct(conf);
}
void AudioEncoderDecoderMutableIsacFloat::SetMaxRate(int max_rate_bps) {
void AudioEncoderMutableIsacFloat::SetMaxRate(int max_rate_bps) {
auto conf = config();
conf.max_bit_rate = max_rate_bps;
Reconstruct(conf);
}
int AudioEncoderDecoderMutableIsacFloat::Decode(const uint8_t* encoded,
size_t encoded_len,
int sample_rate_hz,
size_t max_decoded_bytes,
int16_t* decoded,
SpeechType* speech_type) {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->Decode(encoded, encoded_len, sample_rate_hz,
max_decoded_bytes, decoded, speech_type);
}
int AudioEncoderDecoderMutableIsacFloat::DecodeRedundant(
const uint8_t* encoded,
size_t encoded_len,
int sample_rate_hz,
size_t max_decoded_bytes,
int16_t* decoded,
SpeechType* speech_type) {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->DecodeRedundant(encoded, encoded_len, sample_rate_hz,
max_decoded_bytes, decoded, speech_type);
}
bool AudioEncoderDecoderMutableIsacFloat::HasDecodePlc() const {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->HasDecodePlc();
}
int AudioEncoderDecoderMutableIsacFloat::DecodePlc(int num_frames,
int16_t* decoded) {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->DecodePlc(num_frames, decoded);
}
int AudioEncoderDecoderMutableIsacFloat::Init() {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->Init();
}
int AudioEncoderDecoderMutableIsacFloat::IncomingPacket(
const uint8_t* payload,
size_t payload_len,
uint16_t rtp_sequence_number,
uint32_t rtp_timestamp,
uint32_t arrival_timestamp) {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->IncomingPacket(payload, payload_len, rtp_sequence_number,
rtp_timestamp, arrival_timestamp);
}
int AudioEncoderDecoderMutableIsacFloat::ErrorCode() {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->ErrorCode();
}
int AudioEncoderDecoderMutableIsacFloat::PacketDuration(
const uint8_t* encoded,
size_t encoded_len) const {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->PacketDuration(encoded, encoded_len);
}
int AudioEncoderDecoderMutableIsacFloat::PacketDurationRedundant(
const uint8_t* encoded,
size_t encoded_len) const {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->PacketDurationRedundant(encoded, encoded_len);
}
bool AudioEncoderDecoderMutableIsacFloat::PacketHasFec(
const uint8_t* encoded,
size_t encoded_len) const {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->PacketHasFec(encoded, encoded_len);
}
size_t AudioEncoderDecoderMutableIsacFloat::Channels() const {
CriticalSectionScoped cs(encoder_lock_.get());
return encoder()->Channels();
}
} // namespace webrtc

View File

@ -17,13 +17,13 @@ namespace webrtc {
namespace {
void TestBadConfig(const AudioEncoderDecoderIsac::Config& config) {
void TestBadConfig(const AudioEncoderIsac::Config& config) {
EXPECT_FALSE(config.IsOk());
}
void TestGoodConfig(const AudioEncoderDecoderIsac::Config& config) {
void TestGoodConfig(const AudioEncoderIsac::Config& config) {
EXPECT_TRUE(config.IsOk());
AudioEncoderDecoderIsac ed(config);
AudioEncoderIsac aei(config);
}
// Wrap subroutine calls that test things in this, so that the error messages
@ -34,7 +34,7 @@ void TestGoodConfig(const AudioEncoderDecoderIsac::Config& config) {
} // namespace
TEST(AudioEncoderIsacTest, TestConfigBitrate) {
AudioEncoderDecoderIsac::Config config;
AudioEncoderIsac::Config config;
// The default value is some real, positive value.
EXPECT_GT(config.bit_rate, 1);