Index: content/renderer/media/webrtc_audio_renderer.cc |
diff --git a/content/renderer/media/webrtc_audio_renderer.cc b/content/renderer/media/webrtc_audio_renderer.cc |
index 32c27bf8be65487b9e021bf5e6a3e95d8345ab66..f6801862af369539c8d9e7ccca595a1b27dfe1b2 100644 |
--- a/content/renderer/media/webrtc_audio_renderer.cc |
+++ b/content/renderer/media/webrtc_audio_renderer.cc |
@@ -54,17 +54,24 @@ class SharedAudioRenderer : public MediaStreamAudioRenderer { |
public: |
// Callback definition for a callback that is called when when Play(), Pause() |
// or SetVolume are called (whenever the internal |playing_state_| changes). |
- typedef base::Callback<void(const blink::WebMediaStream&, |
- WebRtcAudioRenderer::PlayingState*)> |
- OnPlayStateChanged; |
+ using OnPlayStateChanged = |
+ base::Callback<void(const blink::WebMediaStream&, |
+ WebRtcAudioRenderer::PlayingState*)>; |
+ |
+ // Signals that the PlayingState* is about to become invalid, see comment in |
+ // OnPlayStateRemoved. |
+ using OnPlayStateRemoved = |
+ base::OnceCallback<void(WebRtcAudioRenderer::PlayingState*)>; |
SharedAudioRenderer(const scoped_refptr<MediaStreamAudioRenderer>& delegate, |
const blink::WebMediaStream& media_stream, |
- const OnPlayStateChanged& on_play_state_changed) |
+ const OnPlayStateChanged& on_play_state_changed, |
+ OnPlayStateRemoved on_play_state_removed) |
: delegate_(delegate), |
media_stream_(media_stream), |
started_(false), |
- on_play_state_changed_(on_play_state_changed) { |
+ on_play_state_changed_(on_play_state_changed), |
+ on_play_state_removed_(std::move(on_play_state_removed)) { |
DCHECK(!on_play_state_changed_.is_null()); |
DCHECK(!media_stream_.isNull()); |
} |
@@ -74,6 +81,7 @@ class SharedAudioRenderer : public MediaStreamAudioRenderer { |
DCHECK(thread_checker_.CalledOnValidThread()); |
DVLOG(1) << __func__; |
Stop(); |
+ std::move(on_play_state_removed_).Run(&playing_state_); |
} |
void Start() override { |
@@ -148,6 +156,7 @@ class SharedAudioRenderer : public MediaStreamAudioRenderer { |
bool started_; |
WebRtcAudioRenderer::PlayingState playing_state_; |
OnPlayStateChanged on_play_state_changed_; |
+ OnPlayStateRemoved on_play_state_removed_; |
}; |
} // namespace |
@@ -220,9 +229,12 @@ bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) { |
scoped_refptr<MediaStreamAudioRenderer> |
WebRtcAudioRenderer::CreateSharedAudioRendererProxy( |
const blink::WebMediaStream& media_stream) { |
- content::SharedAudioRenderer::OnPlayStateChanged on_play_state_changed = |
+ SharedAudioRenderer::OnPlayStateChanged on_play_state_changed = |
base::Bind(&WebRtcAudioRenderer::OnPlayStateChanged, this); |
- return new SharedAudioRenderer(this, media_stream, on_play_state_changed); |
+ SharedAudioRenderer::OnPlayStateRemoved on_play_state_removed = |
+ base::BindOnce(&WebRtcAudioRenderer::OnPlayStateRemoved, this); |
+ return new SharedAudioRenderer(this, media_stream, on_play_state_changed, |
+ std::move(on_play_state_removed)); |
} |
bool WebRtcAudioRenderer::IsStarted() const { |
@@ -593,6 +605,27 @@ void WebRtcAudioRenderer::OnPlayStateChanged( |
} |
} |
+void WebRtcAudioRenderer::OnPlayStateRemoved(PlayingState* state) { |
+ // It is possible we associated |state| to a source for a track that is no |
+ // longer easily reachable. We iterate over |source_playing_states_| to |
+ // ensure there are no dangling pointers to |state| there. See |
+ // crbug.com/697256. |
+ // TODO(maxmorin): Clean up cleanup code in this and related classes so that |
+ // this hack isn't necessary. |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ for (auto it = source_playing_states_.begin(); |
+ it != source_playing_states_.end();) { |
+ PlayingStates& states = it->second; |
+ // We cannot use RemovePlayingState as it might invalidate |it|. |
+ states.erase(std::remove(states.begin(), states.end(), state), |
+ states.end()); |
+ if (states.empty()) |
+ it = source_playing_states_.erase(it); |
+ else |
+ ++it; |
+ } |
+} |
+ |
void WebRtcAudioRenderer::PrepareSink() { |
DCHECK(thread_checker_.CalledOnValidThread()); |
media::AudioParameters new_sink_params; |