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 16 matching lines...) Expand all Loading... | |
| 27 | 27 |
| 28 #if defined(OS_WIN) | 28 #if defined(OS_WIN) |
| 29 #include "base/win/windows_version.h" | 29 #include "base/win/windows_version.h" |
| 30 #include "media/audio/win/core_audio_util_win.h" | 30 #include "media/audio/win/core_audio_util_win.h" |
| 31 #endif | 31 #endif |
| 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 | |
| 38 // every |kNumCallbacksBetweenRenderTimeHistograms| callback. Assuming 10ms | |
| 39 // between each callback leads to one UMA update each 100ms. | |
| 40 const int kNumCallbacksBetweenRenderTimeHistograms = 10; | |
| 41 | |
| 42 // Audio parameters that don't change. | 37 // Audio parameters that don't change. |
| 43 const media::AudioParameters::Format kFormat = | 38 const media::AudioParameters::Format kFormat = |
| 44 media::AudioParameters::AUDIO_PCM_LOW_LATENCY; | 39 media::AudioParameters::AUDIO_PCM_LOW_LATENCY; |
| 45 const media::ChannelLayout kChannelLayout = media::CHANNEL_LAYOUT_STEREO; | 40 const media::ChannelLayout kChannelLayout = media::CHANNEL_LAYOUT_STEREO; |
| 46 const int kChannels = 2; | 41 const int kChannels = 2; |
| 47 const int kBitsPerSample = 16; | 42 const int kBitsPerSample = 16; |
| 48 | 43 |
| 44 // Used for UMA histograms. | |
| 45 const int kRenderTimeHistogramMinMicroseconds = 100; | |
| 46 const int kRenderTimeHistogramMaxMicroseconds = 30 * 1000; // 30 milliseconds | |
|
Ilya Sherman
2016/08/24 21:53:41
I somewhat suspect that this is too low an upper b
Henrik Grunell
2016/08/25 08:34:07
That makes sense, changed to max 1 s.
| |
| 47 | |
| 49 // This is a simple wrapper class that's handed out to users of a shared | 48 // 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' | 49 // WebRtcAudioRenderer instance. This class maintains the per-user 'playing' |
| 51 // and 'started' states to avoid problems related to incorrect usage which | 50 // and 'started' states to avoid problems related to incorrect usage which |
| 52 // might violate the implementation assumptions inside WebRtcAudioRenderer | 51 // might violate the implementation assumptions inside WebRtcAudioRenderer |
| 53 // (see the play reference count). | 52 // (see the play reference count). |
| 54 class SharedAudioRenderer : public MediaStreamAudioRenderer { | 53 class SharedAudioRenderer : public MediaStreamAudioRenderer { |
| 55 public: | 54 public: |
| 56 // Callback definition for a callback that is called when when Play(), Pause() | 55 // Callback definition for a callback that is called when when Play(), Pause() |
| 57 // or SetVolume are called (whenever the internal |playing_state_| changes). | 56 // or SetVolume are called (whenever the internal |playing_state_| changes). |
| 58 typedef base::Callback<void(const blink::WebMediaStream&, | 57 typedef base::Callback<void(const blink::WebMediaStream&, |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 164 source_render_frame_id_(source_render_frame_id), | 163 source_render_frame_id_(source_render_frame_id), |
| 165 session_id_(session_id), | 164 session_id_(session_id), |
| 166 signaling_thread_(signaling_thread), | 165 signaling_thread_(signaling_thread), |
| 167 media_stream_(media_stream), | 166 media_stream_(media_stream), |
| 168 source_(NULL), | 167 source_(NULL), |
| 169 play_ref_count_(0), | 168 play_ref_count_(0), |
| 170 start_ref_count_(0), | 169 start_ref_count_(0), |
| 171 audio_delay_milliseconds_(0), | 170 audio_delay_milliseconds_(0), |
| 172 sink_params_(kFormat, kChannelLayout, 0, kBitsPerSample, 0), | 171 sink_params_(kFormat, kChannelLayout, 0, kBitsPerSample, 0), |
| 173 output_device_id_(device_id), | 172 output_device_id_(device_id), |
| 174 security_origin_(security_origin), | 173 security_origin_(security_origin) { |
| 175 render_callback_count_(0) { | |
| 176 WebRtcLogMessage(base::StringPrintf( | 174 WebRtcLogMessage(base::StringPrintf( |
| 177 "WAR::WAR. source_render_frame_id=%d, session_id=%d, effects=%i", | 175 "WAR::WAR. source_render_frame_id=%d, session_id=%d, effects=%i", |
| 178 source_render_frame_id, session_id, sink_params_.effects())); | 176 source_render_frame_id, session_id, sink_params_.effects())); |
| 179 } | 177 } |
| 180 | 178 |
| 181 WebRtcAudioRenderer::~WebRtcAudioRenderer() { | 179 WebRtcAudioRenderer::~WebRtcAudioRenderer() { |
| 182 DCHECK(thread_checker_.CalledOnValidThread()); | 180 DCHECK(thread_checker_.CalledOnValidThread()); |
| 183 DCHECK_EQ(state_, UNINITIALIZED); | 181 DCHECK_EQ(state_, UNINITIALIZED); |
| 184 } | 182 } |
| 185 | 183 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 244 } | 242 } |
| 245 | 243 |
| 246 void WebRtcAudioRenderer::Play() { | 244 void WebRtcAudioRenderer::Play() { |
| 247 DVLOG(1) << "WebRtcAudioRenderer::Play()"; | 245 DVLOG(1) << "WebRtcAudioRenderer::Play()"; |
| 248 DCHECK(thread_checker_.CalledOnValidThread()); | 246 DCHECK(thread_checker_.CalledOnValidThread()); |
| 249 | 247 |
| 250 if (playing_state_.playing()) | 248 if (playing_state_.playing()) |
| 251 return; | 249 return; |
| 252 | 250 |
| 253 playing_state_.set_playing(true); | 251 playing_state_.set_playing(true); |
| 254 render_callback_count_ = 0; | |
| 255 | 252 |
| 256 OnPlayStateChanged(media_stream_, &playing_state_); | 253 OnPlayStateChanged(media_stream_, &playing_state_); |
| 257 } | 254 } |
| 258 | 255 |
| 259 void WebRtcAudioRenderer::EnterPlayState() { | 256 void WebRtcAudioRenderer::EnterPlayState() { |
| 260 DVLOG(1) << "WebRtcAudioRenderer::EnterPlayState()"; | 257 DVLOG(1) << "WebRtcAudioRenderer::EnterPlayState()"; |
| 261 DCHECK(thread_checker_.CalledOnValidThread()); | 258 DCHECK(thread_checker_.CalledOnValidThread()); |
| 262 DCHECK_GT(start_ref_count_, 0) << "Did you forget to call Start()?"; | 259 DCHECK_GT(start_ref_count_, 0) << "Did you forget to call Start()?"; |
| 263 base::AutoLock auto_lock(lock_); | 260 base::AutoLock auto_lock(lock_); |
| 264 if (state_ == UNINITIALIZED) | 261 if (state_ == UNINITIALIZED) |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 298 | 295 |
| 299 DCHECK_EQ(state_, PLAYING); | 296 DCHECK_EQ(state_, PLAYING); |
| 300 DCHECK_GT(play_ref_count_, 0); | 297 DCHECK_GT(play_ref_count_, 0); |
| 301 if (!--play_ref_count_) | 298 if (!--play_ref_count_) |
| 302 state_ = PAUSED; | 299 state_ = PAUSED; |
| 303 } | 300 } |
| 304 | 301 |
| 305 void WebRtcAudioRenderer::Stop() { | 302 void WebRtcAudioRenderer::Stop() { |
| 306 DVLOG(1) << "WebRtcAudioRenderer::Stop()"; | 303 DVLOG(1) << "WebRtcAudioRenderer::Stop()"; |
| 307 DCHECK(thread_checker_.CalledOnValidThread()); | 304 DCHECK(thread_checker_.CalledOnValidThread()); |
| 305 // If |max_render_time_| is zero, no render call has been made. | |
| 306 if (!max_render_time_.is_zero()) { | |
| 307 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
| 308 "Media.Audio.Render.GetSourceDataTimeMax.WebRTC", | |
| 309 max_render_time_.InMicroseconds(), kRenderTimeHistogramMinMicroseconds, | |
| 310 kRenderTimeHistogramMaxMicroseconds, 50); | |
| 311 max_render_time_ = base::TimeDelta(); | |
| 312 } | |
| 313 | |
| 308 { | 314 { |
| 309 base::AutoLock auto_lock(lock_); | 315 base::AutoLock auto_lock(lock_); |
| 310 if (state_ == UNINITIALIZED) | 316 if (state_ == UNINITIALIZED) |
| 311 return; | 317 return; |
| 312 | 318 |
| 313 if (--start_ref_count_) | 319 if (--start_ref_count_) |
| 314 return; | 320 return; |
| 315 | 321 |
| 316 DVLOG(1) << "Calling RemoveAudioRenderer and Stop()."; | 322 DVLOG(1) << "Calling RemoveAudioRenderer and Stop()."; |
| 317 | 323 |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 469 // otherwise the data will be buffered up inside |source_|. | 475 // otherwise the data will be buffered up inside |source_|. |
| 470 source_->RenderData(audio_bus, sink_params_.sample_rate(), | 476 source_->RenderData(audio_bus, sink_params_.sample_rate(), |
| 471 output_delay_milliseconds, | 477 output_delay_milliseconds, |
| 472 ¤t_time_); | 478 ¤t_time_); |
| 473 | 479 |
| 474 // Avoid filling up the audio bus if we are not playing; instead | 480 // 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. | 481 // return here and ensure that the returned value in Render() is 0. |
| 476 if (state_ != PLAYING) | 482 if (state_ != PLAYING) |
| 477 audio_bus->Zero(); | 483 audio_bus->Zero(); |
| 478 | 484 |
| 479 if (++render_callback_count_ == kNumCallbacksBetweenRenderTimeHistograms) { | 485 // Measure the elapsed time for this function and log it to UMA. Store the max |
| 486 // value. Don't do this for low resolution clocks to not skew data. | |
| 487 if (base::TimeTicks::IsHighResolution()) { | |
|
Henrik Grunell
2016/08/24 12:38:37
This is only applicable to Windows (as of now), wi
o1ka
2016/08/24 12:43:14
I think it's fine to log it for high res only.
Henrik Grunell
2016/08/25 08:34:07
Let's go for that.
| |
| 480 base::TimeDelta elapsed = base::TimeTicks::Now() - start_time; | 488 base::TimeDelta elapsed = base::TimeTicks::Now() - start_time; |
| 481 render_callback_count_ = 0; | 489 UMA_HISTOGRAM_CUSTOM_COUNTS("Media.Audio.Render.GetSourceDataTime.WebRTC", |
| 482 UMA_HISTOGRAM_TIMES("WebRTC.AudioRenderTimes", elapsed); | 490 elapsed.InMicroseconds(), |
| 491 kRenderTimeHistogramMinMicroseconds, | |
| 492 kRenderTimeHistogramMaxMicroseconds, 50); | |
| 493 | |
| 494 if (elapsed > max_render_time_) | |
| 495 max_render_time_ = elapsed; | |
| 483 } | 496 } |
| 484 } | 497 } |
| 485 | 498 |
| 486 void WebRtcAudioRenderer::UpdateSourceVolume( | 499 void WebRtcAudioRenderer::UpdateSourceVolume( |
| 487 webrtc::AudioSourceInterface* source) { | 500 webrtc::AudioSourceInterface* source) { |
| 488 DCHECK(thread_checker_.CalledOnValidThread()); | 501 DCHECK(thread_checker_.CalledOnValidThread()); |
| 489 | 502 |
| 490 // Note: If there are no playing audio renderers, then the volume will be | 503 // Note: If there are no playing audio renderers, then the volume will be |
| 491 // set to 0.0. | 504 // set to 0.0. |
| 492 float volume = 0.0f; | 505 float volume = 0.0f; |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 648 base::Bind(&WebRtcAudioRenderer::SourceCallback, | 661 base::Bind(&WebRtcAudioRenderer::SourceCallback, |
| 649 base::Unretained(this)))); | 662 base::Unretained(this)))); |
| 650 } | 663 } |
| 651 sink_params_ = new_sink_params; | 664 sink_params_ = new_sink_params; |
| 652 } | 665 } |
| 653 | 666 |
| 654 sink_->Initialize(new_sink_params, this); | 667 sink_->Initialize(new_sink_params, this); |
| 655 } | 668 } |
| 656 | 669 |
| 657 } // namespace content | 670 } // namespace content |
| OLD | NEW |