blob: a6e4fb258c6b2483b8e1c21781e0a50911796adc [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/speech/cros_speech_recognition_service.h"
#include "base/files/file_path.h"
#include "base/types/optional_util.h"
#include "chrome/services/speech/audio_source_fetcher_impl.h"
#include "chrome/services/speech/cros_speech_recognition_recognizer_impl.h"
#include "components/soda/constants.h"
#include "components/soda/soda_installer.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "media/base/media_switches.h"
#include "media/mojo/mojom/speech_recognition.mojom.h"
#include "media/mojo/mojom/speech_recognition_service.mojom.h"
namespace speech {
namespace {
void PopulateFilePaths(const std::string* language,
base::FilePath& binary_path,
base::FilePath& languagepack_path) {
speech::SodaInstaller* soda_installer = speech::SodaInstaller::GetInstance();
// TODO(crbug.com/1161569): Language should not be optional in
// PopulateFilePaths, as it will be required once we support multiple
// languages since the CrosSpeechRecognitionService supports several
// features at once. For now only US English is available.
LanguageCode language_code =
language ? GetLanguageCode(*language) : LanguageCode::kEnUs;
if (!soda_installer->IsSodaInstalled(language_code)) {
LOG(DFATAL) << "Instantiation of SODA requested with language "
<< GetLanguageName(language_code)
<< ", but either SODA or the requested language was not "
"already installed";
return;
}
binary_path = soda_installer->GetSodaBinaryPath();
languagepack_path =
soda_installer->GetLanguagePath(GetLanguageName(language_code));
}
} // namespace
CrosSpeechRecognitionService::CrosSpeechRecognitionService(
content::BrowserContext* context)
: ChromeSpeechRecognitionService(context) {}
CrosSpeechRecognitionService::~CrosSpeechRecognitionService() {}
void CrosSpeechRecognitionService::BindSpeechRecognitionContext(
mojo::PendingReceiver<media::mojom::SpeechRecognitionContext> receiver) {
speech_recognition_contexts_.Add(this, std::move(receiver));
}
void CrosSpeechRecognitionService::BindAudioSourceSpeechRecognitionContext(
mojo::PendingReceiver<media::mojom::AudioSourceSpeechRecognitionContext>
receiver) {
audio_source_speech_recognition_contexts_.Add(this, std::move(receiver));
}
void CrosSpeechRecognitionService::BindRecognizer(
mojo::PendingReceiver<media::mojom::SpeechRecognitionRecognizer> receiver,
mojo::PendingRemote<media::mojom::SpeechRecognitionRecognizerClient> client,
media::mojom::SpeechRecognitionOptionsPtr options,
BindRecognizerCallback callback) {
base::FilePath binary_path, languagepack_path;
PopulateFilePaths(base::OptionalToPtr(options->language), binary_path,
languagepack_path);
CrosSpeechRecognitionRecognizerImpl::Create(
std::move(receiver), std::move(client),
nullptr /* =SpeechRecognitionService WeakPtr*/, std::move(options),
binary_path, languagepack_path);
std::move(callback).Run(
CrosSpeechRecognitionRecognizerImpl::IsMultichannelSupported());
}
void CrosSpeechRecognitionService::BindAudioSourceFetcher(
mojo::PendingReceiver<media::mojom::AudioSourceFetcher> fetcher_receiver,
mojo::PendingRemote<media::mojom::SpeechRecognitionRecognizerClient> client,
media::mojom::SpeechRecognitionOptionsPtr options,
BindRecognizerCallback callback) {
base::FilePath binary_path, languagepack_path;
PopulateFilePaths(base::OptionalToPtr(options->language), binary_path,
languagepack_path);
// CrosSpeechRecognitionService runs on browser UI thread.
// Create AudioSourceFetcher on browser IO thread to avoid UI jank.
// Note that its CrosSpeechRecognitionRecognizer must also run
// on the IO thread. If CrosSpeechRecognitionService is moved away from
// browser UI thread, we can call AudioSourceFetcherImpl::Create directly.
content::GetIOThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(
&CrosSpeechRecognitionService::CreateAudioSourceFetcherOnIOThread,
weak_factory_.GetWeakPtr(), std::move(fetcher_receiver),
std::move(client), std::move(options), binary_path,
languagepack_path));
std::move(callback).Run(
CrosSpeechRecognitionRecognizerImpl::IsMultichannelSupported());
}
void CrosSpeechRecognitionService::CreateAudioSourceFetcherOnIOThread(
mojo::PendingReceiver<media::mojom::AudioSourceFetcher> fetcher_receiver,
mojo::PendingRemote<media::mojom::SpeechRecognitionRecognizerClient> client,
media::mojom::SpeechRecognitionOptionsPtr options,
const base::FilePath& binary_path,
const base::FilePath& languagepack_path) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
AudioSourceFetcherImpl::Create(
std::move(fetcher_receiver),
std::make_unique<CrosSpeechRecognitionRecognizerImpl>(
std::move(client), nullptr /* =SpeechRecognitionService WeakPtr*/,
std::move(options), binary_path, languagepack_path));
}
} // namespace speech