15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/video_capture_manager.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 1046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/bind_helpers.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/message_loop/message_loop.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/task_runner_util.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/sequenced_worker_pool.h" 16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/media/capture/web_contents_video_capture_device.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/video_capture_controller.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/desktop_media_id.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/content_switches.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/media_stream_request.h" 2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "media/base/bind_to_current_loop.h" 24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "media/base/scoped_histogram_timer.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/video/capture/video_capture_device.h" 265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "media/video/capture/video_capture_device_factory.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#if defined(ENABLE_SCREEN_CAPTURE) 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/media/capture/desktop_capture_device.h" 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(USE_AURA) 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/media/capture/desktop_capture_device_aura.h" 32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif 3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 35effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochnamespace { 36effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 37effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Compares two VideoCaptureFormat by checking smallest frame_size area, then 38effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// by _largest_ frame_rate. Used to order a VideoCaptureFormats vector so that 39effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// the first entry for a given resolution has the largest frame rate, as needed 40effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// by the ConsolidateCaptureFormats() method. 41effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool IsCaptureFormatSmaller(const media::VideoCaptureFormat& format1, 42effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const media::VideoCaptureFormat& format2) { 43effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (format1.frame_size.GetArea() == format2.frame_size.GetArea()) 44effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return format1.frame_rate > format2.frame_rate; 45effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return format1.frame_size.GetArea() < format2.frame_size.GetArea(); 46effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 47effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 48effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool IsCaptureFormatSizeEqual(const media::VideoCaptureFormat& format1, 49effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const media::VideoCaptureFormat& format2) { 50effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return format1.frame_size.GetArea() == format2.frame_size.GetArea(); 51effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 52effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 53effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// This function receives a list of capture formats, removes duplicated 54effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// resolutions while keeping the highest frame rate for each, and forcing I420 55effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// pixel format. 56effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ConsolidateCaptureFormats(media::VideoCaptureFormats* formats) { 57effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (formats->empty()) 58effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 59effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::sort(formats->begin(), formats->end(), IsCaptureFormatSmaller); 60effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Due to the ordering imposed, the largest frame_rate is kept while removing 61effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // duplicated resolutions. 62effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch media::VideoCaptureFormats::iterator last = 63effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::unique(formats->begin(), formats->end(), IsCaptureFormatSizeEqual); 64effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch formats->erase(last, formats->end()); 65effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Mark all formats as I420, since this is what the renderer side will get 66effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // anyhow: the actual pixel format is decided at the device level. 67effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (media::VideoCaptureFormats::iterator it = formats->begin(); 68effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch it != formats->end(); ++it) { 69effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch it->pixel_format = media::PIXEL_FORMAT_I420; 70effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 71effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 72effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// The maximum number of buffers in the capture pipeline. See 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// VideoCaptureController ctor comments for more details. 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const int kMaxNumberOfBuffers = 3; 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const int kMaxNumberOfBuffersForTabCapture = 5; 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Used for logging capture events. 796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Elements in this enum should not be deleted or rearranged; the only 806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// permitted operation is to add new elements before NUM_VIDEO_CAPTURE_EVENT. 816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)enum VideoCaptureEvent { 826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) VIDEO_CAPTURE_EVENT_START_CAPTURE = 0, 836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) VIDEO_CAPTURE_EVENT_STOP_CAPTURE_NORMAL = 1, 846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) VIDEO_CAPTURE_EVENT_STOP_CAPTURE_DUE_TO_ERROR = 2, 856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) NUM_VIDEO_CAPTURE_EVENT 866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}; 876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void LogVideoCaptureEvent(VideoCaptureEvent event) { 896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Media.VideoCaptureManager.Event", 906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) event, 916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) NUM_VIDEO_CAPTURE_EVENT); 926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 94effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} // namespace 95effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 98d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)VideoCaptureManager::DeviceEntry::DeviceEntry( 99d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) MediaStreamType stream_type, 100d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::string& id, 101d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) scoped_ptr<VideoCaptureController> controller) 102d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) : stream_type(stream_type), 103d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) id(id), 104d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) video_capture_controller(controller.Pass()) {} 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 106d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)VideoCaptureManager::DeviceEntry::~DeviceEntry() {} 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)VideoCaptureManager::DeviceInfo::DeviceInfo() {} 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)VideoCaptureManager::DeviceInfo::DeviceInfo( 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const media::VideoCaptureDevice::Name& name, 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const media::VideoCaptureFormats& supported_formats) 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : name(name), 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) supported_formats(supported_formats) {} 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)VideoCaptureManager::DeviceInfo::~DeviceInfo() {} 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuVideoCaptureManager::VideoCaptureManager( 1195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu scoped_ptr<media::VideoCaptureDeviceFactory> factory) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : listener_(NULL), 1214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) new_capture_session_id_(1), 1225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu video_capture_device_factory_(factory.Pass()) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoCaptureManager::~VideoCaptureManager() { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(devices_.empty()); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void VideoCaptureManager::Register( 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MediaStreamProviderListener* listener, 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner) { 132effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!listener_); 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!device_task_runner_.get()); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listener_ = listener; 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_task_runner_ = device_task_runner; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoCaptureManager::Unregister() { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(listener_); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listener_ = NULL; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void VideoCaptureManager::EnumerateDevices(MediaStreamType stream_type) { 145effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 146d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DVLOG(1) << "VideoCaptureManager::EnumerateDevices, type " << stream_type; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(listener_); 14846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK_EQ(stream_type, MEDIA_DEVICE_VIDEO_CAPTURE); 14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Bind a callback to ConsolidateDevicesInfoOnDeviceThread() with an argument 15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // for another callback to OnDevicesInfoEnumerated() to be run in the current 15246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // loop, i.e. IO loop. Pass a timer for UMA histogram collection. 15346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Callback<void(scoped_ptr<media::VideoCaptureDevice::Names>)> 15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) devices_enumerated_callback = 15546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread, 15646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) this, 15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) media::BindToCurrentLoop(base::Bind( 15846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) &VideoCaptureManager::OnDevicesInfoEnumerated, 15946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) this, 16046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) stream_type, 16146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Owned(new base::ElapsedTimer()))), 16246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) stream_type, 16346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) devices_info_cache_); 16446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // OK to use base::Unretained() since we own the VCDFactory and |this| is 16546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // bound in |devices_enumerated_callback|. 16646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) device_task_runner_->PostTask(FROM_HERE, 16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&media::VideoCaptureDeviceFactory::EnumerateDeviceNames, 16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Unretained(video_capture_device_factory_.get()), 16946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) devices_enumerated_callback)); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 172d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int VideoCaptureManager::Open(const StreamDeviceInfo& device_info) { 173effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(listener_); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 176d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Generate a new id for the session being opened. 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const media::VideoCaptureSessionId capture_session_id = 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new_capture_session_id_++; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 180d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(sessions_.find(capture_session_id) == sessions_.end()); 181d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DVLOG(1) << "VideoCaptureManager::Open, id " << capture_session_id; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 183d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // We just save the stream info for processing later. 184d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) sessions_[capture_session_id] = device_info.device; 185d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 186d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Notify our listener asynchronously; this ensures that we return 187d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // |capture_session_id| to the caller of this function before using that same 188d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // id in a listener event. 189d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::MessageLoop::current()->PostTask(FROM_HERE, 190d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Bind(&VideoCaptureManager::OnOpened, this, 191d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) device_info.device.type, capture_session_id)); 192d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return capture_session_id; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VideoCaptureManager::Close(int capture_session_id) { 196effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(listener_); 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DVLOG(1) << "VideoCaptureManager::Close, id " << capture_session_id; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SessionMap::iterator session_it = sessions_.find(capture_session_id); 201d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (session_it == sessions_.end()) { 202d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NOTREACHED(); 203d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 204d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 206d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DeviceEntry* const existing_device = GetDeviceEntryForMediaStreamDevice( 207d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) session_it->second); 208d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (existing_device) { 209d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Remove any client that is still using the session. This is safe to call 210d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // even if there are no clients using the session. 211d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) existing_device->video_capture_controller->StopSession(capture_session_id); 212d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 213d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // StopSession() may have removed the last client, so we might need to 214d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // close the device. 215d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DestroyDeviceEntryIfNoClients(existing_device); 216d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 217d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 218d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Notify listeners asynchronously, and forget the session. 219d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::MessageLoop::current()->PostTask(FROM_HERE, 220d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Bind(&VideoCaptureManager::OnClosed, this, session_it->second.type, 221d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) capture_session_id)); 222d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) sessions_.erase(session_it); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void VideoCaptureManager::DoStartDeviceOnDeviceThread( 226effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch media::VideoCaptureSessionId session_id, 227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DeviceEntry* entry, 228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const media::VideoCaptureParams& params, 22968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) scoped_ptr<media::VideoCaptureDevice::Client> device_client) { 230d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime"); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsOnDeviceThread()); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 233ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch scoped_ptr<media::VideoCaptureDevice> video_capture_device; 234d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) switch (entry->stream_type) { 235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case MEDIA_DEVICE_VIDEO_CAPTURE: { 236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // We look up the device id from the renderer in our local enumeration 237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // since the renderer does not have all the information that might be 238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // held in the browser-side VideoCaptureDevice::Name structure. 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DeviceInfo* found = FindDeviceInfoById(entry->id, devices_info_cache_); 240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (found) { 2415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu video_capture_device = 24246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) video_capture_device_factory_->Create(found->name); 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case MEDIA_TAB_VIDEO_CAPTURE: { 247ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch video_capture_device.reset( 248d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WebContentsVideoCaptureDevice::Create(entry->id)); 249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 251ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch case MEDIA_DESKTOP_VIDEO_CAPTURE: { 2527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#if defined(ENABLE_SCREEN_CAPTURE) 253d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DesktopMediaID id = DesktopMediaID::Parse(entry->id); 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(USE_AURA) 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (id.type == DesktopMediaID::TYPE_AURA_WINDOW) { 256a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) video_capture_device.reset(DesktopCaptureDeviceAura::Create(id)); 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else 258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (id.type != DesktopMediaID::TYPE_NONE && 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) id.type != DesktopMediaID::TYPE_AURA_WINDOW) { 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) video_capture_device = DesktopCaptureDevice::Create(id); 262effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (notification_window_ids_.find(session_id) != 263effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch notification_window_ids_.end()) { 264effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch static_cast<DesktopCaptureDevice*>(video_capture_device.get()) 265effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ->SetNotificationWindowId(notification_window_ids_[session_id]); 2661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(2) << "Screen capture notification window passed for session " 2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << session_id; 268effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 269ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 2707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#endif // defined(ENABLE_SCREEN_CAPTURE) 271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch default: { 274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NOTIMPLEMENTED(); 275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!video_capture_device) { 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_client->OnError("Could not create capture device"); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) video_capture_device->AllocateAndStart(params, device_client.Pass()); 285d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) entry->video_capture_device = video_capture_device.Pass(); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 288d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void VideoCaptureManager::StartCaptureForClient( 289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) media::VideoCaptureSessionId session_id, 2901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const media::VideoCaptureParams& params, 291d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::ProcessHandle client_render_process, 292d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) VideoCaptureControllerID client_id, 293d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) VideoCaptureControllerEventHandler* client_handler, 294d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const DoneCB& done_cb) { 295effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 296f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DVLOG(1) << "VideoCaptureManager::StartCaptureForClient, " 297f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) << params.requested_format.frame_size.ToString() << ", " 298f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) << params.requested_format.frame_rate << ", #" << session_id << ")"; 299f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 300f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DeviceEntry* entry = GetOrCreateDeviceEntry(session_id); 301d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!entry) { 302d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) done_cb.Run(base::WeakPtr<VideoCaptureController>()); 303d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 306d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(entry->video_capture_controller); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) LogVideoCaptureEvent(VIDEO_CAPTURE_EVENT_START_CAPTURE); 3096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 310d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // First client starts the device. 31134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (entry->video_capture_controller->GetActiveClientCount() == 0) { 312d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DVLOG(1) << "VideoCaptureManager starting device (type = " 313d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << entry->stream_type << ", id = " << entry->id << ")"; 314d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_task_runner_->PostTask( 316f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) FROM_HERE, 317f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Bind( 318f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) &VideoCaptureManager::DoStartDeviceOnDeviceThread, 319f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) this, 320effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch session_id, 321f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) entry, 322f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) params, 323f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Passed(entry->video_capture_controller->NewDeviceClient()))); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 325d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Run the callback first, as AddClient() may trigger OnFrameInfo(). 326d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) done_cb.Run(entry->video_capture_controller->GetWeakPtr()); 327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) entry->video_capture_controller->AddClient( 328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) client_id, client_handler, client_render_process, session_id, params); 329d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 330d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 331d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void VideoCaptureManager::StopCaptureForClient( 332d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) VideoCaptureController* controller, 333d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) VideoCaptureControllerID client_id, 3345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu VideoCaptureControllerEventHandler* client_handler, 3355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu bool aborted_due_to_error) { 336effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 337d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(controller); 338d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(client_handler); 339d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 3406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) LogVideoCaptureEvent(aborted_due_to_error ? 3416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) VIDEO_CAPTURE_EVENT_STOP_CAPTURE_DUE_TO_ERROR : 3426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) VIDEO_CAPTURE_EVENT_STOP_CAPTURE_NORMAL); 3436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 344d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DeviceEntry* entry = GetDeviceEntryForController(controller); 345d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!entry) { 346d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NOTREACHED(); 347a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 348a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 3495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (aborted_due_to_error) { 3505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SessionMap::iterator it; 3515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (it = sessions_.begin(); it != sessions_.end(); ++it) { 3525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (it->second.type == entry->stream_type && 3535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu it->second.id == entry->id) { 3545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu listener_->Aborted(it->second.type, it->first); 3555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu break; 3565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 3575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 3585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 360d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Detach client from controller. 3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) media::VideoCaptureSessionId session_id = 3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller->RemoveClient(client_id, client_handler); 363d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DVLOG(1) << "VideoCaptureManager::StopCaptureForClient, session_id = " 364d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << session_id; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 366d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // If controller has no more clients, delete controller and device. 367d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DestroyDeviceEntryIfNoClients(entry); 368d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 37034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)void VideoCaptureManager::PauseCaptureForClient( 37134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) VideoCaptureController* controller, 37234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) VideoCaptureControllerID client_id, 37334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) VideoCaptureControllerEventHandler* client_handler) { 37434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::IO); 37534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) DCHECK(controller); 37634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) DCHECK(client_handler); 37734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) DeviceEntry* entry = GetDeviceEntryForController(controller); 37834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (!entry) { 37934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) NOTREACHED(); 38034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) return; 38134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 38234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 38334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) // We only pause the MEDIA_DEVICE_VIDEO_CAPTURE entry to release camera to 38434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) // system. 38534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE) 38634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) return; 38734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 38834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) controller->PauseOrResumeClient(client_id, client_handler, true); 38934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (controller->GetActiveClientCount() != 0) 39034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) return; 39134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 39234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) // There is no more client, release the camera. 39334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) device_task_runner_->PostTask( 39434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) FROM_HERE, 39534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, 39634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) base::Unretained(entry))); 39734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)} 39834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 39934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)void VideoCaptureManager::ResumeCaptureForClient( 40034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) media::VideoCaptureSessionId session_id, 40134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) const media::VideoCaptureParams& params, 40234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) VideoCaptureController* controller, 40334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) VideoCaptureControllerID client_id, 40434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) VideoCaptureControllerEventHandler* client_handler) { 40534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::IO); 40634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) DCHECK(controller); 40734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) DCHECK(client_handler); 40834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 40934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) DeviceEntry* entry = GetDeviceEntryForController(controller); 41034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (!entry) { 41134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) NOTREACHED(); 41234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) return; 41334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) } 41434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 41534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) // We only pause/resume the MEDIA_DEVICE_VIDEO_CAPTURE entry. 41634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE) 41734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) return; 41834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 41934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) controller->PauseOrResumeClient(client_id, client_handler, false); 42034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) if (controller->GetActiveClientCount() != 1) 42134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) return; 42234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 42334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) // This is first active client, allocate the camera. 42434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) device_task_runner_->PostTask( 42534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) FROM_HERE, 42634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) base::Bind( 42734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) &VideoCaptureManager::DoStartDeviceOnDeviceThread, 42834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) this, 42934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) session_id, 43034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) entry, 43134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) params, 43234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) base::Passed(entry->video_capture_controller->NewDeviceClient()))); 43334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)} 43434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) 4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool VideoCaptureManager::GetDeviceSupportedFormats( 4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) media::VideoCaptureSessionId capture_session_id, 4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) media::VideoCaptureFormats* supported_formats) { 438effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(supported_formats->empty()); 4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SessionMap::iterator it = sessions_.find(capture_session_id); 4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (it == sessions_.end()) 4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "GetDeviceSupportedFormats for device: " << it->second.name; 4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Return all available formats of the device, regardless its started state. 4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DeviceInfo* existing_device = 4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FindDeviceInfoById(it->second.id, devices_info_cache_); 4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (existing_device) 4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *supported_formats = existing_device->supported_formats; 4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool VideoCaptureManager::GetDeviceFormatsInUse( 4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) media::VideoCaptureSessionId capture_session_id, 4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) media::VideoCaptureFormats* formats_in_use) { 457effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(formats_in_use->empty()); 4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SessionMap::iterator it = sessions_.find(capture_session_id); 4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (it == sessions_.end()) 4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "GetDeviceFormatsInUse for device: " << it->second.name; 4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Return the currently in-use format(s) of the device, if it's started. 4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DeviceEntry* device_in_use = 4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetDeviceEntryForMediaStreamDevice(it->second); 4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (device_in_use) { 4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Currently only one format-in-use is supported at the VCC level. 4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) formats_in_use->push_back( 4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_in_use->video_capture_controller->GetVideoCaptureFormat()); 4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 476effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid VideoCaptureManager::SetDesktopCaptureWindowId( 477effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch media::VideoCaptureSessionId session_id, 478effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch gfx::NativeViewId window_id) { 479effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 4801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(2) << "SetDesktopCaptureWindowId called for session " << session_id; 4811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SessionMap::iterator session_it = sessions_.find(session_id); 483effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (session_it == sessions_.end()) { 4841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(2) << "Session not found, will save the notification window."; 485effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch device_task_runner_->PostTask( 486effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch FROM_HERE, 487effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Bind( 488effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch &VideoCaptureManager::SaveDesktopCaptureWindowIdOnDeviceThread, 489effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch this, 490effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch session_id, 491effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch window_id)); 492effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 493effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 494effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 495effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DeviceEntry* const existing_device = 496effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch GetDeviceEntryForMediaStreamDevice(session_it->second); 4971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!existing_device) { 4981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(2) << "Failed to find an existing device."; 499effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 5001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 501effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 502effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_EQ(MEDIA_DESKTOP_VIDEO_CAPTURE, existing_device->stream_type); 503effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DesktopMediaID id = DesktopMediaID::Parse(existing_device->id); 504effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (id.type == DesktopMediaID::TYPE_NONE || 505effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch id.type == DesktopMediaID::TYPE_AURA_WINDOW) { 5061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(2) << "Video capture device type mismatch."; 507effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 508effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 509effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 510effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch device_task_runner_->PostTask( 511effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch FROM_HERE, 512effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Bind(&VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread, 513effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch this, 514effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch existing_device, 515effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch window_id)); 516effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 517effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 518d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void VideoCaptureManager::DoStopDeviceOnDeviceThread(DeviceEntry* entry) { 519d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime"); 520d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(IsOnDeviceThread()); 521d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (entry->video_capture_device) { 522d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) entry->video_capture_device->StopAndDeAllocate(); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 524d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) entry->video_capture_device.reset(); 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void VideoCaptureManager::OnOpened( 5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MediaStreamType stream_type, 5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) media::VideoCaptureSessionId capture_session_id) { 530effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!listener_) { 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Listener has been removed. 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listener_->Opened(stream_type, capture_session_id); 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void VideoCaptureManager::OnClosed( 5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MediaStreamType stream_type, 5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) media::VideoCaptureSessionId capture_session_id) { 541effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!listener_) { 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Listener has been removed. 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listener_->Closed(stream_type, capture_session_id); 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void VideoCaptureManager::OnDevicesInfoEnumerated( 5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MediaStreamType stream_type, 55146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::ElapsedTimer* timer, 5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const DeviceInfos& new_devices_info_cache) { 553effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 55446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) UMA_HISTOGRAM_TIMES( 55546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "Media.VideoCaptureManager.GetAvailableDevicesInfoOnDeviceThreadTime", 55646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) timer->Elapsed()); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!listener_) { 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Listener has been removed. 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) devices_info_cache_ = new_devices_info_cache; 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Walk the |devices_info_cache_| and transform from VCD::Name to 5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // StreamDeviceInfo for return purposes. 565d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) StreamDeviceInfoArray devices; 5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (DeviceInfos::const_iterator it = devices_info_cache_.begin(); 5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != devices_info_cache_.end(); ++it) { 568d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) devices.push_back(StreamDeviceInfo( 5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) stream_type, it->name.GetNameAndModel(), it->name.id())); 570d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 571d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) listener_->DevicesEnumerated(stream_type, devices); 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VideoCaptureManager::IsOnDeviceThread() const { 5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return device_task_runner_->BelongsToCurrentThread(); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 57846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread( 57946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Callback<void(const DeviceInfos&)> on_devices_enumerated_callback, 5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MediaStreamType stream_type, 58146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const DeviceInfos& old_device_info_cache, 58246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<media::VideoCaptureDevice::Names> names_snapshot) { 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsOnDeviceThread()); 5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Construct |new_devices_info_cache| with the cached devices that are still 5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // present in the system, and remove their names from |names_snapshot|, so we 5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // keep there the truly new devices. 5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DeviceInfos new_devices_info_cache; 5885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (DeviceInfos::const_iterator it_device_info = 5895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) old_device_info_cache.begin(); 5905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it_device_info != old_device_info_cache.end(); ++it_device_info) { 5915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (media::VideoCaptureDevice::Names::iterator it = 59246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) names_snapshot->begin(); 59346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) it != names_snapshot->end(); ++it) { 5945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (it_device_info->name.id() == it->id()) { 5955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new_devices_info_cache.push_back(*it_device_info); 59646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) names_snapshot->erase(it); 5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 5985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Get the supported capture formats for the new devices in |names_snapshot|. 6035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (media::VideoCaptureDevice::Names::const_iterator it = 60446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) names_snapshot->begin(); 60546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) it != names_snapshot->end(); ++it) { 6065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) media::VideoCaptureFormats supported_formats; 6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DeviceInfo device_info(*it, media::VideoCaptureFormats()); 6085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu video_capture_device_factory_->GetDeviceSupportedFormats( 6095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu *it, &(device_info.supported_formats)); 610effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ConsolidateCaptureFormats(&device_info.supported_formats); 6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new_devices_info_cache.push_back(device_info); 6125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 61346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 61446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) on_devices_enumerated_callback.Run(new_devices_info_cache); 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 617d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)VideoCaptureManager::DeviceEntry* 618d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)VideoCaptureManager::GetDeviceEntryForMediaStreamDevice( 619d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const MediaStreamDevice& device_info) { 620effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 622d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (DeviceEntries::iterator it = devices_.begin(); 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != devices_.end(); ++it) { 624d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DeviceEntry* device = *it; 625d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (device_info.type == device->stream_type && 626d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) device_info.id == device->id) { 627d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return device; 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 633d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)VideoCaptureManager::DeviceEntry* 634d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)VideoCaptureManager::GetDeviceEntryForController( 6355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const VideoCaptureController* controller) const { 636d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Look up |controller| in |devices_|. 6375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (DeviceEntries::const_iterator it = devices_.begin(); 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != devices_.end(); ++it) { 639d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if ((*it)->video_capture_controller.get() == controller) { 640d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return *it; 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 643d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return NULL; 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 646d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void VideoCaptureManager::DestroyDeviceEntryIfNoClients(DeviceEntry* entry) { 647effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 648d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Removal of the last client stops the device. 649d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (entry->video_capture_controller->GetClientCount() == 0) { 650d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DVLOG(1) << "VideoCaptureManager stopping device (type = " 651d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << entry->stream_type << ", id = " << entry->id << ")"; 652d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 653d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // The DeviceEntry is removed from |devices_| immediately. The controller is 654d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // deleted immediately, and the device is freed asynchronously. After this 655d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // point, subsequent requests to open this same device ID will create a new 656d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // DeviceEntry, VideoCaptureController, and VideoCaptureDevice. 657d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) devices_.erase(entry); 658d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) entry->video_capture_controller.reset(); 6595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_task_runner_->PostTask( 660d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FROM_HERE, 661d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, 662d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Owned(entry))); 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 664d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 666d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry( 6675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) media::VideoCaptureSessionId capture_session_id) { 668effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::IO); 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SessionMap::iterator session_it = sessions_.find(capture_session_id); 671d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (session_it == sessions_.end()) { 672d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return NULL; 673d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 674d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const MediaStreamDevice& device_info = session_it->second; 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 676d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Check if another session has already opened this device. If so, just 677d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // use that opened device. 678d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DeviceEntry* const existing_device = 6795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetDeviceEntryForMediaStreamDevice(device_info); 680d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (existing_device) { 681d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK_EQ(device_info.type, existing_device->stream_type); 682d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return existing_device; 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 684d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 6855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int max_buffers = device_info.type == MEDIA_TAB_VIDEO_CAPTURE ? 6865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kMaxNumberOfBuffersForTabCapture : kMaxNumberOfBuffers; 687d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) scoped_ptr<VideoCaptureController> video_capture_controller( 6885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new VideoCaptureController(max_buffers)); 689d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DeviceEntry* new_device = new DeviceEntry(device_info.type, 690d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) device_info.id, 691d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) video_capture_controller.Pass()); 692d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) devices_.insert(new_device); 693d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return new_device; 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)VideoCaptureManager::DeviceInfo* VideoCaptureManager::FindDeviceInfoById( 6975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& id, 6985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DeviceInfos& device_vector) { 6995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (DeviceInfos::iterator it = device_vector.begin(); 7005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != device_vector.end(); ++it) { 7015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (it->name.id() == id) 7025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return &(*it); 7035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 7045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return NULL; 7055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 707effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread( 708effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DeviceEntry* entry, 709effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch gfx::NativeViewId window_id) { 710effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(IsOnDeviceThread()); 711effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(entry->stream_type == MEDIA_DESKTOP_VIDEO_CAPTURE); 712effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#if defined(ENABLE_SCREEN_CAPTURE) 713effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DesktopCaptureDevice* device = 714effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch static_cast<DesktopCaptureDevice*>(entry->video_capture_device.get()); 715effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch device->SetNotificationWindowId(window_id); 7161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(2) << "Screen capture notification window passed on device thread."; 717effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#endif 718effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 719effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 720effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid VideoCaptureManager::SaveDesktopCaptureWindowIdOnDeviceThread( 721effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch media::VideoCaptureSessionId session_id, 722effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch gfx::NativeViewId window_id) { 723effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(IsOnDeviceThread()); 724effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(notification_window_ids_.find(session_id) == 725effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch notification_window_ids_.end()); 726effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch notification_window_ids_[session_id] = window_id; 7271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(2) << "Screen capture notification window saved for session " 7281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << session_id << " on device thread."; 729effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 730effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 732