| 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/audio_output_controller.h" | 5 #include "media/audio/audio_output_controller.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <limits> | 10 #include <limits> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/metrics/histogram_macros.h" | 13 #include "base/metrics/histogram_macros.h" |
| 14 #include "base/numerics/safe_conversions.h" | 14 #include "base/numerics/safe_conversions.h" |
| 15 #include "base/task_runner_util.h" | 15 #include "base/task_runner_util.h" |
| 16 #include "base/threading/platform_thread.h" | 16 #include "base/threading/platform_thread.h" |
| 17 #include "base/time/time.h" | 17 #include "base/time/time.h" |
| 18 #include "base/trace_event/trace_event.h" | 18 #include "base/trace_event/trace_event.h" |
| 19 #include "media/base/audio_timestamp_helper.h" | |
| 20 | 19 |
| 21 using base::TimeDelta; | 20 using base::TimeDelta; |
| 22 | 21 |
| 23 namespace media { | 22 namespace media { |
| 24 | 23 |
| 25 AudioOutputController::AudioOutputController( | 24 AudioOutputController::AudioOutputController( |
| 26 AudioManager* audio_manager, | 25 AudioManager* audio_manager, |
| 27 EventHandler* handler, | 26 EventHandler* handler, |
| 28 const AudioParameters& params, | 27 const AudioParameters& params, |
| 29 const std::string& output_device_id, | 28 const std::string& output_device_id, |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 168 void AudioOutputController::DoPlay() { | 167 void AudioOutputController::DoPlay() { |
| 169 DCHECK(message_loop_->BelongsToCurrentThread()); | 168 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 170 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PlayTime"); | 169 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PlayTime"); |
| 171 TRACE_EVENT0("audio", "AudioOutputController::DoPlay"); | 170 TRACE_EVENT0("audio", "AudioOutputController::DoPlay"); |
| 172 | 171 |
| 173 // We can start from created or paused state. | 172 // We can start from created or paused state. |
| 174 if (state_ != kCreated && state_ != kPaused) | 173 if (state_ != kCreated && state_ != kPaused) |
| 175 return; | 174 return; |
| 176 | 175 |
| 177 // Ask for first packet. | 176 // Ask for first packet. |
| 178 sync_reader_->RequestMoreData(base::TimeDelta(), base::TimeTicks(), 0); | 177 sync_reader_->UpdatePendingBytes(0, 0); |
| 179 | 178 |
| 180 state_ = kPlaying; | 179 state_ = kPlaying; |
| 181 | 180 |
| 182 stream_->Start(this); | 181 stream_->Start(this); |
| 183 | 182 |
| 184 // For UMA tracking purposes, start the wedge detection timer. This allows us | 183 // For UMA tracking purposes, start the wedge detection timer. This allows us |
| 185 // to record statistics about the number of wedged playbacks in the field. | 184 // to record statistics about the number of wedged playbacks in the field. |
| 186 // | 185 // |
| 187 // WedgeCheck() will look to see if |on_more_io_data_called_| is true after | 186 // WedgeCheck() will look to see if |on_more_io_data_called_| is true after |
| 188 // the timeout expires. Care must be taken to ensure the wedge check delay is | 187 // the timeout expires. Care must be taken to ensure the wedge check delay is |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 TRACE_EVENT0("audio", "AudioOutputController::DoPause"); | 220 TRACE_EVENT0("audio", "AudioOutputController::DoPause"); |
| 222 | 221 |
| 223 StopStream(); | 222 StopStream(); |
| 224 | 223 |
| 225 if (state_ != kPaused) | 224 if (state_ != kPaused) |
| 226 return; | 225 return; |
| 227 | 226 |
| 228 // Let the renderer know we've stopped. Necessary to let PPAPI clients know | 227 // Let the renderer know we've stopped. Necessary to let PPAPI clients know |
| 229 // audio has been shutdown. TODO(dalecurtis): This stinks. PPAPI should have | 228 // audio has been shutdown. TODO(dalecurtis): This stinks. PPAPI should have |
| 230 // a better way to know when it should exit PPB_Audio_Shared::Run(). | 229 // a better way to know when it should exit PPB_Audio_Shared::Run(). |
| 231 sync_reader_->RequestMoreData(base::TimeDelta::Max(), base::TimeTicks(), 0); | 230 sync_reader_->UpdatePendingBytes(std::numeric_limits<uint32_t>::max(), 0); |
| 232 | 231 |
| 233 handler_->OnPaused(); | 232 handler_->OnPaused(); |
| 234 } | 233 } |
| 235 | 234 |
| 236 void AudioOutputController::DoClose() { | 235 void AudioOutputController::DoClose() { |
| 237 DCHECK(message_loop_->BelongsToCurrentThread()); | 236 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 238 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.CloseTime"); | 237 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.CloseTime"); |
| 239 TRACE_EVENT0("audio", "AudioOutputController::DoClose"); | 238 TRACE_EVENT0("audio", "AudioOutputController::DoClose"); |
| 240 | 239 |
| 241 if (state_ != kClosed) { | 240 if (state_ != kClosed) { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 302 | 301 |
| 303 // Indicate that we haven't wedged (at least not indefinitely, WedgeCheck() | 302 // Indicate that we haven't wedged (at least not indefinitely, WedgeCheck() |
| 304 // may have already fired if OnMoreData() took an abnormal amount of time). | 303 // may have already fired if OnMoreData() took an abnormal amount of time). |
| 305 // Since this thread is the only writer of |on_more_io_data_called_| once the | 304 // Since this thread is the only writer of |on_more_io_data_called_| once the |
| 306 // thread starts, its safe to compare and then increment. | 305 // thread starts, its safe to compare and then increment. |
| 307 if (base::AtomicRefCountIsZero(&on_more_io_data_called_)) | 306 if (base::AtomicRefCountIsZero(&on_more_io_data_called_)) |
| 308 base::AtomicRefCountInc(&on_more_io_data_called_); | 307 base::AtomicRefCountInc(&on_more_io_data_called_); |
| 309 | 308 |
| 310 sync_reader_->Read(dest); | 309 sync_reader_->Read(dest); |
| 311 | 310 |
| 311 const int total_bytes_delay = |
| 312 delay.InSecondsF() * params_.GetBytesPerSecond(); |
| 312 const int frames = dest->frames(); | 313 const int frames = dest->frames(); |
| 313 delay += AudioTimestampHelper::FramesToTime(frames, params_.sample_rate()); | 314 sync_reader_->UpdatePendingBytes( |
| 314 | 315 total_bytes_delay + frames * params_.GetBytesPerFrame(), |
| 315 sync_reader_->RequestMoreData(delay, delay_timestamp, prior_frames_skipped); | 316 prior_frames_skipped); |
| 316 | 317 |
| 317 bool need_to_duplicate = false; | 318 bool need_to_duplicate = false; |
| 318 { | 319 { |
| 319 base::AutoLock lock(duplication_targets_lock_); | 320 base::AutoLock lock(duplication_targets_lock_); |
| 320 need_to_duplicate = !duplication_targets_.empty(); | 321 need_to_duplicate = !duplication_targets_.empty(); |
| 321 } | 322 } |
| 322 if (need_to_duplicate) { | 323 if (need_to_duplicate) { |
| 323 const base::TimeTicks reference_time = delay_timestamp + delay; | 324 const base::TimeTicks reference_time = delay_timestamp + delay; |
| 324 std::unique_ptr<AudioBus> copy(AudioBus::Create(params_)); | 325 std::unique_ptr<AudioBus> copy(AudioBus::Create(params_)); |
| 325 dest->CopyTo(copy.get()); | 326 dest->CopyTo(copy.get()); |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 505 DCHECK(message_loop_->BelongsToCurrentThread()); | 506 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 506 | 507 |
| 507 // If we should be playing and we haven't, that's a wedge. | 508 // If we should be playing and we haven't, that's a wedge. |
| 508 if (state_ == kPlaying) { | 509 if (state_ == kPlaying) { |
| 509 UMA_HISTOGRAM_BOOLEAN("Media.AudioOutputControllerPlaybackStartupSuccess", | 510 UMA_HISTOGRAM_BOOLEAN("Media.AudioOutputControllerPlaybackStartupSuccess", |
| 510 base::AtomicRefCountIsOne(&on_more_io_data_called_)); | 511 base::AtomicRefCountIsOne(&on_more_io_data_called_)); |
| 511 } | 512 } |
| 512 } | 513 } |
| 513 | 514 |
| 514 } // namespace media | 515 } // namespace media |
| OLD | NEW |