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_extra_data.h" 12#include "third_party/WebKit/public/platform/WebString.h" 13 14namespace content { 15 16// RemoteMediaStreamTrackObserver is responsible for listening on change 17// notification on a remote webrtc MediaStreamTrack and notify WebKit. 18class RemoteMediaStreamTrackObserver 19 : NON_EXPORTED_BASE(public webrtc::ObserverInterface), 20 NON_EXPORTED_BASE(public base::NonThreadSafe) { 21 public: 22 RemoteMediaStreamTrackObserver( 23 webrtc::MediaStreamTrackInterface* webrtc_track, 24 const WebKit::WebMediaStreamTrack& webkit_track); 25 virtual ~RemoteMediaStreamTrackObserver(); 26 27 webrtc::MediaStreamTrackInterface* observered_track() { 28 return webrtc_track_.get(); 29 } 30 const WebKit::WebMediaStreamTrack& webkit_track() { return webkit_track_; } 31 32 private: 33 // webrtc::ObserverInterface implementation. 34 virtual void OnChanged() OVERRIDE; 35 36 webrtc::MediaStreamTrackInterface::TrackState state_; 37 scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track_; 38 WebKit::WebMediaStreamTrack webkit_track_; 39 40 DISALLOW_COPY_AND_ASSIGN(RemoteMediaStreamTrackObserver); 41}; 42 43} // namespace content 44 45namespace { 46 47void InitializeWebkitTrack(webrtc::MediaStreamTrackInterface* track, 48 WebKit::WebMediaStreamTrack* webkit_track, 49 WebKit::WebMediaStreamSource::Type type) { 50 WebKit::WebMediaStreamSource webkit_source; 51 WebKit::WebString webkit_track_id(UTF8ToUTF16(track->id())); 52 53 webkit_source.initialize(webkit_track_id, type, webkit_track_id); 54 webkit_track->initialize(webkit_track_id, webkit_source); 55} 56 57content::RemoteMediaStreamTrackObserver* FindTrackObserver( 58 webrtc::MediaStreamTrackInterface* track, 59 const ScopedVector<content::RemoteMediaStreamTrackObserver>& observers) { 60 ScopedVector<content::RemoteMediaStreamTrackObserver>::const_iterator it = 61 observers.begin(); 62 for (; it != observers.end(); ++it) { 63 if ((*it)->observered_track() == track) 64 return *it; 65 } 66 return NULL; 67} 68 69} // namespace anonymous 70 71namespace content { 72 73RemoteMediaStreamTrackObserver::RemoteMediaStreamTrackObserver( 74 webrtc::MediaStreamTrackInterface* webrtc_track, 75 const WebKit::WebMediaStreamTrack& webkit_track) 76 : state_(webrtc_track->state()), 77 webrtc_track_(webrtc_track), 78 webkit_track_(webkit_track) { 79 webrtc_track->RegisterObserver(this); 80} 81 82RemoteMediaStreamTrackObserver::~RemoteMediaStreamTrackObserver() { 83 webrtc_track_->UnregisterObserver(this); 84} 85 86void RemoteMediaStreamTrackObserver::OnChanged() { 87 DCHECK(CalledOnValidThread()); 88 89 webrtc::MediaStreamTrackInterface::TrackState state = webrtc_track_->state(); 90 if (state == state_) 91 return; 92 93 state_ = state; 94 switch (state) { 95 case webrtc::MediaStreamTrackInterface::kInitializing: 96 // Ignore the kInitializing state since there is no match in 97 // WebMediaStreamSource::ReadyState. 98 break; 99 case webrtc::MediaStreamTrackInterface::kLive: 100 webkit_track_.source().setReadyState( 101 WebKit::WebMediaStreamSource::ReadyStateLive); 102 break; 103 case webrtc::MediaStreamTrackInterface::kEnded: 104 webkit_track_.source().setReadyState( 105 WebKit::WebMediaStreamSource::ReadyStateEnded); 106 break; 107 default: 108 NOTREACHED(); 109 break; 110 } 111} 112 113RemoteMediaStreamImpl::RemoteMediaStreamImpl( 114 webrtc::MediaStreamInterface* webrtc_stream) 115 : webrtc_stream_(webrtc_stream) { 116 webrtc_stream_->RegisterObserver(this); 117 118 webrtc::AudioTrackVector webrtc_audio_tracks = 119 webrtc_stream_->GetAudioTracks(); 120 WebKit::WebVector<WebKit::WebMediaStreamTrack> webkit_audio_tracks( 121 webrtc_audio_tracks.size()); 122 123 // Initialize WebKit audio tracks. 124 size_t i = 0; 125 for (; i < webrtc_audio_tracks.size(); ++i) { 126 webrtc::AudioTrackInterface* audio_track = webrtc_audio_tracks[i]; 127 DCHECK(audio_track); 128 InitializeWebkitTrack(audio_track, &webkit_audio_tracks[i], 129 WebKit::WebMediaStreamSource::TypeAudio); 130 audio_track_observers_.push_back( 131 new RemoteMediaStreamTrackObserver(audio_track, 132 webkit_audio_tracks[i])); 133 } 134 135 // Initialize WebKit video tracks. 136 webrtc::VideoTrackVector webrtc_video_tracks = 137 webrtc_stream_->GetVideoTracks(); 138 WebKit::WebVector<WebKit::WebMediaStreamTrack> webkit_video_tracks( 139 webrtc_video_tracks.size()); 140 for (i = 0; i < webrtc_video_tracks.size(); ++i) { 141 webrtc::VideoTrackInterface* video_track = webrtc_video_tracks[i]; 142 DCHECK(video_track); 143 InitializeWebkitTrack(video_track, &webkit_video_tracks[i], 144 WebKit::WebMediaStreamSource::TypeVideo); 145 video_track_observers_.push_back( 146 new RemoteMediaStreamTrackObserver(video_track, 147 webkit_video_tracks[i])); 148 } 149 150 webkit_stream_.initialize(UTF8ToUTF16(webrtc_stream->label()), 151 webkit_audio_tracks, webkit_video_tracks); 152 webkit_stream_.setExtraData(new MediaStreamExtraData(webrtc_stream, false)); 153} 154 155RemoteMediaStreamImpl::~RemoteMediaStreamImpl() { 156 webrtc_stream_->UnregisterObserver(this); 157} 158 159void RemoteMediaStreamImpl::OnChanged() { 160 // Find removed audio tracks. 161 ScopedVector<RemoteMediaStreamTrackObserver>::iterator audio_it = 162 audio_track_observers_.begin(); 163 while (audio_it != audio_track_observers_.end()) { 164 std::string track_id = (*audio_it)->observered_track()->id(); 165 if (webrtc_stream_->FindAudioTrack(track_id) == NULL) { 166 webkit_stream_.removeTrack((*audio_it)->webkit_track()); 167 audio_it = audio_track_observers_.erase(audio_it); 168 } else { 169 ++audio_it; 170 } 171 } 172 173 // Find removed video tracks. 174 ScopedVector<RemoteMediaStreamTrackObserver>::iterator video_it = 175 video_track_observers_.begin(); 176 while (video_it != video_track_observers_.end()) { 177 std::string track_id = (*video_it)->observered_track()->id(); 178 if (webrtc_stream_->FindVideoTrack(track_id) == NULL) { 179 webkit_stream_.removeTrack((*video_it)->webkit_track()); 180 video_it = video_track_observers_.erase(video_it); 181 } else { 182 ++video_it; 183 } 184 } 185 186 // Find added audio tracks. 187 webrtc::AudioTrackVector webrtc_audio_tracks = 188 webrtc_stream_->GetAudioTracks(); 189 for (webrtc::AudioTrackVector::iterator it = webrtc_audio_tracks.begin(); 190 it != webrtc_audio_tracks.end(); ++it) { 191 if (!FindTrackObserver(*it, audio_track_observers_)) { 192 WebKit::WebMediaStreamTrack new_track; 193 InitializeWebkitTrack(*it, &new_track, 194 WebKit::WebMediaStreamSource::TypeAudio); 195 audio_track_observers_.push_back( 196 new RemoteMediaStreamTrackObserver(*it, new_track)); 197 webkit_stream_.addTrack(new_track); 198 } 199 } 200 201 // Find added video tracks. 202 webrtc::VideoTrackVector webrtc_video_tracks = 203 webrtc_stream_->GetVideoTracks(); 204 for (webrtc::VideoTrackVector::iterator it = webrtc_video_tracks.begin(); 205 it != webrtc_video_tracks.end(); ++it) { 206 if (!FindTrackObserver(*it, video_track_observers_)) { 207 WebKit::WebMediaStreamTrack new_track; 208 InitializeWebkitTrack(*it, &new_track, 209 WebKit::WebMediaStreamSource::TypeVideo); 210 video_track_observers_.push_back( 211 new RemoteMediaStreamTrackObserver(*it, new_track)); 212 webkit_stream_.addTrack(new_track); 213 } 214 } 215} 216 217} // namespace content 218