audio_manager_cras.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
1// Copyright 2013 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
5#include "media/audio/cras/audio_manager_cras.h"
6
7#include <algorithm>
8
9#include "base/command_line.h"
10#include "base/environment.h"
11#include "base/logging.h"
12#include "base/nix/xdg_util.h"
13#include "base/stl_util.h"
14#include "media/audio/cras/cras_input.h"
15#include "media/audio/cras/cras_unified.h"
16#include "media/base/channel_layout.h"
17
18// cras_util.h headers pull in min/max macros...
19// TODO(dgreid): Fix headers such that these aren't imported.
20#undef min
21#undef max
22
23namespace media {
24
25static void AddDefaultDevice(AudioDeviceNames* device_names) {
26  DCHECK(device_names->empty());
27
28  // Cras will route audio from a proper physical device automatically.
29  device_names->push_back(
30      AudioDeviceName(AudioManagerBase::kDefaultDeviceName,
31                      AudioManagerBase::kDefaultDeviceId));
32}
33
34// Maximum number of output streams that can be open simultaneously.
35static const int kMaxOutputStreams = 50;
36
37// Default sample rate for input and output streams.
38static const int kDefaultSampleRate = 48000;
39
40// Define bounds for the output buffer size.
41static const int kMinimumOutputBufferSize = 512;
42static const int kMaximumOutputBufferSize = 8192;
43
44// Default input buffer size.
45static const int kDefaultInputBufferSize = 1024;
46
47bool AudioManagerCras::HasAudioOutputDevices() {
48  return true;
49}
50
51bool AudioManagerCras::HasAudioInputDevices() {
52  return true;
53}
54
55AudioManagerCras::AudioManagerCras(AudioLogFactory* audio_log_factory)
56    : AudioManagerBase(audio_log_factory) {
57  SetMaxOutputStreamsAllowed(kMaxOutputStreams);
58}
59
60AudioManagerCras::~AudioManagerCras() {
61  Shutdown();
62}
63
64void AudioManagerCras::ShowAudioInputSettings() {
65  NOTIMPLEMENTED();
66}
67
68void AudioManagerCras::GetAudioInputDeviceNames(
69    AudioDeviceNames* device_names) {
70  AddDefaultDevice(device_names);
71}
72
73void AudioManagerCras::GetAudioOutputDeviceNames(
74    AudioDeviceNames* device_names) {
75  AddDefaultDevice(device_names);
76}
77
78AudioParameters AudioManagerCras::GetInputStreamParameters(
79    const std::string& device_id) {
80  int user_buffer_size = GetUserBufferSize();
81  int buffer_size = user_buffer_size ?
82      user_buffer_size : kDefaultInputBufferSize;
83
84  // TODO(hshi): Fine-tune audio parameters based on |device_id|. The optimal
85  // parameters for the loopback stream may differ from the default.
86  return AudioParameters(
87      AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
88      kDefaultSampleRate, 16, buffer_size);
89}
90
91AudioOutputStream* AudioManagerCras::MakeLinearOutputStream(
92    const AudioParameters& params) {
93  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
94  return MakeOutputStream(params);
95}
96
97AudioOutputStream* AudioManagerCras::MakeLowLatencyOutputStream(
98    const AudioParameters& params,
99    const std::string& device_id) {
100  DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
101  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
102  // TODO(dgreid): Open the correct input device for unified IO.
103  return MakeOutputStream(params);
104}
105
106AudioInputStream* AudioManagerCras::MakeLinearInputStream(
107    const AudioParameters& params, const std::string& device_id) {
108  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
109  return MakeInputStream(params, device_id);
110}
111
112AudioInputStream* AudioManagerCras::MakeLowLatencyInputStream(
113    const AudioParameters& params, const std::string& device_id) {
114  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
115  return MakeInputStream(params, device_id);
116}
117
118AudioParameters AudioManagerCras::GetPreferredOutputStreamParameters(
119    const std::string& output_device_id,
120    const AudioParameters& input_params) {
121  // TODO(tommi): Support |output_device_id|.
122  DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!";
123  ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
124  int sample_rate = kDefaultSampleRate;
125  int buffer_size = kMinimumOutputBufferSize;
126  int bits_per_sample = 16;
127  int input_channels = 0;
128  if (input_params.IsValid()) {
129    sample_rate = input_params.sample_rate();
130    bits_per_sample = input_params.bits_per_sample();
131    channel_layout = input_params.channel_layout();
132    input_channels = input_params.input_channels();
133    buffer_size =
134        std::min(kMaximumOutputBufferSize,
135                 std::max(buffer_size, input_params.frames_per_buffer()));
136  }
137
138  int user_buffer_size = GetUserBufferSize();
139  if (user_buffer_size)
140    buffer_size = user_buffer_size;
141
142  return AudioParameters(
143      AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels,
144      sample_rate, bits_per_sample, buffer_size, AudioParameters::NO_EFFECTS);
145}
146
147AudioOutputStream* AudioManagerCras::MakeOutputStream(
148    const AudioParameters& params) {
149  return new CrasUnifiedStream(params, this);
150}
151
152AudioInputStream* AudioManagerCras::MakeInputStream(
153    const AudioParameters& params, const std::string& device_id) {
154  return new CrasInputStream(params, this, device_id);
155}
156
157snd_pcm_format_t AudioManagerCras::BitsToFormat(int bits_per_sample) {
158  switch (bits_per_sample) {
159    case 8:
160      return SND_PCM_FORMAT_U8;
161    case 16:
162      return SND_PCM_FORMAT_S16;
163    case 24:
164      return SND_PCM_FORMAT_S24;
165    case 32:
166      return SND_PCM_FORMAT_S32;
167    default:
168      return SND_PCM_FORMAT_UNKNOWN;
169  }
170}
171
172}  // namespace media
173