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

Side by Side Diff: chrome/browser/copresence/chrome_whispernet_client_browsertest.cc

Issue 940123004: Convert audio samples in Whispernet. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 10 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 unified diff | Download patch
OLDNEW
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698