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_thread_impl.h" 14 #include "content/renderer/render_view_impl.h" 15 #include "media/video/capture/video_capture_proxy.h" 16 #include "url/gurl.h" 17 18 namespace content { 19 20 PepperPlatformVideoCapture::PepperPlatformVideoCapture( 21 const base::WeakPtr<RenderViewImpl>& render_view, 22 const std::string& device_id, 23 const GURL& document_url, 24 PepperVideoCaptureHost* handler) 25 : render_view_(render_view), 26 device_id_(device_id), 27 session_id_(0), 28 handler_proxy_(new media::VideoCaptureHandlerProxy( 29 this, base::MessageLoopProxy::current())), 30 handler_(handler), 31 video_capture_(NULL), 32 unbalanced_start_(false), 33 pending_open_device_(false), 34 pending_open_device_id_(-1) { 35 // We need to open the device and obtain the label and session ID before 36 // initializing. 37 if (render_view_.get()) { 38 pending_open_device_id_ = GetMediaDeviceManager()->OpenDevice( 39 PP_DEVICETYPE_DEV_VIDEOCAPTURE, 40 device_id, 41 document_url, 42 base::Bind(&PepperPlatformVideoCapture::OnDeviceOpened, this)); 43 pending_open_device_ = true; 44 } 45 } 46 47 void PepperPlatformVideoCapture::StartCapture( 48 media::VideoCapture::EventHandler* handler, 49 const media::VideoCaptureCapability& capability) { 50 DCHECK(handler == handler_); 51 52 if (unbalanced_start_) 53 return; 54 55 if (video_capture_) { 56 unbalanced_start_ = true; 57 AddRef(); // Will be balanced in OnRemoved(). 58 video_capture_->StartCapture(handler_proxy_.get(), capability); 59 } 60 } 61 62 void PepperPlatformVideoCapture::StopCapture( 63 media::VideoCapture::EventHandler* handler) { 64 DCHECK(handler == handler_); 65 if (!unbalanced_start_) 66 return; 67 68 if (video_capture_) { 69 unbalanced_start_ = false; 70 video_capture_->StopCapture(handler_proxy_.get()); 71 } 72 } 73 74 void PepperPlatformVideoCapture::FeedBuffer( 75 scoped_refptr<VideoFrameBuffer> buffer) { 76 if (video_capture_) 77 video_capture_->FeedBuffer(buffer); 78 } 79 80 bool PepperPlatformVideoCapture::CaptureStarted() { 81 return handler_proxy_->state().started; 82 } 83 84 int PepperPlatformVideoCapture::CaptureWidth() { 85 return handler_proxy_->state().width; 86 } 87 88 int PepperPlatformVideoCapture::CaptureHeight() { 89 return handler_proxy_->state().height; 90 } 91 92 int PepperPlatformVideoCapture::CaptureFrameRate() { 93 return handler_proxy_->state().frame_rate; 94 } 95 96 void PepperPlatformVideoCapture::DetachEventHandler() { 97 handler_ = NULL; 98 StopCapture(NULL); 99 100 if (video_capture_) { 101 VideoCaptureImplManager* manager = 102 RenderThreadImpl::current()->video_capture_impl_manager(); 103 manager->RemoveDevice(session_id_, handler_proxy_.get()); 104 video_capture_ = NULL; 105 } 106 107 if (render_view_.get()) { 108 if (!label_.empty()) { 109 GetMediaDeviceManager()->CloseDevice(label_); 110 label_.clear(); 111 } 112 if (pending_open_device_) { 113 GetMediaDeviceManager()->CancelOpenDevice(pending_open_device_id_); 114 pending_open_device_ = false; 115 pending_open_device_id_ = -1; 116 } 117 } 118 } 119 120 void PepperPlatformVideoCapture::OnStarted(VideoCapture* capture) { 121 if (handler_) 122 handler_->OnStarted(capture); 123 } 124 125 void PepperPlatformVideoCapture::OnStopped(VideoCapture* capture) { 126 if (handler_) 127 handler_->OnStopped(capture); 128 } 129 130 void PepperPlatformVideoCapture::OnPaused(VideoCapture* capture) { 131 if (handler_) 132 handler_->OnPaused(capture); 133 } 134 135 void PepperPlatformVideoCapture::OnError(VideoCapture* capture, 136 int error_code) { 137 if (handler_) 138 handler_->OnError(capture, error_code); 139 } 140 141 void PepperPlatformVideoCapture::OnRemoved(VideoCapture* capture) { 142 if (handler_) 143 handler_->OnRemoved(capture); 144 145 Release(); // Balance the AddRef() in StartCapture(). 146 } 147 148 void PepperPlatformVideoCapture::OnBufferReady( 149 VideoCapture* capture, 150 scoped_refptr<VideoFrameBuffer> buffer) { 151 if (handler_) { 152 handler_->OnBufferReady(capture, buffer); 153 } else { 154 // Even after handler_ is detached, we have to return buffers that are in 155 // flight to us. Otherwise VideoCaptureController will not tear down. 156 FeedBuffer(buffer); 157 } 158 } 159 160 void PepperPlatformVideoCapture::OnDeviceInfoReceived( 161 VideoCapture* capture, 162 const media::VideoCaptureParams& device_info) { 163 if (handler_) 164 handler_->OnDeviceInfoReceived(capture, device_info); 165 } 166 167 PepperPlatformVideoCapture::~PepperPlatformVideoCapture() { 168 DCHECK(!video_capture_); 169 DCHECK(label_.empty()); 170 DCHECK(!pending_open_device_); 171 } 172 173 void PepperPlatformVideoCapture::Initialize() { 174 VideoCaptureImplManager* manager = 175 RenderThreadImpl::current()->video_capture_impl_manager(); 176 video_capture_ = manager->AddDevice(session_id_, handler_proxy_.get()); 177 } 178 179 void PepperPlatformVideoCapture::OnDeviceOpened(int request_id, 180 bool succeeded, 181 const std::string& label) { 182 pending_open_device_ = false; 183 pending_open_device_id_ = -1; 184 185 succeeded = succeeded && render_view_.get(); 186 if (succeeded) { 187 label_ = label; 188 session_id_ = GetMediaDeviceManager()->GetSessionID( 189 PP_DEVICETYPE_DEV_VIDEOCAPTURE, label); 190 Initialize(); 191 } 192 193 if (handler_) 194 handler_->OnInitialized(this, succeeded); 195 } 196 197 PepperMediaDeviceManager* 198 PepperPlatformVideoCapture::GetMediaDeviceManager() { 199 return PepperMediaDeviceManager::GetForRenderView(render_view_.get()); 200 } 201 202 } // namespace content 203