OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
| 5 #define _USE_MATH_DEFINES // For VC++ to get M_PI. This has to be first. |
| 6 |
5 #include <utility> | 7 #include <utility> |
6 | 8 |
7 #include "base/bind.h" | 9 #include "base/bind.h" |
8 #include "base/macros.h" | 10 #include "base/macros.h" |
9 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
10 #include "base/message_loop/message_loop.h" | 12 #include "base/message_loop/message_loop.h" |
11 #include "base/run_loop.h" | 13 #include "base/run_loop.h" |
12 #include "remoting/base/constants.h" | 14 #include "remoting/base/constants.h" |
| 15 #include "remoting/proto/audio.pb.h" |
| 16 #include "remoting/protocol/audio_source.h" |
| 17 #include "remoting/protocol/audio_stream.h" |
| 18 #include "remoting/protocol/audio_stub.h" |
13 #include "remoting/protocol/fake_session.h" | 19 #include "remoting/protocol/fake_session.h" |
14 #include "remoting/protocol/fake_video_renderer.h" | 20 #include "remoting/protocol/fake_video_renderer.h" |
15 #include "remoting/protocol/ice_connection_to_client.h" | 21 #include "remoting/protocol/ice_connection_to_client.h" |
16 #include "remoting/protocol/ice_connection_to_host.h" | 22 #include "remoting/protocol/ice_connection_to_host.h" |
17 #include "remoting/protocol/protocol_mock_objects.h" | 23 #include "remoting/protocol/protocol_mock_objects.h" |
18 #include "remoting/protocol/transport_context.h" | 24 #include "remoting/protocol/transport_context.h" |
19 #include "remoting/protocol/video_stream.h" | 25 #include "remoting/protocol/video_stream.h" |
20 #include "remoting/protocol/webrtc_connection_to_client.h" | 26 #include "remoting/protocol/webrtc_connection_to_client.h" |
21 #include "remoting/protocol/webrtc_connection_to_host.h" | 27 #include "remoting/protocol/webrtc_connection_to_host.h" |
22 #include "testing/gmock/include/gmock/gmock.h" | 28 #include "testing/gmock/include/gmock/gmock.h" |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 | 92 |
87 callback_->OnCaptureResult(webrtc::DesktopCapturer::Result::SUCCESS, | 93 callback_->OnCaptureResult(webrtc::DesktopCapturer::Result::SUCCESS, |
88 std::move(frame)); | 94 std::move(frame)); |
89 } | 95 } |
90 | 96 |
91 private: | 97 private: |
92 Callback* callback_ = nullptr; | 98 Callback* callback_ = nullptr; |
93 bool first_frame_sent_ = false; | 99 bool first_frame_sent_ = false; |
94 }; | 100 }; |
95 | 101 |
| 102 static const int kAudioSampleRate = AudioPacket::SAMPLING_RATE_48000; |
| 103 static const int kAudioPacketDurationMs = 50; |
| 104 static constexpr int kSamplesPerAudioPacket = |
| 105 kAudioSampleRate * kAudioPacketDurationMs / |
| 106 base::Time::kMillisecondsPerSecond; |
| 107 static constexpr base::TimeDelta kAudioPacketDuration = |
| 108 base::TimeDelta::FromMilliseconds(kAudioPacketDurationMs); |
| 109 |
| 110 static const int kAudioChannels = 2; |
| 111 |
| 112 static const int kTestAudioSignalFrequencyLeftHz = 3000; |
| 113 static const int kTestAudioSignalFrequencyRightHz = 2000; |
| 114 |
| 115 class TestAudioSource : public AudioSource { |
| 116 public: |
| 117 TestAudioSource() {} |
| 118 ~TestAudioSource() override {} |
| 119 |
| 120 // AudioSource interface. |
| 121 bool Start(const PacketCapturedCallback& callback) override { |
| 122 callback_ = callback; |
| 123 timer_.Start(FROM_HERE, kAudioPacketDuration, |
| 124 base::Bind(&TestAudioSource::GenerateAudioSamples, |
| 125 base::Unretained(this))); |
| 126 return true; |
| 127 } |
| 128 |
| 129 private: |
| 130 static int16_t GetSampleValue(double pos, int frequency) { |
| 131 const int kMaxSampleValue = 32767; |
| 132 return static_cast<int>( |
| 133 sin(pos * 2 * M_PI * frequency / kAudioSampleRate) * kMaxSampleValue + |
| 134 0.5); |
| 135 } |
| 136 |
| 137 void GenerateAudioSamples() { |
| 138 std::vector<int16_t> data(kSamplesPerAudioPacket * kAudioChannels); |
| 139 for (int i = 0; i < kSamplesPerAudioPacket; ++i) { |
| 140 data[i * kAudioChannels] = GetSampleValue( |
| 141 position_samples_ + i, kTestAudioSignalFrequencyLeftHz); |
| 142 data[i * kAudioChannels + 1] = GetSampleValue( |
| 143 position_samples_ + i, kTestAudioSignalFrequencyRightHz); |
| 144 } |
| 145 position_samples_ += kSamplesPerAudioPacket; |
| 146 |
| 147 std::unique_ptr<AudioPacket> packet(new AudioPacket()); |
| 148 packet->add_data(reinterpret_cast<char*>(&(data[0])), |
| 149 kSamplesPerAudioPacket * kAudioChannels * sizeof(int16_t)); |
| 150 packet->set_encoding(AudioPacket::ENCODING_RAW); |
| 151 packet->set_sampling_rate(AudioPacket::SAMPLING_RATE_48000); |
| 152 packet->set_bytes_per_sample(AudioPacket::BYTES_PER_SAMPLE_2); |
| 153 packet->set_channels(AudioPacket::CHANNELS_STEREO); |
| 154 callback_.Run(std::move(packet)); |
| 155 } |
| 156 |
| 157 PacketCapturedCallback callback_; |
| 158 base::RepeatingTimer timer_; |
| 159 int position_samples_ = 0; |
| 160 }; |
| 161 |
| 162 class FakeAudioPlayer : public AudioStub { |
| 163 public: |
| 164 FakeAudioPlayer() : weak_factory_(this) {} |
| 165 ~FakeAudioPlayer() override {} |
| 166 |
| 167 // AudioStub interface. |
| 168 void ProcessAudioPacket(std::unique_ptr<AudioPacket> packet, |
| 169 const base::Closure& done) override { |
| 170 EXPECT_EQ(AudioPacket::ENCODING_RAW, packet->encoding()); |
| 171 EXPECT_EQ(AudioPacket::SAMPLING_RATE_48000, packet->sampling_rate()); |
| 172 EXPECT_EQ(AudioPacket::BYTES_PER_SAMPLE_2, packet->bytes_per_sample()); |
| 173 EXPECT_EQ(AudioPacket::CHANNELS_STEREO, packet->channels()); |
| 174 |
| 175 data_.insert(data_.end(), packet->data(0).begin(), packet->data(0).end()); |
| 176 |
| 177 if (run_loop_ && data_.size() >= samples_expected_ * 4) |
| 178 run_loop_->Quit(); |
| 179 |
| 180 if (!done.is_null()) |
| 181 done.Run(); |
| 182 } |
| 183 |
| 184 void WaitForSamples(size_t samples_expected) { |
| 185 samples_expected_ = samples_expected; |
| 186 base::RunLoop run_loop; |
| 187 run_loop_ = &run_loop; |
| 188 run_loop.Run(); |
| 189 run_loop_ = nullptr; |
| 190 } |
| 191 |
| 192 void Verify() { |
| 193 const int16_t* data = reinterpret_cast<const int16_t*>(data_.data()); |
| 194 int num_samples = data_.size() / kAudioChannels / sizeof(int16_t); |
| 195 |
| 196 int skipped_samples = 0; |
| 197 while (skipped_samples < num_samples && |
| 198 data[skipped_samples * kAudioChannels] == 0 && |
| 199 data[skipped_samples * kAudioChannels + 1] == 0) { |
| 200 skipped_samples += kAudioChannels; |
| 201 } |
| 202 |
| 203 // Estimate signal frequency by counting how often it crosses 0. |
| 204 int left = 0; |
| 205 int right = 0; |
| 206 for (int i = skipped_samples + 1; i < num_samples; ++i) { |
| 207 if (data[(i - 1) * kAudioChannels] < 0 && data[i * kAudioChannels] >= 0) { |
| 208 ++left; |
| 209 } |
| 210 if (data[(i - 1) * kAudioChannels + 1] < 0 && |
| 211 data[i * kAudioChannels + 1] >= 0) { |
| 212 ++right; |
| 213 } |
| 214 } |
| 215 int left_hz = (left * kAudioSampleRate / (num_samples - skipped_samples)); |
| 216 EXPECT_LE(kTestAudioSignalFrequencyLeftHz - 50, left_hz); |
| 217 EXPECT_GE(kTestAudioSignalFrequencyLeftHz + 50, left_hz); |
| 218 int right_hz = (right * kAudioSampleRate / (num_samples - skipped_samples)); |
| 219 EXPECT_LE(kTestAudioSignalFrequencyRightHz - 50, right_hz); |
| 220 EXPECT_GE(kTestAudioSignalFrequencyRightHz + 50, right_hz); |
| 221 } |
| 222 |
| 223 base::WeakPtr<AudioStub> GetWeakPtr() { return weak_factory_.GetWeakPtr(); } |
| 224 |
| 225 private: |
| 226 std::vector<char> data_; |
| 227 base::RunLoop* run_loop_ = nullptr; |
| 228 size_t samples_expected_ = 0; |
| 229 |
| 230 base::WeakPtrFactory<FakeAudioPlayer> weak_factory_; |
| 231 }; |
| 232 |
96 } // namespace | 233 } // namespace |
97 | 234 |
98 class ConnectionTest : public testing::Test, | 235 class ConnectionTest : public testing::Test, |
99 public testing::WithParamInterface<bool> { | 236 public testing::WithParamInterface<bool> { |
100 public: | 237 public: |
101 ConnectionTest() {} | 238 ConnectionTest() {} |
102 | 239 |
103 void DestroyHost() { | 240 void DestroyHost() { |
104 host_connection_.reset(); | 241 host_connection_.reset(); |
105 run_loop_->Quit(); | 242 run_loop_->Quit(); |
(...skipping 27 matching lines...) Expand all Loading... |
133 // Setup host side. | 270 // Setup host side. |
134 host_connection_->SetEventHandler(&host_event_handler_); | 271 host_connection_->SetEventHandler(&host_event_handler_); |
135 host_connection_->set_clipboard_stub(&host_clipboard_stub_); | 272 host_connection_->set_clipboard_stub(&host_clipboard_stub_); |
136 host_connection_->set_host_stub(&host_stub_); | 273 host_connection_->set_host_stub(&host_stub_); |
137 host_connection_->set_input_stub(&host_input_stub_); | 274 host_connection_->set_input_stub(&host_input_stub_); |
138 | 275 |
139 // Setup client side. | 276 // Setup client side. |
140 client_connection_->set_client_stub(&client_stub_); | 277 client_connection_->set_client_stub(&client_stub_); |
141 client_connection_->set_clipboard_stub(&client_clipboard_stub_); | 278 client_connection_->set_clipboard_stub(&client_clipboard_stub_); |
142 client_connection_->set_video_renderer(&client_video_renderer_); | 279 client_connection_->set_video_renderer(&client_video_renderer_); |
| 280 |
| 281 client_connection_->InitializeAudio(message_loop_.task_runner(), |
| 282 client_audio_player_.GetWeakPtr()); |
143 } | 283 } |
144 | 284 |
145 void Connect() { | 285 void Connect() { |
146 { | 286 { |
147 testing::InSequence sequence; | 287 testing::InSequence sequence; |
148 EXPECT_CALL(host_event_handler_, OnConnectionAuthenticating()); | 288 EXPECT_CALL(host_event_handler_, OnConnectionAuthenticating()); |
149 EXPECT_CALL(host_event_handler_, OnConnectionAuthenticated()); | 289 EXPECT_CALL(host_event_handler_, OnConnectionAuthenticated()); |
150 } | 290 } |
151 EXPECT_CALL(host_event_handler_, OnConnectionChannelsConnected()) | 291 EXPECT_CALL(host_event_handler_, OnConnectionChannelsConnected()) |
152 .WillOnce(InvokeWithoutArgs(this, &ConnectionTest::OnHostConnected)); | 292 .WillOnce(InvokeWithoutArgs(this, &ConnectionTest::OnHostConnected)); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 MockHostStub host_stub_; | 399 MockHostStub host_stub_; |
260 MockInputStub host_input_stub_; | 400 MockInputStub host_input_stub_; |
261 std::unique_ptr<ConnectionToClient> host_connection_; | 401 std::unique_ptr<ConnectionToClient> host_connection_; |
262 FakeSession* host_session_; // Owned by |host_connection_|. | 402 FakeSession* host_session_; // Owned by |host_connection_|. |
263 bool host_connected_ = false; | 403 bool host_connected_ = false; |
264 | 404 |
265 MockConnectionToHostEventCallback client_event_handler_; | 405 MockConnectionToHostEventCallback client_event_handler_; |
266 MockClientStub client_stub_; | 406 MockClientStub client_stub_; |
267 MockClipboardStub client_clipboard_stub_; | 407 MockClipboardStub client_clipboard_stub_; |
268 FakeVideoRenderer client_video_renderer_; | 408 FakeVideoRenderer client_video_renderer_; |
| 409 FakeAudioPlayer client_audio_player_; |
269 std::unique_ptr<ConnectionToHost> client_connection_; | 410 std::unique_ptr<ConnectionToHost> client_connection_; |
270 FakeSession* client_session_; // Owned by |client_connection_|. | 411 FakeSession* client_session_; // Owned by |client_connection_|. |
271 std::unique_ptr<FakeSession> owned_client_session_; | 412 std::unique_ptr<FakeSession> owned_client_session_; |
272 bool client_connected_ = false; | 413 bool client_connected_ = false; |
273 | 414 |
274 private: | 415 private: |
275 DISALLOW_COPY_AND_ASSIGN(ConnectionTest); | 416 DISALLOW_COPY_AND_ASSIGN(ConnectionTest); |
276 }; | 417 }; |
277 | 418 |
278 INSTANTIATE_TEST_CASE_P(Ice, ConnectionTest, ::testing::Values(false)); | 419 INSTANTIATE_TEST_CASE_P(Ice, ConnectionTest, ::testing::Values(false)); |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
431 stats.host_stats.encode_delay + | 572 stats.host_stats.encode_delay + |
432 stats.host_stats.send_pending_delay <= | 573 stats.host_stats.send_pending_delay <= |
433 stats.client_stats.time_received); | 574 stats.client_stats.time_received); |
434 EXPECT_TRUE(stats.client_stats.time_received <= | 575 EXPECT_TRUE(stats.client_stats.time_received <= |
435 stats.client_stats.time_decoded); | 576 stats.client_stats.time_decoded); |
436 EXPECT_TRUE(stats.client_stats.time_decoded <= | 577 EXPECT_TRUE(stats.client_stats.time_decoded <= |
437 stats.client_stats.time_rendered); | 578 stats.client_stats.time_rendered); |
438 EXPECT_TRUE(stats.client_stats.time_rendered <= finish_time); | 579 EXPECT_TRUE(stats.client_stats.time_rendered <= finish_time); |
439 } | 580 } |
440 | 581 |
| 582 TEST_P(ConnectionTest, Audio) { |
| 583 Connect(); |
| 584 |
| 585 std::unique_ptr<AudioStream> audio_stream = |
| 586 host_connection_->StartAudioStream(base::MakeUnique<TestAudioSource>()); |
| 587 |
| 588 // Wait for 1 second worth of audio samples. |
| 589 client_audio_player_.WaitForSamples(kAudioSampleRate * 2); |
| 590 client_audio_player_.Verify(); |
| 591 } |
| 592 |
441 } // namespace protocol | 593 } // namespace protocol |
442 } // namespace remoting | 594 } // namespace remoting |
OLD | NEW |