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

Side by Side Diff: content/browser/speech/speech_recognizer_impl.cc

Issue 549373003: Binding media stream audio track to speech recognition [browser] Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Wait with no timeout Created 6 years, 1 month 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 (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 "content/browser/speech/speech_recognizer_impl.h" 5 #include "content/browser/speech/speech_recognizer_impl.h"
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/memory/shared_memory.h"
10 #include "base/threading/thread.h"
11 #include "base/threading/thread_restrictions.h"
9 #include "base/time/time.h" 12 #include "base/time/time.h"
10 #include "content/browser/browser_main_loop.h" 13 #include "content/browser/browser_main_loop.h"
11 #include "content/browser/media/media_internals.h" 14 #include "content/browser/media/media_internals.h"
12 #include "content/browser/speech/audio_buffer.h" 15 #include "content/browser/speech/audio_buffer.h"
13 #include "content/browser/speech/google_one_shot_remote_engine.h" 16 #include "content/browser/speech/google_one_shot_remote_engine.h"
17 #include "content/browser/speech/speech_recognition_audio_receiver.h"
18 #include "content/public/browser/browser_message_filter.h"
14 #include "content/public/browser/speech_recognition_event_listener.h" 19 #include "content/public/browser/speech_recognition_event_listener.h"
15 #include "media/base/audio_converter.h" 20 #include "media/base/audio_converter.h"
16 #include "net/url_request/url_request_context_getter.h" 21 #include "net/url_request/url_request_context_getter.h"
17 22
18 #if defined(OS_WIN) 23 #if defined(OS_WIN)
19 #include "media/audio/win/core_audio_util_win.h" 24 #include "media/audio/win/core_audio_util_win.h"
20 #endif 25 #endif
21 26
22 using media::AudioBus; 27 using media::AudioBus;
23 using media::AudioConverter; 28 using media::AudioConverter;
(...skipping 10 matching lines...) Expand all
34 class SpeechRecognizerImpl::OnDataConverter 39 class SpeechRecognizerImpl::OnDataConverter
35 : public media::AudioConverter::InputCallback { 40 : public media::AudioConverter::InputCallback {
36 public: 41 public:
37 OnDataConverter(const AudioParameters& input_params, 42 OnDataConverter(const AudioParameters& input_params,
38 const AudioParameters& output_params); 43 const AudioParameters& output_params);
39 ~OnDataConverter() override; 44 ~OnDataConverter() override;
40 45
41 // Converts input audio |data| bus into an AudioChunk where the input format 46 // Converts input audio |data| bus into an AudioChunk where the input format
42 // is given by |input_parameters_| and the output format by 47 // is given by |input_parameters_| and the output format by
43 // |output_parameters_|. 48 // |output_parameters_|.
49 // Skips conversion on |audio_converter_| when input and output formats match.
44 scoped_refptr<AudioChunk> Convert(const AudioBus* data); 50 scoped_refptr<AudioChunk> Convert(const AudioBus* data);
45 51
46 private: 52 private:
47 // media::AudioConverter::InputCallback implementation. 53 // media::AudioConverter::InputCallback implementation.
48 double ProvideInput(AudioBus* dest, base::TimeDelta buffer_delay) override; 54 double ProvideInput(AudioBus* dest, base::TimeDelta buffer_delay) override;
49 55
50 // Handles resampling, buffering, and channel mixing between input and output 56 // Handles resampling, buffering, and channel mixing between input and output
51 // parameters. 57 // parameters.
52 AudioConverter audio_converter_; 58 scoped_ptr<AudioConverter> audio_converter_;
53 59
54 scoped_ptr<AudioBus> input_bus_; 60 scoped_ptr<AudioBus> input_bus_;
55 scoped_ptr<AudioBus> output_bus_; 61 scoped_ptr<AudioBus> output_bus_;
56 const AudioParameters input_parameters_; 62 const AudioParameters input_parameters_;
57 const AudioParameters output_parameters_; 63 const AudioParameters output_parameters_;
58 bool waiting_for_input_; 64 bool waiting_for_input_;
65 bool need_conversion_;
59 scoped_ptr<uint8[]> converted_data_; 66 scoped_ptr<uint8[]> converted_data_;
60 67
61 DISALLOW_COPY_AND_ASSIGN(OnDataConverter); 68 DISALLOW_COPY_AND_ASSIGN(OnDataConverter);
62 }; 69 };
63 70
64 namespace { 71 namespace {
65 72
66 // The following constants are related to the volume level indicator shown in 73 // The following constants are related to the volume level indicator shown in
67 // the UI for recorded audio. 74 // the UI for recorded audio.
68 // Multiplier used when new volume is greater than previous level. 75 // Multiplier used when new volume is greater than previous level.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 const int SpeechRecognizerImpl::kEndpointerEstimationTimeMs = 300; 115 const int SpeechRecognizerImpl::kEndpointerEstimationTimeMs = 300;
109 media::AudioManager* SpeechRecognizerImpl::audio_manager_for_tests_ = NULL; 116 media::AudioManager* SpeechRecognizerImpl::audio_manager_for_tests_ = NULL;
110 117
111 COMPILE_ASSERT(SpeechRecognizerImpl::kNumBitsPerAudioSample % 8 == 0, 118 COMPILE_ASSERT(SpeechRecognizerImpl::kNumBitsPerAudioSample % 8 == 0,
112 kNumBitsPerAudioSample_must_be_a_multiple_of_8); 119 kNumBitsPerAudioSample_must_be_a_multiple_of_8);
113 120
114 // SpeechRecognizerImpl::OnDataConverter implementation 121 // SpeechRecognizerImpl::OnDataConverter implementation
115 122
116 SpeechRecognizerImpl::OnDataConverter::OnDataConverter( 123 SpeechRecognizerImpl::OnDataConverter::OnDataConverter(
117 const AudioParameters& input_params, const AudioParameters& output_params) 124 const AudioParameters& input_params, const AudioParameters& output_params)
118 : audio_converter_(input_params, output_params, false), 125 : input_bus_(AudioBus::Create(input_params)),
119 input_bus_(AudioBus::Create(input_params)),
120 output_bus_(AudioBus::Create(output_params)), 126 output_bus_(AudioBus::Create(output_params)),
121 input_parameters_(input_params), 127 input_parameters_(input_params),
122 output_parameters_(output_params), 128 output_parameters_(output_params),
123 waiting_for_input_(false), 129 waiting_for_input_(false),
124 converted_data_(new uint8[output_parameters_.GetBytesPerBuffer()]) { 130 converted_data_(new uint8[output_parameters_.GetBytesPerBuffer()]) {
125 audio_converter_.AddInput(this); 131 if (!input_parameters_.Equals(output_parameters_)) {
132 audio_converter_.reset(new AudioConverter(input_params,
133 output_params,
134 false));
135 audio_converter_->AddInput(this);
136 }
126 } 137 }
127 138
128 SpeechRecognizerImpl::OnDataConverter::~OnDataConverter() { 139 SpeechRecognizerImpl::OnDataConverter::~OnDataConverter() {
129 // It should now be safe to unregister the converter since no more OnData() 140 // It should now be safe to unregister the converter since no more OnData()
130 // callbacks are outstanding at this point. 141 // callbacks are outstanding at this point.
131 audio_converter_.RemoveInput(this); 142 if (audio_converter_.get())
143 audio_converter_->RemoveInput(this);
132 } 144 }
133 145
134 scoped_refptr<AudioChunk> SpeechRecognizerImpl::OnDataConverter::Convert( 146 scoped_refptr<AudioChunk> SpeechRecognizerImpl::OnDataConverter::Convert(
135 const AudioBus* data) { 147 const AudioBus* data) {
136 CHECK_EQ(data->frames(), input_parameters_.frames_per_buffer()); 148 CHECK_EQ(data->frames(), input_parameters_.frames_per_buffer());
137 149
138 data->CopyTo(input_bus_.get()); 150 // Do conversion if needed - only when |input_parameters_| differ from
139 151 // |output_parameters_|.
140 waiting_for_input_ = true; 152 if (audio_converter_.get()) {
141 audio_converter_.Convert(output_bus_.get()); 153 data->CopyTo(input_bus_.get());
154 waiting_for_input_ = true;
155 audio_converter_->Convert(output_bus_.get());
156 } else {
157 data->CopyTo(output_bus_.get());
158 }
142 159
143 output_bus_->ToInterleaved( 160 output_bus_->ToInterleaved(
144 output_bus_->frames(), output_parameters_.bits_per_sample() / 8, 161 output_bus_->frames(), output_parameters_.bits_per_sample() / 8,
145 converted_data_.get()); 162 converted_data_.get());
146 163
147 // TODO(primiano): Refactor AudioChunk to avoid the extra-copy here 164 // TODO(primiano): Refactor AudioChunk to avoid the extra-copy here
148 // (see http://crbug.com/249316 for details). 165 // (see http://crbug.com/249316 for details).
149 return scoped_refptr<AudioChunk>(new AudioChunk( 166 return scoped_refptr<AudioChunk>(new AudioChunk(
150 converted_data_.get(), 167 converted_data_.get(),
151 output_parameters_.GetBytesPerBuffer(), 168 output_parameters_.GetBytesPerBuffer(),
(...skipping 15 matching lines...) Expand all
167 return 1; 184 return 1;
168 } 185 }
169 186
170 // SpeechRecognizerImpl implementation 187 // SpeechRecognizerImpl implementation
171 188
172 SpeechRecognizerImpl::SpeechRecognizerImpl( 189 SpeechRecognizerImpl::SpeechRecognizerImpl(
173 SpeechRecognitionEventListener* listener, 190 SpeechRecognitionEventListener* listener,
174 int session_id, 191 int session_id,
175 bool continuous, 192 bool continuous,
176 bool provisional_results, 193 bool provisional_results,
194 bool using_audio_receiver,
195 const base::ProcessHandle peer_process_handle,
177 SpeechRecognitionEngine* engine) 196 SpeechRecognitionEngine* engine)
178 : SpeechRecognizer(listener, session_id), 197 : SpeechRecognizer(listener, session_id),
179 recognition_engine_(engine), 198 recognition_engine_(engine),
180 endpointer_(kAudioSampleRate), 199 endpointer_(kAudioSampleRate),
181 audio_log_(MediaInternals::GetInstance()->CreateAudioLog( 200 audio_log_(MediaInternals::GetInstance()->CreateAudioLog(
182 media::AudioLogFactory::AUDIO_INPUT_CONTROLLER)), 201 media::AudioLogFactory::AUDIO_INPUT_CONTROLLER)),
183 is_dispatching_event_(false), 202 is_dispatching_event_(false),
184 provisional_results_(provisional_results), 203 provisional_results_(provisional_results),
204 using_audio_receiver_(using_audio_receiver),
205 peer_process_handle_(peer_process_handle),
185 state_(STATE_IDLE) { 206 state_(STATE_IDLE) {
186 DCHECK(recognition_engine_ != NULL); 207 DCHECK(recognition_engine_ != NULL);
187 if (!continuous) { 208 if (!continuous) {
188 // In single shot (non-continous) recognition, 209 // In single shot (non-continous) recognition,
189 // the session is automatically ended after: 210 // the session is automatically ended after:
190 // - 0.5 seconds of silence if time < 3 seconds 211 // - 0.5 seconds of silence if time < 3 seconds
191 // - 1 seconds of silence if time >= 3 seconds 212 // - 1 seconds of silence if time >= 3 seconds
192 endpointer_.set_speech_input_complete_silence_length( 213 endpointer_.set_speech_input_complete_silence_length(
193 base::Time::kMicrosecondsPerSecond / 2); 214 base::Time::kMicrosecondsPerSecond / 2);
194 endpointer_.set_long_speech_input_complete_silence_length( 215 endpointer_.set_long_speech_input_complete_silence_length(
(...skipping 11 matching lines...) Expand all
206 } 227 }
207 228
208 // ------- Methods that trigger Finite State Machine (FSM) events ------------ 229 // ------- Methods that trigger Finite State Machine (FSM) events ------------
209 230
210 // NOTE:all the external events and requests should be enqueued (PostTask), even 231 // NOTE:all the external events and requests should be enqueued (PostTask), even
211 // if they come from the same (IO) thread, in order to preserve the relationship 232 // if they come from the same (IO) thread, in order to preserve the relationship
212 // of causality between events and avoid interleaved event processing due to 233 // of causality between events and avoid interleaved event processing due to
213 // synchronous callbacks. 234 // synchronous callbacks.
214 235
215 void SpeechRecognizerImpl::StartRecognition(const std::string& device_id) { 236 void SpeechRecognizerImpl::StartRecognition(const std::string& device_id) {
216 DCHECK(!device_id.empty()); 237 DCHECK(!device_id.empty() ^ using_audio_receiver_);
217 device_id_ = device_id; 238 device_id_ = device_id;
218 239
219 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 240 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
220 base::Bind(&SpeechRecognizerImpl::DispatchEvent, 241 base::Bind(&SpeechRecognizerImpl::DispatchEvent,
221 this, FSMEventArgs(EVENT_START))); 242 this, FSMEventArgs(EVENT_START)));
222 } 243 }
223 244
224 void SpeechRecognizerImpl::AbortRecognition() { 245 void SpeechRecognizerImpl::AbortRecognition() {
225 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 246 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
226 base::Bind(&SpeechRecognizerImpl::DispatchEvent, 247 base::Bind(&SpeechRecognizerImpl::DispatchEvent,
(...skipping 10 matching lines...) Expand all
237 // Checking the FSM state from another thread (thus, while the FSM is 258 // Checking the FSM state from another thread (thus, while the FSM is
238 // potentially concurrently evolving) is meaningless. 259 // potentially concurrently evolving) is meaningless.
239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 260 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
240 return state_ != STATE_IDLE && state_ != STATE_ENDED; 261 return state_ != STATE_IDLE && state_ != STATE_ENDED;
241 } 262 }
242 263
243 bool SpeechRecognizerImpl::IsCapturingAudio() const { 264 bool SpeechRecognizerImpl::IsCapturingAudio() const {
244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); // See IsActive(). 265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); // See IsActive().
245 const bool is_capturing_audio = state_ >= STATE_STARTING && 266 const bool is_capturing_audio = state_ >= STATE_STARTING &&
246 state_ <= STATE_RECOGNIZING; 267 state_ <= STATE_RECOGNIZING;
247 DCHECK((is_capturing_audio && (audio_controller_.get() != NULL)) || 268 DCHECK((is_capturing_audio &&
269 (using_audio_receiver_ || (audio_controller_.get() != NULL))) ||
248 (!is_capturing_audio && audio_controller_.get() == NULL)); 270 (!is_capturing_audio && audio_controller_.get() == NULL));
249 return is_capturing_audio; 271 return is_capturing_audio;
250 } 272 }
251 273
252 const SpeechRecognitionEngine& 274 const SpeechRecognitionEngine&
253 SpeechRecognizerImpl::recognition_engine() const { 275 SpeechRecognizerImpl::recognition_engine() const {
254 return *(recognition_engine_.get()); 276 return *(recognition_engine_.get());
255 } 277 }
256 278
257 SpeechRecognizerImpl::~SpeechRecognizerImpl() { 279 SpeechRecognizerImpl::~SpeechRecognizerImpl() {
258 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 280 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
259 endpointer_.EndSession(); 281 endpointer_.EndSession();
260 if (audio_controller_.get()) { 282 if (audio_controller_.get()) {
261 audio_controller_->Close( 283 audio_controller_->Close(
262 base::Bind(&KeepAudioControllerRefcountedForDtor, audio_controller_)); 284 base::Bind(&KeepAudioControllerRefcountedForDtor, audio_controller_));
263 audio_log_->OnClosed(0); 285 audio_log_->OnClosed(0);
286 } else if (audio_receiver_.get()) {
287 ResetAudioReceiver();
264 } 288 }
265 } 289 }
266 290
267 // Invoked in the audio thread. 291 // Invoked in the audio thread.
268 void SpeechRecognizerImpl::OnError(AudioInputController* controller, 292 void SpeechRecognizerImpl::OnError(AudioInputController* controller,
269 media::AudioInputController::ErrorCode error_code) { 293 media::AudioInputController::ErrorCode error_code) {
270 FSMEventArgs event_args(EVENT_AUDIO_ERROR); 294 FSMEventArgs event_args(EVENT_AUDIO_ERROR);
271 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 295 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
272 base::Bind(&SpeechRecognizerImpl::DispatchEvent, 296 base::Bind(&SpeechRecognizerImpl::DispatchEvent,
273 this, event_args)); 297 this, event_args));
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 state_ <= STATE_RECOGNIZING; 498 state_ <= STATE_RECOGNIZING;
475 const bool clip_detected = DetectClipping(raw_audio); 499 const bool clip_detected = DetectClipping(raw_audio);
476 float rms = 0.0f; 500 float rms = 0.0f;
477 501
478 num_samples_recorded_ += raw_audio.NumSamples(); 502 num_samples_recorded_ += raw_audio.NumSamples();
479 503
480 if (route_to_endpointer) 504 if (route_to_endpointer)
481 endpointer_.ProcessAudio(raw_audio, &rms); 505 endpointer_.ProcessAudio(raw_audio, &rms);
482 506
483 if (route_to_vumeter) { 507 if (route_to_vumeter) {
484 DCHECK(route_to_endpointer); // Depends on endpointer due to |rms|. 508 DCHECK(route_to_endpointer); // Depends on endpointer due to |rms|.
485 UpdateSignalAndNoiseLevels(rms, clip_detected); 509 UpdateSignalAndNoiseLevels(rms, clip_detected);
486 } 510 }
487 if (route_to_sr_engine) { 511 if (route_to_sr_engine) {
488 DCHECK(recognition_engine_.get() != NULL); 512 DCHECK(recognition_engine_.get() != NULL);
489 recognition_engine_->TakeAudioChunk(raw_audio); 513 recognition_engine_->TakeAudioChunk(raw_audio);
490 } 514 }
491 } 515 }
492 516
493 SpeechRecognizerImpl::FSMState 517 SpeechRecognizerImpl::FSMState
494 SpeechRecognizerImpl::StartRecording(const FSMEventArgs&) { 518 SpeechRecognizerImpl::StartRecording(const FSMEventArgs&) {
(...skipping 26 matching lines...) Expand all
521 return Abort(SpeechRecognitionError(SPEECH_RECOGNITION_ERROR_AUDIO)); 545 return Abort(SpeechRecognitionError(SPEECH_RECOGNITION_ERROR_AUDIO));
522 } 546 }
523 547
524 // Audio converter shall provide audio based on these parameters as output. 548 // Audio converter shall provide audio based on these parameters as output.
525 // Hard coded, WebSpeech specific parameters are utilized here. 549 // Hard coded, WebSpeech specific parameters are utilized here.
526 int frames_per_buffer = (kAudioSampleRate * chunk_duration_ms) / 1000; 550 int frames_per_buffer = (kAudioSampleRate * chunk_duration_ms) / 1000;
527 AudioParameters output_parameters = AudioParameters( 551 AudioParameters output_parameters = AudioParameters(
528 AudioParameters::AUDIO_PCM_LOW_LATENCY, kChannelLayout, kAudioSampleRate, 552 AudioParameters::AUDIO_PCM_LOW_LATENCY, kChannelLayout, kAudioSampleRate,
529 kNumBitsPerAudioSample, frames_per_buffer); 553 kNumBitsPerAudioSample, frames_per_buffer);
530 554
555 // Check if using audio receiver as source (audio data processed on renderer).
556 // If |StartRecordingUsingAudioReceiver()| fails, we abort the recognition.
557 if (using_audio_receiver_) {
558 return StartRecordingUsingAudioReceiver(output_parameters) ?
559 STATE_STARTING :
560 Abort(SpeechRecognitionError(SPEECH_RECOGNITION_ERROR_AUDIO));
561 }
562
563 // Get audio data from microphone on the browser.
564
531 // Audio converter will receive audio based on these parameters as input. 565 // Audio converter will receive audio based on these parameters as input.
532 // On Windows we start by verifying that Core Audio is supported. If not, 566 // On Windows we start by verifying that Core Audio is supported. If not,
533 // the WaveIn API is used and we might as well avoid all audio conversations 567 // the WaveIn API is used and we might as well avoid all audio conversations
534 // since WaveIn does the conversion for us. 568 // since WaveIn does the conversion for us.
535 // TODO(henrika): this code should be moved to platform dependent audio 569 // TODO(henrika): this code should be moved to platform dependent audio
536 // managers. 570 // managers.
537 bool use_native_audio_params = true; 571 bool use_native_audio_params = true;
538 #if defined(OS_WIN) 572 #if defined(OS_WIN)
539 use_native_audio_params = media::CoreAudioUtil::IsSupported(); 573 use_native_audio_params = media::CoreAudioUtil::IsSupported();
540 DVLOG_IF(1, !use_native_audio_params) << "Reverting to WaveIn for WebSpeech"; 574 DVLOG_IF(1, !use_native_audio_params) << "Reverting to WaveIn for WebSpeech";
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
577 // The endpointer needs to estimate the environment/background noise before 611 // The endpointer needs to estimate the environment/background noise before
578 // starting to treat the audio as user input. We wait in the state 612 // starting to treat the audio as user input. We wait in the state
579 // ESTIMATING_ENVIRONMENT until such interval has elapsed before switching 613 // ESTIMATING_ENVIRONMENT until such interval has elapsed before switching
580 // to user input mode. 614 // to user input mode.
581 endpointer_.SetEnvironmentEstimationMode(); 615 endpointer_.SetEnvironmentEstimationMode();
582 audio_controller_->Record(); 616 audio_controller_->Record();
583 audio_log_->OnStarted(0); 617 audio_log_->OnStarted(0);
584 return STATE_STARTING; 618 return STATE_STARTING;
585 } 619 }
586 620
621 bool SpeechRecognizerImpl::StartRecordingUsingAudioReceiver(
622 const media::AudioParameters& params) {
623 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
624 DCHECK(!audio_thread_.get());
625 DCHECK(!audio_receiver_.get());
626
627 audio_thread_.reset(new base::Thread("AudioReceiverThread"));
628 if (!audio_thread_->Start()) {
629 DLOG(ERROR) << "Cannot start new audio thread";
630 audio_thread_.reset();
631 return false;
632 }
633
634 // Start receiving audio, incoming data will be posted to |OnAudioTrackData|.
635 base::SharedMemoryHandle foreign_memory_handle;
636 base::SyncSocket::TransitDescriptor foreign_socket_descriptor;
637 audio_receiver_ = SpeechRecognitionAudioReceiver::Create(
638 params,
639 peer_process_handle_,
640 this, // Trigger OnData() and OnError() events here.
641 audio_thread_->task_runner().get(),
642 &foreign_memory_handle,
643 &foreign_socket_descriptor);
644
645 if (!audio_receiver_.get()) {
646 ResetAudioReceiver();
647 return false;
648 }
649
650 // Reusing the audio converter only to create chunks from the bus.
651 // Same input and output format indicate no additional conversion here.
652 audio_converter_.reset(new OnDataConverter(params, params));
653
654 // The endpointer needs to estimate the environment/background noise before
655 // starting to treat the audio as user input. We wait in the state
656 // ESTIMATING_ENVIRONMENT until such interval has elapsed before switching
657 // to user input mode.
658 endpointer_.SetEnvironmentEstimationMode();
659
660 listener()->OnAudioReceiverReady(session_id(),
661 params,
662 foreign_memory_handle,
663 foreign_socket_descriptor);
664
665 // Start listening on the receiver's audio thread.
666 audio_receiver_->StartListening();
667
668 return true;
669 }
670
671 void SpeechRecognizerImpl::ResetAudioReceiver() {
672 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
673
674 // We stop listening not to post any new tasks to the audio thread.
675 if (audio_receiver_.get())
676 audio_receiver_->Stop();
677
678 if (!audio_thread_.get())
679 return;
680
681 // This synchronous operation is usually instantaneous since the receiver
682 // closes the socket on Stop() and no new tasks will be posted to the
683 // |audio_thread_|.
684 const bool previous_io_allowed = base::ThreadRestrictions::SetIOAllowed(true);
685 audio_thread_->Stop();
686 base::ThreadRestrictions::SetIOAllowed(previous_io_allowed);
687
688 audio_thread_.reset();
689 audio_receiver_.reset();
690 }
691
587 SpeechRecognizerImpl::FSMState 692 SpeechRecognizerImpl::FSMState
588 SpeechRecognizerImpl::StartRecognitionEngine(const FSMEventArgs& event_args) { 693 SpeechRecognizerImpl::StartRecognitionEngine(const FSMEventArgs& event_args) {
589 // This is the first audio packet captured, so the recognition engine is 694 // This is the first audio packet captured, so the recognition engine is
590 // started and the delegate notified about the event. 695 // started and the delegate notified about the event.
591 DCHECK(recognition_engine_.get() != NULL); 696 DCHECK(recognition_engine_.get() != NULL);
592 recognition_engine_->StartRecognition(); 697 recognition_engine_->StartRecognition();
593 listener()->OnAudioStart(session_id()); 698 listener()->OnAudioStart(session_id());
594 699
595 // This is a little hack, since TakeAudioChunk() is already called by 700 // This is a little hack, since TakeAudioChunk() is already called by
596 // ProcessAudioPipeline(). It is the best tradeoff, unless we allow dropping 701 // ProcessAudioPipeline(). It is the best tradeoff, unless we allow dropping
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
762 867
763 SpeechRecognizerImpl::FSMState 868 SpeechRecognizerImpl::FSMState
764 SpeechRecognizerImpl::NotFeasible(const FSMEventArgs& event_args) { 869 SpeechRecognizerImpl::NotFeasible(const FSMEventArgs& event_args) {
765 NOTREACHED() << "Unfeasible event " << event_args.event 870 NOTREACHED() << "Unfeasible event " << event_args.event
766 << " in state " << state_; 871 << " in state " << state_;
767 return state_; 872 return state_;
768 } 873 }
769 874
770 void SpeechRecognizerImpl::CloseAudioControllerAsynchronously() { 875 void SpeechRecognizerImpl::CloseAudioControllerAsynchronously() {
771 DCHECK(IsCapturingAudio()); 876 DCHECK(IsCapturingAudio());
877
878 if (using_audio_receiver_) {
879 ResetAudioReceiver();
880 return;
881 }
882
772 DVLOG(1) << "SpeechRecognizerImpl closing audio controller."; 883 DVLOG(1) << "SpeechRecognizerImpl closing audio controller.";
773 // Issues a Close on the audio controller, passing an empty callback. The only 884 // Issues a Close on the audio controller, passing an empty callback. The only
774 // purpose of such callback is to keep the audio controller refcounted until 885 // purpose of such callback is to keep the audio controller refcounted until
775 // Close has completed (in the audio thread) and automatically destroy it 886 // Close has completed (in the audio thread) and automatically destroy it
776 // afterwards (upon return from OnAudioClosed). 887 // afterwards (upon return from OnAudioClosed).
777 audio_controller_->Close(base::Bind(&SpeechRecognizerImpl::OnAudioClosed, 888 audio_controller_->Close(base::Bind(&SpeechRecognizerImpl::OnAudioClosed,
778 this, audio_controller_)); 889 this, audio_controller_));
779 audio_controller_ = NULL; // The controller is still refcounted by Bind. 890 audio_controller_ = NULL; // The controller is still refcounted by Bind.
780 audio_log_->OnClosed(0); 891 audio_log_->OnClosed(0);
781 } 892 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
814 SpeechRecognizerImpl::FSMEventArgs::FSMEventArgs(FSMEvent event_value) 925 SpeechRecognizerImpl::FSMEventArgs::FSMEventArgs(FSMEvent event_value)
815 : event(event_value), 926 : event(event_value),
816 audio_data(NULL), 927 audio_data(NULL),
817 engine_error(SPEECH_RECOGNITION_ERROR_NONE) { 928 engine_error(SPEECH_RECOGNITION_ERROR_NONE) {
818 } 929 }
819 930
820 SpeechRecognizerImpl::FSMEventArgs::~FSMEventArgs() { 931 SpeechRecognizerImpl::FSMEventArgs::~FSMEventArgs() {
821 } 932 }
822 933
823 } // namespace content 934 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/speech/speech_recognizer_impl.h ('k') | content/browser/speech/speech_recognizer_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698