summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorwjia@chromium.org <wjia@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-14 17:42:09 +0000
committerwjia@chromium.org <wjia@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-14 17:42:09 +0000
commitc305d38efe2c3d1328537e97676911e2aed20885 (patch)
tree73f2f77ef7e4952e0a35f56c5d7097899744ba1c /content
parentbdf9d3684346fdfa99c49a8f43a294b9e63b2e95 (diff)
downloadchromium_src-c305d38efe2c3d1328537e97676911e2aed20885.zip
chromium_src-c305d38efe2c3d1328537e97676911e2aed20885.tar.gz
chromium_src-c305d38efe2c3d1328537e97676911e2aed20885.tar.bz2
use SharedMemory for buffer sharing in video capture
BUG=none TEST=try bots Review URL: http://codereview.chromium.org/6995148 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@89020 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/browser/renderer_host/video_capture_controller.cc61
-rw-r--r--content/browser/renderer_host/video_capture_controller.h8
-rw-r--r--content/browser/renderer_host/video_capture_controller_event_handler.h15
-rw-r--r--content/browser/renderer_host/video_capture_host.cc40
-rw-r--r--content/browser/renderer_host/video_capture_host.h16
-rw-r--r--content/browser/renderer_host/video_capture_host_unittest.cc61
-rw-r--r--content/common/video_capture_messages.h11
-rw-r--r--content/renderer/media/video_capture_impl.cc84
-rw-r--r--content/renderer/media/video_capture_impl.h12
-rw-r--r--content/renderer/video_capture_message_filter.cc35
-rw-r--r--content/renderer/video_capture_message_filter.h17
-rw-r--r--content/renderer/video_capture_message_filter_unittest.cc52
12 files changed, 270 insertions, 142 deletions
diff --git a/content/browser/renderer_host/video_capture_controller.cc b/content/browser/renderer_host/video_capture_controller.cc
index dce342d..c36232b 100644
--- a/content/browser/renderer_host/video_capture_controller.cc
+++ b/content/browser/renderer_host/video_capture_controller.cc
@@ -4,16 +4,11 @@
#include "content/browser/renderer_host/video_capture_controller.h"
-#include "base/logging.h"
#include "base/stl_util-inl.h"
#include "content/browser/browser_thread.h"
#include "content/browser/media_stream/video_capture_manager.h"
#include "media/base/yuv_convert.h"
-#if defined(OS_WIN)
-#include "content/common/section_util_win.h"
-#endif
-
// The number of TransportDIBs VideoCaptureController allocate.
static const size_t kNoOfDIBS = 3;
@@ -54,13 +49,13 @@ void VideoCaptureController::StopCapture(Task* stopped_task) {
stopped_task));
}
-void VideoCaptureController::ReturnTransportDIB(TransportDIB::Handle handle) {
+void VideoCaptureController::ReturnBuffer(int buffer_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
bool ready_to_delete;
{
base::AutoLock lock(lock_);
- free_dibs_.push_back(handle);
+ free_dibs_.push_back(buffer_id);
ready_to_delete = (free_dibs_.size() == owned_dibs_.size());
}
if (report_ready_to_delete_ && ready_to_delete) {
@@ -75,16 +70,16 @@ void VideoCaptureController::ReturnTransportDIB(TransportDIB::Handle handle) {
void VideoCaptureController::OnIncomingCapturedFrame(const uint8* data,
int length,
base::Time timestamp) {
- TransportDIB::Handle handle;
- TransportDIB* dib = NULL;
+ int buffer_id = 0;
+ base::SharedMemory* dib = NULL;
// Check if there is a TransportDIB to fill.
bool buffer_exist = false;
{
base::AutoLock lock(lock_);
if (!report_ready_to_delete_ && free_dibs_.size() > 0) {
- handle = free_dibs_.back();
- free_dibs_.pop_back();
- DIBMap::iterator it = owned_dibs_.find(handle);
+ buffer_id = free_dibs_.front();
+ free_dibs_.pop_front();
+ DIBMap::iterator it = owned_dibs_.find(buffer_id);
if (it != owned_dibs_.end()) {
dib = it->second;
buffer_exist = true;
@@ -96,16 +91,10 @@ void VideoCaptureController::OnIncomingCapturedFrame(const uint8* data,
return;
}
- if (!dib->Map()) {
- VLOG(1) << "OnIncomingCapturedFrame - Failed to map handle.";
- base::AutoLock lock(lock_);
- free_dibs_.push_back(handle);
- return;
- }
uint8* target = static_cast<uint8*>(dib->memory());
- CHECK(dib->size() >= static_cast<size_t> (frame_info_.width *
- frame_info_.height * 3) /
- 2);
+ CHECK(dib->created_size() >= static_cast<size_t> (frame_info_.width *
+ frame_info_.height * 3) /
+ 2);
// Do color conversion from the camera format to I420.
switch (frame_info_.color) {
@@ -160,7 +149,7 @@ void VideoCaptureController::OnIncomingCapturedFrame(const uint8* data,
NOTREACHED();
}
- event_handler_->OnBufferReady(id_, handle, timestamp);
+ event_handler_->OnBufferReady(id_, buffer_id, timestamp);
}
void VideoCaptureController::OnError() {
@@ -172,24 +161,21 @@ void VideoCaptureController::OnFrameInfo(
DCHECK(owned_dibs_.empty());
bool frames_created = true;
const size_t needed_size = (info.width * info.height * 3) / 2;
- for (size_t i = 0; i < kNoOfDIBS; ++i) {
- TransportDIB* dib = TransportDIB::Create(needed_size, i);
- if (!dib) {
+ for (size_t i = 1; i <= kNoOfDIBS; ++i) {
+ base::SharedMemory* shared_memory = new base::SharedMemory();
+ if (!shared_memory->CreateAndMapAnonymous(needed_size)) {
frames_created = false;
break;
}
- // Lock needed since the buffers are used in OnIncomingFrame
- // and we need to use it there in order to avoid memcpy of complete frames.
+ base::SharedMemoryHandle remote_handle;
+ shared_memory->ShareToProcess(render_handle_, &remote_handle);
+
base::AutoLock lock(lock_);
-#if defined(OS_WIN)
- // On Windows we need to get a handle the can be used in the render process.
- TransportDIB::Handle handle = chrome::GetSectionForProcess(
- dib->handle(), render_handle_, false);
-#else
- TransportDIB::Handle handle = dib->handle();
-#endif
- owned_dibs_.insert(std::make_pair(handle, dib));
- free_dibs_.push_back(handle);
+ owned_dibs_.insert(std::make_pair(i, shared_memory));
+ free_dibs_.push_back(i);
+ event_handler_->OnBufferCreated(id_, remote_handle,
+ static_cast<int>(needed_size),
+ static_cast<int>(i));
}
frame_info_= info;
@@ -197,8 +183,7 @@ void VideoCaptureController::OnFrameInfo(
if (!frames_created) {
event_handler_->OnError(id_);
}
- event_handler_->OnFrameInfo(id_, info.width, info.height,
- info.frame_rate);
+ event_handler_->OnFrameInfo(id_, info.width, info.height, info.frame_rate);
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/content/browser/renderer_host/video_capture_controller.h b/content/browser/renderer_host/video_capture_controller.h
index 9eae8c7..4879492 100644
--- a/content/browser/renderer_host/video_capture_controller.h
+++ b/content/browser/renderer_host/video_capture_controller.h
@@ -50,9 +50,9 @@ class VideoCaptureController
// device is stopped.
void StopCapture(Task* stopped_task);
- // Return a DIB previously given in
+ // Return a buffer previously given in
// VideoCaptureControllerEventHandler::OnBufferReady.
- void ReturnTransportDIB(TransportDIB::Handle handle);
+ void ReturnBuffer(int buffer_id);
// Implement media::VideoCaptureDevice::EventHandler.
virtual void OnIncomingCapturedFrame(const uint8* data,
@@ -70,8 +70,8 @@ class VideoCaptureController
// Handle to the render process that will receive the DIBs.
base::ProcessHandle render_handle_;
bool report_ready_to_delete_;
- typedef std::list<TransportDIB::Handle> DIBHandleList;
- typedef std::map<TransportDIB::Handle, TransportDIB*> DIBMap;
+ typedef std::list<int> DIBHandleList;
+ typedef std::map<int, base::SharedMemory*> DIBMap;
// Free DIBS that can be filled with video frames.
DIBHandleList free_dibs_;
diff --git a/content/browser/renderer_host/video_capture_controller_event_handler.h b/content/browser/renderer_host/video_capture_controller_event_handler.h
index 0467941..397e5ae 100644
--- a/content/browser/renderer_host/video_capture_controller_event_handler.h
+++ b/content/browser/renderer_host/video_capture_controller_event_handler.h
@@ -5,10 +5,8 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_VIDEO_CAPTURE_CONTROLLER_EVENT_HANDLER_H_
#define CONTENT_BROWSER_RENDERER_HOST_VIDEO_CAPTURE_CONTROLLER_EVENT_HANDLER_H_
-#include <map>
-
+#include "base/shared_memory.h"
#include "base/time.h"
-#include "ui/gfx/surface/transport_dib.h"
// ID used for identifying an object of VideoCaptureController.
struct VideoCaptureControllerID {
@@ -25,12 +23,17 @@ struct VideoCaptureControllerID {
// BufferReady, FrameInfo, Error, etc.
class VideoCaptureControllerEventHandler {
public:
- // An Error have occurred in the VideoCaptureDevice.
+ // An Error has occurred in the VideoCaptureDevice.
virtual void OnError(const VideoCaptureControllerID& id) = 0;
- // An TransportDIB have been filled with I420 video.
+ // A buffer has been newly created.
+ virtual void OnBufferCreated(const VideoCaptureControllerID& id,
+ base::SharedMemoryHandle handle,
+ int length, int buffer_id) = 0;
+
+ // A buffer has been filled with I420 video.
virtual void OnBufferReady(const VideoCaptureControllerID& id,
- TransportDIB::Handle handle,
+ int buffer_id,
base::Time timestamp) = 0;
// The frame resolution the VideoCaptureDevice capture video in.
diff --git a/content/browser/renderer_host/video_capture_host.cc b/content/browser/renderer_host/video_capture_host.cc
index 8f7fa4a..f4e4011 100644
--- a/content/browser/renderer_host/video_capture_host.cc
+++ b/content/browser/renderer_host/video_capture_host.cc
@@ -39,14 +39,26 @@ void VideoCaptureHost::OnError(const VideoCaptureControllerID& id) {
id.device_id));
}
+void VideoCaptureHost::OnBufferCreated(
+ const VideoCaptureControllerID& id,
+ base::SharedMemoryHandle handle,
+ int length,
+ int buffer_id) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ NewRunnableMethod(this, &VideoCaptureHost::DoSendNewBuffer,
+ id.routing_id, id.device_id, handle, length,
+ buffer_id));
+}
+
void VideoCaptureHost::OnBufferReady(
const VideoCaptureControllerID& id,
- TransportDIB::Handle handle,
+ int buffer_id,
base::Time timestamp) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
NewRunnableMethod(this, &VideoCaptureHost::DoSendFilledBuffer,
- id.routing_id, id.device_id, handle, timestamp));
+ id.routing_id, id.device_id, buffer_id, timestamp));
}
void VideoCaptureHost::OnFrameInfo(const VideoCaptureControllerID& id,
@@ -66,13 +78,20 @@ void VideoCaptureHost::OnReadyToDelete(const VideoCaptureControllerID& id) {
id));
}
-void VideoCaptureHost::DoSendFilledBuffer(int32 routing_id,
- int device_id,
- TransportDIB::Handle handle,
- base::Time timestamp) {
+void VideoCaptureHost::DoSendNewBuffer(
+ int32 routing_id, int device_id, base::SharedMemoryHandle handle,
+ int length, int buffer_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ Send(new VideoCaptureMsg_NewBuffer(routing_id, device_id, handle,
+ length, buffer_id));
+}
+
+void VideoCaptureHost::DoSendFilledBuffer(
+ int32 routing_id, int device_id, int buffer_id, base::Time timestamp) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- Send(new VideoCaptureMsg_BufferReady(routing_id, device_id, handle,
+ Send(new VideoCaptureMsg_BufferReady(routing_id, device_id, buffer_id,
timestamp));
}
@@ -158,16 +177,15 @@ void VideoCaptureHost::OnPauseCapture(const IPC::Message& msg, int device_id) {
media::VideoCapture::kError));
}
-void VideoCaptureHost::OnReceiveEmptyBuffer(const IPC::Message& msg,
- int device_id,
- TransportDIB::Handle handle) {
+void VideoCaptureHost::OnReceiveEmptyBuffer(
+ const IPC::Message& msg, int device_id, int buffer_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
VideoCaptureControllerID controller_id(msg.routing_id(), device_id);
EntryMap::iterator it = entries_.find(controller_id);
if (it != entries_.end()) {
scoped_refptr<VideoCaptureController> controller = it->second;
- controller->ReturnTransportDIB(handle);
+ controller->ReturnBuffer(buffer_id);
}
}
diff --git a/content/browser/renderer_host/video_capture_host.h b/content/browser/renderer_host/video_capture_host.h
index d907944..d2f611f05 100644
--- a/content/browser/renderer_host/video_capture_host.h
+++ b/content/browser/renderer_host/video_capture_host.h
@@ -56,8 +56,11 @@ class VideoCaptureHost : public BrowserMessageFilter,
// VideoCaptureControllerEventHandler implementation.
virtual void OnError(const VideoCaptureControllerID& id);
+ virtual void OnBufferCreated(const VideoCaptureControllerID& id,
+ base::SharedMemoryHandle handle,
+ int length, int buffer_id);
virtual void OnBufferReady(const VideoCaptureControllerID& id,
- TransportDIB::Handle handle,
+ int buffer_id,
base::Time timestamp);
virtual void OnFrameInfo(const VideoCaptureControllerID& id,
int width,
@@ -90,17 +93,24 @@ class VideoCaptureHost : public BrowserMessageFilter,
// referenced by |device_id|.
void OnReceiveEmptyBuffer(const IPC::Message& msg,
int device_id,
- TransportDIB::Handle handle);
+ int buffer_id);
// Called on the IO thread when VideoCaptureController have
// reported that all DIBs have been returned.
void DoDeleteVideoCaptureController(const VideoCaptureControllerID& id);
+ // Send a newly created buffer to the VideoCaptureMessageFilter.
+ void DoSendNewBuffer(int32 routing_id,
+ int device_id,
+ base::SharedMemoryHandle handle,
+ int length,
+ int buffer_id);
+
// Send a filled buffer to the VideoCaptureMessageFilter.
void DoSendFilledBuffer(int32 routing_id,
int device_id,
- TransportDIB::Handle handle,
+ int buffer_id,
base::Time timestamp);
// Send a information about frame resolution and frame rate
diff --git a/content/browser/renderer_host/video_capture_host_unittest.cc b/content/browser/renderer_host/video_capture_host_unittest.cc
index 8751ec4..e9986ca 100644
--- a/content/browser/renderer_host/video_capture_host_unittest.cc
+++ b/content/browser/renderer_host/video_capture_host_unittest.cc
@@ -2,13 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <list>
+#include <map>
#include <string>
#include "base/file_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "base/process_util.h"
+#include "base/stl_util-inl.h"
#include "base/stringprintf.h"
#include "content/browser/browser_thread.h"
#include "content/browser/media_stream/video_capture_manager.h"
@@ -70,11 +71,18 @@ class DumpVideo {
class MockVideoCaptureHost : public VideoCaptureHost {
public:
MockVideoCaptureHost() : return_buffers_(false), dump_video_(false) {}
- virtual ~MockVideoCaptureHost() {}
+ virtual ~MockVideoCaptureHost() {
+ STLDeleteContainerPairSecondPointers(filled_dib_.begin(),
+ filled_dib_.end());
+ }
// A list of mock methods.
+ MOCK_METHOD5(OnNewBufferCreated,
+ void(int routing_id, int device_id,
+ base::SharedMemoryHandle handle,
+ int length, int buffer_id));
MOCK_METHOD3(OnBufferFilled,
- void(int routing_id, int device_id, TransportDIB::Handle));
+ void(int routing_id, int device_id, int buffer_id));
MOCK_METHOD3(OnStateChanged,
void(int routing_id, int device_id,
media::VideoCapture::State state));
@@ -90,19 +98,21 @@ class MockVideoCaptureHost : public VideoCaptureHost {
// Return Dibs we currently have received.
void ReturnReceivedDibs(int device_id) {
- TransportDIB::Handle handle = GetReceivedDib();
- while (TransportDIB::is_valid_handle(handle)) {
+ int handle = GetReceivedDib();
+ while (handle) {
IPC::Message msg;
msg.set_routing_id(kRouteId);
this->OnReceiveEmptyBuffer(msg, device_id, handle);
handle = GetReceivedDib();
}
}
- TransportDIB::Handle GetReceivedDib() {
+ int GetReceivedDib() {
if (filled_dib_.empty())
- return TransportDIB::DefaultHandleValue();
- TransportDIB::Handle h = filled_dib_.front();
- filled_dib_.pop_front();
+ return 0;
+ std::map<int, base::SharedMemory*>::iterator it = filled_dib_.begin();
+ int h = it->first;
+ delete it->second;
+ filled_dib_.erase(it);
return h;
}
@@ -118,6 +128,7 @@ class MockVideoCaptureHost : public VideoCaptureHost {
// we are the renderer.
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(MockVideoCaptureHost, *message)
+ IPC_MESSAGE_HANDLER(VideoCaptureMsg_NewBuffer, OnNewBufferCreated)
IPC_MESSAGE_HANDLER(VideoCaptureMsg_BufferReady, OnBufferFilled)
IPC_MESSAGE_HANDLER(VideoCaptureMsg_StateChanged, OnStateChanged)
IPC_MESSAGE_HANDLER(VideoCaptureMsg_DeviceInfo, OnDeviceInfo)
@@ -130,19 +141,26 @@ class MockVideoCaptureHost : public VideoCaptureHost {
}
// These handler methods do minimal things and delegate to the mock methods.
+ void OnNewBufferCreated(const IPC::Message& msg, int device_id,
+ base::SharedMemoryHandle handle,
+ int length, int buffer_id) {
+ OnNewBufferCreated(msg.routing_id(), device_id, handle, length, buffer_id);
+ base::SharedMemory* dib = new base::SharedMemory(handle, false);
+ dib->Map(length);
+ filled_dib_[buffer_id] = dib;
+ }
+
void OnBufferFilled(const IPC::Message& msg, int device_id,
- TransportDIB::Handle dib_handle) {
+ int buffer_id) {
if (dump_video_) {
- TransportDIB* dib = TransportDIB::Map(dib_handle);
+ base::SharedMemory* dib = filled_dib_[buffer_id];
ASSERT_TRUE(dib != NULL);
dumper_.NewVideoFrame(dib->memory());
}
- OnBufferFilled(msg.routing_id(), device_id, dib_handle);
+ OnBufferFilled(msg.routing_id(), device_id, buffer_id);
if (return_buffers_) {
- VideoCaptureHost::OnReceiveEmptyBuffer(msg, device_id, dib_handle);
- } else {
- filled_dib_.push_back(dib_handle);
+ VideoCaptureHost::OnReceiveEmptyBuffer(msg, device_id, buffer_id);
}
}
@@ -159,7 +177,7 @@ class MockVideoCaptureHost : public VideoCaptureHost {
OnDeviceInfo(msg.routing_id(), device_id);
}
- std::list<TransportDIB::Handle> filled_dib_;
+ std::map<int, base::SharedMemory*> filled_dib_;
bool return_buffers_;
bool dump_video_;
DumpVideo dumper_;
@@ -237,14 +255,19 @@ class VideoCaptureHostTest : public testing::Test {
void StartCapture() {
InSequence s;
- // 1. First - get info about the new resolution
+ // 1. Newly created buffers will arrive.
+ EXPECT_CALL(*host_, OnNewBufferCreated(kRouteId, kDeviceId, _, _, _))
+ .Times(AnyNumber())
+ .WillRepeatedly(Return());
+
+ // 2. First - get info about the new resolution
EXPECT_CALL(*host_, OnDeviceInfo(kRouteId, kDeviceId));
- // 2. Change state to started
+ // 3. Change state to started
EXPECT_CALL(*host_, OnStateChanged(kRouteId, kDeviceId,
media::VideoCapture::kStarted));
- // 3. First filled buffer will arrive.
+ // 4. First filled buffer will arrive.
EXPECT_CALL(*host_, OnBufferFilled(kRouteId, kDeviceId, _))
.Times(AnyNumber())
.WillOnce(ExitMessageLoop(message_loop_.get()));
diff --git a/content/common/video_capture_messages.h b/content/common/video_capture_messages.h
index 67b714d..7b5b8d9 100644
--- a/content/common/video_capture_messages.h
+++ b/content/common/video_capture_messages.h
@@ -23,10 +23,17 @@ IPC_MESSAGE_ROUTED2(VideoCaptureMsg_StateChanged,
int /* device id */,
media::VideoCapture::State /* new state */)
+// Tell the renderer process that a new buffer is allocated for video capture.
+IPC_MESSAGE_ROUTED4(VideoCaptureMsg_NewBuffer,
+ int /* device id */,
+ base::SharedMemoryHandle /* handle */,
+ int /* length */,
+ int /* buffer_id */)
+
// Tell the renderer process that a buffer is available from video capture.
IPC_MESSAGE_ROUTED3(VideoCaptureMsg_BufferReady,
int /* device id */,
- TransportDIB::Handle /* DIB */,
+ int /* buffer_id */,
base::Time /* timestamp */)
// Tell the renderer process the width, height and frame rate the camera use.
@@ -51,4 +58,4 @@ IPC_MESSAGE_ROUTED1(VideoCaptureHostMsg_Stop,
// device (routing_id, device_id) to fill up.
IPC_MESSAGE_ROUTED2(VideoCaptureHostMsg_BufferReady,
int /* device_id */,
- TransportDIB::Handle /* handle */)
+ int /* buffer_id */)
diff --git a/content/renderer/media/video_capture_impl.cc b/content/renderer/media/video_capture_impl.cc
index aed3ef7..54ccded 100644
--- a/content/renderer/media/video_capture_impl.cc
+++ b/content/renderer/media/video_capture_impl.cc
@@ -4,11 +4,12 @@
#include "content/renderer/media/video_capture_impl.h"
+#include "base/stl_util-inl.h"
#include "content/common/child_process.h"
#include "content/common/video_capture_messages.h"
VideoCaptureImpl::DIBBuffer::DIBBuffer(
- TransportDIB* d, media::VideoCapture::VideoFrameBuffer* ptr)
+ base::SharedMemory* d, media::VideoCapture::VideoFrameBuffer* ptr)
: dib(d),
mapped_memory(ptr) {}
@@ -51,7 +52,10 @@ VideoCaptureImpl::VideoCaptureImpl(
DCHECK(filter);
}
-VideoCaptureImpl::~VideoCaptureImpl() {}
+VideoCaptureImpl::~VideoCaptureImpl() {
+ STLDeleteContainerPairSecondPointers(cached_dibs_.begin(),
+ cached_dibs_.end());
+}
void VideoCaptureImpl::Init() {
base::MessageLoopProxy* io_message_loop_proxy =
@@ -127,8 +131,9 @@ void VideoCaptureImpl::StartCapture(
(capability.width != width_ || capability.height != height_)) {
new_width_ = capability.width;
new_height_ = capability.height;
- DLOG(INFO) << "StartCapture: Got master client with new resolution "
- "during started, try to restart.";
+ DLOG(INFO) << "StartCapture: Got master client with new resolution ("
+ << new_width_ << ", " << new_height_ << ") "
+ << "during started, try to restart.";
StopDevice();
}
handler->OnStarted(this);
@@ -139,7 +144,9 @@ void VideoCaptureImpl::StartCapture(
if (capability.resolution_fixed || !pending_start()) {
new_width_ = capability.width;
new_height_ = capability.height;
- DLOG(INFO) << "StartCapture: Got new resolution, already in stopping.";
+ DLOG(INFO) << "StartCapture: Got new resolution ("
+ << new_width_ << ", " << new_height_ << ") "
+ << ", already in stopping.";
}
handler->OnStarted(this);
return;
@@ -151,6 +158,8 @@ void VideoCaptureImpl::StartCapture(
new_height_ = 0;
width_ = capability.width;
height_ = capability.height;
+ DLOG(INFO) << "StartCapture: resolution ("
+ << width_ << ", " << height_ << "). ";
StartCaptureInternal();
}
@@ -199,7 +208,9 @@ void VideoCaptureImpl::StopCapture(media::VideoCapture::EventHandler* handler) {
if (maxw < width_ && maxh < height_) {
new_width_ = maxw;
new_height_ = maxh;
- DLOG(INFO) << "StopCapture: New smaller resolution, stopping ...";
+ DLOG(INFO) << "StopCapture: New smaller resolution ("
+ << new_width_ << ", " << new_height_ << ") "
+ << "), stopping ...";
StopDevice();
}
return;
@@ -208,7 +219,9 @@ void VideoCaptureImpl::StopCapture(media::VideoCapture::EventHandler* handler) {
if (state_ == kStopping) {
new_width_ = maxw;
new_height_ = maxh;
- DLOG(INFO) << "StopCapture: New resolution, during stopping.";
+ DLOG(INFO) << "StopCapture: New resolution ("
+ << new_width_ << ", " << new_height_ << ") "
+ << "), during stopping.";
return;
}
} else {
@@ -219,46 +232,54 @@ void VideoCaptureImpl::StopCapture(media::VideoCapture::EventHandler* handler) {
}
}
-void VideoCaptureImpl::OnBufferReceived(TransportDIB::Handle handle,
- base::Time timestamp) {
+void VideoCaptureImpl::OnBufferCreated(
+ base::SharedMemoryHandle handle,
+ int length, int buffer_id) {
+ if (!ml_proxy_->BelongsToCurrentThread()) {
+ ml_proxy_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &VideoCaptureImpl::OnBufferCreated,
+ handle, length, buffer_id));
+ return;
+ }
+
+ media::VideoCapture::VideoFrameBuffer* buffer;
+ DCHECK(cached_dibs_.find(buffer_id) == cached_dibs_.end());
+
+ base::SharedMemory* dib = new base::SharedMemory(handle, false);
+ dib->Map(length);
+ buffer = new VideoFrameBuffer();
+ buffer->memory_pointer = dib->memory();
+ buffer->buffer_size = length;
+ buffer->width = width_;
+ buffer->height = height_;
+
+ DIBBuffer* dib_buffer = new DIBBuffer(dib, buffer);
+ cached_dibs_[buffer_id] = dib_buffer;
+}
+
+void VideoCaptureImpl::OnBufferReceived(int buffer_id, base::Time timestamp) {
if (!ml_proxy_->BelongsToCurrentThread()) {
ml_proxy_->PostTask(FROM_HERE,
NewRunnableMethod(this, &VideoCaptureImpl::OnBufferReceived,
- handle, timestamp));
+ buffer_id, timestamp));
return;
}
if (state_ != kStarted) {
- Send(new VideoCaptureHostMsg_BufferReady(0, device_id_, handle));
+ Send(new VideoCaptureHostMsg_BufferReady(0, device_id_, buffer_id));
return;
}
media::VideoCapture::VideoFrameBuffer* buffer;
- CachedDIB::iterator it;
- for (it = cached_dibs_.begin(); it != cached_dibs_.end(); it++) {
- if ((*it)->dib->handle() == handle)
- break;
- }
- if (it == cached_dibs_.end()) {
- TransportDIB* dib = TransportDIB::Map(handle);
- buffer = new VideoFrameBuffer();
- buffer->memory_pointer = dib->memory();
- buffer->buffer_size = dib->size();
- buffer->width = width_;
- buffer->height = height_;
-
- DIBBuffer* dib_buffer = new DIBBuffer(dib, buffer);
- cached_dibs_.push_back(dib_buffer);
- } else {
- buffer = (*it)->mapped_memory;
- }
+ DCHECK(cached_dibs_.find(buffer_id) != cached_dibs_.end());
+ buffer = cached_dibs_[buffer_id]->mapped_memory;
// TODO(wjia): handle buffer sharing with downstream modules.
for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); it++) {
it->first->OnBufferReady(this, buffer);
}
- Send(new VideoCaptureHostMsg_BufferReady(0, device_id_, handle));
+ Send(new VideoCaptureHostMsg_BufferReady(0, device_id_, buffer_id));
}
void VideoCaptureImpl::OnStateChanged(
@@ -342,6 +363,9 @@ void VideoCaptureImpl::StopDevice() {
state_ = kStopping;
Send(new VideoCaptureHostMsg_Stop(0, device_id_));
width_ = height_ = 0;
+ STLDeleteContainerPairSecondPointers(cached_dibs_.begin(),
+ cached_dibs_.end());
+ cached_dibs_.clear();
}
}
diff --git a/content/renderer/media/video_capture_impl.h b/content/renderer/media/video_capture_impl.h
index fd4750c..2d5e49d 100644
--- a/content/renderer/media/video_capture_impl.h
+++ b/content/renderer/media/video_capture_impl.h
@@ -34,8 +34,9 @@ class VideoCaptureImpl
virtual int CaptureFrameRate();
// VideoCaptureMessageFilter::Delegate interface.
- virtual void OnBufferReceived(TransportDIB::Handle handle,
- base::Time timestamp);
+ virtual void OnBufferCreated(base::SharedMemoryHandle handle,
+ int length, int buffer_id);
+ virtual void OnBufferReceived(int buffer_id, base::Time timestamp);
virtual void OnStateChanged(const media::VideoCapture::State& state);
virtual void OnDeviceInfoReceived(
const media::VideoCaptureParams& device_info);
@@ -57,10 +58,11 @@ class VideoCaptureImpl
struct DIBBuffer {
public:
- DIBBuffer(TransportDIB* d, media::VideoCapture::VideoFrameBuffer* ptr);
+ DIBBuffer(base::SharedMemory* d,
+ media::VideoCapture::VideoFrameBuffer* ptr);
~DIBBuffer();
- TransportDIB* dib;
+ base::SharedMemory* dib;
scoped_refptr<media::VideoCapture::VideoFrameBuffer> mapped_memory;
};
@@ -84,7 +86,7 @@ class VideoCaptureImpl
int device_id_;
// Pool of DIBs.
- typedef std::list<DIBBuffer*> CachedDIB;
+ typedef std::map<int, DIBBuffer*> CachedDIB;
CachedDIB cached_dibs_;
typedef std::map<media::VideoCapture::EventHandler*, VideoCaptureCapability>
diff --git a/content/renderer/video_capture_message_filter.cc b/content/renderer/video_capture_message_filter.cc
index 05ca8bb..bfb8d87 100644
--- a/content/renderer/video_capture_message_filter.cc
+++ b/content/renderer/video_capture_message_filter.cc
@@ -35,6 +35,7 @@ bool VideoCaptureMessageFilter::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(VideoCaptureMessageFilter, message)
IPC_MESSAGE_HANDLER(VideoCaptureMsg_BufferReady, OnBufferReceived)
IPC_MESSAGE_HANDLER(VideoCaptureMsg_StateChanged, OnDeviceStateChanged)
+ IPC_MESSAGE_HANDLER(VideoCaptureMsg_NewBuffer, OnBufferCreated)
IPC_MESSAGE_HANDLER(VideoCaptureMsg_DeviceInfo, OnDeviceInfoReceived)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -63,10 +64,33 @@ void VideoCaptureMessageFilter::OnChannelClosing() {
channel_ = NULL;
}
+void VideoCaptureMessageFilter::OnBufferCreated(const IPC::Message& msg,
+ int device_id,
+ base::SharedMemoryHandle handle,
+ int length,
+ int buffer_id) {
+ Delegate* delegate = NULL;
+ if (delegates_.find(device_id) != delegates_.end())
+ delegate = delegates_.find(device_id)->second;
+
+ if (!delegate) {
+ DLOG(WARNING) << "OnBufferCreated: Got video frame buffer for a "
+ "non-existent or removed video capture.";
+
+ // Send the buffer back to Host in case it's waiting for all buffers
+ // to be returned.
+ base::SharedMemory::CloseHandle(handle);
+ Send(new VideoCaptureHostMsg_BufferReady(0, device_id, buffer_id));
+ return;
+ }
+
+ delegate->OnBufferCreated(handle, length, buffer_id);
+}
+
void VideoCaptureMessageFilter::OnBufferReceived(const IPC::Message& msg,
- int device_id,
- TransportDIB::Handle handle,
- base::Time timestamp) {
+ int device_id,
+ int buffer_id,
+ base::Time timestamp) {
Delegate* delegate = NULL;
if (delegates_.find(device_id) != delegates_.end())
delegate = delegates_.find(device_id)->second;
@@ -77,11 +101,11 @@ void VideoCaptureMessageFilter::OnBufferReceived(const IPC::Message& msg,
// Send the buffer back to Host in case it's waiting for all buffers
// to be returned.
- Send(new VideoCaptureHostMsg_BufferReady(0, device_id, handle));
+ Send(new VideoCaptureHostMsg_BufferReady(0, device_id, buffer_id));
return;
}
- delegate->OnBufferReceived(handle, timestamp);
+ delegate->OnBufferReceived(buffer_id, timestamp);
}
void VideoCaptureMessageFilter::OnDeviceStateChanged(
@@ -143,4 +167,3 @@ void VideoCaptureMessageFilter::RemoveDelegate(Delegate* delegate) {
}
}
}
-
diff --git a/content/renderer/video_capture_message_filter.h b/content/renderer/video_capture_message_filter.h
index 7ca67be..8fb8d65 100644
--- a/content/renderer/video_capture_message_filter.h
+++ b/content/renderer/video_capture_message_filter.h
@@ -13,17 +13,20 @@
#include <map>
#include "base/message_loop_proxy.h"
+#include "base/shared_memory.h"
#include "ipc/ipc_channel_proxy.h"
#include "media/video/capture/video_capture.h"
-#include "ui/gfx/surface/transport_dib.h"
class VideoCaptureMessageFilter : public IPC::ChannelProxy::MessageFilter {
public:
class Delegate {
public:
+ // Called when a video frame buffer is created in the browser process.
+ virtual void OnBufferCreated(base::SharedMemoryHandle handle,
+ int length, int buffer_id) = 0;
+
// Called when a video frame buffer is received from the browser process.
- virtual void OnBufferReceived(TransportDIB::Handle handle,
- base::Time timestamp) = 0;
+ virtual void OnBufferReceived(int buffer_id, base::Time timestamp) = 0;
// Called when state of a video capture device has changed in the browser
// process.
@@ -66,10 +69,14 @@ class VideoCaptureMessageFilter : public IPC::ChannelProxy::MessageFilter {
virtual void OnFilterRemoved();
virtual void OnChannelClosing();
+ // Receive a newly created buffer from browser process.
+ void OnBufferCreated(const IPC::Message& msg, int device_id,
+ base::SharedMemoryHandle handle,
+ int length, int buffer_id);
+
// Receive a buffer from browser process.
void OnBufferReceived(const IPC::Message& msg, int device_id,
- TransportDIB::Handle handle,
- base::Time timestamp);
+ int buffer_id, base::Time timestamp);
// State of browser process' video capture device has changed.
void OnDeviceStateChanged(int device_id,
diff --git a/content/renderer/video_capture_message_filter_unittest.cc b/content/renderer/video_capture_message_filter_unittest.cc
index 1d647db..99dbeba 100644
--- a/content/renderer/video_capture_message_filter_unittest.cc
+++ b/content/renderer/video_capture_message_filter_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "base/message_loop.h"
+#include "base/shared_memory.h"
#include "content/common/video_capture_messages.h"
#include "content/renderer/video_capture_message_filter.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -17,10 +18,16 @@ class MockVideoCaptureDelegate : public VideoCaptureMessageFilter::Delegate {
device_id_ = 0;
}
- virtual void OnBufferReceived(TransportDIB::Handle handle,
- base::Time timestamp) {
- buffer_received_ = true;
+ virtual void OnBufferCreated(base::SharedMemoryHandle handle,
+ int length, int buffer_id) {
+ buffer_created_ = true;
handle_ = handle;
+ }
+
+ // Called when a video frame buffer is received from the browser process.
+ virtual void OnBufferReceived(int buffer_id, base::Time timestamp) {
+ buffer_received_ = true;
+ buffer_id_ = buffer_id;
timestamp_ = timestamp;
}
@@ -42,8 +49,11 @@ class MockVideoCaptureDelegate : public VideoCaptureMessageFilter::Delegate {
}
void Reset() {
+ buffer_created_ = false;
+ handle_ = base::SharedMemory::NULLHandle();
+
buffer_received_ = false;
- handle_ = TransportDIB::DefaultHandleValue();
+ buffer_id_ = -1;
timestamp_ = base::Time();
state_changed_received_ = false;
@@ -55,8 +65,11 @@ class MockVideoCaptureDelegate : public VideoCaptureMessageFilter::Delegate {
params_.frame_per_second = 0;
}
+ bool buffer_created() { return buffer_created_; }
+ base::SharedMemoryHandle received_buffer_handle() { return handle_; }
+
bool buffer_received() { return buffer_received_; }
- TransportDIB::Handle received_buffer_handle() { return handle_; }
+ int received_buffer_id() { return buffer_id_; }
base::Time received_buffer_ts() { return timestamp_; }
bool state_changed_received() { return state_changed_received_; }
@@ -69,8 +82,11 @@ class MockVideoCaptureDelegate : public VideoCaptureMessageFilter::Delegate {
int32 device_id() { return device_id_; }
private:
+ bool buffer_created_;
+ base::SharedMemoryHandle handle_;
+
bool buffer_received_;
- TransportDIB::Handle handle_;
+ int buffer_id_;
base::Time timestamp_;
bool state_changed_received_;
@@ -107,19 +123,29 @@ TEST(VideoCaptureMessageFilterTest, Basic) {
EXPECT_TRUE(media::VideoCapture::kStarted == delegate.state());
delegate.Reset();
+ // VideoCaptureMsg_NewBuffer
+ const base::SharedMemoryHandle handle =
+#if defined(OS_WIN)
+ reinterpret_cast<base::SharedMemoryHandle>(10);
+#else
+ base::SharedMemoryHandle(10, true);
+#endif
+ EXPECT_FALSE(delegate.buffer_created());
+ filter->OnMessageReceived(VideoCaptureMsg_NewBuffer(
+ kRouteId, delegate.device_id(), handle, 1, 1));
+ EXPECT_TRUE(delegate.buffer_created());
+ EXPECT_EQ(handle, delegate.received_buffer_handle());
+ delegate.Reset();
+
// VideoCaptureMsg_BufferReady
- const TransportDIB::Handle handle = TransportDIB::GetFakeHandleForTest();
+ int buffer_id = 1;
base::Time timestamp = base::Time::FromInternalValue(1);
EXPECT_FALSE(delegate.buffer_received());
filter->OnMessageReceived(VideoCaptureMsg_BufferReady(
- kRouteId, delegate.device_id(), handle, timestamp));
+ kRouteId, delegate.device_id(), buffer_id, timestamp));
EXPECT_TRUE(delegate.buffer_received());
-#if defined(OS_MACOSX)
- EXPECT_EQ(handle.fd, delegate.received_buffer_handle().fd);
-#else
- EXPECT_EQ(handle, delegate.received_buffer_handle());
-#endif // defined(OS_MACOSX)
+ EXPECT_EQ(buffer_id, delegate.received_buffer_id());
EXPECT_TRUE(timestamp == delegate.received_buffer_ts());
delegate.Reset();