aboutsummaryrefslogtreecommitdiff
path: root/webrtc
diff options
context:
space:
mode:
Diffstat (limited to 'webrtc')
-rw-r--r--webrtc/modules/audio_coding/codecs/audio_encoder.h8
-rw-r--r--webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.cc44
-rw-r--r--webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc12
-rw-r--r--webrtc/modules/audio_coding/codecs/cng/include/audio_encoder_cng.h7
-rw-r--r--webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc11
-rw-r--r--webrtc/modules/audio_coding/codecs/g711/include/audio_encoder_pcm.h3
-rw-r--r--webrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.cc18
-rw-r--r--webrtc/modules/audio_coding/codecs/g722/include/audio_encoder_g722.h5
-rw-r--r--webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc38
-rw-r--r--webrtc/modules/audio_coding/codecs/ilbc/interface/audio_encoder_ilbc.h3
-rw-r--r--webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h1
-rw-r--r--webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h5
-rw-r--r--webrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac_red_unittest.cc16
-rw-r--r--webrtc/modules/audio_coding/codecs/mock/mock_audio_encoder.h1
-rw-r--r--webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc17
-rw-r--r--webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h3
-rw-r--r--webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc4
-rw-r--r--webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h3
-rw-r--r--webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red_unittest.cc12
19 files changed, 151 insertions, 60 deletions
diff --git a/webrtc/modules/audio_coding/codecs/audio_encoder.h b/webrtc/modules/audio_coding/codecs/audio_encoder.h
index c0ec2109c3..20ac8b922b 100644
--- a/webrtc/modules/audio_coding/codecs/audio_encoder.h
+++ b/webrtc/modules/audio_coding/codecs/audio_encoder.h
@@ -74,6 +74,14 @@ class AudioEncoder {
virtual int SampleRateHz() const = 0;
virtual int NumChannels() const = 0;
+ // Return the maximum number of bytes that can be produced by the encoder
+ // at each Encode() call. The caller can use the return value to determine
+ // the size of the buffer that needs to be allocated. This value is allowed
+ // to depend on encoder parameters like bitrate, frame size etc., so if
+ // any of these change, the caller of Encode() is responsible for checking
+ // that the buffer is large enough by calling MaxEncodedBytes() again.
+ virtual size_t MaxEncodedBytes() const = 0;
+
// Returns the rate with which the RTP timestamps are updated. By default,
// this is the same as sample_rate_hz().
virtual int RtpTimestampRateHz() const;
diff --git a/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.cc b/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.cc
index 14b210c3ec..d7c1ea013a 100644
--- a/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.cc
+++ b/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.cc
@@ -10,10 +10,17 @@
#include "webrtc/modules/audio_coding/codecs/cng/include/audio_encoder_cng.h"
+#include <algorithm>
#include <limits>
namespace webrtc {
+namespace {
+
+const int kMaxFrameSizeMs = 60;
+
+} // namespace
+
AudioEncoderCng::Config::Config()
: num_channels(1),
payload_type(13),
@@ -77,6 +84,13 @@ int AudioEncoderCng::NumChannels() const {
return 1;
}
+size_t AudioEncoderCng::MaxEncodedBytes() const {
+ const size_t max_encoded_bytes_active = speech_encoder_->MaxEncodedBytes();
+ const size_t max_encoded_bytes_passive =
+ rtc::CheckedDivExact(kMaxFrameSizeMs, 10) * SamplesPer10msFrame();
+ return std::max(max_encoded_bytes_active, max_encoded_bytes_passive);
+}
+
int AudioEncoderCng::Num10MsFramesInNextPacket() const {
return speech_encoder_->Num10MsFramesInNextPacket();
}
@@ -114,8 +128,9 @@ void AudioEncoderCng::EncodeInternal(uint32_t rtp_timestamp,
if (frames_in_buffer_ < speech_encoder_->Num10MsFramesInNextPacket()) {
return;
}
- CHECK_LE(frames_in_buffer_, 6)
- << "Frame size cannot be larger than 60 ms when using VAD/CNG.";
+ CHECK_LE(frames_in_buffer_ * 10, kMaxFrameSizeMs)
+ << "Frame size cannot be larger than " << kMaxFrameSizeMs
+ << " ms when using VAD/CNG.";
const size_t samples_per_10ms_frame = 10 * SampleRateHz() / 1000;
CHECK_EQ(speech_buffer_.size(),
static_cast<size_t>(frames_in_buffer_) * samples_per_10ms_frame);
@@ -146,11 +161,7 @@ void AudioEncoderCng::EncodeInternal(uint32_t rtp_timestamp,
switch (activity) {
case Vad::kPassive: {
- EncodePassive(encoded, &info->encoded_bytes);
- info->encoded_timestamp = first_timestamp_in_buffer_;
- info->payload_type = cng_payload_type_;
- info->send_even_if_empty = true;
- info->speech = false;
+ EncodePassive(max_encoded_bytes, encoded, info);
last_frame_active_ = false;
break;
}
@@ -169,10 +180,13 @@ void AudioEncoderCng::EncodeInternal(uint32_t rtp_timestamp,
frames_in_buffer_ = 0;
}
-void AudioEncoderCng::EncodePassive(uint8_t* encoded, size_t* encoded_bytes) {
+void AudioEncoderCng::EncodePassive(size_t max_encoded_bytes,
+ uint8_t* encoded,
+ EncodedInfo* info) {
bool force_sid = last_frame_active_;
bool output_produced = false;
- const size_t samples_per_10ms_frame = 10 * SampleRateHz() / 1000;
+ const size_t samples_per_10ms_frame = SamplesPer10msFrame();
+ CHECK_GE(max_encoded_bytes, frames_in_buffer_ * samples_per_10ms_frame);
for (int i = 0; i < frames_in_buffer_; ++i) {
int16_t encoded_bytes_tmp = 0;
CHECK_GE(WebRtcCng_Encode(cng_inst_.get(),
@@ -181,17 +195,21 @@ void AudioEncoderCng::EncodePassive(uint8_t* encoded, size_t* encoded_bytes) {
encoded, &encoded_bytes_tmp, force_sid), 0);
if (encoded_bytes_tmp > 0) {
CHECK(!output_produced);
- *encoded_bytes = static_cast<size_t>(encoded_bytes_tmp);
+ info->encoded_bytes = static_cast<size_t>(encoded_bytes_tmp);
output_produced = true;
force_sid = false;
}
}
+ info->encoded_timestamp = first_timestamp_in_buffer_;
+ info->payload_type = cng_payload_type_;
+ info->send_even_if_empty = true;
+ info->speech = false;
}
void AudioEncoderCng::EncodeActive(size_t max_encoded_bytes,
uint8_t* encoded,
EncodedInfo* info) {
- const size_t samples_per_10ms_frame = 10 * SampleRateHz() / 1000;
+ const size_t samples_per_10ms_frame = SamplesPer10msFrame();
for (int i = 0; i < frames_in_buffer_; ++i) {
speech_encoder_->Encode(first_timestamp_in_buffer_,
&speech_buffer_[i * samples_per_10ms_frame],
@@ -203,4 +221,8 @@ void AudioEncoderCng::EncodeActive(size_t max_encoded_bytes,
}
}
+size_t AudioEncoderCng::SamplesPer10msFrame() const {
+ return rtc::CheckedDivExact(10 * SampleRateHz(), 1000);
+}
+
} // namespace webrtc
diff --git a/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc b/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc
index c5d436eb8f..5dfa4d545e 100644
--- a/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc
+++ b/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc
@@ -8,6 +8,8 @@
* be found in the AUTHORS file in the root of the source tree.
*/
+#include <vector>
+
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/common_audio/vad/mock/mock_vad.h"
@@ -23,7 +25,7 @@ using ::testing::Invoke;
namespace webrtc {
namespace {
-static const size_t kMaxEncodedBytes = 1000;
+static const size_t kMockMaxEncodedBytes = 1000;
static const size_t kMaxNumSamples = 48 * 10 * 2; // 10 ms @ 48 kHz stereo.
static const size_t kMockReturnEncodedBytes = 17;
static const int kCngPayloadType = 18;
@@ -36,7 +38,6 @@ class AudioEncoderCngTest : public ::testing::Test {
timestamp_(4711),
num_audio_samples_10ms_(0),
sample_rate_hz_(8000) {
- memset(encoded_, 0, kMaxEncodedBytes);
memset(audio_, 0, kMaxNumSamples * 2);
config_.speech_encoder = &mock_encoder_;
EXPECT_CALL(mock_encoder_, NumChannels()).WillRepeatedly(Return(1));
@@ -66,14 +67,17 @@ class AudioEncoderCngTest : public ::testing::Test {
// is not too small. The return value does not matter that much, as long as
// it is smaller than 10.
EXPECT_CALL(mock_encoder_, Max10MsFramesInAPacket()).WillOnce(Return(1));
+ EXPECT_CALL(mock_encoder_, MaxEncodedBytes())
+ .WillRepeatedly(Return(kMockMaxEncodedBytes));
cng_.reset(new AudioEncoderCng(config_));
+ encoded_.resize(cng_->MaxEncodedBytes(), 0);
}
void Encode() {
ASSERT_TRUE(cng_) << "Must call CreateCng() first.";
encoded_info_ = AudioEncoder::EncodedInfo();
cng_->Encode(timestamp_, audio_, num_audio_samples_10ms_,
- kMaxEncodedBytes, encoded_, &encoded_info_);
+ encoded_.size(), &encoded_[0], &encoded_info_);
timestamp_ += num_audio_samples_10ms_;
}
@@ -182,7 +186,7 @@ class AudioEncoderCngTest : public ::testing::Test {
uint32_t timestamp_;
int16_t audio_[kMaxNumSamples];
size_t num_audio_samples_10ms_;
- uint8_t encoded_[kMaxEncodedBytes];
+ std::vector<uint8_t> encoded_;
AudioEncoder::EncodedInfo encoded_info_;
int sample_rate_hz_;
};
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 1d3c2f3faa..cc0165054b 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
@@ -48,6 +48,7 @@ class AudioEncoderCng final : public AudioEncoder {
int SampleRateHz() const override;
int NumChannels() const override;
+ size_t MaxEncodedBytes() const override;
int RtpTimestampRateHz() const override;
int Num10MsFramesInNextPacket() const override;
int Max10MsFramesInAPacket() const override;
@@ -68,11 +69,13 @@ class AudioEncoderCng final : public AudioEncoder {
inline void operator()(CNG_enc_inst* ptr) const { WebRtcCng_FreeEnc(ptr); }
};
- void EncodePassive(uint8_t* encoded, size_t* encoded_bytes);
-
+ void EncodePassive(size_t max_encoded_bytes,
+ uint8_t* encoded,
+ EncodedInfo* info);
void EncodeActive(size_t max_encoded_bytes,
uint8_t* encoded,
EncodedInfo* info);
+ size_t SamplesPer10msFrame() const;
AudioEncoder* speech_encoder_;
const int cng_payload_type_;
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 284a086db4..5c43a85cb5 100644
--- a/webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc
+++ b/webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc
@@ -49,9 +49,15 @@ AudioEncoderPcm::~AudioEncoderPcm() {
int AudioEncoderPcm::SampleRateHz() const {
return sample_rate_hz_;
}
+
int AudioEncoderPcm::NumChannels() const {
return num_channels_;
}
+
+size_t AudioEncoderPcm::MaxEncodedBytes() const {
+ return full_frame_samples_;
+}
+
int AudioEncoderPcm::Num10MsFramesInNextPacket() const {
return num_10ms_frames_per_packet_;
}
@@ -72,11 +78,12 @@ void AudioEncoderPcm::EncodeInternal(uint32_t rtp_timestamp,
for (int i = 0; i < num_samples; ++i) {
speech_buffer_.push_back(audio[i]);
}
- if (speech_buffer_.size() < static_cast<size_t>(full_frame_samples_)) {
+ if (speech_buffer_.size() < full_frame_samples_) {
info->encoded_bytes = 0;
return;
}
- CHECK_EQ(speech_buffer_.size(), static_cast<size_t>(full_frame_samples_));
+ CHECK_EQ(speech_buffer_.size(), full_frame_samples_);
+ CHECK_GE(max_encoded_bytes, full_frame_samples_);
int16_t ret = EncodeCall(&speech_buffer_[0], full_frame_samples_, encoded);
CHECK_GE(ret, 0);
speech_buffer_.clear();
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 3967c5e00d..e64bcea27e 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
@@ -34,6 +34,7 @@ class AudioEncoderPcm : public AudioEncoder {
int SampleRateHz() const override;
int NumChannels() const override;
+ size_t MaxEncodedBytes() const override;
int Num10MsFramesInNextPacket() const override;
int Max10MsFramesInAPacket() const override;
@@ -55,7 +56,7 @@ class AudioEncoderPcm : public AudioEncoder {
const int num_channels_;
const int payload_type_;
const int num_10ms_frames_per_packet_;
- const int16_t full_frame_samples_;
+ const size_t full_frame_samples_;
std::vector<int16_t> speech_buffer_;
uint32_t first_timestamp_in_buffer_;
};
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 f02bda03a7..bbdcb1da74 100644
--- a/webrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.cc
+++ b/webrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.cc
@@ -54,17 +54,25 @@ AudioEncoderG722::~AudioEncoderG722() {}
int AudioEncoderG722::SampleRateHz() const {
return kSampleRateHz;
}
+
int AudioEncoderG722::RtpTimestampRateHz() const {
// The RTP timestamp rate for G.722 is 8000 Hz, even though it is a 16 kHz
// codec.
return kSampleRateHz / 2;
}
+
int AudioEncoderG722::NumChannels() const {
return num_channels_;
}
+
+size_t AudioEncoderG722::MaxEncodedBytes() const {
+ return static_cast<size_t>(SamplesPerChannel() / 2 * num_channels_);
+}
+
int AudioEncoderG722::Num10MsFramesInNextPacket() const {
return num_10ms_frames_per_packet_;
}
+
int AudioEncoderG722::Max10MsFramesInAPacket() const {
return num_10ms_frames_per_packet_;
}
@@ -74,10 +82,7 @@ void AudioEncoderG722::EncodeInternal(uint32_t rtp_timestamp,
size_t max_encoded_bytes,
uint8_t* encoded,
EncodedInfo* info) {
- const int samples_per_channel =
- kSampleRateHz / 100 * num_10ms_frames_per_packet_;
- CHECK_GE(max_encoded_bytes,
- static_cast<size_t>(samples_per_channel) / 2 * num_channels_);
+ CHECK_GE(max_encoded_bytes, MaxEncodedBytes());
if (num_10ms_frames_buffered_ == 0)
first_timestamp_in_buffer_ = rtp_timestamp;
@@ -97,6 +102,7 @@ void AudioEncoderG722::EncodeInternal(uint32_t rtp_timestamp,
// Encode each channel separately.
CHECK_EQ(num_10ms_frames_buffered_, num_10ms_frames_per_packet_);
num_10ms_frames_buffered_ = 0;
+ const int samples_per_channel = SamplesPerChannel();
for (int i = 0; i < num_channels_; ++i) {
const int encoded = WebRtcG722_Encode(
encoders_[i].encoder, encoders_[i].speech_buffer.get(),
@@ -123,4 +129,8 @@ void AudioEncoderG722::EncodeInternal(uint32_t rtp_timestamp,
info->payload_type = payload_type_;
}
+int AudioEncoderG722::SamplesPerChannel() const {
+ return kSampleRateHz / 100 * num_10ms_frames_per_packet_;
+}
+
} // 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 229c06e463..81b44d6256 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
@@ -31,8 +31,9 @@ class AudioEncoderG722 : public AudioEncoder {
~AudioEncoderG722() override;
int SampleRateHz() const override;
- int RtpTimestampRateHz() const override;
int NumChannels() const override;
+ size_t MaxEncodedBytes() const override;
+ int RtpTimestampRateHz() const override;
int Num10MsFramesInNextPacket() const override;
int Max10MsFramesInAPacket() const override;
@@ -53,6 +54,8 @@ class AudioEncoderG722 : public AudioEncoder {
~EncoderState();
};
+ int SamplesPerChannel() const;
+
const int num_channels_;
const int payload_type_;
const int num_10ms_frames_per_packet_;
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 b939341212..1e85a077ff 100644
--- a/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc
+++ b/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc
@@ -46,12 +46,19 @@ AudioEncoderIlbc::~AudioEncoderIlbc() {
int AudioEncoderIlbc::SampleRateHz() const {
return kSampleRateHz;
}
+
int AudioEncoderIlbc::NumChannels() const {
return 1;
}
+
+size_t AudioEncoderIlbc::MaxEncodedBytes() const {
+ return RequiredOutputSizeBytes();
+}
+
int AudioEncoderIlbc::Num10MsFramesInNextPacket() const {
return num_10ms_frames_per_packet_;
}
+
int AudioEncoderIlbc::Max10MsFramesInAPacket() const {
return num_10ms_frames_per_packet_;
}
@@ -61,24 +68,7 @@ void AudioEncoderIlbc::EncodeInternal(uint32_t rtp_timestamp,
size_t max_encoded_bytes,
uint8_t* encoded,
EncodedInfo* info) {
- size_t expected_output_len;
- switch (num_10ms_frames_per_packet_) {
- case 2:
- expected_output_len = 38;
- break;
- case 3:
- expected_output_len = 50;
- break;
- case 4:
- expected_output_len = 2 * 38;
- break;
- case 6:
- expected_output_len = 2 * 50;
- break;
- default:
- FATAL();
- }
- DCHECK_GE(max_encoded_bytes, expected_output_len);
+ DCHECK_GE(max_encoded_bytes, RequiredOutputSizeBytes());
// Save timestamp if starting a new packet.
if (num_10ms_frames_buffered_ == 0)
@@ -105,10 +95,20 @@ void AudioEncoderIlbc::EncodeInternal(uint32_t rtp_timestamp,
kSampleRateHz / 100 * num_10ms_frames_per_packet_,
encoded);
CHECK_GE(output_len, 0);
- DCHECK_EQ(output_len, static_cast<int>(expected_output_len));
info->encoded_bytes = output_len;
+ DCHECK_EQ(info->encoded_bytes, RequiredOutputSizeBytes());
info->encoded_timestamp = first_timestamp_in_buffer_;
info->payload_type = payload_type_;
}
+size_t AudioEncoderIlbc::RequiredOutputSizeBytes() const {
+ switch (num_10ms_frames_per_packet_) {
+ case 2: return 38;
+ case 3: return 50;
+ case 4: return 2 * 38;
+ case 6: return 2 * 50;
+ default: FATAL();
+ }
+}
+
} // 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 fc3aa0d4ba..a5378d1ed1 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
@@ -33,6 +33,7 @@ class AudioEncoderIlbc : public AudioEncoder {
int SampleRateHz() const override;
int NumChannels() const override;
+ size_t MaxEncodedBytes() const override;
int Num10MsFramesInNextPacket() const override;
int Max10MsFramesInAPacket() const override;
@@ -44,6 +45,8 @@ class AudioEncoderIlbc : public AudioEncoder {
EncodedInfo* info) override;
private:
+ size_t RequiredOutputSizeBytes() const;
+
static const int kMaxSamplesPerPacket = 480;
const int payload_type_;
const int num_10ms_frames_per_packet_;
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 c918eafc41..88ead93402 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
@@ -71,6 +71,7 @@ class AudioEncoderDecoderIsacT : public AudioEncoder, public AudioDecoder {
// AudioEncoder public methods.
int SampleRateHz() const override;
int NumChannels() const override;
+ size_t MaxEncodedBytes() const override;
int Num10MsFramesInNextPacket() const override;
int Max10MsFramesInAPacket() const override;
diff --git a/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h b/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h
index 024efa1413..b9c3e98e8e 100644
--- a/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h
+++ b/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h
@@ -185,6 +185,11 @@ int AudioEncoderDecoderIsacT<T>::NumChannels() const {
}
template <typename T>
+size_t AudioEncoderDecoderIsacT<T>::MaxEncodedBytes() const {
+ return kSufficientEncodeBufferSizeBytes;
+}
+
+template <typename T>
int AudioEncoderDecoderIsacT<T>::Num10MsFramesInNextPacket() const {
CriticalSectionScoped cs(state_lock_.get());
const int samples_in_next_packet = T::GetNewFrameLen(isac_state_);
diff --git a/webrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac_red_unittest.cc b/webrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac_red_unittest.cc
index 4bc616605e..22949a9275 100644
--- a/webrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac_red_unittest.cc
+++ b/webrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac_red_unittest.cc
@@ -30,12 +30,11 @@ TEST(AudioEncoderIsacRedTest, CompareRedAndNoRed) {
double r = rand(); // NOLINT(runtime/threadsafe_fn)
input[i] = (r / RAND_MAX) * 2000 - 1000;
}
- static const size_t kMaxEncodedSizeBytes = 1000;
- uint8_t encoded[kMaxEncodedSizeBytes];
- uint8_t red_encoded[kMaxEncodedSizeBytes];
AudioEncoderDecoderIsac::Config config;
config.sample_rate_hz = kSampleRateHz;
AudioEncoderDecoderIsac isac_encoder(config);
+ size_t max_encoded_bytes = isac_encoder.MaxEncodedBytes();
+ rtc::scoped_ptr<uint8_t[]> encoded(new uint8_t[max_encoded_bytes]);
AudioEncoderDecoderIsac::Config red_config;
red_config.sample_rate_hz = kSampleRateHz;
red_config.red_payload_type = kRedPayloadType;
@@ -43,6 +42,8 @@ TEST(AudioEncoderIsacRedTest, CompareRedAndNoRed) {
ASSERT_NE(red_config.red_payload_type, red_config.payload_type)
<< "iSAC and RED payload types must be different.";
AudioEncoderDecoderIsac isac_red_encoder(red_config);
+ size_t max_red_encoded_bytes = isac_red_encoder.MaxEncodedBytes();
+ rtc::scoped_ptr<uint8_t[]> red_encoded(new uint8_t[max_red_encoded_bytes]);
AudioEncoder::EncodedInfo info, red_info;
// Note that we are not expecting any output from the redundant encoder until
@@ -52,10 +53,11 @@ TEST(AudioEncoderIsacRedTest, CompareRedAndNoRed) {
EXPECT_EQ(0u, red_info.encoded_bytes);
EXPECT_EQ(0u, red_info.redundant.size());
const uint32_t timestamp = static_cast<uint32_t>(i);
- isac_encoder.Encode(timestamp, input, k10MsSamples, kMaxEncodedSizeBytes,
- encoded, &info);
+ isac_encoder.Encode(timestamp, input, k10MsSamples, max_encoded_bytes,
+ encoded.get(), &info);
isac_red_encoder.Encode(timestamp, input, k10MsSamples,
- kMaxEncodedSizeBytes, red_encoded, &red_info);
+ max_red_encoded_bytes, red_encoded.get(),
+ &red_info);
}
EXPECT_GT(info.encoded_bytes, 0u)
<< "Regular codec did not produce any output";
@@ -65,7 +67,7 @@ TEST(AudioEncoderIsacRedTest, CompareRedAndNoRed) {
ASSERT_EQ(info.encoded_bytes, red_info.redundant[0].encoded_bytes)
<< "Primary payload should be same length as non-redundant payload";
// Check that |encoded| and the primary part of |red_encoded| are identical.
- EXPECT_EQ(0, memcmp(encoded, red_encoded, info.encoded_bytes));
+ EXPECT_EQ(0, memcmp(encoded.get(), red_encoded.get(), info.encoded_bytes));
EXPECT_GT(red_info.redundant[0].encoded_bytes,
red_info.redundant[1].encoded_bytes)
<< "Redundant payload should be smaller than primary";
diff --git a/webrtc/modules/audio_coding/codecs/mock/mock_audio_encoder.h b/webrtc/modules/audio_coding/codecs/mock/mock_audio_encoder.h
index 70ee497453..7425e9a188 100644
--- a/webrtc/modules/audio_coding/codecs/mock/mock_audio_encoder.h
+++ b/webrtc/modules/audio_coding/codecs/mock/mock_audio_encoder.h
@@ -23,6 +23,7 @@ class MockAudioEncoder : public AudioEncoder {
MOCK_METHOD0(Die, void());
MOCK_CONST_METHOD0(SampleRateHz, int());
MOCK_CONST_METHOD0(NumChannels, int());
+ MOCK_CONST_METHOD0(MaxEncodedBytes, size_t());
MOCK_CONST_METHOD0(Num10MsFramesInNextPacket, int());
MOCK_CONST_METHOD0(Max10MsFramesInAPacket, int());
MOCK_METHOD1(SetTargetBitrate, void(int));
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 e4779aa0b8..b98033e06d 100644
--- a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
+++ b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
@@ -111,6 +111,16 @@ int AudioEncoderOpus::NumChannels() const {
return num_channels_;
}
+size_t AudioEncoderOpus::MaxEncodedBytes() const {
+ // Calculate the number of bytes we expect the encoder to produce,
+ // then multiply by two to give a wide margin for error.
+ int frame_size_ms = num_10ms_frames_per_packet_ * 10;
+ int bytes_per_millisecond = bitrate_bps_ / (1000 * 8) + 1;
+ size_t approx_encoded_bytes =
+ static_cast<size_t>(frame_size_ms * bytes_per_millisecond);
+ return 2 * approx_encoded_bytes;
+}
+
int AudioEncoderOpus::Num10MsFramesInNextPacket() const {
return num_10ms_frames_per_packet_;
}
@@ -120,10 +130,9 @@ int AudioEncoderOpus::Max10MsFramesInAPacket() const {
}
void AudioEncoderOpus::SetTargetBitrate(int bits_per_second) {
- CHECK_EQ(WebRtcOpus_SetBitRate(
- inst_, std::max(std::min(bits_per_second, kMaxBitrateBps),
- kMinBitrateBps)),
- 0);
+ bitrate_bps_ = std::max(std::min(bits_per_second, kMaxBitrateBps),
+ kMinBitrateBps);
+ CHECK_EQ(WebRtcOpus_SetBitRate(inst_, bitrate_bps_), 0);
}
void AudioEncoderOpus::SetProjectedPacketLossRate(double fraction) {
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 417faf806e..bfd4ba86a8 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
@@ -47,10 +47,12 @@ class AudioEncoderOpus final : public AudioEncoder {
int SampleRateHz() const override;
int NumChannels() const override;
+ size_t MaxEncodedBytes() const override;
int Num10MsFramesInNextPacket() const override;
int Max10MsFramesInAPacket() const override;
void SetTargetBitrate(int bits_per_second) override;
void SetProjectedPacketLossRate(double fraction) override;
+
double packet_loss_rate() const { return packet_loss_rate_; }
ApplicationMode application() const { return application_; }
@@ -66,6 +68,7 @@ class AudioEncoderOpus final : public AudioEncoder {
const int num_channels_;
const int payload_type_;
const ApplicationMode application_;
+ int bitrate_bps_;
const int samples_per_10ms_frame_;
std::vector<int16_t> input_buffer_;
OpusEncInst* inst_;
diff --git a/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc b/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc
index 92e1c0b371..28c72fb3bb 100644
--- a/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc
+++ b/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc
@@ -38,6 +38,10 @@ int AudioEncoderCopyRed::NumChannels() const {
return speech_encoder_->NumChannels();
}
+size_t AudioEncoderCopyRed::MaxEncodedBytes() const {
+ return 2 * speech_encoder_->MaxEncodedBytes();
+}
+
int AudioEncoderCopyRed::Num10MsFramesInNextPacket() const {
return speech_encoder_->Num10MsFramesInNextPacket();
}
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 39f1615d8d..7ce9ca0f01 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
@@ -36,8 +36,9 @@ class AudioEncoderCopyRed : public AudioEncoder {
~AudioEncoderCopyRed() override;
int SampleRateHz() const override;
- int RtpTimestampRateHz() const override;
int NumChannels() const override;
+ size_t MaxEncodedBytes() const override;
+ int RtpTimestampRateHz() const override;
int Num10MsFramesInNextPacket() const override;
int Max10MsFramesInAPacket() const override;
void SetTargetBitrate(int bits_per_second) override;
diff --git a/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red_unittest.cc b/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red_unittest.cc
index ea3ad436a8..2ae2fa21b0 100644
--- a/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red_unittest.cc
+++ b/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red_unittest.cc
@@ -8,6 +8,8 @@
* be found in the AUTHORS file in the root of the source tree.
*/
+#include <vector>
+
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/scoped_ptr.h"
@@ -24,7 +26,7 @@ using ::testing::MockFunction;
namespace webrtc {
namespace {
-static const size_t kMaxEncodedBytes = 1000;
+static const size_t kMockMaxEncodedBytes = 1000;
static const size_t kMaxNumSamples = 48 * 10 * 2; // 10 ms @ 48 kHz stereo.
}
@@ -39,11 +41,13 @@ class AudioEncoderCopyRedTest : public ::testing::Test {
config.payload_type = red_payload_type_;
config.speech_encoder = &mock_encoder_;
red_.reset(new AudioEncoderCopyRed(config));
- memset(encoded_, 0, sizeof(encoded_));
memset(audio_, 0, sizeof(audio_));
EXPECT_CALL(mock_encoder_, NumChannels()).WillRepeatedly(Return(1));
EXPECT_CALL(mock_encoder_, SampleRateHz())
.WillRepeatedly(Return(sample_rate_hz_));
+ EXPECT_CALL(mock_encoder_, MaxEncodedBytes())
+ .WillRepeatedly(Return(kMockMaxEncodedBytes));
+ encoded_.resize(red_->MaxEncodedBytes(), 0);
}
void TearDown() override {
@@ -58,7 +62,7 @@ class AudioEncoderCopyRedTest : public ::testing::Test {
ASSERT_TRUE(red_.get() != NULL);
encoded_info_ = AudioEncoder::EncodedInfo();
red_->Encode(timestamp_, audio_, num_audio_samples_10ms,
- kMaxEncodedBytes, encoded_, &encoded_info_);
+ encoded_.size(), &encoded_[0], &encoded_info_);
timestamp_ += num_audio_samples_10ms;
}
@@ -68,7 +72,7 @@ class AudioEncoderCopyRedTest : public ::testing::Test {
int16_t audio_[kMaxNumSamples];
const int sample_rate_hz_;
size_t num_audio_samples_10ms;
- uint8_t encoded_[kMaxEncodedBytes];
+ std::vector<uint8_t> encoded_;
AudioEncoder::EncodedInfo encoded_info_;
const int red_payload_type_;
};