| OLD | NEW |
| (Empty) |
| 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 <memory> | |
| 12 | |
| 13 #include "modules/audio_conference_mixer/include/audio_conference_mixer.h" | |
| 14 #include "modules/audio_conference_mixer/include/audio_conference_mixer_defines.
h" | |
| 15 #include "test/gmock.h" | |
| 16 | |
| 17 namespace webrtc { | |
| 18 | |
| 19 using testing::_; | |
| 20 using testing::AtLeast; | |
| 21 using testing::Invoke; | |
| 22 using testing::Return; | |
| 23 | |
| 24 class MockAudioMixerOutputReceiver : public AudioMixerOutputReceiver { | |
| 25 public: | |
| 26 MOCK_METHOD4(NewMixedAudio, void(const int32_t id, | |
| 27 const AudioFrame& general_audio_frame, | |
| 28 const AudioFrame** unique_audio_frames, | |
| 29 const uint32_t size)); | |
| 30 }; | |
| 31 | |
| 32 class MockMixerParticipant : public MixerParticipant { | |
| 33 public: | |
| 34 MockMixerParticipant() { | |
| 35 ON_CALL(*this, GetAudioFrame(_, _)) | |
| 36 .WillByDefault(Invoke(this, &MockMixerParticipant::FakeAudioFrame)); | |
| 37 } | |
| 38 MOCK_METHOD2(GetAudioFrame, | |
| 39 int32_t(const int32_t id, AudioFrame* audio_frame)); | |
| 40 MOCK_CONST_METHOD1(NeededFrequency, int32_t(const int32_t id)); | |
| 41 AudioFrame* fake_frame() { return &fake_frame_; } | |
| 42 | |
| 43 private: | |
| 44 AudioFrame fake_frame_; | |
| 45 int32_t FakeAudioFrame(const int32_t id, AudioFrame* audio_frame) { | |
| 46 audio_frame->CopyFrom(fake_frame_); | |
| 47 return 0; | |
| 48 } | |
| 49 }; | |
| 50 | |
| 51 TEST(AudioConferenceMixer, AnonymousAndNamed) { | |
| 52 const int kId = 1; | |
| 53 // Should not matter even if partipants are more than | |
| 54 // kMaximumAmountOfMixedParticipants. | |
| 55 const int kNamed = | |
| 56 AudioConferenceMixer::kMaximumAmountOfMixedParticipants + 1; | |
| 57 const int kAnonymous = | |
| 58 AudioConferenceMixer::kMaximumAmountOfMixedParticipants + 1; | |
| 59 | |
| 60 std::unique_ptr<AudioConferenceMixer> mixer( | |
| 61 AudioConferenceMixer::Create(kId)); | |
| 62 | |
| 63 MockMixerParticipant named[kNamed]; | |
| 64 MockMixerParticipant anonymous[kAnonymous]; | |
| 65 | |
| 66 for (int i = 0; i < kNamed; ++i) { | |
| 67 EXPECT_EQ(0, mixer->SetMixabilityStatus(&named[i], true)); | |
| 68 EXPECT_TRUE(mixer->MixabilityStatus(named[i])); | |
| 69 } | |
| 70 | |
| 71 for (int i = 0; i < kAnonymous; ++i) { | |
| 72 // Participant must be registered before turning it into anonymous. | |
| 73 EXPECT_EQ(-1, mixer->SetAnonymousMixabilityStatus(&anonymous[i], true)); | |
| 74 EXPECT_EQ(0, mixer->SetMixabilityStatus(&anonymous[i], true)); | |
| 75 EXPECT_TRUE(mixer->MixabilityStatus(anonymous[i])); | |
| 76 EXPECT_FALSE(mixer->AnonymousMixabilityStatus(anonymous[i])); | |
| 77 | |
| 78 EXPECT_EQ(0, mixer->SetAnonymousMixabilityStatus(&anonymous[i], true)); | |
| 79 EXPECT_TRUE(mixer->AnonymousMixabilityStatus(anonymous[i])); | |
| 80 | |
| 81 // Anonymous participants do not show status by MixabilityStatus. | |
| 82 EXPECT_FALSE(mixer->MixabilityStatus(anonymous[i])); | |
| 83 } | |
| 84 | |
| 85 for (int i = 0; i < kNamed; ++i) { | |
| 86 EXPECT_EQ(0, mixer->SetMixabilityStatus(&named[i], false)); | |
| 87 EXPECT_FALSE(mixer->MixabilityStatus(named[i])); | |
| 88 } | |
| 89 | |
| 90 for (int i = 0; i < kAnonymous - 1; i++) { | |
| 91 EXPECT_EQ(0, mixer->SetAnonymousMixabilityStatus(&anonymous[i], false)); | |
| 92 EXPECT_FALSE(mixer->AnonymousMixabilityStatus(anonymous[i])); | |
| 93 | |
| 94 // SetAnonymousMixabilityStatus(anonymous, false) moves anonymous to the | |
| 95 // named group. | |
| 96 EXPECT_TRUE(mixer->MixabilityStatus(anonymous[i])); | |
| 97 } | |
| 98 | |
| 99 // SetMixabilityStatus(anonymous, false) will remove anonymous from both | |
| 100 // anonymous and named groups. | |
| 101 EXPECT_EQ(0, mixer->SetMixabilityStatus(&anonymous[kAnonymous - 1], false)); | |
| 102 EXPECT_FALSE(mixer->AnonymousMixabilityStatus(anonymous[kAnonymous - 1])); | |
| 103 EXPECT_FALSE(mixer->MixabilityStatus(anonymous[kAnonymous - 1])); | |
| 104 } | |
| 105 | |
| 106 TEST(AudioConferenceMixer, LargestEnergyVadActiveMixed) { | |
| 107 const int kId = 1; | |
| 108 const int kParticipants = | |
| 109 AudioConferenceMixer::kMaximumAmountOfMixedParticipants + 3; | |
| 110 const int kSampleRateHz = 32000; | |
| 111 | |
| 112 std::unique_ptr<AudioConferenceMixer> mixer( | |
| 113 AudioConferenceMixer::Create(kId)); | |
| 114 | |
| 115 MockAudioMixerOutputReceiver output_receiver; | |
| 116 EXPECT_EQ(0, mixer->RegisterMixedStreamCallback(&output_receiver)); | |
| 117 | |
| 118 MockMixerParticipant participants[kParticipants]; | |
| 119 | |
| 120 for (int i = 0; i < kParticipants; ++i) { | |
| 121 participants[i].fake_frame()->id_ = i; | |
| 122 participants[i].fake_frame()->sample_rate_hz_ = kSampleRateHz; | |
| 123 participants[i].fake_frame()->speech_type_ = AudioFrame::kNormalSpeech; | |
| 124 participants[i].fake_frame()->vad_activity_ = AudioFrame::kVadActive; | |
| 125 participants[i].fake_frame()->num_channels_ = 1; | |
| 126 | |
| 127 // Frame duration 10ms. | |
| 128 participants[i].fake_frame()->samples_per_channel_ = kSampleRateHz / 100; | |
| 129 | |
| 130 // We set the 80-th sample value since the first 80 samples may be | |
| 131 // modified by a ramped-in window. | |
| 132 participants[i].fake_frame()->mutable_data()[80] = i; | |
| 133 | |
| 134 EXPECT_EQ(0, mixer->SetMixabilityStatus(&participants[i], true)); | |
| 135 EXPECT_CALL(participants[i], GetAudioFrame(_, _)) | |
| 136 .Times(AtLeast(1)); | |
| 137 EXPECT_CALL(participants[i], NeededFrequency(_)) | |
| 138 .WillRepeatedly(Return(kSampleRateHz)); | |
| 139 } | |
| 140 | |
| 141 // Last participant gives audio frame with passive VAD, although it has the | |
| 142 // largest energy. | |
| 143 participants[kParticipants - 1].fake_frame()->vad_activity_ = | |
| 144 AudioFrame::kVadPassive; | |
| 145 | |
| 146 EXPECT_CALL(output_receiver, NewMixedAudio(_, _, _, _)) | |
| 147 .Times(AtLeast(1)); | |
| 148 | |
| 149 mixer->Process(); | |
| 150 | |
| 151 for (int i = 0; i < kParticipants; ++i) { | |
| 152 bool is_mixed = participants[i].IsMixed(); | |
| 153 if (i == kParticipants - 1 || i < kParticipants - 1 - | |
| 154 AudioConferenceMixer::kMaximumAmountOfMixedParticipants) { | |
| 155 EXPECT_FALSE(is_mixed) << "Mixing status of Participant #" | |
| 156 << i << " wrong."; | |
| 157 } else { | |
| 158 EXPECT_TRUE(is_mixed) << "Mixing status of Participant #" | |
| 159 << i << " wrong."; | |
| 160 } | |
| 161 } | |
| 162 | |
| 163 EXPECT_EQ(0, mixer->UnRegisterMixedStreamCallback()); | |
| 164 } | |
| 165 | |
| 166 } // namespace webrtc | |
| OLD | NEW |