| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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_unified.h" | 5 #include "media/audio/pulse/pulse_unified.h" |
| 6 | 6 |
| 7 #include "base/message_loop/message_loop.h" | 7 #include "base/single_thread_task_runner.h" |
| 8 #include "base/time/time.h" | 8 #include "base/time/time.h" |
| 9 #include "media/audio/audio_manager_base.h" | 9 #include "media/audio/audio_manager_base.h" |
| 10 #include "media/audio/audio_parameters.h" | 10 #include "media/audio/audio_parameters.h" |
| 11 #include "media/audio/pulse/pulse_util.h" | 11 #include "media/audio/pulse/pulse_util.h" |
| 12 #include "media/base/seekable_buffer.h" | 12 #include "media/base/seekable_buffer.h" |
| 13 | 13 |
| 14 namespace media { | 14 namespace media { |
| 15 | 15 |
| 16 using pulse::AutoPulseLock; | 16 using pulse::AutoPulseLock; |
| 17 using pulse::WaitForOperationCompletion; | 17 using pulse::WaitForOperationCompletion; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 47 AudioManagerBase* manager) | 47 AudioManagerBase* manager) |
| 48 : params_(params), | 48 : params_(params), |
| 49 input_device_id_(input_device_id), | 49 input_device_id_(input_device_id), |
| 50 manager_(manager), | 50 manager_(manager), |
| 51 pa_context_(NULL), | 51 pa_context_(NULL), |
| 52 pa_mainloop_(NULL), | 52 pa_mainloop_(NULL), |
| 53 input_stream_(NULL), | 53 input_stream_(NULL), |
| 54 output_stream_(NULL), | 54 output_stream_(NULL), |
| 55 volume_(1.0f), | 55 volume_(1.0f), |
| 56 source_callback_(NULL) { | 56 source_callback_(NULL) { |
| 57 DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); | 57 DCHECK(manager_->GetTaskRunner()->BelongsToCurrentThread()); |
| 58 CHECK(params_.IsValid()); | 58 CHECK(params_.IsValid()); |
| 59 input_bus_ = AudioBus::Create(params_); | 59 input_bus_ = AudioBus::Create(params_); |
| 60 output_bus_ = AudioBus::Create(params_); | 60 output_bus_ = AudioBus::Create(params_); |
| 61 } | 61 } |
| 62 | 62 |
| 63 PulseAudioUnifiedStream::~PulseAudioUnifiedStream() { | 63 PulseAudioUnifiedStream::~PulseAudioUnifiedStream() { |
| 64 // All internal structures should already have been freed in Close(), which | 64 // All internal structures should already have been freed in Close(), which |
| 65 // calls AudioManagerBase::ReleaseOutputStream() which deletes this object. | 65 // calls AudioManagerBase::ReleaseOutputStream() which deletes this object. |
| 66 DCHECK(!input_stream_); | 66 DCHECK(!input_stream_); |
| 67 DCHECK(!output_stream_); | 67 DCHECK(!output_stream_); |
| 68 DCHECK(!pa_context_); | 68 DCHECK(!pa_context_); |
| 69 DCHECK(!pa_mainloop_); | 69 DCHECK(!pa_mainloop_); |
| 70 } | 70 } |
| 71 | 71 |
| 72 bool PulseAudioUnifiedStream::Open() { | 72 bool PulseAudioUnifiedStream::Open() { |
| 73 DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); | 73 DCHECK(manager_->GetTaskRunner()->BelongsToCurrentThread()); |
| 74 // Prepare the recording buffers for the callbacks. | 74 // Prepare the recording buffers for the callbacks. |
| 75 fifo_.reset(new media::SeekableBuffer( | 75 fifo_.reset(new media::SeekableBuffer( |
| 76 0, kFifoSizeInPackets * params_.GetBytesPerBuffer())); | 76 0, kFifoSizeInPackets * params_.GetBytesPerBuffer())); |
| 77 input_data_buffer_.reset(new uint8[params_.GetBytesPerBuffer()]); | 77 input_data_buffer_.reset(new uint8[params_.GetBytesPerBuffer()]); |
| 78 | 78 |
| 79 if (!pulse::CreateOutputStream(&pa_mainloop_, &pa_context_, &output_stream_, | 79 if (!pulse::CreateOutputStream(&pa_mainloop_, &pa_context_, &output_stream_, |
| 80 params_, &StreamNotifyCallback, NULL, this)) | 80 params_, &StreamNotifyCallback, NULL, this)) |
| 81 return false; | 81 return false; |
| 82 | 82 |
| 83 if (!pulse::CreateInputStream(pa_mainloop_, pa_context_, &input_stream_, | 83 if (!pulse::CreateInputStream(pa_mainloop_, pa_context_, &input_stream_, |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 pa_context_ = NULL; | 131 pa_context_ = NULL; |
| 132 } | 132 } |
| 133 } | 133 } |
| 134 | 134 |
| 135 pa_threaded_mainloop_stop(pa_mainloop_); | 135 pa_threaded_mainloop_stop(pa_mainloop_); |
| 136 pa_threaded_mainloop_free(pa_mainloop_); | 136 pa_threaded_mainloop_free(pa_mainloop_); |
| 137 pa_mainloop_ = NULL; | 137 pa_mainloop_ = NULL; |
| 138 } | 138 } |
| 139 | 139 |
| 140 void PulseAudioUnifiedStream::Close() { | 140 void PulseAudioUnifiedStream::Close() { |
| 141 DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); | 141 DCHECK(manager_->GetTaskRunner()->BelongsToCurrentThread()); |
| 142 Reset(); | 142 Reset(); |
| 143 | 143 |
| 144 // Signal to the manager that we're closed and can be removed. | 144 // Signal to the manager that we're closed and can be removed. |
| 145 // This should be the last call in the function as it deletes "this". | 145 // This should be the last call in the function as it deletes "this". |
| 146 manager_->ReleaseOutputStream(this); | 146 manager_->ReleaseOutputStream(this); |
| 147 } | 147 } |
| 148 | 148 |
| 149 void PulseAudioUnifiedStream::WriteData(size_t requested_bytes) { | 149 void PulseAudioUnifiedStream::WriteData(size_t requested_bytes) { |
| 150 CHECK_EQ(requested_bytes, static_cast<size_t>(params_.GetBytesPerBuffer())); | 150 CHECK_EQ(requested_bytes, static_cast<size_t>(params_.GetBytesPerBuffer())); |
| 151 | 151 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 } | 204 } |
| 205 | 205 |
| 206 // Checks if we still have data. | 206 // Checks if we still have data. |
| 207 pa_stream_drop(input_stream_); | 207 pa_stream_drop(input_stream_); |
| 208 } while (pa_stream_readable_size(input_stream_) > 0); | 208 } while (pa_stream_readable_size(input_stream_) > 0); |
| 209 | 209 |
| 210 pa_threaded_mainloop_signal(pa_mainloop_, 0); | 210 pa_threaded_mainloop_signal(pa_mainloop_, 0); |
| 211 } | 211 } |
| 212 | 212 |
| 213 void PulseAudioUnifiedStream::Start(AudioSourceCallback* callback) { | 213 void PulseAudioUnifiedStream::Start(AudioSourceCallback* callback) { |
| 214 DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); | 214 DCHECK(manager_->GetTaskRunner()->BelongsToCurrentThread()); |
| 215 CHECK(callback); | 215 CHECK(callback); |
| 216 CHECK(input_stream_); | 216 CHECK(input_stream_); |
| 217 CHECK(output_stream_); | 217 CHECK(output_stream_); |
| 218 AutoPulseLock auto_lock(pa_mainloop_); | 218 AutoPulseLock auto_lock(pa_mainloop_); |
| 219 | 219 |
| 220 // Ensure the context and stream are ready. | 220 // Ensure the context and stream are ready. |
| 221 if (pa_context_get_state(pa_context_) != PA_CONTEXT_READY && | 221 if (pa_context_get_state(pa_context_) != PA_CONTEXT_READY && |
| 222 pa_stream_get_state(output_stream_) != PA_STREAM_READY && | 222 pa_stream_get_state(output_stream_) != PA_STREAM_READY && |
| 223 pa_stream_get_state(input_stream_) != PA_STREAM_READY) { | 223 pa_stream_get_state(input_stream_) != PA_STREAM_READY) { |
| 224 callback->OnError(this); | 224 callback->OnError(this); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 237 | 237 |
| 238 // Uncork (resume) the output stream. | 238 // Uncork (resume) the output stream. |
| 239 // We use the recording stream to drive the playback, so we do not need to | 239 // We use the recording stream to drive the playback, so we do not need to |
| 240 // register the write callback using pa_stream_set_write_callback(). | 240 // register the write callback using pa_stream_set_write_callback(). |
| 241 operation = pa_stream_cork(output_stream_, 0, | 241 operation = pa_stream_cork(output_stream_, 0, |
| 242 &pulse::StreamSuccessCallback, pa_mainloop_); | 242 &pulse::StreamSuccessCallback, pa_mainloop_); |
| 243 WaitForOperationCompletion(pa_mainloop_, operation); | 243 WaitForOperationCompletion(pa_mainloop_, operation); |
| 244 } | 244 } |
| 245 | 245 |
| 246 void PulseAudioUnifiedStream::Stop() { | 246 void PulseAudioUnifiedStream::Stop() { |
| 247 DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); | 247 DCHECK(manager_->GetTaskRunner()->BelongsToCurrentThread()); |
| 248 | 248 |
| 249 // Cork (pause) the stream. Waiting for the main loop lock will ensure | 249 // Cork (pause) the stream. Waiting for the main loop lock will ensure |
| 250 // outstanding callbacks have completed. | 250 // outstanding callbacks have completed. |
| 251 AutoPulseLock auto_lock(pa_mainloop_); | 251 AutoPulseLock auto_lock(pa_mainloop_); |
| 252 | 252 |
| 253 // Set |source_callback_| to NULL so all FulfillWriteRequest() calls which may | 253 // Set |source_callback_| to NULL so all FulfillWriteRequest() calls which may |
| 254 // occur while waiting on the flush and cork exit immediately. | 254 // occur while waiting on the flush and cork exit immediately. |
| 255 source_callback_ = NULL; | 255 source_callback_ = NULL; |
| 256 | 256 |
| 257 // Set the read callback to NULL before flushing the stream, otherwise it | 257 // Set the read callback to NULL before flushing the stream, otherwise it |
| (...skipping 13 matching lines...) Expand all Loading... |
| 271 operation = pa_stream_flush( | 271 operation = pa_stream_flush( |
| 272 output_stream_, &pulse::StreamSuccessCallback, pa_mainloop_); | 272 output_stream_, &pulse::StreamSuccessCallback, pa_mainloop_); |
| 273 WaitForOperationCompletion(pa_mainloop_, operation); | 273 WaitForOperationCompletion(pa_mainloop_, operation); |
| 274 | 274 |
| 275 operation = pa_stream_cork(output_stream_, 1, &pulse::StreamSuccessCallback, | 275 operation = pa_stream_cork(output_stream_, 1, &pulse::StreamSuccessCallback, |
| 276 pa_mainloop_); | 276 pa_mainloop_); |
| 277 WaitForOperationCompletion(pa_mainloop_, operation); | 277 WaitForOperationCompletion(pa_mainloop_, operation); |
| 278 } | 278 } |
| 279 | 279 |
| 280 void PulseAudioUnifiedStream::SetVolume(double volume) { | 280 void PulseAudioUnifiedStream::SetVolume(double volume) { |
| 281 DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); | 281 DCHECK(manager_->GetTaskRunner()->BelongsToCurrentThread()); |
| 282 | 282 |
| 283 volume_ = static_cast<float>(volume); | 283 volume_ = static_cast<float>(volume); |
| 284 } | 284 } |
| 285 | 285 |
| 286 void PulseAudioUnifiedStream::GetVolume(double* volume) { | 286 void PulseAudioUnifiedStream::GetVolume(double* volume) { |
| 287 DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); | 287 DCHECK(manager_->GetTaskRunner()->BelongsToCurrentThread()); |
| 288 | 288 |
| 289 *volume = volume_; | 289 *volume = volume_; |
| 290 } | 290 } |
| 291 | 291 |
| 292 } // namespace media | 292 } // namespace media |
| OLD | NEW |