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_platform_video_capture.h" 6 7 #include "base/bind.h" 8 #include "base/logging.h" 9 #include "base/message_loop/message_loop_proxy.h" 10 #include "content/renderer/media/video_capture_impl_manager.h" 11 #include "content/renderer/pepper/pepper_media_device_manager.h" 12 #include "content/renderer/pepper/pepper_video_capture_host.h" 13 #include "content/renderer/render_frame_impl.h" 14 #include "content/renderer/render_thread_impl.h" 15 #include "media/base/bind_to_current_loop.h" 16 #include "url/gurl.h" 17 18 namespace content { 19 20 PepperPlatformVideoCapture::PepperPlatformVideoCapture( 21 int render_frame_id, 22 const std::string& device_id, 23 const GURL& document_url, 24 PepperVideoCaptureHost* handler) 25 : render_frame_id_(render_frame_id), 26 device_id_(device_id), 27 session_id_(0), 28 handler_(handler), 29 pending_open_device_(false), 30 pending_open_device_id_(-1), 31 weak_factory_(this) { 32 // We need to open the device and obtain the label and session ID before 33 // initializing. 34 PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager(); 35 if (device_manager) { 36 pending_open_device_id_ = device_manager->OpenDevice( 37 PP_DEVICETYPE_DEV_VIDEOCAPTURE, 38 device_id, 39 document_url, 40 base::Bind(&PepperPlatformVideoCapture::OnDeviceOpened, 41 weak_factory_.GetWeakPtr())); 42 pending_open_device_ = true; 43 } 44 } 45 46 void PepperPlatformVideoCapture::StartCapture( 47 const media::VideoCaptureParams& params) { 48 DCHECK(thread_checker_.CalledOnValidThread()); 49 if (!stop_capture_cb_.is_null()) 50 return; 51 VideoCaptureImplManager* manager = 52 RenderThreadImpl::current()->video_capture_impl_manager(); 53 stop_capture_cb_ = 54 manager->StartCapture(session_id_, 55 params, 56 media::BindToCurrentLoop(base::Bind( 57 &PepperPlatformVideoCapture::OnStateUpdate, 58 weak_factory_.GetWeakPtr())), 59 media::BindToCurrentLoop(base::Bind( 60 &PepperPlatformVideoCapture::OnFrameReady, 61 weak_factory_.GetWeakPtr()))); 62 } 63 64 void PepperPlatformVideoCapture::StopCapture() { 65 DCHECK(thread_checker_.CalledOnValidThread()); 66 if (stop_capture_cb_.is_null()) 67 return; 68 stop_capture_cb_.Run(); 69 stop_capture_cb_.Reset(); 70 } 71 72 void PepperPlatformVideoCapture::DetachEventHandler() { 73 handler_ = NULL; 74 StopCapture(); 75 if (!release_device_cb_.is_null()) { 76 release_device_cb_.Run(); 77 release_device_cb_.Reset(); 78 } 79 if (!label_.empty()) { 80 PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager(); 81 if (device_manager) 82 device_manager->CloseDevice(label_); 83 label_.clear(); 84 } 85 if (pending_open_device_) { 86 PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager(); 87 if (device_manager) 88 device_manager->CancelOpenDevice(pending_open_device_id_); 89 pending_open_device_ = false; 90 pending_open_device_id_ = -1; 91 } 92 } 93 94 PepperPlatformVideoCapture::~PepperPlatformVideoCapture() { 95 DCHECK(stop_capture_cb_.is_null()); 96 DCHECK(release_device_cb_.is_null()); 97 DCHECK(label_.empty()); 98 DCHECK(!pending_open_device_); 99 } 100 101 void PepperPlatformVideoCapture::OnDeviceOpened(int request_id, 102 bool succeeded, 103 const std::string& label) { 104 pending_open_device_ = false; 105 pending_open_device_id_ = -1; 106 107 PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager(); 108 succeeded = succeeded && device_manager; 109 if (succeeded) { 110 label_ = label; 111 session_id_ = device_manager->GetSessionID( 112 PP_DEVICETYPE_DEV_VIDEOCAPTURE, label); 113 VideoCaptureImplManager* manager = 114 RenderThreadImpl::current()->video_capture_impl_manager(); 115 release_device_cb_ = manager->UseDevice(session_id_); 116 } 117 118 if (handler_) 119 handler_->OnInitialized(succeeded); 120 } 121 122 void PepperPlatformVideoCapture::OnStateUpdate(VideoCaptureState state) { 123 if (!handler_) 124 return; 125 switch (state) { 126 case VIDEO_CAPTURE_STATE_STARTED: 127 handler_->OnStarted(); 128 break; 129 case VIDEO_CAPTURE_STATE_STOPPED: 130 handler_->OnStopped(); 131 break; 132 case VIDEO_CAPTURE_STATE_PAUSED: 133 handler_->OnPaused(); 134 break; 135 case VIDEO_CAPTURE_STATE_ERROR: 136 handler_->OnError(); 137 break; 138 default: 139 NOTREACHED() << "Unexpected state: " << state << "."; 140 } 141 } 142 143 void PepperPlatformVideoCapture::OnFrameReady( 144 const scoped_refptr<media::VideoFrame>& frame, 145 const media::VideoCaptureFormat& format, 146 const base::TimeTicks& estimated_capture_time) { 147 if (handler_ && !stop_capture_cb_.is_null()) 148 handler_->OnFrameReady(frame, format); 149 } 150 151 PepperMediaDeviceManager* PepperPlatformVideoCapture::GetMediaDeviceManager() { 152 RenderFrameImpl* const render_frame = 153 RenderFrameImpl::FromRoutingID(render_frame_id_); 154 return render_frame ? 155 PepperMediaDeviceManager::GetForRenderFrame(render_frame).get() : NULL; 156 } 157 158 } // namespace content 159