OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/remote_media_stream_impl.h" | 5 #include "content/renderer/media/remote_media_stream_impl.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <string> | 8 #include <string> |
9 #include <utility> | 9 #include <utility> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "base/bind.h" | 12 #include "base/bind.h" |
13 #include "base/location.h" | 13 #include "base/location.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "base/macros.h" | 15 #include "base/macros.h" |
16 #include "base/strings/utf_string_conversions.h" | |
17 #include "base/threading/thread_task_runner_handle.h" | 16 #include "base/threading/thread_task_runner_handle.h" |
18 #include "content/renderer/media/media_stream.h" | 17 #include "content/renderer/media/media_stream.h" |
19 #include "content/renderer/media/media_stream_track.h" | 18 #include "content/renderer/media/media_stream_track.h" |
20 #include "content/renderer/media/media_stream_video_track.h" | 19 #include "content/renderer/media/media_stream_video_track.h" |
| 20 #include "content/renderer/media/remote_media_stream_track_adapter.h" |
21 #include "content/renderer/media/webrtc/media_stream_remote_video_source.h" | 21 #include "content/renderer/media/webrtc/media_stream_remote_video_source.h" |
22 #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h" | |
23 #include "content/renderer/media/webrtc/peer_connection_remote_audio_source.h" | |
24 #include "content/renderer/media/webrtc/track_observer.h" | |
25 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h" | |
26 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" | 22 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" |
27 #include "third_party/WebKit/public/platform/WebString.h" | 23 #include "third_party/WebKit/public/platform/WebString.h" |
28 | 24 |
29 namespace content { | 25 namespace content { |
30 namespace { | 26 namespace { |
31 | 27 |
32 template <typename WebRtcTrackVector, typename AdapterType> | 28 template <typename WebRtcTrackVector, typename AdapterType> |
33 void CreateAdaptersForTracks( | 29 void CreateAdaptersForTracks( |
34 const WebRtcTrackVector& tracks, | 30 const WebRtcTrackVector& tracks, |
35 std::vector<scoped_refptr<AdapterType>>* observers, | 31 std::vector<scoped_refptr<AdapterType>>* observers, |
36 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread) { | 32 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread) { |
37 for (auto& track : tracks) | 33 for (auto& track : tracks) |
38 observers->push_back(new AdapterType(main_thread, track)); | 34 observers->push_back(new AdapterType(main_thread, track)); |
39 } | 35 } |
40 | 36 |
41 template<typename VectorType> | 37 template<typename VectorType> |
42 bool IsTrackInVector(const VectorType& v, const std::string& id) { | 38 bool IsTrackInVector(const VectorType& v, const std::string& id) { |
43 for (const auto& t : v) { | 39 for (const auto& t : v) { |
44 if (t->id() == id) | 40 if (t->id() == id) |
45 return true; | 41 return true; |
46 } | 42 } |
47 return false; | 43 return false; |
48 } | 44 } |
49 } // namespace | 45 } // namespace |
50 | 46 |
51 // Base class used for mapping between webrtc and blink MediaStream tracks. | |
52 // An instance of a RemoteMediaStreamTrackAdapter is stored in | |
53 // RemoteMediaStreamImpl per remote audio and video track. | |
54 template<typename WebRtcMediaStreamTrackType> | |
55 class RemoteMediaStreamTrackAdapter | |
56 : public base::RefCountedThreadSafe< | |
57 RemoteMediaStreamTrackAdapter<WebRtcMediaStreamTrackType>> { | |
58 public: | |
59 RemoteMediaStreamTrackAdapter( | |
60 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, | |
61 WebRtcMediaStreamTrackType* webrtc_track) | |
62 : main_thread_(main_thread), webrtc_track_(webrtc_track), | |
63 id_(webrtc_track->id()) { | |
64 } | |
65 | |
66 const scoped_refptr<WebRtcMediaStreamTrackType>& observed_track() { | |
67 return webrtc_track_; | |
68 } | |
69 | |
70 blink::WebMediaStreamTrack* webkit_track() { | |
71 DCHECK(main_thread_->BelongsToCurrentThread()); | |
72 DCHECK(!webkit_track_.IsNull()); | |
73 return &webkit_track_; | |
74 } | |
75 | |
76 const std::string& id() const { return id_; } | |
77 | |
78 bool initialized() const { | |
79 DCHECK(main_thread_->BelongsToCurrentThread()); | |
80 return !webkit_track_.IsNull(); | |
81 } | |
82 | |
83 void Initialize() { | |
84 DCHECK(main_thread_->BelongsToCurrentThread()); | |
85 DCHECK(!initialized()); | |
86 webkit_initialize_.Run(); | |
87 webkit_initialize_.Reset(); | |
88 DCHECK(initialized()); | |
89 } | |
90 | |
91 protected: | |
92 friend class base::RefCountedThreadSafe< | |
93 RemoteMediaStreamTrackAdapter<WebRtcMediaStreamTrackType>>; | |
94 | |
95 virtual ~RemoteMediaStreamTrackAdapter() { | |
96 DCHECK(main_thread_->BelongsToCurrentThread()); | |
97 } | |
98 | |
99 void InitializeWebkitTrack(blink::WebMediaStreamSource::Type type) { | |
100 DCHECK(main_thread_->BelongsToCurrentThread()); | |
101 DCHECK(webkit_track_.IsNull()); | |
102 | |
103 blink::WebString webkit_track_id(blink::WebString::FromUTF8(id_)); | |
104 blink::WebMediaStreamSource webkit_source; | |
105 webkit_source.Initialize(webkit_track_id, type, webkit_track_id, | |
106 true /* remote */); | |
107 webkit_track_.Initialize(webkit_track_id, webkit_source); | |
108 DCHECK(!webkit_track_.IsNull()); | |
109 } | |
110 | |
111 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_; | |
112 // This callback will be run when Initialize() is called and then freed. | |
113 // The callback is used by derived classes to bind objects that need to be | |
114 // instantiated and initialized on the signaling thread but then moved to | |
115 // and used on the main thread when initializing the webkit object(s). | |
116 base::Callback<void()> webkit_initialize_; | |
117 | |
118 private: | |
119 const scoped_refptr<WebRtcMediaStreamTrackType> webrtc_track_; | |
120 blink::WebMediaStreamTrack webkit_track_; | |
121 // const copy of the webrtc track id that allows us to check it from both the | |
122 // main and signaling threads without incurring a synchronous thread hop. | |
123 const std::string id_; | |
124 | |
125 DISALLOW_COPY_AND_ASSIGN(RemoteMediaStreamTrackAdapter); | |
126 }; | |
127 | |
128 class RemoteVideoTrackAdapter | |
129 : public RemoteMediaStreamTrackAdapter<webrtc::VideoTrackInterface> { | |
130 public: | |
131 // Called on the signaling thread | |
132 RemoteVideoTrackAdapter( | |
133 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, | |
134 webrtc::VideoTrackInterface* webrtc_track) | |
135 : RemoteMediaStreamTrackAdapter(main_thread, webrtc_track) { | |
136 std::unique_ptr<TrackObserver> observer( | |
137 new TrackObserver(main_thread, observed_track().get())); | |
138 // Here, we use base::Unretained() to avoid a circular reference. | |
139 webkit_initialize_ = base::Bind( | |
140 &RemoteVideoTrackAdapter::InitializeWebkitVideoTrack, | |
141 base::Unretained(this), base::Passed(&observer), | |
142 observed_track()->enabled()); | |
143 } | |
144 | |
145 protected: | |
146 ~RemoteVideoTrackAdapter() override { | |
147 DCHECK(main_thread_->BelongsToCurrentThread()); | |
148 if (initialized()) { | |
149 static_cast<MediaStreamRemoteVideoSource*>( | |
150 webkit_track()->Source().GetExtraData()) | |
151 ->OnSourceTerminated(); | |
152 } | |
153 } | |
154 | |
155 private: | |
156 void InitializeWebkitVideoTrack(std::unique_ptr<TrackObserver> observer, | |
157 bool enabled) { | |
158 DCHECK(main_thread_->BelongsToCurrentThread()); | |
159 std::unique_ptr<MediaStreamRemoteVideoSource> video_source( | |
160 new MediaStreamRemoteVideoSource(std::move(observer))); | |
161 InitializeWebkitTrack(blink::WebMediaStreamSource::kTypeVideo); | |
162 webkit_track()->Source().SetExtraData(video_source.get()); | |
163 MediaStreamVideoTrack* media_stream_track = new MediaStreamVideoTrack( | |
164 video_source.release(), MediaStreamVideoSource::ConstraintsCallback(), | |
165 enabled); | |
166 webkit_track()->SetTrackData(media_stream_track); | |
167 } | |
168 }; | |
169 | |
170 // RemoteAudioTrackAdapter is responsible for listening on state | |
171 // change notifications on a remote webrtc audio MediaStreamTracks and notify | |
172 // WebKit. | |
173 class RemoteAudioTrackAdapter | |
174 : public RemoteMediaStreamTrackAdapter<webrtc::AudioTrackInterface>, | |
175 public webrtc::ObserverInterface { | |
176 public: | |
177 RemoteAudioTrackAdapter( | |
178 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, | |
179 webrtc::AudioTrackInterface* webrtc_track); | |
180 | |
181 void Unregister(); | |
182 | |
183 protected: | |
184 ~RemoteAudioTrackAdapter() override; | |
185 | |
186 private: | |
187 void InitializeWebkitAudioTrack(); | |
188 | |
189 // webrtc::ObserverInterface implementation. | |
190 void OnChanged() override; | |
191 | |
192 void OnChangedOnMainThread( | |
193 webrtc::MediaStreamTrackInterface::TrackState state); | |
194 | |
195 #if DCHECK_IS_ON() | |
196 bool unregistered_; | |
197 #endif | |
198 | |
199 webrtc::MediaStreamTrackInterface::TrackState state_; | |
200 | |
201 DISALLOW_COPY_AND_ASSIGN(RemoteAudioTrackAdapter); | |
202 }; | |
203 | |
204 // Called on the signaling thread. | |
205 RemoteAudioTrackAdapter::RemoteAudioTrackAdapter( | |
206 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, | |
207 webrtc::AudioTrackInterface* webrtc_track) | |
208 : RemoteMediaStreamTrackAdapter(main_thread, webrtc_track), | |
209 #if DCHECK_IS_ON() | |
210 unregistered_(false), | |
211 #endif | |
212 state_(observed_track()->state()) { | |
213 // TODO(tommi): Use TrackObserver instead. | |
214 observed_track()->RegisterObserver(this); | |
215 // Here, we use base::Unretained() to avoid a circular reference. | |
216 webkit_initialize_ = | |
217 base::Bind(&RemoteAudioTrackAdapter::InitializeWebkitAudioTrack, | |
218 base::Unretained(this)); | |
219 } | |
220 | |
221 RemoteAudioTrackAdapter::~RemoteAudioTrackAdapter() { | |
222 #if DCHECK_IS_ON() | |
223 DCHECK(unregistered_); | |
224 #endif | |
225 } | |
226 | |
227 void RemoteAudioTrackAdapter::Unregister() { | |
228 #if DCHECK_IS_ON() | |
229 DCHECK(!unregistered_); | |
230 unregistered_ = true; | |
231 #endif | |
232 observed_track()->UnregisterObserver(this); | |
233 } | |
234 | |
235 void RemoteAudioTrackAdapter::InitializeWebkitAudioTrack() { | |
236 InitializeWebkitTrack(blink::WebMediaStreamSource::kTypeAudio); | |
237 | |
238 MediaStreamAudioSource* const source = | |
239 new PeerConnectionRemoteAudioSource(observed_track().get()); | |
240 webkit_track()->Source().SetExtraData(source); // Takes ownership. | |
241 source->ConnectToTrack(*(webkit_track())); | |
242 } | |
243 | |
244 void RemoteAudioTrackAdapter::OnChanged() { | |
245 main_thread_->PostTask(FROM_HERE, | |
246 base::Bind(&RemoteAudioTrackAdapter::OnChangedOnMainThread, | |
247 this, observed_track()->state())); | |
248 } | |
249 | |
250 void RemoteAudioTrackAdapter::OnChangedOnMainThread( | |
251 webrtc::MediaStreamTrackInterface::TrackState state) { | |
252 DCHECK(main_thread_->BelongsToCurrentThread()); | |
253 | |
254 if (state == state_ || !initialized()) | |
255 return; | |
256 | |
257 state_ = state; | |
258 | |
259 switch (state) { | |
260 case webrtc::MediaStreamTrackInterface::kLive: | |
261 webkit_track()->Source().SetReadyState( | |
262 blink::WebMediaStreamSource::kReadyStateLive); | |
263 break; | |
264 case webrtc::MediaStreamTrackInterface::kEnded: | |
265 webkit_track()->Source().SetReadyState( | |
266 blink::WebMediaStreamSource::kReadyStateEnded); | |
267 break; | |
268 default: | |
269 NOTREACHED(); | |
270 break; | |
271 } | |
272 } | |
273 | |
274 RemoteMediaStreamImpl::Observer::Observer( | 47 RemoteMediaStreamImpl::Observer::Observer( |
275 const base::WeakPtr<RemoteMediaStreamImpl>& media_stream, | 48 const base::WeakPtr<RemoteMediaStreamImpl>& media_stream, |
276 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, | 49 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, |
277 webrtc::MediaStreamInterface* webrtc_stream) | 50 webrtc::MediaStreamInterface* webrtc_stream) |
278 : media_stream_(media_stream), | 51 : media_stream_(media_stream), |
279 main_thread_(main_thread), | 52 main_thread_(main_thread), |
280 webrtc_stream_(webrtc_stream) { | 53 webrtc_stream_(webrtc_stream) { |
281 webrtc_stream_->RegisterObserver(this); | 54 webrtc_stream_->RegisterObserver(this); |
282 } | 55 } |
283 | 56 |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 track->Unregister(); | 121 track->Unregister(); |
349 observer_->Unregister(); | 122 observer_->Unregister(); |
350 } | 123 } |
351 | 124 |
352 void RemoteMediaStreamImpl::InitializeOnMainThread(const std::string& label) { | 125 void RemoteMediaStreamImpl::InitializeOnMainThread(const std::string& label) { |
353 DCHECK(observer_->main_thread()->BelongsToCurrentThread()); | 126 DCHECK(observer_->main_thread()->BelongsToCurrentThread()); |
354 blink::WebVector<blink::WebMediaStreamTrack> webkit_audio_tracks( | 127 blink::WebVector<blink::WebMediaStreamTrack> webkit_audio_tracks( |
355 audio_track_observers_.size()); | 128 audio_track_observers_.size()); |
356 for (size_t i = 0; i < audio_track_observers_.size(); ++i) { | 129 for (size_t i = 0; i < audio_track_observers_.size(); ++i) { |
357 audio_track_observers_[i]->Initialize(); | 130 audio_track_observers_[i]->Initialize(); |
358 webkit_audio_tracks[i] = *audio_track_observers_[i]->webkit_track(); | 131 webkit_audio_tracks[i] = *audio_track_observers_[i]->web_track(); |
359 } | 132 } |
360 | 133 |
361 blink::WebVector<blink::WebMediaStreamTrack> webkit_video_tracks( | 134 blink::WebVector<blink::WebMediaStreamTrack> webkit_video_tracks( |
362 video_track_observers_.size()); | 135 video_track_observers_.size()); |
363 for (size_t i = 0; i < video_track_observers_.size(); ++i) { | 136 for (size_t i = 0; i < video_track_observers_.size(); ++i) { |
364 video_track_observers_[i]->Initialize(); | 137 video_track_observers_[i]->Initialize(); |
365 webkit_video_tracks[i] = *video_track_observers_[i]->webkit_track(); | 138 webkit_video_tracks[i] = *video_track_observers_[i]->web_track(); |
366 } | 139 } |
367 | 140 |
368 webkit_stream_.Initialize(blink::WebString::FromUTF8(label), | 141 webkit_stream_.Initialize(blink::WebString::FromUTF8(label), |
369 webkit_audio_tracks, webkit_video_tracks); | 142 webkit_audio_tracks, webkit_video_tracks); |
370 webkit_stream_.SetExtraData(new MediaStream()); | 143 webkit_stream_.SetExtraData(new MediaStream()); |
371 } | 144 } |
372 | 145 |
373 void RemoteMediaStreamImpl::OnChanged( | 146 void RemoteMediaStreamImpl::OnChanged( |
374 std::unique_ptr<RemoteAudioTrackAdapters> audio_tracks, | 147 std::unique_ptr<RemoteAudioTrackAdapters> audio_tracks, |
375 std::unique_ptr<RemoteVideoTrackAdapters> video_tracks) { | 148 std::unique_ptr<RemoteVideoTrackAdapters> video_tracks) { |
376 // Find removed tracks. | 149 // Find removed tracks. |
377 auto audio_it = audio_track_observers_.begin(); | 150 auto audio_it = audio_track_observers_.begin(); |
378 while (audio_it != audio_track_observers_.end()) { | 151 while (audio_it != audio_track_observers_.end()) { |
379 if (!IsTrackInVector(*audio_tracks.get(), (*audio_it)->id())) { | 152 if (!IsTrackInVector(*audio_tracks.get(), (*audio_it)->id())) { |
380 (*audio_it)->Unregister(); | 153 (*audio_it)->Unregister(); |
381 webkit_stream_.RemoveTrack(*(*audio_it)->webkit_track()); | 154 webkit_stream_.RemoveTrack(*(*audio_it)->web_track()); |
382 audio_it = audio_track_observers_.erase(audio_it); | 155 audio_it = audio_track_observers_.erase(audio_it); |
383 } else { | 156 } else { |
384 ++audio_it; | 157 ++audio_it; |
385 } | 158 } |
386 } | 159 } |
387 | 160 |
388 auto video_it = video_track_observers_.begin(); | 161 auto video_it = video_track_observers_.begin(); |
389 while (video_it != video_track_observers_.end()) { | 162 while (video_it != video_track_observers_.end()) { |
390 if (!IsTrackInVector(*video_tracks.get(), (*video_it)->id())) { | 163 if (!IsTrackInVector(*video_tracks.get(), (*video_it)->id())) { |
391 webkit_stream_.RemoveTrack(*(*video_it)->webkit_track()); | 164 webkit_stream_.RemoveTrack(*(*video_it)->web_track()); |
392 video_it = video_track_observers_.erase(video_it); | 165 video_it = video_track_observers_.erase(video_it); |
393 } else { | 166 } else { |
394 ++video_it; | 167 ++video_it; |
395 } | 168 } |
396 } | 169 } |
397 | 170 |
398 // Find added tracks. | 171 // Find added tracks. |
399 for (auto& track : *audio_tracks.get()) { | 172 for (auto& track : *audio_tracks.get()) { |
400 if (!IsTrackInVector(audio_track_observers_, track->id())) { | 173 if (!IsTrackInVector(audio_track_observers_, track->id())) { |
401 track->Initialize(); | 174 track->Initialize(); |
402 audio_track_observers_.push_back(track); | 175 audio_track_observers_.push_back(track); |
403 webkit_stream_.AddTrack(*track->webkit_track()); | 176 webkit_stream_.AddTrack(*track->web_track()); |
404 // Set the track to null to avoid unregistering it below now that it's | 177 // Set the track to null to avoid unregistering it below now that it's |
405 // been associated with a media stream. | 178 // been associated with a media stream. |
406 track = nullptr; | 179 track = nullptr; |
407 } | 180 } |
408 } | 181 } |
409 | 182 |
410 // Find added video tracks. | 183 // Find added video tracks. |
411 for (const auto& track : *video_tracks.get()) { | 184 for (const auto& track : *video_tracks.get()) { |
412 if (!IsTrackInVector(video_track_observers_, track->id())) { | 185 if (!IsTrackInVector(video_track_observers_, track->id())) { |
413 track->Initialize(); | 186 track->Initialize(); |
414 video_track_observers_.push_back(track); | 187 video_track_observers_.push_back(track); |
415 webkit_stream_.AddTrack(*track->webkit_track()); | 188 webkit_stream_.AddTrack(*track->web_track()); |
416 } | 189 } |
417 } | 190 } |
418 | 191 |
419 // Unregister all the audio track observers that were not used. | 192 // Unregister all the audio track observers that were not used. |
420 // We need to do this before destruction since the observers can't unregister | 193 // We need to do this before destruction since the observers can't unregister |
421 // from within the dtor due to a race. | 194 // from within the dtor due to a race. |
422 for (auto& track : *audio_tracks.get()) { | 195 for (auto& track : *audio_tracks.get()) { |
423 if (track.get()) | 196 if (track.get()) |
424 track->Unregister(); | 197 track->Unregister(); |
425 } | 198 } |
426 } | 199 } |
427 | 200 |
428 } // namespace content | 201 } // namespace content |
OLD | NEW |