Home | History | Annotate | Download | only in media
      1 // Copyright (c) 2012 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/media_stream_center.h"
      6 
      7 #include <string>
      8 
      9 #include "base/command_line.h"
     10 #include "base/logging.h"
     11 #include "content/common/media/media_stream_messages.h"
     12 #include "content/public/common/content_switches.h"
     13 #include "content/public/renderer/media_stream_audio_sink.h"
     14 #include "content/public/renderer/render_thread.h"
     15 #include "content/renderer/media/media_stream.h"
     16 #include "content/renderer/media/media_stream_source.h"
     17 #include "content/renderer/media/media_stream_video_source.h"
     18 #include "content/renderer/media/media_stream_video_track.h"
     19 #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
     20 #include "content/renderer/media/webrtc_local_audio_source_provider.h"
     21 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
     22 #include "third_party/WebKit/public/platform/WebMediaStream.h"
     23 #include "third_party/WebKit/public/platform/WebMediaStreamCenterClient.h"
     24 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
     25 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
     26 #include "third_party/WebKit/public/platform/WebMediaStreamTrackSourcesRequest.h"
     27 #include "third_party/WebKit/public/platform/WebSourceInfo.h"
     28 #include "third_party/WebKit/public/platform/WebVector.h"
     29 #include "third_party/WebKit/public/web/WebFrame.h"
     30 
     31 using blink::WebFrame;
     32 using blink::WebView;
     33 
     34 namespace content {
     35 
     36 namespace {
     37 
     38 void CreateNativeAudioMediaStreamTrack(
     39     const blink::WebMediaStreamTrack& track,
     40     PeerConnectionDependencyFactory* factory) {
     41   DCHECK(!track.extraData());
     42   blink::WebMediaStreamSource source = track.source();
     43   DCHECK_EQ(source.type(), blink::WebMediaStreamSource::TypeAudio);
     44   factory->CreateLocalAudioTrack(track);
     45 }
     46 
     47 void CreateNativeVideoMediaStreamTrack(
     48     const blink::WebMediaStreamTrack& track) {
     49   DCHECK(track.extraData() == NULL);
     50   blink::WebMediaStreamSource source = track.source();
     51   DCHECK_EQ(source.type(), blink::WebMediaStreamSource::TypeVideo);
     52   MediaStreamVideoSource* native_source =
     53       MediaStreamVideoSource::GetVideoSource(source);
     54   DCHECK(native_source);
     55   blink::WebMediaStreamTrack writable_track(track);
     56   // TODO(perkj): The constraints to use here should be passed from blink when
     57   // a new track is created. For cloning, it should be the constraints of the
     58   // cloned track and not the originating source.
     59   // Also - source.constraints() returns an uninitialized constraint if the
     60   // source is coming from a remote video track. See http://crbug/287805.
     61   blink::WebMediaConstraints constraints = source.constraints();
     62   if (constraints.isNull())
     63     constraints.initialize();
     64   writable_track.setExtraData(
     65       new MediaStreamVideoTrack(native_source, constraints,
     66                                 MediaStreamVideoSource::ConstraintsCallback(),
     67                                 track.isEnabled()));
     68 }
     69 
     70 void CreateNativeMediaStreamTrack(const blink::WebMediaStreamTrack& track,
     71                                   PeerConnectionDependencyFactory* factory) {
     72   DCHECK(!track.isNull() && !track.extraData());
     73   DCHECK(!track.source().isNull());
     74 
     75   switch (track.source().type()) {
     76     case blink::WebMediaStreamSource::TypeAudio:
     77       CreateNativeAudioMediaStreamTrack(track, factory);
     78       break;
     79     case blink::WebMediaStreamSource::TypeVideo:
     80       CreateNativeVideoMediaStreamTrack(track);
     81       break;
     82   }
     83 }
     84 
     85 }  // namespace
     86 
     87 MediaStreamCenter::MediaStreamCenter(blink::WebMediaStreamCenterClient* client,
     88                                      PeerConnectionDependencyFactory* factory)
     89     : rtc_factory_(factory), next_request_id_(0) {}
     90 
     91 MediaStreamCenter::~MediaStreamCenter() {}
     92 
     93 bool MediaStreamCenter::getMediaStreamTrackSources(
     94     const blink::WebMediaStreamTrackSourcesRequest& request) {
     95   if (!CommandLine::ForCurrentProcess()->HasSwitch(
     96       switches::kDisableDeviceEnumeration)) {
     97     int request_id = next_request_id_++;
     98     requests_.insert(std::make_pair(request_id, request));
     99     RenderThread::Get()->Send(new MediaStreamHostMsg_GetSources(
    100         request_id, GURL(request.origin().utf8())));
    101     return true;
    102   }
    103   return false;
    104 }
    105 
    106 void MediaStreamCenter::didCreateMediaStreamTrack(
    107     const blink::WebMediaStreamTrack& track) {
    108   DVLOG(1) << "MediaStreamCenter::didCreateMediaStreamTrack";
    109   CreateNativeMediaStreamTrack(track, rtc_factory_);
    110 }
    111 
    112 void MediaStreamCenter::didEnableMediaStreamTrack(
    113     const blink::WebMediaStreamTrack& track) {
    114   MediaStreamTrack* native_track =
    115       MediaStreamTrack::GetTrack(track);
    116   if (native_track)
    117     native_track->SetEnabled(true);
    118 }
    119 
    120 void MediaStreamCenter::didDisableMediaStreamTrack(
    121     const blink::WebMediaStreamTrack& track) {
    122   MediaStreamTrack* native_track =
    123       MediaStreamTrack::GetTrack(track);
    124   if (native_track)
    125     native_track->SetEnabled(false);
    126 }
    127 
    128 bool MediaStreamCenter::didStopMediaStreamTrack(
    129     const blink::WebMediaStreamTrack& track) {
    130   DVLOG(1) << "MediaStreamCenter::didStopMediaStreamTrack";
    131   MediaStreamTrack* native_track = MediaStreamTrack::GetTrack(track);
    132   native_track->Stop();
    133   return true;
    134 }
    135 
    136 blink::WebAudioSourceProvider*
    137 MediaStreamCenter::createWebAudioSourceFromMediaStreamTrack(
    138     const blink::WebMediaStreamTrack& track) {
    139   DVLOG(1) << "MediaStreamCenter::createWebAudioSourceFromMediaStreamTrack";
    140   MediaStreamTrack* media_stream_track =
    141       static_cast<MediaStreamTrack*>(track.extraData());
    142   // Only local audio track is supported now.
    143   // TODO(xians): Support remote audio track.
    144   if (!media_stream_track || !media_stream_track->is_local_track()) {
    145     NOTIMPLEMENTED();
    146     return NULL;
    147   }
    148 
    149   blink::WebMediaStreamSource source = track.source();
    150   DCHECK_EQ(source.type(), blink::WebMediaStreamSource::TypeAudio);
    151   WebRtcLocalAudioSourceProvider* source_provider =
    152       new WebRtcLocalAudioSourceProvider(track);
    153   return source_provider;
    154 }
    155 
    156 void MediaStreamCenter::didStopLocalMediaStream(
    157     const blink::WebMediaStream& stream) {
    158   DVLOG(1) << "MediaStreamCenter::didStopLocalMediaStream";
    159   MediaStream* native_stream = MediaStream::GetMediaStream(stream);
    160   if (!native_stream) {
    161     NOTREACHED();
    162     return;
    163   }
    164 
    165   // TODO(perkj): MediaStream::Stop is being deprecated. But for the moment we
    166   // need to support both MediaStream::Stop and MediaStreamTrack::Stop.
    167   blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
    168   stream.audioTracks(audio_tracks);
    169   for (size_t i = 0; i < audio_tracks.size(); ++i)
    170     didStopMediaStreamTrack(audio_tracks[i]);
    171 
    172   blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
    173   stream.videoTracks(video_tracks);
    174   for (size_t i = 0; i < video_tracks.size(); ++i)
    175     didStopMediaStreamTrack(video_tracks[i]);
    176 }
    177 
    178 void MediaStreamCenter::didCreateMediaStream(blink::WebMediaStream& stream) {
    179   DVLOG(1) << "MediaStreamCenter::didCreateMediaStream";
    180   blink::WebMediaStream writable_stream(stream);
    181   MediaStream* native_stream(
    182       new MediaStream(stream));
    183   writable_stream.setExtraData(native_stream);
    184 
    185   blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
    186   stream.videoTracks(video_tracks);
    187   for (size_t i = 0; i < video_tracks.size(); ++i) {
    188     if (!MediaStreamTrack::GetTrack(video_tracks[i]))
    189       CreateNativeMediaStreamTrack(video_tracks[i], rtc_factory_);
    190   }
    191 }
    192 
    193 bool MediaStreamCenter::didAddMediaStreamTrack(
    194     const blink::WebMediaStream& stream,
    195     const blink::WebMediaStreamTrack& track) {
    196   DVLOG(1) << "MediaStreamCenter::didAddMediaStreamTrack";
    197   MediaStream* native_stream = MediaStream::GetMediaStream(stream);
    198   return native_stream->AddTrack(track);
    199 }
    200 
    201 bool MediaStreamCenter::didRemoveMediaStreamTrack(
    202     const blink::WebMediaStream& stream,
    203     const blink::WebMediaStreamTrack& track) {
    204   DVLOG(1) << "MediaStreamCenter::didRemoveMediaStreamTrack";
    205   MediaStream* native_stream = MediaStream::GetMediaStream(stream);
    206   return native_stream->RemoveTrack(track);
    207 }
    208 
    209 bool MediaStreamCenter::OnControlMessageReceived(const IPC::Message& message) {
    210   bool handled = true;
    211   IPC_BEGIN_MESSAGE_MAP(MediaStreamCenter, message)
    212     IPC_MESSAGE_HANDLER(MediaStreamMsg_GetSourcesACK,
    213                         OnGetSourcesComplete)
    214     IPC_MESSAGE_UNHANDLED(handled = false)
    215   IPC_END_MESSAGE_MAP()
    216   return handled;
    217 }
    218 
    219 void MediaStreamCenter::OnGetSourcesComplete(
    220     int request_id,
    221     const content::StreamDeviceInfoArray& devices) {
    222   RequestMap::iterator request_it = requests_.find(request_id);
    223   DCHECK(request_it != requests_.end());
    224 
    225   blink::WebVector<blink::WebSourceInfo> sourceInfos(devices.size());
    226   for (size_t i = 0; i < devices.size(); ++i) {
    227     const MediaStreamDevice& device = devices[i].device;
    228     DCHECK(device.type == MEDIA_DEVICE_AUDIO_CAPTURE ||
    229            device.type == MEDIA_DEVICE_VIDEO_CAPTURE);
    230     blink::WebSourceInfo::VideoFacingMode video_facing;
    231     switch (device.video_facing) {
    232       case MEDIA_VIDEO_FACING_USER:
    233         video_facing = blink::WebSourceInfo::VideoFacingModeUser;
    234         break;
    235       case MEDIA_VIDEO_FACING_ENVIRONMENT:
    236         video_facing = blink::WebSourceInfo::VideoFacingModeEnvironment;
    237         break;
    238       default:
    239         video_facing = blink::WebSourceInfo::VideoFacingModeNone;
    240     }
    241 
    242     sourceInfos[i]
    243         .initialize(blink::WebString::fromUTF8(device.id),
    244                     device.type == MEDIA_DEVICE_AUDIO_CAPTURE
    245                         ? blink::WebSourceInfo::SourceKindAudio
    246                         : blink::WebSourceInfo::SourceKindVideo,
    247                     blink::WebString::fromUTF8(device.name),
    248                     video_facing);
    249   }
    250   request_it->second.requestSucceeded(sourceInfos);
    251 }
    252 
    253 }  // namespace content
    254