blob: 4f02edaa83744c193b0e742ec22f78738e3e8eba [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
andrew@webrtc.org63a50982012-05-02 23:56:37 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_coding/test/TestVADDTX.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
minyue@webrtc.org05617162015-03-03 12:02:30 +000013#include <string>
kjellander@webrtc.org5490c712011-12-21 13:34:18 +000014
Karl Wiberg895ce822018-10-01 17:26:11 +020015#include "api/audio_codecs/audio_decoder_factory_template.h"
16#include "api/audio_codecs/audio_encoder_factory_template.h"
17#include "api/audio_codecs/ilbc/audio_decoder_ilbc.h"
18#include "api/audio_codecs/ilbc/audio_encoder_ilbc.h"
19#include "api/audio_codecs/isac/audio_decoder_isac_float.h"
20#include "api/audio_codecs/isac/audio_encoder_isac_float.h"
21#include "api/audio_codecs/opus/audio_decoder_opus.h"
22#include "api/audio_codecs/opus/audio_encoder_opus.h"
23#include "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "modules/audio_coding/test/PCMFile.h"
25#include "modules/audio_coding/test/utility.h"
Jonas Olsson366a50c2018-09-06 13:41:30 +020026#include "rtc_base/strings/string_builder.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020027#include "test/testsupport/fileutils.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000028
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000029namespace webrtc {
niklase@google.com470e71d2011-07-07 08:21:25 +000030
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000031ActivityMonitor::ActivityMonitor() {
minyue@webrtc.org05617162015-03-03 12:02:30 +000032 ResetStatistics();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000033}
34
henrik.lundin@webrtc.orge9217b42015-03-06 07:50:34 +000035int32_t ActivityMonitor::InFrameType(FrameType frame_type) {
minyue@webrtc.org05617162015-03-03 12:02:30 +000036 counter_[frame_type]++;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000037 return 0;
38}
39
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +000040void ActivityMonitor::PrintStatistics() {
41 printf("\n");
pbos22993e12015-10-19 02:39:06 -070042 printf("kEmptyFrame %u\n", counter_[kEmptyFrame]);
henrik.lundin@webrtc.orge9217b42015-03-06 07:50:34 +000043 printf("kAudioFrameSpeech %u\n", counter_[kAudioFrameSpeech]);
44 printf("kAudioFrameCN %u\n", counter_[kAudioFrameCN]);
45 printf("kVideoFrameKey %u\n", counter_[kVideoFrameKey]);
46 printf("kVideoFrameDelta %u\n", counter_[kVideoFrameDelta]);
tina.legrand@webrtc.orgee92b662013-08-27 07:33:51 +000047 printf("\n\n");
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000048}
49
50void ActivityMonitor::ResetStatistics() {
minyue@webrtc.org05617162015-03-03 12:02:30 +000051 memset(counter_, 0, sizeof(counter_));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000052}
53
minyue@webrtc.org05617162015-03-03 12:02:30 +000054void ActivityMonitor::GetStatistics(uint32_t* counter) {
55 memcpy(counter, counter_, sizeof(counter_));
56}
57
58TestVadDtx::TestVadDtx()
Karl Wiberg895ce822018-10-01 17:26:11 +020059 : encoder_factory_(CreateAudioEncoderFactory<AudioEncoderIlbc,
60 AudioEncoderIsacFloat,
61 AudioEncoderOpus>()),
62 decoder_factory_(CreateAudioDecoderFactory<AudioDecoderIlbc,
63 AudioDecoderIsacFloat,
64 AudioDecoderOpus>()),
65 acm_send_(AudioCodingModule::Create(
66 AudioCodingModule::Config(decoder_factory_))),
Karl Wiberg5817d3d2018-04-06 10:06:42 +020067 acm_receive_(AudioCodingModule::Create(
Karl Wiberg895ce822018-10-01 17:26:11 +020068 AudioCodingModule::Config(decoder_factory_))),
minyue@webrtc.org05617162015-03-03 12:02:30 +000069 channel_(new Channel),
70 monitor_(new ActivityMonitor) {
71 EXPECT_EQ(0, acm_send_->RegisterTransportCallback(channel_.get()));
72 channel_->RegisterReceiverACM(acm_receive_.get());
73 EXPECT_EQ(0, acm_send_->RegisterVADCallback(monitor_.get()));
minyue@webrtc.org05617162015-03-03 12:02:30 +000074}
75
Karl Wiberg895ce822018-10-01 17:26:11 +020076bool TestVadDtx::RegisterCodec(const SdpAudioFormat& codec_format,
77 absl::optional<Vad::Aggressiveness> vad_mode) {
78 constexpr int payload_type = 17, cn_payload_type = 117;
79 bool added_comfort_noise = false;
80
81 auto encoder = encoder_factory_->MakeAudioEncoder(payload_type, codec_format,
82 absl::nullopt);
83 if (vad_mode.has_value() &&
84 STR_CASE_CMP(codec_format.name.c_str(), "opus") != 0) {
85 AudioEncoderCng::Config config;
86 config.speech_encoder = std::move(encoder);
87 config.num_channels = 1;
88 config.payload_type = cn_payload_type;
89 config.vad_mode = vad_mode.value();
90 encoder = absl::make_unique<AudioEncoderCng>(std::move(config));
91 added_comfort_noise = true;
92 }
93 channel_->SetIsStereo(encoder->NumChannels() > 1);
94 acm_send_->SetEncoder(std::move(encoder));
95
96 EXPECT_EQ(true,
97 acm_receive_->RegisterReceiveCodec(payload_type, codec_format));
98 return added_comfort_noise;
minyue@webrtc.org05617162015-03-03 12:02:30 +000099}
100
101// Encoding a file and see if the numbers that various packets occur follow
102// the expectation.
Yves Gerey665174f2018-06-19 15:03:05 +0200103void TestVadDtx::Run(std::string in_filename,
104 int frequency,
105 int channels,
106 std::string out_filename,
107 bool append,
minyue@webrtc.org05617162015-03-03 12:02:30 +0000108 const int* expects) {
109 monitor_->ResetStatistics();
110
111 PCMFile in_file;
112 in_file.Open(in_filename, frequency, "rb");
113 in_file.ReadStereo(channels > 1);
Henrik Lundin4d682082015-12-10 16:24:39 +0100114 // Set test length to 1000 ms (100 blocks of 10 ms each).
115 in_file.SetNum10MsBlocksToRead(100);
116 // Fast-forward both files 500 ms (50 blocks). The first second of the file is
117 // silence, but we want to keep half of that to test silence periods.
118 in_file.FastForward(50);
minyue@webrtc.org05617162015-03-03 12:02:30 +0000119
120 PCMFile out_file;
121 if (append) {
122 out_file.Open(out_filename, kOutputFreqHz, "ab");
123 } else {
124 out_file.Open(out_filename, kOutputFreqHz, "wb");
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000125 }
minyue@webrtc.org05617162015-03-03 12:02:30 +0000126
127 uint16_t frame_size_samples = in_file.PayloadLength10Ms();
minyue@webrtc.org05617162015-03-03 12:02:30 +0000128 AudioFrame audio_frame;
129 while (!in_file.EndOfFile()) {
130 in_file.Read10MsData(audio_frame);
ossu63fb95a2016-07-06 09:34:22 -0700131 audio_frame.timestamp_ = time_stamp_;
132 time_stamp_ += frame_size_samples;
minyue@webrtc.org05617162015-03-03 12:02:30 +0000133 EXPECT_GE(acm_send_->Add10MsData(audio_frame), 0);
henrik.lundind4ccb002016-05-17 12:21:55 -0700134 bool muted;
135 acm_receive_->PlayoutData10Ms(kOutputFreqHz, &audio_frame, &muted);
136 ASSERT_FALSE(muted);
minyue@webrtc.org05617162015-03-03 12:02:30 +0000137 out_file.Write10MsData(audio_frame);
138 }
139
140 in_file.Close();
141 out_file.Close();
142
143#ifdef PRINT_STAT
144 monitor_->PrintStatistics();
145#endif
146
henrik.lundin@webrtc.orge9217b42015-03-06 07:50:34 +0000147 uint32_t stats[5];
minyue@webrtc.org05617162015-03-03 12:02:30 +0000148 monitor_->GetStatistics(stats);
149 monitor_->ResetStatistics();
150
henrik.lundin@webrtc.orge9217b42015-03-06 07:50:34 +0000151 for (const auto& st : stats) {
152 int i = &st - stats; // Calculate the current position in stats.
minyue@webrtc.org05617162015-03-03 12:02:30 +0000153 switch (expects[i]) {
154 case 0: {
henrik.lundin@webrtc.orge9217b42015-03-06 07:50:34 +0000155 EXPECT_EQ(0u, st) << "stats[" << i << "] error.";
minyue@webrtc.org05617162015-03-03 12:02:30 +0000156 break;
157 }
158 case 1: {
henrik.lundin@webrtc.orge9217b42015-03-06 07:50:34 +0000159 EXPECT_GT(st, 0u) << "stats[" << i << "] error.";
minyue@webrtc.org05617162015-03-03 12:02:30 +0000160 break;
161 }
162 }
163 }
164}
165
166// Following is the implementation of TestWebRtcVadDtx.
Karl Wiberg895ce822018-10-01 17:26:11 +0200167TestWebRtcVadDtx::TestWebRtcVadDtx() : output_file_num_(0) {}
minyue@webrtc.org05617162015-03-03 12:02:30 +0000168
169void TestWebRtcVadDtx::Perform() {
Karl Wiberg895ce822018-10-01 17:26:11 +0200170 RunTestCases({"ISAC", 16000, 1});
171 RunTestCases({"ISAC", 32000, 1});
172 RunTestCases({"ILBC", 8000, 1});
173 RunTestCases({"opus", 48000, 2});
minyue@webrtc.org05617162015-03-03 12:02:30 +0000174}
175
176// Test various configurations on VAD/DTX.
Karl Wiberg895ce822018-10-01 17:26:11 +0200177void TestWebRtcVadDtx::RunTestCases(const SdpAudioFormat& codec_format) {
178 Test(/*new_outfile=*/true,
179 /*expect_dtx_enabled=*/RegisterCodec(codec_format, absl::nullopt));
minyue@webrtc.org05617162015-03-03 12:02:30 +0000180
Karl Wiberg895ce822018-10-01 17:26:11 +0200181 Test(/*new_outfile=*/false,
182 /*expect_dtx_enabled=*/RegisterCodec(codec_format, Vad::kVadAggressive));
minyue@webrtc.org05617162015-03-03 12:02:30 +0000183
Karl Wiberg895ce822018-10-01 17:26:11 +0200184 Test(/*new_outfile=*/false,
185 /*expect_dtx_enabled=*/RegisterCodec(codec_format, Vad::kVadLowBitrate));
minyue@webrtc.org05617162015-03-03 12:02:30 +0000186
Karl Wiberg895ce822018-10-01 17:26:11 +0200187 Test(/*new_outfile=*/false, /*expect_dtx_enabled=*/RegisterCodec(
188 codec_format, Vad::kVadVeryAggressive));
minyue@webrtc.org05617162015-03-03 12:02:30 +0000189
Karl Wiberg895ce822018-10-01 17:26:11 +0200190 Test(/*new_outfile=*/false,
191 /*expect_dtx_enabled=*/RegisterCodec(codec_format, Vad::kVadNormal));
minyue@webrtc.org05617162015-03-03 12:02:30 +0000192}
193
194// Set the expectation and run the test.
Karl Wiberg895ce822018-10-01 17:26:11 +0200195void TestWebRtcVadDtx::Test(bool new_outfile, bool expect_dtx_enabled) {
196 int expects[] = {-1, 1, expect_dtx_enabled, 0, 0};
minyue@webrtc.org05617162015-03-03 12:02:30 +0000197 if (new_outfile) {
198 output_file_num_++;
199 }
Jonas Olsson366a50c2018-09-06 13:41:30 +0200200 rtc::StringBuilder out_filename;
Yves Gerey665174f2018-06-19 15:03:05 +0200201 out_filename << webrtc::test::OutputPath() << "testWebRtcVadDtx_outFile_"
202 << output_file_num_ << ".pcm";
203 Run(webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm"), 32000, 1,
204 out_filename.str(), !new_outfile, expects);
minyue@webrtc.org05617162015-03-03 12:02:30 +0000205}
206
minyue@webrtc.org05617162015-03-03 12:02:30 +0000207// Following is the implementation of TestOpusDtx.
208void TestOpusDtx::Perform() {
kwiberg44307632015-12-16 06:24:05 -0800209 // If we set other codec than Opus, DTX cannot be switched on.
Karl Wiberg895ce822018-10-01 17:26:11 +0200210 RegisterCodec({"ISAC", 16000, 1}, absl::nullopt);
Minyue Li092041c2015-05-11 12:19:35 +0200211 EXPECT_EQ(-1, acm_send_->EnableOpusDtx());
kwiberg44307632015-12-16 06:24:05 -0800212 EXPECT_EQ(0, acm_send_->DisableOpusDtx());
minyue@webrtc.orge16bfde2015-03-12 15:28:41 +0000213
henrik.lundin@webrtc.orge9217b42015-03-06 07:50:34 +0000214 int expects[] = {0, 1, 0, 0, 0};
minyue@webrtc.org05617162015-03-03 12:02:30 +0000215
216 // Register Opus as send codec
Yves Gerey665174f2018-06-19 15:03:05 +0200217 std::string out_filename =
218 webrtc::test::OutputPath() + "testOpusDtx_outFile_mono.pcm";
Karl Wiberg895ce822018-10-01 17:26:11 +0200219 RegisterCodec({"opus", 48000, 2}, absl::nullopt);
minyue@webrtc.org05617162015-03-03 12:02:30 +0000220 EXPECT_EQ(0, acm_send_->DisableOpusDtx());
221
Yves Gerey665174f2018-06-19 15:03:05 +0200222 Run(webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm"), 32000, 1,
223 out_filename, false, expects);
minyue@webrtc.org05617162015-03-03 12:02:30 +0000224
Minyue Li092041c2015-05-11 12:19:35 +0200225 EXPECT_EQ(0, acm_send_->EnableOpusDtx());
pbos22993e12015-10-19 02:39:06 -0700226 expects[kEmptyFrame] = 1;
Gustaf Ullberg36de62e2017-11-20 14:55:41 +0100227 expects[kAudioFrameCN] = 1;
Yves Gerey665174f2018-06-19 15:03:05 +0200228 Run(webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm"), 32000, 1,
229 out_filename, true, expects);
minyue@webrtc.org05617162015-03-03 12:02:30 +0000230
231 // Register stereo Opus as send codec
232 out_filename = webrtc::test::OutputPath() + "testOpusDtx_outFile_stereo.pcm";
Karl Wiberg895ce822018-10-01 17:26:11 +0200233 RegisterCodec({"opus", 48000, 2, {{"stereo", "1"}}}, absl::nullopt);
minyue@webrtc.org05617162015-03-03 12:02:30 +0000234 EXPECT_EQ(0, acm_send_->DisableOpusDtx());
pbos22993e12015-10-19 02:39:06 -0700235 expects[kEmptyFrame] = 0;
Gustaf Ullberg36de62e2017-11-20 14:55:41 +0100236 expects[kAudioFrameCN] = 0;
Yves Gerey665174f2018-06-19 15:03:05 +0200237 Run(webrtc::test::ResourcePath("audio_coding/teststereo32kHz", "pcm"), 32000,
238 2, out_filename, false, expects);
minyue@webrtc.org05617162015-03-03 12:02:30 +0000239
Minyue Li092041c2015-05-11 12:19:35 +0200240 EXPECT_EQ(0, acm_send_->EnableOpusDtx());
minyue@webrtc.org05617162015-03-03 12:02:30 +0000241
pbos22993e12015-10-19 02:39:06 -0700242 expects[kEmptyFrame] = 1;
Gustaf Ullberg36de62e2017-11-20 14:55:41 +0100243 expects[kAudioFrameCN] = 1;
Yves Gerey665174f2018-06-19 15:03:05 +0200244 Run(webrtc::test::ResourcePath("audio_coding/teststereo32kHz", "pcm"), 32000,
245 2, out_filename, true, expects);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000246}
247
248} // namespace webrtc