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:
@ -380,6 +380,15 @@ source_set("ilbc") {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
source_set("isac_common") {
|
||||||
|
sources = [
|
||||||
|
"codecs/isac/audio_encoder_isac_t.h",
|
||||||
|
"codecs/isac/audio_encoder_isac_t_impl.h",
|
||||||
|
"codecs/isac/locked_bandwidth_info.cc",
|
||||||
|
"codecs/isac/locked_bandwidth_info.h",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
config("isac_config") {
|
config("isac_config") {
|
||||||
include_dirs = [
|
include_dirs = [
|
||||||
"../../..",
|
"../../..",
|
||||||
@ -389,8 +398,6 @@ config("isac_config") {
|
|||||||
|
|
||||||
source_set("isac") {
|
source_set("isac") {
|
||||||
sources = [
|
sources = [
|
||||||
"codecs/isac/audio_encoder_isac_t.h",
|
|
||||||
"codecs/isac/audio_encoder_isac_t_impl.h",
|
|
||||||
"codecs/isac/main/interface/audio_encoder_isac.h",
|
"codecs/isac/main/interface/audio_encoder_isac.h",
|
||||||
"codecs/isac/main/interface/isac.h",
|
"codecs/isac/main/interface/isac.h",
|
||||||
"codecs/isac/main/source/arith_routines.c",
|
"codecs/isac/main/source/arith_routines.c",
|
||||||
@ -458,6 +465,7 @@ source_set("isac") {
|
|||||||
deps = [
|
deps = [
|
||||||
":audio_decoder_interface",
|
":audio_decoder_interface",
|
||||||
":audio_encoder_interface",
|
":audio_encoder_interface",
|
||||||
|
":isac_common",
|
||||||
"../../common_audio",
|
"../../common_audio",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -471,8 +479,6 @@ config("isac_fix_config") {
|
|||||||
|
|
||||||
source_set("isac_fix") {
|
source_set("isac_fix") {
|
||||||
sources = [
|
sources = [
|
||||||
"codecs/isac/audio_encoder_isac_t.h",
|
|
||||||
"codecs/isac/audio_encoder_isac_t_impl.h",
|
|
||||||
"codecs/isac/fix/interface/audio_encoder_isacfix.h",
|
"codecs/isac/fix/interface/audio_encoder_isacfix.h",
|
||||||
"codecs/isac/fix/interface/isacfix.h",
|
"codecs/isac/fix/interface/isacfix.h",
|
||||||
"codecs/isac/fix/source/arith_routines.c",
|
"codecs/isac/fix/source/arith_routines.c",
|
||||||
@ -533,6 +539,7 @@ source_set("isac_fix") {
|
|||||||
|
|
||||||
deps = [
|
deps = [
|
||||||
":audio_encoder_interface",
|
":audio_encoder_interface",
|
||||||
|
":isac_common",
|
||||||
"../../common_audio",
|
"../../common_audio",
|
||||||
"../../system_wrappers",
|
"../../system_wrappers",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -15,6 +15,7 @@
|
|||||||
'codecs/g722/g722.gypi',
|
'codecs/g722/g722.gypi',
|
||||||
'codecs/ilbc/ilbc.gypi',
|
'codecs/ilbc/ilbc.gypi',
|
||||||
'codecs/isac/isac.gypi',
|
'codecs/isac/isac.gypi',
|
||||||
|
'codecs/isac/isac_common.gypi',
|
||||||
'codecs/isac/isacfix.gypi',
|
'codecs/isac/isacfix.gypi',
|
||||||
'codecs/pcm16b/pcm16b.gypi',
|
'codecs/pcm16b/pcm16b.gypi',
|
||||||
'codecs/red/red.gypi',
|
'codecs/red/red.gypi',
|
||||||
|
|||||||
@ -13,17 +13,14 @@
|
|||||||
|
|
||||||
#include <vector>
|
#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_decoder.h"
|
||||||
#include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
|
#include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
|
||||||
|
#include "webrtc/modules/audio_coding/codecs/isac/locked_bandwidth_info.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
class CriticalSectionWrapper;
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class AudioEncoderDecoderIsacT : public AudioEncoder, public AudioDecoder {
|
class AudioEncoderIsacT final : public AudioEncoder {
|
||||||
public:
|
public:
|
||||||
// Allowed combinations of sample rate, frame size, and bit rate are
|
// Allowed combinations of sample rate, frame size, and bit rate are
|
||||||
// - 16000 Hz, 30 ms, 10000-32000 bps
|
// - 16000 Hz, 30 ms, 10000-32000 bps
|
||||||
@ -34,6 +31,8 @@ class AudioEncoderDecoderIsacT : public AudioEncoder, public AudioDecoder {
|
|||||||
Config();
|
Config();
|
||||||
bool IsOk() const;
|
bool IsOk() const;
|
||||||
|
|
||||||
|
LockedIsacBandwidthInfo* bwinfo;
|
||||||
|
|
||||||
int payload_type;
|
int payload_type;
|
||||||
int sample_rate_hz;
|
int sample_rate_hz;
|
||||||
int frame_size_ms;
|
int frame_size_ms;
|
||||||
@ -50,18 +49,50 @@ class AudioEncoderDecoderIsacT : public AudioEncoder, public AudioDecoder {
|
|||||||
bool enforce_frame_size;
|
bool enforce_frame_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit AudioEncoderDecoderIsacT(const Config& config);
|
explicit AudioEncoderIsacT(const Config& config);
|
||||||
~AudioEncoderDecoderIsacT() override;
|
~AudioEncoderIsacT() override;
|
||||||
|
|
||||||
// AudioEncoder public methods.
|
|
||||||
int SampleRateHz() const override;
|
int SampleRateHz() const override;
|
||||||
int NumChannels() const override;
|
int NumChannels() const override;
|
||||||
size_t MaxEncodedBytes() const override;
|
size_t MaxEncodedBytes() const override;
|
||||||
int Num10MsFramesInNextPacket() const override;
|
int Num10MsFramesInNextPacket() const override;
|
||||||
int Max10MsFramesInAPacket() const override;
|
int Max10MsFramesInAPacket() const override;
|
||||||
int GetTargetBitrate() 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;
|
bool HasDecodePlc() const override;
|
||||||
int DecodePlc(int num_frames, int16_t* decoded) override;
|
int DecodePlc(int num_frames, int16_t* decoded) override;
|
||||||
int Init() override;
|
int Init() override;
|
||||||
@ -71,15 +102,7 @@ class AudioEncoderDecoderIsacT : public AudioEncoder, public AudioDecoder {
|
|||||||
uint32_t rtp_timestamp,
|
uint32_t rtp_timestamp,
|
||||||
uint32_t arrival_timestamp) override;
|
uint32_t arrival_timestamp) override;
|
||||||
int ErrorCode() override;
|
int ErrorCode() override;
|
||||||
size_t Channels() const override { return 1; }
|
size_t Channels() const override;
|
||||||
|
|
||||||
// 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.
|
|
||||||
int DecodeInternal(const uint8_t* encoded,
|
int DecodeInternal(const uint8_t* encoded,
|
||||||
size_t encoded_len,
|
size_t encoded_len,
|
||||||
int sample_rate_hz,
|
int sample_rate_hz,
|
||||||
@ -87,44 +110,11 @@ class AudioEncoderDecoderIsacT : public AudioEncoder, public AudioDecoder {
|
|||||||
SpeechType* speech_type) override;
|
SpeechType* speech_type) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// This value is taken from STREAM_SIZE_MAX_60 for iSAC float (60 ms) and
|
typename T::instance_type* isac_state_;
|
||||||
// STREAM_MAXW16_60MS for iSAC fix (60 ms).
|
LockedIsacBandwidthInfo* bwinfo_;
|
||||||
static const size_t kSufficientEncodeBufferSizeBytes = 400;
|
int decoder_sample_rate_hz_;
|
||||||
|
|
||||||
const int payload_type_;
|
DISALLOW_COPY_AND_ASSIGN(AudioDecoderIsacT);
|
||||||
|
|
||||||
// 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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
#include "webrtc/base/checks.h"
|
#include "webrtc/base/checks.h"
|
||||||
#include "webrtc/modules/audio_coding/codecs/isac/main/interface/isac.h"
|
#include "webrtc/modules/audio_coding/codecs/isac/main/interface/isac.h"
|
||||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
@ -25,8 +24,9 @@ const int kIsacPayloadType = 103;
|
|||||||
const int kDefaultBitRate = 32000;
|
const int kDefaultBitRate = 32000;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
AudioEncoderDecoderIsacT<T>::Config::Config()
|
AudioEncoderIsacT<T>::Config::Config()
|
||||||
: payload_type(kIsacPayloadType),
|
: bwinfo(nullptr),
|
||||||
|
payload_type(kIsacPayloadType),
|
||||||
sample_rate_hz(16000),
|
sample_rate_hz(16000),
|
||||||
frame_size_ms(30),
|
frame_size_ms(30),
|
||||||
bit_rate(kDefaultBitRate),
|
bit_rate(kDefaultBitRate),
|
||||||
@ -37,11 +37,13 @@ AudioEncoderDecoderIsacT<T>::Config::Config()
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool AudioEncoderDecoderIsacT<T>::Config::IsOk() const {
|
bool AudioEncoderIsacT<T>::Config::IsOk() const {
|
||||||
if (max_bit_rate < 32000 && max_bit_rate != -1)
|
if (max_bit_rate < 32000 && max_bit_rate != -1)
|
||||||
return false;
|
return false;
|
||||||
if (max_payload_size_bytes < 120 && max_payload_size_bytes != -1)
|
if (max_payload_size_bytes < 120 && max_payload_size_bytes != -1)
|
||||||
return false;
|
return false;
|
||||||
|
if (adaptive_mode && !bwinfo)
|
||||||
|
return false;
|
||||||
switch (sample_rate_hz) {
|
switch (sample_rate_hz) {
|
||||||
case 16000:
|
case 16000:
|
||||||
if (max_bit_rate > 53400)
|
if (max_bit_rate > 53400)
|
||||||
@ -65,11 +67,9 @@ bool AudioEncoderDecoderIsacT<T>::Config::IsOk() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
AudioEncoderDecoderIsacT<T>::AudioEncoderDecoderIsacT(const Config& config)
|
AudioEncoderIsacT<T>::AudioEncoderIsacT(const Config& config)
|
||||||
: payload_type_(config.payload_type),
|
: payload_type_(config.payload_type),
|
||||||
state_lock_(CriticalSectionWrapper::CreateCriticalSection()),
|
bwinfo_(config.bwinfo),
|
||||||
decoder_sample_rate_hz_(0),
|
|
||||||
lock_(CriticalSectionWrapper::CreateCriticalSection()),
|
|
||||||
packet_in_progress_(false),
|
packet_in_progress_(false),
|
||||||
target_bitrate_bps_(config.adaptive_mode ? -1 : (config.bit_rate == 0
|
target_bitrate_bps_(config.adaptive_mode ? -1 : (config.bit_rate == 0
|
||||||
? kDefaultBitRate
|
? kDefaultBitRate
|
||||||
@ -85,80 +85,82 @@ AudioEncoderDecoderIsacT<T>::AudioEncoderDecoderIsacT(const Config& config)
|
|||||||
} else {
|
} else {
|
||||||
CHECK_EQ(0, T::Control(isac_state_, bit_rate, config.frame_size_ms));
|
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)
|
if (config.max_payload_size_bytes != -1)
|
||||||
CHECK_EQ(0,
|
CHECK_EQ(0,
|
||||||
T::SetMaxPayloadSize(isac_state_, config.max_payload_size_bytes));
|
T::SetMaxPayloadSize(isac_state_, config.max_payload_size_bytes));
|
||||||
if (config.max_bit_rate != -1)
|
if (config.max_bit_rate != -1)
|
||||||
CHECK_EQ(0, T::SetMaxRate(isac_state_, config.max_bit_rate));
|
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>
|
template <typename T>
|
||||||
AudioEncoderDecoderIsacT<T>::~AudioEncoderDecoderIsacT() {
|
AudioEncoderIsacT<T>::~AudioEncoderIsacT() {
|
||||||
CHECK_EQ(0, T::Free(isac_state_));
|
CHECK_EQ(0, T::Free(isac_state_));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
int AudioEncoderDecoderIsacT<T>::SampleRateHz() const {
|
int AudioEncoderIsacT<T>::SampleRateHz() const {
|
||||||
CriticalSectionScoped cs(state_lock_.get());
|
|
||||||
return T::EncSampRate(isac_state_);
|
return T::EncSampRate(isac_state_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
int AudioEncoderDecoderIsacT<T>::NumChannels() const {
|
int AudioEncoderIsacT<T>::NumChannels() const {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
size_t AudioEncoderDecoderIsacT<T>::MaxEncodedBytes() const {
|
size_t AudioEncoderIsacT<T>::MaxEncodedBytes() const {
|
||||||
return kSufficientEncodeBufferSizeBytes;
|
return kSufficientEncodeBufferSizeBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
int AudioEncoderDecoderIsacT<T>::Num10MsFramesInNextPacket() const {
|
int AudioEncoderIsacT<T>::Num10MsFramesInNextPacket() const {
|
||||||
CriticalSectionScoped cs(state_lock_.get());
|
|
||||||
const int samples_in_next_packet = T::GetNewFrameLen(isac_state_);
|
const int samples_in_next_packet = T::GetNewFrameLen(isac_state_);
|
||||||
return rtc::CheckedDivExact(samples_in_next_packet,
|
return rtc::CheckedDivExact(samples_in_next_packet,
|
||||||
rtc::CheckedDivExact(SampleRateHz(), 100));
|
rtc::CheckedDivExact(SampleRateHz(), 100));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
int AudioEncoderDecoderIsacT<T>::Max10MsFramesInAPacket() const {
|
int AudioEncoderIsacT<T>::Max10MsFramesInAPacket() const {
|
||||||
return 6; // iSAC puts at most 60 ms in a packet.
|
return 6; // iSAC puts at most 60 ms in a packet.
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
int AudioEncoderDecoderIsacT<T>::GetTargetBitrate() const {
|
int AudioEncoderIsacT<T>::GetTargetBitrate() const {
|
||||||
return target_bitrate_bps_;
|
return target_bitrate_bps_;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
AudioEncoder::EncodedInfo AudioEncoderDecoderIsacT<T>::EncodeInternal(
|
AudioEncoder::EncodedInfo AudioEncoderIsacT<T>::EncodeInternal(
|
||||||
uint32_t rtp_timestamp,
|
uint32_t rtp_timestamp,
|
||||||
const int16_t* audio,
|
const int16_t* audio,
|
||||||
size_t max_encoded_bytes,
|
size_t max_encoded_bytes,
|
||||||
uint8_t* encoded) {
|
uint8_t* encoded) {
|
||||||
CriticalSectionScoped cs_lock(lock_.get());
|
|
||||||
if (!packet_in_progress_) {
|
if (!packet_in_progress_) {
|
||||||
// Starting a new packet; remember the timestamp for later.
|
// Starting a new packet; remember the timestamp for later.
|
||||||
packet_in_progress_ = true;
|
packet_in_progress_ = true;
|
||||||
packet_timestamp_ = rtp_timestamp;
|
packet_timestamp_ = rtp_timestamp;
|
||||||
}
|
}
|
||||||
int r;
|
if (bwinfo_) {
|
||||||
{
|
IsacBandwidthInfo bwinfo = bwinfo_->Get();
|
||||||
CriticalSectionScoped cs(state_lock_.get());
|
T::SetBandwidthInfo(isac_state_, &bwinfo);
|
||||||
r = T::Encode(isac_state_, audio, encoded);
|
|
||||||
CHECK_GE(r, 0) << "Encode failed (error code "
|
|
||||||
<< T::GetErrorCode(isac_state_) << ")";
|
|
||||||
}
|
}
|
||||||
|
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
|
// 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.
|
// 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)
|
if (r == 0)
|
||||||
return EncodedInfo();
|
return EncodedInfo();
|
||||||
@ -174,12 +176,33 @@ AudioEncoder::EncodedInfo AudioEncoderDecoderIsacT<T>::EncodeInternal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
int AudioEncoderDecoderIsacT<T>::DecodeInternal(const uint8_t* encoded,
|
AudioDecoderIsacT<T>::AudioDecoderIsacT()
|
||||||
size_t encoded_len,
|
: AudioDecoderIsacT(nullptr) {
|
||||||
int sample_rate_hz,
|
}
|
||||||
int16_t* decoded,
|
|
||||||
SpeechType* speech_type) {
|
template <typename T>
|
||||||
CriticalSectionScoped cs(state_lock_.get());
|
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
|
// 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.
|
// in fact it outputs 32000 Hz. This is the iSAC fullband mode.
|
||||||
if (sample_rate_hz == 48000)
|
if (sample_rate_hz == 48000)
|
||||||
@ -199,40 +222,47 @@ int AudioEncoderDecoderIsacT<T>::DecodeInternal(const uint8_t* encoded,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool AudioEncoderDecoderIsacT<T>::HasDecodePlc() const {
|
bool AudioDecoderIsacT<T>::HasDecodePlc() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
int AudioEncoderDecoderIsacT<T>::DecodePlc(int num_frames, int16_t* decoded) {
|
int AudioDecoderIsacT<T>::DecodePlc(int num_frames, int16_t* decoded) {
|
||||||
CriticalSectionScoped cs(state_lock_.get());
|
|
||||||
return T::DecodePlc(isac_state_, decoded, num_frames);
|
return T::DecodePlc(isac_state_, decoded, num_frames);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
int AudioEncoderDecoderIsacT<T>::Init() {
|
int AudioDecoderIsacT<T>::Init() {
|
||||||
CriticalSectionScoped cs(state_lock_.get());
|
|
||||||
return T::DecoderInit(isac_state_);
|
return T::DecoderInit(isac_state_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
int AudioEncoderDecoderIsacT<T>::IncomingPacket(const uint8_t* payload,
|
int AudioDecoderIsacT<T>::IncomingPacket(const uint8_t* payload,
|
||||||
size_t payload_len,
|
size_t payload_len,
|
||||||
uint16_t rtp_sequence_number,
|
uint16_t rtp_sequence_number,
|
||||||
uint32_t rtp_timestamp,
|
uint32_t rtp_timestamp,
|
||||||
uint32_t arrival_timestamp) {
|
uint32_t arrival_timestamp) {
|
||||||
CriticalSectionScoped cs(state_lock_.get());
|
int ret = T::UpdateBwEstimate(
|
||||||
return T::UpdateBwEstimate(
|
|
||||||
isac_state_, payload, static_cast<int32_t>(payload_len),
|
isac_state_, payload, static_cast<int32_t>(payload_len),
|
||||||
rtp_sequence_number, rtp_timestamp, arrival_timestamp);
|
rtp_sequence_number, rtp_timestamp, arrival_timestamp);
|
||||||
|
if (bwinfo_) {
|
||||||
|
IsacBandwidthInfo bwinfo;
|
||||||
|
T::GetBandwidthInfo(isac_state_, &bwinfo);
|
||||||
|
bwinfo_->Set(bwinfo);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
int AudioEncoderDecoderIsacT<T>::ErrorCode() {
|
int AudioDecoderIsacT<T>::ErrorCode() {
|
||||||
CriticalSectionScoped cs(state_lock_.get());
|
|
||||||
return T::GetErrorCode(isac_state_);
|
return T::GetErrorCode(isac_state_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
size_t AudioDecoderIsacT<T>::Channels() const {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
||||||
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_
|
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_
|
||||||
|
|||||||
@ -120,46 +120,18 @@ struct IsacFix {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef AudioEncoderDecoderIsacT<IsacFix> AudioEncoderDecoderIsacFix;
|
using AudioEncoderIsacFix = AudioEncoderIsacT<IsacFix>;
|
||||||
|
using AudioDecoderIsacFix = AudioDecoderIsacT<IsacFix>;
|
||||||
|
|
||||||
struct CodecInst;
|
struct CodecInst;
|
||||||
|
|
||||||
class AudioEncoderDecoderMutableIsacFix
|
class AudioEncoderMutableIsacFix
|
||||||
: public AudioEncoderMutableImpl<AudioEncoderDecoderIsacFix,
|
: public AudioEncoderMutableImpl<AudioEncoderIsacFix> {
|
||||||
AudioEncoderDecoderMutableIsac> {
|
|
||||||
public:
|
public:
|
||||||
explicit AudioEncoderDecoderMutableIsacFix(const CodecInst& codec_inst);
|
explicit AudioEncoderMutableIsacFix(const CodecInst& codec_inst,
|
||||||
void UpdateSettings(const CodecInst& codec_inst) override;
|
LockedIsacBandwidthInfo* bwinfo);
|
||||||
void SetMaxPayloadSize(int max_payload_size_bytes) override;
|
void SetMaxPayloadSize(int max_payload_size_bytes) override;
|
||||||
void SetMaxRate(int max_rate_bps) 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
|
} // namespace webrtc
|
||||||
|
|||||||
@ -17,13 +17,15 @@ namespace webrtc {
|
|||||||
|
|
||||||
const uint16_t IsacFix::kFixSampleRate;
|
const uint16_t IsacFix::kFixSampleRate;
|
||||||
|
|
||||||
// Explicit instantiation of AudioEncoderDecoderIsacT<IsacFix>, a.k.a.
|
// Explicit instantiation:
|
||||||
// AudioEncoderDecoderIsacFix.
|
template class AudioEncoderIsacT<IsacFix>;
|
||||||
template class AudioEncoderDecoderIsacT<IsacFix>;
|
template class AudioDecoderIsacT<IsacFix>;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
AudioEncoderDecoderIsacFix::Config CreateConfig(const CodecInst& codec_inst) {
|
AudioEncoderIsacFix::Config CreateConfig(const CodecInst& codec_inst,
|
||||||
AudioEncoderDecoderIsacFix::Config config;
|
LockedIsacBandwidthInfo* bwinfo) {
|
||||||
|
AudioEncoderIsacFix::Config config;
|
||||||
|
config.bwinfo = bwinfo;
|
||||||
config.payload_type = codec_inst.pltype;
|
config.payload_type = codec_inst.pltype;
|
||||||
config.sample_rate_hz = codec_inst.plfreq;
|
config.sample_rate_hz = codec_inst.plfreq;
|
||||||
config.frame_size_ms =
|
config.frame_size_ms =
|
||||||
@ -35,110 +37,22 @@ AudioEncoderDecoderIsacFix::Config CreateConfig(const CodecInst& codec_inst) {
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
AudioEncoderDecoderMutableIsacFix::AudioEncoderDecoderMutableIsacFix(
|
AudioEncoderMutableIsacFix::AudioEncoderMutableIsacFix(
|
||||||
const CodecInst& codec_inst)
|
const CodecInst& codec_inst,
|
||||||
: AudioEncoderMutableImpl<AudioEncoderDecoderIsacFix,
|
LockedIsacBandwidthInfo* bwinfo)
|
||||||
AudioEncoderDecoderMutableIsac>(
|
: AudioEncoderMutableImpl<AudioEncoderIsacFix>(
|
||||||
CreateConfig(codec_inst)) {
|
CreateConfig(codec_inst, bwinfo)) {}
|
||||||
}
|
|
||||||
|
|
||||||
void AudioEncoderDecoderMutableIsacFix::UpdateSettings(
|
void AudioEncoderMutableIsacFix::SetMaxPayloadSize(int max_payload_size_bytes) {
|
||||||
const CodecInst& codec_inst) {
|
|
||||||
bool success = Reconstruct(CreateConfig(codec_inst));
|
|
||||||
DCHECK(success);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioEncoderDecoderMutableIsacFix::SetMaxPayloadSize(
|
|
||||||
int max_payload_size_bytes) {
|
|
||||||
auto conf = config();
|
auto conf = config();
|
||||||
conf.max_payload_size_bytes = max_payload_size_bytes;
|
conf.max_payload_size_bytes = max_payload_size_bytes;
|
||||||
Reconstruct(conf);
|
Reconstruct(conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioEncoderDecoderMutableIsacFix::SetMaxRate(int max_rate_bps) {
|
void AudioEncoderMutableIsacFix::SetMaxRate(int max_rate_bps) {
|
||||||
auto conf = config();
|
auto conf = config();
|
||||||
conf.max_bit_rate = max_rate_bps;
|
conf.max_bit_rate = max_rate_bps;
|
||||||
Reconstruct(conf);
|
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
|
} // namespace webrtc
|
||||||
|
|||||||
@ -241,6 +241,31 @@ static void WebRtcIsacfix_InitMIPS(void) {
|
|||||||
}
|
}
|
||||||
#endif
|
#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(...)
|
* WebRtcIsacfix_EncoderInit(...)
|
||||||
*
|
*
|
||||||
@ -317,29 +342,7 @@ int16_t WebRtcIsacfix_EncoderInit(ISACFIX_MainStruct *ISAC_main_inst,
|
|||||||
WebRtcIsacfix_InitPostFilterbank(&ISAC_inst->ISACenc_obj.interpolatorstr_obj);
|
WebRtcIsacfix_InitPostFilterbank(&ISAC_inst->ISACenc_obj.interpolatorstr_obj);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Initiaze function pointers.
|
InitFunctionPointers();
|
||||||
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
|
|
||||||
|
|
||||||
return statusInit;
|
return statusInit;
|
||||||
}
|
}
|
||||||
@ -575,6 +578,8 @@ int16_t WebRtcIsacfix_DecoderInit(ISACFIX_MainStruct *ISAC_main_inst)
|
|||||||
{
|
{
|
||||||
ISACFIX_SubStruct *ISAC_inst;
|
ISACFIX_SubStruct *ISAC_inst;
|
||||||
|
|
||||||
|
InitFunctionPointers();
|
||||||
|
|
||||||
/* typecast pointer to real structure */
|
/* typecast pointer to real structure */
|
||||||
ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
|
ISAC_inst = (ISACFIX_SubStruct *)ISAC_main_inst;
|
||||||
|
|
||||||
|
|||||||
@ -15,6 +15,7 @@
|
|||||||
'<(webrtc_root)/common_audio/common_audio.gyp:common_audio',
|
'<(webrtc_root)/common_audio/common_audio.gyp:common_audio',
|
||||||
'audio_decoder_interface',
|
'audio_decoder_interface',
|
||||||
'audio_encoder_interface',
|
'audio_encoder_interface',
|
||||||
|
'isac_common',
|
||||||
],
|
],
|
||||||
'include_dirs': [
|
'include_dirs': [
|
||||||
'main/interface',
|
'main/interface',
|
||||||
@ -27,8 +28,6 @@
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
'sources': [
|
'sources': [
|
||||||
'audio_encoder_isac_t.h',
|
|
||||||
'audio_encoder_isac_t_impl.h',
|
|
||||||
'main/interface/audio_encoder_isac.h',
|
'main/interface/audio_encoder_isac.h',
|
||||||
'main/interface/isac.h',
|
'main/interface/isac.h',
|
||||||
'main/source/arith_routines.c',
|
'main/source/arith_routines.c',
|
||||||
|
|||||||
22
webrtc/modules/audio_coding/codecs/isac/isac_common.gypi
Normal file
22
webrtc/modules/audio_coding/codecs/isac/isac_common.gypi
Normal 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',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
@ -14,6 +14,7 @@
|
|||||||
'dependencies': [
|
'dependencies': [
|
||||||
'<(webrtc_root)/common_audio/common_audio.gyp:common_audio',
|
'<(webrtc_root)/common_audio/common_audio.gyp:common_audio',
|
||||||
'<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers',
|
'<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers',
|
||||||
|
'isac_common',
|
||||||
],
|
],
|
||||||
'include_dirs': [
|
'include_dirs': [
|
||||||
'fix/interface',
|
'fix/interface',
|
||||||
@ -26,8 +27,6 @@
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
'sources': [
|
'sources': [
|
||||||
'audio_encoder_isac_t.h',
|
|
||||||
'audio_encoder_isac_t_impl.h',
|
|
||||||
'fix/interface/audio_encoder_isacfix.h',
|
'fix/interface/audio_encoder_isacfix.h',
|
||||||
'fix/interface/isacfix.h',
|
'fix/interface/isacfix.h',
|
||||||
'fix/source/arith_routines.c',
|
'fix/source/arith_routines.c',
|
||||||
|
|||||||
@ -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
|
||||||
@ -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_
|
||||||
@ -118,46 +118,18 @@ struct IsacFloat {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef AudioEncoderDecoderIsacT<IsacFloat> AudioEncoderDecoderIsac;
|
using AudioEncoderIsac = AudioEncoderIsacT<IsacFloat>;
|
||||||
|
using AudioDecoderIsac = AudioDecoderIsacT<IsacFloat>;
|
||||||
|
|
||||||
struct CodecInst;
|
struct CodecInst;
|
||||||
|
|
||||||
class AudioEncoderDecoderMutableIsacFloat
|
class AudioEncoderMutableIsacFloat
|
||||||
: public AudioEncoderMutableImpl<AudioEncoderDecoderIsac,
|
: public AudioEncoderMutableImpl<AudioEncoderIsac> {
|
||||||
AudioEncoderDecoderMutableIsac> {
|
|
||||||
public:
|
public:
|
||||||
explicit AudioEncoderDecoderMutableIsacFloat(const CodecInst& codec_inst);
|
AudioEncoderMutableIsacFloat(const CodecInst& codec_inst,
|
||||||
void UpdateSettings(const CodecInst& codec_inst) override;
|
LockedIsacBandwidthInfo* bwinfo);
|
||||||
void SetMaxPayloadSize(int max_payload_size_bytes) override;
|
void SetMaxPayloadSize(int max_payload_size_bytes) override;
|
||||||
void SetMaxRate(int max_rate_bps) 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
|
} // namespace webrtc
|
||||||
|
|||||||
@ -15,13 +15,15 @@
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
// Explicit instantiation of AudioEncoderDecoderIsacT<IsacFloat>, a.k.a.
|
// Explicit instantiation:
|
||||||
// AudioEncoderDecoderIsac.
|
template class AudioEncoderIsacT<IsacFloat>;
|
||||||
template class AudioEncoderDecoderIsacT<IsacFloat>;
|
template class AudioDecoderIsacT<IsacFloat>;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
AudioEncoderDecoderIsac::Config CreateConfig(const CodecInst& codec_inst) {
|
AudioEncoderIsac::Config CreateConfig(const CodecInst& codec_inst,
|
||||||
AudioEncoderDecoderIsac::Config config;
|
LockedIsacBandwidthInfo* bwinfo) {
|
||||||
|
AudioEncoderIsac::Config config;
|
||||||
|
config.bwinfo = bwinfo;
|
||||||
config.payload_type = codec_inst.pltype;
|
config.payload_type = codec_inst.pltype;
|
||||||
config.sample_rate_hz = codec_inst.plfreq;
|
config.sample_rate_hz = codec_inst.plfreq;
|
||||||
config.frame_size_ms =
|
config.frame_size_ms =
|
||||||
@ -33,111 +35,24 @@ AudioEncoderDecoderIsac::Config CreateConfig(const CodecInst& codec_inst) {
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
AudioEncoderDecoderMutableIsacFloat::AudioEncoderDecoderMutableIsacFloat(
|
AudioEncoderMutableIsacFloat::AudioEncoderMutableIsacFloat(
|
||||||
const CodecInst& codec_inst)
|
const CodecInst& codec_inst,
|
||||||
: AudioEncoderMutableImpl<AudioEncoderDecoderIsac,
|
LockedIsacBandwidthInfo* bwinfo)
|
||||||
AudioEncoderDecoderMutableIsac>(
|
: AudioEncoderMutableImpl<AudioEncoderIsac>(
|
||||||
CreateConfig(codec_inst)) {
|
CreateConfig(codec_inst, bwinfo)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioEncoderDecoderMutableIsacFloat::UpdateSettings(
|
void AudioEncoderMutableIsacFloat::SetMaxPayloadSize(
|
||||||
const CodecInst& codec_inst) {
|
|
||||||
bool success = Reconstruct(CreateConfig(codec_inst));
|
|
||||||
DCHECK(success);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioEncoderDecoderMutableIsacFloat::SetMaxPayloadSize(
|
|
||||||
int max_payload_size_bytes) {
|
int max_payload_size_bytes) {
|
||||||
auto conf = config();
|
auto conf = config();
|
||||||
conf.max_payload_size_bytes = max_payload_size_bytes;
|
conf.max_payload_size_bytes = max_payload_size_bytes;
|
||||||
Reconstruct(conf);
|
Reconstruct(conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioEncoderDecoderMutableIsacFloat::SetMaxRate(int max_rate_bps) {
|
void AudioEncoderMutableIsacFloat::SetMaxRate(int max_rate_bps) {
|
||||||
auto conf = config();
|
auto conf = config();
|
||||||
conf.max_bit_rate = max_rate_bps;
|
conf.max_bit_rate = max_rate_bps;
|
||||||
Reconstruct(conf);
|
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
|
} // namespace webrtc
|
||||||
|
|||||||
@ -17,13 +17,13 @@ namespace webrtc {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void TestBadConfig(const AudioEncoderDecoderIsac::Config& config) {
|
void TestBadConfig(const AudioEncoderIsac::Config& config) {
|
||||||
EXPECT_FALSE(config.IsOk());
|
EXPECT_FALSE(config.IsOk());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestGoodConfig(const AudioEncoderDecoderIsac::Config& config) {
|
void TestGoodConfig(const AudioEncoderIsac::Config& config) {
|
||||||
EXPECT_TRUE(config.IsOk());
|
EXPECT_TRUE(config.IsOk());
|
||||||
AudioEncoderDecoderIsac ed(config);
|
AudioEncoderIsac aei(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrap subroutine calls that test things in this, so that the error messages
|
// Wrap subroutine calls that test things in this, so that the error messages
|
||||||
@ -34,7 +34,7 @@ void TestGoodConfig(const AudioEncoderDecoderIsac::Config& config) {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST(AudioEncoderIsacTest, TestConfigBitrate) {
|
TEST(AudioEncoderIsacTest, TestConfigBitrate) {
|
||||||
AudioEncoderDecoderIsac::Config config;
|
AudioEncoderIsac::Config config;
|
||||||
|
|
||||||
// The default value is some real, positive value.
|
// The default value is some real, positive value.
|
||||||
EXPECT_GT(config.bit_rate, 1);
|
EXPECT_GT(config.bit_rate, 1);
|
||||||
|
|||||||
@ -721,9 +721,9 @@ class AcmReRegisterIsacMtTestOldApi : public AudioCodingModuleTestOldApi {
|
|||||||
receive_packet_count_(0),
|
receive_packet_count_(0),
|
||||||
next_insert_packet_time_ms_(0),
|
next_insert_packet_time_ms_(0),
|
||||||
fake_clock_(new SimulatedClock(0)) {
|
fake_clock_(new SimulatedClock(0)) {
|
||||||
AudioEncoderDecoderIsac::Config config;
|
AudioEncoderIsac::Config config;
|
||||||
config.payload_type = kPayloadType;
|
config.payload_type = kPayloadType;
|
||||||
isac_encoder_.reset(new AudioEncoderDecoderIsac(config));
|
isac_encoder_.reset(new AudioEncoderIsac(config));
|
||||||
clock_ = fake_clock_.get();
|
clock_ = fake_clock_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -845,7 +845,7 @@ class AcmReRegisterIsacMtTestOldApi : public AudioCodingModuleTestOldApi {
|
|||||||
bool codec_registered_ GUARDED_BY(crit_sect_);
|
bool codec_registered_ GUARDED_BY(crit_sect_);
|
||||||
int receive_packet_count_ GUARDED_BY(crit_sect_);
|
int receive_packet_count_ GUARDED_BY(crit_sect_);
|
||||||
int64_t next_insert_packet_time_ms_ GUARDED_BY(crit_sect_);
|
int64_t next_insert_packet_time_ms_ GUARDED_BY(crit_sect_);
|
||||||
rtc::scoped_ptr<AudioEncoderDecoderIsac> isac_encoder_;
|
rtc::scoped_ptr<AudioEncoderIsac> isac_encoder_;
|
||||||
rtc::scoped_ptr<SimulatedClock> fake_clock_;
|
rtc::scoped_ptr<SimulatedClock> fake_clock_;
|
||||||
test::AudioLoop audio_loop_;
|
test::AudioLoop audio_loop_;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -75,55 +75,61 @@ bool IsG722(const CodecInst& codec) {
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
CodecOwner::CodecOwner()
|
CodecOwner::CodecOwner() : external_speech_encoder_(nullptr) {
|
||||||
: isac_is_encoder_(false), external_speech_encoder_(nullptr) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CodecOwner::~CodecOwner() = default;
|
CodecOwner::~CodecOwner() = default;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
AudioEncoderDecoderMutableIsac* CreateIsacCodec(const CodecInst& speech_inst) {
|
|
||||||
|
rtc::scoped_ptr<AudioDecoder> CreateIsacDecoder(
|
||||||
|
LockedIsacBandwidthInfo* bwinfo) {
|
||||||
#if defined(WEBRTC_CODEC_ISACFX)
|
#if defined(WEBRTC_CODEC_ISACFX)
|
||||||
return new AudioEncoderDecoderMutableIsacFix(speech_inst);
|
return rtc_make_scoped_ptr(new AudioDecoderIsacFix(bwinfo));
|
||||||
#elif defined(WEBRTC_CODEC_ISAC)
|
#elif defined(WEBRTC_CODEC_ISAC)
|
||||||
return new AudioEncoderDecoderMutableIsacFloat(speech_inst);
|
return rtc_make_scoped_ptr(new AudioDecoderIsac(bwinfo));
|
||||||
#else
|
#else
|
||||||
FATAL() << "iSAC is not supported.";
|
FATAL() << "iSAC is not supported.";
|
||||||
return nullptr;
|
return rtc::scoped_ptr<AudioDecoder>();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateSpeechEncoder(
|
rtc::scoped_ptr<AudioEncoderMutable> CreateIsacEncoder(
|
||||||
const CodecInst& speech_inst,
|
const CodecInst& speech_inst,
|
||||||
rtc::scoped_ptr<AudioEncoderMutable>* speech_encoder,
|
LockedIsacBandwidthInfo* bwinfo) {
|
||||||
rtc::scoped_ptr<AudioEncoderDecoderMutableIsac>* isac_codec,
|
#if defined(WEBRTC_CODEC_ISACFX)
|
||||||
bool* isac_is_encoder) {
|
return rtc_make_scoped_ptr(
|
||||||
|
new AudioEncoderMutableIsacFix(speech_inst, bwinfo));
|
||||||
|
#elif defined(WEBRTC_CODEC_ISAC)
|
||||||
|
return rtc_make_scoped_ptr(
|
||||||
|
new AudioEncoderMutableIsacFloat(speech_inst, bwinfo));
|
||||||
|
#else
|
||||||
|
FATAL() << "iSAC is not supported.";
|
||||||
|
return rtc::scoped_ptr<AudioEncoderMutable>();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc::scoped_ptr<AudioEncoderMutable> CreateSpeechEncoder(
|
||||||
|
const CodecInst& speech_inst,
|
||||||
|
LockedIsacBandwidthInfo* bwinfo) {
|
||||||
if (IsIsac(speech_inst)) {
|
if (IsIsac(speech_inst)) {
|
||||||
if (*isac_codec) {
|
return CreateIsacEncoder(speech_inst, bwinfo);
|
||||||
(*isac_codec)->UpdateSettings(speech_inst);
|
} else if (IsOpus(speech_inst)) {
|
||||||
} else {
|
return rtc_make_scoped_ptr(new AudioEncoderMutableOpus(speech_inst));
|
||||||
isac_codec->reset(CreateIsacCodec(speech_inst));
|
|
||||||
}
|
|
||||||
*isac_is_encoder = true;
|
|
||||||
speech_encoder->reset();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (IsOpus(speech_inst)) {
|
|
||||||
speech_encoder->reset(new AudioEncoderMutableOpus(speech_inst));
|
|
||||||
} else if (IsPcmU(speech_inst)) {
|
} else if (IsPcmU(speech_inst)) {
|
||||||
speech_encoder->reset(new AudioEncoderMutablePcmU(speech_inst));
|
return rtc_make_scoped_ptr(new AudioEncoderMutablePcmU(speech_inst));
|
||||||
} else if (IsPcmA(speech_inst)) {
|
} else if (IsPcmA(speech_inst)) {
|
||||||
speech_encoder->reset(new AudioEncoderMutablePcmA(speech_inst));
|
return rtc_make_scoped_ptr(new AudioEncoderMutablePcmA(speech_inst));
|
||||||
} else if (IsPcm16B(speech_inst)) {
|
} else if (IsPcm16B(speech_inst)) {
|
||||||
speech_encoder->reset(new AudioEncoderMutablePcm16B(speech_inst));
|
return rtc_make_scoped_ptr(new AudioEncoderMutablePcm16B(speech_inst));
|
||||||
} else if (IsIlbc(speech_inst)) {
|
} else if (IsIlbc(speech_inst)) {
|
||||||
speech_encoder->reset(new AudioEncoderMutableIlbc(speech_inst));
|
return rtc_make_scoped_ptr(new AudioEncoderMutableIlbc(speech_inst));
|
||||||
} else if (IsG722(speech_inst)) {
|
} else if (IsG722(speech_inst)) {
|
||||||
speech_encoder->reset(new AudioEncoderMutableG722(speech_inst));
|
return rtc_make_scoped_ptr(new AudioEncoderMutableG722(speech_inst));
|
||||||
} else {
|
} else {
|
||||||
FATAL();
|
FATAL();
|
||||||
|
return rtc::scoped_ptr<AudioEncoderMutable>();
|
||||||
}
|
}
|
||||||
*isac_is_encoder = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioEncoder* CreateRedEncoder(int red_payload_type,
|
AudioEncoder* CreateRedEncoder(int red_payload_type,
|
||||||
@ -176,8 +182,7 @@ void CodecOwner::SetEncoders(const CodecInst& speech_inst,
|
|||||||
int cng_payload_type,
|
int cng_payload_type,
|
||||||
ACMVADMode vad_mode,
|
ACMVADMode vad_mode,
|
||||||
int red_payload_type) {
|
int red_payload_type) {
|
||||||
CreateSpeechEncoder(speech_inst, &speech_encoder_, &isac_codec_,
|
speech_encoder_ = CreateSpeechEncoder(speech_inst, &isac_bandwidth_info_);
|
||||||
&isac_is_encoder_);
|
|
||||||
external_speech_encoder_ = nullptr;
|
external_speech_encoder_ = nullptr;
|
||||||
ChangeCngAndRed(cng_payload_type, vad_mode, red_payload_type);
|
ChangeCngAndRed(cng_payload_type, vad_mode, red_payload_type);
|
||||||
}
|
}
|
||||||
@ -188,7 +193,6 @@ void CodecOwner::SetEncoders(AudioEncoderMutable* external_speech_encoder,
|
|||||||
int red_payload_type) {
|
int red_payload_type) {
|
||||||
external_speech_encoder_ = external_speech_encoder;
|
external_speech_encoder_ = external_speech_encoder;
|
||||||
speech_encoder_.reset();
|
speech_encoder_.reset();
|
||||||
isac_is_encoder_ = false;
|
|
||||||
ChangeCngAndRed(cng_payload_type, vad_mode, red_payload_type);
|
ChangeCngAndRed(cng_payload_type, vad_mode, red_payload_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,24 +208,13 @@ void CodecOwner::ChangeCngAndRed(int cng_payload_type,
|
|||||||
AudioEncoder* encoder =
|
AudioEncoder* encoder =
|
||||||
CreateRedEncoder(red_payload_type, speech_encoder, &red_encoder_);
|
CreateRedEncoder(red_payload_type, speech_encoder, &red_encoder_);
|
||||||
CreateCngEncoder(cng_payload_type, vad_mode, encoder, &cng_encoder_);
|
CreateCngEncoder(cng_payload_type, vad_mode, encoder, &cng_encoder_);
|
||||||
int num_true =
|
DCHECK_EQ(!!speech_encoder_ + !!external_speech_encoder_, 1);
|
||||||
!!speech_encoder_ + !!external_speech_encoder_ + isac_is_encoder_;
|
|
||||||
DCHECK_EQ(num_true, 1);
|
|
||||||
DCHECK(!isac_is_encoder_ || isac_codec_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioDecoder* CodecOwner::GetIsacDecoder() {
|
AudioDecoder* CodecOwner::GetIsacDecoder() {
|
||||||
if (!isac_codec_) {
|
if (!isac_decoder_)
|
||||||
DCHECK(!isac_is_encoder_);
|
isac_decoder_ = CreateIsacDecoder(&isac_bandwidth_info_);
|
||||||
// None of the parameter values in |speech_inst| matter when the codec is
|
return isac_decoder_.get();
|
||||||
// used only as a decoder.
|
|
||||||
CodecInst speech_inst;
|
|
||||||
speech_inst.plfreq = 16000;
|
|
||||||
speech_inst.rate = -1;
|
|
||||||
speech_inst.pacsize = 480;
|
|
||||||
isac_codec_.reset(CreateIsacCodec(speech_inst));
|
|
||||||
}
|
|
||||||
return isac_codec_.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioEncoder* CodecOwner::Encoder() {
|
AudioEncoder* CodecOwner::Encoder() {
|
||||||
@ -243,15 +236,9 @@ AudioEncoderMutable* CodecOwner::SpeechEncoder() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const AudioEncoderMutable* CodecOwner::SpeechEncoder() const {
|
const AudioEncoderMutable* CodecOwner::SpeechEncoder() const {
|
||||||
int num_true =
|
DCHECK(!speech_encoder_ || !external_speech_encoder_);
|
||||||
!!speech_encoder_ + !!external_speech_encoder_ + isac_is_encoder_;
|
return external_speech_encoder_ ? external_speech_encoder_
|
||||||
DCHECK_GE(num_true, 0);
|
: speech_encoder_.get();
|
||||||
DCHECK_LE(num_true, 1);
|
|
||||||
if (external_speech_encoder_)
|
|
||||||
return external_speech_encoder_;
|
|
||||||
if (speech_encoder_)
|
|
||||||
return speech_encoder_.get();
|
|
||||||
return isac_is_encoder_ ? isac_codec_.get() : nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace acm2
|
} // namespace acm2
|
||||||
|
|||||||
@ -53,21 +53,17 @@ class CodecOwner {
|
|||||||
const AudioEncoderMutable* SpeechEncoder() const;
|
const AudioEncoderMutable* SpeechEncoder() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// There are three main cases for the state of the encoder members below:
|
// At most one of these is non-null:
|
||||||
// 1. An external encoder is used. |external_speech_encoder_| points to it.
|
|
||||||
// |speech_encoder_| is null, and |isac_is_encoder_| is false.
|
|
||||||
// 2. The internal iSAC codec is used as encoder. |isac_codec_| points to it
|
|
||||||
// and |isac_is_encoder_| is true. |external_speech_encoder_| and
|
|
||||||
// |speech_encoder_| are null.
|
|
||||||
// 3. Another internal encoder is used. |speech_encoder_| points to it.
|
|
||||||
// |external_speech_encoder_| is null, and |isac_is_encoder_| is false.
|
|
||||||
// In addition to case 2, |isac_codec_| is valid when GetIsacDecoder has been
|
|
||||||
// called.
|
|
||||||
rtc::scoped_ptr<AudioEncoderMutable> speech_encoder_;
|
rtc::scoped_ptr<AudioEncoderMutable> speech_encoder_;
|
||||||
rtc::scoped_ptr<AudioEncoderDecoderMutableIsac> isac_codec_;
|
|
||||||
bool isac_is_encoder_;
|
|
||||||
AudioEncoderMutable* external_speech_encoder_;
|
AudioEncoderMutable* external_speech_encoder_;
|
||||||
|
|
||||||
|
// If we've created an iSAC decoder because someone called GetIsacDecoder,
|
||||||
|
// store it here.
|
||||||
|
rtc::scoped_ptr<AudioDecoder> isac_decoder_;
|
||||||
|
|
||||||
|
// iSAC bandwidth estimation info, for use with iSAC encoders and decoders.
|
||||||
|
LockedIsacBandwidthInfo isac_bandwidth_info_;
|
||||||
|
|
||||||
// |cng_encoder_| and |red_encoder_| are valid iff CNG or RED, respectively,
|
// |cng_encoder_| and |red_encoder_| are valid iff CNG or RED, respectively,
|
||||||
// are active.
|
// are active.
|
||||||
rtc::scoped_ptr<AudioEncoder> cng_encoder_;
|
rtc::scoped_ptr<AudioEncoder> cng_encoder_;
|
||||||
|
|||||||
@ -559,22 +559,13 @@ AudioDecoder* CreateAudioDecoder(NetEqDecoder codec_type) {
|
|||||||
return new AudioDecoderIlbc;
|
return new AudioDecoderIlbc;
|
||||||
#endif
|
#endif
|
||||||
#if defined(WEBRTC_CODEC_ISACFX)
|
#if defined(WEBRTC_CODEC_ISACFX)
|
||||||
case kDecoderISAC: {
|
case kDecoderISAC:
|
||||||
AudioEncoderDecoderIsacFix::Config config;
|
return new AudioDecoderIsacFix();
|
||||||
return new AudioEncoderDecoderIsacFix(config);
|
|
||||||
}
|
|
||||||
#elif defined(WEBRTC_CODEC_ISAC)
|
#elif defined(WEBRTC_CODEC_ISAC)
|
||||||
case kDecoderISAC: {
|
case kDecoderISAC:
|
||||||
AudioEncoderDecoderIsac::Config config;
|
|
||||||
config.sample_rate_hz = 16000;
|
|
||||||
return new AudioEncoderDecoderIsac(config);
|
|
||||||
}
|
|
||||||
case kDecoderISACswb:
|
case kDecoderISACswb:
|
||||||
case kDecoderISACfb: {
|
case kDecoderISACfb:
|
||||||
AudioEncoderDecoderIsac::Config config;
|
return new AudioDecoderIsac();
|
||||||
config.sample_rate_hz = 32000;
|
|
||||||
return new AudioEncoderDecoderIsac(config);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef WEBRTC_CODEC_PCM16
|
#ifdef WEBRTC_CODEC_PCM16
|
||||||
case kDecoderPCM16B:
|
case kDecoderPCM16B:
|
||||||
|
|||||||
@ -358,17 +358,14 @@ class AudioDecoderIsacFloatTest : public AudioDecoderTest {
|
|||||||
codec_input_rate_hz_ = 16000;
|
codec_input_rate_hz_ = 16000;
|
||||||
frame_size_ = 480;
|
frame_size_ = 480;
|
||||||
data_length_ = 10 * frame_size_;
|
data_length_ = 10 * frame_size_;
|
||||||
AudioEncoderDecoderIsac::Config config;
|
AudioEncoderIsac::Config config;
|
||||||
config.payload_type = payload_type_;
|
config.payload_type = payload_type_;
|
||||||
config.sample_rate_hz = codec_input_rate_hz_;
|
config.sample_rate_hz = codec_input_rate_hz_;
|
||||||
config.adaptive_mode = false;
|
config.adaptive_mode = false;
|
||||||
config.frame_size_ms =
|
config.frame_size_ms =
|
||||||
1000 * static_cast<int>(frame_size_) / codec_input_rate_hz_;
|
1000 * static_cast<int>(frame_size_) / codec_input_rate_hz_;
|
||||||
|
audio_encoder_.reset(new AudioEncoderIsac(config));
|
||||||
// We need to create separate AudioEncoderDecoderIsac objects for encoding
|
decoder_ = new AudioDecoderIsac();
|
||||||
// and decoding, because the test class destructor destroys them both.
|
|
||||||
audio_encoder_.reset(new AudioEncoderDecoderIsac(config));
|
|
||||||
decoder_ = new AudioEncoderDecoderIsac(config);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -378,17 +375,14 @@ class AudioDecoderIsacSwbTest : public AudioDecoderTest {
|
|||||||
codec_input_rate_hz_ = 32000;
|
codec_input_rate_hz_ = 32000;
|
||||||
frame_size_ = 960;
|
frame_size_ = 960;
|
||||||
data_length_ = 10 * frame_size_;
|
data_length_ = 10 * frame_size_;
|
||||||
AudioEncoderDecoderIsac::Config config;
|
AudioEncoderIsac::Config config;
|
||||||
config.payload_type = payload_type_;
|
config.payload_type = payload_type_;
|
||||||
config.sample_rate_hz = codec_input_rate_hz_;
|
config.sample_rate_hz = codec_input_rate_hz_;
|
||||||
config.adaptive_mode = false;
|
config.adaptive_mode = false;
|
||||||
config.frame_size_ms =
|
config.frame_size_ms =
|
||||||
1000 * static_cast<int>(frame_size_) / codec_input_rate_hz_;
|
1000 * static_cast<int>(frame_size_) / codec_input_rate_hz_;
|
||||||
|
audio_encoder_.reset(new AudioEncoderIsac(config));
|
||||||
// We need to create separate AudioEncoderDecoderIsac objects for encoding
|
decoder_ = new AudioDecoderIsac();
|
||||||
// and decoding, because the test class destructor destroys them both.
|
|
||||||
audio_encoder_.reset(new AudioEncoderDecoderIsac(config));
|
|
||||||
decoder_ = new AudioEncoderDecoderIsac(config);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -398,18 +392,14 @@ class AudioDecoderIsacFixTest : public AudioDecoderTest {
|
|||||||
codec_input_rate_hz_ = 16000;
|
codec_input_rate_hz_ = 16000;
|
||||||
frame_size_ = 480;
|
frame_size_ = 480;
|
||||||
data_length_ = 10 * frame_size_;
|
data_length_ = 10 * frame_size_;
|
||||||
AudioEncoderDecoderIsacFix::Config config;
|
AudioEncoderIsacFix::Config config;
|
||||||
config.payload_type = payload_type_;
|
config.payload_type = payload_type_;
|
||||||
config.sample_rate_hz = codec_input_rate_hz_;
|
config.sample_rate_hz = codec_input_rate_hz_;
|
||||||
config.adaptive_mode = false;
|
config.adaptive_mode = false;
|
||||||
config.frame_size_ms =
|
config.frame_size_ms =
|
||||||
1000 * static_cast<int>(frame_size_) / codec_input_rate_hz_;
|
1000 * static_cast<int>(frame_size_) / codec_input_rate_hz_;
|
||||||
|
audio_encoder_.reset(new AudioEncoderIsacFix(config));
|
||||||
// We need to create separate AudioEncoderDecoderIsacFix objects for
|
decoder_ = new AudioDecoderIsacFix();
|
||||||
// encoding and decoding, because the test class destructor destroys them
|
|
||||||
// both.
|
|
||||||
audio_encoder_.reset(new AudioEncoderDecoderIsacFix(config));
|
|
||||||
decoder_ = new AudioEncoderDecoderIsacFix(config);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user