blob: 13ad0136cc9bb552f3bbf054a400b18393aff72c [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 "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