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/pepper/pepper_media_device_manager.h" 6 7#include "base/logging.h" 8#include "content/renderer/media/media_stream_dispatcher.h" 9#include "content/renderer/render_view_impl.h" 10#include "ppapi/shared_impl/ppb_device_ref_shared.h" 11 12namespace content { 13 14namespace { 15 16ppapi::DeviceRefData FromStreamDeviceInfo(const StreamDeviceInfo& info) { 17 ppapi::DeviceRefData data; 18 data.id = info.device.id; 19 data.name = info.device.name; 20 data.type = PepperMediaDeviceManager::FromMediaStreamType(info.device.type); 21 return data; 22} 23 24} // namespace 25 26PepperMediaDeviceManager* PepperMediaDeviceManager::GetForRenderView( 27 RenderView* render_view) { 28 PepperMediaDeviceManager* handler = 29 PepperMediaDeviceManager::Get(render_view); 30 if (!handler) 31 handler = new PepperMediaDeviceManager(render_view); 32 return handler; 33} 34 35PepperMediaDeviceManager::PepperMediaDeviceManager(RenderView* render_view) 36 : RenderViewObserver(render_view), 37 RenderViewObserverTracker<PepperMediaDeviceManager>(render_view), 38 next_id_(1) {} 39 40PepperMediaDeviceManager::~PepperMediaDeviceManager() { 41 DCHECK(enumerate_callbacks_.empty()); 42 DCHECK(open_callbacks_.empty()); 43} 44 45int PepperMediaDeviceManager::EnumerateDevices( 46 PP_DeviceType_Dev type, 47 const GURL& document_url, 48 const EnumerateDevicesCallback& callback) { 49 enumerate_callbacks_[next_id_] = callback; 50 int request_id = next_id_++; 51 52#if defined(ENABLE_WEBRTC) 53 GetRenderViewImpl()->media_stream_dispatcher()->EnumerateDevices( 54 request_id, 55 AsWeakPtr(), 56 PepperMediaDeviceManager::FromPepperDeviceType(type), 57 document_url.GetOrigin(), 58 false); 59#else 60 base::MessageLoop::current()->PostTask( 61 FROM_HERE, 62 base::Bind(&PepperMediaDeviceManager::OnDevicesEnumerated, 63 AsWeakPtr(), 64 request_id, 65 StreamDeviceInfoArray())); 66#endif 67 68 return request_id; 69} 70 71void PepperMediaDeviceManager::StopEnumerateDevices(int request_id) { 72 enumerate_callbacks_.erase(request_id); 73 74#if defined(ENABLE_WEBRTC) 75 // Need to post task since this function might be called inside the callback 76 // of EnumerateDevices. 77 base::MessageLoop::current()->PostTask( 78 FROM_HERE, 79 base::Bind(&MediaStreamDispatcher::StopEnumerateDevices, 80 GetRenderViewImpl()->media_stream_dispatcher()->AsWeakPtr(), 81 request_id, 82 AsWeakPtr())); 83#endif 84} 85 86int PepperMediaDeviceManager::OpenDevice(PP_DeviceType_Dev type, 87 const std::string& device_id, 88 const GURL& document_url, 89 const OpenDeviceCallback& callback) { 90 open_callbacks_[next_id_] = callback; 91 int request_id = next_id_++; 92 93#if defined(ENABLE_WEBRTC) 94 GetRenderViewImpl()->media_stream_dispatcher()->OpenDevice( 95 request_id, 96 AsWeakPtr(), 97 device_id, 98 PepperMediaDeviceManager::FromPepperDeviceType(type), 99 document_url.GetOrigin()); 100#else 101 base::MessageLoop::current()->PostTask( 102 FROM_HERE, 103 base::Bind(&PepperMediaDeviceManager::OnDeviceOpenFailed, 104 AsWeakPtr(), 105 request_id)); 106#endif 107 108 return request_id; 109} 110 111void PepperMediaDeviceManager::CancelOpenDevice(int request_id) { 112 open_callbacks_.erase(request_id); 113 114#if defined(ENABLE_WEBRTC) 115 GetRenderViewImpl()->media_stream_dispatcher()->CancelOpenDevice(request_id, 116 AsWeakPtr()); 117#endif 118} 119 120void PepperMediaDeviceManager::CloseDevice(const std::string& label) { 121#if defined(ENABLE_WEBRTC) 122 GetRenderViewImpl()->media_stream_dispatcher()->CloseDevice(label); 123#endif 124} 125 126int PepperMediaDeviceManager::GetSessionID(PP_DeviceType_Dev type, 127 const std::string& label) { 128#if defined(ENABLE_WEBRTC) 129 switch (type) { 130 case PP_DEVICETYPE_DEV_AUDIOCAPTURE: 131 return GetRenderViewImpl()->media_stream_dispatcher()->audio_session_id( 132 label, 0); 133 case PP_DEVICETYPE_DEV_VIDEOCAPTURE: 134 return GetRenderViewImpl()->media_stream_dispatcher()->video_session_id( 135 label, 0); 136 default: 137 NOTREACHED(); 138 return 0; 139 } 140#else 141 return 0; 142#endif 143} 144 145void PepperMediaDeviceManager::OnStreamGenerated( 146 int request_id, 147 const std::string& label, 148 const StreamDeviceInfoArray& audio_device_array, 149 const StreamDeviceInfoArray& video_device_array) {} 150 151void PepperMediaDeviceManager::OnStreamGenerationFailed( 152 int request_id, 153 content::MediaStreamRequestResult result) {} 154 155void PepperMediaDeviceManager::OnDeviceStopped( 156 const std::string& label, 157 const StreamDeviceInfo& device_info) {} 158 159void PepperMediaDeviceManager::OnDevicesEnumerated( 160 int request_id, 161 const StreamDeviceInfoArray& device_array) { 162 EnumerateCallbackMap::iterator iter = enumerate_callbacks_.find(request_id); 163 if (iter == enumerate_callbacks_.end()) { 164 // This might be enumerated result sent before StopEnumerateDevices is 165 // called since EnumerateDevices is persistent request. 166 return; 167 } 168 169 EnumerateDevicesCallback callback = iter->second; 170 171 std::vector<ppapi::DeviceRefData> devices; 172 devices.reserve(device_array.size()); 173 for (StreamDeviceInfoArray::const_iterator info = device_array.begin(); 174 info != device_array.end(); 175 ++info) { 176 devices.push_back(FromStreamDeviceInfo(*info)); 177 } 178 callback.Run(request_id, devices); 179} 180 181void PepperMediaDeviceManager::OnDeviceOpened( 182 int request_id, 183 const std::string& label, 184 const StreamDeviceInfo& device_info) { 185 NotifyDeviceOpened(request_id, true, label); 186} 187 188void PepperMediaDeviceManager::OnDeviceOpenFailed(int request_id) { 189 NotifyDeviceOpened(request_id, false, std::string()); 190} 191 192// static 193MediaStreamType PepperMediaDeviceManager::FromPepperDeviceType( 194 PP_DeviceType_Dev type) { 195 switch (type) { 196 case PP_DEVICETYPE_DEV_INVALID: 197 return MEDIA_NO_SERVICE; 198 case PP_DEVICETYPE_DEV_AUDIOCAPTURE: 199 return MEDIA_DEVICE_AUDIO_CAPTURE; 200 case PP_DEVICETYPE_DEV_VIDEOCAPTURE: 201 return MEDIA_DEVICE_VIDEO_CAPTURE; 202 default: 203 NOTREACHED(); 204 return MEDIA_NO_SERVICE; 205 } 206} 207 208// static 209PP_DeviceType_Dev PepperMediaDeviceManager::FromMediaStreamType( 210 MediaStreamType type) { 211 switch (type) { 212 case MEDIA_NO_SERVICE: 213 return PP_DEVICETYPE_DEV_INVALID; 214 case MEDIA_DEVICE_AUDIO_CAPTURE: 215 return PP_DEVICETYPE_DEV_AUDIOCAPTURE; 216 case MEDIA_DEVICE_VIDEO_CAPTURE: 217 return PP_DEVICETYPE_DEV_VIDEOCAPTURE; 218 default: 219 NOTREACHED(); 220 return PP_DEVICETYPE_DEV_INVALID; 221 } 222} 223 224void PepperMediaDeviceManager::NotifyDeviceOpened(int request_id, 225 bool succeeded, 226 const std::string& label) { 227 OpenCallbackMap::iterator iter = open_callbacks_.find(request_id); 228 if (iter == open_callbacks_.end()) { 229 // The callback may have been unregistered. 230 return; 231 } 232 233 OpenDeviceCallback callback = iter->second; 234 open_callbacks_.erase(iter); 235 236 callback.Run(request_id, succeeded, label); 237} 238 239RenderViewImpl* PepperMediaDeviceManager::GetRenderViewImpl() { 240 return static_cast<RenderViewImpl*>(render_view()); 241} 242 243} // namespace content 244