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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 | 47 |
48 // 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 |
49 // WebRtcAudioRenderer instance. This class maintains the per-user 'playing' | 49 // WebRtcAudioRenderer instance. This class maintains the per-user 'playing' |
50 // and 'started' states to avoid problems related to incorrect usage which | 50 // and 'started' states to avoid problems related to incorrect usage which |
51 // might violate the implementation assumptions inside WebRtcAudioRenderer | 51 // might violate the implementation assumptions inside WebRtcAudioRenderer |
52 // (see the play reference count). | 52 // (see the play reference count). |
53 class SharedAudioRenderer : public MediaStreamAudioRenderer { | 53 class SharedAudioRenderer : public MediaStreamAudioRenderer { |
54 public: | 54 public: |
55 // 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() |
56 // or SetVolume are called (whenever the internal |playing_state_| changes). | 56 // or SetVolume are called (whenever the internal |playing_state_| changes). |
57 typedef base::Callback<void(const blink::WebMediaStream&, | 57 using OnPlayStateChanged = |
58 WebRtcAudioRenderer::PlayingState*)> | 58 base::Callback<void(const blink::WebMediaStream&, |
59 OnPlayStateChanged; | 59 WebRtcAudioRenderer::PlayingState*)>; |
| 60 |
| 61 // Signals that the PlayingState* is about to become invalid, see comment in |
| 62 // OnPlayStateRemoved. |
| 63 using OnPlayStateRemoved = |
| 64 base::OnceCallback<void(WebRtcAudioRenderer::PlayingState*)>; |
60 | 65 |
61 SharedAudioRenderer(const scoped_refptr<MediaStreamAudioRenderer>& delegate, | 66 SharedAudioRenderer(const scoped_refptr<MediaStreamAudioRenderer>& delegate, |
62 const blink::WebMediaStream& media_stream, | 67 const blink::WebMediaStream& media_stream, |
63 const OnPlayStateChanged& on_play_state_changed) | 68 const OnPlayStateChanged& on_play_state_changed, |
| 69 OnPlayStateRemoved on_play_state_removed) |
64 : delegate_(delegate), | 70 : delegate_(delegate), |
65 media_stream_(media_stream), | 71 media_stream_(media_stream), |
66 started_(false), | 72 started_(false), |
67 on_play_state_changed_(on_play_state_changed) { | 73 on_play_state_changed_(on_play_state_changed), |
| 74 on_play_state_removed_(std::move(on_play_state_removed)) { |
68 DCHECK(!on_play_state_changed_.is_null()); | 75 DCHECK(!on_play_state_changed_.is_null()); |
69 DCHECK(!media_stream_.isNull()); | 76 DCHECK(!media_stream_.isNull()); |
70 } | 77 } |
71 | 78 |
72 protected: | 79 protected: |
73 ~SharedAudioRenderer() override { | 80 ~SharedAudioRenderer() override { |
74 DCHECK(thread_checker_.CalledOnValidThread()); | 81 DCHECK(thread_checker_.CalledOnValidThread()); |
75 DVLOG(1) << __func__; | 82 DVLOG(1) << __func__; |
76 Stop(); | 83 Stop(); |
| 84 std::move(on_play_state_removed_).Run(&playing_state_); |
77 } | 85 } |
78 | 86 |
79 void Start() override { | 87 void Start() override { |
80 DCHECK(thread_checker_.CalledOnValidThread()); | 88 DCHECK(thread_checker_.CalledOnValidThread()); |
81 if (started_) | 89 if (started_) |
82 return; | 90 return; |
83 started_ = true; | 91 started_ = true; |
84 delegate_->Start(); | 92 delegate_->Start(); |
85 } | 93 } |
86 | 94 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 return delegate_->IsLocalRenderer(); | 149 return delegate_->IsLocalRenderer(); |
142 } | 150 } |
143 | 151 |
144 private: | 152 private: |
145 base::ThreadChecker thread_checker_; | 153 base::ThreadChecker thread_checker_; |
146 const scoped_refptr<MediaStreamAudioRenderer> delegate_; | 154 const scoped_refptr<MediaStreamAudioRenderer> delegate_; |
147 const blink::WebMediaStream media_stream_; | 155 const blink::WebMediaStream media_stream_; |
148 bool started_; | 156 bool started_; |
149 WebRtcAudioRenderer::PlayingState playing_state_; | 157 WebRtcAudioRenderer::PlayingState playing_state_; |
150 OnPlayStateChanged on_play_state_changed_; | 158 OnPlayStateChanged on_play_state_changed_; |
| 159 OnPlayStateRemoved on_play_state_removed_; |
151 }; | 160 }; |
152 | 161 |
153 } // namespace | 162 } // namespace |
154 | 163 |
155 WebRtcAudioRenderer::WebRtcAudioRenderer( | 164 WebRtcAudioRenderer::WebRtcAudioRenderer( |
156 const scoped_refptr<base::SingleThreadTaskRunner>& signaling_thread, | 165 const scoped_refptr<base::SingleThreadTaskRunner>& signaling_thread, |
157 const blink::WebMediaStream& media_stream, | 166 const blink::WebMediaStream& media_stream, |
158 int source_render_frame_id, | 167 int source_render_frame_id, |
159 int session_id, | 168 int session_id, |
160 const std::string& device_id, | 169 const std::string& device_id, |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 } | 222 } |
214 sink_->Start(); | 223 sink_->Start(); |
215 sink_->Play(); // Not all the sinks play on start. | 224 sink_->Play(); // Not all the sinks play on start. |
216 | 225 |
217 return true; | 226 return true; |
218 } | 227 } |
219 | 228 |
220 scoped_refptr<MediaStreamAudioRenderer> | 229 scoped_refptr<MediaStreamAudioRenderer> |
221 WebRtcAudioRenderer::CreateSharedAudioRendererProxy( | 230 WebRtcAudioRenderer::CreateSharedAudioRendererProxy( |
222 const blink::WebMediaStream& media_stream) { | 231 const blink::WebMediaStream& media_stream) { |
223 content::SharedAudioRenderer::OnPlayStateChanged on_play_state_changed = | 232 SharedAudioRenderer::OnPlayStateChanged on_play_state_changed = |
224 base::Bind(&WebRtcAudioRenderer::OnPlayStateChanged, this); | 233 base::Bind(&WebRtcAudioRenderer::OnPlayStateChanged, this); |
225 return new SharedAudioRenderer(this, media_stream, on_play_state_changed); | 234 SharedAudioRenderer::OnPlayStateRemoved on_play_state_removed = |
| 235 base::BindOnce(&WebRtcAudioRenderer::OnPlayStateRemoved, this); |
| 236 return new SharedAudioRenderer(this, media_stream, on_play_state_changed, |
| 237 std::move(on_play_state_removed)); |
226 } | 238 } |
227 | 239 |
228 bool WebRtcAudioRenderer::IsStarted() const { | 240 bool WebRtcAudioRenderer::IsStarted() const { |
229 DCHECK(thread_checker_.CalledOnValidThread()); | 241 DCHECK(thread_checker_.CalledOnValidThread()); |
230 return start_ref_count_ != 0; | 242 return start_ref_count_ != 0; |
231 } | 243 } |
232 | 244 |
233 bool WebRtcAudioRenderer::CurrentThreadIsRenderingThread() { | 245 bool WebRtcAudioRenderer::CurrentThreadIsRenderingThread() { |
234 return sink_->CurrentThreadIsRenderingThread(); | 246 return sink_->CurrentThreadIsRenderingThread(); |
235 } | 247 } |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
586 if (!state->playing()) { | 598 if (!state->playing()) { |
587 if (RemovePlayingState(source, state)) | 599 if (RemovePlayingState(source, state)) |
588 EnterPauseState(); | 600 EnterPauseState(); |
589 } else if (AddPlayingState(source, state)) { | 601 } else if (AddPlayingState(source, state)) { |
590 EnterPlayState(); | 602 EnterPlayState(); |
591 } | 603 } |
592 UpdateSourceVolume(source); | 604 UpdateSourceVolume(source); |
593 } | 605 } |
594 } | 606 } |
595 | 607 |
| 608 void WebRtcAudioRenderer::OnPlayStateRemoved(PlayingState* state) { |
| 609 // It is possible we associated |state| to a source for a track that is no |
| 610 // longer easily reachable. We iterate over |source_playing_states_| to |
| 611 // ensure there are no dangling pointers to |state| there. See |
| 612 // crbug.com/697256. |
| 613 // TODO(maxmorin): Clean up cleanup code in this and related classes so that |
| 614 // this hack isn't necessary. |
| 615 DCHECK(thread_checker_.CalledOnValidThread()); |
| 616 for (auto it = source_playing_states_.begin(); |
| 617 it != source_playing_states_.end();) { |
| 618 PlayingStates& states = it->second; |
| 619 // We cannot use RemovePlayingState as it might invalidate |it|. |
| 620 states.erase(std::remove(states.begin(), states.end(), state), |
| 621 states.end()); |
| 622 if (states.empty()) |
| 623 it = source_playing_states_.erase(it); |
| 624 else |
| 625 ++it; |
| 626 } |
| 627 } |
| 628 |
596 void WebRtcAudioRenderer::PrepareSink() { | 629 void WebRtcAudioRenderer::PrepareSink() { |
597 DCHECK(thread_checker_.CalledOnValidThread()); | 630 DCHECK(thread_checker_.CalledOnValidThread()); |
598 media::AudioParameters new_sink_params; | 631 media::AudioParameters new_sink_params; |
599 { | 632 { |
600 base::AutoLock lock(lock_); | 633 base::AutoLock lock(lock_); |
601 new_sink_params = sink_params_; | 634 new_sink_params = sink_params_; |
602 } | 635 } |
603 | 636 |
604 const media::OutputDeviceInfo& device_info = sink_->GetOutputDeviceInfo(); | 637 const media::OutputDeviceInfo& device_info = sink_->GetOutputDeviceInfo(); |
605 DCHECK_EQ(device_info.device_status(), media::OUTPUT_DEVICE_STATUS_OK); | 638 DCHECK_EQ(device_info.device_status(), media::OUTPUT_DEVICE_STATUS_OK); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
658 sink_params_ = new_sink_params; | 691 sink_params_ = new_sink_params; |
659 } | 692 } |
660 | 693 |
661 // Specify the latency info to be passed to the browser side. | 694 // Specify the latency info to be passed to the browser side. |
662 new_sink_params.set_latency_tag(AudioDeviceFactory::GetSourceLatencyType( | 695 new_sink_params.set_latency_tag(AudioDeviceFactory::GetSourceLatencyType( |
663 AudioDeviceFactory::AudioDeviceFactory::kSourceWebRtc)); | 696 AudioDeviceFactory::AudioDeviceFactory::kSourceWebRtc)); |
664 sink_->Initialize(new_sink_params, this); | 697 sink_->Initialize(new_sink_params, this); |
665 } | 698 } |
666 | 699 |
667 } // namespace content | 700 } // namespace content |
OLD | NEW |