OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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" |
11 #include "base/time.h" | 11 #include "base/time.h" |
12 #include "media/audio/audio_manager.h" | 12 #include "media/audio/audio_manager.h" |
13 #include "media/audio/linux/alsa_output.h" | 13 #include "media/audio/linux/alsa_output.h" |
14 #include "media/audio/linux/alsa_util.h" | 14 #include "media/audio/linux/alsa_util.h" |
15 #include "media/audio/linux/alsa_wrapper.h" | 15 #include "media/audio/linux/alsa_wrapper.h" |
16 #include "media/audio/linux/audio_manager_linux.h" | 16 #include "media/audio/linux/audio_manager_linux.h" |
17 | 17 |
18 static const int kNumPacketsInRingBuffer = 3; | 18 static const int kNumPacketsInRingBuffer = 3; |
19 | 19 |
20 static const char kDefaultDevice1[] = "default"; | 20 static const char kDefaultDevice1[] = "default"; |
21 static const char kDefaultDevice2[] = "plug:default"; | 21 static const char kDefaultDevice2[] = "plug:default"; |
22 | 22 |
23 const char* AlsaPcmInputStream::kAutoSelectDevice = ""; | 23 const char* AlsaPcmInputStream::kAutoSelectDevice = ""; |
24 | 24 |
25 AlsaPcmInputStream::AlsaPcmInputStream(const std::string& device_name, | 25 AlsaPcmInputStream::AlsaPcmInputStream(AudioManagerLinux* audio_manager, |
| 26 const std::string& device_name, |
26 const AudioParameters& params, | 27 const AudioParameters& params, |
27 AlsaWrapper* wrapper) | 28 AlsaWrapper* wrapper) |
28 : device_name_(device_name), | 29 : audio_manager_(audio_manager), |
| 30 device_name_(device_name), |
29 params_(params), | 31 params_(params), |
30 bytes_per_packet_(params.samples_per_packet * | 32 bytes_per_packet_(params.samples_per_packet * |
31 (params.channels * params.bits_per_sample) / 8), | 33 (params.channels * params.bits_per_sample) / 8), |
32 wrapper_(wrapper), | 34 wrapper_(wrapper), |
33 packet_duration_ms_( | 35 packet_duration_ms_( |
34 (params.samples_per_packet * base::Time::kMillisecondsPerSecond) / | 36 (params.samples_per_packet * base::Time::kMillisecondsPerSecond) / |
35 params.sample_rate), | 37 params.sample_rate), |
36 callback_(NULL), | 38 callback_(NULL), |
37 device_handle_(NULL), | 39 device_handle_(NULL), |
38 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), | 40 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 // packet might have got filled, to accommodate some delays in the audio | 105 // packet might have got filled, to accommodate some delays in the audio |
104 // driver. This could also give us a smooth read sequence going forward. | 106 // driver. This could also give us a smooth read sequence going forward. |
105 int64 delay_ms = packet_duration_ms_ + packet_duration_ms_ / 2; | 107 int64 delay_ms = packet_duration_ms_ + packet_duration_ms_ / 2; |
106 next_read_time_ = base::Time::Now() + base::TimeDelta::FromMilliseconds( | 108 next_read_time_ = base::Time::Now() + base::TimeDelta::FromMilliseconds( |
107 delay_ms); | 109 delay_ms); |
108 MessageLoop::current()->PostDelayedTask( | 110 MessageLoop::current()->PostDelayedTask( |
109 FROM_HERE, | 111 FROM_HERE, |
110 base::Bind(&AlsaPcmInputStream::ReadAudio, weak_factory_.GetWeakPtr()), | 112 base::Bind(&AlsaPcmInputStream::ReadAudio, weak_factory_.GetWeakPtr()), |
111 delay_ms); | 113 delay_ms); |
112 | 114 |
113 static_cast<AudioManagerLinux*>(AudioManager::GetAudioManager())-> | 115 audio_manager_->IncreaseActiveInputStreamCount(); |
114 IncreaseActiveInputStreamCount(); | |
115 } | 116 } |
116 } | 117 } |
117 | 118 |
118 bool AlsaPcmInputStream::Recover(int original_error) { | 119 bool AlsaPcmInputStream::Recover(int original_error) { |
119 int error = wrapper_->PcmRecover(device_handle_, original_error, 1); | 120 int error = wrapper_->PcmRecover(device_handle_, original_error, 1); |
120 if (error < 0) { | 121 if (error < 0) { |
121 // Docs say snd_pcm_recover returns the original error if it is not one | 122 // Docs say snd_pcm_recover returns the original error if it is not one |
122 // of the recoverable ones, so this log message will probably contain the | 123 // of the recoverable ones, so this log message will probably contain the |
123 // same error twice. | 124 // same error twice. |
124 LOG(WARNING) << "Unable to recover from \"" | 125 LOG(WARNING) << "Unable to recover from \"" |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 base::Bind(&AlsaPcmInputStream::ReadAudio, weak_factory_.GetWeakPtr()), | 218 base::Bind(&AlsaPcmInputStream::ReadAudio, weak_factory_.GetWeakPtr()), |
218 delay_ms); | 219 delay_ms); |
219 } | 220 } |
220 | 221 |
221 void AlsaPcmInputStream::Stop() { | 222 void AlsaPcmInputStream::Stop() { |
222 if (!device_handle_ || !callback_) | 223 if (!device_handle_ || !callback_) |
223 return; | 224 return; |
224 | 225 |
225 // Stop is always called before Close. In case of error, this will be | 226 // Stop is always called before Close. In case of error, this will be |
226 // also called when closing the input controller. | 227 // also called when closing the input controller. |
227 static_cast<AudioManagerLinux*>(AudioManager::GetAudioManager())-> | 228 audio_manager_->DecreaseActiveInputStreamCount(); |
228 DecreaseActiveInputStreamCount(); | |
229 | 229 |
230 weak_factory_.InvalidateWeakPtrs(); // Cancel the next scheduled read. | 230 weak_factory_.InvalidateWeakPtrs(); // Cancel the next scheduled read. |
231 int error = wrapper_->PcmDrop(device_handle_); | 231 int error = wrapper_->PcmDrop(device_handle_); |
232 if (error < 0) | 232 if (error < 0) |
233 HandleError("PcmDrop", error); | 233 HandleError("PcmDrop", error); |
234 } | 234 } |
235 | 235 |
236 void AlsaPcmInputStream::Close() { | 236 void AlsaPcmInputStream::Close() { |
237 scoped_ptr<AlsaPcmInputStream> self_deleter(this); | 237 scoped_ptr<AlsaPcmInputStream> self_deleter(this); |
238 | 238 |
239 // Check in case we were already closed or not initialized yet. | 239 // Check in case we were already closed or not initialized yet. |
240 if (!device_handle_ || !callback_) | 240 if (!device_handle_ || !callback_) |
241 return; | 241 return; |
242 | 242 |
243 weak_factory_.InvalidateWeakPtrs(); // Cancel the next scheduled read. | 243 weak_factory_.InvalidateWeakPtrs(); // Cancel the next scheduled read. |
244 int error = alsa_util::CloseDevice(wrapper_, device_handle_); | 244 int error = alsa_util::CloseDevice(wrapper_, device_handle_); |
245 if (error < 0) | 245 if (error < 0) |
246 HandleError("PcmClose", error); | 246 HandleError("PcmClose", error); |
247 | 247 |
248 audio_packet_.reset(); | 248 audio_packet_.reset(); |
249 device_handle_ = NULL; | 249 device_handle_ = NULL; |
250 callback_->OnClose(this); | 250 callback_->OnClose(this); |
251 } | 251 } |
252 | 252 |
253 void AlsaPcmInputStream::HandleError(const char* method, int error) { | 253 void AlsaPcmInputStream::HandleError(const char* method, int error) { |
254 LOG(WARNING) << method << ": " << wrapper_->StrError(error); | 254 LOG(WARNING) << method << ": " << wrapper_->StrError(error); |
255 callback_->OnError(this, error); | 255 callback_->OnError(this, error); |
256 } | 256 } |
OLD | NEW |