audio_manager_cras.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
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
44bool AudioManagerCras::HasAudioOutputDevices() {
45  return true;
46}
47
48bool AudioManagerCras::HasAudioInputDevices() {
49  return true;
50}
51
52AudioManagerCras::AudioManagerCras(AudioLogFactory* audio_log_factory)
53    : AudioManagerBase(audio_log_factory) {
54  SetMaxOutputStreamsAllowed(kMaxOutputStreams);
55}
56
57AudioManagerCras::~AudioManagerCras() {
58  Shutdown();
59}
60
61void AudioManagerCras::ShowAudioInputSettings() {
62  NOTIMPLEMENTED();
63}
64
65void AudioManagerCras::GetAudioInputDeviceNames(
66    AudioDeviceNames* device_names) {
67  AddDefaultDevice(device_names);
68}
69
70void AudioManagerCras::GetAudioOutputDeviceNames(
71    AudioDeviceNames* device_names) {
72  AddDefaultDevice(device_names);
73}
74
75AudioParameters AudioManagerCras::GetInputStreamParameters(
76    const std::string& device_id) {
77  static const int kDefaultInputBufferSize = 1024;
78  // TODO(hshi): Fine-tune audio parameters based on |device_id|. The optimal
79  // parameters for the loopback stream may differ from the default.
80  return AudioParameters(
81      AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
82      kDefaultSampleRate, 16, kDefaultInputBufferSize);
83}
84
85AudioOutputStream* AudioManagerCras::MakeLinearOutputStream(
86    const AudioParameters& params) {
87  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
88  return MakeOutputStream(params);
89}
90
91AudioOutputStream* AudioManagerCras::MakeLowLatencyOutputStream(
92    const AudioParameters& params,
93    const std::string& device_id) {
94  DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
95  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
96  // TODO(dgreid): Open the correct input device for unified IO.
97  return MakeOutputStream(params);
98}
99
100AudioInputStream* AudioManagerCras::MakeLinearInputStream(
101    const AudioParameters& params, const std::string& device_id) {
102  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
103  return MakeInputStream(params, device_id);
104}
105
106AudioInputStream* AudioManagerCras::MakeLowLatencyInputStream(
107    const AudioParameters& params, const std::string& device_id) {
108  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
109  return MakeInputStream(params, device_id);
110}
111
112AudioParameters AudioManagerCras::GetPreferredOutputStreamParameters(
113    const std::string& output_device_id,
114    const AudioParameters& input_params) {
115  // TODO(tommi): Support |output_device_id|.
116  DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!";
117  ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
118  int sample_rate = kDefaultSampleRate;
119  int buffer_size = kMinimumOutputBufferSize;
120  int bits_per_sample = 16;
121  int input_channels = 0;
122  if (input_params.IsValid()) {
123    sample_rate = input_params.sample_rate();
124    bits_per_sample = input_params.bits_per_sample();
125    channel_layout = input_params.channel_layout();
126    input_channels = input_params.input_channels();
127    buffer_size =
128        std::min(kMaximumOutputBufferSize,
129                 std::max(buffer_size, input_params.frames_per_buffer()));
130  }
131
132  int user_buffer_size = GetUserBufferSize();
133  if (user_buffer_size)
134    buffer_size = user_buffer_size;
135
136  return AudioParameters(
137      AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels,
138      sample_rate, bits_per_sample, buffer_size, AudioParameters::NO_EFFECTS);
139}
140
141AudioOutputStream* AudioManagerCras::MakeOutputStream(
142    const AudioParameters& params) {
143  return new CrasUnifiedStream(params, this);
144}
145
146AudioInputStream* AudioManagerCras::MakeInputStream(
147    const AudioParameters& params, const std::string& device_id) {
148  return new CrasInputStream(params, this, device_id);
149}
150
151snd_pcm_format_t AudioManagerCras::BitsToFormat(int bits_per_sample) {
152  switch (bits_per_sample) {
153    case 8:
154      return SND_PCM_FORMAT_U8;
155    case 16:
156      return SND_PCM_FORMAT_S16;
157    case 24:
158      return SND_PCM_FORMAT_S24;
159    case 32:
160      return SND_PCM_FORMAT_S32;
161    default:
162      return SND_PCM_FORMAT_UNKNOWN;
163  }
164}
165
166}  // namespace media
167