Chromium Code Reviews| 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/threading/thread_task_runner_handle.h" | 16 #include "base/threading/thread_task_runner_handle.h" |
| 17 #include "content/renderer/media/media_stream.h" | 17 #include "content/renderer/media/media_stream.h" |
| 18 #include "content/renderer/media/media_stream_track.h" | 18 #include "content/renderer/media/media_stream_track.h" |
| 19 #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" | 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 "third_party/WebKit/public/platform/WebMediaStreamTrack.h" | 22 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" |
| 23 #include "third_party/WebKit/public/platform/WebString.h" | 23 #include "third_party/WebKit/public/platform/WebString.h" |
| 24 | 24 |
| 25 namespace content { | 25 namespace content { |
| 26 | |
| 26 namespace { | 27 namespace { |
| 27 | 28 |
| 28 template <typename WebRtcTrackVector, typename AdapterType> | 29 // Gets the adapters for the tracks that are members of the webrtc stream. |
| 29 void CreateAdaptersForTracks( | 30 // Invoke on webrtc signaling thread. New adapters are initialized in a post |
| 30 const WebRtcTrackVector& tracks, | 31 // to the main thread after which their |web_track| becomes available. |
| 31 std::vector<scoped_refptr<AdapterType>>* observers, | 32 RemoteMediaStreamImpl::AdapterRefMap GetAdapterRefMapFromWebRtcStream( |
| 32 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread) { | 33 const scoped_refptr<WebRtcMediaStreamTrackAdapterMap>& track_adapter_map, |
| 33 for (auto& track : tracks) | 34 webrtc::MediaStreamInterface* webrtc_stream) { |
| 34 observers->push_back(new AdapterType(main_thread, track)); | 35 RemoteMediaStreamImpl::AdapterRefMap adapter_refs; |
| 36 for (auto& webrtc_audio_track : webrtc_stream->GetAudioTracks()) { | |
| 37 adapter_refs.insert( | |
| 38 std::make_pair(webrtc_audio_track->id(), | |
| 39 track_adapter_map->GetOrCreateRemoteTrackAdapter( | |
| 40 webrtc_audio_track.get()))); | |
| 41 } | |
| 42 for (auto& webrtc_video_track : webrtc_stream->GetVideoTracks()) { | |
| 43 adapter_refs.insert( | |
| 44 std::make_pair(webrtc_video_track->id(), | |
| 45 track_adapter_map->GetOrCreateRemoteTrackAdapter( | |
| 46 webrtc_video_track.get()))); | |
| 47 } | |
| 48 return adapter_refs; | |
| 35 } | 49 } |
| 36 | 50 |
| 37 template<typename VectorType> | |
| 38 bool IsTrackInVector(const VectorType& v, const std::string& id) { | |
| 39 for (const auto& t : v) { | |
| 40 if (t->id() == id) | |
| 41 return true; | |
| 42 } | |
| 43 return false; | |
| 44 } | |
| 45 } // namespace | 51 } // namespace |
| 46 | 52 |
| 47 RemoteMediaStreamImpl::Observer::Observer( | 53 RemoteMediaStreamImpl::Observer::Observer( |
| 48 const base::WeakPtr<RemoteMediaStreamImpl>& media_stream, | 54 const base::WeakPtr<RemoteMediaStreamImpl>& media_stream, |
| 49 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, | 55 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, |
| 56 const scoped_refptr<WebRtcMediaStreamTrackAdapterMap>& track_adapter_map, | |
| 50 webrtc::MediaStreamInterface* webrtc_stream) | 57 webrtc::MediaStreamInterface* webrtc_stream) |
| 51 : media_stream_(media_stream), | 58 : media_stream_(media_stream), |
| 52 main_thread_(main_thread), | 59 main_thread_(main_thread), |
| 60 track_adapter_map_(track_adapter_map), | |
| 53 webrtc_stream_(webrtc_stream) { | 61 webrtc_stream_(webrtc_stream) { |
| 54 webrtc_stream_->RegisterObserver(this); | 62 webrtc_stream_->RegisterObserver(this); |
| 55 } | 63 } |
| 56 | 64 |
| 57 RemoteMediaStreamImpl::Observer::~Observer() { | 65 RemoteMediaStreamImpl::Observer::~Observer() { |
| 58 DCHECK(!webrtc_stream_.get()) << "Unregister hasn't been called"; | 66 DCHECK(!webrtc_stream_.get()) << "Unregister hasn't been called"; |
| 59 } | 67 } |
| 60 | 68 |
| 61 void RemoteMediaStreamImpl::Observer::InitializeOnMainThread( | 69 void RemoteMediaStreamImpl::Observer::InitializeOnMainThread( |
| 62 const std::string& label) { | 70 const std::string& label, |
| 71 AdapterRefMap adapter_refs, | |
| 72 size_t audio_track_count, | |
| 73 size_t video_track_count) { | |
| 63 DCHECK(main_thread_->BelongsToCurrentThread()); | 74 DCHECK(main_thread_->BelongsToCurrentThread()); |
| 64 if (media_stream_) | 75 if (media_stream_) { |
| 65 media_stream_->InitializeOnMainThread(label); | 76 media_stream_->InitializeOnMainThread(label, std::move(adapter_refs), |
| 77 audio_track_count, video_track_count); | |
| 78 } | |
| 66 } | 79 } |
| 67 | 80 |
| 68 void RemoteMediaStreamImpl::Observer::Unregister() { | 81 void RemoteMediaStreamImpl::Observer::Unregister() { |
| 69 DCHECK(main_thread_->BelongsToCurrentThread()); | 82 DCHECK(main_thread_->BelongsToCurrentThread()); |
| 70 webrtc_stream_->UnregisterObserver(this); | 83 webrtc_stream_->UnregisterObserver(this); |
| 71 // Since we're guaranteed to not get further notifications, it's safe to | 84 // Since we're guaranteed to not get further notifications, it's safe to |
| 72 // release the webrtc_stream_ here. | 85 // release the webrtc_stream_ here. |
| 73 webrtc_stream_ = nullptr; | 86 webrtc_stream_ = nullptr; |
| 74 } | 87 } |
| 75 | 88 |
| 76 void RemoteMediaStreamImpl::Observer::OnChanged() { | 89 void RemoteMediaStreamImpl::Observer::OnChanged() { |
| 77 std::unique_ptr<RemoteAudioTrackAdapters> audio( | 90 AdapterRefMap new_adapter_refs = GetAdapterRefMapFromWebRtcStream( |
|
Guido Urdaneta
2017/06/12 14:25:28
Is there a race if you access track_adapter_map_ f
hbos_chromium
2017/06/12 15:05:20
No, track_adapter_map_ is thread-safe.
Guido Urdaneta
2017/06/12 15:18:34
Acknowledged.
| |
| 78 new RemoteAudioTrackAdapters()); | 91 track_adapter_map_, webrtc_stream_.get()); |
| 79 std::unique_ptr<RemoteVideoTrackAdapters> video( | 92 main_thread_->PostTask( |
| 80 new RemoteVideoTrackAdapters()); | 93 FROM_HERE, |
| 81 | 94 base::Bind(&RemoteMediaStreamImpl::Observer::OnChangedOnMainThread, this, |
| 82 CreateAdaptersForTracks( | 95 base::Passed(&new_adapter_refs))); |
| 83 webrtc_stream_->GetAudioTracks(), audio.get(), main_thread_); | |
| 84 CreateAdaptersForTracks( | |
| 85 webrtc_stream_->GetVideoTracks(), video.get(), main_thread_); | |
| 86 | |
| 87 main_thread_->PostTask(FROM_HERE, | |
| 88 base::Bind(&RemoteMediaStreamImpl::Observer::OnChangedOnMainThread, | |
| 89 this, base::Passed(&audio), base::Passed(&video))); | |
| 90 } | 96 } |
| 91 | 97 |
| 92 void RemoteMediaStreamImpl::Observer::OnChangedOnMainThread( | 98 void RemoteMediaStreamImpl::Observer::OnChangedOnMainThread( |
| 93 std::unique_ptr<RemoteAudioTrackAdapters> audio_tracks, | 99 AdapterRefMap new_adapter_refs) { |
| 94 std::unique_ptr<RemoteVideoTrackAdapters> video_tracks) { | |
| 95 DCHECK(main_thread_->BelongsToCurrentThread()); | 100 DCHECK(main_thread_->BelongsToCurrentThread()); |
| 96 if (media_stream_) | 101 if (media_stream_) |
| 97 media_stream_->OnChanged(std::move(audio_tracks), std::move(video_tracks)); | 102 media_stream_->OnChanged(std::move(new_adapter_refs)); |
| 98 } | 103 } |
| 99 | 104 |
| 100 // Called on the signaling thread. | 105 // Called on the signaling thread. |
| 101 RemoteMediaStreamImpl::RemoteMediaStreamImpl( | 106 RemoteMediaStreamImpl::RemoteMediaStreamImpl( |
| 102 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, | 107 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, |
| 108 const scoped_refptr<WebRtcMediaStreamTrackAdapterMap>& track_adapter_map, | |
| 103 webrtc::MediaStreamInterface* webrtc_stream) | 109 webrtc::MediaStreamInterface* webrtc_stream) |
| 104 : signaling_thread_(base::ThreadTaskRunnerHandle::Get()), | 110 : signaling_thread_(base::ThreadTaskRunnerHandle::Get()), |
| 111 track_adapter_map_(track_adapter_map), | |
| 105 weak_factory_(this) { | 112 weak_factory_(this) { |
|
Guido Urdaneta
2017/06/12 14:25:28
If necessary, can you add a check to ensure this r
hbos_chromium
2017/06/12 15:05:20
Added a DCHECK that we are not on the main thread,
Guido Urdaneta
2017/06/12 15:18:34
Acknowledged.
| |
| 113 DCHECK(track_adapter_map_); | |
| 106 observer_ = new RemoteMediaStreamImpl::Observer( | 114 observer_ = new RemoteMediaStreamImpl::Observer( |
| 107 weak_factory_.GetWeakPtr(), main_thread, webrtc_stream); | 115 weak_factory_.GetWeakPtr(), main_thread, track_adapter_map_, |
| 108 CreateAdaptersForTracks(webrtc_stream->GetAudioTracks(), | 116 webrtc_stream); |
| 109 &audio_track_observers_, main_thread); | |
| 110 CreateAdaptersForTracks(webrtc_stream->GetVideoTracks(), | |
| 111 &video_track_observers_, main_thread); | |
| 112 | 117 |
| 113 main_thread->PostTask(FROM_HERE, | 118 AdapterRefMap adapter_refs = |
| 119 GetAdapterRefMapFromWebRtcStream(track_adapter_map_, webrtc_stream); | |
| 120 main_thread->PostTask( | |
| 121 FROM_HERE, | |
| 114 base::Bind(&RemoteMediaStreamImpl::Observer::InitializeOnMainThread, | 122 base::Bind(&RemoteMediaStreamImpl::Observer::InitializeOnMainThread, |
| 115 observer_, webrtc_stream->label())); | 123 observer_, webrtc_stream->label(), base::Passed(&adapter_refs), |
| 124 webrtc_stream->GetAudioTracks().size(), | |
| 125 webrtc_stream->GetVideoTracks().size())); | |
| 116 } | 126 } |
| 117 | 127 |
| 118 RemoteMediaStreamImpl::~RemoteMediaStreamImpl() { | 128 RemoteMediaStreamImpl::~RemoteMediaStreamImpl() { |
| 119 DCHECK(observer_->main_thread()->BelongsToCurrentThread()); | 129 DCHECK(observer_->main_thread()->BelongsToCurrentThread()); |
| 120 for (auto& track : audio_track_observers_) | |
| 121 track->Unregister(); | |
| 122 observer_->Unregister(); | 130 observer_->Unregister(); |
| 131 OnChanged(AdapterRefMap()); | |
| 123 } | 132 } |
| 124 | 133 |
| 125 void RemoteMediaStreamImpl::InitializeOnMainThread(const std::string& label) { | 134 void RemoteMediaStreamImpl::InitializeOnMainThread(const std::string& label, |
| 135 AdapterRefMap adapter_refs, | |
| 136 size_t audio_track_count, | |
| 137 size_t video_track_count) { | |
| 126 DCHECK(observer_->main_thread()->BelongsToCurrentThread()); | 138 DCHECK(observer_->main_thread()->BelongsToCurrentThread()); |
| 127 blink::WebVector<blink::WebMediaStreamTrack> webkit_audio_tracks( | 139 DCHECK_EQ(audio_track_count + video_track_count, adapter_refs.size()); |
| 128 audio_track_observers_.size()); | 140 |
| 129 for (size_t i = 0; i < audio_track_observers_.size(); ++i) { | 141 adapter_refs_ = std::move(adapter_refs); |
| 130 audio_track_observers_[i]->Initialize(); | 142 blink::WebVector<blink::WebMediaStreamTrack> web_audio_tracks( |
| 131 webkit_audio_tracks[i] = *audio_track_observers_[i]->web_track(); | 143 audio_track_count); |
| 144 blink::WebVector<blink::WebMediaStreamTrack> web_video_tracks( | |
| 145 video_track_count); | |
| 146 size_t audio_i = 0; | |
| 147 size_t video_i = 0; | |
| 148 for (const auto& it : adapter_refs_) { | |
| 149 const blink::WebMediaStreamTrack& web_track = it.second->web_track(); | |
| 150 if (web_track.Source().GetType() == blink::WebMediaStreamSource::kTypeAudio) | |
| 151 web_audio_tracks[audio_i++] = web_track; | |
| 152 else | |
| 153 web_video_tracks[video_i++] = web_track; | |
| 132 } | 154 } |
| 133 | 155 |
| 134 blink::WebVector<blink::WebMediaStreamTrack> webkit_video_tracks( | 156 webkit_stream_.Initialize(blink::WebString::FromUTF8(label), web_audio_tracks, |
| 135 video_track_observers_.size()); | 157 web_video_tracks); |
| 136 for (size_t i = 0; i < video_track_observers_.size(); ++i) { | |
| 137 video_track_observers_[i]->Initialize(); | |
| 138 webkit_video_tracks[i] = *video_track_observers_[i]->web_track(); | |
| 139 } | |
| 140 | |
| 141 webkit_stream_.Initialize(blink::WebString::FromUTF8(label), | |
| 142 webkit_audio_tracks, webkit_video_tracks); | |
| 143 webkit_stream_.SetExtraData(new MediaStream()); | 158 webkit_stream_.SetExtraData(new MediaStream()); |
| 144 } | 159 } |
| 145 | 160 |
| 146 void RemoteMediaStreamImpl::OnChanged( | 161 void RemoteMediaStreamImpl::OnChanged(AdapterRefMap new_adapter_refs) { |
| 147 std::unique_ptr<RemoteAudioTrackAdapters> audio_tracks, | 162 DCHECK(observer_->main_thread()->BelongsToCurrentThread()); |
| 148 std::unique_ptr<RemoteVideoTrackAdapters> video_tracks) { | 163 |
| 149 // Find removed tracks. | 164 // Find removed tracks. |
| 150 auto audio_it = audio_track_observers_.begin(); | 165 for (auto it = adapter_refs_.begin(); it != adapter_refs_.end();) { |
| 151 while (audio_it != audio_track_observers_.end()) { | 166 if (new_adapter_refs.find(it->first) == new_adapter_refs.end()) { |
| 152 if (!IsTrackInVector(*audio_tracks.get(), (*audio_it)->id())) { | 167 webkit_stream_.RemoveTrack(it->second->web_track()); |
| 153 (*audio_it)->Unregister(); | 168 it = adapter_refs_.erase(it); |
| 154 webkit_stream_.RemoveTrack(*(*audio_it)->web_track()); | |
| 155 audio_it = audio_track_observers_.erase(audio_it); | |
| 156 } else { | 169 } else { |
| 157 ++audio_it; | 170 ++it; |
| 158 } | 171 } |
| 159 } | 172 } |
| 160 | 173 // Find added tracks. |
| 161 auto video_it = video_track_observers_.begin(); | 174 for (auto& it : new_adapter_refs) { |
| 162 while (video_it != video_track_observers_.end()) { | 175 if (adapter_refs_.find(it.first) == adapter_refs_.end()) { |
| 163 if (!IsTrackInVector(*video_tracks.get(), (*video_it)->id())) { | 176 webkit_stream_.AddTrack(it.second->web_track()); |
| 164 webkit_stream_.RemoveTrack(*(*video_it)->web_track()); | 177 adapter_refs_.insert(std::make_pair(it.first, std::move(it.second))); |
| 165 video_it = video_track_observers_.erase(video_it); | |
| 166 } else { | |
| 167 ++video_it; | |
| 168 } | 178 } |
| 169 } | 179 } |
| 170 | |
| 171 // Find added tracks. | |
| 172 for (auto& track : *audio_tracks.get()) { | |
| 173 if (!IsTrackInVector(audio_track_observers_, track->id())) { | |
| 174 track->Initialize(); | |
| 175 audio_track_observers_.push_back(track); | |
| 176 webkit_stream_.AddTrack(*track->web_track()); | |
| 177 // Set the track to null to avoid unregistering it below now that it's | |
| 178 // been associated with a media stream. | |
| 179 track = nullptr; | |
| 180 } | |
| 181 } | |
| 182 | |
| 183 // Find added video tracks. | |
| 184 for (const auto& track : *video_tracks.get()) { | |
| 185 if (!IsTrackInVector(video_track_observers_, track->id())) { | |
| 186 track->Initialize(); | |
| 187 video_track_observers_.push_back(track); | |
| 188 webkit_stream_.AddTrack(*track->web_track()); | |
| 189 } | |
| 190 } | |
| 191 | |
| 192 // Unregister all the audio track observers that were not used. | |
| 193 // We need to do this before destruction since the observers can't unregister | |
| 194 // from within the dtor due to a race. | |
| 195 for (auto& track : *audio_tracks.get()) { | |
| 196 if (track.get()) | |
| 197 track->Unregister(); | |
| 198 } | |
| 199 } | 180 } |
| 200 | 181 |
| 201 } // namespace content | 182 } // namespace content |
| OLD | NEW |