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

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: audio_power_monitor_unittest.cc compile fixes 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
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.h" 9 #include "base/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_.reset(new AudioPowerMonitor(
162 params_.sample_rate(), 163 params_.sample_rate(),
163 TimeDelta::FromMilliseconds(kQuestionableSilencePeriodMillis), 164 TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMillis),
164 kIndistinguishableSilenceThreshold)); 165 TimeDelta::FromSeconds(1) / kPowerMeasurementsPerSecond,
166 base::MessageLoop::current(),
167 base::Bind(&EventHandler::OnPowerMeasured, base::Unretained(handler_))));
165 168
166 // We start the AudioOutputStream lazily. 169 // We start the AudioOutputStream lazily.
167 AllowEntryToOnMoreIOData(); 170 AllowEntryToOnMoreIOData();
168 stream_->Start(this); 171 stream_->Start(this);
169 172
170 // Tell the event handler that we are now playing, and also start the silence
171 // detection notifications.
172 handler_->OnPlaying(); 173 handler_->OnPlaying();
173 silence_detector_->Start(
174 base::Bind(&EventHandler::OnAudible, base::Unretained(handler_)));
175 } 174 }
176 175
177 void AudioOutputController::StopStream() { 176 void AudioOutputController::StopStream() {
178 DCHECK(message_loop_->BelongsToCurrentThread()); 177 DCHECK(message_loop_->BelongsToCurrentThread());
179 178
180 if (state_ == kPlaying) { 179 if (state_ == kPlaying) {
181 stream_->Stop(); 180 stream_->Stop();
182 DisallowEntryToOnMoreIOData(); 181 DisallowEntryToOnMoreIOData();
183 silence_detector_->Stop(true); 182 power_monitor_.reset();
184 silence_detector_.reset(); 183 // Send a final notification that we're ending in silence.
184 handler_->OnPowerMeasured(AudioPowerMonitor::zero_power(), false);
185 state_ = kPaused; 185 state_ = kPaused;
186 } 186 }
187 } 187 }
188 188
189 void AudioOutputController::DoPause() { 189 void AudioOutputController::DoPause() {
190 DCHECK(message_loop_->BelongsToCurrentThread()); 190 DCHECK(message_loop_->BelongsToCurrentThread());
191 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PauseTime"); 191 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PauseTime");
192 192
193 StopStream(); 193 StopStream();
194 194
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 const bool kShouldBlock = true; 263 const bool kShouldBlock = true;
264 #else 264 #else
265 const bool kShouldBlock = diverting_to_stream_ != NULL; 265 const bool kShouldBlock = diverting_to_stream_ != NULL;
266 #endif 266 #endif
267 267
268 const int frames = sync_reader_->Read(kShouldBlock, source, dest); 268 const int frames = sync_reader_->Read(kShouldBlock, source, dest);
269 DCHECK_LE(0, frames); 269 DCHECK_LE(0, frames);
270 sync_reader_->UpdatePendingBytes( 270 sync_reader_->UpdatePendingBytes(
271 buffers_state.total_bytes() + frames * params_.GetBytesPerFrame()); 271 buffers_state.total_bytes() + frames * params_.GetBytesPerFrame());
272 272
273 silence_detector_->Scan(dest, frames); 273 power_monitor_->Scan(*dest, frames);
274 274
275 AllowEntryToOnMoreIOData(); 275 AllowEntryToOnMoreIOData();
276 return frames; 276 return frames;
277 } 277 }
278 278
279 void AudioOutputController::OnError(AudioOutputStream* stream) { 279 void AudioOutputController::OnError(AudioOutputStream* stream) {
280 // Handle error on the audio controller thread. 280 // Handle error on the audio controller thread.
281 message_loop_->PostTask(FROM_HERE, base::Bind( 281 message_loop_->PostTask(FROM_HERE, base::Bind(
282 &AudioOutputController::DoReportError, this)); 282 &AudioOutputController::DoReportError, this));
283 } 283 }
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_)); 377 DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_));
378 base::AtomicRefCountInc(&num_allowed_io_); 378 base::AtomicRefCountInc(&num_allowed_io_);
379 } 379 }
380 380
381 void AudioOutputController::DisallowEntryToOnMoreIOData() { 381 void AudioOutputController::DisallowEntryToOnMoreIOData() {
382 const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_); 382 const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_);
383 DCHECK(is_zero); 383 DCHECK(is_zero);
384 } 384 }
385 385
386 } // namespace media 386 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698