Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Side by Side Diff: media/audio/sounds/audio_stream_handler.cc

Issue 1453233002: Improve input handling for WaveAudioHandler. (Closed) Base URL: https://chromium.googlesource.com/chromium/src@master
Patch Set: Update FileSource Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/sounds/audio_stream_handler.h" 5 #include "media/audio/sounds/audio_stream_handler.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/cancelable_callback.h" 9 #include "base/cancelable_callback.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/single_thread_task_runner.h" 11 #include "base/single_thread_task_runner.h"
12 #include "base/synchronization/lock.h" 12 #include "base/synchronization/lock.h"
13 #include "base/time/time.h" 13 #include "base/time/time.h"
14 #include "media/audio/audio_manager.h" 14 #include "media/audio/audio_manager.h"
15 #include "media/audio/audio_manager_base.h" 15 #include "media/audio/audio_manager_base.h"
16 #include "media/audio/sounds/wav_audio_handler.h"
16 #include "media/base/channel_layout.h" 17 #include "media/base/channel_layout.h"
17 18
18 namespace media { 19 namespace media {
19 20
20 namespace { 21 namespace {
21 22
22 // Volume percent. 23 // Volume percent.
23 const double kOutputVolumePercent = 0.8; 24 const double kOutputVolumePercent = 0.8;
24 25
25 // The number of frames each OnMoreData() call will request. 26 // The number of frames each OnMoreData() call will request.
26 const int kDefaultFrameCount = 1024; 27 const int kDefaultFrameCount = 1024;
27 28
28 // Keep alive timeout for audio stream. 29 // Keep alive timeout for audio stream.
29 const int kKeepAliveMs = 1500; 30 const int kKeepAliveMs = 1500;
30 31
31 AudioStreamHandler::TestObserver* g_observer_for_testing = NULL; 32 AudioStreamHandler::TestObserver* g_observer_for_testing = NULL;
32 AudioOutputStream::AudioSourceCallback* g_audio_source_for_testing = NULL; 33 AudioOutputStream::AudioSourceCallback* g_audio_source_for_testing = NULL;
33 34
34 } // namespace 35 } // namespace
35 36
36 class AudioStreamHandler::AudioStreamContainer 37 class AudioStreamHandler::AudioStreamContainer
37 : public AudioOutputStream::AudioSourceCallback { 38 : public AudioOutputStream::AudioSourceCallback {
38 public: 39 public:
39 explicit AudioStreamContainer(const WavAudioHandler& wav_audio) 40 explicit AudioStreamContainer(scoped_ptr<WavAudioHandler> wav_audio)
40 : started_(false), 41 : started_(false),
41 stream_(NULL), 42 stream_(NULL),
42 cursor_(0), 43 cursor_(0),
43 delayed_stop_posted_(false), 44 delayed_stop_posted_(false),
44 wav_audio_(wav_audio) {} 45 wav_audio_(wav_audio.Pass()) {
46 DCHECK(wav_audio_);
47 }
45 48
46 ~AudioStreamContainer() override { 49 ~AudioStreamContainer() override {
47 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 50 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
48 } 51 }
49 52
50 void Play() { 53 void Play() {
51 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 54 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
52 55
53 if (!stream_) { 56 if (!stream_) {
54 const AudioParameters params( 57 const AudioParameters params(
55 AudioParameters::AUDIO_PCM_LOW_LATENCY, 58 AudioParameters::AUDIO_PCM_LOW_LATENCY,
56 GuessChannelLayout(wav_audio_.num_channels()), 59 GuessChannelLayout(wav_audio_->num_channels()),
57 wav_audio_.sample_rate(), wav_audio_.bits_per_sample(), 60 wav_audio_->sample_rate(),
61 wav_audio_->bits_per_sample(),
58 kDefaultFrameCount); 62 kDefaultFrameCount);
59 stream_ = AudioManager::Get()->MakeAudioOutputStreamProxy(params, 63 stream_ = AudioManager::Get()->MakeAudioOutputStreamProxy(params,
60 std::string()); 64 std::string());
61 if (!stream_ || !stream_->Open()) { 65 if (!stream_ || !stream_->Open()) {
62 LOG(ERROR) << "Failed to open an output stream."; 66 LOG(ERROR) << "Failed to open an output stream.";
63 return; 67 return;
64 } 68 }
65 stream_->SetVolume(kOutputVolumePercent); 69 stream_->SetVolume(kOutputVolumePercent);
66 } 70 }
67 71
68 { 72 {
69 base::AutoLock al(state_lock_); 73 base::AutoLock al(state_lock_);
70 74
71 delayed_stop_posted_ = false; 75 delayed_stop_posted_ = false;
72 stop_closure_.Reset(base::Bind(&AudioStreamContainer::StopStream, 76 stop_closure_.Reset(base::Bind(&AudioStreamContainer::StopStream,
73 base::Unretained(this))); 77 base::Unretained(this)));
74 78
75 if (started_) { 79 if (started_) {
76 if (wav_audio_.AtEnd(cursor_)) 80 if (wav_audio_->AtEnd(cursor_))
77 cursor_ = 0; 81 cursor_ = 0;
78 return; 82 return;
79 } 83 }
80 84
81 cursor_ = 0; 85 cursor_ = 0;
82 } 86 }
83 87
84 started_ = true; 88 started_ = true;
85 if (g_audio_source_for_testing) 89 if (g_audio_source_for_testing)
86 stream_->Start(g_audio_source_for_testing); 90 stream_->Start(g_audio_source_for_testing);
(...skipping 13 matching lines...) Expand all
100 stop_closure_.Cancel(); 104 stop_closure_.Cancel();
101 } 105 }
102 106
103 private: 107 private:
104 // AudioOutputStream::AudioSourceCallback overrides: 108 // AudioOutputStream::AudioSourceCallback overrides:
105 // Following methods could be called from *ANY* thread. 109 // Following methods could be called from *ANY* thread.
106 int OnMoreData(AudioBus* dest, uint32 /* total_bytes_delay */) override { 110 int OnMoreData(AudioBus* dest, uint32 /* total_bytes_delay */) override {
107 base::AutoLock al(state_lock_); 111 base::AutoLock al(state_lock_);
108 size_t bytes_written = 0; 112 size_t bytes_written = 0;
109 113
110 if (wav_audio_.AtEnd(cursor_) || 114 if (wav_audio_->AtEnd(cursor_) ||
111 !wav_audio_.CopyTo(dest, cursor_, &bytes_written)) { 115 !wav_audio_->CopyTo(dest, cursor_, &bytes_written)) {
112 if (delayed_stop_posted_) 116 if (delayed_stop_posted_)
113 return 0; 117 return 0;
114 delayed_stop_posted_ = true; 118 delayed_stop_posted_ = true;
115 AudioManager::Get()->GetTaskRunner()->PostDelayedTask( 119 AudioManager::Get()->GetTaskRunner()->PostDelayedTask(
116 FROM_HERE, 120 FROM_HERE,
117 stop_closure_.callback(), 121 stop_closure_.callback(),
118 base::TimeDelta::FromMilliseconds(kKeepAliveMs)); 122 base::TimeDelta::FromMilliseconds(kKeepAliveMs));
119 return 0; 123 return 0;
120 } 124 }
121 cursor_ += bytes_written; 125 cursor_ += bytes_written;
(...skipping 21 matching lines...) Expand all
143 } 147 }
144 148
145 // Must only be accessed on the AudioManager::GetTaskRunner() thread. 149 // Must only be accessed on the AudioManager::GetTaskRunner() thread.
146 bool started_; 150 bool started_;
147 AudioOutputStream* stream_; 151 AudioOutputStream* stream_;
148 152
149 // All variables below must be accessed under |state_lock_| when |started_|. 153 // All variables below must be accessed under |state_lock_| when |started_|.
150 base::Lock state_lock_; 154 base::Lock state_lock_;
151 size_t cursor_; 155 size_t cursor_;
152 bool delayed_stop_posted_; 156 bool delayed_stop_posted_;
153 const WavAudioHandler wav_audio_; 157 scoped_ptr<WavAudioHandler> wav_audio_;
154 base::CancelableClosure stop_closure_; 158 base::CancelableClosure stop_closure_;
155 159
156 DISALLOW_COPY_AND_ASSIGN(AudioStreamContainer); 160 DISALLOW_COPY_AND_ASSIGN(AudioStreamContainer);
157 }; 161 };
158 162
159 AudioStreamHandler::AudioStreamHandler(const base::StringPiece& wav_data) 163 AudioStreamHandler::AudioStreamHandler(const base::StringPiece& wav_data)
160 : wav_audio_(wav_data), 164 : initialized_(false) {
161 initialized_(false) {
162 AudioManager* manager = AudioManager::Get(); 165 AudioManager* manager = AudioManager::Get();
163 if (!manager) { 166 if (!manager) {
164 LOG(ERROR) << "Can't get access to audio manager."; 167 LOG(ERROR) << "Can't get access to audio manager.";
165 return; 168 return;
166 } 169 }
167 const AudioParameters params( 170
168 AudioParameters::AUDIO_PCM_LOW_LATENCY, 171 scoped_ptr<WavAudioHandler> wav_audio = WavAudioHandler::Create(wav_data);
169 GuessChannelLayout(wav_audio_.num_channels()), wav_audio_.sample_rate(), 172 if (!wav_audio) {
170 wav_audio_.bits_per_sample(), kDefaultFrameCount); 173 LOG(ERROR) << "wav_data is not valid";
174 return;
175 }
176
177 const AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY,
178 GuessChannelLayout(wav_audio->num_channels()),
179 wav_audio->sample_rate(),
180 wav_audio->bits_per_sample(),
181 kDefaultFrameCount);
171 if (!params.IsValid()) { 182 if (!params.IsValid()) {
172 LOG(ERROR) << "Audio params are invalid."; 183 LOG(ERROR) << "Audio params are invalid.";
173 return; 184 return;
174 } 185 }
175 stream_.reset(new AudioStreamContainer(wav_audio_)); 186
187 // Store the duration of the WAV data then pass the handler to |stream_|.
188 duration_ = wav_audio->GetDuration();
189 stream_.reset(new AudioStreamContainer(wav_audio.Pass()));
176 initialized_ = true; 190 initialized_ = true;
177 } 191 }
178 192
179 AudioStreamHandler::~AudioStreamHandler() { 193 AudioStreamHandler::~AudioStreamHandler() {
180 DCHECK(CalledOnValidThread()); 194 DCHECK(CalledOnValidThread());
181 AudioManager::Get()->GetTaskRunner()->PostTask( 195 if (IsInitialized()) {
182 FROM_HERE, 196 AudioManager::Get()->GetTaskRunner()->PostTask(
183 base::Bind(&AudioStreamContainer::Stop, base::Unretained(stream_.get()))); 197 FROM_HERE,
184 AudioManager::Get()->GetTaskRunner()->DeleteSoon(FROM_HERE, 198 base::Bind(&AudioStreamContainer::Stop,
185 stream_.release()); 199 base::Unretained(stream_.get())));
200 AudioManager::Get()->GetTaskRunner()->DeleteSoon(FROM_HERE,
201 stream_.release());
202 }
186 } 203 }
187 204
188 bool AudioStreamHandler::IsInitialized() const { 205 bool AudioStreamHandler::IsInitialized() const {
189 DCHECK(CalledOnValidThread()); 206 DCHECK(CalledOnValidThread());
190 return initialized_; 207 return initialized_;
191 } 208 }
192 209
193 bool AudioStreamHandler::Play() { 210 bool AudioStreamHandler::Play() {
194 DCHECK(CalledOnValidThread()); 211 DCHECK(CalledOnValidThread());
195 212
196 if (!IsInitialized()) 213 if (!IsInitialized())
197 return false; 214 return false;
198 215
199 AudioManager::Get()->GetTaskRunner()->PostTask( 216 AudioManager::Get()->GetTaskRunner()->PostTask(
200 FROM_HERE, 217 FROM_HERE,
201 base::Bind(base::IgnoreResult(&AudioStreamContainer::Play), 218 base::Bind(base::IgnoreResult(&AudioStreamContainer::Play),
202 base::Unretained(stream_.get()))); 219 base::Unretained(stream_.get())));
203 return true; 220 return true;
204 } 221 }
205 222
206 void AudioStreamHandler::Stop() { 223 void AudioStreamHandler::Stop() {
207 DCHECK(CalledOnValidThread()); 224 DCHECK(CalledOnValidThread());
225
226 if (!IsInitialized())
227 return;
228
208 AudioManager::Get()->GetTaskRunner()->PostTask( 229 AudioManager::Get()->GetTaskRunner()->PostTask(
209 FROM_HERE, 230 FROM_HERE,
210 base::Bind(&AudioStreamContainer::Stop, base::Unretained(stream_.get()))); 231 base::Bind(&AudioStreamContainer::Stop, base::Unretained(stream_.get())));
211 } 232 }
212 233
234 base::TimeDelta AudioStreamHandler::duration() const {
235 DCHECK(CalledOnValidThread());
236 return duration_;
237 }
238
213 // static 239 // static
214 void AudioStreamHandler::SetObserverForTesting(TestObserver* observer) { 240 void AudioStreamHandler::SetObserverForTesting(TestObserver* observer) {
215 g_observer_for_testing = observer; 241 g_observer_for_testing = observer;
216 } 242 }
217 243
218 // static 244 // static
219 void AudioStreamHandler::SetAudioSourceForTesting( 245 void AudioStreamHandler::SetAudioSourceForTesting(
220 AudioOutputStream::AudioSourceCallback* source) { 246 AudioOutputStream::AudioSourceCallback* source) {
221 g_audio_source_for_testing = source; 247 g_audio_source_for_testing = source;
222 } 248 }
223 249
224 } // namespace media 250 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698