Home | History | Annotate | Download | only in media
      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