Expose ILBC codec in webrtc/api/audio_codecs/
BUG=webrtc:7834, webrtc:7840
Review-Url: https://codereview.webrtc.org/2951873002
Cr-Commit-Position: refs/heads/master@{#18803}
diff --git a/webrtc/api/audio_codecs/ilbc/BUILD.gn b/webrtc/api/audio_codecs/ilbc/BUILD.gn
new file mode 100644
index 0000000..bba2662
--- /dev/null
+++ b/webrtc/api/audio_codecs/ilbc/BUILD.gn
@@ -0,0 +1,45 @@
+# Copyright (c) 2017 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.
+
+import("../../../webrtc.gni")
+if (is_android) {
+ import("//build/config/android/config.gni")
+ import("//build/config/android/rules.gni")
+}
+
+rtc_source_set("audio_encoder_ilbc_config") {
+ sources = [
+ "audio_encoder_ilbc_config.h",
+ ]
+}
+
+rtc_static_library("audio_encoder_ilbc") {
+ sources = [
+ "audio_encoder_ilbc.cc",
+ "audio_encoder_ilbc.h",
+ ]
+ deps = [
+ ":audio_encoder_ilbc_config",
+ "..:audio_codecs_api",
+ "../../../base:rtc_base_approved",
+ "../../../modules/audio_coding:ilbc",
+ ]
+}
+
+rtc_static_library("audio_decoder_ilbc") {
+ sources = [
+ "audio_decoder_ilbc.cc",
+ "audio_decoder_ilbc.h",
+ ]
+ deps = [
+ "..:audio_codecs_api",
+ "../../..:webrtc_common",
+ "../../../base:rtc_base_approved",
+ "../../../modules/audio_coding:ilbc",
+ ]
+}
diff --git a/webrtc/api/audio_codecs/ilbc/audio_decoder_ilbc.cc b/webrtc/api/audio_codecs/ilbc/audio_decoder_ilbc.cc
new file mode 100644
index 0000000..da290af
--- /dev/null
+++ b/webrtc/api/audio_codecs/ilbc/audio_decoder_ilbc.cc
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/api/audio_codecs/ilbc/audio_decoder_ilbc.h"
+
+#include <memory>
+#include <vector>
+
+#include "webrtc/base/ptr_util.h"
+#include "webrtc/common_types.h"
+#include "webrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h"
+
+namespace webrtc {
+
+rtc::Optional<AudioDecoderIlbc::Config> AudioDecoderIlbc::SdpToConfig(
+ const SdpAudioFormat& format) {
+ return STR_CASE_CMP(format.name.c_str(), "ilbc") == 0 &&
+ format.clockrate_hz == 8000 && format.num_channels == 1
+ ? rtc::Optional<Config>(Config())
+ : rtc::Optional<Config>();
+}
+
+void AudioDecoderIlbc::AppendSupportedDecoders(
+ std::vector<AudioCodecSpec>* specs) {
+ specs->push_back({{"ILBC", 8000, 1}, {8000, 1, 13300}});
+}
+
+std::unique_ptr<AudioDecoder> AudioDecoderIlbc::MakeAudioDecoder(
+ Config config) {
+ return rtc::MakeUnique<AudioDecoderIlbcImpl>();
+}
+
+} // namespace webrtc
diff --git a/webrtc/api/audio_codecs/ilbc/audio_decoder_ilbc.h b/webrtc/api/audio_codecs/ilbc/audio_decoder_ilbc.h
new file mode 100644
index 0000000..1d58810
--- /dev/null
+++ b/webrtc/api/audio_codecs/ilbc/audio_decoder_ilbc.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017 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_API_AUDIO_CODECS_ILBC_AUDIO_DECODER_ILBC_H_
+#define WEBRTC_API_AUDIO_CODECS_ILBC_AUDIO_DECODER_ILBC_H_
+
+#include <memory>
+#include <vector>
+
+#include "webrtc/api/audio_codecs/audio_decoder.h"
+#include "webrtc/api/audio_codecs/audio_format.h"
+#include "webrtc/base/optional.h"
+
+namespace webrtc {
+
+// ILBC decoder API for use as a template parameter to
+// CreateAudioDecoderFactory<...>().
+//
+// NOTE: This struct is still under development and may change without notice.
+struct AudioDecoderIlbc {
+ struct Config {}; // Empty---no config values needed!
+ static rtc::Optional<Config> SdpToConfig(const SdpAudioFormat& audio_format);
+ static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs);
+ static std::unique_ptr<AudioDecoder> MakeAudioDecoder(Config config);
+};
+
+} // namespace webrtc
+
+#endif // WEBRTC_API_AUDIO_CODECS_ILBC_AUDIO_DECODER_ILBC_H_
diff --git a/webrtc/api/audio_codecs/ilbc/audio_encoder_ilbc.cc b/webrtc/api/audio_codecs/ilbc/audio_encoder_ilbc.cc
new file mode 100644
index 0000000..a4b3a38
--- /dev/null
+++ b/webrtc/api/audio_codecs/ilbc/audio_encoder_ilbc.cc
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/api/audio_codecs/ilbc/audio_encoder_ilbc.h"
+
+#include <memory>
+#include <vector>
+
+#include "webrtc/base/ptr_util.h"
+#include "webrtc/base/safe_conversions.h"
+#include "webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h"
+
+namespace webrtc {
+namespace {
+int GetIlbcBitrate(int ptime) {
+ switch (ptime) {
+ case 20:
+ case 40:
+ // 38 bytes per frame of 20 ms => 15200 bits/s.
+ return 15200;
+ case 30:
+ case 60:
+ // 50 bytes per frame of 30 ms => (approx) 13333 bits/s.
+ return 13333;
+ default:
+ FATAL();
+ }
+}
+} // namespace
+
+rtc::Optional<AudioEncoderIlbcConfig> AudioEncoderIlbc::SdpToConfig(
+ const SdpAudioFormat& format) {
+ return AudioEncoderIlbcImpl::SdpToConfig(format);
+}
+
+void AudioEncoderIlbc::AppendSupportedEncoders(
+ std::vector<AudioCodecSpec>* specs) {
+ const SdpAudioFormat fmt = {"ILBC", 8000, 1};
+ const AudioCodecInfo info = QueryAudioEncoder(*SdpToConfig(fmt));
+ specs->push_back({fmt, info});
+}
+
+AudioCodecInfo AudioEncoderIlbc::QueryAudioEncoder(
+ const AudioEncoderIlbcConfig& config) {
+ RTC_DCHECK(config.IsOk());
+ return {8000, 1, GetIlbcBitrate(config.frame_size_ms)};
+}
+
+std::unique_ptr<AudioEncoder> AudioEncoderIlbc::MakeAudioEncoder(
+ const AudioEncoderIlbcConfig& config,
+ int payload_type) {
+ RTC_DCHECK(config.IsOk());
+ return rtc::MakeUnique<AudioEncoderIlbcImpl>(config, payload_type);
+}
+
+} // namespace webrtc
diff --git a/webrtc/api/audio_codecs/ilbc/audio_encoder_ilbc.h b/webrtc/api/audio_codecs/ilbc/audio_encoder_ilbc.h
new file mode 100644
index 0000000..4201035
--- /dev/null
+++ b/webrtc/api/audio_codecs/ilbc/audio_encoder_ilbc.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017 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_API_AUDIO_CODECS_ILBC_AUDIO_ENCODER_ILBC_H_
+#define WEBRTC_API_AUDIO_CODECS_ILBC_AUDIO_ENCODER_ILBC_H_
+
+#include <memory>
+#include <vector>
+
+#include "webrtc/api/audio_codecs/audio_encoder.h"
+#include "webrtc/api/audio_codecs/audio_format.h"
+#include "webrtc/api/audio_codecs/ilbc/audio_encoder_ilbc_config.h"
+#include "webrtc/base/optional.h"
+
+namespace webrtc {
+
+// ILBC encoder API for use as a template parameter to
+// CreateAudioEncoderFactory<...>().
+//
+// NOTE: This struct is still under development and may change without notice.
+struct AudioEncoderIlbc {
+ static rtc::Optional<AudioEncoderIlbcConfig> SdpToConfig(
+ const SdpAudioFormat& audio_format);
+ static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs);
+ static AudioCodecInfo QueryAudioEncoder(const AudioEncoderIlbcConfig& config);
+ static std::unique_ptr<AudioEncoder> MakeAudioEncoder(
+ const AudioEncoderIlbcConfig& config,
+ int payload_type);
+};
+
+} // namespace webrtc
+
+#endif // WEBRTC_API_AUDIO_CODECS_ILBC_AUDIO_ENCODER_ILBC_H_
diff --git a/webrtc/api/audio_codecs/ilbc/audio_encoder_ilbc_config.h b/webrtc/api/audio_codecs/ilbc/audio_encoder_ilbc_config.h
new file mode 100644
index 0000000..429ac81
--- /dev/null
+++ b/webrtc/api/audio_codecs/ilbc/audio_encoder_ilbc_config.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017 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_API_AUDIO_CODECS_ILBC_AUDIO_ENCODER_ILBC_CONFIG_H_
+#define WEBRTC_API_AUDIO_CODECS_ILBC_AUDIO_ENCODER_ILBC_CONFIG_H_
+
+namespace webrtc {
+
+// NOTE: This struct is still under development and may change without notice.
+struct AudioEncoderIlbcConfig {
+ bool IsOk() const {
+ return (frame_size_ms == 20 || frame_size_ms == 30 || frame_size_ms == 40 ||
+ frame_size_ms == 60);
+ }
+ int frame_size_ms = 30; // Valid values are 20, 30, 40, and 60 ms.
+ // Note that frame size 40 ms produces encodings with two 20 ms frames in
+ // them, and frame size 60 ms consists of two 30 ms frames.
+};
+
+} // namespace webrtc
+
+#endif // WEBRTC_API_AUDIO_CODECS_ILBC_AUDIO_ENCODER_ILBC_CONFIG_H_
diff --git a/webrtc/api/audio_codecs/test/BUILD.gn b/webrtc/api/audio_codecs/test/BUILD.gn
index 08d527d..38ca736 100644
--- a/webrtc/api/audio_codecs/test/BUILD.gn
+++ b/webrtc/api/audio_codecs/test/BUILD.gn
@@ -26,6 +26,8 @@
"../../../test:test_support",
"../g722:audio_decoder_g722",
"../g722:audio_encoder_g722",
+ "../ilbc:audio_decoder_ilbc",
+ "../ilbc:audio_encoder_ilbc",
"//testing/gmock",
]
}
diff --git a/webrtc/api/audio_codecs/test/audio_decoder_factory_template_unittest.cc b/webrtc/api/audio_codecs/test/audio_decoder_factory_template_unittest.cc
index c05fcd6..283a5f5 100644
--- a/webrtc/api/audio_codecs/test/audio_decoder_factory_template_unittest.cc
+++ b/webrtc/api/audio_codecs/test/audio_decoder_factory_template_unittest.cc
@@ -10,6 +10,7 @@
#include "webrtc/api/audio_codecs/audio_decoder_factory_template.h"
#include "webrtc/api/audio_codecs/g722/audio_decoder_g722.h"
+#include "webrtc/api/audio_codecs/ilbc/audio_decoder_ilbc.h"
#include "webrtc/base/ptr_util.h"
#include "webrtc/test/gmock.h"
#include "webrtc/test/gtest.h"
@@ -131,4 +132,17 @@
ASSERT_EQ(nullptr, dec3);
}
+TEST(AudioDecoderFactoryTemplateTest, Ilbc) {
+ auto factory = CreateAudioDecoderFactory<AudioDecoderIlbc>();
+ EXPECT_THAT(factory->GetSupportedDecoders(),
+ testing::ElementsAre(
+ AudioCodecSpec{{"ILBC", 8000, 1}, {8000, 1, 13300}}));
+ EXPECT_FALSE(factory->IsSupportedDecoder({"foo", 8000, 1}));
+ EXPECT_TRUE(factory->IsSupportedDecoder({"ilbc", 8000, 1}));
+ EXPECT_EQ(nullptr, factory->MakeAudioDecoder({"bar", 8000, 1}));
+ auto dec = factory->MakeAudioDecoder({"ilbc", 8000, 1});
+ ASSERT_NE(nullptr, dec);
+ EXPECT_EQ(8000, dec->SampleRateHz());
+}
+
} // namespace webrtc
diff --git a/webrtc/api/audio_codecs/test/audio_encoder_factory_template_unittest.cc b/webrtc/api/audio_codecs/test/audio_encoder_factory_template_unittest.cc
index abca968..c3c07c6 100644
--- a/webrtc/api/audio_codecs/test/audio_encoder_factory_template_unittest.cc
+++ b/webrtc/api/audio_codecs/test/audio_encoder_factory_template_unittest.cc
@@ -10,6 +10,7 @@
#include "webrtc/api/audio_codecs/audio_encoder_factory_template.h"
#include "webrtc/api/audio_codecs/g722/audio_encoder_g722.h"
+#include "webrtc/api/audio_codecs/ilbc/audio_encoder_ilbc.h"
#include "webrtc/base/ptr_util.h"
#include "webrtc/test/gmock.h"
#include "webrtc/test/gtest.h"
@@ -133,4 +134,19 @@
EXPECT_EQ(16000, enc->SampleRateHz());
}
+TEST(AudioEncoderFactoryTemplateTest, Ilbc) {
+ auto factory = CreateAudioEncoderFactory<AudioEncoderIlbc>();
+ EXPECT_THAT(factory->GetSupportedEncoders(),
+ testing::ElementsAre(
+ AudioCodecSpec{{"ILBC", 8000, 1}, {8000, 1, 13333}}));
+ EXPECT_EQ(rtc::Optional<AudioCodecInfo>(),
+ factory->QueryAudioEncoder({"foo", 8000, 1}));
+ EXPECT_EQ(rtc::Optional<AudioCodecInfo>({8000, 1, 13333}),
+ factory->QueryAudioEncoder({"ilbc", 8000, 1}));
+ EXPECT_EQ(nullptr, factory->MakeAudioEncoder(17, {"bar", 8000, 1}));
+ auto enc = factory->MakeAudioEncoder(17, {"ilbc", 8000, 1});
+ ASSERT_NE(nullptr, enc);
+ EXPECT_EQ(8000, enc->SampleRateHz());
+}
+
} // namespace webrtc
diff --git a/webrtc/modules/audio_coding/BUILD.gn b/webrtc/modules/audio_coding/BUILD.gn
index afd2720..30460ba 100644
--- a/webrtc/modules/audio_coding/BUILD.gn
+++ b/webrtc/modules/audio_coding/BUILD.gn
@@ -322,6 +322,7 @@
":legacy_encoded_audio_frame",
"../..:webrtc_common",
"../../api/audio_codecs:audio_codecs_api",
+ "../../api/audio_codecs/ilbc:audio_encoder_ilbc_config",
"../../base:rtc_base_approved",
"../../common_audio",
]
diff --git a/webrtc/modules/audio_coding/acm2/rent_a_codec.cc b/webrtc/modules/audio_coding/acm2/rent_a_codec.cc
index 79491b8..8456285 100644
--- a/webrtc/modules/audio_coding/acm2/rent_a_codec.cc
+++ b/webrtc/modules/audio_coding/acm2/rent_a_codec.cc
@@ -173,7 +173,7 @@
return std::unique_ptr<AudioEncoder>(new AudioEncoderPcm16B(speech_inst));
#ifdef WEBRTC_CODEC_ILBC
if (STR_CASE_CMP(speech_inst.plname, "ilbc") == 0)
- return std::unique_ptr<AudioEncoder>(new AudioEncoderIlbc(speech_inst));
+ return std::unique_ptr<AudioEncoder>(new AudioEncoderIlbcImpl(speech_inst));
#endif
#ifdef WEBRTC_CODEC_G722
if (STR_CASE_CMP(speech_inst.plname, "g722") == 0)
diff --git a/webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory_internal.cc b/webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory_internal.cc
index 332ad06..ce7ec3d 100644
--- a/webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory_internal.cc
+++ b/webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory_internal.cc
@@ -78,7 +78,7 @@
[](const SdpAudioFormat& format, std::unique_ptr<AudioDecoder>* out) {
if (format.clockrate_hz == 8000 && format.num_channels == 1) {
if (out) {
- out->reset(new AudioDecoderIlbc);
+ out->reset(new AudioDecoderIlbcImpl);
}
return true;
} else {
diff --git a/webrtc/modules/audio_coding/codecs/builtin_audio_encoder_factory_internal.cc b/webrtc/modules/audio_coding/codecs/builtin_audio_encoder_factory_internal.cc
index 3f75cc8..3c8c030 100644
--- a/webrtc/modules/audio_coding/codecs/builtin_audio_encoder_factory_internal.cc
+++ b/webrtc/modules/audio_coding/codecs/builtin_audio_encoder_factory_internal.cc
@@ -65,7 +65,7 @@
NamedEncoderFactory::ForEncoder<AudioEncoderG722Impl>(),
#endif
#ifdef WEBRTC_CODEC_ILBC
- NamedEncoderFactory::ForEncoder<AudioEncoderIlbc>(),
+ NamedEncoderFactory::ForEncoder<AudioEncoderIlbcImpl>(),
#endif
#if defined(WEBRTC_CODEC_ISACFX)
NamedEncoderFactory::ForEncoder<AudioEncoderIsacFix>(),
diff --git a/webrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.cc b/webrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.cc
index a0fc02b..a95c7d5 100644
--- a/webrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.cc
+++ b/webrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.cc
@@ -19,20 +19,20 @@
namespace webrtc {
-AudioDecoderIlbc::AudioDecoderIlbc() {
+AudioDecoderIlbcImpl::AudioDecoderIlbcImpl() {
WebRtcIlbcfix_DecoderCreate(&dec_state_);
WebRtcIlbcfix_Decoderinit30Ms(dec_state_);
}
-AudioDecoderIlbc::~AudioDecoderIlbc() {
+AudioDecoderIlbcImpl::~AudioDecoderIlbcImpl() {
WebRtcIlbcfix_DecoderFree(dec_state_);
}
-bool AudioDecoderIlbc::HasDecodePlc() const {
+bool AudioDecoderIlbcImpl::HasDecodePlc() const {
return true;
}
-int AudioDecoderIlbc::DecodeInternal(const uint8_t* encoded,
+int AudioDecoderIlbcImpl::DecodeInternal(const uint8_t* encoded,
size_t encoded_len,
int sample_rate_hz,
int16_t* decoded,
@@ -45,22 +45,22 @@
return ret;
}
-size_t AudioDecoderIlbc::DecodePlc(size_t num_frames, int16_t* decoded) {
+size_t AudioDecoderIlbcImpl::DecodePlc(size_t num_frames, int16_t* decoded) {
return WebRtcIlbcfix_NetEqPlc(dec_state_, decoded, num_frames);
}
-void AudioDecoderIlbc::Reset() {
+void AudioDecoderIlbcImpl::Reset() {
WebRtcIlbcfix_Decoderinit30Ms(dec_state_);
}
-std::vector<AudioDecoder::ParseResult> AudioDecoderIlbc::ParsePayload(
+std::vector<AudioDecoder::ParseResult> AudioDecoderIlbcImpl::ParsePayload(
rtc::Buffer&& payload,
uint32_t timestamp) {
std::vector<ParseResult> results;
size_t bytes_per_frame;
int timestamps_per_frame;
if (payload.size() >= 950) {
- LOG(LS_WARNING) << "AudioDecoderIlbc::ParsePayload: Payload too large";
+ LOG(LS_WARNING) << "AudioDecoderIlbcImpl::ParsePayload: Payload too large";
return results;
}
if (payload.size() % 38 == 0) {
@@ -72,7 +72,7 @@
bytes_per_frame = 50;
timestamps_per_frame = 240;
} else {
- LOG(LS_WARNING) << "AudioDecoderIlbc::ParsePayload: Invalid payload";
+ LOG(LS_WARNING) << "AudioDecoderIlbcImpl::ParsePayload: Invalid payload";
return results;
}
@@ -97,11 +97,11 @@
return results;
}
-int AudioDecoderIlbc::SampleRateHz() const {
+int AudioDecoderIlbcImpl::SampleRateHz() const {
return 8000;
}
-size_t AudioDecoderIlbc::Channels() const {
+size_t AudioDecoderIlbcImpl::Channels() const {
return 1;
}
diff --git a/webrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h b/webrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h
index bc01a5d..5269f4d 100644
--- a/webrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h
+++ b/webrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h
@@ -18,10 +18,10 @@
namespace webrtc {
-class AudioDecoderIlbc final : public AudioDecoder {
+class AudioDecoderIlbcImpl final : public AudioDecoder {
public:
- AudioDecoderIlbc();
- ~AudioDecoderIlbc() override;
+ AudioDecoderIlbcImpl();
+ ~AudioDecoderIlbcImpl() override;
bool HasDecodePlc() const override;
size_t DecodePlc(size_t num_frames, int16_t* decoded) override;
void Reset() override;
@@ -39,7 +39,7 @@
private:
IlbcDecoderInstance* dec_state_;
- RTC_DISALLOW_COPY_AND_ASSIGN(AudioDecoderIlbc);
+ RTC_DISALLOW_COPY_AND_ASSIGN(AudioDecoderIlbcImpl);
};
} // namespace webrtc
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 6ed445a..0dc9bb4 100644
--- a/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc
+++ b/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc
@@ -24,34 +24,20 @@
const int kSampleRateHz = 8000;
-AudioEncoderIlbc::Config CreateConfig(const CodecInst& codec_inst) {
- AudioEncoderIlbc::Config config;
+AudioEncoderIlbcConfig CreateConfig(const CodecInst& codec_inst) {
+ AudioEncoderIlbcConfig config;
config.frame_size_ms = codec_inst.pacsize / 8;
- config.payload_type = codec_inst.pltype;
- return config;
-}
-
-AudioEncoderIlbc::Config CreateConfig(int payload_type,
- const SdpAudioFormat& format) {
- AudioEncoderIlbc::Config config;
- config.payload_type = payload_type;
- auto ptime_iter = format.parameters.find("ptime");
- if (ptime_iter != format.parameters.end()) {
- auto ptime = rtc::StringToNumber<int>(ptime_iter->second);
- if (ptime && *ptime > 0) {
- const int whole_packets = *ptime / 10;
- config.frame_size_ms = std::max(20, std::min(whole_packets * 10, 60));
- }
- }
return config;
}
int GetIlbcBitrate(int ptime) {
switch (ptime) {
- case 20: case 40:
+ case 20:
+ case 40:
// 38 bytes per frame of 20 ms => 15200 bits/s.
return 15200;
- case 30: case 60:
+ case 30:
+ case 60:
// 50 bytes per frame of 30 ms => (approx) 13333 bits/s.
return 13333;
default:
@@ -61,71 +47,85 @@
} // namespace
-// static
-const size_t AudioEncoderIlbc::kMaxSamplesPerPacket;
+rtc::Optional<AudioEncoderIlbcConfig> AudioEncoderIlbcImpl::SdpToConfig(
+ const SdpAudioFormat& format) {
+ if (STR_CASE_CMP(format.name.c_str(), "ilbc") != 0 ||
+ format.clockrate_hz != 8000 || format.num_channels != 1) {
+ return rtc::Optional<AudioEncoderIlbcConfig>();
+ }
-bool AudioEncoderIlbc::Config::IsOk() const {
- return (frame_size_ms == 20 || frame_size_ms == 30 || frame_size_ms == 40 ||
- frame_size_ms == 60) &&
- static_cast<size_t>(kSampleRateHz / 100 * (frame_size_ms / 10)) <=
- kMaxSamplesPerPacket;
+ AudioEncoderIlbcConfig config;
+ auto ptime_iter = format.parameters.find("ptime");
+ if (ptime_iter != format.parameters.end()) {
+ auto ptime = rtc::StringToNumber<int>(ptime_iter->second);
+ if (ptime && *ptime > 0) {
+ const int whole_packets = *ptime / 10;
+ config.frame_size_ms = std::max(20, std::min(whole_packets * 10, 60));
+ }
+ }
+ return config.IsOk() ? rtc::Optional<AudioEncoderIlbcConfig>(config)
+ : rtc::Optional<AudioEncoderIlbcConfig>();
}
-AudioEncoderIlbc::AudioEncoderIlbc(const Config& config)
- : config_(config),
+AudioEncoderIlbcImpl::AudioEncoderIlbcImpl(const AudioEncoderIlbcConfig& config,
+ int payload_type)
+ : frame_size_ms_(config.frame_size_ms),
+ payload_type_(payload_type),
num_10ms_frames_per_packet_(
static_cast<size_t>(config.frame_size_ms / 10)),
encoder_(nullptr) {
+ RTC_CHECK(config.IsOk());
Reset();
}
-AudioEncoderIlbc::AudioEncoderIlbc(const CodecInst& codec_inst)
- : AudioEncoderIlbc(CreateConfig(codec_inst)) {}
+AudioEncoderIlbcImpl::AudioEncoderIlbcImpl(const CodecInst& codec_inst)
+ : AudioEncoderIlbcImpl(CreateConfig(codec_inst), codec_inst.pltype) {}
-AudioEncoderIlbc::AudioEncoderIlbc(int payload_type,
- const SdpAudioFormat& format)
- : AudioEncoderIlbc(CreateConfig(payload_type, format)) {}
+AudioEncoderIlbcImpl::AudioEncoderIlbcImpl(int payload_type,
+ const SdpAudioFormat& format)
+ : AudioEncoderIlbcImpl(*SdpToConfig(format), payload_type) {}
-rtc::Optional<AudioCodecInfo> AudioEncoderIlbc::QueryAudioEncoder(
- const SdpAudioFormat& format) {
- if (STR_CASE_CMP(format.name.c_str(), GetPayloadName()) == 0 &&
- format.clockrate_hz == 8000 && format.num_channels == 1) {
- Config config = CreateConfig(0, format);
- if (config.IsOk()) {
- return rtc::Optional<AudioCodecInfo>(
- {kSampleRateHz, 1, GetIlbcBitrate(config.frame_size_ms)});
- }
- }
-
- return rtc::Optional<AudioCodecInfo>();
-}
-
-AudioEncoderIlbc::~AudioEncoderIlbc() {
+AudioEncoderIlbcImpl::~AudioEncoderIlbcImpl() {
RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderFree(encoder_));
}
-int AudioEncoderIlbc::SampleRateHz() const {
+rtc::Optional<AudioCodecInfo> AudioEncoderIlbcImpl::QueryAudioEncoder(
+ const SdpAudioFormat& format) {
+ if (STR_CASE_CMP(format.name.c_str(), GetPayloadName()) == 0) {
+ const auto config_opt = SdpToConfig(format);
+ if (format.clockrate_hz == 8000 && format.num_channels == 1 &&
+ config_opt) {
+ RTC_DCHECK(config_opt->IsOk());
+ return rtc::Optional<AudioCodecInfo>(
+ {rtc::dchecked_cast<int>(kSampleRateHz), 1,
+ GetIlbcBitrate(config_opt->frame_size_ms)});
+ }
+ }
+ return rtc::Optional<AudioCodecInfo>();
+}
+
+int AudioEncoderIlbcImpl::SampleRateHz() const {
return kSampleRateHz;
}
-size_t AudioEncoderIlbc::NumChannels() const {
+size_t AudioEncoderIlbcImpl::NumChannels() const {
return 1;
}
-size_t AudioEncoderIlbc::Num10MsFramesInNextPacket() const {
+size_t AudioEncoderIlbcImpl::Num10MsFramesInNextPacket() const {
return num_10ms_frames_per_packet_;
}
-size_t AudioEncoderIlbc::Max10MsFramesInAPacket() const {
+size_t AudioEncoderIlbcImpl::Max10MsFramesInAPacket() const {
return num_10ms_frames_per_packet_;
}
-int AudioEncoderIlbc::GetTargetBitrate() const {
+int AudioEncoderIlbcImpl::GetTargetBitrate() const {
return GetIlbcBitrate(rtc::dchecked_cast<int>(num_10ms_frames_per_packet_) *
10);
}
-AudioEncoder::EncodedInfo AudioEncoderIlbc::EncodeImpl(
+AudioEncoder::EncodedInfo AudioEncoderIlbcImpl::EncodeImpl(
uint32_t rtp_timestamp,
rtc::ArrayView<const int16_t> audio,
rtc::Buffer* encoded) {
@@ -166,24 +166,23 @@
EncodedInfo info;
info.encoded_bytes = encoded_bytes;
info.encoded_timestamp = first_timestamp_in_buffer_;
- info.payload_type = config_.payload_type;
+ info.payload_type = payload_type_;
info.encoder_type = CodecType::kIlbc;
return info;
}
-void AudioEncoderIlbc::Reset() {
+void AudioEncoderIlbcImpl::Reset() {
if (encoder_)
RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderFree(encoder_));
- RTC_CHECK(config_.IsOk());
RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderCreate(&encoder_));
- const int encoder_frame_size_ms = config_.frame_size_ms > 30
- ? config_.frame_size_ms / 2
- : config_.frame_size_ms;
+ const int encoder_frame_size_ms = frame_size_ms_ > 30
+ ? frame_size_ms_ / 2
+ : frame_size_ms_;
RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderInit(encoder_, encoder_frame_size_ms));
num_10ms_frames_buffered_ = 0;
}
-size_t AudioEncoderIlbc::RequiredOutputSizeBytes() const {
+size_t AudioEncoderIlbcImpl::RequiredOutputSizeBytes() const {
switch (num_10ms_frames_per_packet_) {
case 2: return 38;
case 3: return 50;
diff --git a/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h b/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h
index 6d3d102..0d9b366 100644
--- a/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h
+++ b/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h
@@ -13,6 +13,7 @@
#include "webrtc/api/audio_codecs/audio_encoder.h"
#include "webrtc/api/audio_codecs/audio_format.h"
+#include "webrtc/api/audio_codecs/ilbc/audio_encoder_ilbc_config.h"
#include "webrtc/base/constructormagic.h"
#include "webrtc/modules/audio_coding/codecs/ilbc/ilbc.h"
@@ -20,21 +21,15 @@
struct CodecInst;
-class AudioEncoderIlbc final : public AudioEncoder {
+class AudioEncoderIlbcImpl final : public AudioEncoder {
public:
- struct Config {
- bool IsOk() const;
+ static rtc::Optional<AudioEncoderIlbcConfig> SdpToConfig(
+ const SdpAudioFormat& format);
- int payload_type = 102;
- int frame_size_ms = 30; // Valid values are 20, 30, 40, and 60 ms.
- // Note that frame size 40 ms produces encodings with two 20 ms frames in
- // them, and frame size 60 ms consists of two 30 ms frames.
- };
-
- explicit AudioEncoderIlbc(const Config& config);
- explicit AudioEncoderIlbc(const CodecInst& codec_inst);
- AudioEncoderIlbc(int payload_type, const SdpAudioFormat& format);
- ~AudioEncoderIlbc() override;
+ AudioEncoderIlbcImpl(const AudioEncoderIlbcConfig& config, int payload_type);
+ explicit AudioEncoderIlbcImpl(const CodecInst& codec_inst);
+ AudioEncoderIlbcImpl(int payload_type, const SdpAudioFormat& format);
+ ~AudioEncoderIlbcImpl() override;
static constexpr const char* GetPayloadName() { return "ILBC"; }
static rtc::Optional<AudioCodecInfo> QueryAudioEncoder(
@@ -53,14 +48,15 @@
private:
size_t RequiredOutputSizeBytes() const;
- static const size_t kMaxSamplesPerPacket = 480;
- const Config config_;
+ static constexpr size_t kMaxSamplesPerPacket = 480;
+ const int frame_size_ms_;
+ const int payload_type_;
const size_t num_10ms_frames_per_packet_;
size_t num_10ms_frames_buffered_;
uint32_t first_timestamp_in_buffer_;
int16_t input_buffer_[kMaxSamplesPerPacket];
IlbcEncoderInstance* encoder_;
- RTC_DISALLOW_COPY_AND_ASSIGN(AudioEncoderIlbc);
+ RTC_DISALLOW_COPY_AND_ASSIGN(AudioEncoderIlbcImpl);
};
} // namespace webrtc
diff --git a/webrtc/modules/audio_coding/codecs/ilbc/ilbc_unittest.cc b/webrtc/modules/audio_coding/codecs/ilbc/ilbc_unittest.cc
index dbd5c07..69e2181 100644
--- a/webrtc/modules/audio_coding/codecs/ilbc/ilbc_unittest.cc
+++ b/webrtc/modules/audio_coding/codecs/ilbc/ilbc_unittest.cc
@@ -17,11 +17,11 @@
TEST(IlbcTest, BadPacket) {
// Get a good packet.
- AudioEncoderIlbc::Config config;
+ AudioEncoderIlbcConfig config;
config.frame_size_ms = 20; // We need 20 ms rather than the default 30 ms;
// otherwise, all possible values of cb_index[2]
// are valid.
- AudioEncoderIlbc encoder(config);
+ AudioEncoderIlbcImpl encoder(config, 102);
std::vector<int16_t> samples(encoder.SampleRateHz() / 100, 4711);
rtc::Buffer packet;
int num_10ms_chunks = 0;
@@ -39,7 +39,7 @@
bad_packet[30] |= 0x80; // Bit 0.
// Decode the bad packet. We expect the decoder to respond by returning -1.
- AudioDecoderIlbc decoder;
+ AudioDecoderIlbcImpl decoder;
std::vector<int16_t> decoded_samples(num_10ms_chunks * samples.size());
AudioDecoder::SpeechType speech_type;
EXPECT_EQ(-1, decoder.Decode(bad_packet.data(), bad_packet.size(),
@@ -69,7 +69,7 @@
};
TEST_P(SplitIlbcTest, NumFrames) {
- AudioDecoderIlbc decoder;
+ AudioDecoderIlbcImpl decoder;
const size_t frame_length_samples = frame_length_ms_ * 8;
const auto generate_payload = [] (size_t payload_length_bytes) {
rtc::Buffer payload(payload_length_bytes);
@@ -120,7 +120,7 @@
// Test too large payload size.
TEST(IlbcTest, SplitTooLargePayload) {
- AudioDecoderIlbc decoder;
+ AudioDecoderIlbcImpl decoder;
constexpr size_t kPayloadLengthBytes = 950;
const auto results =
decoder.ParsePayload(rtc::Buffer(kPayloadLengthBytes), 0);
@@ -129,7 +129,7 @@
// Payload not an integer number of frames.
TEST(IlbcTest, SplitUnevenPayload) {
- AudioDecoderIlbc decoder;
+ AudioDecoderIlbcImpl decoder;
constexpr size_t kPayloadLengthBytes = 39; // Not an even number of frames.
const auto results =
decoder.ParsePayload(rtc::Buffer(kPayloadLengthBytes), 0);
diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc b/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc
index 6d71b85..15a89e9 100644
--- a/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc
+++ b/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc
@@ -315,12 +315,11 @@
codec_input_rate_hz_ = 8000;
frame_size_ = 240;
data_length_ = 10 * frame_size_;
- decoder_ = new AudioDecoderIlbc;
+ decoder_ = new AudioDecoderIlbcImpl;
assert(decoder_);
- AudioEncoderIlbc::Config config;
+ AudioEncoderIlbcConfig config;
config.frame_size_ms = 30;
- config.payload_type = payload_type_;
- audio_encoder_.reset(new AudioEncoderIlbc(config));
+ audio_encoder_.reset(new AudioEncoderIlbcImpl(config, payload_type_));
}
// Overload the default test since iLBC's function WebRtcIlbcfix_NetEqPlc does
diff --git a/webrtc/modules/audio_coding/neteq/test/neteq_ilbc_quality_test.cc b/webrtc/modules/audio_coding/neteq/test/neteq_ilbc_quality_test.cc
index 1c6d2ca..b3524a3 100644
--- a/webrtc/modules/audio_coding/neteq/test/neteq_ilbc_quality_test.cc
+++ b/webrtc/modules/audio_coding/neteq/test/neteq_ilbc_quality_test.cc
@@ -51,9 +51,9 @@
void SetUp() override {
ASSERT_EQ(1u, channels_) << "iLBC supports only mono audio.";
- AudioEncoderIlbc::Config config;
+ AudioEncoderIlbcConfig config;
config.frame_size_ms = FLAGS_frame_size_ms;
- encoder_.reset(new AudioEncoderIlbc(config));
+ encoder_.reset(new AudioEncoderIlbcImpl(config, 102));
NetEqQualityTest::SetUp();
}
@@ -75,7 +75,7 @@
}
private:
- std::unique_ptr<AudioEncoderIlbc> encoder_;
+ std::unique_ptr<AudioEncoderIlbcImpl> encoder_;
};
TEST_F(NetEqIlbcQualityTest, Test) {
diff --git a/webrtc/test/fuzzers/audio_decoder_ilbc_fuzzer.cc b/webrtc/test/fuzzers/audio_decoder_ilbc_fuzzer.cc
index b3bc434..fbc9d66 100644
--- a/webrtc/test/fuzzers/audio_decoder_ilbc_fuzzer.cc
+++ b/webrtc/test/fuzzers/audio_decoder_ilbc_fuzzer.cc
@@ -13,7 +13,7 @@
namespace webrtc {
void FuzzOneInput(const uint8_t* data, size_t size) {
- AudioDecoderIlbc dec;
+ AudioDecoderIlbcImpl dec;
static const int kSampleRateHz = 8000;
static const size_t kAllocatedOuputSizeSamples = kSampleRateHz / 10;
int16_t output[kAllocatedOuputSizeSamples];