Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(287)

Side by Side Diff: media/audio/linux/alsa_input.cc

Issue 9655018: Make AudioParameters a class instead of a struct (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix tests Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/audio/linux/alsa_input.h" 5 #include "media/audio/linux/alsa_input.h"
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/message_loop.h" 10 #include "base/message_loop.h"
(...skipping 11 matching lines...) Expand all
22 22
23 const char* AlsaPcmInputStream::kAutoSelectDevice = ""; 23 const char* AlsaPcmInputStream::kAutoSelectDevice = "";
24 24
25 AlsaPcmInputStream::AlsaPcmInputStream(AudioManagerLinux* audio_manager, 25 AlsaPcmInputStream::AlsaPcmInputStream(AudioManagerLinux* audio_manager,
26 const std::string& device_name, 26 const std::string& device_name,
27 const AudioParameters& params, 27 const AudioParameters& params,
28 AlsaWrapper* wrapper) 28 AlsaWrapper* wrapper)
29 : audio_manager_(audio_manager), 29 : audio_manager_(audio_manager),
30 device_name_(device_name), 30 device_name_(device_name),
31 params_(params), 31 params_(params),
32 bytes_per_packet_(params.samples_per_packet * 32 bytes_per_packet_(params.samples_per_packet() *
33 (params.channels * params.bits_per_sample) / 8), 33 (params.channels() * params.bits_per_sample()) / 8),
34 wrapper_(wrapper), 34 wrapper_(wrapper),
35 packet_duration_ms_( 35 packet_duration_ms_(
36 (params.samples_per_packet * base::Time::kMillisecondsPerSecond) / 36 (params.samples_per_packet() * base::Time::kMillisecondsPerSecond) /
37 params.sample_rate), 37 params.samples_per_second()),
38 callback_(NULL), 38 callback_(NULL),
39 device_handle_(NULL), 39 device_handle_(NULL),
40 mixer_handle_(NULL), 40 mixer_handle_(NULL),
41 mixer_element_handle_(NULL), 41 mixer_element_handle_(NULL),
42 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), 42 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
43 read_callback_behind_schedule_(false) { 43 read_callback_behind_schedule_(false) {
44 } 44 }
45 45
46 AlsaPcmInputStream::~AlsaPcmInputStream() {} 46 AlsaPcmInputStream::~AlsaPcmInputStream() {}
47 47
48 bool AlsaPcmInputStream::Open() { 48 bool AlsaPcmInputStream::Open() {
49 if (device_handle_) 49 if (device_handle_)
50 return false; // Already open. 50 return false; // Already open.
51 51
52 snd_pcm_format_t pcm_format = alsa_util::BitsToFormat( 52 snd_pcm_format_t pcm_format = alsa_util::BitsToFormat(
53 params_.bits_per_sample); 53 params_.bits_per_sample());
54 if (pcm_format == SND_PCM_FORMAT_UNKNOWN) { 54 if (pcm_format == SND_PCM_FORMAT_UNKNOWN) {
55 LOG(WARNING) << "Unsupported bits per sample: " 55 LOG(WARNING) << "Unsupported bits per sample: "
56 << params_.bits_per_sample; 56 << params_.bits_per_sample();
57 return false; 57 return false;
58 } 58 }
59 59
60 uint32 latency_us = packet_duration_ms_ * kNumPacketsInRingBuffer * 60 uint32 latency_us = packet_duration_ms_ * kNumPacketsInRingBuffer *
61 base::Time::kMicrosecondsPerMillisecond; 61 base::Time::kMicrosecondsPerMillisecond;
62 62
63 // Use the same minimum required latency as output. 63 // Use the same minimum required latency as output.
64 latency_us = std::max(latency_us, AlsaPcmOutputStream::kMinLatencyMicros); 64 latency_us = std::max(latency_us, AlsaPcmOutputStream::kMinLatencyMicros);
65 65
66 if (device_name_ == kAutoSelectDevice) { 66 if (device_name_ == kAutoSelectDevice) {
67 const char* device_names[] = { kDefaultDevice1, kDefaultDevice2 }; 67 const char* device_names[] = { kDefaultDevice1, kDefaultDevice2 };
68 for (size_t i = 0; i < arraysize(device_names); ++i) { 68 for (size_t i = 0; i < arraysize(device_names); ++i) {
69 device_handle_ = alsa_util::OpenCaptureDevice(wrapper_, device_names[i], 69 device_handle_ = alsa_util::OpenCaptureDevice(
70 params_.channels, 70 wrapper_, device_names[i], params_.channels(),
71 params_.sample_rate, 71 params_.samples_per_second(), pcm_format, latency_us);
72 pcm_format, latency_us); 72
73 if (device_handle_) { 73 if (device_handle_) {
74 device_name_ = device_names[i]; 74 device_name_ = device_names[i];
75 break; 75 break;
76 } 76 }
77 } 77 }
78 } else { 78 } else {
79 device_handle_ = alsa_util::OpenCaptureDevice(wrapper_, 79 device_handle_ = alsa_util::OpenCaptureDevice(wrapper_,
80 device_name_.c_str(), 80 device_name_.c_str(),
81 params_.channels, 81 params_.channels(),
82 params_.sample_rate, 82 params_.samples_per_second(),
83 pcm_format, latency_us); 83 pcm_format, latency_us);
84 } 84 }
85 85
86 if (device_handle_) { 86 if (device_handle_) {
87 audio_packet_.reset(new uint8[bytes_per_packet_]); 87 audio_packet_.reset(new uint8[bytes_per_packet_]);
88 88
89 // Open the microphone mixer. 89 // Open the microphone mixer.
90 mixer_handle_ = alsa_util::OpenMixer(wrapper_, device_name_); 90 mixer_handle_ = alsa_util::OpenMixer(wrapper_, device_name_);
91 if (mixer_handle_) { 91 if (mixer_handle_) {
92 mixer_element_handle_ = alsa_util::LoadCaptureMixerElement( 92 mixer_element_handle_ = alsa_util::LoadCaptureMixerElement(
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 169
170 void AlsaPcmInputStream::ReadAudio() { 170 void AlsaPcmInputStream::ReadAudio() {
171 DCHECK(callback_); 171 DCHECK(callback_);
172 172
173 snd_pcm_sframes_t frames = wrapper_->PcmAvailUpdate(device_handle_); 173 snd_pcm_sframes_t frames = wrapper_->PcmAvailUpdate(device_handle_);
174 if (frames < 0) { // Potentially recoverable error? 174 if (frames < 0) { // Potentially recoverable error?
175 LOG(WARNING) << "PcmAvailUpdate(): " << wrapper_->StrError(frames); 175 LOG(WARNING) << "PcmAvailUpdate(): " << wrapper_->StrError(frames);
176 Recover(frames); 176 Recover(frames);
177 } 177 }
178 178
179 if (frames < params_.samples_per_packet) { 179 if (frames < params_.samples_per_packet()) {
180 // Not enough data yet or error happened. In both cases wait for a very 180 // Not enough data yet or error happened. In both cases wait for a very
181 // small duration before checking again. 181 // small duration before checking again.
182 // Even Though read callback was behind schedule, there is no data, so 182 // Even Though read callback was behind schedule, there is no data, so
183 // reset the next_read_time_. 183 // reset the next_read_time_.
184 if (read_callback_behind_schedule_) { 184 if (read_callback_behind_schedule_) {
185 next_read_time_ = base::Time::Now(); 185 next_read_time_ = base::Time::Now();
186 read_callback_behind_schedule_ = false; 186 read_callback_behind_schedule_ = false;
187 } 187 }
188 188
189 base::TimeDelta next_check_time = base::TimeDelta::FromMilliseconds( 189 base::TimeDelta next_check_time = base::TimeDelta::FromMilliseconds(
190 packet_duration_ms_ / 2); 190 packet_duration_ms_ / 2);
191 MessageLoop::current()->PostDelayedTask( 191 MessageLoop::current()->PostDelayedTask(
192 FROM_HERE, 192 FROM_HERE,
193 base::Bind(&AlsaPcmInputStream::ReadAudio, weak_factory_.GetWeakPtr()), 193 base::Bind(&AlsaPcmInputStream::ReadAudio, weak_factory_.GetWeakPtr()),
194 next_check_time); 194 next_check_time);
195 return; 195 return;
196 } 196 }
197 197
198 int num_packets = frames / params_.samples_per_packet; 198 int num_packets = frames / params_.samples_per_packet();
199 int num_packets_read = num_packets; 199 int num_packets_read = num_packets;
200 int bytes_per_frame = params_.channels * params_.bits_per_sample / 8; 200 int bytes_per_frame = params_.channels() * params_.bits_per_sample() / 8;
201 uint32 hardware_delay_bytes = 201 uint32 hardware_delay_bytes =
202 static_cast<uint32>(GetCurrentDelay() * bytes_per_frame); 202 static_cast<uint32>(GetCurrentDelay() * bytes_per_frame);
203 while (num_packets--) { 203 while (num_packets--) {
204 int frames_read = wrapper_->PcmReadi(device_handle_, audio_packet_.get(), 204 int frames_read = wrapper_->PcmReadi(device_handle_, audio_packet_.get(),
205 params_.samples_per_packet); 205 params_.samples_per_packet());
206 if (frames_read == params_.samples_per_packet) { 206 if (frames_read == params_.samples_per_packet()) {
207 callback_->OnData(this, audio_packet_.get(), bytes_per_packet_, 207 callback_->OnData(this, audio_packet_.get(), bytes_per_packet_,
208 hardware_delay_bytes); 208 hardware_delay_bytes);
209 } else { 209 } else {
210 LOG(WARNING) << "PcmReadi returning less than expected frames: " 210 LOG(WARNING) << "PcmReadi returning less than expected frames: "
211 << frames_read << " vs. " << params_.samples_per_packet 211 << frames_read << " vs. " << params_.samples_per_packet()
212 << ". Dropping this packet."; 212 << ". Dropping this packet.";
213 } 213 }
214 } 214 }
215 215
216 next_read_time_ += base::TimeDelta::FromMilliseconds( 216 next_read_time_ += base::TimeDelta::FromMilliseconds(
217 packet_duration_ms_ * num_packets_read); 217 packet_duration_ms_ * num_packets_read);
218 base::TimeDelta delay = next_read_time_ - base::Time::Now(); 218 base::TimeDelta delay = next_read_time_ - base::Time::Now();
219 if (delay < base::TimeDelta()) { 219 if (delay < base::TimeDelta()) {
220 LOG(WARNING) << "Audio read callback behind schedule by " 220 LOG(WARNING) << "Audio read callback behind schedule by "
221 << (packet_duration_ms_ - delay.InMilliseconds()) 221 << (packet_duration_ms_ - delay.InMilliseconds())
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 return 0.0; 321 return 0.0;
322 } 322 }
323 323
324 return static_cast<double>(current_volume); 324 return static_cast<double>(current_volume);
325 } 325 }
326 326
327 void AlsaPcmInputStream::HandleError(const char* method, int error) { 327 void AlsaPcmInputStream::HandleError(const char* method, int error) {
328 LOG(WARNING) << method << ": " << wrapper_->StrError(error); 328 LOG(WARNING) << method << ": " << wrapper_->StrError(error);
329 callback_->OnError(this, error); 329 callback_->OnError(this, error);
330 } 330 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698