OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/google_streaming_remote_engine.h" | 5 #include "content/browser/speech/google_streaming_remote_engine.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/big_endian.h" | 10 #include "base/big_endian.h" |
(...skipping 20 matching lines...) Expand all Loading... |
31 | 31 |
32 namespace content { | 32 namespace content { |
33 namespace { | 33 namespace { |
34 | 34 |
35 const char kWebServiceBaseUrl[] = | 35 const char kWebServiceBaseUrl[] = |
36 "https://www.google.com/speech-api/full-duplex/v1"; | 36 "https://www.google.com/speech-api/full-duplex/v1"; |
37 const char kDownstreamUrl[] = "/down?"; | 37 const char kDownstreamUrl[] = "/down?"; |
38 const char kUpstreamUrl[] = "/up?"; | 38 const char kUpstreamUrl[] = "/up?"; |
39 | 39 |
40 // This matches the maximum maxAlternatives value supported by the server. | 40 // This matches the maximum maxAlternatives value supported by the server. |
41 const uint32 kMaxMaxAlternatives = 30; | 41 const uint32_t kMaxMaxAlternatives = 30; |
42 | 42 |
43 // TODO(hans): Remove this and other logging when we don't need it anymore. | 43 // TODO(hans): Remove this and other logging when we don't need it anymore. |
44 void DumpResponse(const std::string& response) { | 44 void DumpResponse(const std::string& response) { |
45 DVLOG(1) << "------------"; | 45 DVLOG(1) << "------------"; |
46 proto::SpeechRecognitionEvent event; | 46 proto::SpeechRecognitionEvent event; |
47 if (!event.ParseFromString(response)) { | 47 if (!event.ParseFromString(response)) { |
48 DVLOG(1) << "Parse failed!"; | 48 DVLOG(1) << "Parse failed!"; |
49 return; | 49 return; |
50 } | 50 } |
51 if (event.has_status()) | 51 if (event.has_status()) |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 FSMEventArgs event_args(EVENT_AUDIO_CHUNKS_ENDED); | 114 FSMEventArgs event_args(EVENT_AUDIO_CHUNKS_ENDED); |
115 DispatchEvent(event_args); | 115 DispatchEvent(event_args); |
116 } | 116 } |
117 | 117 |
118 void GoogleStreamingRemoteEngine::OnURLFetchComplete(const URLFetcher* source) { | 118 void GoogleStreamingRemoteEngine::OnURLFetchComplete(const URLFetcher* source) { |
119 const bool kResponseComplete = true; | 119 const bool kResponseComplete = true; |
120 DispatchHTTPResponse(source, kResponseComplete); | 120 DispatchHTTPResponse(source, kResponseComplete); |
121 } | 121 } |
122 | 122 |
123 void GoogleStreamingRemoteEngine::OnURLFetchDownloadProgress( | 123 void GoogleStreamingRemoteEngine::OnURLFetchDownloadProgress( |
124 const URLFetcher* source, int64 current, int64 total) { | 124 const URLFetcher* source, |
| 125 int64_t current, |
| 126 int64_t total) { |
125 const bool kPartialResponse = false; | 127 const bool kPartialResponse = false; |
126 DispatchHTTPResponse(source, kPartialResponse); | 128 DispatchHTTPResponse(source, kPartialResponse); |
127 } | 129 } |
128 | 130 |
129 void GoogleStreamingRemoteEngine::DispatchHTTPResponse(const URLFetcher* source, | 131 void GoogleStreamingRemoteEngine::DispatchHTTPResponse(const URLFetcher* source, |
130 bool end_of_response) { | 132 bool end_of_response) { |
131 DCHECK(CalledOnValidThread()); | 133 DCHECK(CalledOnValidThread()); |
132 DCHECK(source); | 134 DCHECK(source); |
133 const bool response_is_good = source->GetStatus().is_success() && | 135 const bool response_is_good = source->GetStatus().is_success() && |
134 source->GetResponseCode() == 200; | 136 source->GetResponseCode() == 200; |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 std::vector<std::string> upstream_args; | 336 std::vector<std::string> upstream_args; |
335 upstream_args.push_back("key=" + | 337 upstream_args.push_back("key=" + |
336 net::EscapeQueryParamValue(google_apis::GetAPIKey(), true)); | 338 net::EscapeQueryParamValue(google_apis::GetAPIKey(), true)); |
337 upstream_args.push_back("pair=" + request_key); | 339 upstream_args.push_back("pair=" + request_key); |
338 upstream_args.push_back("output=pb"); | 340 upstream_args.push_back("output=pb"); |
339 upstream_args.push_back( | 341 upstream_args.push_back( |
340 "lang=" + net::EscapeQueryParamValue(GetAcceptedLanguages(), true)); | 342 "lang=" + net::EscapeQueryParamValue(GetAcceptedLanguages(), true)); |
341 upstream_args.push_back( | 343 upstream_args.push_back( |
342 config_.filter_profanities ? "pFilter=2" : "pFilter=0"); | 344 config_.filter_profanities ? "pFilter=2" : "pFilter=0"); |
343 if (config_.max_hypotheses > 0U) { | 345 if (config_.max_hypotheses > 0U) { |
344 uint32 max_alternatives = | 346 uint32_t max_alternatives = |
345 std::min(kMaxMaxAlternatives, config_.max_hypotheses); | 347 std::min(kMaxMaxAlternatives, config_.max_hypotheses); |
346 upstream_args.push_back("maxAlternatives=" + | 348 upstream_args.push_back("maxAlternatives=" + |
347 base::UintToString(max_alternatives)); | 349 base::UintToString(max_alternatives)); |
348 } | 350 } |
349 upstream_args.push_back("app=chromium"); | 351 upstream_args.push_back("app=chromium"); |
350 if (!config_.hardware_info.empty()) { | 352 if (!config_.hardware_info.empty()) { |
351 upstream_args.push_back( | 353 upstream_args.push_back( |
352 "xhw=" + net::EscapeQueryParamValue(config_.hardware_info, true)); | 354 "xhw=" + net::EscapeQueryParamValue(config_.hardware_info, true)); |
353 } | 355 } |
354 for (const SpeechRecognitionGrammar& grammar : config_.grammars) { | 356 for (const SpeechRecognitionGrammar& grammar : config_.grammars) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391 upstream_fetcher_->SetReferrer(config_.origin_url); | 393 upstream_fetcher_->SetReferrer(config_.origin_url); |
392 upstream_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | | 394 upstream_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | |
393 net::LOAD_DO_NOT_SEND_COOKIES | | 395 net::LOAD_DO_NOT_SEND_COOKIES | |
394 net::LOAD_DO_NOT_SEND_AUTH_DATA); | 396 net::LOAD_DO_NOT_SEND_AUTH_DATA); |
395 upstream_fetcher_->Start(); | 397 upstream_fetcher_->Start(); |
396 previous_response_length_ = 0; | 398 previous_response_length_ = 0; |
397 | 399 |
398 if (preamble_encoder_) { | 400 if (preamble_encoder_) { |
399 // Encode and send preamble right away. | 401 // Encode and send preamble right away. |
400 scoped_refptr<AudioChunk> chunk = new AudioChunk( | 402 scoped_refptr<AudioChunk> chunk = new AudioChunk( |
401 reinterpret_cast<const uint8*>(config_.preamble->sample_data.data()), | 403 reinterpret_cast<const uint8_t*>(config_.preamble->sample_data.data()), |
402 config_.preamble->sample_data.size(), | 404 config_.preamble->sample_data.size(), config_.preamble->sample_depth); |
403 config_.preamble->sample_depth); | |
404 preamble_encoder_->Encode(*chunk); | 405 preamble_encoder_->Encode(*chunk); |
405 preamble_encoder_->Flush(); | 406 preamble_encoder_->Flush(); |
406 scoped_refptr<AudioChunk> encoded_data( | 407 scoped_refptr<AudioChunk> encoded_data( |
407 preamble_encoder_->GetEncodedDataAndClear()); | 408 preamble_encoder_->GetEncodedDataAndClear()); |
408 UploadAudioChunk(encoded_data->AsString(), FRAME_PREAMBLE_AUDIO, false); | 409 UploadAudioChunk(encoded_data->AsString(), FRAME_PREAMBLE_AUDIO, false); |
409 } | 410 } |
410 return STATE_BOTH_STREAMS_CONNECTED; | 411 return STATE_BOTH_STREAMS_CONNECTED; |
411 } | 412 } |
412 | 413 |
413 GoogleStreamingRemoteEngine::FSMState | 414 GoogleStreamingRemoteEngine::FSMState |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
512 DCHECK(upstream_fetcher_.get()); | 513 DCHECK(upstream_fetcher_.get()); |
513 DCHECK(encoder_.get()); | 514 DCHECK(encoder_.get()); |
514 | 515 |
515 DVLOG(1) << "Closing upstream."; | 516 DVLOG(1) << "Closing upstream."; |
516 | 517 |
517 // The encoder requires a non-empty final buffer. So we encode a packet | 518 // The encoder requires a non-empty final buffer. So we encode a packet |
518 // of silence in case encoder had no data already. | 519 // of silence in case encoder had no data already. |
519 size_t sample_count = | 520 size_t sample_count = |
520 config_.audio_sample_rate * kAudioPacketIntervalMs / 1000; | 521 config_.audio_sample_rate * kAudioPacketIntervalMs / 1000; |
521 scoped_refptr<AudioChunk> dummy_chunk = new AudioChunk( | 522 scoped_refptr<AudioChunk> dummy_chunk = new AudioChunk( |
522 sample_count * sizeof(int16), encoder_->GetBitsPerSample() / 8); | 523 sample_count * sizeof(int16_t), encoder_->GetBitsPerSample() / 8); |
523 encoder_->Encode(*dummy_chunk.get()); | 524 encoder_->Encode(*dummy_chunk.get()); |
524 encoder_->Flush(); | 525 encoder_->Flush(); |
525 scoped_refptr<AudioChunk> encoded_dummy_data = | 526 scoped_refptr<AudioChunk> encoded_dummy_data = |
526 encoder_->GetEncodedDataAndClear(); | 527 encoder_->GetEncodedDataAndClear(); |
527 DCHECK(!encoded_dummy_data->IsEmpty()); | 528 DCHECK(!encoded_dummy_data->IsEmpty()); |
528 encoder_.reset(); | 529 encoder_.reset(); |
529 | 530 |
530 UploadAudioChunk(encoded_dummy_data->AsString(), | 531 UploadAudioChunk(encoded_dummy_data->AsString(), |
531 FRAME_RECOGNITION_AUDIO, | 532 FRAME_RECOGNITION_AUDIO, |
532 true); | 533 true); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
600 langs = accepted_language_list.substr(0, separator); | 601 langs = accepted_language_list.substr(0, separator); |
601 } | 602 } |
602 } | 603 } |
603 if (langs.empty()) | 604 if (langs.empty()) |
604 langs = "en-US"; | 605 langs = "en-US"; |
605 return langs; | 606 return langs; |
606 } | 607 } |
607 | 608 |
608 // TODO(primiano): Is there any utility in the codebase that already does this? | 609 // TODO(primiano): Is there any utility in the codebase that already does this? |
609 std::string GoogleStreamingRemoteEngine::GenerateRequestKey() const { | 610 std::string GoogleStreamingRemoteEngine::GenerateRequestKey() const { |
610 const int64 kKeepLowBytes = 0x00000000FFFFFFFFLL; | 611 const int64_t kKeepLowBytes = 0x00000000FFFFFFFFLL; |
611 const int64 kKeepHighBytes = 0xFFFFFFFF00000000LL; | 612 const int64_t kKeepHighBytes = 0xFFFFFFFF00000000LL; |
612 | 613 |
613 // Just keep the least significant bits of timestamp, in order to reduce | 614 // Just keep the least significant bits of timestamp, in order to reduce |
614 // probability of collisions. | 615 // probability of collisions. |
615 int64 key = (base::Time::Now().ToInternalValue() & kKeepLowBytes) | | 616 int64_t key = (base::Time::Now().ToInternalValue() & kKeepLowBytes) | |
616 (base::RandUint64() & kKeepHighBytes); | 617 (base::RandUint64() & kKeepHighBytes); |
617 return base::HexEncode(reinterpret_cast<void*>(&key), sizeof(key)); | 618 return base::HexEncode(reinterpret_cast<void*>(&key), sizeof(key)); |
618 } | 619 } |
619 | 620 |
620 void GoogleStreamingRemoteEngine::UploadAudioChunk(const std::string& data, | 621 void GoogleStreamingRemoteEngine::UploadAudioChunk(const std::string& data, |
621 FrameType type, | 622 FrameType type, |
622 bool is_final) { | 623 bool is_final) { |
623 if (use_framed_post_data_) { | 624 if (use_framed_post_data_) { |
624 std::string frame(data.size() + 8, 0); | 625 std::string frame(data.size() + 8, 0); |
625 base::WriteBigEndian(&frame[0], static_cast<uint32_t>(data.size())); | 626 base::WriteBigEndian(&frame[0], static_cast<uint32_t>(data.size())); |
626 base::WriteBigEndian(&frame[4], static_cast<uint32_t>(type)); | 627 base::WriteBigEndian(&frame[4], static_cast<uint32_t>(type)); |
627 frame.replace(8, data.size(), data); | 628 frame.replace(8, data.size(), data); |
628 upstream_fetcher_->AppendChunkToUpload(frame, is_final); | 629 upstream_fetcher_->AppendChunkToUpload(frame, is_final); |
629 } else { | 630 } else { |
630 upstream_fetcher_->AppendChunkToUpload(data, is_final); | 631 upstream_fetcher_->AppendChunkToUpload(data, is_final); |
631 } | 632 } |
632 } | 633 } |
633 | 634 |
634 GoogleStreamingRemoteEngine::FSMEventArgs::FSMEventArgs(FSMEvent event_value) | 635 GoogleStreamingRemoteEngine::FSMEventArgs::FSMEventArgs(FSMEvent event_value) |
635 : event(event_value) { | 636 : event(event_value) { |
636 } | 637 } |
637 | 638 |
638 GoogleStreamingRemoteEngine::FSMEventArgs::~FSMEventArgs() { | 639 GoogleStreamingRemoteEngine::FSMEventArgs::~FSMEventArgs() { |
639 } | 640 } |
640 | 641 |
641 } // namespace content | 642 } // namespace content |
OLD | NEW |