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

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: More comments, more test cases. 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"
(...skipping 18 matching lines...) Expand all
29 const int kKeepAliveMs = 1500; 29 const int kKeepAliveMs = 1500;
30 30
31 AudioStreamHandler::TestObserver* g_observer_for_testing = NULL; 31 AudioStreamHandler::TestObserver* g_observer_for_testing = NULL;
32 AudioOutputStream::AudioSourceCallback* g_audio_source_for_testing = NULL; 32 AudioOutputStream::AudioSourceCallback* g_audio_source_for_testing = NULL;
33 33
34 } // namespace 34 } // namespace
35 35
36 class AudioStreamHandler::AudioStreamContainer 36 class AudioStreamHandler::AudioStreamContainer
37 : public AudioOutputStream::AudioSourceCallback { 37 : public AudioOutputStream::AudioSourceCallback {
38 public: 38 public:
39 explicit AudioStreamContainer(const WavAudioHandler& wav_audio) 39 explicit AudioStreamContainer(scoped_ptr<WavAudioHandler> wav_audio)
40 : started_(false), 40 : started_(false),
41 stream_(NULL), 41 stream_(NULL),
42 cursor_(0), 42 cursor_(0),
43 delayed_stop_posted_(false), 43 delayed_stop_posted_(false),
44 wav_audio_(wav_audio) {} 44 wav_audio_(wav_audio.Pass()) {
45 DCHECK(wav_audio_);
46 }
45 47
46 ~AudioStreamContainer() override { 48 ~AudioStreamContainer() override {
47 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 49 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
48 } 50 }
49 51
50 void Play() { 52 void Play() {
51 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 53 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
52 54
53 if (!stream_) { 55 if (!stream_) {
54 const AudioParameters params( 56 const AudioParameters params(
55 AudioParameters::AUDIO_PCM_LOW_LATENCY, 57 AudioParameters::AUDIO_PCM_LOW_LATENCY,
56 GuessChannelLayout(wav_audio_.num_channels()), 58 GuessChannelLayout(wav_audio_->num_channels()),
57 wav_audio_.sample_rate(), wav_audio_.bits_per_sample(), 59 wav_audio_->sample_rate(),
60 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 21 matching lines...) Expand all
143 } 146 }
144 147
145 // Must only be accessed on the AudioManager::GetTaskRunner() thread. 148 // Must only be accessed on the AudioManager::GetTaskRunner() thread.
146 bool started_; 149 bool started_;
147 AudioOutputStream* stream_; 150 AudioOutputStream* stream_;
148 151
149 // All variables below must be accessed under |state_lock_| when |started_|. 152 // All variables below must be accessed under |state_lock_| when |started_|.
150 base::Lock state_lock_; 153 base::Lock state_lock_;
151 size_t cursor_; 154 size_t cursor_;
152 bool delayed_stop_posted_; 155 bool delayed_stop_posted_;
153 const WavAudioHandler wav_audio_; 156 scoped_ptr<WavAudioHandler> wav_audio_;
154 base::CancelableClosure stop_closure_; 157 base::CancelableClosure stop_closure_;
155 158
156 DISALLOW_COPY_AND_ASSIGN(AudioStreamContainer); 159 DISALLOW_COPY_AND_ASSIGN(AudioStreamContainer);
157 }; 160 };
158 161
159 AudioStreamHandler::AudioStreamHandler(const base::StringPiece& wav_data) 162 AudioStreamHandler::AudioStreamHandler(const base::StringPiece& wav_data)
160 : wav_audio_(wav_data), 163 : initialized_(false) {
161 initialized_(false) {
162 AudioManager* manager = AudioManager::Get(); 164 AudioManager* manager = AudioManager::Get();
163 if (!manager) { 165 if (!manager) {
164 LOG(ERROR) << "Can't get access to audio manager."; 166 LOG(ERROR) << "Can't get access to audio manager.";
165 return; 167 return;
166 } 168 }
167 const AudioParameters params( 169
168 AudioParameters::AUDIO_PCM_LOW_LATENCY, 170 wav_audio_ = WavAudioHandler::Create(wav_data);
169 GuessChannelLayout(wav_audio_.num_channels()), wav_audio_.sample_rate(), 171 if (!wav_audio_) {
170 wav_audio_.bits_per_sample(), kDefaultFrameCount); 172 LOG(ERROR) << "wav_audio handler is not valid";
173 return;
174 }
175
176 const AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY,
177 GuessChannelLayout(wav_audio_->num_channels()),
178 wav_audio_->sample_rate(),
179 wav_audio_->bits_per_sample(),
180 kDefaultFrameCount);
171 if (!params.IsValid()) { 181 if (!params.IsValid()) {
172 LOG(ERROR) << "Audio params are invalid."; 182 LOG(ERROR) << "Audio params are invalid.";
173 return; 183 return;
174 } 184 }
175 stream_.reset(new AudioStreamContainer(wav_audio_)); 185
186 // Create an identical WavAudioHandler and pass it to AudioStreamContainer.
187 // This copy will be used on the AudioManager thread, and |wav_audio_| can
188 // safely be accessed on this thread via wav_audio_handler().
tommi (sloooow) - chröme 2015/11/19 09:44:06 that's unfortunate. Can you file a bug for it? H
slan 2015/11/19 18:57:16 Done. There was only one caller that needed it, an
189 // TODO(slan): Find a way to use just one copy. This approach is silly.
190 auto wav_audio_copy = WavAudioHandler::Create(wav_data);
191 DCHECK(wav_audio_copy);
192 stream_.reset(new AudioStreamContainer(wav_audio_copy.Pass()));
176 initialized_ = true; 193 initialized_ = true;
177 } 194 }
178 195
179 AudioStreamHandler::~AudioStreamHandler() { 196 AudioStreamHandler::~AudioStreamHandler() {
180 DCHECK(CalledOnValidThread()); 197 DCHECK(CalledOnValidThread());
181 AudioManager::Get()->GetTaskRunner()->PostTask( 198 AudioManager::Get()->GetTaskRunner()->PostTask(
182 FROM_HERE, 199 FROM_HERE,
183 base::Bind(&AudioStreamContainer::Stop, base::Unretained(stream_.get()))); 200 base::Bind(&AudioStreamContainer::Stop, base::Unretained(stream_.get())));
184 AudioManager::Get()->GetTaskRunner()->DeleteSoon(FROM_HERE, 201 AudioManager::Get()->GetTaskRunner()->DeleteSoon(FROM_HERE,
185 stream_.release()); 202 stream_.release());
(...skipping 29 matching lines...) Expand all
215 g_observer_for_testing = observer; 232 g_observer_for_testing = observer;
216 } 233 }
217 234
218 // static 235 // static
219 void AudioStreamHandler::SetAudioSourceForTesting( 236 void AudioStreamHandler::SetAudioSourceForTesting(
220 AudioOutputStream::AudioSourceCallback* source) { 237 AudioOutputStream::AudioSourceCallback* source) {
221 g_audio_source_for_testing = source; 238 g_audio_source_for_testing = source;
222 } 239 }
223 240
224 } // namespace media 241 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698