• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
InitializeWebkitTrack(webrtc::MediaStreamTrackInterface * track,blink::WebMediaStreamTrack * webkit_track,blink::WebMediaStreamSource::Type type)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:
RemoteMediaStreamTrackAdapter(webrtc::MediaStreamTrackInterface * webrtc_track,const blink::WebMediaStreamTrack & webkit_track)57   RemoteMediaStreamTrackAdapter(webrtc::MediaStreamTrackInterface* webrtc_track,
58                                 const blink::WebMediaStreamTrack& webkit_track)
59      : webrtc_track_(webrtc_track),
60        webkit_track_(webkit_track) {
61   }
62 
~RemoteMediaStreamTrackAdapter()63   virtual ~RemoteMediaStreamTrackAdapter() {
64   }
65 
observed_track()66   webrtc::MediaStreamTrackInterface* observed_track() {
67     return webrtc_track_.get();
68   }
69 
webkit_track()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 
FindTrackObserver(webrtc::MediaStreamTrackInterface * track,const ScopedVector<content::RemoteMediaStreamTrackAdapter> & observers)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 
RemoteAudioMediaStreamTrackAdapter(webrtc::MediaStreamTrackInterface * webrtc_track,const blink::WebMediaStreamTrack & webkit_track)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 
~RemoteAudioMediaStreamTrackAdapter()121 RemoteAudioMediaStreamTrackAdapter::~RemoteAudioMediaStreamTrackAdapter() {
122   observed_track()->UnregisterObserver(this);
123 }
124 
OnChanged()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 
RemoteMediaStreamImpl(webrtc::MediaStreamInterface * webrtc_stream)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 
~RemoteMediaStreamImpl()195 RemoteMediaStreamImpl::~RemoteMediaStreamImpl() {
196   webrtc_stream_->UnregisterObserver(this);
197 }
198 
OnChanged()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