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

Side by Side Diff: content/renderer/media/webrtc_audio_renderer.cc

Issue 2758453004: Remove dangling PlayingState pointers in WebRtcAudioRenderer. (Closed)
Patch Set: Created 3 years, 9 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
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 "content/renderer/media/webrtc_audio_renderer.h" 5 #include "content/renderer/media/webrtc_audio_renderer.h"
6 6
7 #include <algorithm>
7 #include <utility> 8 #include <utility>
8 9
9 #include "base/bind.h" 10 #include "base/bind.h"
10 #include "base/bind_helpers.h" 11 #include "base/bind_helpers.h"
11 #include "base/location.h" 12 #include "base/location.h"
12 #include "base/logging.h" 13 #include "base/logging.h"
13 #include "base/metrics/histogram_macros.h" 14 #include "base/metrics/histogram_macros.h"
14 #include "base/strings/string_util.h" 15 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h" 16 #include "base/strings/stringprintf.h"
16 #include "build/build_config.h" 17 #include "build/build_config.h"
(...skipping 29 matching lines...) Expand all
46 const int kRenderTimeHistogramMaxMicroseconds = 1 * 1000 * 1000; // 1 second 47 const int kRenderTimeHistogramMaxMicroseconds = 1 * 1000 * 1000; // 1 second
47 48
48 // This is a simple wrapper class that's handed out to users of a shared 49 // This is a simple wrapper class that's handed out to users of a shared
49 // WebRtcAudioRenderer instance. This class maintains the per-user 'playing' 50 // WebRtcAudioRenderer instance. This class maintains the per-user 'playing'
50 // and 'started' states to avoid problems related to incorrect usage which 51 // and 'started' states to avoid problems related to incorrect usage which
51 // might violate the implementation assumptions inside WebRtcAudioRenderer 52 // might violate the implementation assumptions inside WebRtcAudioRenderer
52 // (see the play reference count). 53 // (see the play reference count).
53 class SharedAudioRenderer : public MediaStreamAudioRenderer { 54 class SharedAudioRenderer : public MediaStreamAudioRenderer {
54 public: 55 public:
55 // Callback definition for a callback that is called when when Play(), Pause() 56 // Callback definition for a callback that is called when when Play(), Pause()
56 // or SetVolume are called (whenever the internal |playing_state_| changes). 57 // or SetVolume are called (whenever the internal |playing_state_| changes).
tommi (sloooow) - chröme 2017/03/17 12:44:08 add documentation for the new parameter
57 typedef base::Callback<void(const blink::WebMediaStream&, 58 typedef base::Callback<void(const blink::WebMediaStream&,
58 WebRtcAudioRenderer::PlayingState*)> 59 WebRtcAudioRenderer::PlayingState*,
60 bool playing_state_deleted)>
59 OnPlayStateChanged; 61 OnPlayStateChanged;
60 62
61 SharedAudioRenderer(const scoped_refptr<MediaStreamAudioRenderer>& delegate, 63 SharedAudioRenderer(const scoped_refptr<MediaStreamAudioRenderer>& delegate,
62 const blink::WebMediaStream& media_stream, 64 const blink::WebMediaStream& media_stream,
63 const OnPlayStateChanged& on_play_state_changed) 65 const OnPlayStateChanged& on_play_state_changed)
64 : delegate_(delegate), 66 : delegate_(delegate),
65 media_stream_(media_stream), 67 media_stream_(media_stream),
66 started_(false), 68 started_(false),
67 on_play_state_changed_(on_play_state_changed) { 69 on_play_state_changed_(on_play_state_changed) {
68 DCHECK(!on_play_state_changed_.is_null()); 70 DCHECK(!on_play_state_changed_.is_null());
69 DCHECK(!media_stream_.isNull()); 71 DCHECK(!media_stream_.isNull());
70 } 72 }
71 73
72 protected: 74 protected:
73 ~SharedAudioRenderer() override { 75 ~SharedAudioRenderer() override {
74 DCHECK(thread_checker_.CalledOnValidThread()); 76 DCHECK(thread_checker_.CalledOnValidThread());
75 DVLOG(1) << __func__; 77 DVLOG(1) << __func__;
76 Stop(); 78 Stop();
79 // Make extra sure no reference to the playing state is left.
80 on_play_state_changed_.Run(media_stream_, &playing_state_, true);
77 } 81 }
78 82
79 void Start() override { 83 void Start() override {
80 DCHECK(thread_checker_.CalledOnValidThread()); 84 DCHECK(thread_checker_.CalledOnValidThread());
81 if (started_) 85 if (started_)
82 return; 86 return;
83 started_ = true; 87 started_ = true;
84 delegate_->Start(); 88 delegate_->Start();
85 } 89 }
86 90
87 void Play() override { 91 void Play() override {
88 DCHECK(thread_checker_.CalledOnValidThread()); 92 DCHECK(thread_checker_.CalledOnValidThread());
89 DCHECK(started_); 93 DCHECK(started_);
90 if (playing_state_.playing()) 94 if (playing_state_.playing())
91 return; 95 return;
92 playing_state_.set_playing(true); 96 playing_state_.set_playing(true);
93 on_play_state_changed_.Run(media_stream_, &playing_state_); 97 on_play_state_changed_.Run(media_stream_, &playing_state_, false);
94 } 98 }
95 99
96 void Pause() override { 100 void Pause() override {
97 DCHECK(thread_checker_.CalledOnValidThread()); 101 DCHECK(thread_checker_.CalledOnValidThread());
98 DCHECK(started_); 102 DCHECK(started_);
99 if (!playing_state_.playing()) 103 if (!playing_state_.playing())
100 return; 104 return;
101 playing_state_.set_playing(false); 105 playing_state_.set_playing(false);
102 on_play_state_changed_.Run(media_stream_, &playing_state_); 106 on_play_state_changed_.Run(media_stream_, &playing_state_, false);
103 } 107 }
104 108
105 void Stop() override { 109 void Stop() override {
106 DCHECK(thread_checker_.CalledOnValidThread()); 110 DCHECK(thread_checker_.CalledOnValidThread());
107 if (!started_) 111 if (!started_)
108 return; 112 return;
109 Pause(); 113 Pause();
110 started_ = false; 114 started_ = false;
111 delegate_->Stop(); 115 delegate_->Stop();
112 } 116 }
113 117
114 void SetVolume(float volume) override { 118 void SetVolume(float volume) override {
115 DCHECK(thread_checker_.CalledOnValidThread()); 119 DCHECK(thread_checker_.CalledOnValidThread());
116 DCHECK(volume >= 0.0f && volume <= 1.0f); 120 DCHECK(volume >= 0.0f && volume <= 1.0f);
117 playing_state_.set_volume(volume); 121 playing_state_.set_volume(volume);
118 on_play_state_changed_.Run(media_stream_, &playing_state_); 122 on_play_state_changed_.Run(media_stream_, &playing_state_, false);
119 } 123 }
120 124
121 media::OutputDeviceInfo GetOutputDeviceInfo() override { 125 media::OutputDeviceInfo GetOutputDeviceInfo() override {
122 DCHECK(thread_checker_.CalledOnValidThread()); 126 DCHECK(thread_checker_.CalledOnValidThread());
123 return delegate_->GetOutputDeviceInfo(); 127 return delegate_->GetOutputDeviceInfo();
124 } 128 }
125 129
126 void SwitchOutputDevice( 130 void SwitchOutputDevice(
127 const std::string& device_id, 131 const std::string& device_id,
128 const url::Origin& security_origin, 132 const url::Origin& security_origin,
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 246
243 void WebRtcAudioRenderer::Play() { 247 void WebRtcAudioRenderer::Play() {
244 DVLOG(1) << "WebRtcAudioRenderer::Play()"; 248 DVLOG(1) << "WebRtcAudioRenderer::Play()";
245 DCHECK(thread_checker_.CalledOnValidThread()); 249 DCHECK(thread_checker_.CalledOnValidThread());
246 250
247 if (playing_state_.playing()) 251 if (playing_state_.playing())
248 return; 252 return;
249 253
250 playing_state_.set_playing(true); 254 playing_state_.set_playing(true);
251 255
252 OnPlayStateChanged(media_stream_, &playing_state_); 256 OnPlayStateChanged(media_stream_, &playing_state_, false);
253 } 257 }
254 258
255 void WebRtcAudioRenderer::EnterPlayState() { 259 void WebRtcAudioRenderer::EnterPlayState() {
256 DVLOG(1) << "WebRtcAudioRenderer::EnterPlayState()"; 260 DVLOG(1) << "WebRtcAudioRenderer::EnterPlayState()";
257 DCHECK(thread_checker_.CalledOnValidThread()); 261 DCHECK(thread_checker_.CalledOnValidThread());
258 DCHECK_GT(start_ref_count_, 0) << "Did you forget to call Start()?"; 262 DCHECK_GT(start_ref_count_, 0) << "Did you forget to call Start()?";
259 base::AutoLock auto_lock(lock_); 263 base::AutoLock auto_lock(lock_);
260 if (state_ == UNINITIALIZED) 264 if (state_ == UNINITIALIZED)
261 return; 265 return;
262 266
(...skipping 11 matching lines...) Expand all
274 } 278 }
275 279
276 void WebRtcAudioRenderer::Pause() { 280 void WebRtcAudioRenderer::Pause() {
277 DVLOG(1) << "WebRtcAudioRenderer::Pause()"; 281 DVLOG(1) << "WebRtcAudioRenderer::Pause()";
278 DCHECK(thread_checker_.CalledOnValidThread()); 282 DCHECK(thread_checker_.CalledOnValidThread());
279 if (!playing_state_.playing()) 283 if (!playing_state_.playing())
280 return; 284 return;
281 285
282 playing_state_.set_playing(false); 286 playing_state_.set_playing(false);
283 287
284 OnPlayStateChanged(media_stream_, &playing_state_); 288 OnPlayStateChanged(media_stream_, &playing_state_, false);
285 } 289 }
286 290
287 void WebRtcAudioRenderer::EnterPauseState() { 291 void WebRtcAudioRenderer::EnterPauseState() {
288 DVLOG(1) << "WebRtcAudioRenderer::EnterPauseState()"; 292 DVLOG(1) << "WebRtcAudioRenderer::EnterPauseState()";
289 DCHECK(thread_checker_.CalledOnValidThread()); 293 DCHECK(thread_checker_.CalledOnValidThread());
290 DCHECK_GT(start_ref_count_, 0) << "Did you forget to call Start()?"; 294 DCHECK_GT(start_ref_count_, 0) << "Did you forget to call Start()?";
291 base::AutoLock auto_lock(lock_); 295 base::AutoLock auto_lock(lock_);
292 if (state_ == UNINITIALIZED) 296 if (state_ == UNINITIALIZED)
293 return; 297 return;
294 298
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 // callback may currently be executing and trying to grab the lock while we're 337 // callback may currently be executing and trying to grab the lock while we're
334 // stopping the thread on which it runs. 338 // stopping the thread on which it runs.
335 sink_->Stop(); 339 sink_->Stop();
336 } 340 }
337 341
338 void WebRtcAudioRenderer::SetVolume(float volume) { 342 void WebRtcAudioRenderer::SetVolume(float volume) {
339 DCHECK(thread_checker_.CalledOnValidThread()); 343 DCHECK(thread_checker_.CalledOnValidThread());
340 DCHECK(volume >= 0.0f && volume <= 1.0f); 344 DCHECK(volume >= 0.0f && volume <= 1.0f);
341 345
342 playing_state_.set_volume(volume); 346 playing_state_.set_volume(volume);
343 OnPlayStateChanged(media_stream_, &playing_state_); 347 OnPlayStateChanged(media_stream_, &playing_state_, false);
344 } 348 }
345 349
346 media::OutputDeviceInfo WebRtcAudioRenderer::GetOutputDeviceInfo() { 350 media::OutputDeviceInfo WebRtcAudioRenderer::GetOutputDeviceInfo() {
347 DCHECK(thread_checker_.CalledOnValidThread()); 351 DCHECK(thread_checker_.CalledOnValidThread());
348 return sink_ ? sink_->GetOutputDeviceInfo() : media::OutputDeviceInfo(); 352 return sink_ ? sink_->GetOutputDeviceInfo() : media::OutputDeviceInfo();
349 } 353 }
350 354
351 base::TimeDelta WebRtcAudioRenderer::GetCurrentRenderTime() const { 355 base::TimeDelta WebRtcAudioRenderer::GetCurrentRenderTime() const {
352 DCHECK(thread_checker_.CalledOnValidThread()); 356 DCHECK(thread_checker_.CalledOnValidThread());
353 base::AutoLock auto_lock(lock_); 357 base::AutoLock auto_lock(lock_);
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
559 array.erase(state_it); 563 array.erase(state_it);
560 564
561 if (array.empty()) 565 if (array.empty())
562 source_playing_states_.erase(found); 566 source_playing_states_.erase(found);
563 567
564 return true; 568 return true;
565 } 569 }
566 570
567 void WebRtcAudioRenderer::OnPlayStateChanged( 571 void WebRtcAudioRenderer::OnPlayStateChanged(
568 const blink::WebMediaStream& media_stream, 572 const blink::WebMediaStream& media_stream,
569 PlayingState* state) { 573 PlayingState* state,
574 bool playing_state_deleted) {
570 DCHECK(thread_checker_.CalledOnValidThread()); 575 DCHECK(thread_checker_.CalledOnValidThread());
576 if (playing_state_deleted) {
577 // We must ensure that no references to playing_state remains.
o1ka 2017/03/17 12:03:30 Could you add explanation and reference to a bug?
Max Morin 2017/03/17 12:21:44 Done.
578 for (auto it = source_playing_states_.begin();
579 it != source_playing_states_.end();) {
580 PlayingStates& states = it->second;
581 states.erase(std::remove(states.begin(), states.end(), state),
582 states.end());
583 if (states.empty())
584 it = source_playing_states_.erase(it);
585 else
586 ++it;
587 }
588 return;
589 }
571 blink::WebVector<blink::WebMediaStreamTrack> web_tracks; 590 blink::WebVector<blink::WebMediaStreamTrack> web_tracks;
572 media_stream.audioTracks(web_tracks); 591 media_stream.audioTracks(web_tracks);
573 592
574 for (const blink::WebMediaStreamTrack& web_track : web_tracks) { 593 for (const blink::WebMediaStreamTrack& web_track : web_tracks) {
575 // WebRtcAudioRenderer can only render audio tracks received from a remote 594 // WebRtcAudioRenderer can only render audio tracks received from a remote
576 // peer. Since the actual MediaStream is mutable from JavaScript, we need 595 // peer. Since the actual MediaStream is mutable from JavaScript, we need
577 // to make sure |web_track| is actually a remote track. 596 // to make sure |web_track| is actually a remote track.
578 PeerConnectionRemoteAudioTrack* const remote_track = 597 PeerConnectionRemoteAudioTrack* const remote_track =
579 PeerConnectionRemoteAudioTrack::From( 598 PeerConnectionRemoteAudioTrack::From(
580 MediaStreamAudioTrack::From(web_track)); 599 MediaStreamAudioTrack::From(web_track));
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
658 sink_params_ = new_sink_params; 677 sink_params_ = new_sink_params;
659 } 678 }
660 679
661 // Specify the latency info to be passed to the browser side. 680 // Specify the latency info to be passed to the browser side.
662 new_sink_params.set_latency_tag(AudioDeviceFactory::GetSourceLatencyType( 681 new_sink_params.set_latency_tag(AudioDeviceFactory::GetSourceLatencyType(
663 AudioDeviceFactory::AudioDeviceFactory::kSourceWebRtc)); 682 AudioDeviceFactory::AudioDeviceFactory::kSourceWebRtc));
664 sink_->Initialize(new_sink_params, this); 683 sink_->Initialize(new_sink_params, this);
665 } 684 }
666 685
667 } // namespace content 686 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698