// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "content/renderer/media/media_stream_center.h" #include <string> #include "base/command_line.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "content/common/media/media_stream_messages.h" #include "content/public/common/content_switches.h" #include "content/public/renderer/render_thread.h" #include "content/renderer/media/media_stream_dependency_factory.h" #include "content/renderer/media/media_stream_extra_data.h" #include "content/renderer/media/media_stream_source_extra_data.h" #include "content/renderer/media/media_stream_track_extra_data.h" #include "content/renderer/render_view_impl.h" #include "third_party/WebKit/public/platform/WebMediaStream.h" #include "third_party/WebKit/public/platform/WebMediaStreamCenterClient.h" #include "third_party/WebKit/public/platform/WebMediaStreamSource.h" #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" #include "third_party/WebKit/public/platform/WebMediaStreamTrackSourcesRequest.h" #include "third_party/WebKit/public/platform/WebSourceInfo.h" #include "third_party/WebKit/public/platform/WebVector.h" #include "third_party/WebKit/public/web/WebFrame.h" #include "third_party/libjingle/source/talk/app/webrtc/jsep.h" using blink::WebFrame; using blink::WebView; namespace content { MediaStreamCenter::MediaStreamCenter(blink::WebMediaStreamCenterClient* client, MediaStreamDependencyFactory* factory) : rtc_factory_(factory), next_request_id_(0) {} MediaStreamCenter::~MediaStreamCenter() {} bool MediaStreamCenter::getMediaStreamTrackSources( const blink::WebMediaStreamTrackSourcesRequest& request) { if (!CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableDeviceEnumeration)) { int request_id = next_request_id_++; requests_.insert(std::make_pair(request_id, request)); RenderThread::Get()->Send(new MediaStreamHostMsg_GetSources( request_id, GURL(request.origin().utf8()))); return true; } return false; } void MediaStreamCenter::didCreateMediaStreamTrack( const blink::WebMediaStreamTrack& track) { if (!rtc_factory_) return; rtc_factory_->CreateNativeMediaStreamTrack(track); } void MediaStreamCenter::didEnableMediaStreamTrack( const blink::WebMediaStreamTrack& track) { webrtc::MediaStreamTrackInterface* native_track = MediaStreamDependencyFactory::GetNativeMediaStreamTrack(track); if (native_track) native_track->set_enabled(true); } void MediaStreamCenter::didDisableMediaStreamTrack( const blink::WebMediaStreamTrack& track) { webrtc::MediaStreamTrackInterface* native_track = MediaStreamDependencyFactory::GetNativeMediaStreamTrack(track); if (native_track) native_track->set_enabled(false); } bool MediaStreamCenter::didStopMediaStreamTrack( const blink::WebMediaStreamTrack& track) { DVLOG(1) << "MediaStreamCenter::didStopMediaStreamTrack"; blink::WebMediaStreamSource source = track.source(); MediaStreamSourceExtraData* extra_data = static_cast<MediaStreamSourceExtraData*>(source.extraData()); if (!extra_data) { DVLOG(1) << "didStopMediaStreamTrack called on a remote track."; return false; } extra_data->OnLocalSourceStop(); return true; } void MediaStreamCenter::didStopLocalMediaStream( const blink::WebMediaStream& stream) { DVLOG(1) << "MediaStreamCenter::didStopLocalMediaStream"; MediaStreamExtraData* extra_data = static_cast<MediaStreamExtraData*>(stream.extraData()); if (!extra_data) { NOTREACHED(); return; } // TODO(perkj): MediaStream::Stop is being deprecated. But for the moment we // need to support the old behavior and the new. Since we only create one // source object per actual device- we need to fake stopping a // MediaStreamTrack by disabling it if the same device is used as source by // multiple tracks. Note that disabling a track here, don't affect the // enabled property in JS. blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; stream.audioTracks(audio_tracks); for (size_t i = 0; i < audio_tracks.size(); ++i) didDisableMediaStreamTrack(audio_tracks[i]); blink::WebVector<blink::WebMediaStreamTrack> video_tracks; stream.videoTracks(video_tracks); for (size_t i = 0; i < video_tracks.size(); ++i) didDisableMediaStreamTrack(video_tracks[i]); extra_data->OnLocalStreamStop(); } void MediaStreamCenter::didCreateMediaStream( blink::WebMediaStream& stream) { if (!rtc_factory_) return; rtc_factory_->CreateNativeLocalMediaStream(&stream); } bool MediaStreamCenter::didAddMediaStreamTrack( const blink::WebMediaStream& stream, const blink::WebMediaStreamTrack& track) { if (!rtc_factory_) return false; return rtc_factory_->AddNativeMediaStreamTrack(stream, track); } bool MediaStreamCenter::didRemoveMediaStreamTrack( const blink::WebMediaStream& stream, const blink::WebMediaStreamTrack& track) { if (!rtc_factory_) return false; return rtc_factory_->RemoveNativeMediaStreamTrack(stream, track); } bool MediaStreamCenter::OnControlMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(MediaStreamCenter, message) IPC_MESSAGE_HANDLER(MediaStreamMsg_GetSourcesACK, OnGetSourcesComplete) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; } void MediaStreamCenter::OnGetSourcesComplete( int request_id, const content::StreamDeviceInfoArray& devices) { RequestMap::iterator request_it = requests_.find(request_id); DCHECK(request_it != requests_.end()); blink::WebVector<blink::WebSourceInfo> sourceInfos(devices.size()); for (size_t i = 0; i < devices.size(); ++i) { const MediaStreamDevice& device = devices[i].device; DCHECK(device.type == MEDIA_DEVICE_AUDIO_CAPTURE || device.type == MEDIA_DEVICE_VIDEO_CAPTURE); blink::WebSourceInfo::VideoFacingMode video_facing; switch (device.video_facing) { case MEDIA_VIDEO_FACING_USER: video_facing = blink::WebSourceInfo::VideoFacingModeUser; break; case MEDIA_VIDEO_FACING_ENVIRONMENT: video_facing = blink::WebSourceInfo::VideoFacingModeEnvironment; break; default: video_facing = blink::WebSourceInfo::VideoFacingModeNone; } sourceInfos[i] .initialize(blink::WebString::fromUTF8(device.id), device.type == MEDIA_DEVICE_AUDIO_CAPTURE ? blink::WebSourceInfo::SourceKindAudio : blink::WebSourceInfo::SourceKindVideo, blink::WebString::fromUTF8(device.name), video_facing); } request_it->second.requestSucceeded(sourceInfos); } } // namespace content