New interface: AudioEncoderMutable

With implementations for all codecs. It has no users yet. This new
interface is the same as AudioEncoder (in fact it is a subclass) but
it allows changing some parameters after construction.

COAUTHOR=henrik.lundin@webrtc.org
BUG=4228
R=jmarusic@webrtc.org, minyue@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/51679004

Cr-Commit-Position: refs/heads/master@{#9149}
This commit is contained in:
Karl Wiberg
2015-05-07 12:35:12 +02:00
parent 81ea54eaac
commit dcccab3ebb
21 changed files with 784 additions and 27 deletions

View File

@ -105,12 +105,45 @@ class AudioEncoder {
// coding efforts, such as FEC.
virtual void SetProjectedPacketLossRate(double fraction) {}
protected:
// This is the encode function that the inherited classes must implement. It
// is called from Encode in the base class.
virtual EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
const int16_t* audio,
size_t max_encoded_bytes,
uint8_t* encoded) = 0;
};
class AudioEncoderMutable : public AudioEncoder {
public:
enum Application { kApplicationSpeech, kApplicationAudio };
// Discards unprocessed audio data.
virtual void Reset() = 0;
// Enables codec-internal FEC, if the implementation supports it.
virtual bool SetFec(bool enable) = 0;
// Enables or disables codec-internal VAD/DTX, if the implementation supports
// it. Otherwise, false is returned. If |force| is true, other configurations
// may be changed to allow the operation.
virtual bool SetDtx(bool enable, bool force) = 0;
// Sets the application mode. The implementation is free to disregard this
// setting. If |force| is true, other configurations may be changed to allow
// the operation.
virtual bool SetApplication(Application application, bool force) = 0;
// Sets an upper limit on the payload size produced by the encoder. The
// implementation is free to disregard this setting.
virtual void SetMaxPayloadSize(int max_payload_size_bytes) = 0;
// Sets the maximum rate which the codec may not exceed for any packet.
virtual void SetMaxRate(int max_rate_bps) = 0;
// Informs the encoder about the maximum sample rate which the decoder will
// use when decoding the bitstream. The implementation is free to disregard
// this hint.
virtual bool SetMaxPlaybackRate(int frequency_hz) = 0;
};
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_AUDIO_ENCODER_H_

View File

@ -0,0 +1,96 @@
/*
* 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_AUDIO_ENCODER_MUTABLE_IMPL_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_AUDIO_ENCODER_MUTABLE_IMPL_H_
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
namespace webrtc {
// This is a convenient base class for implementations of AudioEncoderMutable.
// T is the type of the encoder state; it has to look like an AudioEncoder
// subclass whose constructor takes a single T::Config parameter. If P is
// given, this class will inherit from it instead of directly from
// AudioEncoderMutable.
template <typename T, typename P = AudioEncoderMutable>
class AudioEncoderMutableImpl : public P {
public:
void Reset() override { Reconstruct(config_); }
bool SetFec(bool enable) override { return false; }
bool SetDtx(bool enable, bool force) override { return false; }
bool SetApplication(AudioEncoderMutable::Application application,
bool force) override {
return false;
}
void SetMaxPayloadSize(int max_payload_size_bytes) override {}
void SetMaxRate(int max_rate_bps) override {}
bool SetMaxPlaybackRate(int frequency_hz) override { return false; }
AudioEncoderMutable::EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
const int16_t* audio,
size_t max_encoded_bytes,
uint8_t* encoded) override {
return encoder_->EncodeInternal(rtp_timestamp, audio, max_encoded_bytes,
encoded);
}
int SampleRateHz() const override { return encoder_->SampleRateHz(); }
int NumChannels() const override { return encoder_->NumChannels(); }
size_t MaxEncodedBytes() const override {
return encoder_->MaxEncodedBytes();
}
int RtpTimestampRateHz() const override {
return encoder_->RtpTimestampRateHz();
}
int Num10MsFramesInNextPacket() const override {
return encoder_->Num10MsFramesInNextPacket();
}
int Max10MsFramesInAPacket() const override {
return encoder_->Max10MsFramesInAPacket();
}
void SetTargetBitrate(int bits_per_second) override {
encoder_->SetTargetBitrate(bits_per_second);
}
void SetProjectedPacketLossRate(double fraction) override {
encoder_->SetProjectedPacketLossRate(fraction);
}
protected:
explicit AudioEncoderMutableImpl(const typename T::Config& config) {
Reconstruct(config);
}
bool Reconstruct(const typename T::Config& config) {
if (!config.IsOk())
return false;
config_ = config;
encoder_.reset(new T(config_));
return true;
}
const typename T::Config& config() const { return config_; }
T* encoder() { return encoder_.get(); }
const T* encoder() const { return encoder_.get(); }
private:
rtc::scoped_ptr<T> encoder_;
typename T::Config config_;
};
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_AUDIO_ENCODER_MUTABLE_IMPL_H_

View File

@ -54,8 +54,6 @@ class AudioEncoderCng final : public AudioEncoder {
int Max10MsFramesInAPacket() const override;
void SetTargetBitrate(int bits_per_second) override;
void SetProjectedPacketLossRate(double fraction) override;
protected:
EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
const int16_t* audio,
size_t max_encoded_bytes,

View File

@ -13,6 +13,7 @@
#include <limits>
#include "webrtc/base/checks.h"
#include "webrtc/common_types.h"
#include "webrtc/modules/audio_coding/codecs/g711/include/g711_interface.h"
namespace webrtc {
@ -28,6 +29,10 @@ int16_t NumSamplesPerFrame(int num_channels,
}
} // namespace
bool AudioEncoderPcm::Config::IsOk() const {
return (frame_size_ms % 10 == 0) && (num_channels >= 1);
}
AudioEncoderPcm::AudioEncoderPcm(const Config& config, int sample_rate_hz)
: sample_rate_hz_(sample_rate_hz),
num_channels_(config.num_channels),
@ -105,4 +110,25 @@ int16_t AudioEncoderPcmU::EncodeCall(const int16_t* audio,
return WebRtcG711_EncodeU(audio, static_cast<int16_t>(input_len), encoded);
}
namespace {
template <typename T>
typename T::Config CreateConfig(const CodecInst& codec_inst) {
typename T::Config config;
config.frame_size_ms = codec_inst.pacsize / 8;
config.num_channels = codec_inst.channels;
config.payload_type = codec_inst.pltype;
return config;
}
} // namespace
AudioEncoderMutablePcmU::AudioEncoderMutablePcmU(const CodecInst& codec_inst)
: AudioEncoderMutableImpl<AudioEncoderPcmU>(
CreateConfig<AudioEncoderPcmU>(codec_inst)) {
}
AudioEncoderMutablePcmA::AudioEncoderMutablePcmA(const CodecInst& codec_inst)
: AudioEncoderMutableImpl<AudioEncoderPcmA>(
CreateConfig<AudioEncoderPcmA>(codec_inst)) {
}
} // namespace webrtc

View File

@ -13,7 +13,9 @@
#include <vector>
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
#include "webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h"
namespace webrtc {
@ -21,6 +23,8 @@ class AudioEncoderPcm : public AudioEncoder {
public:
struct Config {
public:
bool IsOk() const;
int frame_size_ms;
int num_channels;
int payload_type;
@ -37,15 +41,14 @@ class AudioEncoderPcm : public AudioEncoder {
size_t MaxEncodedBytes() const override;
int Num10MsFramesInNextPacket() const override;
int Max10MsFramesInAPacket() const override;
protected:
AudioEncoderPcm(const Config& config, int sample_rate_hz);
EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
const int16_t* audio,
size_t max_encoded_bytes,
uint8_t* encoded) override;
protected:
AudioEncoderPcm(const Config& config, int sample_rate_hz);
virtual int16_t EncodeCall(const int16_t* audio,
size_t input_len,
uint8_t* encoded) = 0;
@ -96,5 +99,19 @@ class AudioEncoderPcmU : public AudioEncoderPcm {
static const int kSampleRateHz = 8000;
};
struct CodecInst;
class AudioEncoderMutablePcmU
: public AudioEncoderMutableImpl<AudioEncoderPcmU> {
public:
explicit AudioEncoderMutablePcmU(const CodecInst& codec_inst);
};
class AudioEncoderMutablePcmA
: public AudioEncoderMutableImpl<AudioEncoderPcmA> {
public:
explicit AudioEncoderMutablePcmA(const CodecInst& codec_inst);
};
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_G711_INCLUDE_AUDIO_ENCODER_PCM_H_

View File

@ -12,6 +12,7 @@
#include <limits>
#include "webrtc/base/checks.h"
#include "webrtc/common_types.h"
#include "webrtc/modules/audio_coding/codecs/g722/include/g722_interface.h"
namespace webrtc {
@ -22,6 +23,10 @@ const int kSampleRateHz = 16000;
} // namespace
bool AudioEncoderG722::Config::IsOk() const {
return (frame_size_ms % 10 == 0) && (num_channels >= 1);
}
AudioEncoderG722::EncoderState::EncoderState() {
CHECK_EQ(0, WebRtcG722_CreateEncoder(&encoder));
CHECK_EQ(0, WebRtcG722_EncoderInit(encoder));
@ -39,8 +44,7 @@ AudioEncoderG722::AudioEncoderG722(const Config& config)
first_timestamp_in_buffer_(0),
encoders_(new EncoderState[num_channels_]),
interleave_buffer_(2 * num_channels_) {
CHECK_EQ(config.frame_size_ms % 10, 0)
<< "Frame size must be an integer multiple of 10 ms.";
CHECK(config.IsOk());
const int samples_per_channel =
kSampleRateHz / 100 * num_10ms_frames_per_packet_;
for (int i = 0; i < num_channels_; ++i) {
@ -134,4 +138,18 @@ int AudioEncoderG722::SamplesPerChannel() const {
return kSampleRateHz / 100 * num_10ms_frames_per_packet_;
}
namespace {
AudioEncoderG722::Config CreateConfig(const CodecInst& codec_inst) {
AudioEncoderG722::Config config;
config.num_channels = codec_inst.channels;
config.frame_size_ms = codec_inst.pacsize / 16;
config.payload_type = codec_inst.pltype;
return config;
}
} // namespace
AudioEncoderMutableG722::AudioEncoderMutableG722(const CodecInst& codec_inst)
: AudioEncoderMutableImpl<AudioEncoderG722>(CreateConfig(codec_inst)) {
}
} // namespace webrtc

View File

@ -14,6 +14,7 @@
#include "webrtc/base/buffer.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
#include "webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h"
#include "webrtc/modules/audio_coding/codecs/g722/include/g722_interface.h"
namespace webrtc {
@ -22,6 +23,7 @@ class AudioEncoderG722 : public AudioEncoder {
public:
struct Config {
Config() : payload_type(9), frame_size_ms(20), num_channels(1) {}
bool IsOk() const;
int payload_type;
int frame_size_ms;
@ -37,8 +39,6 @@ class AudioEncoderG722 : public AudioEncoder {
int RtpTimestampRateHz() const override;
int Num10MsFramesInNextPacket() const override;
int Max10MsFramesInAPacket() const override;
protected:
EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
const int16_t* audio,
size_t max_encoded_bytes,
@ -65,5 +65,13 @@ class AudioEncoderG722 : public AudioEncoder {
rtc::Buffer interleave_buffer_;
};
struct CodecInst;
class AudioEncoderMutableG722
: public AudioEncoderMutableImpl<AudioEncoderG722> {
public:
explicit AudioEncoderMutableG722(const CodecInst& codec_inst);
};
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_G722_INCLUDE_AUDIO_ENCODER_G722_H_

View File

@ -13,6 +13,7 @@
#include <cstring>
#include <limits>
#include "webrtc/base/checks.h"
#include "webrtc/common_types.h"
#include "webrtc/modules/audio_coding/codecs/ilbc/interface/ilbc.h"
namespace webrtc {
@ -23,15 +24,20 @@ const int kSampleRateHz = 8000;
} // namespace
bool AudioEncoderIlbc::Config::IsOk() const {
if (!(frame_size_ms == 20 || frame_size_ms == 30 || frame_size_ms == 40 ||
frame_size_ms == 60))
return false;
if (kSampleRateHz / 100 * (frame_size_ms / 10) > kMaxSamplesPerPacket)
return false;
return true;
}
AudioEncoderIlbc::AudioEncoderIlbc(const Config& config)
: payload_type_(config.payload_type),
num_10ms_frames_per_packet_(config.frame_size_ms / 10),
num_10ms_frames_buffered_(0) {
CHECK(config.frame_size_ms == 20 || config.frame_size_ms == 30 ||
config.frame_size_ms == 40 || config.frame_size_ms == 60)
<< "Frame size must be 20, 30, 40, or 60 ms.";
DCHECK_LE(kSampleRateHz / 100 * num_10ms_frames_per_packet_,
kMaxSamplesPerPacket);
CHECK(config.IsOk());
CHECK_EQ(0, WebRtcIlbcfix_EncoderCreate(&encoder_));
const int encoder_frame_size_ms = config.frame_size_ms > 30
? config.frame_size_ms / 2
@ -112,4 +118,17 @@ size_t AudioEncoderIlbc::RequiredOutputSizeBytes() const {
}
}
namespace {
AudioEncoderIlbc::Config CreateConfig(const CodecInst& codec_inst) {
AudioEncoderIlbc::Config config;
config.frame_size_ms = codec_inst.pacsize / 8;
config.payload_type = codec_inst.pltype;
return config;
}
} // namespace
AudioEncoderMutableIlbc::AudioEncoderMutableIlbc(const CodecInst& codec_inst)
: AudioEncoderMutableImpl<AudioEncoderIlbc>(CreateConfig(codec_inst)) {
}
} // namespace webrtc

View File

@ -13,6 +13,7 @@
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
#include "webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h"
#include "webrtc/modules/audio_coding/codecs/ilbc/interface/ilbc.h"
namespace webrtc {
@ -21,6 +22,7 @@ class AudioEncoderIlbc : public AudioEncoder {
public:
struct Config {
Config() : payload_type(102), frame_size_ms(30) {}
bool IsOk() const;
int payload_type;
int frame_size_ms; // Valid values are 20, 30, 40, and 60 ms.
@ -36,8 +38,6 @@ class AudioEncoderIlbc : public AudioEncoder {
size_t MaxEncodedBytes() const override;
int Num10MsFramesInNextPacket() const override;
int Max10MsFramesInAPacket() const override;
protected:
EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
const int16_t* audio,
size_t max_encoded_bytes,
@ -55,5 +55,13 @@ class AudioEncoderIlbc : public AudioEncoder {
IlbcEncoderInstance* encoder_;
};
struct CodecInst;
class AudioEncoderMutableIlbc
: public AudioEncoderMutableImpl<AudioEncoderIlbc> {
public:
explicit AudioEncoderMutableIlbc(const CodecInst& codec_inst);
};
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_INTERFACE_AUDIO_ENCODER_ILBC_H_

View File

@ -72,7 +72,6 @@ class AudioEncoderDecoderIsacT : public AudioEncoder, public AudioDecoder {
int ErrorCode() override;
size_t Channels() const override { return 1; }
protected:
// AudioEncoder protected method.
EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
const int16_t* audio,
@ -117,5 +116,13 @@ class AudioEncoderDecoderIsacT : public AudioEncoder, public AudioDecoder {
DISALLOW_COPY_AND_ASSIGN(AudioEncoderDecoderIsacT);
};
struct CodecInst;
class AudioEncoderDecoderMutableIsac : public AudioEncoderMutable,
public AudioDecoder {
public:
virtual void UpdateSettings(const CodecInst& codec_inst) = 0;
};
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_H_

View File

@ -12,6 +12,8 @@
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INTERFACE_AUDIO_ENCODER_ISACFIX_H_
#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"
@ -104,5 +106,45 @@ struct IsacFix {
typedef AudioEncoderDecoderIsacT<IsacFix> AudioEncoderDecoderIsacFix;
struct CodecInst;
class AudioEncoderDecoderMutableIsacFix
: public AudioEncoderMutableImpl<AudioEncoderDecoderIsacFix,
AudioEncoderDecoderMutableIsac> {
public:
explicit AudioEncoderDecoderMutableIsacFix(const CodecInst& codec_inst);
void UpdateSettings(const CodecInst& codec_inst) override;
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
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INTERFACE_AUDIO_ENCODER_ISACFIX_H_

View File

@ -10,6 +10,7 @@
#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 {
@ -20,4 +21,113 @@ const uint16_t IsacFix::kFixSampleRate;
// AudioEncoderDecoderIsacFix.
template class AudioEncoderDecoderIsacT<IsacFix>;
namespace {
AudioEncoderDecoderIsacFix::Config CreateConfig(const CodecInst& codec_inst) {
AudioEncoderDecoderIsacFix::Config config;
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
AudioEncoderDecoderMutableIsacFix::AudioEncoderDecoderMutableIsacFix(
const CodecInst& codec_inst)
: AudioEncoderMutableImpl<AudioEncoderDecoderIsacFix,
AudioEncoderDecoderMutableIsac>(
CreateConfig(codec_inst)) {
}
void AudioEncoderDecoderMutableIsacFix::UpdateSettings(
const CodecInst& codec_inst) {
bool success = Reconstruct(CreateConfig(codec_inst));
DCHECK(success);
}
void AudioEncoderDecoderMutableIsacFix::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) {
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) {
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) {
return encoder()->DecodeRedundant(encoded, encoded_len, sample_rate_hz,
max_decoded_bytes, decoded, speech_type);
}
bool AudioEncoderDecoderMutableIsacFix::HasDecodePlc() const {
return encoder()->HasDecodePlc();
}
int AudioEncoderDecoderMutableIsacFix::DecodePlc(int num_frames,
int16_t* decoded) {
return encoder()->DecodePlc(num_frames, decoded);
}
int AudioEncoderDecoderMutableIsacFix::Init() {
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) {
return encoder()->IncomingPacket(payload, payload_len, rtp_sequence_number,
rtp_timestamp, arrival_timestamp);
}
int AudioEncoderDecoderMutableIsacFix::ErrorCode() {
return encoder()->ErrorCode();
}
int AudioEncoderDecoderMutableIsacFix::PacketDuration(
const uint8_t* encoded,
size_t encoded_len) const {
return encoder()->PacketDuration(encoded, encoded_len);
}
int AudioEncoderDecoderMutableIsacFix::PacketDurationRedundant(
const uint8_t* encoded,
size_t encoded_len) const {
return encoder()->PacketDurationRedundant(encoded, encoded_len);
}
bool AudioEncoderDecoderMutableIsacFix::PacketHasFec(const uint8_t* encoded,
size_t encoded_len) const {
return encoder()->PacketHasFec(encoded, encoded_len);
}
size_t AudioEncoderDecoderMutableIsacFix::Channels() const {
return encoder()->Channels();
}
} // namespace webrtc

View File

@ -12,6 +12,8 @@
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INTERFACE_AUDIO_ENCODER_ISAC_H_
#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"
@ -102,5 +104,45 @@ struct IsacFloat {
typedef AudioEncoderDecoderIsacT<IsacFloat> AudioEncoderDecoderIsac;
struct CodecInst;
class AudioEncoderDecoderMutableIsacFloat
: public AudioEncoderMutableImpl<AudioEncoderDecoderIsac,
AudioEncoderDecoderMutableIsac> {
public:
explicit AudioEncoderDecoderMutableIsacFloat(const CodecInst& codec_inst);
void UpdateSettings(const CodecInst& codec_inst) override;
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
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INTERFACE_AUDIO_ENCODER_ISAC_H_

View File

@ -10,6 +10,7 @@
#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 {
@ -18,4 +19,114 @@ namespace webrtc {
// AudioEncoderDecoderIsac.
template class AudioEncoderDecoderIsacT<IsacFloat>;
namespace {
AudioEncoderDecoderIsac::Config CreateConfig(const CodecInst& codec_inst) {
AudioEncoderDecoderIsac::Config config;
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
AudioEncoderDecoderMutableIsacFloat::AudioEncoderDecoderMutableIsacFloat(
const CodecInst& codec_inst)
: AudioEncoderMutableImpl<AudioEncoderDecoderIsac,
AudioEncoderDecoderMutableIsac>(
CreateConfig(codec_inst)) {
}
void AudioEncoderDecoderMutableIsacFloat::UpdateSettings(
const CodecInst& codec_inst) {
bool success = Reconstruct(CreateConfig(codec_inst));
DCHECK(success);
}
void AudioEncoderDecoderMutableIsacFloat::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) {
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) {
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) {
return encoder()->DecodeRedundant(encoded, encoded_len, sample_rate_hz,
max_decoded_bytes, decoded, speech_type);
}
bool AudioEncoderDecoderMutableIsacFloat::HasDecodePlc() const {
return encoder()->HasDecodePlc();
}
int AudioEncoderDecoderMutableIsacFloat::DecodePlc(int num_frames,
int16_t* decoded) {
return encoder()->DecodePlc(num_frames, decoded);
}
int AudioEncoderDecoderMutableIsacFloat::Init() {
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) {
return encoder()->IncomingPacket(payload, payload_len, rtp_sequence_number,
rtp_timestamp, arrival_timestamp);
}
int AudioEncoderDecoderMutableIsacFloat::ErrorCode() {
return encoder()->ErrorCode();
}
int AudioEncoderDecoderMutableIsacFloat::PacketDuration(
const uint8_t* encoded,
size_t encoded_len) const {
return encoder()->PacketDuration(encoded, encoded_len);
}
int AudioEncoderDecoderMutableIsacFloat::PacketDurationRedundant(
const uint8_t* encoded,
size_t encoded_len) const {
return encoder()->PacketDurationRedundant(encoded, encoded_len);
}
bool AudioEncoderDecoderMutableIsacFloat::PacketHasFec(
const uint8_t* encoded,
size_t encoded_len) const {
return encoder()->PacketHasFec(encoded, encoded_len);
}
size_t AudioEncoderDecoderMutableIsacFloat::Channels() const {
return encoder()->Channels();
}
} // namespace webrtc

View File

@ -0,0 +1,114 @@
/*
* 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 "testing/gtest/include/gtest/gtest.h"
#include "webrtc/common_types.h"
#include "webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h"
namespace webrtc {
namespace acm2 {
#ifdef WEBRTC_CODEC_OPUS
namespace {
const CodecInst kDefaultOpusCodecInst = {105, "opus", 48000, 960, 1, 32000};
} // namespace
class AudioEncoderMutableOpusTest : public ::testing::Test {
protected:
AudioEncoderMutableOpusTest() : codec_inst_(kDefaultOpusCodecInst) {}
void CreateCodec(int num_channels) {
codec_inst_.channels = num_channels;
encoder_.reset(new AudioEncoderMutableOpus(codec_inst_));
auto expected_app =
num_channels == 1 ? AudioEncoderOpus::kVoip : AudioEncoderOpus::kAudio;
EXPECT_EQ(expected_app, encoder_->application());
}
CodecInst codec_inst_;
rtc::scoped_ptr<AudioEncoderMutableOpus> encoder_;
};
TEST_F(AudioEncoderMutableOpusTest, DefaultApplicationModeMono) {
CreateCodec(1);
}
TEST_F(AudioEncoderMutableOpusTest, DefaultApplicationModeStereo) {
CreateCodec(2);
}
TEST_F(AudioEncoderMutableOpusTest, ChangeApplicationMode) {
CreateCodec(2);
EXPECT_TRUE(
encoder_->SetApplication(AudioEncoderMutable::kApplicationSpeech, false));
EXPECT_EQ(AudioEncoderOpus::kVoip, encoder_->application());
}
TEST_F(AudioEncoderMutableOpusTest, ResetWontChangeApplicationMode) {
CreateCodec(2);
// Trigger a reset.
encoder_->Reset();
// Verify that the mode is still kAudio.
EXPECT_EQ(AudioEncoderOpus::kAudio, encoder_->application());
// Now change to kVoip.
EXPECT_TRUE(
encoder_->SetApplication(AudioEncoderMutable::kApplicationSpeech, false));
EXPECT_EQ(AudioEncoderOpus::kVoip, encoder_->application());
// Trigger a reset again.
encoder_->Reset();
// Verify that the mode is still kVoip.
EXPECT_EQ(AudioEncoderOpus::kVoip, encoder_->application());
}
TEST_F(AudioEncoderMutableOpusTest, ToggleDtx) {
CreateCodec(2);
// DTX is not allowed in audio mode, if mode forcing flag is false.
EXPECT_FALSE(encoder_->SetDtx(true, false));
EXPECT_EQ(AudioEncoderOpus::kAudio, encoder_->application());
// DTX will be on, if mode forcing flag is true. Then application mode is
// switched to kVoip.
EXPECT_TRUE(encoder_->SetDtx(true, true));
EXPECT_EQ(AudioEncoderOpus::kVoip, encoder_->application());
// Audio mode is not allowed when DTX is on, and DTX forcing flag is false.
EXPECT_FALSE(
encoder_->SetApplication(AudioEncoderMutable::kApplicationAudio, false));
EXPECT_TRUE(encoder_->dtx_enabled());
// Audio mode will be set, if DTX forcing flag is true. Then DTX is switched
// off.
EXPECT_TRUE(
encoder_->SetApplication(AudioEncoderMutable::kApplicationAudio, true));
EXPECT_FALSE(encoder_->dtx_enabled());
// Now we set VOIP mode. The DTX forcing flag has no effect.
EXPECT_TRUE(
encoder_->SetApplication(AudioEncoderMutable::kApplicationSpeech, true));
EXPECT_FALSE(encoder_->dtx_enabled());
// In VOIP mode, we can enable DTX with mode forcing flag being false.
EXPECT_TRUE(encoder_->SetDtx(true, false));
// Turn off DTX.
EXPECT_TRUE(encoder_->SetDtx(false, false));
// When DTX is off, we can set Audio mode with DTX forcing flag being false.
EXPECT_TRUE(
encoder_->SetApplication(AudioEncoderMutable::kApplicationAudio, false));
}
#endif // WEBRTC_CODEC_OPUS
} // namespace acm2
} // namespace webrtc

View File

@ -11,6 +11,7 @@
#include "webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h"
#include "webrtc/base/checks.h"
#include "webrtc/common_types.h"
#include "webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h"
namespace webrtc {
@ -199,20 +200,73 @@ AudioEncoder::EncodedInfo AudioEncoderOpus::EncodeInternal(
CHECK_EQ(input_buffer_.size(),
static_cast<size_t>(num_10ms_frames_per_packet_) *
samples_per_10ms_frame_);
int16_t r = WebRtcOpus_Encode(
int16_t status = WebRtcOpus_Encode(
inst_, &input_buffer_[0],
rtc::CheckedDivExact(CastInt16(input_buffer_.size()),
static_cast<int16_t>(num_channels_)),
ClampInt16(max_encoded_bytes), encoded);
CHECK_GE(r, 0); // Fails only if fed invalid data.
CHECK_GE(status, 0); // Fails only if fed invalid data.
input_buffer_.clear();
EncodedInfo info;
info.encoded_bytes = r;
info.encoded_bytes = status;
info.encoded_timestamp = first_timestamp_in_buffer_;
info.payload_type = payload_type_;
info.send_even_if_empty = true; // Allows Opus to send empty packets.
info.speech = r > 0;
info.speech = (status > 0);
return info;
}
namespace {
AudioEncoderOpus::Config CreateConfig(const CodecInst& codec_inst) {
AudioEncoderOpus::Config config;
config.frame_size_ms = rtc::CheckedDivExact(codec_inst.pacsize, 48);
config.num_channels = codec_inst.channels;
config.bitrate_bps = codec_inst.rate;
config.payload_type = codec_inst.pltype;
config.application = (config.num_channels == 1 ? AudioEncoderOpus::kVoip
: AudioEncoderOpus::kAudio);
return config;
}
} // namespace
AudioEncoderMutableOpus::AudioEncoderMutableOpus(const CodecInst& codec_inst)
: AudioEncoderMutableImpl<AudioEncoderOpus>(CreateConfig(codec_inst)) {
}
bool AudioEncoderMutableOpus::SetFec(bool enable) {
auto conf = config();
conf.fec_enabled = enable;
return Reconstruct(conf);
}
bool AudioEncoderMutableOpus::SetDtx(bool enable, bool force) {
auto conf = config();
if (enable && force)
conf.application = AudioEncoderOpus::kVoip;
conf.dtx_enabled = enable;
return Reconstruct(conf);
}
bool AudioEncoderMutableOpus::SetApplication(Application application,
bool force) {
auto conf = config();
switch (application) {
case kApplicationSpeech:
conf.application = AudioEncoderOpus::kVoip;
break;
case kApplicationAudio:
if (force)
conf.dtx_enabled = false;
conf.application = AudioEncoderOpus::kAudio;
break;
}
return Reconstruct(conf);
}
bool AudioEncoderMutableOpus::SetMaxPlaybackRate(int frequency_hz) {
auto conf = config();
conf.max_playback_rate_hz = frequency_hz;
return Reconstruct(conf);
}
} // namespace webrtc

View File

@ -13,6 +13,8 @@
#include <vector>
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h"
#include "webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h"
#include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
@ -56,8 +58,6 @@ class AudioEncoderOpus final : public AudioEncoder {
double packet_loss_rate() const { return packet_loss_rate_; }
ApplicationMode application() const { return application_; }
bool dtx_enabled() const { return dtx_enabled_; }
protected:
EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
const int16_t* audio,
size_t max_encoded_bytes,
@ -77,5 +77,22 @@ class AudioEncoderOpus final : public AudioEncoder {
double packet_loss_rate_;
};
struct CodecInst;
class AudioEncoderMutableOpus
: public AudioEncoderMutableImpl<AudioEncoderOpus> {
public:
explicit AudioEncoderMutableOpus(const CodecInst& codec_inst);
bool SetFec(bool enable) override;
bool SetDtx(bool enable, bool force) override;
bool SetApplication(Application application, bool force) override;
bool SetMaxPlaybackRate(int frequency_hz) override;
AudioEncoderOpus::ApplicationMode application() const {
return encoder()->application();
}
double packet_loss_rate() const { return encoder()->packet_loss_rate(); }
bool dtx_enabled() const { return encoder()->dtx_enabled(); }
};
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_OPUS_INTERFACE_AUDIO_ENCODER_OPUS_H_

View File

@ -9,14 +9,41 @@
*/
#include "webrtc/modules/audio_coding/codecs/pcm16b/include/audio_encoder_pcm16b.h"
#include "webrtc/base/checks.h"
#include "webrtc/common_types.h"
#include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h"
namespace webrtc {
bool AudioEncoderPcm16B::Config::IsOk() const {
if ((sample_rate_hz != 8000) && (sample_rate_hz != 16000) &&
(sample_rate_hz != 32000) && (sample_rate_hz != 48000))
return false;
return AudioEncoderPcm::Config::IsOk();
}
int16_t AudioEncoderPcm16B::EncodeCall(const int16_t* audio,
size_t input_len,
uint8_t* encoded) {
return WebRtcPcm16b_Encode(audio, static_cast<int16_t>(input_len), encoded);
}
namespace {
AudioEncoderPcm16B::Config CreateConfig(const CodecInst& codec_inst) {
AudioEncoderPcm16B::Config config;
config.num_channels = codec_inst.channels;
config.sample_rate_hz = codec_inst.plfreq;
config.frame_size_ms = rtc::CheckedDivExact(
codec_inst.pacsize, rtc::CheckedDivExact(config.sample_rate_hz, 1000));
config.payload_type = codec_inst.pltype;
return config;
}
} // namespace
AudioEncoderMutablePcm16B::AudioEncoderMutablePcm16B(
const CodecInst& codec_inst)
: AudioEncoderMutableImpl<AudioEncoderPcm16B>(CreateConfig(codec_inst)) {
}
} // namespace webrtc

View File

@ -11,6 +11,8 @@
#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_PCM16B_INCLUDE_AUDIO_ENCODER_PCM16B_H_
#define WEBRTC_MODULES_AUDIO_CODING_CODECS_PCM16B_INCLUDE_AUDIO_ENCODER_PCM16B_H_
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h"
#include "webrtc/modules/audio_coding/codecs/g711/include/audio_encoder_pcm.h"
namespace webrtc {
@ -20,6 +22,7 @@ class AudioEncoderPcm16B : public AudioEncoderPcm {
struct Config : public AudioEncoderPcm::Config {
public:
Config() : AudioEncoderPcm::Config(107), sample_rate_hz(8000) {}
bool IsOk() const;
int sample_rate_hz;
};
@ -33,5 +36,13 @@ class AudioEncoderPcm16B : public AudioEncoderPcm {
uint8_t* encoded) override;
};
struct CodecInst;
class AudioEncoderMutablePcm16B
: public AudioEncoderMutableImpl<AudioEncoderPcm16B> {
public:
explicit AudioEncoderMutablePcm16B(const CodecInst& codec_inst);
};
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_PCM16B_INCLUDE_AUDIO_ENCODER_PCM16B_H_

View File

@ -44,8 +44,6 @@ class AudioEncoderCopyRed : public AudioEncoder {
int Max10MsFramesInAPacket() const override;
void SetTargetBitrate(int bits_per_second) override;
void SetProjectedPacketLossRate(double fraction) override;
protected:
EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
const int16_t* audio,
size_t max_encoded_bytes,

View File

@ -96,6 +96,7 @@
'audio_coding/codecs/cng/audio_encoder_cng_unittest.cc',
'audio_coding/main/acm2/acm_generic_codec_test.cc',
'audio_coding/main/acm2/acm_generic_codec_opus_test.cc',
'audio_coding/codecs/opus/audio_encoder_mutable_opus_test.cc',
'audio_coding/main/acm2/acm_receiver_unittest.cc',
'audio_coding/main/acm2/acm_receiver_unittest_oldapi.cc',
'audio_coding/main/acm2/audio_coding_module_unittest.cc',