Fold AudioEncoderMutable into AudioEncoder
It makes more sense to combine the two interfaces, since there wasn't a clear line separating them. The result is a combined interface with just over a dozen methods, half of which need to be implemented by every subclass, while the other half have sensible (and trivial) default implementations and are implemented only by the few subclasses that need non-default behavior. Review URL: https://codereview.webrtc.org/1322973004 Cr-Commit-Position: refs/heads/master@{#9894}
This commit is contained in:
@ -19,6 +19,8 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
struct CodecInst;
|
||||
|
||||
template <typename T>
|
||||
class AudioEncoderIsacT final : public AudioEncoder {
|
||||
public:
|
||||
@ -28,33 +30,35 @@ class AudioEncoderIsacT final : public AudioEncoder {
|
||||
// - 32000 Hz, 30 ms, 10000-56000 bps (if T has super-wideband support)
|
||||
// - 48000 Hz, 30 ms, 10000-56000 bps (if T has super-wideband support)
|
||||
struct Config {
|
||||
Config();
|
||||
bool IsOk() const;
|
||||
|
||||
LockedIsacBandwidthInfo* bwinfo;
|
||||
LockedIsacBandwidthInfo* bwinfo = nullptr;
|
||||
|
||||
int payload_type;
|
||||
int sample_rate_hz;
|
||||
int frame_size_ms;
|
||||
int bit_rate; // Limit on the short-term average bit rate, in bits/s.
|
||||
int max_payload_size_bytes;
|
||||
int max_bit_rate;
|
||||
int payload_type = 103;
|
||||
int sample_rate_hz = 16000;
|
||||
int frame_size_ms = 30;
|
||||
int bit_rate = kDefaultBitRate; // Limit on the short-term average bit
|
||||
// rate, in bits/s.
|
||||
int max_payload_size_bytes = -1;
|
||||
int max_bit_rate = -1;
|
||||
|
||||
// If true, the encoder will dynamically adjust frame size and bit rate;
|
||||
// the configured values are then merely the starting point.
|
||||
bool adaptive_mode;
|
||||
bool adaptive_mode = false;
|
||||
|
||||
// In adaptive mode, prevent adaptive changes to the frame size. (Not used
|
||||
// in nonadaptive mode.)
|
||||
bool enforce_frame_size;
|
||||
bool enforce_frame_size = false;
|
||||
};
|
||||
|
||||
explicit AudioEncoderIsacT(const Config& config);
|
||||
explicit AudioEncoderIsacT(const CodecInst& codec_inst,
|
||||
LockedIsacBandwidthInfo* bwinfo);
|
||||
~AudioEncoderIsacT() override;
|
||||
|
||||
size_t MaxEncodedBytes() const override;
|
||||
int SampleRateHz() const override;
|
||||
int NumChannels() const override;
|
||||
size_t MaxEncodedBytes() const override;
|
||||
size_t Num10MsFramesInNextPacket() const override;
|
||||
size_t Max10MsFramesInAPacket() const override;
|
||||
int GetTargetBitrate() const override;
|
||||
@ -62,18 +66,26 @@ class AudioEncoderIsacT final : public AudioEncoder {
|
||||
const int16_t* audio,
|
||||
size_t max_encoded_bytes,
|
||||
uint8_t* encoded) override;
|
||||
void Reset() override;
|
||||
void SetMaxPayloadSize(int max_payload_size_bytes) override;
|
||||
void SetMaxBitrate(int max_rate_bps) 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_;
|
||||
static const int kDefaultBitRate = 32000;
|
||||
|
||||
// Recreate the iSAC encoder instance with the given settings, and save them.
|
||||
void RecreateEncoderInstance(const Config& config);
|
||||
|
||||
Config config_;
|
||||
typename T::instance_type* isac_state_ = nullptr;
|
||||
LockedIsacBandwidthInfo* bwinfo_ = nullptr;
|
||||
|
||||
// Have we accepted input but not yet emitted it in a packet?
|
||||
bool packet_in_progress_;
|
||||
bool packet_in_progress_ = false;
|
||||
|
||||
// Timestamp of the first input of the currently in-progress packet.
|
||||
uint32_t packet_timestamp_;
|
||||
@ -81,8 +93,6 @@ class AudioEncoderIsacT final : public AudioEncoder {
|
||||
// Timestamp of the previously encoded packet.
|
||||
uint32_t last_encoded_timestamp_;
|
||||
|
||||
const int target_bitrate_bps_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AudioEncoderIsacT);
|
||||
};
|
||||
|
||||
|
||||
@ -20,20 +20,20 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
const int kIsacPayloadType = 103;
|
||||
const int kDefaultBitRate = 32000;
|
||||
|
||||
template <typename T>
|
||||
AudioEncoderIsacT<T>::Config::Config()
|
||||
: bwinfo(nullptr),
|
||||
payload_type(kIsacPayloadType),
|
||||
sample_rate_hz(16000),
|
||||
frame_size_ms(30),
|
||||
bit_rate(kDefaultBitRate),
|
||||
max_payload_size_bytes(-1),
|
||||
max_bit_rate(-1),
|
||||
adaptive_mode(false),
|
||||
enforce_frame_size(false) {
|
||||
typename AudioEncoderIsacT<T>::Config CreateIsacConfig(
|
||||
const CodecInst& codec_inst,
|
||||
LockedIsacBandwidthInfo* bwinfo) {
|
||||
typename AudioEncoderIsacT<T>::Config config;
|
||||
config.bwinfo = bwinfo;
|
||||
config.payload_type = codec_inst.pltype;
|
||||
config.sample_rate_hz = codec_inst.plfreq;
|
||||
config.frame_size_ms =
|
||||
rtc::CheckedDivExact(1000 * codec_inst.pacsize, config.sample_rate_hz);
|
||||
config.adaptive_mode = (codec_inst.rate == -1);
|
||||
if (codec_inst.rate != -1)
|
||||
config.bit_rate = codec_inst.rate;
|
||||
return config;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -67,46 +67,25 @@ bool AudioEncoderIsacT<T>::Config::IsOk() const {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
AudioEncoderIsacT<T>::AudioEncoderIsacT(const Config& config)
|
||||
: payload_type_(config.payload_type),
|
||||
bwinfo_(config.bwinfo),
|
||||
packet_in_progress_(false),
|
||||
target_bitrate_bps_(config.adaptive_mode ? -1 : (config.bit_rate == 0
|
||||
? kDefaultBitRate
|
||||
: config.bit_rate)) {
|
||||
CHECK(config.IsOk());
|
||||
CHECK_EQ(0, T::Create(&isac_state_));
|
||||
CHECK_EQ(0, T::EncoderInit(isac_state_, config.adaptive_mode ? 0 : 1));
|
||||
CHECK_EQ(0, T::SetEncSampRate(isac_state_, config.sample_rate_hz));
|
||||
const int bit_rate = config.bit_rate == 0 ? kDefaultBitRate : config.bit_rate;
|
||||
if (config.adaptive_mode) {
|
||||
CHECK_EQ(0, T::ControlBwe(isac_state_, bit_rate, config.frame_size_ms,
|
||||
config.enforce_frame_size));
|
||||
} else {
|
||||
CHECK_EQ(0, T::Control(isac_state_, bit_rate, config.frame_size_ms));
|
||||
}
|
||||
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));
|
||||
|
||||
// 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));
|
||||
AudioEncoderIsacT<T>::AudioEncoderIsacT(const Config& config) {
|
||||
RecreateEncoderInstance(config);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
AudioEncoderIsacT<T>::AudioEncoderIsacT(const CodecInst& codec_inst,
|
||||
LockedIsacBandwidthInfo* bwinfo)
|
||||
: AudioEncoderIsacT(CreateIsacConfig<T>(codec_inst, bwinfo)) {}
|
||||
|
||||
template <typename T>
|
||||
AudioEncoderIsacT<T>::~AudioEncoderIsacT() {
|
||||
CHECK_EQ(0, T::Free(isac_state_));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t AudioEncoderIsacT<T>::MaxEncodedBytes() const {
|
||||
return kSufficientEncodeBufferSizeBytes;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int AudioEncoderIsacT<T>::SampleRateHz() const {
|
||||
return T::EncSampRate(isac_state_);
|
||||
@ -117,11 +96,6 @@ int AudioEncoderIsacT<T>::NumChannels() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t AudioEncoderIsacT<T>::MaxEncodedBytes() const {
|
||||
return kSufficientEncodeBufferSizeBytes;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t AudioEncoderIsacT<T>::Num10MsFramesInNextPacket() const {
|
||||
const int samples_in_next_packet = T::GetNewFrameLen(isac_state_);
|
||||
@ -137,7 +111,9 @@ size_t AudioEncoderIsacT<T>::Max10MsFramesInAPacket() const {
|
||||
|
||||
template <typename T>
|
||||
int AudioEncoderIsacT<T>::GetTargetBitrate() const {
|
||||
return target_bitrate_bps_;
|
||||
if (config_.adaptive_mode)
|
||||
return -1;
|
||||
return config_.bit_rate == 0 ? kDefaultBitRate : config_.bit_rate;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -172,15 +148,69 @@ AudioEncoder::EncodedInfo AudioEncoderIsacT<T>::EncodeInternal(
|
||||
EncodedInfo info;
|
||||
info.encoded_bytes = r;
|
||||
info.encoded_timestamp = packet_timestamp_;
|
||||
info.payload_type = payload_type_;
|
||||
info.payload_type = config_.payload_type;
|
||||
return info;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
AudioDecoderIsacT<T>::AudioDecoderIsacT()
|
||||
: AudioDecoderIsacT(nullptr) {
|
||||
void AudioEncoderIsacT<T>::Reset() {
|
||||
RecreateEncoderInstance(config_);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void AudioEncoderIsacT<T>::SetMaxPayloadSize(int max_payload_size_bytes) {
|
||||
auto conf = config_;
|
||||
conf.max_payload_size_bytes = max_payload_size_bytes;
|
||||
RecreateEncoderInstance(conf);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void AudioEncoderIsacT<T>::SetMaxBitrate(int max_rate_bps) {
|
||||
auto conf = config_;
|
||||
conf.max_bit_rate = max_rate_bps;
|
||||
RecreateEncoderInstance(conf);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void AudioEncoderIsacT<T>::RecreateEncoderInstance(const Config& config) {
|
||||
CHECK(config.IsOk());
|
||||
packet_in_progress_ = false;
|
||||
bwinfo_ = config.bwinfo;
|
||||
if (isac_state_)
|
||||
CHECK_EQ(0, T::Free(isac_state_));
|
||||
CHECK_EQ(0, T::Create(&isac_state_));
|
||||
CHECK_EQ(0, T::EncoderInit(isac_state_, config.adaptive_mode ? 0 : 1));
|
||||
CHECK_EQ(0, T::SetEncSampRate(isac_state_, config.sample_rate_hz));
|
||||
const int bit_rate = config.bit_rate == 0 ? kDefaultBitRate : config.bit_rate;
|
||||
if (config.adaptive_mode) {
|
||||
CHECK_EQ(0, T::ControlBwe(isac_state_, bit_rate, config.frame_size_ms,
|
||||
config.enforce_frame_size));
|
||||
} else {
|
||||
CHECK_EQ(0, T::Control(isac_state_, bit_rate, config.frame_size_ms));
|
||||
}
|
||||
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));
|
||||
|
||||
// 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));
|
||||
|
||||
config_ = config;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
AudioDecoderIsacT<T>::AudioDecoderIsacT()
|
||||
: AudioDecoderIsacT(nullptr) {}
|
||||
|
||||
template <typename T>
|
||||
AudioDecoderIsacT<T>::AudioDecoderIsacT(LockedIsacBandwidthInfo* bwinfo)
|
||||
: bwinfo_(bwinfo), decoder_sample_rate_hz_(-1) {
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h"
|
||||
#include "webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h"
|
||||
#include "webrtc/modules/audio_coding/codecs/isac/fix/interface/isacfix.h"
|
||||
|
||||
@ -123,16 +122,5 @@ struct IsacFix {
|
||||
using AudioEncoderIsacFix = AudioEncoderIsacT<IsacFix>;
|
||||
using AudioDecoderIsacFix = AudioDecoderIsacT<IsacFix>;
|
||||
|
||||
struct CodecInst;
|
||||
|
||||
class AudioEncoderMutableIsacFix
|
||||
: public AudioEncoderMutableImpl<AudioEncoderIsacFix> {
|
||||
public:
|
||||
explicit AudioEncoderMutableIsacFix(const CodecInst& codec_inst,
|
||||
LockedIsacBandwidthInfo* bwinfo);
|
||||
void SetMaxPayloadSize(int max_payload_size_bytes) override;
|
||||
void SetMaxRate(int max_rate_bps) override;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INTERFACE_AUDIO_ENCODER_ISACFIX_H_
|
||||
|
||||
@ -10,7 +10,6 @@
|
||||
|
||||
#include "webrtc/modules/audio_coding/codecs/isac/fix/interface/audio_encoder_isacfix.h"
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -21,38 +20,4 @@ const uint16_t IsacFix::kFixSampleRate;
|
||||
template class AudioEncoderIsacT<IsacFix>;
|
||||
template class AudioDecoderIsacT<IsacFix>;
|
||||
|
||||
namespace {
|
||||
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 =
|
||||
rtc::CheckedDivExact(1000 * codec_inst.pacsize, config.sample_rate_hz);
|
||||
if (codec_inst.rate != -1)
|
||||
config.bit_rate = codec_inst.rate;
|
||||
config.adaptive_mode = (codec_inst.rate == -1);
|
||||
return config;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
AudioEncoderMutableIsacFix::AudioEncoderMutableIsacFix(
|
||||
const CodecInst& codec_inst,
|
||||
LockedIsacBandwidthInfo* bwinfo)
|
||||
: AudioEncoderMutableImpl<AudioEncoderIsacFix>(
|
||||
CreateConfig(codec_inst, bwinfo)) {}
|
||||
|
||||
void AudioEncoderMutableIsacFix::SetMaxPayloadSize(int max_payload_size_bytes) {
|
||||
auto conf = config();
|
||||
conf.max_payload_size_bytes = max_payload_size_bytes;
|
||||
Reconstruct(conf);
|
||||
}
|
||||
|
||||
void AudioEncoderMutableIsacFix::SetMaxRate(int max_rate_bps) {
|
||||
auto conf = config();
|
||||
conf.max_bit_rate = max_rate_bps;
|
||||
Reconstruct(conf);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h"
|
||||
#include "webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h"
|
||||
#include "webrtc/modules/audio_coding/codecs/isac/main/interface/isac.h"
|
||||
|
||||
@ -121,16 +120,5 @@ struct IsacFloat {
|
||||
using AudioEncoderIsac = AudioEncoderIsacT<IsacFloat>;
|
||||
using AudioDecoderIsac = AudioDecoderIsacT<IsacFloat>;
|
||||
|
||||
struct CodecInst;
|
||||
|
||||
class AudioEncoderMutableIsacFloat
|
||||
: public AudioEncoderMutableImpl<AudioEncoderIsac> {
|
||||
public:
|
||||
AudioEncoderMutableIsacFloat(const CodecInst& codec_inst,
|
||||
LockedIsacBandwidthInfo* bwinfo);
|
||||
void SetMaxPayloadSize(int max_payload_size_bytes) override;
|
||||
void SetMaxRate(int max_rate_bps) override;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INTERFACE_AUDIO_ENCODER_ISAC_H_
|
||||
|
||||
@ -10,7 +10,6 @@
|
||||
|
||||
#include "webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h"
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -19,40 +18,4 @@ namespace webrtc {
|
||||
template class AudioEncoderIsacT<IsacFloat>;
|
||||
template class AudioDecoderIsacT<IsacFloat>;
|
||||
|
||||
namespace {
|
||||
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 =
|
||||
rtc::CheckedDivExact(1000 * codec_inst.pacsize, config.sample_rate_hz);
|
||||
if (codec_inst.rate != -1)
|
||||
config.bit_rate = codec_inst.rate;
|
||||
config.adaptive_mode = (codec_inst.rate == -1);
|
||||
return config;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
AudioEncoderMutableIsacFloat::AudioEncoderMutableIsacFloat(
|
||||
const CodecInst& codec_inst,
|
||||
LockedIsacBandwidthInfo* bwinfo)
|
||||
: AudioEncoderMutableImpl<AudioEncoderIsac>(
|
||||
CreateConfig(codec_inst, bwinfo)) {
|
||||
}
|
||||
|
||||
void AudioEncoderMutableIsacFloat::SetMaxPayloadSize(
|
||||
int max_payload_size_bytes) {
|
||||
auto conf = config();
|
||||
conf.max_payload_size_bytes = max_payload_size_bytes;
|
||||
Reconstruct(conf);
|
||||
}
|
||||
|
||||
void AudioEncoderMutableIsacFloat::SetMaxRate(int max_rate_bps) {
|
||||
auto conf = config();
|
||||
conf.max_bit_rate = max_rate_bps;
|
||||
Reconstruct(conf);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
Reference in New Issue
Block a user