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_impl.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" |
11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/run_loop.h" | 13 #include "base/run_loop.h" |
14 #include "components/copresence/public/copresence_constants.h" | 14 #include "components/copresence/public/copresence_constants.h" |
15 #include "content/public/browser/browser_thread.h" | 15 #include "content/public/browser/browser_thread.h" |
16 #include "media/audio/audio_manager.h" | 16 #include "media/audio/audio_manager.h" |
17 #include "media/audio/audio_parameters.h" | 17 #include "media/audio/audio_parameters.h" |
18 #include "media/base/audio_bus.h" | 18 #include "media/base/audio_bus.h" |
19 | 19 |
20 namespace { | 20 namespace { |
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 |