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

Side by Side Diff: media/audio/audio_output_controller.cc

Issue 14600025: Replace AudioSilenceDetector with an AudioPowerMonitor. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Use CancelableCallback instead of extra-task for close reply. Created 7 years, 5 months 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 | Annotate | Revision Log
« no previous file with comments | « media/audio/audio_output_controller.h ('k') | media/audio/audio_output_controller_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/audio_output_controller.h" 5 #include "media/audio/audio_output_controller.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/debug/trace_event.h" 8 #include "base/debug/trace_event.h"
9 #include "base/message_loop/message_loop.h" 9 #include "base/message_loop/message_loop.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
11 #include "base/threading/platform_thread.h" 11 #include "base/threading/platform_thread.h"
12 #include "base/time/time.h" 12 #include "base/time/time.h"
13 #include "build/build_config.h" 13 #include "build/build_config.h"
14 #include "media/audio/audio_silence_detector.h" 14 #include "media/audio/audio_power_monitor.h"
15 #include "media/audio/audio_util.h" 15 #include "media/audio/audio_util.h"
16 #include "media/audio/shared_memory_util.h" 16 #include "media/audio/shared_memory_util.h"
17 #include "media/base/scoped_histogram_timer.h" 17 #include "media/base/scoped_histogram_timer.h"
18 18
19 using base::Time; 19 using base::Time;
20 using base::TimeDelta; 20 using base::TimeDelta;
21 21
22 namespace media { 22 namespace media {
23 23
24 // Amount of contiguous time where all audio is silent before considering the 24 // Time constant for AudioPowerMonitor. See AudioPowerMonitor ctor comments for
25 // stream to have transitioned and EventHandler::OnAudible() should be called. 25 // semantics. This value was arbitrarily chosen, but seems to work well.
26 static const int kQuestionableSilencePeriodMillis = 50; 26 static const int kPowerMeasurementTimeConstantMillis = 10;
27 27
28 // Sample value range below which audio is considered indistinguishably silent. 28 // Desired frequency of calls to EventHandler::OnPowerMeasured() for reporting
29 // 29 // power levels in the audio signal.
30 // TODO(miu): This value should be specified in dbFS units rather than full 30 static const int kPowerMeasurementsPerSecond = 30;
31 // scale. See TODO in audio_silence_detector.h.
32 static const float kIndistinguishableSilenceThreshold =
33 1.0f / 4096.0f; // Note: This is approximately -72 dbFS.
34 31
35 // Polling-related constants. 32 // Polling-related constants.
36 const int AudioOutputController::kPollNumAttempts = 3; 33 const int AudioOutputController::kPollNumAttempts = 3;
37 const int AudioOutputController::kPollPauseInMilliseconds = 3; 34 const int AudioOutputController::kPollPauseInMilliseconds = 3;
38 35
39 AudioOutputController::AudioOutputController(AudioManager* audio_manager, 36 AudioOutputController::AudioOutputController(AudioManager* audio_manager,
40 EventHandler* handler, 37 EventHandler* handler,
41 const AudioParameters& params, 38 const AudioParameters& params,
42 const std::string& input_device_id, 39 const std::string& input_device_id,
43 SyncReader* sync_reader) 40 SyncReader* sync_reader)
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PlayTime"); 148 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PlayTime");
152 149
153 // We can start from created or paused state. 150 // We can start from created or paused state.
154 if (state_ != kCreated && state_ != kPaused) 151 if (state_ != kCreated && state_ != kPaused)
155 return; 152 return;
156 153
157 // Ask for first packet. 154 // Ask for first packet.
158 sync_reader_->UpdatePendingBytes(0); 155 sync_reader_->UpdatePendingBytes(0);
159 156
160 state_ = kPlaying; 157 state_ = kPlaying;
161 silence_detector_.reset(new AudioSilenceDetector( 158
159 // Start monitoring power levels and send an initial notification that we're
160 // starting in silence.
161 handler_->OnPowerMeasured(AudioPowerMonitor::zero_power(), false);
162 power_monitor_callback_.Reset(
163 base::Bind(&EventHandler::OnPowerMeasured, base::Unretained(handler_)));
164 power_monitor_.reset(new AudioPowerMonitor(
162 params_.sample_rate(), 165 params_.sample_rate(),
163 TimeDelta::FromMilliseconds(kQuestionableSilencePeriodMillis), 166 TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMillis),
164 kIndistinguishableSilenceThreshold)); 167 TimeDelta::FromSeconds(1) / kPowerMeasurementsPerSecond,
168 base::MessageLoop::current(),
169 power_monitor_callback_.callback()));
165 170
166 // We start the AudioOutputStream lazily. 171 // We start the AudioOutputStream lazily.
167 AllowEntryToOnMoreIOData(); 172 AllowEntryToOnMoreIOData();
168 stream_->Start(this); 173 stream_->Start(this);
169 174
170 // Tell the event handler that we are now playing, and also start the silence
171 // detection notifications.
172 handler_->OnPlaying(); 175 handler_->OnPlaying();
173 silence_detector_->Start(
174 base::Bind(&EventHandler::OnAudible, base::Unretained(handler_)));
175 } 176 }
176 177
177 void AudioOutputController::StopStream() { 178 void AudioOutputController::StopStream() {
178 DCHECK(message_loop_->BelongsToCurrentThread()); 179 DCHECK(message_loop_->BelongsToCurrentThread());
179 180
180 if (state_ == kPlaying) { 181 if (state_ == kPlaying) {
181 stream_->Stop(); 182 stream_->Stop();
182 DisallowEntryToOnMoreIOData(); 183 DisallowEntryToOnMoreIOData();
183 silence_detector_->Stop(true); 184
184 silence_detector_.reset(); 185 // Stop monitoring power levels. By canceling power_monitor_callback_, any
186 // tasks posted to |message_loop_| by AudioPowerMonitor during the
187 // stream_->Stop() call above will not run.
188 power_monitor_.reset();
189 power_monitor_callback_.Cancel();
190
185 state_ = kPaused; 191 state_ = kPaused;
186 } 192 }
187 } 193 }
188 194
189 void AudioOutputController::DoPause() { 195 void AudioOutputController::DoPause() {
190 DCHECK(message_loop_->BelongsToCurrentThread()); 196 DCHECK(message_loop_->BelongsToCurrentThread());
191 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PauseTime"); 197 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PauseTime");
192 198
193 StopStream(); 199 StopStream();
194 200
195 if (state_ != kPaused) 201 if (state_ != kPaused)
196 return; 202 return;
197 203
198 // Send a special pause mark to the low-latency audio thread. 204 // Send a special pause mark to the low-latency audio thread.
199 sync_reader_->UpdatePendingBytes(kPauseMark); 205 sync_reader_->UpdatePendingBytes(kPauseMark);
200 206
207 // Paused means silence follows.
208 handler_->OnPowerMeasured(AudioPowerMonitor::zero_power(), false);
209
201 handler_->OnPaused(); 210 handler_->OnPaused();
202 } 211 }
203 212
204 void AudioOutputController::DoClose() { 213 void AudioOutputController::DoClose() {
205 DCHECK(message_loop_->BelongsToCurrentThread()); 214 DCHECK(message_loop_->BelongsToCurrentThread());
206 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.CloseTime"); 215 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.CloseTime");
207 216
208 if (state_ != kClosed) { 217 if (state_ != kClosed) {
209 DoStopCloseAndClearStream(); 218 DoStopCloseAndClearStream();
210 sync_reader_->Close(); 219 sync_reader_->Close();
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 const bool kShouldBlock = true; 272 const bool kShouldBlock = true;
264 #else 273 #else
265 const bool kShouldBlock = diverting_to_stream_ != NULL; 274 const bool kShouldBlock = diverting_to_stream_ != NULL;
266 #endif 275 #endif
267 276
268 const int frames = sync_reader_->Read(kShouldBlock, source, dest); 277 const int frames = sync_reader_->Read(kShouldBlock, source, dest);
269 DCHECK_LE(0, frames); 278 DCHECK_LE(0, frames);
270 sync_reader_->UpdatePendingBytes( 279 sync_reader_->UpdatePendingBytes(
271 buffers_state.total_bytes() + frames * params_.GetBytesPerFrame()); 280 buffers_state.total_bytes() + frames * params_.GetBytesPerFrame());
272 281
273 silence_detector_->Scan(dest, frames); 282 power_monitor_->Scan(*dest, frames);
274 283
275 AllowEntryToOnMoreIOData(); 284 AllowEntryToOnMoreIOData();
276 return frames; 285 return frames;
277 } 286 }
278 287
279 void AudioOutputController::OnError(AudioOutputStream* stream) { 288 void AudioOutputController::OnError(AudioOutputStream* stream) {
280 // Handle error on the audio controller thread. 289 // Handle error on the audio controller thread.
281 message_loop_->PostTask(FROM_HERE, base::Bind( 290 message_loop_->PostTask(FROM_HERE, base::Bind(
282 &AudioOutputController::DoReportError, this)); 291 &AudioOutputController::DoReportError, this));
283 } 292 }
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_)); 386 DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_));
378 base::AtomicRefCountInc(&num_allowed_io_); 387 base::AtomicRefCountInc(&num_allowed_io_);
379 } 388 }
380 389
381 void AudioOutputController::DisallowEntryToOnMoreIOData() { 390 void AudioOutputController::DisallowEntryToOnMoreIOData() {
382 const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_); 391 const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_);
383 DCHECK(is_zero); 392 DCHECK(is_zero);
384 } 393 }
385 394
386 } // namespace media 395 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/audio_output_controller.h ('k') | media/audio/audio_output_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698