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 3 // found in the LICENSE file. 4 5 #include "content/renderer/media/remote_media_stream_impl.h" 6 7 #include <string> 8 9 #include "base/logging.h" 10 #include "base/strings/utf_string_conversions.h" 11 #include "content/renderer/media/media_stream.h" 12 #include "content/renderer/media/media_stream_video_track.h" 13 #include "content/renderer/media/webrtc/media_stream_remote_video_source.h" 14 #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h" 15 #include "third_party/WebKit/public/platform/WebString.h" 16 17 namespace content { 18 19 namespace { 20 21 void InitializeWebkitTrack(webrtc::MediaStreamTrackInterface* track, 22 blink::WebMediaStreamTrack* webkit_track, 23 blink::WebMediaStreamSource::Type type) { 24 blink::WebMediaStreamSource webkit_source; 25 blink::WebString webkit_track_id(base::UTF8ToUTF16(track->id())); 26 27 webkit_source.initialize(webkit_track_id, type, webkit_track_id); 28 webkit_track->initialize(webkit_track_id, webkit_source); 29 30 if (type == blink::WebMediaStreamSource::TypeVideo) { 31 MediaStreamRemoteVideoSource* video_source = 32 new MediaStreamRemoteVideoSource( 33 static_cast<webrtc::VideoTrackInterface*>(track)); 34 webkit_source.setExtraData(video_source); 35 // Initial constraints must be provided to a MediaStreamVideoTrack. But 36 // no constraints are available initially on a remote video track. 37 blink::WebMediaConstraints constraints; 38 constraints.initialize(); 39 webkit_track->setExtraData( 40 new MediaStreamVideoTrack(video_source, constraints, 41 MediaStreamVideoSource::ConstraintsCallback(), 42 track->enabled())); 43 } else { 44 DCHECK(type == blink::WebMediaStreamSource::TypeAudio); 45 content::PeerConnectionDependencyFactory::AddNativeAudioTrackToBlinkTrack( 46 track, *webkit_track, false); 47 } 48 } 49 50 } // namespace 51 52 // Base class used for mapping between webrtc and blink MediaStream tracks. 53 // An instance of a RemoteMediaStreamTrackAdapter is stored in 54 // RemoteMediaStreamImpl per remote audio and video track. 55 class RemoteMediaStreamTrackAdapter { 56 public: 57 RemoteMediaStreamTrackAdapter(webrtc::MediaStreamTrackInterface* webrtc_track, 58 const blink::WebMediaStreamTrack& webkit_track) 59 : webrtc_track_(webrtc_track), 60 webkit_track_(webkit_track) { 61 } 62 63 virtual ~RemoteMediaStreamTrackAdapter() { 64 } 65 66 webrtc::MediaStreamTrackInterface* observed_track() { 67 return webrtc_track_.get(); 68 } 69 70 const blink::WebMediaStreamTrack& webkit_track() { return webkit_track_; } 71 72 private: 73 scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track_; 74 blink::WebMediaStreamTrack webkit_track_; 75 76 DISALLOW_COPY_AND_ASSIGN(RemoteMediaStreamTrackAdapter); 77 }; 78 79 static content::RemoteMediaStreamTrackAdapter* FindTrackObserver( 80 webrtc::MediaStreamTrackInterface* track, 81 const ScopedVector<content::RemoteMediaStreamTrackAdapter>& observers) { 82 ScopedVector<content::RemoteMediaStreamTrackAdapter>::const_iterator it = 83 observers.begin(); 84 for (; it != observers.end(); ++it) { 85 if ((*it)->observed_track() == track) 86 return *it; 87 } 88 return NULL; 89 } 90 91 // RemoteAudioMediaStreamTrackAdapter is responsible for listening on state 92 // change notifications on a remote webrtc audio MediaStreamTracks and notify 93 // WebKit. 94 class RemoteAudioMediaStreamTrackAdapter 95 : public RemoteMediaStreamTrackAdapter, 96 public webrtc::ObserverInterface, 97 public base::NonThreadSafe { 98 public: 99 RemoteAudioMediaStreamTrackAdapter( 100 webrtc::MediaStreamTrackInterface* webrtc_track, 101 const blink::WebMediaStreamTrack& webkit_track); 102 virtual ~RemoteAudioMediaStreamTrackAdapter(); 103 104 private: 105 // webrtc::ObserverInterface implementation. 106 virtual void OnChanged() OVERRIDE; 107 108 webrtc::MediaStreamTrackInterface::TrackState state_; 109 110 DISALLOW_COPY_AND_ASSIGN(RemoteAudioMediaStreamTrackAdapter); 111 }; 112 113 RemoteAudioMediaStreamTrackAdapter::RemoteAudioMediaStreamTrackAdapter( 114 webrtc::MediaStreamTrackInterface* webrtc_track, 115 const blink::WebMediaStreamTrack& webkit_track) 116 : RemoteMediaStreamTrackAdapter(webrtc_track, webkit_track), 117 state_(observed_track()->state()) { 118 observed_track()->RegisterObserver(this); 119 } 120 121 RemoteAudioMediaStreamTrackAdapter::~RemoteAudioMediaStreamTrackAdapter() { 122 observed_track()->UnregisterObserver(this); 123 } 124 125 void RemoteAudioMediaStreamTrackAdapter::OnChanged() { 126 DCHECK(CalledOnValidThread()); 127 128 webrtc::MediaStreamTrackInterface::TrackState state = 129 observed_track()->state(); 130 if (state == state_) 131 return; 132 133 state_ = state; 134 switch (state) { 135 case webrtc::MediaStreamTrackInterface::kInitializing: 136 // Ignore the kInitializing state since there is no match in 137 // WebMediaStreamSource::ReadyState. 138 break; 139 case webrtc::MediaStreamTrackInterface::kLive: 140 webkit_track().source().setReadyState( 141 blink::WebMediaStreamSource::ReadyStateLive); 142 break; 143 case webrtc::MediaStreamTrackInterface::kEnded: 144 webkit_track().source().setReadyState( 145 blink::WebMediaStreamSource::ReadyStateEnded); 146 break; 147 default: 148 NOTREACHED(); 149 break; 150 } 151 } 152 153 RemoteMediaStreamImpl::RemoteMediaStreamImpl( 154 webrtc::MediaStreamInterface* webrtc_stream) 155 : webrtc_stream_(webrtc_stream) { 156 webrtc_stream_->RegisterObserver(this); 157 158 webrtc::AudioTrackVector webrtc_audio_tracks = 159 webrtc_stream_->GetAudioTracks(); 160 blink::WebVector<blink::WebMediaStreamTrack> webkit_audio_tracks( 161 webrtc_audio_tracks.size()); 162 163 // Initialize WebKit audio tracks. 164 size_t i = 0; 165 for (; i < webrtc_audio_tracks.size(); ++i) { 166 webrtc::AudioTrackInterface* audio_track = webrtc_audio_tracks[i]; 167 DCHECK(audio_track); 168 InitializeWebkitTrack(audio_track, &webkit_audio_tracks[i], 169 blink::WebMediaStreamSource::TypeAudio); 170 audio_track_observers_.push_back( 171 new RemoteAudioMediaStreamTrackAdapter(audio_track, 172 webkit_audio_tracks[i])); 173 } 174 175 // Initialize WebKit video tracks. 176 webrtc::VideoTrackVector webrtc_video_tracks = 177 webrtc_stream_->GetVideoTracks(); 178 blink::WebVector<blink::WebMediaStreamTrack> webkit_video_tracks( 179 webrtc_video_tracks.size()); 180 for (i = 0; i < webrtc_video_tracks.size(); ++i) { 181 webrtc::VideoTrackInterface* video_track = webrtc_video_tracks[i]; 182 DCHECK(video_track); 183 InitializeWebkitTrack(video_track, &webkit_video_tracks[i], 184 blink::WebMediaStreamSource::TypeVideo); 185 video_track_observers_.push_back( 186 new RemoteMediaStreamTrackAdapter(video_track, 187 webkit_video_tracks[i])); 188 } 189 190 webkit_stream_.initialize(base::UTF8ToUTF16(webrtc_stream->label()), 191 webkit_audio_tracks, webkit_video_tracks); 192 webkit_stream_.setExtraData(new MediaStream(webrtc_stream)); 193 } 194 195 RemoteMediaStreamImpl::~RemoteMediaStreamImpl() { 196 webrtc_stream_->UnregisterObserver(this); 197 } 198 199 void RemoteMediaStreamImpl::OnChanged() { 200 // Find removed audio tracks. 201 ScopedVector<RemoteMediaStreamTrackAdapter>::iterator audio_it = 202 audio_track_observers_.begin(); 203 while (audio_it != audio_track_observers_.end()) { 204 std::string track_id = (*audio_it)->observed_track()->id(); 205 if (webrtc_stream_->FindAudioTrack(track_id) == NULL) { 206 webkit_stream_.removeTrack((*audio_it)->webkit_track()); 207 audio_it = audio_track_observers_.erase(audio_it); 208 } else { 209 ++audio_it; 210 } 211 } 212 213 // Find removed video tracks. 214 ScopedVector<RemoteMediaStreamTrackAdapter>::iterator video_it = 215 video_track_observers_.begin(); 216 while (video_it != video_track_observers_.end()) { 217 std::string track_id = (*video_it)->observed_track()->id(); 218 if (webrtc_stream_->FindVideoTrack(track_id) == NULL) { 219 webkit_stream_.removeTrack((*video_it)->webkit_track()); 220 video_it = video_track_observers_.erase(video_it); 221 } else { 222 ++video_it; 223 } 224 } 225 226 // Find added audio tracks. 227 webrtc::AudioTrackVector webrtc_audio_tracks = 228 webrtc_stream_->GetAudioTracks(); 229 for (webrtc::AudioTrackVector::iterator it = webrtc_audio_tracks.begin(); 230 it != webrtc_audio_tracks.end(); ++it) { 231 if (!FindTrackObserver(*it, audio_track_observers_)) { 232 blink::WebMediaStreamTrack new_track; 233 InitializeWebkitTrack(*it, &new_track, 234 blink::WebMediaStreamSource::TypeAudio); 235 audio_track_observers_.push_back( 236 new RemoteAudioMediaStreamTrackAdapter(*it, new_track)); 237 webkit_stream_.addTrack(new_track); 238 } 239 } 240 241 // Find added video tracks. 242 webrtc::VideoTrackVector webrtc_video_tracks = 243 webrtc_stream_->GetVideoTracks(); 244 for (webrtc::VideoTrackVector::iterator it = webrtc_video_tracks.begin(); 245 it != webrtc_video_tracks.end(); ++it) { 246 if (!FindTrackObserver(*it, video_track_observers_)) { 247 blink::WebMediaStreamTrack new_track; 248 InitializeWebkitTrack(*it, &new_track, 249 blink::WebMediaStreamSource::TypeVideo); 250 video_track_observers_.push_back( 251 new RemoteMediaStreamTrackAdapter(*it, new_track)); 252 webkit_stream_.addTrack(new_track); 253 } 254 } 255 } 256 257 } // namespace content 258