From dcccab3ebb623df74fbb1425da2cb9d9a42439fa Mon Sep 17 00:00:00 2001 From: Karl Wiberg Date: Thu, 7 May 2015 12:35:12 +0200 Subject: 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} --- webrtc/modules/audio_coding/codecs/audio_encoder.h | 35 ++++++- .../codecs/audio_encoder_mutable_impl.h | 96 +++++++++++++++++ .../codecs/cng/include/audio_encoder_cng.h | 2 - .../audio_coding/codecs/g711/audio_encoder_pcm.cc | 26 +++++ .../codecs/g711/include/audio_encoder_pcm.h | 25 ++++- .../audio_coding/codecs/g722/audio_encoder_g722.cc | 22 +++- .../codecs/g722/include/audio_encoder_g722.h | 12 ++- .../audio_coding/codecs/ilbc/audio_encoder_ilbc.cc | 29 +++++- .../codecs/ilbc/interface/audio_encoder_ilbc.h | 12 ++- .../codecs/isac/audio_encoder_isac_t.h | 9 +- .../isac/fix/interface/audio_encoder_isacfix.h | 42 ++++++++ .../isac/fix/source/audio_encoder_isacfix.cc | 110 ++++++++++++++++++++ .../isac/main/interface/audio_encoder_isac.h | 42 ++++++++ .../codecs/isac/main/source/audio_encoder_isac.cc | 111 ++++++++++++++++++++ .../codecs/opus/audio_encoder_mutable_opus_test.cc | 114 +++++++++++++++++++++ .../audio_coding/codecs/opus/audio_encoder_opus.cc | 62 ++++++++++- .../codecs/opus/interface/audio_encoder_opus.h | 21 +++- .../codecs/pcm16b/audio_encoder_pcm16b.cc | 27 +++++ .../codecs/pcm16b/include/audio_encoder_pcm16b.h | 11 ++ .../codecs/red/audio_encoder_copy_red.h | 2 - webrtc/modules/modules.gyp | 1 + 21 files changed, 784 insertions(+), 27 deletions(-) create mode 100644 webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h create mode 100644 webrtc/modules/audio_coding/codecs/opus/audio_encoder_mutable_opus_test.cc diff --git a/webrtc/modules/audio_coding/codecs/audio_encoder.h b/webrtc/modules/audio_coding/codecs/audio_encoder.h index e8a2c6ea1e..b5cf827306 100644 --- a/webrtc/modules/audio_coding/codecs/audio_encoder.h +++ b/webrtc/modules/audio_coding/codecs/audio_encoder.h @@ -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_ diff --git a/webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h b/webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h new file mode 100644 index 0000000000..3de4046464 --- /dev/null +++ b/webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h @@ -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 +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 encoder_; + typename T::Config config_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_AUDIO_ENCODER_MUTABLE_IMPL_H_ diff --git a/webrtc/modules/audio_coding/codecs/cng/include/audio_encoder_cng.h b/webrtc/modules/audio_coding/codecs/cng/include/audio_encoder_cng.h index daecd51ff3..831758b8d3 100644 --- a/webrtc/modules/audio_coding/codecs/cng/include/audio_encoder_cng.h +++ b/webrtc/modules/audio_coding/codecs/cng/include/audio_encoder_cng.h @@ -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, diff --git a/webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc b/webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc index 5c45fa5178..0a3a6398fc 100644 --- a/webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc +++ b/webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc @@ -13,6 +13,7 @@ #include #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(input_len), encoded); } +namespace { +template +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( + CreateConfig(codec_inst)) { +} + +AudioEncoderMutablePcmA::AudioEncoderMutablePcmA(const CodecInst& codec_inst) + : AudioEncoderMutableImpl( + CreateConfig(codec_inst)) { +} + } // namespace webrtc diff --git a/webrtc/modules/audio_coding/codecs/g711/include/audio_encoder_pcm.h b/webrtc/modules/audio_coding/codecs/g711/include/audio_encoder_pcm.h index 6e588ecfcd..870b4ddfb6 100644 --- a/webrtc/modules/audio_coding/codecs/g711/include/audio_encoder_pcm.h +++ b/webrtc/modules/audio_coding/codecs/g711/include/audio_encoder_pcm.h @@ -13,7 +13,9 @@ #include +#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 { + public: + explicit AudioEncoderMutablePcmU(const CodecInst& codec_inst); +}; + +class AudioEncoderMutablePcmA + : public AudioEncoderMutableImpl { + public: + explicit AudioEncoderMutablePcmA(const CodecInst& codec_inst); +}; + } // namespace webrtc #endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_G711_INCLUDE_AUDIO_ENCODER_PCM_H_ diff --git a/webrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.cc b/webrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.cc index a9fa25f0ef..effb4058f4 100644 --- a/webrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.cc +++ b/webrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.cc @@ -12,6 +12,7 @@ #include #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(CreateConfig(codec_inst)) { +} + } // namespace webrtc diff --git a/webrtc/modules/audio_coding/codecs/g722/include/audio_encoder_g722.h b/webrtc/modules/audio_coding/codecs/g722/include/audio_encoder_g722.h index ba6e5dde67..f5e0a9899f 100644 --- a/webrtc/modules/audio_coding/codecs/g722/include/audio_encoder_g722.h +++ b/webrtc/modules/audio_coding/codecs/g722/include/audio_encoder_g722.h @@ -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 { + public: + explicit AudioEncoderMutableG722(const CodecInst& codec_inst); +}; + } // namespace webrtc #endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_G722_INCLUDE_AUDIO_ENCODER_G722_H_ diff --git a/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc b/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc index fad531f6bb..4fea44babd 100644 --- a/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc +++ b/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc @@ -13,6 +13,7 @@ #include #include #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(CreateConfig(codec_inst)) { +} + } // namespace webrtc diff --git a/webrtc/modules/audio_coding/codecs/ilbc/interface/audio_encoder_ilbc.h b/webrtc/modules/audio_coding/codecs/ilbc/interface/audio_encoder_ilbc.h index 91d17b4f85..c172db1b8f 100644 --- a/webrtc/modules/audio_coding/codecs/ilbc/interface/audio_encoder_ilbc.h +++ b/webrtc/modules/audio_coding/codecs/ilbc/interface/audio_encoder_ilbc.h @@ -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 { + public: + explicit AudioEncoderMutableIlbc(const CodecInst& codec_inst); +}; + } // namespace webrtc #endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_INTERFACE_AUDIO_ENCODER_ILBC_H_ diff --git a/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h b/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h index ad531667f5..b67a9b09fc 100644 --- a/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h +++ b/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h @@ -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_ diff --git a/webrtc/modules/audio_coding/codecs/isac/fix/interface/audio_encoder_isacfix.h b/webrtc/modules/audio_coding/codecs/isac/fix/interface/audio_encoder_isacfix.h index d12c1678b8..bf9f875d78 100644 --- a/webrtc/modules/audio_coding/codecs/isac/fix/interface/audio_encoder_isacfix.h +++ b/webrtc/modules/audio_coding/codecs/isac/fix/interface/audio_encoder_isacfix.h @@ -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 AudioEncoderDecoderIsacFix; +struct CodecInst; + +class AudioEncoderDecoderMutableIsacFix + : public AudioEncoderMutableImpl { + 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_ diff --git a/webrtc/modules/audio_coding/codecs/isac/fix/source/audio_encoder_isacfix.cc b/webrtc/modules/audio_coding/codecs/isac/fix/source/audio_encoder_isacfix.cc index d0aea26e44..4003b26e70 100644 --- a/webrtc/modules/audio_coding/codecs/isac/fix/source/audio_encoder_isacfix.cc +++ b/webrtc/modules/audio_coding/codecs/isac/fix/source/audio_encoder_isacfix.cc @@ -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; +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( + 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 diff --git a/webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h b/webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h index 7d8ac7951b..5a75807469 100644 --- a/webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h +++ b/webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h @@ -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 AudioEncoderDecoderIsac; +struct CodecInst; + +class AudioEncoderDecoderMutableIsacFloat + : public AudioEncoderMutableImpl { + 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_ diff --git a/webrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac.cc b/webrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac.cc index ba08603637..b2c1241e76 100644 --- a/webrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac.cc +++ b/webrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac.cc @@ -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; +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( + 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 diff --git a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_mutable_opus_test.cc b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_mutable_opus_test.cc new file mode 100644 index 0000000000..ddb5f1ea80 --- /dev/null +++ b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_mutable_opus_test.cc @@ -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 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 diff --git a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc index 941e635b17..a3a34bf340 100644 --- a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc +++ b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc @@ -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(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(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(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 diff --git a/webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h b/webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h index bd76b4900a..8d123a9537 100644 --- a/webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h +++ b/webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h @@ -13,6 +13,8 @@ #include +#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 { + 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_ diff --git a/webrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc b/webrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc index f761922201..491fdfdb14 100644 --- a/webrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc +++ b/webrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc @@ -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(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(CreateConfig(codec_inst)) { +} + } // namespace webrtc diff --git a/webrtc/modules/audio_coding/codecs/pcm16b/include/audio_encoder_pcm16b.h b/webrtc/modules/audio_coding/codecs/pcm16b/include/audio_encoder_pcm16b.h index 99ecd249c1..f1e1c51da8 100644 --- a/webrtc/modules/audio_coding/codecs/pcm16b/include/audio_encoder_pcm16b.h +++ b/webrtc/modules/audio_coding/codecs/pcm16b/include/audio_encoder_pcm16b.h @@ -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 { + public: + explicit AudioEncoderMutablePcm16B(const CodecInst& codec_inst); +}; + } // namespace webrtc #endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_PCM16B_INCLUDE_AUDIO_ENCODER_PCM16B_H_ diff --git a/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h b/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h index 99e5ee2a3e..49ab948fab 100644 --- a/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h +++ b/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h @@ -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, diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp index 5fbd501641..e97d8527dd 100644 --- a/webrtc/modules/modules.gyp +++ b/webrtc/modules/modules.gyp @@ -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', -- cgit v1.2.3