blob: 1727ae1ea8057b75d1d2ce958ad8aa4e9241430e [file] [log] [blame]
// 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/message_loop/message_loop_proxy.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_thread_impl.h"
#include "content/renderer/render_view_impl.h"
#include "media/video/capture/video_capture_proxy.h"
#include "url/gurl.h"
namespace content {
PepperPlatformVideoCapture::PepperPlatformVideoCapture(
const base::WeakPtr<RenderViewImpl>& render_view,
const std::string& device_id,
const GURL& document_url,
PepperVideoCaptureHost* handler)
: render_view_(render_view),
device_id_(device_id),
session_id_(0),
handler_proxy_(new media::VideoCaptureHandlerProxy(
this, base::MessageLoopProxy::current())),
handler_(handler),
video_capture_(NULL),
unbalanced_start_(false),
pending_open_device_(false),
pending_open_device_id_(-1) {
// We need to open the device and obtain the label and session ID before
// initializing.
if (render_view_.get()) {
pending_open_device_id_ = GetMediaDeviceManager()->OpenDevice(
PP_DEVICETYPE_DEV_VIDEOCAPTURE,
device_id,
document_url,
base::Bind(&PepperPlatformVideoCapture::OnDeviceOpened, this));
pending_open_device_ = true;
}
}
void PepperPlatformVideoCapture::StartCapture(
media::VideoCapture::EventHandler* handler,
const media::VideoCaptureCapability& capability) {
DCHECK(handler == handler_);
if (unbalanced_start_)
return;
if (video_capture_) {
unbalanced_start_ = true;
AddRef(); // Will be balanced in OnRemoved().
video_capture_->StartCapture(handler_proxy_.get(), capability);
}
}
void PepperPlatformVideoCapture::StopCapture(
media::VideoCapture::EventHandler* handler) {
DCHECK(handler == handler_);
if (!unbalanced_start_)
return;
if (video_capture_) {
unbalanced_start_ = false;
video_capture_->StopCapture(handler_proxy_.get());
}
}
void PepperPlatformVideoCapture::FeedBuffer(
scoped_refptr<VideoFrameBuffer> buffer) {
if (video_capture_)
video_capture_->FeedBuffer(buffer);
}
bool PepperPlatformVideoCapture::CaptureStarted() {
return handler_proxy_->state().started;
}
int PepperPlatformVideoCapture::CaptureWidth() {
return handler_proxy_->state().width;
}
int PepperPlatformVideoCapture::CaptureHeight() {
return handler_proxy_->state().height;
}
int PepperPlatformVideoCapture::CaptureFrameRate() {
return handler_proxy_->state().frame_rate;
}
void PepperPlatformVideoCapture::DetachEventHandler() {
handler_ = NULL;
StopCapture(NULL);
if (video_capture_) {
VideoCaptureImplManager* manager =
RenderThreadImpl::current()->video_capture_impl_manager();
manager->RemoveDevice(session_id_, handler_proxy_.get());
video_capture_ = NULL;
}
if (render_view_.get()) {
if (!label_.empty()) {
GetMediaDeviceManager()->CloseDevice(label_);
label_.clear();
}
if (pending_open_device_) {
GetMediaDeviceManager()->CancelOpenDevice(pending_open_device_id_);
pending_open_device_ = false;
pending_open_device_id_ = -1;
}
}
}
void PepperPlatformVideoCapture::OnStarted(VideoCapture* capture) {
if (handler_)
handler_->OnStarted(capture);
}
void PepperPlatformVideoCapture::OnStopped(VideoCapture* capture) {
if (handler_)
handler_->OnStopped(capture);
}
void PepperPlatformVideoCapture::OnPaused(VideoCapture* capture) {
if (handler_)
handler_->OnPaused(capture);
}
void PepperPlatformVideoCapture::OnError(VideoCapture* capture,
int error_code) {
if (handler_)
handler_->OnError(capture, error_code);
}
void PepperPlatformVideoCapture::OnRemoved(VideoCapture* capture) {
if (handler_)
handler_->OnRemoved(capture);
Release(); // Balance the AddRef() in StartCapture().
}
void PepperPlatformVideoCapture::OnBufferReady(
VideoCapture* capture,
scoped_refptr<VideoFrameBuffer> buffer) {
if (handler_) {
handler_->OnBufferReady(capture, buffer);
} else {
// Even after handler_ is detached, we have to return buffers that are in
// flight to us. Otherwise VideoCaptureController will not tear down.
FeedBuffer(buffer);
}
}
void PepperPlatformVideoCapture::OnDeviceInfoReceived(
VideoCapture* capture,
const media::VideoCaptureParams& device_info) {
if (handler_)
handler_->OnDeviceInfoReceived(capture, device_info);
}
PepperPlatformVideoCapture::~PepperPlatformVideoCapture() {
DCHECK(!video_capture_);
DCHECK(label_.empty());
DCHECK(!pending_open_device_);
}
void PepperPlatformVideoCapture::Initialize() {
VideoCaptureImplManager* manager =
RenderThreadImpl::current()->video_capture_impl_manager();
video_capture_ = manager->AddDevice(session_id_, handler_proxy_.get());
}
void PepperPlatformVideoCapture::OnDeviceOpened(int request_id,
bool succeeded,
const std::string& label) {
pending_open_device_ = false;
pending_open_device_id_ = -1;
succeeded = succeeded && render_view_.get();
if (succeeded) {
label_ = label;
session_id_ = GetMediaDeviceManager()->GetSessionID(
PP_DEVICETYPE_DEV_VIDEOCAPTURE, label);
Initialize();
}
if (handler_)
handler_->OnInitialized(this, succeeded);
}
PepperMediaDeviceManager*
PepperPlatformVideoCapture::GetMediaDeviceManager() {
return PepperMediaDeviceManager::GetForRenderView(render_view_.get());
}
} // namespace content