From 327af331515570a44f30a1f6ea102c65029a7719 Mon Sep 17 00:00:00 2001 From: kwiberg Date: Fri, 18 Aug 2017 04:09:40 -0700 Subject: [PATCH] iSAC fixed-point implementation of the Audio{En,De}coderFactoryTemplate APIs BUG=webrtc:7835, webrtc:7841 Review-Url: https://codereview.webrtc.org/2996693002 Cr-Commit-Position: refs/heads/master@{#19409} --- webrtc/api/audio_codecs/isac/BUILD.gn | 39 ++++++++++++ .../isac/audio_decoder_isac_fix.cc | 37 +++++++++++ .../isac/audio_decoder_isac_fix.h | 36 +++++++++++ .../isac/audio_encoder_isac_fix.cc | 61 +++++++++++++++++++ .../isac/audio_encoder_isac_fix.h | 41 +++++++++++++ webrtc/api/audio_codecs/test/BUILD.gn | 2 + ...audio_decoder_factory_template_unittest.cc | 14 +++++ ...audio_encoder_factory_template_unittest.cc | 21 +++++++ 8 files changed, 251 insertions(+) create mode 100644 webrtc/api/audio_codecs/isac/BUILD.gn create mode 100644 webrtc/api/audio_codecs/isac/audio_decoder_isac_fix.cc create mode 100644 webrtc/api/audio_codecs/isac/audio_decoder_isac_fix.h create mode 100644 webrtc/api/audio_codecs/isac/audio_encoder_isac_fix.cc create mode 100644 webrtc/api/audio_codecs/isac/audio_encoder_isac_fix.h diff --git a/webrtc/api/audio_codecs/isac/BUILD.gn b/webrtc/api/audio_codecs/isac/BUILD.gn new file mode 100644 index 0000000000..164babf92c --- /dev/null +++ b/webrtc/api/audio_codecs/isac/BUILD.gn @@ -0,0 +1,39 @@ +# 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_static_library("audio_encoder_isac_fix") { + sources = [ + "audio_encoder_isac_fix.cc", + "audio_encoder_isac_fix.h", + ] + deps = [ + "..:audio_codecs_api", + "../../..:webrtc_common", + "../../../modules/audio_coding:isac_fix", + "../../../rtc_base:rtc_base_approved", + ] +} + +rtc_static_library("audio_decoder_isac_fix") { + sources = [ + "audio_decoder_isac_fix.cc", + "audio_decoder_isac_fix.h", + ] + deps = [ + "..:audio_codecs_api", + "../../..:webrtc_common", + "../../../modules/audio_coding:isac_fix", + "../../../rtc_base:rtc_base_approved", + ] +} diff --git a/webrtc/api/audio_codecs/isac/audio_decoder_isac_fix.cc b/webrtc/api/audio_codecs/isac/audio_decoder_isac_fix.cc new file mode 100644 index 0000000000..ef8655fc25 --- /dev/null +++ b/webrtc/api/audio_codecs/isac/audio_decoder_isac_fix.cc @@ -0,0 +1,37 @@ +/* + * 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/isac/audio_decoder_isac_fix.h" + +#include "webrtc/common_types.h" +#include "webrtc/modules/audio_coding/codecs/isac/fix/include/audio_decoder_isacfix.h" +#include "webrtc/rtc_base/ptr_util.h" + +namespace webrtc { + +rtc::Optional AudioDecoderIsacFix::SdpToConfig( + const SdpAudioFormat& format) { + return STR_CASE_CMP(format.name.c_str(), "ISAC") == 0 && + format.clockrate_hz == 16000 && format.num_channels == 1 + ? rtc::Optional(Config()) + : rtc::Optional(); +} + +void AudioDecoderIsacFix::AppendSupportedDecoders( + std::vector* specs) { + specs->push_back({{"ISAC", 16000, 1}, {16000, 1, 32000, 10000, 32000}}); +} + +std::unique_ptr AudioDecoderIsacFix::MakeAudioDecoder( + Config config) { + return rtc::MakeUnique(16000); +} + +} // namespace webrtc diff --git a/webrtc/api/audio_codecs/isac/audio_decoder_isac_fix.h b/webrtc/api/audio_codecs/isac/audio_decoder_isac_fix.h new file mode 100644 index 0000000000..71e7cc41f2 --- /dev/null +++ b/webrtc/api/audio_codecs/isac/audio_decoder_isac_fix.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_ISAC_AUDIO_DECODER_ISAC_FIX_H_ +#define WEBRTC_API_AUDIO_CODECS_ISAC_AUDIO_DECODER_ISAC_FIX_H_ + +#include +#include + +#include "webrtc/api/audio_codecs/audio_decoder.h" +#include "webrtc/api/audio_codecs/audio_format.h" +#include "webrtc/rtc_base/optional.h" + +namespace webrtc { + +// iSAC decoder API (fixed-point implementation) for use as a template +// parameter to CreateAudioDecoderFactory<...>(). +// +// NOTE: This struct is still under development and may change without notice. +struct AudioDecoderIsacFix { + struct Config {}; // Empty---no config values needed! + static rtc::Optional SdpToConfig(const SdpAudioFormat& audio_format); + static void AppendSupportedDecoders(std::vector* specs); + static std::unique_ptr MakeAudioDecoder(Config config); +}; + +} // namespace webrtc + +#endif // WEBRTC_API_AUDIO_CODECS_ISAC_AUDIO_DECODER_ISAC_FIX_H_ diff --git a/webrtc/api/audio_codecs/isac/audio_encoder_isac_fix.cc b/webrtc/api/audio_codecs/isac/audio_encoder_isac_fix.cc new file mode 100644 index 0000000000..c07957d984 --- /dev/null +++ b/webrtc/api/audio_codecs/isac/audio_encoder_isac_fix.cc @@ -0,0 +1,61 @@ +/* + * 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/isac/audio_encoder_isac_fix.h" + +#include "webrtc/common_types.h" +#include "webrtc/modules/audio_coding/codecs/isac/fix/include/audio_encoder_isacfix.h" +#include "webrtc/rtc_base/ptr_util.h" +#include "webrtc/rtc_base/string_to_number.h" + +namespace webrtc { + +rtc::Optional AudioEncoderIsacFix::SdpToConfig( + const SdpAudioFormat& format) { + if (STR_CASE_CMP(format.name.c_str(), "ISAC") == 0 && + format.clockrate_hz == 16000 && format.num_channels == 1) { + Config config; + const auto ptime_iter = format.parameters.find("ptime"); + if (ptime_iter != format.parameters.end()) { + const auto ptime = rtc::StringToNumber(ptime_iter->second); + if (ptime && *ptime >= 60) { + config.frame_size_ms = 60; + } + } + return rtc::Optional(config); + } else { + return rtc::Optional(); + } +} + +void AudioEncoderIsacFix::AppendSupportedEncoders( + std::vector* specs) { + const SdpAudioFormat fmt = {"ISAC", 16000, 1}; + const AudioCodecInfo info = QueryAudioEncoder(*SdpToConfig(fmt)); + specs->push_back({fmt, info}); +} + +AudioCodecInfo AudioEncoderIsacFix::QueryAudioEncoder( + AudioEncoderIsacFix::Config config) { + RTC_DCHECK(config.IsOk()); + return {16000, 1, 32000, 10000, 32000}; +} + +std::unique_ptr AudioEncoderIsacFix::MakeAudioEncoder( + AudioEncoderIsacFix::Config config, + int payload_type) { + RTC_DCHECK(config.IsOk()); + AudioEncoderIsacFixImpl::Config c; + c.frame_size_ms = config.frame_size_ms; + c.payload_type = payload_type; + return rtc::MakeUnique(c); +} + +} // namespace webrtc diff --git a/webrtc/api/audio_codecs/isac/audio_encoder_isac_fix.h b/webrtc/api/audio_codecs/isac/audio_encoder_isac_fix.h new file mode 100644 index 0000000000..5f0e8fe4b5 --- /dev/null +++ b/webrtc/api/audio_codecs/isac/audio_encoder_isac_fix.h @@ -0,0 +1,41 @@ +/* + * 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_ISAC_AUDIO_ENCODER_ISAC_FIX_H_ +#define WEBRTC_API_AUDIO_CODECS_ISAC_AUDIO_ENCODER_ISAC_FIX_H_ + +#include +#include + +#include "webrtc/api/audio_codecs/audio_encoder.h" +#include "webrtc/api/audio_codecs/audio_format.h" +#include "webrtc/rtc_base/optional.h" + +namespace webrtc { + +// iSAC encoder API (fixed-point implementation) for use as a template +// parameter to CreateAudioEncoderFactory<...>(). +// +// NOTE: This struct is still under development and may change without notice. +struct AudioEncoderIsacFix { + struct Config { + bool IsOk() const { return frame_size_ms == 30 || frame_size_ms == 60; } + int frame_size_ms = 30; + }; + static rtc::Optional SdpToConfig(const SdpAudioFormat& audio_format); + static void AppendSupportedEncoders(std::vector* specs); + static AudioCodecInfo QueryAudioEncoder(Config config); + static std::unique_ptr MakeAudioEncoder(Config config, + int payload_type); +}; + +} // namespace webrtc + +#endif // WEBRTC_API_AUDIO_CODECS_ISAC_AUDIO_ENCODER_ISAC_FIX_H_ diff --git a/webrtc/api/audio_codecs/test/BUILD.gn b/webrtc/api/audio_codecs/test/BUILD.gn index 882ac033e7..ce6ed92544 100644 --- a/webrtc/api/audio_codecs/test/BUILD.gn +++ b/webrtc/api/audio_codecs/test/BUILD.gn @@ -33,6 +33,8 @@ if (rtc_include_tests) { "../g722:audio_encoder_g722", "../ilbc:audio_decoder_ilbc", "../ilbc:audio_encoder_ilbc", + "../isac:audio_decoder_isac_fix", + "../isac:audio_encoder_isac_fix", "../opus:audio_decoder_opus", "../opus:audio_encoder_opus", "//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 da261ac5b3..c27f24218b 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 @@ -13,6 +13,7 @@ #include "webrtc/api/audio_codecs/g711/audio_decoder_g711.h" #include "webrtc/api/audio_codecs/g722/audio_decoder_g722.h" #include "webrtc/api/audio_codecs/ilbc/audio_decoder_ilbc.h" +#include "webrtc/api/audio_codecs/isac/audio_decoder_isac_fix.h" #include "webrtc/api/audio_codecs/opus/audio_decoder_opus.h" #include "webrtc/rtc_base/ptr_util.h" #include "webrtc/test/gmock.h" @@ -166,6 +167,19 @@ TEST(AudioDecoderFactoryTemplateTest, Ilbc) { EXPECT_EQ(8000, dec->SampleRateHz()); } +TEST(AudioDecoderFactoryTemplateTest, IsacFix) { + auto factory = CreateAudioDecoderFactory(); + EXPECT_THAT(factory->GetSupportedDecoders(), + testing::ElementsAre(AudioCodecSpec{ + {"ISAC", 16000, 1}, {16000, 1, 32000, 10000, 32000}})); + EXPECT_FALSE(factory->IsSupportedDecoder({"isac", 16000, 2})); + EXPECT_TRUE(factory->IsSupportedDecoder({"isac", 16000, 1})); + EXPECT_EQ(nullptr, factory->MakeAudioDecoder({"isac", 8000, 1})); + auto dec = factory->MakeAudioDecoder({"isac", 16000, 1}); + ASSERT_NE(nullptr, dec); + EXPECT_EQ(16000, dec->SampleRateHz()); +} + TEST(AudioDecoderFactoryTemplateTest, L16) { auto factory = CreateAudioDecoderFactory(); EXPECT_THAT( 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 19c3071bef..4120978291 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 @@ -13,6 +13,7 @@ #include "webrtc/api/audio_codecs/g711/audio_encoder_g711.h" #include "webrtc/api/audio_codecs/g722/audio_encoder_g722.h" #include "webrtc/api/audio_codecs/ilbc/audio_encoder_ilbc.h" +#include "webrtc/api/audio_codecs/isac/audio_encoder_isac_fix.h" #include "webrtc/api/audio_codecs/opus/audio_encoder_opus.h" #include "webrtc/rtc_base/ptr_util.h" #include "webrtc/test/gmock.h" @@ -171,6 +172,26 @@ TEST(AudioEncoderFactoryTemplateTest, Ilbc) { EXPECT_EQ(8000, enc->SampleRateHz()); } +TEST(AudioEncoderFactoryTemplateTest, IsacFix) { + auto factory = CreateAudioEncoderFactory(); + EXPECT_THAT(factory->GetSupportedEncoders(), + testing::ElementsAre(AudioCodecSpec{ + {"ISAC", 16000, 1}, {16000, 1, 32000, 10000, 32000}})); + EXPECT_EQ(rtc::Optional(), + factory->QueryAudioEncoder({"isac", 16000, 2})); + EXPECT_EQ(rtc::Optional({16000, 1, 32000, 10000, 32000}), + factory->QueryAudioEncoder({"isac", 16000, 1})); + EXPECT_EQ(nullptr, factory->MakeAudioEncoder(17, {"isac", 8000, 1})); + auto enc1 = factory->MakeAudioEncoder(17, {"isac", 16000, 1}); + ASSERT_NE(nullptr, enc1); + EXPECT_EQ(16000, enc1->SampleRateHz()); + EXPECT_EQ(3u, enc1->Num10MsFramesInNextPacket()); + auto enc2 = + factory->MakeAudioEncoder(17, {"isac", 16000, 1, {{"ptime", "60"}}}); + ASSERT_NE(nullptr, enc2); + EXPECT_EQ(6u, enc2->Num10MsFramesInNextPacket()); +} + TEST(AudioEncoderFactoryTemplateTest, L16) { auto factory = CreateAudioEncoderFactory(); EXPECT_THAT(