// 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 "base/memory/ref_counted.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 "media/base/video_frame.h" namespace content { PepperPlatformVideoCapture::PepperPlatformVideoCapture( int render_frame_id, const std::string& device_id, 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, handler->pp_instance(), 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_ = nullptr; 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& 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() : nullptr; } } // namespace content