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
3 // found in the LICENSE file.
4 
5 #include "base/metrics/histogram_macros.h"
6 #include "base/memory/ptr_util.h"
7 
8 #include "media/audio/openbsd/audio_manager_openbsd.h"
9 
10 #include "media/audio/audio_device_description.h"
11 #include "media/audio/audio_output_dispatcher.h"
12 #if defined(USE_SNDIO)
13 #include "media/audio/sndio/sndio_input.h"
14 #include "media/audio/sndio/sndio_output.h"
15 #else
16 #include "media/audio/fake_audio_manager.h"
17 #endif
18 #include "media/base/limits.h"
19 #include "media/base/media_switches.h"
20 
21 namespace media {
22 
23 enum OpenBSDAudioIO {
24   kPulse,
25   kSndio,
26   kAudioIOMax = kSndio
27 };
28 
29 #if defined(USE_SNDIO)
30 // Maximum number of output streams that can be open simultaneously.
31 static const int kMaxOutputStreams = 4;
32 
33 // Default sample rate for input and output streams.
34 static const int kDefaultSampleRate = 48000;
35 
AddDefaultDevice(AudioDeviceNames * device_names)36 void AddDefaultDevice(AudioDeviceNames* device_names) {
37   DCHECK(device_names->empty());
38   device_names->push_front(AudioDeviceName::CreateDefault());
39 }
40 
HasAudioOutputDevices()41 bool AudioManagerOpenBSD::HasAudioOutputDevices() {
42   return true;
43 }
44 
HasAudioInputDevices()45 bool AudioManagerOpenBSD::HasAudioInputDevices() {
46   return true;
47 }
48 
GetAudioInputDeviceNames(AudioDeviceNames * device_names)49 void AudioManagerOpenBSD::GetAudioInputDeviceNames(
50     AudioDeviceNames* device_names) {
51   DCHECK(device_names->empty());
52   AddDefaultDevice(device_names);
53 }
54 
GetAudioOutputDeviceNames(AudioDeviceNames * device_names)55 void AudioManagerOpenBSD::GetAudioOutputDeviceNames(
56     AudioDeviceNames* device_names) {
57   AddDefaultDevice(device_names);
58 }
59 
60 #if defined(USE_SNDIO)
GetName()61 const char* AudioManagerOpenBSD::GetName() {
62   return "SNDIO";
63 }
64 #endif
65 
GetInputStreamParameters(const std::string & device_id)66 AudioParameters AudioManagerOpenBSD::GetInputStreamParameters(
67     const std::string& device_id) {
68   static const int kDefaultInputBufferSize = 1024;
69 
70   int user_buffer_size = GetUserBufferSize();
71   int buffer_size = user_buffer_size ?
72       user_buffer_size : kDefaultInputBufferSize;
73 
74   return AudioParameters(
75       AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
76       kDefaultSampleRate, buffer_size);
77 }
78 
AudioManagerOpenBSD(std::unique_ptr<AudioThread> audio_thread,AudioLogFactory * audio_log_factory)79 AudioManagerOpenBSD::AudioManagerOpenBSD(std::unique_ptr<AudioThread> audio_thread,
80                                          AudioLogFactory* audio_log_factory)
81     : AudioManagerBase(std::move(audio_thread),
82                        audio_log_factory) {
83   DLOG(WARNING) << "AudioManagerOpenBSD";
84   SetMaxOutputStreamsAllowed(kMaxOutputStreams);
85 }
86 
~AudioManagerOpenBSD()87 AudioManagerOpenBSD::~AudioManagerOpenBSD() {
88   Shutdown();
89 }
90 
MakeLinearOutputStream(const AudioParameters & params,const LogCallback & log_callback)91 AudioOutputStream* AudioManagerOpenBSD::MakeLinearOutputStream(
92     const AudioParameters& params,
93     const LogCallback& log_callback) {
94   DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
95   return MakeOutputStream(params);
96 }
97 
MakeLowLatencyOutputStream(const AudioParameters & params,const std::string & device_id,const LogCallback & log_callback)98 AudioOutputStream* AudioManagerOpenBSD::MakeLowLatencyOutputStream(
99     const AudioParameters& params,
100     const std::string& device_id,
101     const LogCallback& log_callback) {
102   DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
103   DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
104   return MakeOutputStream(params);
105 }
106 
MakeLinearInputStream(const AudioParameters & params,const std::string & device_id,const LogCallback & log_callback)107 AudioInputStream* AudioManagerOpenBSD::MakeLinearInputStream(
108     const AudioParameters& params,
109     const std::string& device_id,
110     const LogCallback& log_callback) {
111   DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
112   return MakeInputStream(params);
113 }
114 
MakeLowLatencyInputStream(const AudioParameters & params,const std::string & device_id,const LogCallback & log_callback)115 AudioInputStream* AudioManagerOpenBSD::MakeLowLatencyInputStream(
116     const AudioParameters& params,
117     const std::string& device_id,
118     const LogCallback& log_callback) {
119   DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
120   return MakeInputStream(params);
121 }
122 
GetPreferredOutputStreamParameters(const std::string & output_device_id,const AudioParameters & input_params)123 AudioParameters AudioManagerOpenBSD::GetPreferredOutputStreamParameters(
124     const std::string& output_device_id,
125     const AudioParameters& input_params) {
126   // TODO(tommi): Support |output_device_id|.
127   DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!";
128   static const int kDefaultOutputBufferSize = 2048;
129 
130   ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
131   int sample_rate = kDefaultSampleRate;
132   int buffer_size = kDefaultOutputBufferSize;
133   if (input_params.IsValid()) {
134     sample_rate = input_params.sample_rate();
135     channel_layout = input_params.channel_layout();
136     buffer_size = std::min(buffer_size, input_params.frames_per_buffer());
137   }
138 
139   int user_buffer_size = GetUserBufferSize();
140   if (user_buffer_size)
141     buffer_size = user_buffer_size;
142 
143   return AudioParameters(
144       AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
145       sample_rate, buffer_size);
146 }
147 
MakeInputStream(const AudioParameters & params)148 AudioInputStream* AudioManagerOpenBSD::MakeInputStream(
149     const AudioParameters& params) {
150   DLOG(WARNING) << "MakeInputStream";
151   return new SndioAudioInputStream(this,
152              AudioDeviceDescription::kDefaultDeviceId, params);
153 }
154 
MakeOutputStream(const AudioParameters & params)155 AudioOutputStream* AudioManagerOpenBSD::MakeOutputStream(
156     const AudioParameters& params) {
157   DLOG(WARNING) << "MakeOutputStream";
158   return new SndioAudioOutputStream(params, this);
159 }
160 #endif
161 
CreateAudioManager(std::unique_ptr<AudioThread> audio_thread,AudioLogFactory * audio_log_factory)162 std::unique_ptr<media::AudioManager> CreateAudioManager(
163     std::unique_ptr<AudioThread> audio_thread,
164     AudioLogFactory* audio_log_factory) {
165   DLOG(WARNING) << "CreateAudioManager";
166 #if defined(USE_SNDIO)
167   UMA_HISTOGRAM_ENUMERATION("Media.OpenBSDAudioIO", kSndio, kAudioIOMax + 1);
168   return std::make_unique<AudioManagerOpenBSD>(std::move(audio_thread),
169                                             audio_log_factory);
170 #else
171   return std::make_unique<FakeAudioManager>(std::move(audio_thread),
172                                             audio_log_factory);
173 #endif
174 
175 }
176 
177 }  // namespace media
178