From 635838bd9b57bffd40b991311f55d924b875e93c Mon Sep 17 00:00:00 2001 From: "henrik.lundin@webrtc.org" <henrik.lundin@webrtc.org> Date: Wed, 18 Feb 2015 13:15:08 +0000 Subject: [PATCH] Re-implementing AcmOpusTest as AcmGenericCodecOpusTest The old AcmOpusTest depends on the ACMOpus class, but this class was obsoleted by AudioEncoderOpus. In this CL, the test code is re-written to use AudioEncoderOpus and ACMGenericCodecWrapper instead of ACMOpus. Most of the test functionality is preserved, except for the packet loss rate tests, which where already transferred to AudioEncoderOpusTest in r8244. R=kwiberg@webrtc.org, minyue@webrtc.org Review URL: https://webrtc-codereview.appspot.com/40029004 Cr-Commit-Position: refs/heads/master@{#8410} git-svn-id: http://webrtc.googlecode.com/svn/trunk@8410 4adac7df-926f-26a2-2b94-8c16560cd09d --- .../opus/interface/audio_encoder_opus.h | 1 + .../main/acm2/acm_generic_codec.cc | 5 + .../main/acm2/acm_generic_codec.h | 3 + .../main/acm2/acm_generic_codec_opus_test.cc | 106 +++++++++++++ .../main/acm2/acm_opus_unittest.cc | 146 ------------------ webrtc/modules/modules.gyp | 2 +- 6 files changed, 116 insertions(+), 147 deletions(-) create mode 100644 webrtc/modules/audio_coding/main/acm2/acm_generic_codec_opus_test.cc delete mode 100644 webrtc/modules/audio_coding/main/acm2/acm_opus_unittest.cc 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 245e33430..d330eeba7 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 @@ -51,6 +51,7 @@ class AudioEncoderOpus final : public AudioEncoder { 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_; } protected: virtual bool EncodeInternal(uint32_t rtp_timestamp, diff --git a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc index 24fdca31c..5e9930e1c 100644 --- a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc +++ b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc @@ -1715,6 +1715,11 @@ bool ACMGenericCodecWrapper::ExternalRedNeeded() { return false; } +const AudioEncoder* ACMGenericCodecWrapper::GetAudioEncoder() const { + WriteLockScoped wl(codec_wrapper_lock_); + return encoder_; +} + void ACMGenericCodecWrapper::DestructEncoderSafe() { FATAL(); } diff --git a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h index 2154ebf93..5a36a8e28 100644 --- a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h +++ b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h @@ -1111,6 +1111,9 @@ class ACMGenericCodecWrapper : public ACMGenericCodec { bool ExternalRedNeeded() override; + // This method is only for testing. + const AudioEncoder* GetAudioEncoder() const; + protected: void DestructEncoderSafe() override EXCLUSIVE_LOCKS_REQUIRED(codec_wrapper_lock_); diff --git a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec_opus_test.cc b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec_opus_test.cc new file mode 100644 index 000000000..b7a25226a --- /dev/null +++ b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec_opus_test.cc @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2014 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/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h" +#include "webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h" + +namespace webrtc { +namespace acm2 { + +#ifdef WEBRTC_CODEC_OPUS +namespace { +const CodecInst kDefaultOpusCodecInst = {105, "opus", 48000, 960, 1, 32000}; +const int kCngPt = 255; // Not using CNG in this test. +const int kRedPt = 255; // Not using RED in this test. +} // namespace + +class AcmGenericCodecOpusTest : public ::testing::Test { + protected: + AcmGenericCodecOpusTest() { + acm_codec_params_ = {kDefaultOpusCodecInst, false, false, VADNormal}; + } + + void CreateCodec() { + codec_wrapper_.reset(new ACMGenericCodecWrapper( + acm_codec_params_.codec_inst, kCngPt, kCngPt, kCngPt, kCngPt, + false /* enable RED */, kRedPt)); + ASSERT_TRUE(codec_wrapper_); + ASSERT_EQ(0, codec_wrapper_->InitEncoder(&acm_codec_params_, true)); + } + + const AudioEncoderOpus* GetAudioEncoderOpus() { + const AudioEncoderOpus* ptr = static_cast<const AudioEncoderOpus*>( + codec_wrapper_->GetAudioEncoder()); + EXPECT_NE(nullptr, ptr); + return ptr; + } + WebRtcACMCodecParams acm_codec_params_; + scoped_ptr<ACMGenericCodecWrapper> codec_wrapper_; +}; + +TEST_F(AcmGenericCodecOpusTest, DefaultApplicationModeMono) { + acm_codec_params_.codec_inst.channels = 1; + CreateCodec(); + EXPECT_EQ(AudioEncoderOpus::kVoip, GetAudioEncoderOpus()->application()); +} + +TEST_F(AcmGenericCodecOpusTest, DefaultApplicationModeStereo) { + acm_codec_params_.codec_inst.channels = 2; + CreateCodec(); + EXPECT_EQ(AudioEncoderOpus::kAudio, GetAudioEncoderOpus()->application()); +} + +TEST_F(AcmGenericCodecOpusTest, ChangeApplicationMode) { + // Create a stereo encoder. + acm_codec_params_.codec_inst.channels = 2; + CreateCodec(); + // Verify that the mode is kAudio. + const AudioEncoderOpus* opus_ptr = GetAudioEncoderOpus(); + EXPECT_EQ(AudioEncoderOpus::kAudio, opus_ptr->application()); + + // Change mode. + EXPECT_EQ(0, codec_wrapper_->SetOpusApplication(kVoip)); + // Verify that the AudioEncoder object was changed. + EXPECT_NE(opus_ptr, GetAudioEncoderOpus()); + EXPECT_EQ(AudioEncoderOpus::kVoip, GetAudioEncoderOpus()->application()); +} + +TEST_F(AcmGenericCodecOpusTest, ResetWontChangeApplicationMode) { + // Create a stereo encoder. + acm_codec_params_.codec_inst.channels = 2; + CreateCodec(); + const AudioEncoderOpus* opus_ptr = GetAudioEncoderOpus(); + // Verify that the mode is kAudio. + EXPECT_EQ(AudioEncoderOpus::kAudio, opus_ptr->application()); + + // Trigger a reset. + ASSERT_EQ(0, codec_wrapper_->InitEncoder(&acm_codec_params_, false)); + // Verify that the AudioEncoder object changed. + EXPECT_NE(opus_ptr, GetAudioEncoderOpus()); + // Verify that the mode is still kAudio. + EXPECT_EQ(AudioEncoderOpus::kAudio, GetAudioEncoderOpus()->application()); + + // Now change to kVoip. + EXPECT_EQ(0, codec_wrapper_->SetOpusApplication(kVoip)); + EXPECT_EQ(AudioEncoderOpus::kVoip, GetAudioEncoderOpus()->application()); + + opus_ptr = GetAudioEncoderOpus(); + // Trigger a reset again. + ASSERT_EQ(0, codec_wrapper_->InitEncoder(&acm_codec_params_, false)); + // Verify that the AudioEncoder object changed. + EXPECT_NE(opus_ptr, GetAudioEncoderOpus()); + // Verify that the mode is still kVoip. + EXPECT_EQ(AudioEncoderOpus::kVoip, GetAudioEncoderOpus()->application()); +} +#endif // WEBRTC_CODEC_OPUS + +} // namespace acm2 +} // namespace webrtc diff --git a/webrtc/modules/audio_coding/main/acm2/acm_opus_unittest.cc b/webrtc/modules/audio_coding/main/acm2/acm_opus_unittest.cc deleted file mode 100644 index 2c4358fc8..000000000 --- a/webrtc/modules/audio_coding/main/acm2/acm_opus_unittest.cc +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2014 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/modules/audio_coding/main/acm2/acm_opus.h" - -#include "testing/gtest/include/gtest/gtest.h" -#include "webrtc/modules/audio_coding/main/acm2/acm_codec_database.h" - -namespace webrtc { - -namespace acm2 { - -namespace { - const CodecInst kOpusCodecInst = {105, "opus", 48000, 960, 1, 32000}; - // These constants correspond to those used in ACMOpus::SetPacketLossRate(). - const int kPacketLossRate20 = 20; - const int kPacketLossRate10 = 10; - const int kPacketLossRate5 = 5; - const int kPacketLossRate1 = 1; - const int kLossRate20Margin = 2; - const int kLossRate10Margin = 1; - const int kLossRate5Margin = 1; -} // namespace - -class AcmOpusTest : public ACMOpus { - public: - explicit AcmOpusTest(int16_t codec_id) : ACMOpus(codec_id, false) {} - ~AcmOpusTest() {} - int packet_loss_rate() { return packet_loss_rate_; } - OpusApplicationMode application() { return application_; } - bool encoder_initialized() { - ReadLockScoped cs(codec_wrapper_lock_); - return encoder_initialized_; - } - - void TestSetPacketLossRate(int from, int to, int expected_return); -}; - -#ifdef WEBRTC_CODEC_OPUS -void AcmOpusTest::TestSetPacketLossRate(int from, int to, int expected_return) { - for (int loss = from; loss <= to; (to >= from) ? ++loss : --loss) { - EXPECT_EQ(0, SetPacketLossRate(loss)); - EXPECT_EQ(expected_return, packet_loss_rate()); - } -} - -TEST(AcmOpusTest, PacketLossRateOptimized) { - AcmOpusTest opus(ACMCodecDB::kOpus); - WebRtcACMCodecParams params; - memcpy(&(params.codec_inst), &kOpusCodecInst, sizeof(CodecInst)); - EXPECT_EQ(0, opus.InitEncoder(¶ms, true)); - EXPECT_EQ(0, opus.SetFEC(true)); - - // Note that the order of the following calls is critical. - opus.TestSetPacketLossRate(0, 0, 0); - opus.TestSetPacketLossRate(kPacketLossRate1, - kPacketLossRate5 + kLossRate5Margin - 1, - kPacketLossRate1); - opus.TestSetPacketLossRate(kPacketLossRate5 + kLossRate5Margin, - kPacketLossRate10 + kLossRate10Margin - 1, - kPacketLossRate5); - opus.TestSetPacketLossRate(kPacketLossRate10 + kLossRate10Margin, - kPacketLossRate20 + kLossRate20Margin - 1, - kPacketLossRate10); - opus.TestSetPacketLossRate(kPacketLossRate20 + kLossRate20Margin, - 100, - kPacketLossRate20); - opus.TestSetPacketLossRate(kPacketLossRate20 + kLossRate20Margin, - kPacketLossRate20 - kLossRate20Margin, - kPacketLossRate20); - opus.TestSetPacketLossRate(kPacketLossRate20 - kLossRate20Margin - 1, - kPacketLossRate10 - kLossRate10Margin, - kPacketLossRate10); - opus.TestSetPacketLossRate(kPacketLossRate10 - kLossRate10Margin - 1, - kPacketLossRate5 - kLossRate5Margin, - kPacketLossRate5); - opus.TestSetPacketLossRate(kPacketLossRate5 - kLossRate5Margin - 1, - kPacketLossRate1, - kPacketLossRate1); - opus.TestSetPacketLossRate(0, 0, 0); -} - -TEST(AcmOpusTest, DefaultApplicationMode) { - AcmOpusTest opus(ACMCodecDB::kOpus); - WebRtcACMCodecParams params; - memcpy(&(params.codec_inst), &kOpusCodecInst, sizeof(CodecInst)); - - params.codec_inst.channels = 2; - // Codec is not initialized, and hence without force initialization (2nd - // argument being false), an initialization will take place. - EXPECT_FALSE(opus.encoder_initialized()); - EXPECT_EQ(0, opus.InitEncoder(¶ms, false)); - EXPECT_EQ(kAudio, opus.application()); - - params.codec_inst.channels = 1; - EXPECT_EQ(0, opus.InitEncoder(¶ms, true)); - EXPECT_EQ(kVoip, opus.application()); -} - -TEST(AcmOpusTest, ChangeApplicationMode) { - AcmOpusTest opus(ACMCodecDB::kOpus); - WebRtcACMCodecParams params; - memcpy(&(params.codec_inst), &kOpusCodecInst, sizeof(CodecInst)); - - params.codec_inst.channels = 2; - // Codec is not initialized, and hence without force initialization (2nd - // argument being false), an initialization will take place. - EXPECT_EQ(0, opus.InitEncoder(¶ms, false)); - EXPECT_EQ(kAudio, opus.application()); - - opus.SetOpusApplication(kVoip); - EXPECT_EQ(kVoip, opus.application()); -} - -TEST(AcmOpusTest, ResetWontChangeApplicationMode) { - AcmOpusTest opus(ACMCodecDB::kOpus); - WebRtcACMCodecParams params; - memcpy(&(params.codec_inst), &kOpusCodecInst, sizeof(CodecInst)); - - params.codec_inst.channels = 2; - // Codec is not initialized, and hence without force initialization (2nd - // argument being false), an initialization will take place. - EXPECT_EQ(0, opus.InitEncoder(¶ms, false)); - EXPECT_EQ(kAudio, opus.application()); - - opus.ResetEncoder(); - EXPECT_EQ(kAudio, opus.application()); -} - -#else -void AcmOpusTest:TestSetPacketLossRate(int /* from */, int /* to */, - int /* expected_return */) { - return; -} -#endif // WEBRTC_CODEC_OPUS - -} // namespace acm2 - -} // namespace webrtc diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp index c1c8dabb2..d9f071e99 100644 --- a/webrtc/modules/modules.gyp +++ b/webrtc/modules/modules.gyp @@ -91,7 +91,7 @@ ], 'sources': [ 'audio_coding/codecs/cng/audio_encoder_cng_unittest.cc', - 'audio_coding/main/acm2/acm_opus_unittest.cc', + 'audio_coding/main/acm2/acm_generic_codec_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',