audio_manager_cras.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "media/audio/cras/audio_manager_cras.h"
  5. #include <stddef.h>
  6. #include <algorithm>
  7. #include <map>
  8. #include <utility>
  9. #include "base/bind.h"
  10. #include "base/check_op.h"
  11. #include "base/command_line.h"
  12. #include "base/environment.h"
  13. #include "base/metrics/field_trial_params.h"
  14. #include "base/nix/xdg_util.h"
  15. #include "base/strings/string_number_conversions.h"
  16. #include "base/system/sys_info.h"
  17. #include "base/threading/thread_task_runner_handle.h"
  18. #include "media/audio/audio_device_description.h"
  19. #include "media/audio/audio_features.h"
  20. #include "media/audio/cras/cras_input.h"
  21. #include "media/audio/cras/cras_unified.h"
  22. #include "media/audio/cras/cras_util.h"
  23. #include "media/base/channel_layout.h"
  24. #include "media/base/limits.h"
  25. #include "media/base/localized_strings.h"
  26. namespace media {
  27. namespace {
  28. // Default sample rate for input and output streams.
  29. const int kDefaultSampleRate = 48000;
  30. // Default input buffer size.
  31. const int kDefaultInputBufferSize = 1024;
  32. // Default output buffer size.
  33. const int kDefaultOutputBufferSize = 512;
  34. } // namespace
  35. bool AudioManagerCras::HasAudioOutputDevices() {
  36. return true;
  37. }
  38. bool AudioManagerCras::HasAudioInputDevices() {
  39. return !cras_util_->CrasGetAudioDevices(DeviceType::kInput).empty();
  40. }
  41. AudioManagerCras::AudioManagerCras(std::unique_ptr<AudioThread> audio_thread,
  42. AudioLogFactory* audio_log_factory)
  43. : AudioManagerCrasBase(std::move(audio_thread), audio_log_factory),
  44. cras_util_(std::make_unique<CrasUtil>()),
  45. main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
  46. weak_ptr_factory_(this) {
  47. weak_this_ = weak_ptr_factory_.GetWeakPtr();
  48. }
  49. AudioManagerCras::~AudioManagerCras() = default;
  50. void AudioManagerCras::GetAudioInputDeviceNames(
  51. AudioDeviceNames* device_names) {
  52. for (const auto& device :
  53. cras_util_->CrasGetAudioDevices(DeviceType::kInput)) {
  54. device_names->emplace_back(device.name, base::NumberToString(device.id));
  55. }
  56. if (!device_names->empty())
  57. device_names->push_front(AudioDeviceName::CreateDefault());
  58. }
  59. void AudioManagerCras::GetAudioOutputDeviceNames(
  60. AudioDeviceNames* device_names) {
  61. for (const auto& device :
  62. cras_util_->CrasGetAudioDevices(DeviceType::kOutput)) {
  63. device_names->emplace_back(device.name, base::NumberToString(device.id));
  64. }
  65. if (!device_names->empty())
  66. device_names->push_front(AudioDeviceName::CreateDefault());
  67. }
  68. // Checks if a system AEC with a specific group ID is flagged to be deactivated
  69. // by the field trial.
  70. bool IsSystemAecDeactivated(int aec_group_id) {
  71. return base::GetFieldTrialParamByFeatureAsBool(
  72. features::kCrOSSystemAECDeactivatedGroups,
  73. base::NumberToString(aec_group_id), false);
  74. }
  75. // Checks if the board with `aec_group_id` is flagged by the field trial to not
  76. // allow using DSP-based AEC effect.
  77. bool IsDspBasedAecDeactivated(int aec_group_id) {
  78. return base::GetFieldTrialParamByFeatureAsBool(
  79. features::kCrOSDspBasedAecDeactivatedGroups,
  80. base::NumberToString(aec_group_id), false) ||
  81. !base::FeatureList::IsEnabled(features::kCrOSDspBasedAecAllowed);
  82. }
  83. // Checks if the board with `aec_group_id` is flagged by the field trial to not
  84. // allow using DSP-based NS effect.
  85. bool IsDspBasedNsDeactivated(int aec_group_id) {
  86. return base::GetFieldTrialParamByFeatureAsBool(
  87. features::kCrOSDspBasedNsDeactivatedGroups,
  88. base::NumberToString(aec_group_id), false) ||
  89. !base::FeatureList::IsEnabled(features::kCrOSDspBasedNsAllowed);
  90. }
  91. // Checks if the board with `aec_group_id` is flagged by the field trial to not
  92. // allow using DSP-based AGC effect.
  93. bool IsDspBasedAgcDeactivated(int aec_group_id) {
  94. return base::GetFieldTrialParamByFeatureAsBool(
  95. features::kCrOSDspBasedAgcDeactivatedGroups,
  96. base::NumberToString(aec_group_id), false) ||
  97. !base::FeatureList::IsEnabled(features::kCrOSDspBasedAgcAllowed);
  98. }
  99. // Specifies which DSP-based effects are allowed based on media constraints and
  100. // any finch field trials.
  101. void SetAllowedDspBasedEffects(int aec_group_id, AudioParameters& params) {
  102. int effects = params.effects();
  103. // Allow AEC to be applied by CRAS on DSP if the AEC is active in CRAS and if
  104. // using the AEC on DSP has not been deactivated by any field trials.
  105. if ((effects & AudioParameters::ECHO_CANCELLER) &&
  106. !IsDspBasedAecDeactivated(aec_group_id)) {
  107. effects = effects | AudioParameters::ALLOW_DSP_ECHO_CANCELLER;
  108. } else {
  109. effects = effects & ~AudioParameters::ALLOW_DSP_ECHO_CANCELLER;
  110. }
  111. // Allow NS to be applied by CRAS on DSP if the NS is active in CRAS and if
  112. // using the NS on DSP has not been deactivated by any field trials.
  113. if ((effects & AudioParameters::NOISE_SUPPRESSION) &&
  114. !IsDspBasedNsDeactivated(aec_group_id)) {
  115. effects = effects | AudioParameters::ALLOW_DSP_NOISE_SUPPRESSION;
  116. } else {
  117. effects = effects & ~AudioParameters::ALLOW_DSP_NOISE_SUPPRESSION;
  118. }
  119. // Allow AGC to be applied by CRAS on DSP if the AGC is active in CRAS and if
  120. // using the AGC on DSP has not been deactivated by any field trials.
  121. if ((effects & AudioParameters::AUTOMATIC_GAIN_CONTROL) &&
  122. !IsDspBasedAgcDeactivated(aec_group_id)) {
  123. effects = effects | AudioParameters::ALLOW_DSP_AUTOMATIC_GAIN_CONTROL;
  124. } else {
  125. effects = effects & ~AudioParameters::ALLOW_DSP_AUTOMATIC_GAIN_CONTROL;
  126. }
  127. params.set_effects(effects);
  128. }
  129. // Collects flags values for whether, and in what way, the AEC, NS or AGC
  130. // effects should be enforced in spite of them not being flagged as supported by
  131. // the board.
  132. void RetrieveSystemEffectFeatures(bool& enforce_system_aec,
  133. bool& enforce_system_ns,
  134. bool& enforce_system_agc,
  135. bool& tuned_system_aec_allowed) {
  136. const bool enforce_system_aec_ns_agc_feature =
  137. base::FeatureList::IsEnabled(features::kCrOSEnforceSystemAecNsAgc);
  138. const bool enforce_system_aec_ns_feature =
  139. base::FeatureList::IsEnabled(features::kCrOSEnforceSystemAecNs);
  140. const bool enforce_system_aec_agc_feature =
  141. base::FeatureList::IsEnabled(features::kCrOSEnforceSystemAecAgc);
  142. const bool enforce_system_aec_feature =
  143. base::FeatureList::IsEnabled(features::kCrOSEnforceSystemAec);
  144. enforce_system_aec =
  145. enforce_system_aec_feature || enforce_system_aec_ns_agc_feature ||
  146. enforce_system_aec_ns_feature || enforce_system_aec_agc_feature;
  147. enforce_system_ns =
  148. enforce_system_aec_ns_agc_feature || enforce_system_aec_ns_feature;
  149. enforce_system_agc =
  150. enforce_system_aec_ns_agc_feature || enforce_system_aec_agc_feature;
  151. tuned_system_aec_allowed =
  152. base::FeatureList::IsEnabled(features::kCrOSSystemAEC);
  153. }
  154. AudioParameters AudioManagerCras::GetStreamParametersForSystem(
  155. int user_buffer_size) {
  156. AudioParameters params(
  157. AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
  158. kDefaultSampleRate, user_buffer_size,
  159. AudioParameters::HardwareCapabilities(limits::kMinAudioBufferSize,
  160. limits::kMaxAudioBufferSize));
  161. bool enforce_system_aec;
  162. bool enforce_system_ns;
  163. bool enforce_system_agc;
  164. bool tuned_system_aec_allowed;
  165. RetrieveSystemEffectFeatures(enforce_system_aec, enforce_system_ns,
  166. enforce_system_agc, tuned_system_aec_allowed);
  167. // Activation of the system AEC. Allow experimentation with system AEC with
  168. // all devices, but enable it by default on devices that actually support it.
  169. params.set_effects(params.effects() |
  170. AudioParameters::EXPERIMENTAL_ECHO_CANCELLER);
  171. // Rephrase the field aec_supported to properly reflect its meaning in this
  172. // context (since it currently signals whether an CrAS APM with tuned settings
  173. // is available).
  174. // TODO(crbug.com/1307680): add unit tests and caching cras_util_ results.
  175. const bool tuned_system_apm_available = cras_util_->CrasGetAecSupported();
  176. // Don't use the system AEC if it is deactivated for this group ID. Also never
  177. // activate NS nor AGC for this board if the AEC is not activated, since this
  178. // will cause issues for the Browser AEC.
  179. bool use_system_aec =
  180. (tuned_system_apm_available && tuned_system_aec_allowed) ||
  181. enforce_system_aec;
  182. // TODO(hychao): query from CRAS
  183. bool system_ns_supported = true;
  184. bool system_agc_supported = true;
  185. int aec_group_id = cras_util_->CrasGetAecGroupId();
  186. if (!use_system_aec || IsSystemAecDeactivated(aec_group_id)) {
  187. SetAllowedDspBasedEffects(aec_group_id, params);
  188. return params;
  189. }
  190. // Activation of the system AEC.
  191. params.set_effects(params.effects() | AudioParameters::ECHO_CANCELLER);
  192. // Don't use system NS or AGC if the AEC has board-specific tunings.
  193. if (!tuned_system_apm_available) {
  194. // Activation of the system NS.
  195. if (system_ns_supported || enforce_system_ns) {
  196. params.set_effects(params.effects() | AudioParameters::NOISE_SUPPRESSION);
  197. }
  198. // Activation of the system AGC.
  199. if (system_agc_supported || enforce_system_agc) {
  200. params.set_effects(params.effects() |
  201. AudioParameters::AUTOMATIC_GAIN_CONTROL);
  202. }
  203. }
  204. SetAllowedDspBasedEffects(aec_group_id, params);
  205. return params;
  206. }
  207. AudioParameters AudioManagerCras::GetInputStreamParameters(
  208. const std::string& device_id) {
  209. DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  210. int user_buffer_size = GetUserBufferSize();
  211. user_buffer_size =
  212. user_buffer_size ? user_buffer_size : kDefaultInputBufferSize;
  213. return GetStreamParametersForSystem(user_buffer_size);
  214. }
  215. std::string AudioManagerCras::GetDefaultInputDeviceID() {
  216. DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  217. return base::NumberToString(GetPrimaryActiveInputNode());
  218. }
  219. std::string AudioManagerCras::GetDefaultOutputDeviceID() {
  220. DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  221. return base::NumberToString(GetPrimaryActiveOutputNode());
  222. }
  223. std::string AudioManagerCras::GetGroupIDInput(const std::string& device_id) {
  224. for (const auto& device :
  225. cras_util_->CrasGetAudioDevices(DeviceType::kInput)) {
  226. if (base::NumberToString(device.id) == device_id ||
  227. (AudioDeviceDescription::IsDefaultDevice(device_id) && device.active)) {
  228. return device.dev_name;
  229. }
  230. }
  231. return "";
  232. }
  233. std::string AudioManagerCras::GetGroupIDOutput(const std::string& device_id) {
  234. for (const auto& device :
  235. cras_util_->CrasGetAudioDevices(DeviceType::kOutput)) {
  236. if (base::NumberToString(device.id) == device_id ||
  237. (AudioDeviceDescription::IsDefaultDevice(device_id) && device.active)) {
  238. return device.dev_name;
  239. }
  240. }
  241. return "";
  242. }
  243. std::string AudioManagerCras::GetAssociatedOutputDeviceID(
  244. const std::string& input_device_id) {
  245. if (AudioDeviceDescription::IsDefaultDevice(input_device_id)) {
  246. // Note: the default input should not be associated to any output, as this
  247. // may lead to accidental uses of a pinned stream.
  248. return "";
  249. }
  250. std::string device_name = GetGroupIDInput(input_device_id);
  251. if (device_name.empty())
  252. return "";
  253. // Now search for an output device with the same device name.
  254. for (const auto& device :
  255. cras_util_->CrasGetAudioDevices(DeviceType::kOutput)) {
  256. if (device.dev_name == device_name)
  257. return base::NumberToString(device.id);
  258. }
  259. return "";
  260. }
  261. AudioParameters AudioManagerCras::GetPreferredOutputStreamParameters(
  262. const std::string& output_device_id,
  263. const AudioParameters& input_params) {
  264. DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  265. ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
  266. int sample_rate = kDefaultSampleRate;
  267. int buffer_size = GetUserBufferSize();
  268. if (input_params.IsValid()) {
  269. channel_layout = input_params.channel_layout();
  270. sample_rate = input_params.sample_rate();
  271. if (!buffer_size) // Not user-provided.
  272. buffer_size =
  273. std::min(static_cast<int>(limits::kMaxAudioBufferSize),
  274. std::max(static_cast<int>(limits::kMinAudioBufferSize),
  275. input_params.frames_per_buffer()));
  276. return AudioParameters(
  277. AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, sample_rate,
  278. buffer_size,
  279. AudioParameters::HardwareCapabilities(limits::kMinAudioBufferSize,
  280. limits::kMaxAudioBufferSize));
  281. }
  282. // Get max supported channels from |output_device_id| or the primary active
  283. // one if |output_device_id| is the default device.
  284. uint64_t preferred_device_id;
  285. if (AudioDeviceDescription::IsDefaultDevice(output_device_id)) {
  286. preferred_device_id = GetPrimaryActiveOutputNode();
  287. } else {
  288. if (!base::StringToUint64(output_device_id, &preferred_device_id))
  289. preferred_device_id = 0; // 0 represents invalid |output_device_id|.
  290. }
  291. for (const auto& device :
  292. cras_util_->CrasGetAudioDevices(DeviceType::kOutput)) {
  293. if (device.id == preferred_device_id) {
  294. channel_layout =
  295. GuessChannelLayout(static_cast<int>(device.max_supported_channels));
  296. // Fall-back to old fashion: always fixed to STEREO layout.
  297. if (channel_layout == CHANNEL_LAYOUT_UNSUPPORTED) {
  298. channel_layout = CHANNEL_LAYOUT_STEREO;
  299. }
  300. break;
  301. }
  302. }
  303. if (!buffer_size) // Not user-provided.
  304. buffer_size = cras_util_->CrasGetDefaultOutputBufferSize();
  305. if (buffer_size <= 0)
  306. buffer_size = kDefaultOutputBufferSize;
  307. return AudioParameters(
  308. AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, sample_rate,
  309. buffer_size,
  310. AudioParameters::HardwareCapabilities(limits::kMinAudioBufferSize,
  311. limits::kMaxAudioBufferSize));
  312. }
  313. uint64_t AudioManagerCras::GetPrimaryActiveInputNode() {
  314. for (const auto& device :
  315. cras_util_->CrasGetAudioDevices(DeviceType::kInput)) {
  316. if (device.active)
  317. return device.id;
  318. }
  319. return 0;
  320. }
  321. uint64_t AudioManagerCras::GetPrimaryActiveOutputNode() {
  322. for (const auto& device :
  323. cras_util_->CrasGetAudioDevices(DeviceType::kOutput)) {
  324. if (device.active)
  325. return device.id;
  326. }
  327. return 0;
  328. }
  329. bool AudioManagerCras::IsDefault(const std::string& device_id, bool is_input) {
  330. return AudioDeviceDescription::IsDefaultDevice(device_id);
  331. }
  332. enum CRAS_CLIENT_TYPE AudioManagerCras::GetClientType() {
  333. return CRAS_CLIENT_TYPE_LACROS;
  334. }
  335. } // namespace media