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 using OnPlayStateChanged = | 57 typedef base::Callback<void(const blink::WebMediaStream&, |
58 base::Callback<void(const blink::WebMediaStream&, | 58 WebRtcAudioRenderer::PlayingState*)> |
59 WebRtcAudioRenderer::PlayingState*)>; | 59 OnPlayStateChanged; |
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*)>; | |
65 | 60 |
66 SharedAudioRenderer(const scoped_refptr<MediaStreamAudioRenderer>& delegate, | 61 SharedAudioRenderer(const scoped_refptr<MediaStreamAudioRenderer>& delegate, |
67 const blink::WebMediaStream& media_stream, | 62 const blink::WebMediaStream& media_stream, |
68 const OnPlayStateChanged& on_play_state_changed, | 63 const OnPlayStateChanged& on_play_state_changed) |
69 OnPlayStateRemoved on_play_state_removed) | |
70 : delegate_(delegate), | 64 : delegate_(delegate), |
71 media_stream_(media_stream), | 65 media_stream_(media_stream), |
72 started_(false), | 66 started_(false), |
73 on_play_state_changed_(on_play_state_changed), | 67 on_play_state_changed_(on_play_state_changed) { |
74 on_play_state_removed_(std::move(on_play_state_removed)) { | |
75 DCHECK(!on_play_state_changed_.is_null()); | 68 DCHECK(!on_play_state_changed_.is_null()); |
76 DCHECK(!media_stream_.isNull()); | 69 DCHECK(!media_stream_.isNull()); |
77 } | 70 } |
78 | 71 |
79 protected: | 72 protected: |
80 ~SharedAudioRenderer() override { | 73 ~SharedAudioRenderer() override { |
81 DCHECK(thread_checker_.CalledOnValidThread()); | 74 DCHECK(thread_checker_.CalledOnValidThread()); |
82 DVLOG(1) << __func__; | 75 DVLOG(1) << __func__; |
83 Stop(); | 76 Stop(); |
84 std::move(on_play_state_removed_).Run(&playing_state_); | |
85 } | 77 } |
86 | 78 |
87 void Start() override { | 79 void Start() override { |
88 DCHECK(thread_checker_.CalledOnValidThread()); | 80 DCHECK(thread_checker_.CalledOnValidThread()); |
89 if (started_) | 81 if (started_) |
90 return; | 82 return; |
91 started_ = true; | 83 started_ = true; |
92 delegate_->Start(); | 84 delegate_->Start(); |
93 } | 85 } |
94 | 86 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 return delegate_->IsLocalRenderer(); | 141 return delegate_->IsLocalRenderer(); |
150 } | 142 } |
151 | 143 |
152 private: | 144 private: |
153 base::ThreadChecker thread_checker_; | 145 base::ThreadChecker thread_checker_; |
154 const scoped_refptr<MediaStreamAudioRenderer> delegate_; | 146 const scoped_refptr<MediaStreamAudioRenderer> delegate_; |
155 const blink::WebMediaStream media_stream_; | 147 const blink::WebMediaStream media_stream_; |
156 bool started_; | 148 bool started_; |
157 WebRtcAudioRenderer::PlayingState playing_state_; | 149 WebRtcAudioRenderer::PlayingState playing_state_; |
158 OnPlayStateChanged on_play_state_changed_; | 150 OnPlayStateChanged on_play_state_changed_; |
159 OnPlayStateRemoved on_play_state_removed_; | |
160 }; | 151 }; |
161 | 152 |
162 } // namespace | 153 } // namespace |
163 | 154 |
164 WebRtcAudioRenderer::WebRtcAudioRenderer( | 155 WebRtcAudioRenderer::WebRtcAudioRenderer( |
165 const scoped_refptr<base::SingleThreadTaskRunner>& signaling_thread, | 156 const scoped_refptr<base::SingleThreadTaskRunner>& signaling_thread, |
166 const blink::WebMediaStream& media_stream, | 157 const blink::WebMediaStream& media_stream, |
167 int source_render_frame_id, | 158 int source_render_frame_id, |
168 int session_id, | 159 int session_id, |
169 const std::string& device_id, | 160 const std::string& device_id, |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 } | 213 } |
223 sink_->Start(); | 214 sink_->Start(); |
224 sink_->Play(); // Not all the sinks play on start. | 215 sink_->Play(); // Not all the sinks play on start. |
225 | 216 |
226 return true; | 217 return true; |
227 } | 218 } |
228 | 219 |
229 scoped_refptr<MediaStreamAudioRenderer> | 220 scoped_refptr<MediaStreamAudioRenderer> |
230 WebRtcAudioRenderer::CreateSharedAudioRendererProxy( | 221 WebRtcAudioRenderer::CreateSharedAudioRendererProxy( |
231 const blink::WebMediaStream& media_stream) { | 222 const blink::WebMediaStream& media_stream) { |
232 SharedAudioRenderer::OnPlayStateChanged on_play_state_changed = | 223 content::SharedAudioRenderer::OnPlayStateChanged on_play_state_changed = |
233 base::Bind(&WebRtcAudioRenderer::OnPlayStateChanged, this); | 224 base::Bind(&WebRtcAudioRenderer::OnPlayStateChanged, this); |
234 SharedAudioRenderer::OnPlayStateRemoved on_play_state_removed = | 225 return new SharedAudioRenderer(this, media_stream, on_play_state_changed); |
235 base::BindOnce(&WebRtcAudioRenderer::OnPlayStateRemoved, this); | |
236 return new SharedAudioRenderer(this, media_stream, on_play_state_changed, | |
237 std::move(on_play_state_removed)); | |
238 } | 226 } |
239 | 227 |
240 bool WebRtcAudioRenderer::IsStarted() const { | 228 bool WebRtcAudioRenderer::IsStarted() const { |
241 DCHECK(thread_checker_.CalledOnValidThread()); | 229 DCHECK(thread_checker_.CalledOnValidThread()); |
242 return start_ref_count_ != 0; | 230 return start_ref_count_ != 0; |
243 } | 231 } |
244 | 232 |
245 bool WebRtcAudioRenderer::CurrentThreadIsRenderingThread() { | 233 bool WebRtcAudioRenderer::CurrentThreadIsRenderingThread() { |
246 return sink_->CurrentThreadIsRenderingThread(); | 234 return sink_->CurrentThreadIsRenderingThread(); |
247 } | 235 } |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
598 if (!state->playing()) { | 586 if (!state->playing()) { |
599 if (RemovePlayingState(source, state)) | 587 if (RemovePlayingState(source, state)) |
600 EnterPauseState(); | 588 EnterPauseState(); |
601 } else if (AddPlayingState(source, state)) { | 589 } else if (AddPlayingState(source, state)) { |
602 EnterPlayState(); | 590 EnterPlayState(); |
603 } | 591 } |
604 UpdateSourceVolume(source); | 592 UpdateSourceVolume(source); |
605 } | 593 } |
606 } | 594 } |
607 | 595 |
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 | |
629 void WebRtcAudioRenderer::PrepareSink() { | 596 void WebRtcAudioRenderer::PrepareSink() { |
630 DCHECK(thread_checker_.CalledOnValidThread()); | 597 DCHECK(thread_checker_.CalledOnValidThread()); |
631 media::AudioParameters new_sink_params; | 598 media::AudioParameters new_sink_params; |
632 { | 599 { |
633 base::AutoLock lock(lock_); | 600 base::AutoLock lock(lock_); |
634 new_sink_params = sink_params_; | 601 new_sink_params = sink_params_; |
635 } | 602 } |
636 | 603 |
637 const media::OutputDeviceInfo& device_info = sink_->GetOutputDeviceInfo(); | 604 const media::OutputDeviceInfo& device_info = sink_->GetOutputDeviceInfo(); |
638 DCHECK_EQ(device_info.device_status(), media::OUTPUT_DEVICE_STATUS_OK); | 605 DCHECK_EQ(device_info.device_status(), media::OUTPUT_DEVICE_STATUS_OK); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
691 sink_params_ = new_sink_params; | 658 sink_params_ = new_sink_params; |
692 } | 659 } |
693 | 660 |
694 // Specify the latency info to be passed to the browser side. | 661 // Specify the latency info to be passed to the browser side. |
695 new_sink_params.set_latency_tag(AudioDeviceFactory::GetSourceLatencyType( | 662 new_sink_params.set_latency_tag(AudioDeviceFactory::GetSourceLatencyType( |
696 AudioDeviceFactory::AudioDeviceFactory::kSourceWebRtc)); | 663 AudioDeviceFactory::AudioDeviceFactory::kSourceWebRtc)); |
697 sink_->Initialize(new_sink_params, this); | 664 sink_->Initialize(new_sink_params, this); |
698 } | 665 } |
699 | 666 |
700 } // namespace content | 667 } // namespace content |
OLD | NEW |