Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 "content/renderer/media/webrtc_audio_renderer.h" | 5 #include "content/renderer/media/webrtc_audio_renderer.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 32 | 32 |
| 33 namespace content { | 33 namespace content { |
| 34 | 34 |
| 35 namespace { | 35 namespace { |
| 36 | 36 |
| 37 // We add a UMA histogram measuring the execution time of the Render() method | 37 // We add a UMA histogram measuring the execution time of the Render() method |
| 38 // every |kNumCallbacksBetweenRenderTimeHistograms| callback. Assuming 10ms | 38 // every |kNumCallbacksBetweenRenderTimeHistograms| callback. Assuming 10ms |
| 39 // between each callback leads to one UMA update each 100ms. | 39 // between each callback leads to one UMA update each 100ms. |
| 40 const int kNumCallbacksBetweenRenderTimeHistograms = 10; | 40 const int kNumCallbacksBetweenRenderTimeHistograms = 10; |
| 41 | 41 |
| 42 // We log UMA data for the average execution time of the SourceCallback() method | |
| 43 // every |kNumCallbacksBetweenRenderAverageTimeHistograms| callback. Assuming | |
| 44 // 10 ms between each callback leads to one UMA update per second. | |
| 45 const int kNumCallbacksBetweenRenderAverageTimeHistograms = 100; | |
| 46 | |
| 42 // Audio parameters that don't change. | 47 // Audio parameters that don't change. |
| 43 const media::AudioParameters::Format kFormat = | 48 const media::AudioParameters::Format kFormat = |
| 44 media::AudioParameters::AUDIO_PCM_LOW_LATENCY; | 49 media::AudioParameters::AUDIO_PCM_LOW_LATENCY; |
| 45 const media::ChannelLayout kChannelLayout = media::CHANNEL_LAYOUT_STEREO; | 50 const media::ChannelLayout kChannelLayout = media::CHANNEL_LAYOUT_STEREO; |
| 46 const int kChannels = 2; | 51 const int kChannels = 2; |
| 47 const int kBitsPerSample = 16; | 52 const int kBitsPerSample = 16; |
| 48 | 53 |
| 49 // This is a simple wrapper class that's handed out to users of a shared | 54 // This is a simple wrapper class that's handed out to users of a shared |
| 50 // WebRtcAudioRenderer instance. This class maintains the per-user 'playing' | 55 // WebRtcAudioRenderer instance. This class maintains the per-user 'playing' |
| 51 // and 'started' states to avoid problems related to incorrect usage which | 56 // and 'started' states to avoid problems related to incorrect usage which |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 245 | 250 |
| 246 void WebRtcAudioRenderer::Play() { | 251 void WebRtcAudioRenderer::Play() { |
| 247 DVLOG(1) << "WebRtcAudioRenderer::Play()"; | 252 DVLOG(1) << "WebRtcAudioRenderer::Play()"; |
| 248 DCHECK(thread_checker_.CalledOnValidThread()); | 253 DCHECK(thread_checker_.CalledOnValidThread()); |
| 249 | 254 |
| 250 if (playing_state_.playing()) | 255 if (playing_state_.playing()) |
| 251 return; | 256 return; |
| 252 | 257 |
| 253 playing_state_.set_playing(true); | 258 playing_state_.set_playing(true); |
| 254 render_callback_count_ = 0; | 259 render_callback_count_ = 0; |
| 260 accumulated_render_time_ = base::TimeDelta(); | |
| 255 | 261 |
| 256 OnPlayStateChanged(media_stream_, &playing_state_); | 262 OnPlayStateChanged(media_stream_, &playing_state_); |
| 257 } | 263 } |
| 258 | 264 |
| 259 void WebRtcAudioRenderer::EnterPlayState() { | 265 void WebRtcAudioRenderer::EnterPlayState() { |
| 260 DVLOG(1) << "WebRtcAudioRenderer::EnterPlayState()"; | 266 DVLOG(1) << "WebRtcAudioRenderer::EnterPlayState()"; |
| 261 DCHECK(thread_checker_.CalledOnValidThread()); | 267 DCHECK(thread_checker_.CalledOnValidThread()); |
| 262 DCHECK_GT(start_ref_count_, 0) << "Did you forget to call Start()?"; | 268 DCHECK_GT(start_ref_count_, 0) << "Did you forget to call Start()?"; |
| 263 base::AutoLock auto_lock(lock_); | 269 base::AutoLock auto_lock(lock_); |
| 264 if (state_ == UNINITIALIZED) | 270 if (state_ == UNINITIALIZED) |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 298 | 304 |
| 299 DCHECK_EQ(state_, PLAYING); | 305 DCHECK_EQ(state_, PLAYING); |
| 300 DCHECK_GT(play_ref_count_, 0); | 306 DCHECK_GT(play_ref_count_, 0); |
| 301 if (!--play_ref_count_) | 307 if (!--play_ref_count_) |
| 302 state_ = PAUSED; | 308 state_ = PAUSED; |
| 303 } | 309 } |
| 304 | 310 |
| 305 void WebRtcAudioRenderer::Stop() { | 311 void WebRtcAudioRenderer::Stop() { |
| 306 DVLOG(1) << "WebRtcAudioRenderer::Stop()"; | 312 DVLOG(1) << "WebRtcAudioRenderer::Stop()"; |
| 307 DCHECK(thread_checker_.CalledOnValidThread()); | 313 DCHECK(thread_checker_.CalledOnValidThread()); |
| 314 if (render_callback_count_ > 0) { | |
| 315 UMA_HISTOGRAM_TIMES("WebRTC.AudioRenderTimeMax", max_render_time_); | |
| 316 max_render_time_ = base::TimeDelta(); | |
| 317 } | |
| 318 | |
| 308 { | 319 { |
| 309 base::AutoLock auto_lock(lock_); | 320 base::AutoLock auto_lock(lock_); |
| 310 if (state_ == UNINITIALIZED) | 321 if (state_ == UNINITIALIZED) |
| 311 return; | 322 return; |
| 312 | 323 |
| 313 if (--start_ref_count_) | 324 if (--start_ref_count_) |
| 314 return; | 325 return; |
| 315 | 326 |
| 316 DVLOG(1) << "Calling RemoveAudioRenderer and Stop()."; | 327 DVLOG(1) << "Calling RemoveAudioRenderer and Stop()."; |
| 317 | 328 |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 469 // otherwise the data will be buffered up inside |source_|. | 480 // otherwise the data will be buffered up inside |source_|. |
| 470 source_->RenderData(audio_bus, sink_params_.sample_rate(), | 481 source_->RenderData(audio_bus, sink_params_.sample_rate(), |
| 471 output_delay_milliseconds, | 482 output_delay_milliseconds, |
| 472 ¤t_time_); | 483 ¤t_time_); |
| 473 | 484 |
| 474 // Avoid filling up the audio bus if we are not playing; instead | 485 // Avoid filling up the audio bus if we are not playing; instead |
| 475 // return here and ensure that the returned value in Render() is 0. | 486 // return here and ensure that the returned value in Render() is 0. |
| 476 if (state_ != PLAYING) | 487 if (state_ != PLAYING) |
| 477 audio_bus->Zero(); | 488 audio_bus->Zero(); |
| 478 | 489 |
| 479 if (++render_callback_count_ == kNumCallbacksBetweenRenderTimeHistograms) { | 490 // Measure the elapsed time for this function and log periodically. |
| 480 base::TimeDelta elapsed = base::TimeTicks::Now() - start_time; | 491 base::TimeDelta elapsed = base::TimeTicks::Now() - start_time; |
|
DaleCurtis
2016/08/22 17:32:19
This will skew if you catch it between a suspend/r
Henrik Grunell
2016/08/23 10:42:04
Hmm, isn't it so that the ticks are updated as lon
DaleCurtis
2016/08/24 17:45:16
If you record start_time prior to suspend and then
| |
| 481 render_callback_count_ = 0; | 492 if (elapsed > max_render_time_) |
| 493 max_render_time_ = elapsed; | |
| 494 accumulated_render_time_ += elapsed; | |
| 495 ++render_callback_count_; | |
| 496 if (render_callback_count_ % kNumCallbacksBetweenRenderTimeHistograms == 0) | |
| 482 UMA_HISTOGRAM_TIMES("WebRTC.AudioRenderTimes", elapsed); | 497 UMA_HISTOGRAM_TIMES("WebRTC.AudioRenderTimes", elapsed); |
| 498 if (render_callback_count_ % | |
| 499 kNumCallbacksBetweenRenderAverageTimeHistograms == | |
| 500 0) { | |
| 501 UMA_HISTOGRAM_CUSTOM_TIMES( | |
| 502 "WebRTC.AudioRenderTimesAverage", | |
| 503 accumulated_render_time_ / | |
| 504 kNumCallbacksBetweenRenderAverageTimeHistograms, | |
| 505 base::TimeDelta::FromMicroseconds(100), | |
|
Henrik Grunell
2016/08/22 15:21:59
I'm not sure if microseconds precision is possible
DaleCurtis
2016/08/22 17:32:19
Yeah, the best you can do is milliseconds. The mac
Ilya Sherman
2016/08/22 21:17:47
Alternately, you could use a CUSTOM_COUNTS macro a
Henrik Grunell
2016/08/23 10:42:04
OK, I've switched to CUSTOM_COUNTS.
| |
| 506 base::TimeDelta::FromMilliseconds(30), 50); | |
| 507 accumulated_render_time_ = base::TimeDelta(); | |
| 483 } | 508 } |
| 484 } | 509 } |
| 485 | 510 |
| 486 void WebRtcAudioRenderer::UpdateSourceVolume( | 511 void WebRtcAudioRenderer::UpdateSourceVolume( |
| 487 webrtc::AudioSourceInterface* source) { | 512 webrtc::AudioSourceInterface* source) { |
| 488 DCHECK(thread_checker_.CalledOnValidThread()); | 513 DCHECK(thread_checker_.CalledOnValidThread()); |
| 489 | 514 |
| 490 // Note: If there are no playing audio renderers, then the volume will be | 515 // Note: If there are no playing audio renderers, then the volume will be |
| 491 // set to 0.0. | 516 // set to 0.0. |
| 492 float volume = 0.0f; | 517 float volume = 0.0f; |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 648 base::Bind(&WebRtcAudioRenderer::SourceCallback, | 673 base::Bind(&WebRtcAudioRenderer::SourceCallback, |
| 649 base::Unretained(this)))); | 674 base::Unretained(this)))); |
| 650 } | 675 } |
| 651 sink_params_ = new_sink_params; | 676 sink_params_ = new_sink_params; |
| 652 } | 677 } |
| 653 | 678 |
| 654 sink_->Initialize(new_sink_params, this); | 679 sink_->Initialize(new_sink_params, this); |
| 655 } | 680 } |
| 656 | 681 |
| 657 } // namespace content | 682 } // namespace content |
| OLD | NEW |