| OLD | NEW |
| 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/pulse/pulse_input.h" | 5 #include "media/audio/pulse/pulse_input.h" |
| 6 | 6 |
| 7 #include <pulse/pulseaudio.h> | 7 #include <pulse/pulseaudio.h> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 pa_cvolume pa_volume; | 210 pa_cvolume pa_volume; |
| 211 pa_cvolume_set(&pa_volume, channels_, volume); | 211 pa_cvolume_set(&pa_volume, channels_, volume); |
| 212 operation = pa_context_set_source_volume_by_index( | 212 operation = pa_context_set_source_volume_by_index( |
| 213 pa_context_, index, &pa_volume, NULL, NULL); | 213 pa_context_, index, &pa_volume, NULL, NULL); |
| 214 | 214 |
| 215 // Don't need to wait for this task to complete. | 215 // Don't need to wait for this task to complete. |
| 216 pa_operation_unref(operation); | 216 pa_operation_unref(operation); |
| 217 } | 217 } |
| 218 | 218 |
| 219 double PulseAudioInputStream::GetVolume() { | 219 double PulseAudioInputStream::GetVolume() { |
| 220 AutoPulseLock auto_lock(pa_mainloop_); | 220 if (pa_threaded_mainloop_in_thread(pa_mainloop_)) { |
| 221 if (!handle_) | 221 // When being called by the pulse thread, GetVolume() is asynchronous and |
| 222 // called under AutoPulseLock. |
| 223 if (!handle_) |
| 224 return 0.0; |
| 225 |
| 226 size_t index = pa_stream_get_device_index(handle_); |
| 227 pa_operation* operation = pa_context_get_source_info_by_index( |
| 228 pa_context_, index, &VolumeCallback, this); |
| 229 // Do not wait for the operation since we can't block the pulse thread. |
| 230 pa_operation_unref(operation); |
| 231 |
| 232 // Return zero and the callback will asynchronously update the |volume_|. |
| 222 return 0.0; | 233 return 0.0; |
| 234 } else { |
| 235 // Called by other thread, put an AutoPulseLock and wait for the operation. |
| 236 AutoPulseLock auto_lock(pa_mainloop_); |
| 237 if (!handle_) |
| 238 return 0.0; |
| 223 | 239 |
| 224 size_t index = pa_stream_get_device_index(handle_); | 240 size_t index = pa_stream_get_device_index(handle_); |
| 225 pa_operation* operation = pa_context_get_source_info_by_index( | 241 pa_operation* operation = pa_context_get_source_info_by_index( |
| 226 pa_context_, index, &VolumeCallback, this); | 242 pa_context_, index, &VolumeCallback, this); |
| 227 WaitForOperationCompletion(pa_mainloop_, operation); | 243 WaitForOperationCompletion(pa_mainloop_, operation); |
| 228 | 244 |
| 229 return volume_; | 245 return volume_; |
| 246 } |
| 230 } | 247 } |
| 231 | 248 |
| 232 // static, used by pa_stream_set_read_callback. | 249 // static, used by pa_stream_set_read_callback. |
| 233 void PulseAudioInputStream::ReadCallback(pa_stream* handle, | 250 void PulseAudioInputStream::ReadCallback(pa_stream* handle, |
| 234 size_t length, | 251 size_t length, |
| 235 void* user_data) { | 252 void* user_data) { |
| 236 PulseAudioInputStream* stream = | 253 PulseAudioInputStream* stream = |
| 237 reinterpret_cast<PulseAudioInputStream*>(user_data); | 254 reinterpret_cast<PulseAudioInputStream*>(user_data); |
| 238 | 255 |
| 239 stream->ReadData(); | 256 stream->ReadData(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 254 if (stream->channels_ != info->channel_map.channels) | 271 if (stream->channels_ != info->channel_map.channels) |
| 255 stream->channels_ = info->channel_map.channels; | 272 stream->channels_ = info->channel_map.channels; |
| 256 | 273 |
| 257 pa_volume_t volume = PA_VOLUME_MUTED; // Minimum possible value. | 274 pa_volume_t volume = PA_VOLUME_MUTED; // Minimum possible value. |
| 258 // Use the max volume of any channel as the volume. | 275 // Use the max volume of any channel as the volume. |
| 259 for (int i = 0; i < stream->channels_; ++i) { | 276 for (int i = 0; i < stream->channels_; ++i) { |
| 260 if (volume < info->volume.values[i]) | 277 if (volume < info->volume.values[i]) |
| 261 volume = info->volume.values[i]; | 278 volume = info->volume.values[i]; |
| 262 } | 279 } |
| 263 | 280 |
| 281 // It is safe to access |volume_| here since VolumeCallback() is running |
| 282 // under PulseLock. |
| 264 stream->volume_ = static_cast<double>(volume); | 283 stream->volume_ = static_cast<double>(volume); |
| 265 } | 284 } |
| 266 | 285 |
| 267 // static, used by pa_stream_set_state_callback. | 286 // static, used by pa_stream_set_state_callback. |
| 268 void PulseAudioInputStream::StreamNotifyCallback(pa_stream* s, | 287 void PulseAudioInputStream::StreamNotifyCallback(pa_stream* s, |
| 269 void* user_data) { | 288 void* user_data) { |
| 270 PulseAudioInputStream* stream = | 289 PulseAudioInputStream* stream = |
| 271 reinterpret_cast<PulseAudioInputStream*>(user_data); | 290 reinterpret_cast<PulseAudioInputStream*>(user_data); |
| 272 if (s && stream->callback_ && | 291 if (s && stream->callback_ && |
| 273 pa_stream_get_state(s) == PA_STREAM_FAILED) { | 292 pa_stream_get_state(s) == PA_STREAM_FAILED) { |
| 274 stream->callback_->OnError(stream, pa_context_errno(stream->pa_context_)); | 293 stream->callback_->OnError(stream, pa_context_errno(stream->pa_context_)); |
| 275 } | 294 } |
| 276 | 295 |
| 277 pa_threaded_mainloop_signal(stream->pa_mainloop_, 0); | 296 pa_threaded_mainloop_signal(stream->pa_mainloop_, 0); |
| 278 } | 297 } |
| 279 | 298 |
| 280 void PulseAudioInputStream::ReadData() { | 299 void PulseAudioInputStream::ReadData() { |
| 281 uint32 hardware_delay = pulse::GetHardwareLatencyInBytes( | 300 uint32 hardware_delay = pulse::GetHardwareLatencyInBytes( |
| 282 handle_, params_.sample_rate(), params_.GetBytesPerFrame()); | 301 handle_, params_.sample_rate(), params_.GetBytesPerFrame()); |
| 283 | 302 |
| 284 // Update the AGC volume level once every second. Note that, | 303 // Update the AGC volume level once every second. Note that, |
| 285 // |volume| is also updated each time SetVolume() is called | 304 // |volume| is also updated each time SetVolume() is called |
| 286 // through IPC by the render-side AGC. | 305 // through IPC by the render-side AGC. |
| 306 // QueryAgcVolume() will trigger a callback to asynchronously update the |
| 307 // |volume_|, we disregard the |normalized_volume| from QueryAgcVolume() |
| 308 // and use the value calculated by |volume_|. |
| 287 double normalized_volume = 0.0; | 309 double normalized_volume = 0.0; |
| 288 QueryAgcVolume(&normalized_volume); | 310 QueryAgcVolume(&normalized_volume); |
| 311 normalized_volume = volume_ / GetMaxVolume(); |
| 289 | 312 |
| 290 do { | 313 do { |
| 291 size_t length = 0; | 314 size_t length = 0; |
| 292 const void* data = NULL; | 315 const void* data = NULL; |
| 293 pa_stream_peek(handle_, &data, &length); | 316 pa_stream_peek(handle_, &data, &length); |
| 294 if (!data || length == 0) | 317 if (!data || length == 0) |
| 295 break; | 318 break; |
| 296 | 319 |
| 297 buffer_->Append(reinterpret_cast<const uint8*>(data), length); | 320 buffer_->Append(reinterpret_cast<const uint8*>(data), length); |
| 298 | 321 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 314 DLOG(WARNING) << "OnData is being called consecutively, sleep 5ms to " | 337 DLOG(WARNING) << "OnData is being called consecutively, sleep 5ms to " |
| 315 << "wait until render consumes the data"; | 338 << "wait until render consumes the data"; |
| 316 base::PlatformThread::Sleep( | 339 base::PlatformThread::Sleep( |
| 317 base::TimeDelta::FromMilliseconds(5)); | 340 base::TimeDelta::FromMilliseconds(5)); |
| 318 } | 341 } |
| 319 | 342 |
| 320 pa_threaded_mainloop_signal(pa_mainloop_, 0); | 343 pa_threaded_mainloop_signal(pa_mainloop_, 0); |
| 321 } | 344 } |
| 322 | 345 |
| 323 } // namespace media | 346 } // namespace media |
| OLD | NEW |