OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 <stddef.h> | 5 #include <stddef.h> |
6 #include <stdint.h> | 6 #include <stdint.h> |
7 | 7 |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/run_loop.h" | 10 #include "base/run_loop.h" |
11 #include "base/synchronization/waitable_event.h" | 11 #include "base/synchronization/waitable_event.h" |
12 #include "base/sys_byteorder.h" | 12 #include "base/sys_byteorder.h" |
13 #include "base/threading/thread.h" | 13 #include "base/threading/thread.h" |
14 #include "base/threading/thread_task_runner_handle.h" | 14 #include "base/threading/thread_task_runner_handle.h" |
15 #include "content/browser/speech/proto/google_streaming_api.pb.h" | 15 #include "content/browser/speech/proto/google_streaming_api.pb.h" |
16 #include "content/browser/speech/speech_recognition_engine.h" | 16 #include "content/browser/speech/speech_recognition_engine.h" |
17 #include "content/browser/speech/speech_recognizer_impl.h" | 17 #include "content/browser/speech/speech_recognizer_impl.h" |
18 #include "content/public/browser/speech_recognition_event_listener.h" | 18 #include "content/public/browser/speech_recognition_event_listener.h" |
19 #include "content/public/test/test_browser_thread_bundle.h" | 19 #include "content/public/test/test_browser_thread_bundle.h" |
20 #include "media/audio/audio_device_description.h" | 20 #include "media/audio/audio_device_description.h" |
21 #include "media/audio/audio_system_impl.h" | 21 #include "media/audio/audio_system_impl.h" |
22 #include "media/audio/fake_audio_input_stream.h" | 22 #include "media/audio/fake_audio_input_stream.h" |
23 #include "media/audio/fake_audio_output_stream.h" | 23 #include "media/audio/fake_audio_output_stream.h" |
24 #include "media/audio/mock_audio_manager.h" | 24 #include "media/audio/mock_audio_manager.h" |
25 #include "media/audio/test_audio_input_controller_factory.h" | 25 #include "media/audio/test_audio_input_controller_factory.h" |
| 26 #include "media/audio/test_audio_thread.h" |
26 #include "media/base/audio_bus.h" | 27 #include "media/base/audio_bus.h" |
27 #include "media/base/test_helpers.h" | 28 #include "media/base/test_helpers.h" |
28 #include "net/base/net_errors.h" | 29 #include "net/base/net_errors.h" |
29 #include "net/url_request/test_url_fetcher_factory.h" | 30 #include "net/url_request/test_url_fetcher_factory.h" |
30 #include "net/url_request/url_request_status.h" | 31 #include "net/url_request/url_request_status.h" |
31 #include "testing/gtest/include/gtest/gtest.h" | 32 #include "testing/gtest/include/gtest/gtest.h" |
32 | 33 |
33 using media::AudioInputController; | 34 using media::AudioInputController; |
34 using media::AudioInputStream; | 35 using media::AudioInputStream; |
35 using media::AudioOutputStream; | 36 using media::AudioOutputStream; |
36 using media::AudioParameters; | 37 using media::AudioParameters; |
37 using media::TestAudioInputController; | 38 using media::TestAudioInputController; |
38 using media::TestAudioInputControllerFactory; | 39 using media::TestAudioInputControllerFactory; |
39 | 40 |
40 namespace content { | 41 namespace content { |
41 | 42 |
42 class SpeechRecognizerImplTest : public SpeechRecognitionEventListener, | 43 class SpeechRecognizerImplTest : public SpeechRecognitionEventListener, |
43 public testing::Test { | 44 public testing::Test { |
44 public: | 45 public: |
45 SpeechRecognizerImplTest() | 46 SpeechRecognizerImplTest() |
46 : audio_thread_("SpeechAudioThread"), | 47 : recognition_started_(false), |
47 recognition_started_(false), | |
48 recognition_ended_(false), | 48 recognition_ended_(false), |
49 result_received_(false), | 49 result_received_(false), |
50 audio_started_(false), | 50 audio_started_(false), |
51 audio_ended_(false), | 51 audio_ended_(false), |
52 sound_started_(false), | 52 sound_started_(false), |
53 sound_ended_(false), | 53 sound_ended_(false), |
54 error_(SPEECH_RECOGNITION_ERROR_NONE), | 54 error_(SPEECH_RECOGNITION_ERROR_NONE), |
55 volume_(-1.0f) { | 55 volume_(-1.0f) { |
56 // SpeechRecognizer takes ownership of sr_engine. | 56 // SpeechRecognizer takes ownership of sr_engine. |
57 SpeechRecognitionEngine* sr_engine = | 57 SpeechRecognitionEngine* sr_engine = |
58 new SpeechRecognitionEngine(NULL /* URLRequestContextGetter */); | 58 new SpeechRecognitionEngine(NULL /* URLRequestContextGetter */); |
59 SpeechRecognitionEngine::Config config; | 59 SpeechRecognitionEngine::Config config; |
60 config.audio_num_bits_per_sample = | 60 config.audio_num_bits_per_sample = |
61 SpeechRecognizerImpl::kNumBitsPerAudioSample; | 61 SpeechRecognizerImpl::kNumBitsPerAudioSample; |
62 config.audio_sample_rate = SpeechRecognizerImpl::kAudioSampleRate; | 62 config.audio_sample_rate = SpeechRecognizerImpl::kAudioSampleRate; |
63 config.filter_profanities = false; | 63 config.filter_profanities = false; |
64 sr_engine->SetConfig(config); | 64 sr_engine->SetConfig(config); |
65 | 65 |
66 const int kTestingSessionId = 1; | 66 const int kTestingSessionId = 1; |
67 | 67 |
68 audio_thread_.StartAndWaitForTesting(); | 68 audio_manager_.reset(new media::MockAudioManager( |
69 audio_manager_.reset( | 69 base::MakeUnique<media::TestAudioThread>(true))); |
70 new media::MockAudioManager(audio_thread_.task_runner())); | |
71 audio_manager_->SetInputStreamParameters( | 70 audio_manager_->SetInputStreamParameters( |
72 media::AudioParameters::UnavailableDeviceParams()); | 71 media::AudioParameters::UnavailableDeviceParams()); |
73 audio_system_ = media::AudioSystemImpl::Create(audio_manager_.get()); | 72 audio_system_ = media::AudioSystemImpl::Create(audio_manager_.get()); |
74 recognizer_ = new SpeechRecognizerImpl( | 73 recognizer_ = new SpeechRecognizerImpl( |
75 this, audio_system_.get(), audio_manager_.get(), kTestingSessionId, | 74 this, audio_system_.get(), audio_manager_.get(), kTestingSessionId, |
76 false, false, sr_engine); | 75 false, false, sr_engine); |
77 | 76 |
78 int audio_packet_length_bytes = | 77 int audio_packet_length_bytes = |
79 (SpeechRecognizerImpl::kAudioSampleRate * | 78 (SpeechRecognizerImpl::kAudioSampleRate * |
80 SpeechRecognitionEngine::kAudioPacketIntervalMs * | 79 SpeechRecognitionEngine::kAudioPacketIntervalMs * |
81 ChannelLayoutToChannelCount(SpeechRecognizerImpl::kChannelLayout) * | 80 ChannelLayoutToChannelCount(SpeechRecognizerImpl::kChannelLayout) * |
82 SpeechRecognizerImpl::kNumBitsPerAudioSample) / (8 * 1000); | 81 SpeechRecognizerImpl::kNumBitsPerAudioSample) / (8 * 1000); |
83 audio_packet_.resize(audio_packet_length_bytes); | 82 audio_packet_.resize(audio_packet_length_bytes); |
84 | 83 |
85 const int channels = | 84 const int channels = |
86 ChannelLayoutToChannelCount(SpeechRecognizerImpl::kChannelLayout); | 85 ChannelLayoutToChannelCount(SpeechRecognizerImpl::kChannelLayout); |
87 bytes_per_sample_ = SpeechRecognizerImpl::kNumBitsPerAudioSample / 8; | 86 bytes_per_sample_ = SpeechRecognizerImpl::kNumBitsPerAudioSample / 8; |
88 const int frames = audio_packet_length_bytes / channels / bytes_per_sample_; | 87 const int frames = audio_packet_length_bytes / channels / bytes_per_sample_; |
89 audio_bus_ = media::AudioBus::Create(channels, frames); | 88 audio_bus_ = media::AudioBus::Create(channels, frames); |
90 audio_bus_->Zero(); | 89 audio_bus_->Zero(); |
91 } | 90 } |
92 | 91 |
93 ~SpeechRecognizerImplTest() override { | 92 ~SpeechRecognizerImplTest() override { audio_manager_->Shutdown(); } |
94 // Deleting |audio_manager_| on audio thread. | |
95 audio_system_.reset(); | |
96 audio_manager_.reset(); | |
97 audio_thread_.Stop(); | |
98 } | |
99 | 93 |
100 void CheckEventsConsistency() { | 94 void CheckEventsConsistency() { |
101 // Note: "!x || y" == "x implies y". | 95 // Note: "!x || y" == "x implies y". |
102 EXPECT_TRUE(!recognition_ended_ || recognition_started_); | 96 EXPECT_TRUE(!recognition_ended_ || recognition_started_); |
103 EXPECT_TRUE(!audio_ended_ || audio_started_); | 97 EXPECT_TRUE(!audio_ended_ || audio_started_); |
104 EXPECT_TRUE(!sound_ended_ || sound_started_); | 98 EXPECT_TRUE(!sound_ended_ || sound_started_); |
105 EXPECT_TRUE(!audio_started_ || recognition_started_); | 99 EXPECT_TRUE(!audio_started_ || recognition_started_); |
106 EXPECT_TRUE(!sound_started_ || audio_started_); | 100 EXPECT_TRUE(!sound_started_ || audio_started_); |
107 EXPECT_TRUE(!audio_ended_ || (sound_ended_ || !sound_started_)); | 101 EXPECT_TRUE(!audio_ended_ || (sound_ended_ || !sound_started_)); |
108 EXPECT_TRUE(!recognition_ended_ || (audio_ended_ || !audio_started_)); | 102 EXPECT_TRUE(!recognition_ended_ || (audio_ended_ || !audio_started_)); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 } | 195 } |
202 | 196 |
203 void OnData(media::AudioBus* data) { | 197 void OnData(media::AudioBus* data) { |
204 auto* writer = | 198 auto* writer = |
205 static_cast<AudioInputController::SyncWriter*>(recognizer_.get()); | 199 static_cast<AudioInputController::SyncWriter*>(recognizer_.get()); |
206 writer->Write(data, 0.0, false, 0); | 200 writer->Write(data, 0.0, false, 0); |
207 } | 201 } |
208 | 202 |
209 void WaitForAudioThreadToPostDeviceInfo() { | 203 void WaitForAudioThreadToPostDeviceInfo() { |
210 media::WaitableMessageLoopEvent event; | 204 media::WaitableMessageLoopEvent event; |
211 audio_thread_.task_runner()->PostTaskAndReply( | 205 audio_manager_->GetTaskRunner()->PostTaskAndReply( |
212 FROM_HERE, base::Bind(&base::DoNothing), event.GetClosure()); | 206 FROM_HERE, base::Bind(&base::DoNothing), event.GetClosure()); |
213 // Runs the loop and waits for the |audio_thread_| to call event's closure, | 207 // Runs the loop and waits for the audio thread to call event's closure, |
214 // which means AudioSystem reply containing device parameters is already | 208 // which means AudioSystem reply containing device parameters is already |
215 // queued on the main thread. | 209 // queued on the main thread. |
216 event.RunAndWait(); | 210 event.RunAndWait(); |
217 } | 211 } |
218 | 212 |
219 protected: | 213 protected: |
220 TestBrowserThreadBundle thread_bundle_; | 214 TestBrowserThreadBundle thread_bundle_; |
221 scoped_refptr<SpeechRecognizerImpl> recognizer_; | 215 scoped_refptr<SpeechRecognizerImpl> recognizer_; |
222 base::Thread audio_thread_; | 216 std::unique_ptr<media::MockAudioManager> audio_manager_; |
223 media::MockAudioManager::UniquePtr audio_manager_; | |
224 std::unique_ptr<media::AudioSystem> audio_system_; | 217 std::unique_ptr<media::AudioSystem> audio_system_; |
225 bool recognition_started_; | 218 bool recognition_started_; |
226 bool recognition_ended_; | 219 bool recognition_ended_; |
227 bool result_received_; | 220 bool result_received_; |
228 bool audio_started_; | 221 bool audio_started_; |
229 bool audio_ended_; | 222 bool audio_ended_; |
230 bool sound_started_; | 223 bool sound_started_; |
231 bool sound_ended_; | 224 bool sound_ended_; |
232 SpeechRecognitionErrorCode error_; | 225 SpeechRecognitionErrorCode error_; |
233 net::TestURLFetcherFactory url_fetcher_factory_; | 226 net::TestURLFetcherFactory url_fetcher_factory_; |
(...skipping 20 matching lines...) Expand all Loading... |
254 CheckFinalEventsConsistency(); | 247 CheckFinalEventsConsistency(); |
255 } | 248 } |
256 | 249 |
257 TEST_F(SpeechRecognizerImplTest, StopBeforeDeviceInfoReceived) { | 250 TEST_F(SpeechRecognizerImplTest, StopBeforeDeviceInfoReceived) { |
258 // Check for callbacks when stopping record before reply is received from | 251 // Check for callbacks when stopping record before reply is received from |
259 // AudioSystem. | 252 // AudioSystem. |
260 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC, | 253 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC, |
261 base::WaitableEvent::InitialState::NOT_SIGNALED); | 254 base::WaitableEvent::InitialState::NOT_SIGNALED); |
262 | 255 |
263 // Block audio thread. | 256 // Block audio thread. |
264 audio_thread_.task_runner()->PostTask( | 257 audio_manager_->GetTaskRunner()->PostTask( |
265 FROM_HERE, | 258 FROM_HERE, |
266 base::Bind(&base::WaitableEvent::Wait, base::Unretained(&event))); | 259 base::Bind(&base::WaitableEvent::Wait, base::Unretained(&event))); |
267 | 260 |
268 recognizer_->StartRecognition( | 261 recognizer_->StartRecognition( |
269 media::AudioDeviceDescription::kDefaultDeviceId); | 262 media::AudioDeviceDescription::kDefaultDeviceId); |
270 recognizer_->StopAudioCapture(); | 263 recognizer_->StopAudioCapture(); |
271 base::RunLoop().RunUntilIdle(); | 264 base::RunLoop().RunUntilIdle(); |
272 | 265 |
273 // Release audio thread and receive a callback from it. | 266 // Release audio thread and receive a callback from it. |
274 event.Signal(); | 267 event.Signal(); |
275 WaitForAudioThreadToPostDeviceInfo(); | 268 WaitForAudioThreadToPostDeviceInfo(); |
276 base::RunLoop().RunUntilIdle(); | 269 base::RunLoop().RunUntilIdle(); |
277 | 270 |
278 EXPECT_TRUE(recognition_started_); | 271 EXPECT_TRUE(recognition_started_); |
279 EXPECT_FALSE(audio_started_); | 272 EXPECT_FALSE(audio_started_); |
280 EXPECT_FALSE(result_received_); | 273 EXPECT_FALSE(result_received_); |
281 EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_); | 274 EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_); |
282 CheckFinalEventsConsistency(); | 275 CheckFinalEventsConsistency(); |
283 } | 276 } |
284 | 277 |
285 TEST_F(SpeechRecognizerImplTest, CancelBeforeDeviceInfoReceived) { | 278 TEST_F(SpeechRecognizerImplTest, CancelBeforeDeviceInfoReceived) { |
286 // Check for callbacks when stopping record before reply is received from | 279 // Check for callbacks when stopping record before reply is received from |
287 // AudioSystem. | 280 // AudioSystem. |
288 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC, | 281 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC, |
289 base::WaitableEvent::InitialState::NOT_SIGNALED); | 282 base::WaitableEvent::InitialState::NOT_SIGNALED); |
290 | 283 |
291 // Block audio thread. | 284 // Block audio thread. |
292 audio_thread_.task_runner()->PostTask( | 285 audio_manager_->GetTaskRunner()->PostTask( |
293 FROM_HERE, | 286 FROM_HERE, |
294 base::Bind(&base::WaitableEvent::Wait, base::Unretained(&event))); | 287 base::Bind(&base::WaitableEvent::Wait, base::Unretained(&event))); |
295 | 288 |
296 recognizer_->StartRecognition( | 289 recognizer_->StartRecognition( |
297 media::AudioDeviceDescription::kDefaultDeviceId); | 290 media::AudioDeviceDescription::kDefaultDeviceId); |
298 recognizer_->AbortRecognition(); | 291 recognizer_->AbortRecognition(); |
299 base::RunLoop().RunUntilIdle(); | 292 base::RunLoop().RunUntilIdle(); |
300 | 293 |
301 // Release audio thread and receive a callback from it. | 294 // Release audio thread and receive a callback from it. |
302 event.Signal(); | 295 event.Signal(); |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
650 | 643 |
651 EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_); | 644 EXPECT_EQ(SPEECH_RECOGNITION_ERROR_NONE, error_); |
652 EXPECT_FALSE(audio_ended_); | 645 EXPECT_FALSE(audio_ended_); |
653 EXPECT_FALSE(recognition_ended_); | 646 EXPECT_FALSE(recognition_ended_); |
654 recognizer_->AbortRecognition(); | 647 recognizer_->AbortRecognition(); |
655 base::RunLoop().RunUntilIdle(); | 648 base::RunLoop().RunUntilIdle(); |
656 CheckFinalEventsConsistency(); | 649 CheckFinalEventsConsistency(); |
657 } | 650 } |
658 | 651 |
659 } // namespace content | 652 } // namespace content |
OLD | NEW |