OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 #include "chrome/browser/copresence/chrome_whispernet_client.h" | 5 #include "chrome/browser/copresence/chrome_whispernet_client.h" |
6 | 6 |
7 #include <cmath> | |
7 #include <cstdlib> | 8 #include <cstdlib> |
8 #include <string> | 9 #include <string> |
9 | 10 |
10 #include "base/bind.h" | 11 #include "base/bind.h" |
11 #include "base/macros.h" | 12 #include "base/macros.h" |
12 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
13 #include "base/run_loop.h" | 14 #include "base/run_loop.h" |
14 #include "base/stl_util.h" | 15 #include "base/stl_util.h" |
15 #include "chrome/browser/extensions/api/copresence/copresence_api.h" | 16 #include "chrome/browser/extensions/api/copresence/copresence_api.h" |
16 #include "chrome/browser/extensions/extension_browsertest.h" | 17 #include "chrome/browser/extensions/extension_browsertest.h" |
17 #include "chrome/browser/profiles/profile.h" | 18 #include "chrome/browser/profiles/profile.h" |
18 #include "chrome/browser/ui/browser.h" | 19 #include "chrome/browser/ui/browser.h" |
19 #include "chrome/test/base/in_process_browser_test.h" | 20 #include "chrome/test/base/in_process_browser_test.h" |
21 #include "components/audio_modem/public/audio_modem_types.h" | |
20 #include "components/audio_modem/public/whispernet_client.h" | 22 #include "components/audio_modem/public/whispernet_client.h" |
23 #include "media/audio/audio_manager.h" | |
24 #include "media/audio/audio_manager_base.h" | |
25 #include "media/audio/audio_parameters.h" | |
21 #include "media/base/audio_bus.h" | 26 #include "media/base/audio_bus.h" |
27 #include "media/base/audio_converter.h" | |
22 | 28 |
23 using audio_modem::WhispernetClient; | 29 using audio_modem::WhispernetClient; |
24 using audio_modem::AUDIBLE; | 30 using audio_modem::AUDIBLE; |
25 using audio_modem::INAUDIBLE; | 31 using audio_modem::INAUDIBLE; |
26 | 32 |
27 namespace { | 33 namespace { |
28 | 34 |
29 // TODO(rkc): Add more varied test input. | 35 // TODO(rkc): Add more varied test input. |
30 const char kSixZeros[] = "MDAwMDAw"; | 36 const char kSixZeros[] = "MDAwMDAw"; |
31 const char kEightZeros[] = "MDAwMDAwMDA"; | 37 const char kEightZeros[] = "MDAwMDAwMDA"; |
(...skipping 17 matching lines...) Expand all Loading... | |
49 for (int ch = 0; ch < channels; ++ch) { | 55 for (int ch = 0; ch < channels; ++ch) { |
50 for (int si = 0, di = ch; si < source->frames(); ++si, di += channels) | 56 for (int si = 0, di = ch; si < source->frames(); ++si, di += channels) |
51 buffer_view[di] = source->channel(ch)[si]; | 57 buffer_view[di] = source->channel(ch)[si]; |
52 } | 58 } |
53 | 59 |
54 return buffer; | 60 return buffer; |
55 } | 61 } |
56 | 62 |
57 } // namespace | 63 } // namespace |
58 | 64 |
59 class ChromeWhispernetClientTest : public ExtensionBrowserTest { | 65 class ChromeWhispernetClientTest : public ExtensionBrowserTest, |
66 public media::AudioConverter::InputCallback { | |
60 protected: | 67 protected: |
61 ChromeWhispernetClientTest() | 68 ChromeWhispernetClientTest() |
62 : context_(NULL), expected_audible_(false), initialized_(false) {} | 69 : context_(NULL), |
70 expected_audible_(false), | |
71 saved_samples_index_(0), | |
72 initialized_(false) {} | |
63 | 73 |
64 ~ChromeWhispernetClientTest() override {} | 74 ~ChromeWhispernetClientTest() override {} |
65 | 75 |
66 void InitializeWhispernet() { | 76 void InitializeWhispernet() { |
67 context_ = browser()->profile(); | 77 context_ = browser()->profile(); |
68 run_loop_.reset(new base::RunLoop()); | 78 run_loop_.reset(new base::RunLoop()); |
69 GetWhispernetClient(context_)->Initialize(base::Bind( | 79 GetWhispernetClient(context_)->Initialize(base::Bind( |
70 &ChromeWhispernetClientTest::InitCallback, base::Unretained(this))); | 80 &ChromeWhispernetClientTest::InitCallback, base::Unretained(this))); |
71 run_loop_->Run(); | 81 run_loop_->Run(); |
82 EXPECT_TRUE(initialized_); | |
72 | 83 |
73 EXPECT_TRUE(initialized_); | 84 // We get default parameters here instead of the constructor since |
85 // initializing Whispernet also creates our AudioManager. Initializing from | |
86 // the test instead causes issues. | |
87 default_params_ = media::AudioManager::Get()->GetInputStreamParameters( | |
88 media::AudioManagerBase::kDefaultDeviceId); | |
89 | |
90 coder_params_ = media::AudioParameters( | |
Charlie
2015/02/20 00:58:20
nit: extra space before =
rkc
2015/02/20 18:53:07
There is a space between the coder_params_ and the
| |
91 default_params_.format(), audio_modem::kDefaultChannelLayout, | |
92 audio_modem::kDefaultSampleRate, audio_modem::kDefaultBitsPerSample, | |
93 default_params_.frames_per_buffer(), | |
94 media::AudioParameters::NO_EFFECTS); | |
95 | |
96 converter_.reset(new media::AudioConverter( | |
97 coder_params_, default_params_, | |
98 default_params_.sample_rate() == coder_params_.sample_rate())); | |
99 converter_->AddInput(this); | |
74 } | 100 } |
75 | 101 |
76 void EncodeTokenAndSaveSamples(bool audible, const std::string& token) { | 102 void EncodeTokenAndSaveSamples(bool audible, const std::string& token) { |
77 WhispernetClient* client = GetWhispernetClient(context_); | 103 WhispernetClient* client = GetWhispernetClient(context_); |
78 ASSERT_TRUE(client); | 104 ASSERT_TRUE(client); |
79 | 105 |
80 run_loop_.reset(new base::RunLoop()); | 106 run_loop_.reset(new base::RunLoop()); |
81 client->RegisterSamplesCallback( | 107 client->RegisterSamplesCallback( |
82 base::Bind(&ChromeWhispernetClientTest::SamplesCallback, | 108 base::Bind(&ChromeWhispernetClientTest::SamplesCallback, |
83 base::Unretained(this))); | 109 base::Unretained(this))); |
(...skipping 13 matching lines...) Expand all Loading... | |
97 ASSERT_TRUE(client); | 123 ASSERT_TRUE(client); |
98 | 124 |
99 run_loop_.reset(new base::RunLoop()); | 125 run_loop_.reset(new base::RunLoop()); |
100 client->RegisterTokensCallback(base::Bind( | 126 client->RegisterTokensCallback(base::Bind( |
101 &ChromeWhispernetClientTest::TokensCallback, base::Unretained(this))); | 127 &ChromeWhispernetClientTest::TokensCallback, base::Unretained(this))); |
102 expected_token_ = expected_token; | 128 expected_token_ = expected_token; |
103 expected_audible_ = expect_audible; | 129 expected_audible_ = expect_audible; |
104 | 130 |
105 ASSERT_GT(saved_samples_->frames(), 0); | 131 ASSERT_GT(saved_samples_->frames(), 0); |
106 | 132 |
107 // Convert our single channel samples to two channel. Decode samples | |
108 // expects 2 channel data. | |
109 scoped_refptr<media::AudioBusRefCounted> samples_bus = | 133 scoped_refptr<media::AudioBusRefCounted> samples_bus = |
110 media::AudioBusRefCounted::Create(2, saved_samples_->frames()); | 134 ConvertSavedSamplesToSystemParams(); |
111 memcpy(samples_bus->channel(0), | |
112 saved_samples_->channel(0), | |
113 sizeof(float) * saved_samples_->frames()); | |
114 memcpy(samples_bus->channel(1), | |
115 saved_samples_->channel(0), | |
116 sizeof(float) * saved_samples_->frames()); | |
117 | |
118 client->DecodeSamples( | 135 client->DecodeSamples( |
119 expect_audible ? AUDIBLE : INAUDIBLE, | 136 expect_audible ? AUDIBLE : INAUDIBLE, |
120 AudioBusToString(samples_bus), token_length); | 137 AudioBusToString(samples_bus), token_length); |
121 run_loop_->Run(); | 138 run_loop_->Run(); |
122 } | 139 } |
123 | 140 |
124 void DetectBroadcast() { | 141 void DetectBroadcast() { |
125 WhispernetClient* client = GetWhispernetClient(context_); | 142 WhispernetClient* client = GetWhispernetClient(context_); |
126 ASSERT_TRUE(client); | 143 ASSERT_TRUE(client); |
127 | 144 |
(...skipping 30 matching lines...) Expand all Loading... | |
158 EXPECT_EQ(expected_token_, tokens[0].token); | 175 EXPECT_EQ(expected_token_, tokens[0].token); |
159 EXPECT_EQ(expected_audible_, tokens[0].audible); | 176 EXPECT_EQ(expected_audible_, tokens[0].audible); |
160 } | 177 } |
161 | 178 |
162 void DetectBroadcastCallback(bool success) { | 179 void DetectBroadcastCallback(bool success) { |
163 EXPECT_TRUE(success); | 180 EXPECT_TRUE(success); |
164 ASSERT_TRUE(run_loop_); | 181 ASSERT_TRUE(run_loop_); |
165 run_loop_->Quit(); | 182 run_loop_->Quit(); |
166 } | 183 } |
167 | 184 |
185 // AudioConverter::InputCallback overrides: | |
186 double ProvideInput(media::AudioBus* dest, | |
Charlie
2015/02/20 00:58:20
This can be private.
rkc
2015/02/20 18:53:07
Done.
| |
187 base::TimeDelta /* buffer_delay */) override { | |
188 int remaining_frames = saved_samples_->frames() - saved_samples_index_; | |
189 int frames_to_copy = std::min(remaining_frames, dest->frames()); | |
190 saved_samples_stereo_->CopyPartialFramesTo(saved_samples_index_, | |
191 frames_to_copy, 0, dest); | |
192 saved_samples_index_ += frames_to_copy; | |
193 return 1.0; | |
194 } | |
195 | |
168 private: | 196 private: |
197 scoped_refptr<media::AudioBusRefCounted> ConvertSavedSamplesToSystemParams() { | |
198 int new_size = | |
199 saved_samples_->frames() * | |
200 std::ceil(static_cast<double>(default_params_.sample_rate()) / | |
Charlie
2015/02/20 00:58:21
Instead of static_cast<double>, just multiply by 1
rkc
2015/02/20 18:53:07
I prefer casting here since it makes it very expli
| |
201 coder_params_.sample_rate()); | |
202 new_size = | |
203 std::ceil(static_cast<double>(new_size) / converter_->ChunkSize()) * | |
204 converter_->ChunkSize(); | |
205 scoped_refptr<media::AudioBusRefCounted> converted_samples = | |
206 media::AudioBusRefCounted::Create(default_params_.channels(), new_size); | |
207 int converted_samples_index = 0; | |
208 | |
209 // Convert our single channel samples to two channel. Decode samples | |
210 // expects 2 channel data. | |
211 saved_samples_stereo_ = | |
212 media::AudioBusRefCounted::Create(2, saved_samples_->frames()); | |
213 memcpy(saved_samples_stereo_->channel(0), saved_samples_->channel(0), | |
214 sizeof(float) * saved_samples_->frames()); | |
215 memcpy(saved_samples_stereo_->channel(1), saved_samples_->channel(0), | |
216 sizeof(float) * saved_samples_->frames()); | |
217 | |
218 saved_samples_index_ = 0; | |
219 // While we still have frames to convert. | |
220 while (saved_samples_->frames() - saved_samples_index_ != 0) { | |
Charlie
2015/02/20 00:58:20
while (saved_samples_index_ < saved_samples_->fram
rkc
2015/02/20 18:53:07
Done.
| |
221 scoped_ptr<media::AudioBus> converted_source = media::AudioBus::Create( | |
DaleCurtis
2015/02/20 18:31:42
Why not just make a single call to Convert asking
rkc
2015/02/20 18:53:07
Done.
| |
222 default_params_.channels(), converter_->ChunkSize()); | |
223 converter_->Convert(converted_source.get()); | |
224 converted_source->CopyPartialFramesTo(0, converted_source->frames(), | |
225 converted_samples_index, | |
226 converted_samples.get()); | |
227 converted_samples_index += converted_source->frames(); | |
228 } | |
229 | |
230 return converted_samples; | |
231 } | |
232 | |
169 scoped_ptr<base::RunLoop> run_loop_; | 233 scoped_ptr<base::RunLoop> run_loop_; |
170 content::BrowserContext* context_; | 234 content::BrowserContext* context_; |
171 | 235 |
172 std::string expected_token_; | 236 std::string expected_token_; |
173 bool expected_audible_; | 237 bool expected_audible_; |
174 scoped_refptr<media::AudioBusRefCounted> saved_samples_; | 238 scoped_refptr<media::AudioBusRefCounted> saved_samples_; |
239 scoped_refptr<media::AudioBusRefCounted> saved_samples_stereo_; | |
240 int saved_samples_index_; | |
241 scoped_ptr<media::AudioConverter> converter_; | |
242 | |
243 media::AudioParameters default_params_; | |
244 media::AudioParameters coder_params_; | |
175 | 245 |
176 bool initialized_; | 246 bool initialized_; |
177 | 247 |
178 DISALLOW_COPY_AND_ASSIGN(ChromeWhispernetClientTest); | 248 DISALLOW_COPY_AND_ASSIGN(ChromeWhispernetClientTest); |
179 }; | 249 }; |
180 | 250 |
181 // These tests are irrelevant if NACL is disabled. See crbug.com/449198 | 251 // These tests are irrelevant if NACL is disabled. See crbug.com/449198 |
182 #if defined(DISABLE_NACL) | 252 #if defined(DISABLE_NACL) |
183 #define MAYBE_Initialize DISABLED_Initialize | 253 #define MAYBE_Initialize DISABLED_Initialize |
184 #define MAYBE_EncodeToken DISABLED_EncodeToken | 254 #define MAYBE_EncodeToken DISABLED_EncodeToken |
185 #define MAYBE_DecodeSamples DISABLED_DecodeSamples | 255 #define MAYBE_DecodeSamples DISABLED_DecodeSamples |
186 #define MAYBE_DetectBroadcast DISABLED_DetectBroadcast | |
187 #define MAYBE_Audible DISABLED_Audible | 256 #define MAYBE_Audible DISABLED_Audible |
188 #define MAYBE_TokenLengths DISABLED_TokenLengths | 257 #define MAYBE_TokenLengths DISABLED_TokenLengths |
189 #else | 258 #else |
190 #define MAYBE_Initialize Initialize | 259 #define MAYBE_Initialize Initialize |
191 #define MAYBE_EncodeToken EncodeToken | 260 #define MAYBE_EncodeToken EncodeToken |
192 #define MAYBE_DecodeSamples DecodeSamples | 261 #define MAYBE_DecodeSamples DecodeSamples |
193 #define MAYBE_DetectBroadcast DetectBroadcast | |
194 #define MAYBE_Audible Audible | 262 #define MAYBE_Audible Audible |
195 #define MAYBE_TokenLengths TokenLengths | 263 #define MAYBE_TokenLengths TokenLengths |
196 #endif | 264 #endif |
197 | 265 |
266 // DetectBroadcast will be removed soon, it isn't supported or needed anymore. | |
Charlie
2015/02/20 00:58:21
The CL I just checked in deletes this. And leaves
rkc
2015/02/20 18:53:07
Acknowledged.
| |
267 #define MAYBE_DetectBroadcast DISABLED_DetectBroadcast | |
268 | |
198 IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, MAYBE_Initialize) { | 269 IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, MAYBE_Initialize) { |
199 InitializeWhispernet(); | 270 InitializeWhispernet(); |
200 } | 271 } |
201 | 272 |
202 IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, MAYBE_EncodeToken) { | 273 IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, MAYBE_EncodeToken) { |
203 InitializeWhispernet(); | 274 InitializeWhispernet(); |
204 EncodeTokenAndSaveSamples(false, kSixZeros); | 275 EncodeTokenAndSaveSamples(false, kSixZeros); |
205 } | 276 } |
206 | 277 |
207 IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, MAYBE_DecodeSamples) { | 278 IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, MAYBE_DecodeSamples) { |
(...skipping 18 matching lines...) Expand all Loading... | |
226 IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, MAYBE_TokenLengths) { | 297 IN_PROC_BROWSER_TEST_F(ChromeWhispernetClientTest, MAYBE_TokenLengths) { |
227 InitializeWhispernet(); | 298 InitializeWhispernet(); |
228 size_t kLongTokenLengths[2] = {8, 9}; | 299 size_t kLongTokenLengths[2] = {8, 9}; |
229 | 300 |
230 EncodeTokenAndSaveSamples(true, kEightZeros); | 301 EncodeTokenAndSaveSamples(true, kEightZeros); |
231 DecodeSamplesAndVerifyToken(true, kEightZeros, kLongTokenLengths); | 302 DecodeSamplesAndVerifyToken(true, kEightZeros, kLongTokenLengths); |
232 | 303 |
233 EncodeTokenAndSaveSamples(false, kNineZeros); | 304 EncodeTokenAndSaveSamples(false, kNineZeros); |
234 DecodeSamplesAndVerifyToken(false, kNineZeros, kLongTokenLengths); | 305 DecodeSamplesAndVerifyToken(false, kNineZeros, kLongTokenLengths); |
235 } | 306 } |
OLD | NEW |