• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3  *
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 
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "webrtc/base/checks.h"
13 #include "webrtc/base/scoped_ptr.h"
14 #include "webrtc/common_types.h"
15 #include "webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.h"
16 
17 namespace webrtc {
18 
19 namespace {
20 const CodecInst kOpusSettings = {105, "opus", 48000, 960, 1, 32000};
21 }  // namespace
22 
23 class AudioEncoderOpusTest : public ::testing::Test {
24  protected:
CreateCodec(int num_channels)25   void CreateCodec(int num_channels) {
26     codec_inst_.channels = num_channels;
27     encoder_.reset(new AudioEncoderOpus(codec_inst_));
28     auto expected_app =
29         num_channels == 1 ? AudioEncoderOpus::kVoip : AudioEncoderOpus::kAudio;
30     EXPECT_EQ(expected_app, encoder_->application());
31   }
32 
33   CodecInst codec_inst_ = kOpusSettings;
34   rtc::scoped_ptr<AudioEncoderOpus> encoder_;
35 };
36 
TEST_F(AudioEncoderOpusTest,DefaultApplicationModeMono)37 TEST_F(AudioEncoderOpusTest, DefaultApplicationModeMono) {
38   CreateCodec(1);
39 }
40 
TEST_F(AudioEncoderOpusTest,DefaultApplicationModeStereo)41 TEST_F(AudioEncoderOpusTest, DefaultApplicationModeStereo) {
42   CreateCodec(2);
43 }
44 
TEST_F(AudioEncoderOpusTest,ChangeApplicationMode)45 TEST_F(AudioEncoderOpusTest, ChangeApplicationMode) {
46   CreateCodec(2);
47   EXPECT_TRUE(encoder_->SetApplication(AudioEncoder::Application::kSpeech));
48   EXPECT_EQ(AudioEncoderOpus::kVoip, encoder_->application());
49 }
50 
TEST_F(AudioEncoderOpusTest,ResetWontChangeApplicationMode)51 TEST_F(AudioEncoderOpusTest, ResetWontChangeApplicationMode) {
52   CreateCodec(2);
53 
54   // Trigger a reset.
55   encoder_->Reset();
56   // Verify that the mode is still kAudio.
57   EXPECT_EQ(AudioEncoderOpus::kAudio, encoder_->application());
58 
59   // Now change to kVoip.
60   EXPECT_TRUE(encoder_->SetApplication(AudioEncoder::Application::kSpeech));
61   EXPECT_EQ(AudioEncoderOpus::kVoip, encoder_->application());
62 
63   // Trigger a reset again.
64   encoder_->Reset();
65   // Verify that the mode is still kVoip.
66   EXPECT_EQ(AudioEncoderOpus::kVoip, encoder_->application());
67 }
68 
TEST_F(AudioEncoderOpusTest,ToggleDtx)69 TEST_F(AudioEncoderOpusTest, ToggleDtx) {
70   CreateCodec(2);
71   // Enable DTX
72   EXPECT_TRUE(encoder_->SetDtx(true));
73   // Verify that the mode is still kAudio.
74   EXPECT_EQ(AudioEncoderOpus::kAudio, encoder_->application());
75   // Turn off DTX.
76   EXPECT_TRUE(encoder_->SetDtx(false));
77 }
78 
TEST_F(AudioEncoderOpusTest,SetBitrate)79 TEST_F(AudioEncoderOpusTest, SetBitrate) {
80   CreateCodec(1);
81   // Constants are replicated from audio_encoder_opus.cc.
82   const int kMinBitrateBps = 500;
83   const int kMaxBitrateBps = 512000;
84   // Set a too low bitrate.
85   encoder_->SetTargetBitrate(kMinBitrateBps - 1);
86   EXPECT_EQ(kMinBitrateBps, encoder_->GetTargetBitrate());
87   // Set a too high bitrate.
88   encoder_->SetTargetBitrate(kMaxBitrateBps + 1);
89   EXPECT_EQ(kMaxBitrateBps, encoder_->GetTargetBitrate());
90   // Set the minimum rate.
91   encoder_->SetTargetBitrate(kMinBitrateBps);
92   EXPECT_EQ(kMinBitrateBps, encoder_->GetTargetBitrate());
93   // Set the maximum rate.
94   encoder_->SetTargetBitrate(kMaxBitrateBps);
95   EXPECT_EQ(kMaxBitrateBps, encoder_->GetTargetBitrate());
96   // Set rates from 1000 up to 32000 bps.
97   for (int rate = 1000; rate <= 32000; rate += 1000) {
98     encoder_->SetTargetBitrate(rate);
99     EXPECT_EQ(rate, encoder_->GetTargetBitrate());
100   }
101 }
102 
103 namespace {
104 
105 // Returns a vector with the n evenly-spaced numbers a, a + (b - a)/(n - 1),
106 // ..., b.
IntervalSteps(double a,double b,size_t n)107 std::vector<double> IntervalSteps(double a, double b, size_t n) {
108   RTC_DCHECK_GT(n, 1u);
109   const double step = (b - a) / (n - 1);
110   std::vector<double> points;
111   for (size_t i = 0; i < n; ++i)
112     points.push_back(a + i * step);
113   return points;
114 }
115 
116 // Sets the packet loss rate to each number in the vector in turn, and verifies
117 // that the loss rate as reported by the encoder is |expected_return| for all
118 // of them.
TestSetPacketLossRate(AudioEncoderOpus * encoder,const std::vector<double> & losses,double expected_return)119 void TestSetPacketLossRate(AudioEncoderOpus* encoder,
120                            const std::vector<double>& losses,
121                            double expected_return) {
122   for (double loss : losses) {
123     encoder->SetProjectedPacketLossRate(loss);
124     EXPECT_DOUBLE_EQ(expected_return, encoder->packet_loss_rate());
125   }
126 }
127 
128 }  // namespace
129 
TEST_F(AudioEncoderOpusTest,PacketLossRateOptimized)130 TEST_F(AudioEncoderOpusTest, PacketLossRateOptimized) {
131   CreateCodec(1);
132   auto I = [](double a, double b) { return IntervalSteps(a, b, 10); };
133   const double eps = 1e-15;
134 
135   // Note that the order of the following calls is critical.
136 
137   // clang-format off
138   TestSetPacketLossRate(encoder_.get(), I(0.00      , 0.01 - eps), 0.00);
139   TestSetPacketLossRate(encoder_.get(), I(0.01 + eps, 0.06 - eps), 0.01);
140   TestSetPacketLossRate(encoder_.get(), I(0.06 + eps, 0.11 - eps), 0.05);
141   TestSetPacketLossRate(encoder_.get(), I(0.11 + eps, 0.22 - eps), 0.10);
142   TestSetPacketLossRate(encoder_.get(), I(0.22 + eps, 1.00      ), 0.20);
143 
144   TestSetPacketLossRate(encoder_.get(), I(1.00      , 0.18 + eps), 0.20);
145   TestSetPacketLossRate(encoder_.get(), I(0.18 - eps, 0.09 + eps), 0.10);
146   TestSetPacketLossRate(encoder_.get(), I(0.09 - eps, 0.04 + eps), 0.05);
147   TestSetPacketLossRate(encoder_.get(), I(0.04 - eps, 0.01 + eps), 0.01);
148   TestSetPacketLossRate(encoder_.get(), I(0.01 - eps, 0.00      ), 0.00);
149   // clang-format on
150 }
151 
152 }  // namespace webrtc
153