OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include <memory> | 11 #include <memory> |
| 12 #include <utility> |
12 | 13 |
13 #include "testing/gmock/include/gmock/gmock.h" | 14 #include "testing/gmock/include/gmock/gmock.h" |
14 | 15 |
| 16 #include "webrtc/modules/audio_conference_mixer/include/audio_conference_mixer.h
" |
| 17 #include "webrtc/modules/audio_conference_mixer/include/audio_conference_mixer_d
efines.h" |
15 #include "webrtc/modules/audio_conference_mixer/source/audio_frame_manipulator.h
" | 18 #include "webrtc/modules/audio_conference_mixer/source/audio_frame_manipulator.h
" |
16 #include "webrtc/modules/audio_mixer/audio_mixer.h" | 19 #include "webrtc/modules/audio_mixer/audio_mixer.h" |
17 #include "webrtc/modules/audio_mixer/include/audio_mixer_defines.h" | 20 #include "webrtc/modules/audio_mixer/include/audio_mixer_defines.h" |
18 #include "webrtc/modules/audio_mixer/include/new_audio_conference_mixer.h" | 21 #include "webrtc/modules/audio_mixer/include/new_audio_conference_mixer.h" |
19 #include "webrtc/modules/audio_mixer/source/new_audio_conference_mixer_impl.h" | 22 #include "webrtc/modules/audio_mixer/source/new_audio_conference_mixer_impl.h" |
20 | 23 |
21 using testing::_; | 24 using testing::_; |
22 using testing::Exactly; | 25 using testing::Exactly; |
23 using testing::Invoke; | 26 using testing::Invoke; |
24 using testing::Return; | 27 using testing::Return; |
25 | 28 |
26 using webrtc::voe::AudioMixer; | 29 using webrtc::voe::AudioMixer; |
27 | 30 |
28 namespace webrtc { | 31 namespace webrtc { |
| 32 class MockAudioMixerParticipant : public MixerParticipant { |
| 33 public: |
| 34 MockAudioMixerParticipant() |
| 35 : fake_audio_frame_info_(MixerParticipant::AudioFrameInfo::kNormal) { |
| 36 ON_CALL(*this, GetAudioFrameWithMuted(_, _)) |
| 37 .WillByDefault( |
| 38 Invoke(this, &MockAudioMixerParticipant::FakeAudioFrameWithMuted)); |
| 39 } |
| 40 |
| 41 MOCK_METHOD2(GetAudioFrameWithMuted, |
| 42 AudioFrameInfo(const int32_t id, AudioFrame* audio_frame)); |
| 43 MOCK_CONST_METHOD1(NeededFrequency, int32_t(const int32_t id)); |
| 44 |
| 45 AudioFrame* fake_frame() { return &fake_frame_; } |
| 46 AudioFrameInfo fake_info() { return this->fake_audio_frame_info_; } |
| 47 void set_fake_info(const AudioFrameInfo audio_frame_info) { |
| 48 fake_audio_frame_info_ = audio_frame_info; |
| 49 } |
| 50 |
| 51 private: |
| 52 AudioFrame fake_frame_; |
| 53 AudioFrameInfo fake_audio_frame_info_; |
| 54 AudioFrameInfo FakeAudioFrameWithMuted(const int32_t id, |
| 55 AudioFrame* audio_frame) { |
| 56 audio_frame->CopyFrom(*fake_frame()); |
| 57 return fake_info(); |
| 58 } |
| 59 }; |
| 60 |
29 class MockMixerAudioSource : public MixerAudioSource { | 61 class MockMixerAudioSource : public MixerAudioSource { |
30 public: | 62 public: |
31 MockMixerAudioSource() { | 63 MockMixerAudioSource() |
| 64 : fake_audio_frame_info_(MixerAudioSource::AudioFrameInfo::kNormal) { |
32 ON_CALL(*this, GetAudioFrameWithMuted(_, _)) | 65 ON_CALL(*this, GetAudioFrameWithMuted(_, _)) |
33 .WillByDefault( | 66 .WillByDefault( |
34 Invoke(this, &MockMixerAudioSource::FakeAudioFrameWithMuted)); | 67 Invoke(this, &MockMixerAudioSource::FakeAudioFrameWithMuted)); |
35 } | 68 } |
| 69 |
36 MOCK_METHOD2(GetAudioFrameWithMuted, | 70 MOCK_METHOD2(GetAudioFrameWithMuted, |
37 AudioFrameWithInfo(const int32_t id, int sample_rate_hz)); | 71 AudioFrameWithMuted(const int32_t id, int sample_rate_hz)); |
38 MOCK_CONST_METHOD1(NeededFrequency, int32_t(const int32_t id)); | 72 MOCK_CONST_METHOD1(NeededFrequency, int32_t(const int32_t id)); |
39 | 73 |
40 AudioFrame* fake_frame() { return &fake_frame_; } | 74 AudioFrame* fake_frame() { return &fake_frame_; } |
| 75 AudioFrameInfo fake_info() { return fake_audio_frame_info_; } |
| 76 void set_fake_info(const AudioFrameInfo audio_frame_info) { |
| 77 fake_audio_frame_info_ = audio_frame_info; |
| 78 } |
41 | 79 |
42 private: | 80 private: |
43 AudioFrame fake_frame_; | 81 AudioFrame fake_frame_; |
44 AudioFrameWithInfo FakeAudioFrameWithMuted(const int32_t id, | 82 AudioFrameInfo fake_audio_frame_info_; |
45 int sample_rate_hz) { | 83 AudioFrameWithMuted FakeAudioFrameWithMuted(const int32_t id, |
| 84 int sample_rate_hz) { |
46 return { | 85 return { |
47 fake_frame(), // audio_frame_pointer | 86 fake_frame(), // audio_frame_pointer |
48 AudioFrameInfo::kNormal, // audio_frame_info | 87 fake_info(), // audio_frame_info |
49 }; | 88 }; |
50 } | 89 } |
51 }; | 90 }; |
52 | 91 |
| 92 // Keeps two identical sets of participants and two mixers to test |
| 93 // that the same participants are chosen for mixing. |
| 94 class CompareWithOldMixerTest : public testing::Test, AudioMixerOutputReceiver { |
| 95 protected: |
| 96 constexpr static int kId = 1; |
| 97 constexpr static int kSampleRateHz = 32000; |
| 98 |
| 99 CompareWithOldMixerTest() |
| 100 : old_mixer_(AudioConferenceMixer::Create(kId)), |
| 101 new_mixer_(NewAudioConferenceMixer::Create(kId)) {} |
| 102 |
| 103 ~CompareWithOldMixerTest() { Reset(); } |
| 104 |
| 105 // Mixes with both mixers and compares results: resulting frames and |
| 106 // mix statuses. |
| 107 void MixAndCompare() { |
| 108 old_mixer_->Process(); |
| 109 new_mixer_->Mix(&new_mixer_frame_); |
| 110 EXPECT_EQ(0, memcmp(old_mixer_frame_.data_, new_mixer_frame_.data_, |
| 111 sizeof(old_mixer_frame_.data_))); |
| 112 |
| 113 for (auto& participant_pair : participants_) { |
| 114 EXPECT_EQ(participant_pair.first->IsMixed(), |
| 115 participant_pair.second->IsMixed()); |
| 116 } |
| 117 } |
| 118 |
| 119 std::unique_ptr<AudioFrame> last_mixed_audio_old() { |
| 120 std::unique_ptr<AudioFrame> result(new AudioFrame); |
| 121 result->CopyFrom(old_mixer_frame_); |
| 122 return result; |
| 123 } |
| 124 |
| 125 void Reset() { |
| 126 old_mixer_.reset(AudioConferenceMixer::Create(kId)); |
| 127 new_mixer_.reset(NewAudioConferenceMixer::Create(kId)); |
| 128 for (auto& participant_pair : participants_) { |
| 129 delete participant_pair.first; |
| 130 delete participant_pair.second; |
| 131 } |
| 132 participants_.clear(); |
| 133 } |
| 134 |
| 135 void ResetFrame(AudioFrame* audio_frame) { |
| 136 audio_frame->sample_rate_hz_ = kSampleRateHz; |
| 137 audio_frame->speech_type_ = AudioFrame::kNormalSpeech; |
| 138 audio_frame->vad_activity_ = AudioFrame::kVadActive; |
| 139 audio_frame->num_channels_ = 1; |
| 140 } |
| 141 |
| 142 void AddParticipant(AudioFrame* audio_frame, |
| 143 MixerParticipant::AudioFrameInfo audio_frame_info) { |
| 144 auto old_participant = new MockAudioMixerParticipant; |
| 145 auto new_participant = new MockMixerAudioSource; |
| 146 old_participant->fake_frame()->CopyFrom(*audio_frame); |
| 147 new_participant->fake_frame()->CopyFrom(*audio_frame); |
| 148 old_participant->set_fake_info(audio_frame_info); |
| 149 MixerAudioSource::AudioFrameInfo new_audio_frame_info; |
| 150 switch (audio_frame_info) { |
| 151 case MixerParticipant::AudioFrameInfo::kNormal: |
| 152 new_audio_frame_info = MixerAudioSource::AudioFrameInfo::kNormal; |
| 153 break; |
| 154 case MixerParticipant::AudioFrameInfo::kMuted: |
| 155 new_audio_frame_info = MixerAudioSource::AudioFrameInfo::kMuted; |
| 156 break; |
| 157 default: |
| 158 new_audio_frame_info = MixerAudioSource::AudioFrameInfo::kError; |
| 159 } |
| 160 new_participant->set_fake_info(new_audio_frame_info); |
| 161 participants_.emplace_back(old_participant, new_participant); |
| 162 } |
| 163 |
| 164 void NewMixedAudio(const int32_t id, |
| 165 const AudioFrame& generalAudioFrame, |
| 166 const AudioFrame** uniqueAudioFrames, |
| 167 const uint32_t size) override { |
| 168 old_mixer_frame_.CopyFrom(generalAudioFrame); |
| 169 } |
| 170 |
| 171 AudioFrame old_mixer_frame_; |
| 172 AudioFrame new_mixer_frame_; |
| 173 |
| 174 std::vector<std::pair<MockAudioMixerParticipant*, MockMixerAudioSource*>> |
| 175 participants_; |
| 176 std::unique_ptr<AudioConferenceMixer> old_mixer_; |
| 177 std::unique_ptr<NewAudioConferenceMixer> new_mixer_; |
| 178 }; |
| 179 |
53 class BothMixersTest : public testing::Test { | 180 class BothMixersTest : public testing::Test { |
54 protected: | 181 protected: |
55 BothMixersTest() { | 182 BothMixersTest() { |
56 // Create an OutputMixer. | 183 // Create an OutputMixer. |
57 AudioMixer::Create(audio_mixer_, kId); | 184 AudioMixer::Create(audio_mixer_, kId); |
58 | 185 |
59 // Create one mixer participant and add it to the mixer. | 186 // Create one mixer participant and add it to the mixer. |
60 EXPECT_EQ(0, audio_mixer_->SetMixabilityStatus(participant_, true)); | 187 EXPECT_EQ(0, audio_mixer_->SetMixabilityStatus(participant_, true)); |
61 | 188 |
62 // Each iteration, the participant will return a frame with this content: | 189 // Each iteration, the participant will return a frame with this content: |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 | 366 |
240 // Mix frames a second time and compare with the expected frame | 367 // Mix frames a second time and compare with the expected frame |
241 // (which is the participant's frame). | 368 // (which is the participant's frame). |
242 audio_mixer_->MixActiveChannels(); | 369 audio_mixer_->MixActiveChannels(); |
243 audio_mixer_->GetMixedAudio(kSampleRateHz, 1, &mixed_results_frame_); | 370 audio_mixer_->GetMixedAudio(kSampleRateHz, 1, &mixed_results_frame_); |
244 EXPECT_EQ(0, | 371 EXPECT_EQ(0, |
245 memcmp(participant_.fake_frame()->data_, mixed_results_frame_.data_, | 372 memcmp(participant_.fake_frame()->data_, mixed_results_frame_.data_, |
246 sizeof(mixing_round_frame.data_))); | 373 sizeof(mixing_round_frame.data_))); |
247 } | 374 } |
248 | 375 |
| 376 TEST_F(CompareWithOldMixerTest, TwoParticipantsNormalFrames) { |
| 377 Reset(); |
| 378 AudioFrame first_frame, second_frame; |
| 379 |
| 380 ResetFrame(&first_frame); |
| 381 ResetFrame(&second_frame); |
| 382 |
| 383 first_frame.id_ = 1; |
| 384 second_frame.id_ = 2; |
| 385 |
| 386 AddParticipant(&first_frame, MixerParticipant::AudioFrameInfo::kNormal); |
| 387 AddParticipant(&second_frame, MixerParticipant::AudioFrameInfo::kNormal); |
| 388 |
| 389 for (int i = 0; i < 3; ++i) { |
| 390 MixAndCompare(); |
| 391 } |
| 392 } |
| 393 |
| 394 TEST_F(CompareWithOldMixerTest, ThreeParticipantsDifferentFrames) { |
| 395 Reset(); |
| 396 AudioFrame first_frame, second_frame, third_frame; |
| 397 |
| 398 ResetFrame(&first_frame); |
| 399 ResetFrame(&second_frame); |
| 400 ResetFrame(&third_frame); |
| 401 |
| 402 first_frame.id_ = 1; |
| 403 second_frame.id_ = 2; |
| 404 third_frame.id_ = 3; |
| 405 second_frame.vad_activity_ = AudioFrame::kVadPassive; |
| 406 |
| 407 AddParticipant(&first_frame, MixerParticipant::AudioFrameInfo::kNormal); |
| 408 AddParticipant(&second_frame, MixerParticipant::AudioFrameInfo::kMuted); |
| 409 AddParticipant(&third_frame, MixerParticipant::AudioFrameInfo::kMuted); |
| 410 |
| 411 for (int i = 0; i < 3; ++i) { |
| 412 MixAndCompare(); |
| 413 } |
| 414 } |
| 415 |
| 416 TEST_F(CompareWithOldMixerTest, ManyParticipantsDifferentFrames) { |
| 417 Reset(); |
| 418 constexpr int num_participants = 20; |
| 419 AudioFrame audio_frames[num_participants]; |
| 420 |
| 421 for (int i = 0; i < num_participants; ++i) { |
| 422 ResetFrame(&audio_frames[i]); |
| 423 audio_frames[i].id_ = 1; |
| 424 audio_frames[i].data_[10] = 100 * (i % 5); |
| 425 audio_frames[i].data_[100] = 100 * (i % 5); |
| 426 if (i % 2 == 0) { |
| 427 audio_frames[i].vad_activity_ = AudioFrame::kVadPassive; |
| 428 } |
| 429 } |
| 430 |
| 431 for (int i = 0; i < num_participants; ++i) { |
| 432 if (i % 2 == 0) { |
| 433 AddParticipant(&audio_frames[i], |
| 434 MixerParticipant::AudioFrameInfo::kMuted); |
| 435 } else { |
| 436 AddParticipant(&audio_frames[i], |
| 437 MixerParticipant::AudioFrameInfo::kNormal); |
| 438 } |
| 439 MixAndCompare(); |
| 440 } |
| 441 } |
| 442 |
249 } // namespace webrtc | 443 } // namespace webrtc |
OLD | NEW |