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

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: Formatting 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(), wav_audio_->bits_per_sample(),
58 kDefaultFrameCount); 61 kDefaultFrameCount);
59 stream_ = AudioManager::Get()->MakeAudioOutputStreamProxy(params, 62 stream_ = AudioManager::Get()->MakeAudioOutputStreamProxy(params,
60 std::string()); 63 std::string());
61 if (!stream_ || !stream_->Open()) { 64 if (!stream_ || !stream_->Open()) {
62 LOG(ERROR) << "Failed to open an output stream."; 65 LOG(ERROR) << "Failed to open an output stream.";
63 return; 66 return;
64 } 67 }
65 stream_->SetVolume(kOutputVolumePercent); 68 stream_->SetVolume(kOutputVolumePercent);
66 } 69 }
67 70
68 { 71 {
69 base::AutoLock al(state_lock_); 72 base::AutoLock al(state_lock_);
70 73
71 delayed_stop_posted_ = false; 74 delayed_stop_posted_ = false;
72 stop_closure_.Reset(base::Bind(&AudioStreamContainer::StopStream, 75 stop_closure_.Reset(base::Bind(&AudioStreamContainer::StopStream,
73 base::Unretained(this))); 76 base::Unretained(this)));
74 77
75 if (started_) { 78 if (started_) {
76 if (wav_audio_.AtEnd(cursor_)) 79 if (wav_audio_->AtEnd(cursor_))
77 cursor_ = 0; 80 cursor_ = 0;
78 return; 81 return;
79 } 82 }
80 83
81 cursor_ = 0; 84 cursor_ = 0;
82 } 85 }
83 86
84 started_ = true; 87 started_ = true;
85 if (g_audio_source_for_testing) 88 if (g_audio_source_for_testing)
86 stream_->Start(g_audio_source_for_testing); 89 stream_->Start(g_audio_source_for_testing);
(...skipping 13 matching lines...) Expand all
100 stop_closure_.Cancel(); 103 stop_closure_.Cancel();
101 } 104 }
102 105
103 private: 106 private:
104 // AudioOutputStream::AudioSourceCallback overrides: 107 // AudioOutputStream::AudioSourceCallback overrides:
105 // Following methods could be called from *ANY* thread. 108 // Following methods could be called from *ANY* thread.
106 int OnMoreData(AudioBus* dest, uint32 /* total_bytes_delay */) override { 109 int OnMoreData(AudioBus* dest, uint32 /* total_bytes_delay */) override {
107 base::AutoLock al(state_lock_); 110 base::AutoLock al(state_lock_);
108 size_t bytes_written = 0; 111 size_t bytes_written = 0;
109 112
110 if (wav_audio_.AtEnd(cursor_) || 113 if (wav_audio_->AtEnd(cursor_) ||
111 !wav_audio_.CopyTo(dest, cursor_, &bytes_written)) { 114 !wav_audio_->CopyTo(dest, cursor_, &bytes_written)) {
112 if (delayed_stop_posted_) 115 if (delayed_stop_posted_)
113 return 0; 116 return 0;
114 delayed_stop_posted_ = true; 117 delayed_stop_posted_ = true;
115 AudioManager::Get()->GetTaskRunner()->PostDelayedTask( 118 AudioManager::Get()->GetTaskRunner()->PostDelayedTask(
116 FROM_HERE, 119 FROM_HERE,
117 stop_closure_.callback(), 120 stop_closure_.callback(),
118 base::TimeDelta::FromMilliseconds(kKeepAliveMs)); 121 base::TimeDelta::FromMilliseconds(kKeepAliveMs));
119 return 0; 122 return 0;
120 } 123 }
121 cursor_ += bytes_written; 124 cursor_ += bytes_written;
(...skipping 18 matching lines...) Expand all
140 } 143 }
141 144
142 // Must only be accessed on the AudioManager::GetTaskRunner() thread. 145 // Must only be accessed on the AudioManager::GetTaskRunner() thread.
143 bool started_; 146 bool started_;
144 AudioOutputStream* stream_; 147 AudioOutputStream* stream_;
145 148
146 // All variables below must be accessed under |state_lock_| when |started_|. 149 // All variables below must be accessed under |state_lock_| when |started_|.
147 base::Lock state_lock_; 150 base::Lock state_lock_;
148 size_t cursor_; 151 size_t cursor_;
149 bool delayed_stop_posted_; 152 bool delayed_stop_posted_;
150 const WavAudioHandler wav_audio_; 153 scoped_ptr<WavAudioHandler> wav_audio_;
151 base::CancelableClosure stop_closure_; 154 base::CancelableClosure stop_closure_;
152 155
153 DISALLOW_COPY_AND_ASSIGN(AudioStreamContainer); 156 DISALLOW_COPY_AND_ASSIGN(AudioStreamContainer);
154 }; 157 };
155 158
156 AudioStreamHandler::AudioStreamHandler(const base::StringPiece& wav_data) 159 AudioStreamHandler::AudioStreamHandler(const base::StringPiece& wav_data) {
157 : wav_audio_(wav_data),
158 initialized_(false) {
159 AudioManager* manager = AudioManager::Get(); 160 AudioManager* manager = AudioManager::Get();
160 if (!manager) { 161 if (!manager) {
161 LOG(ERROR) << "Can't get access to audio manager."; 162 LOG(ERROR) << "Can't get access to audio manager.";
162 return; 163 return;
163 } 164 }
165
166 scoped_ptr<WavAudioHandler> wav_audio = WavAudioHandler::Create(wav_data);
167 if (!wav_audio) {
168 LOG(ERROR) << "wav_data is not valid";
169 return;
170 }
171
164 const AudioParameters params( 172 const AudioParameters params(
165 AudioParameters::AUDIO_PCM_LOW_LATENCY, 173 AudioParameters::AUDIO_PCM_LOW_LATENCY,
166 GuessChannelLayout(wav_audio_.num_channels()), wav_audio_.sample_rate(), 174 GuessChannelLayout(wav_audio->num_channels()), wav_audio->sample_rate(),
167 wav_audio_.bits_per_sample(), kDefaultFrameCount); 175 wav_audio->bits_per_sample(), kDefaultFrameCount);
168 if (!params.IsValid()) { 176 if (!params.IsValid()) {
169 LOG(ERROR) << "Audio params are invalid."; 177 LOG(ERROR) << "Audio params are invalid.";
170 return; 178 return;
171 } 179 }
172 stream_.reset(new AudioStreamContainer(wav_audio_)); 180
173 initialized_ = true; 181 // Store the duration of the WAV data then pass the handler to |stream_|.
182 duration_ = wav_audio->GetDuration();
183 stream_.reset(new AudioStreamContainer(wav_audio.Pass()));
174 } 184 }
175 185
176 AudioStreamHandler::~AudioStreamHandler() { 186 AudioStreamHandler::~AudioStreamHandler() {
177 DCHECK(CalledOnValidThread()); 187 DCHECK(CalledOnValidThread());
178 AudioManager::Get()->GetTaskRunner()->PostTask( 188 if (IsInitialized()) {
179 FROM_HERE, 189 AudioManager::Get()->GetTaskRunner()->PostTask(
180 base::Bind(&AudioStreamContainer::Stop, base::Unretained(stream_.get()))); 190 FROM_HERE, base::Bind(&AudioStreamContainer::Stop,
181 AudioManager::Get()->GetTaskRunner()->DeleteSoon(FROM_HERE, 191 base::Unretained(stream_.get())));
182 stream_.release()); 192 AudioManager::Get()->GetTaskRunner()->DeleteSoon(FROM_HERE,
193 stream_.release());
194 }
183 } 195 }
184 196
185 bool AudioStreamHandler::IsInitialized() const { 197 bool AudioStreamHandler::IsInitialized() const {
186 DCHECK(CalledOnValidThread()); 198 DCHECK(CalledOnValidThread());
187 return initialized_; 199 return stream_;
188 } 200 }
189 201
190 bool AudioStreamHandler::Play() { 202 bool AudioStreamHandler::Play() {
191 DCHECK(CalledOnValidThread()); 203 DCHECK(CalledOnValidThread());
192 204
193 if (!IsInitialized()) 205 if (!IsInitialized())
194 return false; 206 return false;
195 207
196 AudioManager::Get()->GetTaskRunner()->PostTask( 208 AudioManager::Get()->GetTaskRunner()->PostTask(
197 FROM_HERE, 209 FROM_HERE,
198 base::Bind(base::IgnoreResult(&AudioStreamContainer::Play), 210 base::Bind(base::IgnoreResult(&AudioStreamContainer::Play),
199 base::Unretained(stream_.get()))); 211 base::Unretained(stream_.get())));
200 return true; 212 return true;
201 } 213 }
202 214
203 void AudioStreamHandler::Stop() { 215 void AudioStreamHandler::Stop() {
204 DCHECK(CalledOnValidThread()); 216 DCHECK(CalledOnValidThread());
217
218 if (!IsInitialized())
219 return;
220
205 AudioManager::Get()->GetTaskRunner()->PostTask( 221 AudioManager::Get()->GetTaskRunner()->PostTask(
206 FROM_HERE, 222 FROM_HERE,
207 base::Bind(&AudioStreamContainer::Stop, base::Unretained(stream_.get()))); 223 base::Bind(&AudioStreamContainer::Stop, base::Unretained(stream_.get())));
208 } 224 }
209 225
226 base::TimeDelta AudioStreamHandler::duration() const {
227 DCHECK(CalledOnValidThread());
228 return duration_;
229 }
230
210 // static 231 // static
211 void AudioStreamHandler::SetObserverForTesting(TestObserver* observer) { 232 void AudioStreamHandler::SetObserverForTesting(TestObserver* observer) {
212 g_observer_for_testing = observer; 233 g_observer_for_testing = observer;
213 } 234 }
214 235
215 // static 236 // static
216 void AudioStreamHandler::SetAudioSourceForTesting( 237 void AudioStreamHandler::SetAudioSourceForTesting(
217 AudioOutputStream::AudioSourceCallback* source) { 238 AudioOutputStream::AudioSourceCallback* source) {
218 g_audio_source_for_testing = source; 239 g_audio_source_for_testing = source;
219 } 240 }
220 241
221 } // namespace media 242 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/sounds/audio_stream_handler.h ('k') | media/audio/sounds/audio_stream_handler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698