| // 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/pepper/pepper_platform_video_capture.h" |
| |
| #include "base/bind.h" |
| #include "base/logging.h" |
| #include "content/renderer/media/video_capture_impl_manager.h" |
| #include "content/renderer/pepper/pepper_media_device_manager.h" |
| #include "content/renderer/pepper/pepper_video_capture_host.h" |
| #include "content/renderer/render_frame_impl.h" |
| #include "content/renderer/render_thread_impl.h" |
| #include "media/base/bind_to_current_loop.h" |
| #include "url/gurl.h" |
| |
| namespace content { |
| |
| PepperPlatformVideoCapture::PepperPlatformVideoCapture( |
| int render_frame_id, |
| const std::string& device_id, |
| const GURL& document_url, |
| PepperVideoCaptureHost* handler) |
| : render_frame_id_(render_frame_id), |
| device_id_(device_id), |
| session_id_(0), |
| handler_(handler), |
| pending_open_device_(false), |
| pending_open_device_id_(-1), |
| weak_factory_(this) { |
| // We need to open the device and obtain the label and session ID before |
| // initializing. |
| PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager(); |
| if (device_manager) { |
| pending_open_device_id_ = device_manager->OpenDevice( |
| PP_DEVICETYPE_DEV_VIDEOCAPTURE, |
| device_id, |
| document_url, |
| base::Bind(&PepperPlatformVideoCapture::OnDeviceOpened, |
| weak_factory_.GetWeakPtr())); |
| pending_open_device_ = true; |
| } |
| } |
| |
| void PepperPlatformVideoCapture::StartCapture( |
| const media::VideoCaptureParams& params) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| if (!stop_capture_cb_.is_null()) |
| return; |
| VideoCaptureImplManager* manager = |
| RenderThreadImpl::current()->video_capture_impl_manager(); |
| stop_capture_cb_ = |
| manager->StartCapture(session_id_, |
| params, |
| media::BindToCurrentLoop(base::Bind( |
| &PepperPlatformVideoCapture::OnStateUpdate, |
| weak_factory_.GetWeakPtr())), |
| media::BindToCurrentLoop(base::Bind( |
| &PepperPlatformVideoCapture::OnFrameReady, |
| weak_factory_.GetWeakPtr()))); |
| } |
| |
| void PepperPlatformVideoCapture::StopCapture() { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| if (stop_capture_cb_.is_null()) |
| return; |
| stop_capture_cb_.Run(); |
| stop_capture_cb_.Reset(); |
| } |
| |
| void PepperPlatformVideoCapture::DetachEventHandler() { |
| handler_ = NULL; |
| StopCapture(); |
| if (!release_device_cb_.is_null()) { |
| release_device_cb_.Run(); |
| release_device_cb_.Reset(); |
| } |
| if (!label_.empty()) { |
| PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager(); |
| if (device_manager) |
| device_manager->CloseDevice(label_); |
| label_.clear(); |
| } |
| if (pending_open_device_) { |
| PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager(); |
| if (device_manager) |
| device_manager->CancelOpenDevice(pending_open_device_id_); |
| pending_open_device_ = false; |
| pending_open_device_id_ = -1; |
| } |
| } |
| |
| PepperPlatformVideoCapture::~PepperPlatformVideoCapture() { |
| DCHECK(stop_capture_cb_.is_null()); |
| DCHECK(release_device_cb_.is_null()); |
| DCHECK(label_.empty()); |
| DCHECK(!pending_open_device_); |
| } |
| |
| void PepperPlatformVideoCapture::OnDeviceOpened(int request_id, |
| bool succeeded, |
| const std::string& label) { |
| pending_open_device_ = false; |
| pending_open_device_id_ = -1; |
| |
| PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager(); |
| succeeded = succeeded && device_manager; |
| if (succeeded) { |
| label_ = label; |
| session_id_ = device_manager->GetSessionID( |
| PP_DEVICETYPE_DEV_VIDEOCAPTURE, label); |
| VideoCaptureImplManager* manager = |
| RenderThreadImpl::current()->video_capture_impl_manager(); |
| release_device_cb_ = manager->UseDevice(session_id_); |
| } |
| |
| if (handler_) |
| handler_->OnInitialized(succeeded); |
| } |
| |
| void PepperPlatformVideoCapture::OnStateUpdate(VideoCaptureState state) { |
| if (!handler_) |
| return; |
| switch (state) { |
| case VIDEO_CAPTURE_STATE_STARTED: |
| handler_->OnStarted(); |
| break; |
| case VIDEO_CAPTURE_STATE_STOPPED: |
| handler_->OnStopped(); |
| break; |
| case VIDEO_CAPTURE_STATE_PAUSED: |
| handler_->OnPaused(); |
| break; |
| case VIDEO_CAPTURE_STATE_ERROR: |
| handler_->OnError(); |
| break; |
| default: |
| NOTREACHED() << "Unexpected state: " << state << "."; |
| } |
| } |
| |
| void PepperPlatformVideoCapture::OnFrameReady( |
| const scoped_refptr<media::VideoFrame>& frame, |
| base::TimeTicks estimated_capture_time) { |
| if (handler_ && !stop_capture_cb_.is_null()) |
| handler_->OnFrameReady(frame); |
| } |
| |
| PepperMediaDeviceManager* PepperPlatformVideoCapture::GetMediaDeviceManager() { |
| RenderFrameImpl* const render_frame = |
| RenderFrameImpl::FromRoutingID(render_frame_id_); |
| return render_frame ? |
| PepperMediaDeviceManager::GetForRenderFrame(render_frame).get() : NULL; |
| } |
| |
| } // namespace content |