diff --git a/modules/audio_coding/BUILD.gn b/modules/audio_coding/BUILD.gn index 669deebb51..8efc22107d 100644 --- a/modules/audio_coding/BUILD.gn +++ b/modules/audio_coding/BUILD.gn @@ -744,7 +744,8 @@ rtc_library("webrtc_opus") { "//third_party/abseil-cpp/absl/strings", "//third_party/abseil-cpp/absl/types:optional", ] - public_deps = [ ":webrtc_opus_wrapper" ] # no-presubmit-check TODO(webrtc:8603) + public_deps = # no-presubmit-check TODO(webrtc:8603) + [ ":webrtc_opus_wrapper" ] defines = audio_codec_defines @@ -780,7 +781,8 @@ rtc_library("webrtc_multiopus") { "//third_party/abseil-cpp/absl/strings", "//third_party/abseil-cpp/absl/types:optional", ] - public_deps = [ ":webrtc_opus_wrapper" ] # no-presubmit-check TODO(webrtc:8603) + public_deps = # no-presubmit-check TODO(webrtc:8603) + [ ":webrtc_opus_wrapper" ] defines = audio_codec_defines @@ -865,7 +867,8 @@ rtc_library("audio_network_adaptor") { "audio_network_adaptor/util/threshold_curve.h", ] - public_deps = [ ":audio_network_adaptor_config" ] # no-presubmit-check TODO(webrtc:8603) + public_deps = # no-presubmit-check TODO(webrtc:8603) + [ ":audio_network_adaptor_config" ] deps = [ "../../api/audio_codecs:audio_codecs_api", @@ -1160,7 +1163,8 @@ if (rtc_enable_protobuf) { "../rtp_rtcp:rtp_rtcp_format", "//third_party/abseil-cpp/absl/types:optional", ] - public_deps = [ "../../logging:rtc_event_log_proto" ] # no-presubmit-check TODO(webrtc:8603) + public_deps = # no-presubmit-check TODO(webrtc:8603) + [ "../../logging:rtc_event_log_proto" ] } # Only used for test purpose. Since we want to use it from chromium @@ -1911,6 +1915,7 @@ if (rtc_include_tests) { "codecs/isac/fix/source/filters_unittest.cc", "codecs/isac/fix/source/lpc_masking_model_unittest.cc", "codecs/isac/fix/source/transform_unittest.cc", + "codecs/isac/isac_webrtc_api_test.cc", "codecs/isac/main/source/audio_encoder_isac_unittest.cc", "codecs/isac/main/source/isac_unittest.cc", "codecs/legacy_encoded_audio_frame_unittest.cc", @@ -1976,6 +1981,7 @@ if (rtc_include_tests) { ":ilbc", ":isac", ":isac_c", + ":isac_common", ":isac_fix", ":legacy_encoded_audio_frame", ":mocks", @@ -1988,10 +1994,15 @@ if (rtc_include_tests) { ":webrtc_opus", "..:module_api", "..:module_api_public", + "../../api:array_view", "../../api/audio:audio_frame_api", "../../api/audio_codecs:audio_codecs_api", "../../api/audio_codecs:builtin_audio_decoder_factory", "../../api/audio_codecs:builtin_audio_encoder_factory", + "../../api/audio_codecs/isac:audio_decoder_isac_fix", + "../../api/audio_codecs/isac:audio_decoder_isac_float", + "../../api/audio_codecs/isac:audio_encoder_isac_fix", + "../../api/audio_codecs/isac:audio_encoder_isac_float", "../../api/audio_codecs/opus:audio_decoder_multiopus", "../../api/audio_codecs/opus:audio_decoder_opus", "../../api/audio_codecs/opus:audio_encoder_multiopus", diff --git a/modules/audio_coding/codecs/isac/isac_webrtc_api_test.cc b/modules/audio_coding/codecs/isac/isac_webrtc_api_test.cc new file mode 100644 index 0000000000..ac83861c87 --- /dev/null +++ b/modules/audio_coding/codecs/isac/isac_webrtc_api_test.cc @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2020 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 +#include +#include + +#include "api/array_view.h" +#include "api/audio_codecs/isac/audio_decoder_isac_fix.h" +#include "api/audio_codecs/isac/audio_decoder_isac_float.h" +#include "api/audio_codecs/isac/audio_encoder_isac_fix.h" +#include "api/audio_codecs/isac/audio_encoder_isac_float.h" +#include "rtc_base/random.h" +#include "test/gtest.h" + +namespace webrtc { +namespace { + +constexpr int kPayloadType = 42; +constexpr int kBitrateBps = 20000; + +enum class IsacImpl { kFixed, kFloat }; + +std::vector GetRandomSamplesVector(size_t size) { + constexpr int32_t kMin = std::numeric_limits::min(); + constexpr int32_t kMax = std::numeric_limits::max(); + std::vector v(size); + Random gen(/*seed=*/42); + for (auto& x : v) { + x = static_cast(gen.Rand(kMin, kMax)); + } + return v; +} + +class IsacApiTest + : public testing::TestWithParam> { + protected: + IsacApiTest() : input_frame_(GetRandomSamplesVector(GetInputFrameLength())) {} + rtc::ArrayView GetInputFrame() { return input_frame_; } + int GetSampleRateHz() const { return std::get<0>(GetParam()); } + int GetEncoderFrameLenght() const { + return GetEncoderFrameLenghtMs() * GetSampleRateHz() / 1000; + } + std::unique_ptr CreateEncoder() const { + switch (GetEncoderIsacImpl()) { + case IsacImpl::kFixed: { + AudioEncoderIsacFix::Config config; + config.frame_size_ms = GetEncoderFrameLenghtMs(); + RTC_CHECK_EQ(16000, GetSampleRateHz()); + return AudioEncoderIsacFix::MakeAudioEncoder(config, kPayloadType); + } + case IsacImpl::kFloat: { + AudioEncoderIsacFloat::Config config; + config.bit_rate = kBitrateBps; + config.frame_size_ms = GetEncoderFrameLenghtMs(); + config.sample_rate_hz = GetSampleRateHz(); + return AudioEncoderIsacFloat::MakeAudioEncoder(config, kPayloadType); + } + } + } + std::unique_ptr CreateDecoder() const { + switch (GetDecoderIsacImpl()) { + case IsacImpl::kFixed: { + webrtc::AudioDecoderIsacFix::Config config; + RTC_CHECK_EQ(16000, GetSampleRateHz()); + return webrtc::AudioDecoderIsacFix::MakeAudioDecoder(config); + } + case IsacImpl::kFloat: { + webrtc::AudioDecoderIsacFloat::Config config; + config.sample_rate_hz = GetSampleRateHz(); + return webrtc::AudioDecoderIsacFloat::MakeAudioDecoder(config); + } + } + } + + private: + const std::vector input_frame_; + int GetInputFrameLength() const { + return rtc::CheckedDivExact(std::get<0>(GetParam()), 100); // 10 ms. + } + int GetEncoderFrameLenghtMs() const { + int frame_size_ms = std::get<1>(GetParam()); + RTC_CHECK(frame_size_ms == 30 || frame_size_ms == 60); + return frame_size_ms; + } + IsacImpl GetEncoderIsacImpl() const { return std::get<2>(GetParam()); } + IsacImpl GetDecoderIsacImpl() const { return std::get<3>(GetParam()); } +}; + +// Checks that the number of encoded and decoded samples match. +TEST_P(IsacApiTest, EncodeDecode) { + auto encoder = CreateEncoder(); + auto decoder = CreateDecoder(); + const int encoder_frame_length = GetEncoderFrameLenght(); + std::vector out(encoder_frame_length); + size_t num_encoded_samples = 0; + size_t num_decoded_samples = 0; + constexpr int kNumFrames = 12; + for (int i = 0; i < kNumFrames; ++i) { + rtc::Buffer encoded; + auto in = GetInputFrame(); + encoder->Encode(/*rtp_timestamp=*/0, in, &encoded); + num_encoded_samples += in.size(); + if (encoded.empty()) { + continue; + } + // Decode. + const std::vector parse_result = + decoder->ParsePayload(std::move(encoded), /*timestamp=*/0); + EXPECT_EQ(parse_result.size(), size_t{1}); + auto decode_result = parse_result[0].frame->Decode(out); + EXPECT_TRUE(decode_result.has_value()); + EXPECT_EQ(out.size(), decode_result->num_decoded_samples); + num_decoded_samples += decode_result->num_decoded_samples; + } + EXPECT_EQ(num_encoded_samples, num_decoded_samples); +} + +// Creates tests for different encoder frame lengths and different +// encoder/decoder implementations. +INSTANTIATE_TEST_SUITE_P( + AllTest, + IsacApiTest, + ::testing::ValuesIn([] { + std::vector> cases; + for (int frame_length_ms : {30, 60}) { + for (IsacImpl enc : {IsacImpl::kFloat, IsacImpl::kFixed}) { + for (IsacImpl dec : {IsacImpl::kFloat, IsacImpl::kFixed}) { + cases.push_back({16000, frame_length_ms, enc, dec}); + } + } + } + cases.push_back({32000, 30, IsacImpl::kFloat, IsacImpl::kFloat}); + return cases; + }())); + +} // namespace +} // namespace webrtc diff --git a/modules/audio_coding/codecs/isac/main/include/isac.h b/modules/audio_coding/codecs/isac/main/include/isac.h index 6bbbf8a81e..3d2caefc23 100644 --- a/modules/audio_coding/codecs/isac/main/include/isac.h +++ b/modules/audio_coding/codecs/isac/main/include/isac.h @@ -252,7 +252,7 @@ int16_t WebRtcIsac_ControlBwe(ISACStruct* ISAC_main_inst, * */ -int16_t WebRtcIsac_ReadFrameLen(ISACStruct* ISAC_main_inst, +int16_t WebRtcIsac_ReadFrameLen(const ISACStruct* ISAC_main_inst, const uint8_t* encoded, int16_t* frameLength); diff --git a/modules/audio_coding/codecs/isac/main/source/isac.c b/modules/audio_coding/codecs/isac/main/source/isac.c index 552bab811a..73f132c228 100644 --- a/modules/audio_coding/codecs/isac/main/source/isac.c +++ b/modules/audio_coding/codecs/isac/main/source/isac.c @@ -1719,7 +1719,7 @@ int16_t WebRtcIsac_ReadBwIndex(const uint8_t* encoded, * - frameLength : Length of frame in packet (in samples) * */ -int16_t WebRtcIsac_ReadFrameLen(ISACStruct* ISAC_main_inst, +int16_t WebRtcIsac_ReadFrameLen(const ISACStruct* ISAC_main_inst, const uint8_t* encoded, int16_t* frameLength) { Bitstr streamdata;