| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "components/copresence/mediums/audio/audio_player.h" | 5 #include "components/copresence/mediums/audio/audio_player.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 | 21 |
| 22 const int kDefaultFrameCount = 1024; | 22 const int kDefaultFrameCount = 1024; |
| 23 const double kOutputVolumePercent = 1.0f; | 23 const double kOutputVolumePercent = 1.0f; |
| 24 | 24 |
| 25 } // namespace | 25 } // namespace |
| 26 | 26 |
| 27 namespace copresence { | 27 namespace copresence { |
| 28 | 28 |
| 29 // Public methods. | 29 // Public methods. |
| 30 | 30 |
| 31 AudioPlayer::AudioPlayer() | 31 AudioPlayerImpl::AudioPlayerImpl() |
| 32 : is_playing_(false), stream_(NULL), frame_index_(0) { | 32 : is_playing_(false), stream_(NULL), frame_index_(0) { |
| 33 } | 33 } |
| 34 | 34 |
| 35 AudioPlayer::~AudioPlayer() { | 35 AudioPlayerImpl::~AudioPlayerImpl() { |
| 36 } | 36 } |
| 37 | 37 |
| 38 void AudioPlayer::Initialize() { | 38 void AudioPlayerImpl::Initialize() { |
| 39 media::AudioManager::Get()->GetTaskRunner()->PostTask( | 39 media::AudioManager::Get()->GetTaskRunner()->PostTask( |
| 40 FROM_HERE, | 40 FROM_HERE, |
| 41 base::Bind(&AudioPlayer::InitializeOnAudioThread, | 41 base::Bind(&AudioPlayerImpl::InitializeOnAudioThread, |
| 42 base::Unretained(this))); | 42 base::Unretained(this))); |
| 43 } | 43 } |
| 44 | 44 |
| 45 void AudioPlayer::Play( | 45 void AudioPlayerImpl::Play( |
| 46 const scoped_refptr<media::AudioBusRefCounted>& samples) { | 46 const scoped_refptr<media::AudioBusRefCounted>& samples) { |
| 47 media::AudioManager::Get()->GetTaskRunner()->PostTask( | 47 media::AudioManager::Get()->GetTaskRunner()->PostTask( |
| 48 FROM_HERE, | 48 FROM_HERE, |
| 49 base::Bind( | 49 base::Bind(&AudioPlayerImpl::PlayOnAudioThread, |
| 50 &AudioPlayer::PlayOnAudioThread, base::Unretained(this), samples)); | 50 base::Unretained(this), |
| 51 samples)); |
| 51 } | 52 } |
| 52 | 53 |
| 53 void AudioPlayer::Stop() { | 54 void AudioPlayerImpl::Stop() { |
| 54 media::AudioManager::Get()->GetTaskRunner()->PostTask( | 55 media::AudioManager::Get()->GetTaskRunner()->PostTask( |
| 55 FROM_HERE, | 56 FROM_HERE, |
| 56 base::Bind(&AudioPlayer::StopOnAudioThread, base::Unretained(this))); | 57 base::Bind(&AudioPlayerImpl::StopOnAudioThread, base::Unretained(this))); |
| 57 } | 58 } |
| 58 | 59 |
| 59 bool AudioPlayer::IsPlaying() { | 60 bool AudioPlayerImpl::IsPlaying() { |
| 60 return is_playing_; | 61 return is_playing_; |
| 61 } | 62 } |
| 62 | 63 |
| 63 void AudioPlayer::Finalize() { | 64 void AudioPlayerImpl::Finalize() { |
| 64 media::AudioManager::Get()->GetTaskRunner()->PostTask( | 65 media::AudioManager::Get()->GetTaskRunner()->PostTask( |
| 65 FROM_HERE, | 66 FROM_HERE, |
| 66 base::Bind(&AudioPlayer::FinalizeOnAudioThread, base::Unretained(this))); | 67 base::Bind(&AudioPlayerImpl::FinalizeOnAudioThread, |
| 68 base::Unretained(this))); |
| 67 } | 69 } |
| 68 | 70 |
| 69 // Private methods. | 71 // Private methods. |
| 70 | 72 |
| 71 void AudioPlayer::InitializeOnAudioThread() { | 73 void AudioPlayerImpl::InitializeOnAudioThread() { |
| 72 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); | 74 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); |
| 73 stream_ = output_stream_for_testing_ | 75 stream_ = output_stream_for_testing_ |
| 74 ? output_stream_for_testing_.get() | 76 ? output_stream_for_testing_.get() |
| 75 : media::AudioManager::Get()->MakeAudioOutputStreamProxy( | 77 : media::AudioManager::Get()->MakeAudioOutputStreamProxy( |
| 76 media::AudioParameters( | 78 media::AudioParameters( |
| 77 media::AudioParameters::AUDIO_PCM_LOW_LATENCY, | 79 media::AudioParameters::AUDIO_PCM_LOW_LATENCY, |
| 78 media::CHANNEL_LAYOUT_MONO, | 80 media::CHANNEL_LAYOUT_MONO, |
| 79 kDefaultSampleRate, | 81 kDefaultSampleRate, |
| 80 kDefaultBitsPerSample, | 82 kDefaultBitsPerSample, |
| 81 kDefaultFrameCount), | 83 kDefaultFrameCount), |
| 82 std::string()); | 84 std::string()); |
| 83 | 85 |
| 84 if (!stream_ || !stream_->Open()) { | 86 if (!stream_ || !stream_->Open()) { |
| 85 LOG(ERROR) << "Failed to open an output stream."; | 87 LOG(ERROR) << "Failed to open an output stream."; |
| 86 if (stream_) { | 88 if (stream_) { |
| 87 stream_->Close(); | 89 stream_->Close(); |
| 88 stream_ = NULL; | 90 stream_ = NULL; |
| 89 } | 91 } |
| 90 return; | 92 return; |
| 91 } | 93 } |
| 92 stream_->SetVolume(kOutputVolumePercent); | 94 stream_->SetVolume(kOutputVolumePercent); |
| 93 } | 95 } |
| 94 | 96 |
| 95 void AudioPlayer::PlayOnAudioThread( | 97 void AudioPlayerImpl::PlayOnAudioThread( |
| 96 const scoped_refptr<media::AudioBusRefCounted>& samples) { | 98 const scoped_refptr<media::AudioBusRefCounted>& samples) { |
| 97 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); | 99 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); |
| 98 if (!stream_) | 100 if (!stream_) |
| 99 return; | 101 return; |
| 100 | 102 |
| 101 { | 103 { |
| 102 base::AutoLock al(state_lock_); | 104 base::AutoLock al(state_lock_); |
| 103 | 105 |
| 104 samples_ = samples; | 106 samples_ = samples; |
| 105 frame_index_ = 0; | 107 frame_index_ = 0; |
| 106 | 108 |
| 107 if (is_playing_) | 109 if (is_playing_) |
| 108 return; | 110 return; |
| 109 } | 111 } |
| 110 | 112 |
| 111 is_playing_ = true; | 113 is_playing_ = true; |
| 112 stream_->Start(this); | 114 stream_->Start(this); |
| 113 } | 115 } |
| 114 | 116 |
| 115 void AudioPlayer::StopOnAudioThread() { | 117 void AudioPlayerImpl::StopOnAudioThread() { |
| 116 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); | 118 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); |
| 117 if (!stream_) | 119 if (!stream_) |
| 118 return; | 120 return; |
| 119 | 121 |
| 120 stream_->Stop(); | 122 stream_->Stop(); |
| 121 is_playing_ = false; | 123 is_playing_ = false; |
| 122 } | 124 } |
| 123 | 125 |
| 124 void AudioPlayer::StopAndCloseOnAudioThread() { | 126 void AudioPlayerImpl::StopAndCloseOnAudioThread() { |
| 125 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); | 127 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); |
| 126 if (!stream_) | 128 if (!stream_) |
| 127 return; | 129 return; |
| 128 | 130 |
| 129 if (is_playing_) | 131 if (is_playing_) |
| 130 stream_->Stop(); | 132 stream_->Stop(); |
| 131 stream_->Close(); | 133 stream_->Close(); |
| 132 stream_ = NULL; | 134 stream_ = NULL; |
| 133 | 135 |
| 134 is_playing_ = false; | 136 is_playing_ = false; |
| 135 } | 137 } |
| 136 | 138 |
| 137 void AudioPlayer::FinalizeOnAudioThread() { | 139 void AudioPlayerImpl::FinalizeOnAudioThread() { |
| 138 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); | 140 DCHECK(media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); |
| 139 StopAndCloseOnAudioThread(); | 141 StopAndCloseOnAudioThread(); |
| 140 delete this; | 142 delete this; |
| 141 } | 143 } |
| 142 | 144 |
| 143 int AudioPlayer::OnMoreData(media::AudioBus* dest, | 145 int AudioPlayerImpl::OnMoreData(media::AudioBus* dest, |
| 144 uint32 /* total_bytes_delay */) { | 146 uint32 /* total_bytes_delay */) { |
| 145 base::AutoLock al(state_lock_); | 147 base::AutoLock al(state_lock_); |
| 146 // Continuously play our samples till explicitly told to stop. | 148 // Continuously play our samples till explicitly told to stop. |
| 147 const int leftover_frames = samples_->frames() - frame_index_; | 149 const int leftover_frames = samples_->frames() - frame_index_; |
| 148 const int frames_to_copy = std::min(dest->frames(), leftover_frames); | 150 const int frames_to_copy = std::min(dest->frames(), leftover_frames); |
| 149 | 151 |
| 150 samples_->CopyPartialFramesTo(frame_index_, frames_to_copy, 0, dest); | 152 samples_->CopyPartialFramesTo(frame_index_, frames_to_copy, 0, dest); |
| 151 frame_index_ += frames_to_copy; | 153 frame_index_ += frames_to_copy; |
| 152 | 154 |
| 153 // If we didn't fill the destination audio bus, wrap around and fill the rest. | 155 // If we didn't fill the destination audio bus, wrap around and fill the rest. |
| 154 if (leftover_frames <= dest->frames()) { | 156 if (leftover_frames <= dest->frames()) { |
| 155 samples_->CopyPartialFramesTo( | 157 samples_->CopyPartialFramesTo( |
| 156 0, dest->frames() - frames_to_copy, frames_to_copy, dest); | 158 0, dest->frames() - frames_to_copy, frames_to_copy, dest); |
| 157 frame_index_ = dest->frames() - frames_to_copy; | 159 frame_index_ = dest->frames() - frames_to_copy; |
| 158 } | 160 } |
| 159 | 161 |
| 160 return dest->frames(); | 162 return dest->frames(); |
| 161 } | 163 } |
| 162 | 164 |
| 163 void AudioPlayer::OnError(media::AudioOutputStream* /* stream */) { | 165 void AudioPlayerImpl::OnError(media::AudioOutputStream* /* stream */) { |
| 164 LOG(ERROR) << "Error during system sound reproduction."; | 166 LOG(ERROR) << "Error during system sound reproduction."; |
| 165 media::AudioManager::Get()->GetTaskRunner()->PostTask( | 167 media::AudioManager::Get()->GetTaskRunner()->PostTask( |
| 166 FROM_HERE, | 168 FROM_HERE, |
| 167 base::Bind(&AudioPlayer::StopAndCloseOnAudioThread, | 169 base::Bind(&AudioPlayerImpl::StopAndCloseOnAudioThread, |
| 168 base::Unretained(this))); | 170 base::Unretained(this))); |
| 169 } | 171 } |
| 170 | 172 |
| 171 void AudioPlayer::FlushAudioLoopForTesting() { | 173 void AudioPlayerImpl::FlushAudioLoopForTesting() { |
| 172 if (media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()) | 174 if (media::AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()) |
| 173 return; | 175 return; |
| 174 | 176 |
| 175 // Queue task on the audio thread, when it is executed, that means we've | 177 // Queue task on the audio thread, when it is executed, that means we've |
| 176 // successfully executed all the tasks before us. | 178 // successfully executed all the tasks before us. |
| 177 base::RunLoop rl; | 179 base::RunLoop rl; |
| 178 media::AudioManager::Get()->GetTaskRunner()->PostTaskAndReply( | 180 media::AudioManager::Get()->GetTaskRunner()->PostTaskAndReply( |
| 179 FROM_HERE, | 181 FROM_HERE, |
| 180 base::Bind(base::IgnoreResult(&AudioPlayer::FlushAudioLoopForTesting), | 182 base::Bind(base::IgnoreResult(&AudioPlayerImpl::FlushAudioLoopForTesting), |
| 181 base::Unretained(this)), | 183 base::Unretained(this)), |
| 182 rl.QuitClosure()); | 184 rl.QuitClosure()); |
| 183 rl.Run(); | 185 rl.Run(); |
| 184 } | 186 } |
| 185 | 187 |
| 186 } // namespace copresence | 188 } // namespace copresence |
| OLD | NEW |