Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2604)

Unified Diff: remoting/protocol/connection_unittest.cc

Issue 2371323007: Add audio support in WebrtcConnectionToHost, audio unittest (Closed)
Patch Set: more reliable test Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « remoting/protocol/BUILD.gn ('k') | remoting/protocol/session_config.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/protocol/connection_unittest.cc
diff --git a/remoting/protocol/connection_unittest.cc b/remoting/protocol/connection_unittest.cc
index 92a07198aa83e3931e59f34a9e6f0ec60742bf33..03ee5e35694e46be68aadc65ef3ddb955b9fd134 100644
--- a/remoting/protocol/connection_unittest.cc
+++ b/remoting/protocol/connection_unittest.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#define _USE_MATH_DEFINES // For VC++ to get M_PI. This has to be first.
+
#include <utility>
#include "base/bind.h"
@@ -10,6 +12,10 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "remoting/base/constants.h"
+#include "remoting/proto/audio.pb.h"
+#include "remoting/protocol/audio_source.h"
+#include "remoting/protocol/audio_stream.h"
+#include "remoting/protocol/audio_stub.h"
#include "remoting/protocol/fake_session.h"
#include "remoting/protocol/fake_video_renderer.h"
#include "remoting/protocol/ice_connection_to_client.h"
@@ -93,6 +99,137 @@ class TestScreenCapturer : public webrtc::DesktopCapturer {
bool first_frame_sent_ = false;
};
+static const int kAudioSampleRate = AudioPacket::SAMPLING_RATE_48000;
+static const int kAudioPacketDurationMs = 50;
+static constexpr int kSamplesPerAudioPacket =
+ kAudioSampleRate * kAudioPacketDurationMs /
+ base::Time::kMillisecondsPerSecond;
+static constexpr base::TimeDelta kAudioPacketDuration =
+ base::TimeDelta::FromMilliseconds(kAudioPacketDurationMs);
+
+static const int kAudioChannels = 2;
+
+static const int kTestAudioSignalFrequencyLeftHz = 3000;
+static const int kTestAudioSignalFrequencyRightHz = 2000;
+
+class TestAudioSource : public AudioSource {
+ public:
+ TestAudioSource() {}
+ ~TestAudioSource() override {}
+
+ // AudioSource interface.
+ bool Start(const PacketCapturedCallback& callback) override {
+ callback_ = callback;
+ timer_.Start(FROM_HERE, kAudioPacketDuration,
+ base::Bind(&TestAudioSource::GenerateAudioSamples,
+ base::Unretained(this)));
+ return true;
+ }
+
+ private:
+ static int16_t GetSampleValue(double pos, int frequency) {
+ const int kMaxSampleValue = 32767;
+ return static_cast<int>(
+ sin(pos * 2 * M_PI * frequency / kAudioSampleRate) * kMaxSampleValue +
+ 0.5);
+ }
+
+ void GenerateAudioSamples() {
+ std::vector<int16_t> data(kSamplesPerAudioPacket * kAudioChannels);
+ for (int i = 0; i < kSamplesPerAudioPacket; ++i) {
+ data[i * kAudioChannels] = GetSampleValue(
+ position_samples_ + i, kTestAudioSignalFrequencyLeftHz);
+ data[i * kAudioChannels + 1] = GetSampleValue(
+ position_samples_ + i, kTestAudioSignalFrequencyRightHz);
+ }
+ position_samples_ += kSamplesPerAudioPacket;
+
+ std::unique_ptr<AudioPacket> packet(new AudioPacket());
+ packet->add_data(reinterpret_cast<char*>(&(data[0])),
+ kSamplesPerAudioPacket * kAudioChannels * sizeof(int16_t));
+ packet->set_encoding(AudioPacket::ENCODING_RAW);
+ packet->set_sampling_rate(AudioPacket::SAMPLING_RATE_48000);
+ packet->set_bytes_per_sample(AudioPacket::BYTES_PER_SAMPLE_2);
+ packet->set_channels(AudioPacket::CHANNELS_STEREO);
+ callback_.Run(std::move(packet));
+ }
+
+ PacketCapturedCallback callback_;
+ base::RepeatingTimer timer_;
+ int position_samples_ = 0;
+};
+
+class FakeAudioPlayer : public AudioStub {
+ public:
+ FakeAudioPlayer() : weak_factory_(this) {}
+ ~FakeAudioPlayer() override {}
+
+ // AudioStub interface.
+ void ProcessAudioPacket(std::unique_ptr<AudioPacket> packet,
+ const base::Closure& done) override {
+ EXPECT_EQ(AudioPacket::ENCODING_RAW, packet->encoding());
+ EXPECT_EQ(AudioPacket::SAMPLING_RATE_48000, packet->sampling_rate());
+ EXPECT_EQ(AudioPacket::BYTES_PER_SAMPLE_2, packet->bytes_per_sample());
+ EXPECT_EQ(AudioPacket::CHANNELS_STEREO, packet->channels());
+
+ data_.insert(data_.end(), packet->data(0).begin(), packet->data(0).end());
+
+ if (run_loop_ && data_.size() >= samples_expected_ * 4)
+ run_loop_->Quit();
+
+ if (!done.is_null())
+ done.Run();
+ }
+
+ void WaitForSamples(size_t samples_expected) {
+ samples_expected_ = samples_expected;
+ base::RunLoop run_loop;
+ run_loop_ = &run_loop;
+ run_loop.Run();
+ run_loop_ = nullptr;
+ }
+
+ void Verify() {
+ const int16_t* data = reinterpret_cast<const int16_t*>(data_.data());
+ int num_samples = data_.size() / kAudioChannels / sizeof(int16_t);
+
+ int skipped_samples = 0;
+ while (skipped_samples < num_samples &&
+ data[skipped_samples * kAudioChannels] == 0 &&
+ data[skipped_samples * kAudioChannels + 1] == 0) {
+ skipped_samples += kAudioChannels;
+ }
+
+ // Estimate signal frequency by counting how often it crosses 0.
+ int left = 0;
+ int right = 0;
+ for (int i = skipped_samples + 1; i < num_samples; ++i) {
+ if (data[(i - 1) * kAudioChannels] < 0 && data[i * kAudioChannels] >= 0) {
+ ++left;
+ }
+ if (data[(i - 1) * kAudioChannels + 1] < 0 &&
+ data[i * kAudioChannels + 1] >= 0) {
+ ++right;
+ }
+ }
+ int left_hz = (left * kAudioSampleRate / (num_samples - skipped_samples));
+ EXPECT_LE(kTestAudioSignalFrequencyLeftHz - 50, left_hz);
+ EXPECT_GE(kTestAudioSignalFrequencyLeftHz + 50, left_hz);
+ int right_hz = (right * kAudioSampleRate / (num_samples - skipped_samples));
+ EXPECT_LE(kTestAudioSignalFrequencyRightHz - 50, right_hz);
+ EXPECT_GE(kTestAudioSignalFrequencyRightHz + 50, right_hz);
+ }
+
+ base::WeakPtr<AudioStub> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
+
+ private:
+ std::vector<char> data_;
+ base::RunLoop* run_loop_ = nullptr;
+ size_t samples_expected_ = 0;
+
+ base::WeakPtrFactory<FakeAudioPlayer> weak_factory_;
+};
+
} // namespace
class ConnectionTest : public testing::Test,
@@ -140,6 +277,9 @@ class ConnectionTest : public testing::Test,
client_connection_->set_client_stub(&client_stub_);
client_connection_->set_clipboard_stub(&client_clipboard_stub_);
client_connection_->set_video_renderer(&client_video_renderer_);
+
+ client_connection_->InitializeAudio(message_loop_.task_runner(),
+ client_audio_player_.GetWeakPtr());
}
void Connect() {
@@ -266,6 +406,7 @@ class ConnectionTest : public testing::Test,
MockClientStub client_stub_;
MockClipboardStub client_clipboard_stub_;
FakeVideoRenderer client_video_renderer_;
+ FakeAudioPlayer client_audio_player_;
std::unique_ptr<ConnectionToHost> client_connection_;
FakeSession* client_session_; // Owned by |client_connection_|.
std::unique_ptr<FakeSession> owned_client_session_;
@@ -438,5 +579,16 @@ TEST_P(ConnectionTest, VideoStats) {
EXPECT_TRUE(stats.client_stats.time_rendered <= finish_time);
}
+TEST_P(ConnectionTest, Audio) {
+ Connect();
+
+ std::unique_ptr<AudioStream> audio_stream =
+ host_connection_->StartAudioStream(base::MakeUnique<TestAudioSource>());
+
+ // Wait for 1 second worth of audio samples.
+ client_audio_player_.WaitForSamples(kAudioSampleRate * 2);
+ client_audio_player_.Verify();
+}
+
} // namespace protocol
} // namespace remoting
« no previous file with comments | « remoting/protocol/BUILD.gn ('k') | remoting/protocol/session_config.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698