1 /* 2 * libjingle 3 * Copyright 2004 Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "talk/base/gunit.h" 29 #include "talk/base/thread.h" 30 #include "talk/session/media/call.h" 31 #include "talk/session/media/currentspeakermonitor.h" 32 33 namespace cricket { 34 35 static const uint32 kSsrc1 = 1001; 36 static const uint32 kSsrc2 = 1002; 37 static const uint32 kMinTimeBetweenSwitches = 10; 38 // Due to limited system clock resolution, the CurrentSpeakerMonitor may 39 // actually require more or less time between switches than that specified 40 // in the call to set_min_time_between_switches. To be safe, we sleep for 41 // 90 ms more than the min time between switches before checking for a switch. 42 // I am assuming system clocks do not have a coarser resolution than 90 ms. 43 static const uint32 kSleepTimeBetweenSwitches = 100; 44 45 class MockCall : public Call { 46 public: 47 MockCall() : Call(NULL) {} 48 49 void EmitAudioMonitor(const AudioInfo& info) { 50 GetAudioSourceProxy()->SignalAudioMonitor(GetAudioSourceProxy(), info); 51 } 52 }; 53 54 class CurrentSpeakerMonitorTest : public testing::Test, 55 public sigslot::has_slots<> { 56 public: 57 CurrentSpeakerMonitorTest() { 58 call_ = new MockCall(); 59 monitor_ = new CurrentSpeakerMonitor(call_->GetAudioSourceProxy(), NULL); 60 // Shrink the minimum time betweeen switches to 10 ms so we don't have to 61 // slow down our tests. 62 monitor_->set_min_time_between_switches(kMinTimeBetweenSwitches); 63 monitor_->SignalUpdate.connect(this, &CurrentSpeakerMonitorTest::OnUpdate); 64 current_speaker_ = 0; 65 num_changes_ = 0; 66 monitor_->Start(); 67 } 68 69 ~CurrentSpeakerMonitorTest() { 70 delete monitor_; 71 delete call_; 72 } 73 74 protected: 75 MockCall* call_; 76 CurrentSpeakerMonitor* monitor_; 77 int num_changes_; 78 uint32 current_speaker_; 79 80 void OnUpdate(CurrentSpeakerMonitor* monitor, uint32 current_speaker) { 81 current_speaker_ = current_speaker; 82 num_changes_++; 83 } 84 }; 85 86 static void InitAudioInfo(AudioInfo* info, int input_level, int output_level) { 87 info->input_level = input_level; 88 info->output_level = output_level; 89 } 90 91 TEST_F(CurrentSpeakerMonitorTest, NoActiveStreams) { 92 AudioInfo info; 93 InitAudioInfo(&info, 0, 0); 94 call_->EmitAudioMonitor(info); 95 96 EXPECT_EQ(current_speaker_, 0U); 97 EXPECT_EQ(num_changes_, 0); 98 } 99 100 TEST_F(CurrentSpeakerMonitorTest, MultipleActiveStreams) { 101 AudioInfo info; 102 InitAudioInfo(&info, 0, 0); 103 104 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); 105 info.active_streams.push_back(std::make_pair(kSsrc2, 7)); 106 call_->EmitAudioMonitor(info); 107 108 // No speaker recognized because the initial sample is treated as possibly 109 // just noise and disregarded. 110 EXPECT_EQ(current_speaker_, 0U); 111 EXPECT_EQ(num_changes_, 0); 112 113 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); 114 info.active_streams.push_back(std::make_pair(kSsrc2, 7)); 115 call_->EmitAudioMonitor(info); 116 117 EXPECT_EQ(current_speaker_, kSsrc2); 118 EXPECT_EQ(num_changes_, 1); 119 } 120 121 // See: https://code.google.com/p/webrtc/issues/detail?id=2409 122 TEST_F(CurrentSpeakerMonitorTest, DISABLED_RapidSpeakerChange) { 123 AudioInfo info; 124 InitAudioInfo(&info, 0, 0); 125 126 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); 127 info.active_streams.push_back(std::make_pair(kSsrc2, 7)); 128 call_->EmitAudioMonitor(info); 129 130 EXPECT_EQ(current_speaker_, 0U); 131 EXPECT_EQ(num_changes_, 0); 132 133 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); 134 info.active_streams.push_back(std::make_pair(kSsrc2, 7)); 135 call_->EmitAudioMonitor(info); 136 137 EXPECT_EQ(current_speaker_, kSsrc2); 138 EXPECT_EQ(num_changes_, 1); 139 140 info.active_streams.push_back(std::make_pair(kSsrc1, 9)); 141 info.active_streams.push_back(std::make_pair(kSsrc2, 1)); 142 call_->EmitAudioMonitor(info); 143 144 // We expect no speaker change because of the rapid change. 145 EXPECT_EQ(current_speaker_, kSsrc2); 146 EXPECT_EQ(num_changes_, 1); 147 } 148 149 TEST_F(CurrentSpeakerMonitorTest, SpeakerChange) { 150 AudioInfo info; 151 InitAudioInfo(&info, 0, 0); 152 153 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); 154 info.active_streams.push_back(std::make_pair(kSsrc2, 7)); 155 call_->EmitAudioMonitor(info); 156 157 EXPECT_EQ(current_speaker_, 0U); 158 EXPECT_EQ(num_changes_, 0); 159 160 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); 161 info.active_streams.push_back(std::make_pair(kSsrc2, 7)); 162 call_->EmitAudioMonitor(info); 163 164 EXPECT_EQ(current_speaker_, kSsrc2); 165 EXPECT_EQ(num_changes_, 1); 166 167 // Wait so the changes don't come so rapidly. 168 talk_base::Thread::SleepMs(kSleepTimeBetweenSwitches); 169 170 info.active_streams.push_back(std::make_pair(kSsrc1, 9)); 171 info.active_streams.push_back(std::make_pair(kSsrc2, 1)); 172 call_->EmitAudioMonitor(info); 173 174 EXPECT_EQ(current_speaker_, kSsrc1); 175 EXPECT_EQ(num_changes_, 2); 176 } 177 178 TEST_F(CurrentSpeakerMonitorTest, InterwordSilence) { 179 AudioInfo info; 180 InitAudioInfo(&info, 0, 0); 181 182 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); 183 info.active_streams.push_back(std::make_pair(kSsrc2, 7)); 184 call_->EmitAudioMonitor(info); 185 186 EXPECT_EQ(current_speaker_, 0U); 187 EXPECT_EQ(num_changes_, 0); 188 189 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); 190 info.active_streams.push_back(std::make_pair(kSsrc2, 7)); 191 call_->EmitAudioMonitor(info); 192 193 EXPECT_EQ(current_speaker_, kSsrc2); 194 EXPECT_EQ(num_changes_, 1); 195 196 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); 197 info.active_streams.push_back(std::make_pair(kSsrc2, 7)); 198 call_->EmitAudioMonitor(info); 199 200 EXPECT_EQ(current_speaker_, kSsrc2); 201 EXPECT_EQ(num_changes_, 1); 202 203 // Wait so the changes don't come so rapidly. 204 talk_base::Thread::SleepMs(kSleepTimeBetweenSwitches); 205 206 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); 207 info.active_streams.push_back(std::make_pair(kSsrc2, 0)); 208 call_->EmitAudioMonitor(info); 209 210 // Current speaker shouldn't have changed because we treat this as an inter- 211 // word silence. 212 EXPECT_EQ(current_speaker_, kSsrc2); 213 EXPECT_EQ(num_changes_, 1); 214 215 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); 216 info.active_streams.push_back(std::make_pair(kSsrc2, 0)); 217 call_->EmitAudioMonitor(info); 218 219 // Current speaker shouldn't have changed because we treat this as an inter- 220 // word silence. 221 EXPECT_EQ(current_speaker_, kSsrc2); 222 EXPECT_EQ(num_changes_, 1); 223 224 info.active_streams.push_back(std::make_pair(kSsrc1, 3)); 225 info.active_streams.push_back(std::make_pair(kSsrc2, 0)); 226 call_->EmitAudioMonitor(info); 227 228 // At this point, we should have concluded that SSRC2 stopped speaking. 229 EXPECT_EQ(current_speaker_, kSsrc1); 230 EXPECT_EQ(num_changes_, 2); 231 } 232 233 } // namespace cricket 234