| 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 class RemoteMediaStreamImpl::Observer |
| 48 const base::WeakPtr<RemoteMediaStreamImpl>& media_stream, | 54 : NON_EXPORTED_BASE(public webrtc::ObserverInterface), |
| 49 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, | 55 public base::RefCountedThreadSafe<Observer> { |
| 50 webrtc::MediaStreamInterface* webrtc_stream) | 56 public: |
| 51 : media_stream_(media_stream), | 57 Observer( |
| 52 main_thread_(main_thread), | 58 const base::WeakPtr<RemoteMediaStreamImpl>& media_stream, |
| 53 webrtc_stream_(webrtc_stream) { | 59 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, |
| 54 webrtc_stream_->RegisterObserver(this); | 60 const scoped_refptr<WebRtcMediaStreamTrackAdapterMap>& track_adapter_map, |
| 55 } | 61 webrtc::MediaStreamInterface* webrtc_stream) |
| 62 : media_stream_(media_stream), |
| 63 main_thread_(main_thread), |
| 64 track_adapter_map_(track_adapter_map), |
| 65 webrtc_stream_(webrtc_stream) { |
| 66 webrtc_stream_->RegisterObserver(this); |
| 67 } |
| 56 | 68 |
| 57 RemoteMediaStreamImpl::Observer::~Observer() { | 69 const scoped_refptr<webrtc::MediaStreamInterface>& stream() const { |
| 58 DCHECK(!webrtc_stream_.get()) << "Unregister hasn't been called"; | 70 return webrtc_stream_; |
| 59 } | 71 } |
| 60 | 72 |
| 61 void RemoteMediaStreamImpl::Observer::InitializeOnMainThread( | 73 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread() const { |
| 62 const std::string& label) { | 74 return main_thread_; |
| 63 DCHECK(main_thread_->BelongsToCurrentThread()); | 75 } |
| 64 if (media_stream_) | |
| 65 media_stream_->InitializeOnMainThread(label); | |
| 66 } | |
| 67 | 76 |
| 68 void RemoteMediaStreamImpl::Observer::Unregister() { | 77 void InitializeOnMainThread(const std::string& label, |
| 69 DCHECK(main_thread_->BelongsToCurrentThread()); | 78 AdapterRefMap adapter_refs, |
| 70 webrtc_stream_->UnregisterObserver(this); | 79 size_t audio_track_count, |
| 71 // Since we're guaranteed to not get further notifications, it's safe to | 80 size_t video_track_count) { |
| 72 // release the webrtc_stream_ here. | 81 DCHECK(main_thread_->BelongsToCurrentThread()); |
| 73 webrtc_stream_ = nullptr; | 82 if (media_stream_) { |
| 74 } | 83 media_stream_->InitializeOnMainThread( |
| 84 label, std::move(adapter_refs), audio_track_count, video_track_count); |
| 85 } |
| 86 } |
| 75 | 87 |
| 76 void RemoteMediaStreamImpl::Observer::OnChanged() { | 88 // Uninitializes the observer, unregisteres from receiving notifications |
| 77 std::unique_ptr<RemoteAudioTrackAdapters> audio( | 89 // and releases the webrtc stream. |
| 78 new RemoteAudioTrackAdapters()); | 90 // Note: Must be called from the main thread before releasing the main |
| 79 std::unique_ptr<RemoteVideoTrackAdapters> video( | 91 // reference. |
| 80 new RemoteVideoTrackAdapters()); | 92 void Unregister() { |
| 93 DCHECK(main_thread_->BelongsToCurrentThread()); |
| 94 webrtc_stream_->UnregisterObserver(this); |
| 95 // Since we're guaranteed to not get further notifications, it's safe to |
| 96 // release the webrtc_stream_ here. |
| 97 webrtc_stream_ = nullptr; |
| 98 } |
| 81 | 99 |
| 82 CreateAdaptersForTracks( | 100 private: |
| 83 webrtc_stream_->GetAudioTracks(), audio.get(), main_thread_); | 101 friend class base::RefCountedThreadSafe<Observer>; |
| 84 CreateAdaptersForTracks( | |
| 85 webrtc_stream_->GetVideoTracks(), video.get(), main_thread_); | |
| 86 | 102 |
| 87 main_thread_->PostTask(FROM_HERE, | 103 ~Observer() override { |
| 88 base::Bind(&RemoteMediaStreamImpl::Observer::OnChangedOnMainThread, | 104 DCHECK(!webrtc_stream_.get()) << "Unregister hasn't been called"; |
| 89 this, base::Passed(&audio), base::Passed(&video))); | 105 } |
| 90 } | |
| 91 | 106 |
| 92 void RemoteMediaStreamImpl::Observer::OnChangedOnMainThread( | 107 // webrtc::ObserverInterface implementation. |
| 93 std::unique_ptr<RemoteAudioTrackAdapters> audio_tracks, | 108 void OnChanged() override { |
| 94 std::unique_ptr<RemoteVideoTrackAdapters> video_tracks) { | 109 AdapterRefMap new_adapter_refs = GetAdapterRefMapFromWebRtcStream( |
| 95 DCHECK(main_thread_->BelongsToCurrentThread()); | 110 track_adapter_map_, webrtc_stream_.get()); |
| 96 if (media_stream_) | 111 main_thread_->PostTask( |
| 97 media_stream_->OnChanged(std::move(audio_tracks), std::move(video_tracks)); | 112 FROM_HERE, |
| 98 } | 113 base::Bind(&RemoteMediaStreamImpl::Observer::OnChangedOnMainThread, |
| 114 this, base::Passed(&new_adapter_refs))); |
| 115 } |
| 116 |
| 117 void OnChangedOnMainThread(AdapterRefMap new_adapter_refs) { |
| 118 DCHECK(main_thread_->BelongsToCurrentThread()); |
| 119 if (media_stream_) |
| 120 media_stream_->OnChanged(std::move(new_adapter_refs)); |
| 121 } |
| 122 |
| 123 base::WeakPtr<RemoteMediaStreamImpl> media_stream_; |
| 124 const scoped_refptr<base::SingleThreadTaskRunner> main_thread_; |
| 125 const scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map_; |
| 126 scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream_; |
| 127 }; |
| 99 | 128 |
| 100 // Called on the signaling thread. | 129 // Called on the signaling thread. |
| 101 RemoteMediaStreamImpl::RemoteMediaStreamImpl( | 130 RemoteMediaStreamImpl::RemoteMediaStreamImpl( |
| 102 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, | 131 const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, |
| 132 const scoped_refptr<WebRtcMediaStreamTrackAdapterMap>& track_adapter_map, |
| 103 webrtc::MediaStreamInterface* webrtc_stream) | 133 webrtc::MediaStreamInterface* webrtc_stream) |
| 104 : signaling_thread_(base::ThreadTaskRunnerHandle::Get()), | 134 : signaling_thread_(base::ThreadTaskRunnerHandle::Get()), |
| 135 track_adapter_map_(track_adapter_map), |
| 105 weak_factory_(this) { | 136 weak_factory_(this) { |
| 137 DCHECK(!main_thread->BelongsToCurrentThread()); |
| 138 DCHECK(track_adapter_map_); |
| 106 observer_ = new RemoteMediaStreamImpl::Observer( | 139 observer_ = new RemoteMediaStreamImpl::Observer( |
| 107 weak_factory_.GetWeakPtr(), main_thread, webrtc_stream); | 140 weak_factory_.GetWeakPtr(), main_thread, track_adapter_map_, |
| 108 CreateAdaptersForTracks(webrtc_stream->GetAudioTracks(), | 141 webrtc_stream); |
| 109 &audio_track_observers_, main_thread); | |
| 110 CreateAdaptersForTracks(webrtc_stream->GetVideoTracks(), | |
| 111 &video_track_observers_, main_thread); | |
| 112 | 142 |
| 113 main_thread->PostTask(FROM_HERE, | 143 AdapterRefMap adapter_refs = |
| 144 GetAdapterRefMapFromWebRtcStream(track_adapter_map_, webrtc_stream); |
| 145 main_thread->PostTask( |
| 146 FROM_HERE, |
| 114 base::Bind(&RemoteMediaStreamImpl::Observer::InitializeOnMainThread, | 147 base::Bind(&RemoteMediaStreamImpl::Observer::InitializeOnMainThread, |
| 115 observer_, webrtc_stream->label())); | 148 observer_, webrtc_stream->label(), base::Passed(&adapter_refs), |
| 149 webrtc_stream->GetAudioTracks().size(), |
| 150 webrtc_stream->GetVideoTracks().size())); |
| 116 } | 151 } |
| 117 | 152 |
| 118 RemoteMediaStreamImpl::~RemoteMediaStreamImpl() { | 153 RemoteMediaStreamImpl::~RemoteMediaStreamImpl() { |
| 119 DCHECK(observer_->main_thread()->BelongsToCurrentThread()); | 154 DCHECK(observer_->main_thread()->BelongsToCurrentThread()); |
| 120 for (auto& track : audio_track_observers_) | |
| 121 track->Unregister(); | |
| 122 observer_->Unregister(); | 155 observer_->Unregister(); |
| 156 OnChanged(AdapterRefMap()); |
| 123 } | 157 } |
| 124 | 158 |
| 125 void RemoteMediaStreamImpl::InitializeOnMainThread(const std::string& label) { | 159 const scoped_refptr<webrtc::MediaStreamInterface>& |
| 160 RemoteMediaStreamImpl::webrtc_stream() { |
| 161 return observer_->stream(); |
| 162 } |
| 163 |
| 164 void RemoteMediaStreamImpl::InitializeOnMainThread(const std::string& label, |
| 165 AdapterRefMap adapter_refs, |
| 166 size_t audio_track_count, |
| 167 size_t video_track_count) { |
| 126 DCHECK(observer_->main_thread()->BelongsToCurrentThread()); | 168 DCHECK(observer_->main_thread()->BelongsToCurrentThread()); |
| 127 blink::WebVector<blink::WebMediaStreamTrack> webkit_audio_tracks( | 169 DCHECK_EQ(audio_track_count + video_track_count, adapter_refs.size()); |
| 128 audio_track_observers_.size()); | 170 |
| 129 for (size_t i = 0; i < audio_track_observers_.size(); ++i) { | 171 adapter_refs_ = std::move(adapter_refs); |
| 130 audio_track_observers_[i]->Initialize(); | 172 blink::WebVector<blink::WebMediaStreamTrack> web_audio_tracks( |
| 131 webkit_audio_tracks[i] = *audio_track_observers_[i]->web_track(); | 173 audio_track_count); |
| 174 blink::WebVector<blink::WebMediaStreamTrack> web_video_tracks( |
| 175 video_track_count); |
| 176 size_t audio_i = 0; |
| 177 size_t video_i = 0; |
| 178 for (const auto& it : adapter_refs_) { |
| 179 const blink::WebMediaStreamTrack& web_track = it.second->web_track(); |
| 180 if (web_track.Source().GetType() == blink::WebMediaStreamSource::kTypeAudio) |
| 181 web_audio_tracks[audio_i++] = web_track; |
| 182 else |
| 183 web_video_tracks[video_i++] = web_track; |
| 132 } | 184 } |
| 133 | 185 |
| 134 blink::WebVector<blink::WebMediaStreamTrack> webkit_video_tracks( | 186 webkit_stream_.Initialize(blink::WebString::FromUTF8(label), web_audio_tracks, |
| 135 video_track_observers_.size()); | 187 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()); | 188 webkit_stream_.SetExtraData(new MediaStream()); |
| 144 } | 189 } |
| 145 | 190 |
| 146 void RemoteMediaStreamImpl::OnChanged( | 191 void RemoteMediaStreamImpl::OnChanged(AdapterRefMap new_adapter_refs) { |
| 147 std::unique_ptr<RemoteAudioTrackAdapters> audio_tracks, | 192 DCHECK(observer_->main_thread()->BelongsToCurrentThread()); |
| 148 std::unique_ptr<RemoteVideoTrackAdapters> video_tracks) { | 193 |
| 149 // Find removed tracks. | 194 // Find removed tracks. |
| 150 auto audio_it = audio_track_observers_.begin(); | 195 for (auto it = adapter_refs_.begin(); it != adapter_refs_.end();) { |
| 151 while (audio_it != audio_track_observers_.end()) { | 196 if (new_adapter_refs.find(it->first) == new_adapter_refs.end()) { |
| 152 if (!IsTrackInVector(*audio_tracks.get(), (*audio_it)->id())) { | 197 webkit_stream_.RemoveTrack(it->second->web_track()); |
| 153 (*audio_it)->Unregister(); | 198 it = adapter_refs_.erase(it); |
| 154 webkit_stream_.RemoveTrack(*(*audio_it)->web_track()); | |
| 155 audio_it = audio_track_observers_.erase(audio_it); | |
| 156 } else { | 199 } else { |
| 157 ++audio_it; | 200 ++it; |
| 158 } | 201 } |
| 159 } | 202 } |
| 160 | 203 // Find added tracks. |
| 161 auto video_it = video_track_observers_.begin(); | 204 for (auto& it : new_adapter_refs) { |
| 162 while (video_it != video_track_observers_.end()) { | 205 if (adapter_refs_.find(it.first) == adapter_refs_.end()) { |
| 163 if (!IsTrackInVector(*video_tracks.get(), (*video_it)->id())) { | 206 webkit_stream_.AddTrack(it.second->web_track()); |
| 164 webkit_stream_.RemoveTrack(*(*video_it)->web_track()); | 207 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 } | 208 } |
| 169 } | 209 } |
| 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 } | 210 } |
| 200 | 211 |
| 201 } // namespace content | 212 } // namespace content |
| OLD | NEW |