Chromium Code Reviews| 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 |