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 | |
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 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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) { | 174 source_render_called_(false) { |
176 WebRtcLogMessage(base::StringPrintf( | 175 WebRtcLogMessage(base::StringPrintf( |
177 "WAR::WAR. source_render_frame_id=%d, session_id=%d, effects=%i", | 176 "WAR::WAR. source_render_frame_id=%d, session_id=%d, effects=%i", |
178 source_render_frame_id, session_id, sink_params_.effects())); | 177 source_render_frame_id, session_id, sink_params_.effects())); |
179 } | 178 } |
180 | 179 |
181 WebRtcAudioRenderer::~WebRtcAudioRenderer() { | 180 WebRtcAudioRenderer::~WebRtcAudioRenderer() { |
182 DCHECK(thread_checker_.CalledOnValidThread()); | 181 DCHECK(thread_checker_.CalledOnValidThread()); |
183 DCHECK_EQ(state_, UNINITIALIZED); | 182 DCHECK_EQ(state_, UNINITIALIZED); |
184 } | 183 } |
185 | 184 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
244 } | 243 } |
245 | 244 |
246 void WebRtcAudioRenderer::Play() { | 245 void WebRtcAudioRenderer::Play() { |
247 DVLOG(1) << "WebRtcAudioRenderer::Play()"; | 246 DVLOG(1) << "WebRtcAudioRenderer::Play()"; |
248 DCHECK(thread_checker_.CalledOnValidThread()); | 247 DCHECK(thread_checker_.CalledOnValidThread()); |
249 | 248 |
250 if (playing_state_.playing()) | 249 if (playing_state_.playing()) |
251 return; | 250 return; |
252 | 251 |
253 playing_state_.set_playing(true); | 252 playing_state_.set_playing(true); |
254 render_callback_count_ = 0; | 253 source_render_called_ = false; |
255 | 254 |
256 OnPlayStateChanged(media_stream_, &playing_state_); | 255 OnPlayStateChanged(media_stream_, &playing_state_); |
257 } | 256 } |
258 | 257 |
259 void WebRtcAudioRenderer::EnterPlayState() { | 258 void WebRtcAudioRenderer::EnterPlayState() { |
260 DVLOG(1) << "WebRtcAudioRenderer::EnterPlayState()"; | 259 DVLOG(1) << "WebRtcAudioRenderer::EnterPlayState()"; |
261 DCHECK(thread_checker_.CalledOnValidThread()); | 260 DCHECK(thread_checker_.CalledOnValidThread()); |
262 DCHECK_GT(start_ref_count_, 0) << "Did you forget to call Start()?"; | 261 DCHECK_GT(start_ref_count_, 0) << "Did you forget to call Start()?"; |
263 base::AutoLock auto_lock(lock_); | 262 base::AutoLock auto_lock(lock_); |
264 if (state_ == UNINITIALIZED) | 263 if (state_ == UNINITIALIZED) |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
298 | 297 |
299 DCHECK_EQ(state_, PLAYING); | 298 DCHECK_EQ(state_, PLAYING); |
300 DCHECK_GT(play_ref_count_, 0); | 299 DCHECK_GT(play_ref_count_, 0); |
301 if (!--play_ref_count_) | 300 if (!--play_ref_count_) |
302 state_ = PAUSED; | 301 state_ = PAUSED; |
303 } | 302 } |
304 | 303 |
305 void WebRtcAudioRenderer::Stop() { | 304 void WebRtcAudioRenderer::Stop() { |
306 DVLOG(1) << "WebRtcAudioRenderer::Stop()"; | 305 DVLOG(1) << "WebRtcAudioRenderer::Stop()"; |
307 DCHECK(thread_checker_.CalledOnValidThread()); | 306 DCHECK(thread_checker_.CalledOnValidThread()); |
307 if (source_render_called_) { | |
o1ka
2016/08/24 11:52:42
No need for the flag: you can just check (!max_ren
Henrik Grunell
2016/08/24 12:16:09
Of course. We can safely assume that the render ca
| |
308 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
309 "Media.Audio.Render.GetSourceDataTimeMax.WebRTC", | |
310 max_render_time_.InMicroseconds(), kRenderTimeHistogramMinMicroseconds, | |
311 kRenderTimeHistogramMaxMicroseconds, 50); | |
312 max_render_time_ = base::TimeDelta(); | |
313 } | |
314 | |
308 { | 315 { |
309 base::AutoLock auto_lock(lock_); | 316 base::AutoLock auto_lock(lock_); |
310 if (state_ == UNINITIALIZED) | 317 if (state_ == UNINITIALIZED) |
311 return; | 318 return; |
312 | 319 |
313 if (--start_ref_count_) | 320 if (--start_ref_count_) |
314 return; | 321 return; |
315 | 322 |
316 DVLOG(1) << "Calling RemoveAudioRenderer and Stop()."; | 323 DVLOG(1) << "Calling RemoveAudioRenderer and Stop()."; |
317 | 324 |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
469 // otherwise the data will be buffered up inside |source_|. | 476 // otherwise the data will be buffered up inside |source_|. |
470 source_->RenderData(audio_bus, sink_params_.sample_rate(), | 477 source_->RenderData(audio_bus, sink_params_.sample_rate(), |
471 output_delay_milliseconds, | 478 output_delay_milliseconds, |
472 ¤t_time_); | 479 ¤t_time_); |
473 | 480 |
474 // Avoid filling up the audio bus if we are not playing; instead | 481 // 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. | 482 // return here and ensure that the returned value in Render() is 0. |
476 if (state_ != PLAYING) | 483 if (state_ != PLAYING) |
477 audio_bus->Zero(); | 484 audio_bus->Zero(); |
478 | 485 |
479 if (++render_callback_count_ == kNumCallbacksBetweenRenderTimeHistograms) { | 486 // Measure the elapsed time for this function and log it. |
480 base::TimeDelta elapsed = base::TimeTicks::Now() - start_time; | 487 base::TimeDelta elapsed = base::TimeTicks::Now() - start_time; |
481 render_callback_count_ = 0; | 488 UMA_HISTOGRAM_CUSTOM_COUNTS("Media.Audio.Render.GetSourceDataTime.WebRTC", |
482 UMA_HISTOGRAM_TIMES("WebRTC.AudioRenderTimes", elapsed); | 489 elapsed.InMicroseconds(), |
483 } | 490 kRenderTimeHistogramMinMicroseconds, |
491 kRenderTimeHistogramMaxMicroseconds, 50); | |
492 | |
493 // Store max render call time. | |
494 if (elapsed > max_render_time_) | |
495 max_render_time_ = elapsed; | |
496 source_render_called_ = true; | |
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; |
493 | 506 |
(...skipping 154 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 |