Commit 642a157e authored by sheu@chromium.org's avatar sheu@chromium.org

Replace media::VideoCapture::VideoFrameBuffer with media::VideoFrame.

This CL removes a redundant class in the form of
media::VideoCapture::VideoFrameBuffer, and replaces it with
media::VideoFrame.  Also: as media::VideoFrame has an embedded
destruction callback, use this to handle buffer returns on
the video capture stack, and remove the explicit
VideoCapture::FeedBuffer entry point.

BUG=None
TEST=local build, content_unittests, run on desktop Linux with
     screen capture and webcam

Review URL: https://chromiumcodereview.appspot.com/23587018

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@223434 0039d316-1c4b-4281-b951-d872f2087c98
parent d3029578
...@@ -81,13 +81,15 @@ void RtcVideoCaptureDelegate::OnRemoved(media::VideoCapture* capture) { ...@@ -81,13 +81,15 @@ void RtcVideoCaptureDelegate::OnRemoved(media::VideoCapture* capture) {
Release(); Release();
} }
void RtcVideoCaptureDelegate::OnBufferReady( void RtcVideoCaptureDelegate::OnFrameReady(
media::VideoCapture* capture, media::VideoCapture* capture,
scoped_refptr<media::VideoCapture::VideoFrameBuffer> buf) { const scoped_refptr<media::VideoFrame>& frame) {
message_loop_proxy_->PostTask( message_loop_proxy_->PostTask(
FROM_HERE, FROM_HERE,
base::Bind(&RtcVideoCaptureDelegate::OnBufferReadyOnCaptureThread, base::Bind(&RtcVideoCaptureDelegate::OnFrameReadyOnCaptureThread,
this, capture, buf)); this,
capture,
frame));
} }
void RtcVideoCaptureDelegate::OnDeviceInfoReceived( void RtcVideoCaptureDelegate::OnDeviceInfoReceived(
...@@ -100,9 +102,9 @@ void RtcVideoCaptureDelegate::OnDeviceInfoChanged( ...@@ -100,9 +102,9 @@ void RtcVideoCaptureDelegate::OnDeviceInfoChanged(
const media::VideoCaptureParams& device_info) { const media::VideoCaptureParams& device_info) {
} }
void RtcVideoCaptureDelegate::OnBufferReadyOnCaptureThread( void RtcVideoCaptureDelegate::OnFrameReadyOnCaptureThread(
media::VideoCapture* capture, media::VideoCapture* capture,
scoped_refptr<media::VideoCapture::VideoFrameBuffer> buf) { const scoped_refptr<media::VideoFrame>& frame) {
if (!captured_callback_.is_null()) { if (!captured_callback_.is_null()) {
if (!got_first_frame_) { if (!got_first_frame_) {
got_first_frame_ = true; got_first_frame_ = true;
...@@ -110,9 +112,8 @@ void RtcVideoCaptureDelegate::OnBufferReadyOnCaptureThread( ...@@ -110,9 +112,8 @@ void RtcVideoCaptureDelegate::OnBufferReadyOnCaptureThread(
state_callback_.Run(CAPTURE_RUNNING); state_callback_.Run(CAPTURE_RUNNING);
} }
captured_callback_.Run(*buf.get()); captured_callback_.Run(frame);
} }
capture->FeedBuffer(buf);
} }
void RtcVideoCaptureDelegate::OnErrorOnCaptureThread( void RtcVideoCaptureDelegate::OnErrorOnCaptureThread(
......
...@@ -29,9 +29,9 @@ class RtcVideoCaptureDelegate ...@@ -29,9 +29,9 @@ class RtcVideoCaptureDelegate
CAPTURE_FAILED, // The capturer failed to start. CAPTURE_FAILED, // The capturer failed to start.
}; };
typedef base::Callback<void(const media::VideoCapture::VideoFrameBuffer& buf)> typedef base::Callback<void(const scoped_refptr<media::VideoFrame>&)>
FrameCapturedCallback; FrameCapturedCallback;
typedef base::Callback<void(CaptureState state)> StateChangeCallback; typedef base::Callback<void(CaptureState)> StateChangeCallback;
RtcVideoCaptureDelegate(const media::VideoCaptureSessionId id, RtcVideoCaptureDelegate(const media::VideoCaptureSessionId id,
VideoCaptureImplManager* vc_manager); VideoCaptureImplManager* vc_manager);
...@@ -48,9 +48,9 @@ class RtcVideoCaptureDelegate ...@@ -48,9 +48,9 @@ class RtcVideoCaptureDelegate
virtual void OnPaused(media::VideoCapture* capture) OVERRIDE; virtual void OnPaused(media::VideoCapture* capture) OVERRIDE;
virtual void OnError(media::VideoCapture* capture, int error_code) OVERRIDE; virtual void OnError(media::VideoCapture* capture, int error_code) OVERRIDE;
virtual void OnRemoved(media::VideoCapture* capture) OVERRIDE; virtual void OnRemoved(media::VideoCapture* capture) OVERRIDE;
virtual void OnBufferReady( virtual void OnFrameReady(
media::VideoCapture* capture, media::VideoCapture* capture,
scoped_refptr<media::VideoCapture::VideoFrameBuffer> buf) OVERRIDE; const scoped_refptr<media::VideoFrame>& frame) OVERRIDE;
virtual void OnDeviceInfoReceived( virtual void OnDeviceInfoReceived(
media::VideoCapture* capture, media::VideoCapture* capture,
const media::VideoCaptureParams& device_info) OVERRIDE; const media::VideoCaptureParams& device_info) OVERRIDE;
...@@ -63,9 +63,9 @@ class RtcVideoCaptureDelegate ...@@ -63,9 +63,9 @@ class RtcVideoCaptureDelegate
virtual ~RtcVideoCaptureDelegate(); virtual ~RtcVideoCaptureDelegate();
void OnBufferReadyOnCaptureThread( void OnFrameReadyOnCaptureThread(
media::VideoCapture* capture, media::VideoCapture* capture,
scoped_refptr<media::VideoCapture::VideoFrameBuffer> buf); const scoped_refptr<media::VideoFrame>& frame);
void OnErrorOnCaptureThread(media::VideoCapture* capture); void OnErrorOnCaptureThread(media::VideoCapture* capture);
void OnRemovedOnCaptureThread(media::VideoCapture* capture); void OnRemovedOnCaptureThread(media::VideoCapture* capture);
......
...@@ -9,14 +9,12 @@ ...@@ -9,14 +9,12 @@
namespace content { namespace content {
RtcVideoCapturer::RtcVideoCapturer( RtcVideoCapturer::RtcVideoCapturer(const media::VideoCaptureSessionId id,
const media::VideoCaptureSessionId id, VideoCaptureImplManager* vc_manager,
VideoCaptureImplManager* vc_manager, bool is_screencast)
bool is_screencast)
: is_screencast_(is_screencast), : is_screencast_(is_screencast),
delegate_(new RtcVideoCaptureDelegate(id, vc_manager)), delegate_(new RtcVideoCaptureDelegate(id, vc_manager)),
state_(VIDEO_CAPTURE_STATE_STOPPED) { state_(VIDEO_CAPTURE_STATE_STOPPED) {}
}
RtcVideoCapturer::~RtcVideoCapturer() { RtcVideoCapturer::~RtcVideoCapturer() {
DCHECK(VIDEO_CAPTURE_STATE_STOPPED); DCHECK(VIDEO_CAPTURE_STATE_STOPPED);
...@@ -40,8 +38,9 @@ cricket::CaptureState RtcVideoCapturer::Start( ...@@ -40,8 +38,9 @@ cricket::CaptureState RtcVideoCapturer::Start(
SetCaptureFormat(&capture_format); SetCaptureFormat(&capture_format);
state_ = VIDEO_CAPTURE_STATE_STARTED; state_ = VIDEO_CAPTURE_STATE_STARTED;
start_time_ = base::Time::Now(); first_frame_timestamp_ = media::kNoTimestamp();
delegate_->StartCapture(cap, delegate_->StartCapture(
cap,
base::Bind(&RtcVideoCapturer::OnFrameCaptured, base::Unretained(this)), base::Bind(&RtcVideoCapturer::OnFrameCaptured, base::Unretained(this)),
base::Bind(&RtcVideoCapturer::OnStateChange, base::Unretained(this))); base::Bind(&RtcVideoCapturer::OnStateChange, base::Unretained(this)));
// Update the desired aspect ratio so that later the video frame can be // Update the desired aspect ratio so that later the video frame can be
...@@ -95,34 +94,40 @@ bool RtcVideoCapturer::GetBestCaptureFormat(const cricket::VideoFormat& desired, ...@@ -95,34 +94,40 @@ bool RtcVideoCapturer::GetBestCaptureFormat(const cricket::VideoFormat& desired,
} }
void RtcVideoCapturer::OnFrameCaptured( void RtcVideoCapturer::OnFrameCaptured(
const media::VideoCapture::VideoFrameBuffer& buf) { const scoped_refptr<media::VideoFrame>& frame) {
if (first_frame_timestamp_ == media::kNoTimestamp())
first_frame_timestamp_ = frame->GetTimestamp();
// Currently, |fourcc| is always I420. // Currently, |fourcc| is always I420.
cricket::CapturedFrame frame; cricket::CapturedFrame captured_frame;
frame.width = buf.width; captured_frame.width = frame->coded_size().width();
frame.height = buf.height; captured_frame.height = frame->coded_size().height();
frame.fourcc = cricket::FOURCC_I420; captured_frame.fourcc = cricket::FOURCC_I420;
frame.data_size = buf.buffer_size;
// cricket::CapturedFrame time is in nanoseconds. // cricket::CapturedFrame time is in nanoseconds.
frame.elapsed_time = (buf.timestamp - start_time_).InMicroseconds() * captured_frame.elapsed_time =
base::Time::kNanosecondsPerMicrosecond; (frame->GetTimestamp() - first_frame_timestamp_).InMicroseconds() *
frame.time_stamp =
(buf.timestamp - base::Time::UnixEpoch()).InMicroseconds() *
base::Time::kNanosecondsPerMicrosecond; base::Time::kNanosecondsPerMicrosecond;
frame.data = buf.memory_pointer; captured_frame.time_stamp = frame->GetTimestamp().InMicroseconds() *
frame.pixel_height = 1; base::Time::kNanosecondsPerMicrosecond;
frame.pixel_width = 1; // TODO(sheu): we assume contiguous layout of image planes.
captured_frame.data = frame->data(0);
TRACE_EVENT_INSTANT2("rtc_video_capturer", captured_frame.data_size =
"OnFrameCaptured", media::VideoFrame::AllocationSize(frame->format(), frame->coded_size());
TRACE_EVENT_SCOPE_THREAD, captured_frame.pixel_height = 1;
"elapsed time", captured_frame.pixel_width = 1;
frame.elapsed_time,
"timestamp_ms", TRACE_EVENT_INSTANT2(
frame.time_stamp / talk_base::kNumNanosecsPerMillisec); "rtc_video_capturer",
"OnFrameCaptured",
TRACE_EVENT_SCOPE_THREAD,
"elapsed time",
captured_frame.elapsed_time,
"timestamp_ms",
captured_frame.time_stamp / talk_base::kNumNanosecsPerMillisec);
// This signals to libJingle that a new VideoFrame is available. // This signals to libJingle that a new VideoFrame is available.
// libJingle have no assumptions on what thread this signal come from. // libJingle have no assumptions on what thread this signal come from.
SignalFrameCaptured(this, &frame); SignalFrameCaptured(this, &captured_frame);
} }
void RtcVideoCapturer::OnStateChange( void RtcVideoCapturer::OnStateChange(
......
...@@ -41,8 +41,7 @@ class RtcVideoCapturer ...@@ -41,8 +41,7 @@ class RtcVideoCapturer
private: private:
// Frame captured callback method. // Frame captured callback method.
virtual void OnFrameCaptured( virtual void OnFrameCaptured(const scoped_refptr<media::VideoFrame>& frame);
const media::VideoCapture::VideoFrameBuffer& frame);
// State change callback, must be called on same thread as Start is called. // State change callback, must be called on same thread as Start is called.
void OnStateChange(RtcVideoCaptureDelegate::CaptureState state); void OnStateChange(RtcVideoCaptureDelegate::CaptureState state);
...@@ -50,7 +49,7 @@ class RtcVideoCapturer ...@@ -50,7 +49,7 @@ class RtcVideoCapturer
const bool is_screencast_; const bool is_screencast_;
scoped_refptr<RtcVideoCaptureDelegate> delegate_; scoped_refptr<RtcVideoCaptureDelegate> delegate_;
VideoCaptureState state_; VideoCaptureState state_;
base::Time start_time_; base::TimeDelta first_frame_timestamp_;
DISALLOW_COPY_AND_ASSIGN(RtcVideoCapturer); DISALLOW_COPY_AND_ASSIGN(RtcVideoCapturer);
}; };
......
...@@ -8,26 +8,35 @@ ...@@ -8,26 +8,35 @@
#include "base/stl_util.h" #include "base/stl_util.h"
#include "content/child/child_process.h" #include "content/child/child_process.h"
#include "content/common/media/video_capture_messages.h" #include "content/common/media/video_capture_messages.h"
#include "media/base/bind_to_loop.h"
#include "media/base/limits.h" #include "media/base/limits.h"
namespace content { namespace content {
struct VideoCaptureImpl::DIBBuffer { class VideoCaptureImpl::ClientBuffer : public base::RefCounted<ClientBuffer> {
public: public:
DIBBuffer( ClientBuffer(scoped_ptr<base::SharedMemory> buffer,
base::SharedMemory* d, size_t buffer_size,
media::VideoCapture::VideoFrameBuffer* ptr) int frame_width,
: dib(d), int frame_height,
mapped_memory(ptr), int frame_stride)
references(0) { : buffer(buffer.Pass()),
} buffer_size(buffer_size),
~DIBBuffer() {} frame_width(frame_width),
frame_height(frame_height),
scoped_ptr<base::SharedMemory> dib; frame_stride(frame_stride) {}
scoped_refptr<media::VideoCapture::VideoFrameBuffer> mapped_memory; const scoped_ptr<base::SharedMemory> buffer;
const size_t buffer_size;
// Number of clients which hold this DIB. const int frame_width; // In pixels.
int references; const int frame_height; // In pixels.
const int frame_stride; // In pixels.
private:
friend class base::RefCounted<ClientBuffer>;
virtual ~ClientBuffer() {}
DISALLOW_COPY_AND_ASSIGN(ClientBuffer);
}; };
bool VideoCaptureImpl::CaptureStarted() { bool VideoCaptureImpl::CaptureStarted() {
...@@ -55,6 +64,7 @@ VideoCaptureImpl::VideoCaptureImpl( ...@@ -55,6 +64,7 @@ VideoCaptureImpl::VideoCaptureImpl(
capture_message_loop_proxy_(capture_message_loop_proxy), capture_message_loop_proxy_(capture_message_loop_proxy),
io_message_loop_proxy_(ChildProcess::current()->io_message_loop_proxy()), io_message_loop_proxy_(ChildProcess::current()->io_message_loop_proxy()),
device_id_(0), device_id_(0),
client_buffer_weak_this_factory_(this),
video_type_(media::PIXEL_FORMAT_I420), video_type_(media::PIXEL_FORMAT_I420),
device_info_available_(false), device_info_available_(false),
suspended_(false), suspended_(false),
...@@ -63,9 +73,7 @@ VideoCaptureImpl::VideoCaptureImpl( ...@@ -63,9 +73,7 @@ VideoCaptureImpl::VideoCaptureImpl(
capture_format_.session_id = id; capture_format_.session_id = id;
} }
VideoCaptureImpl::~VideoCaptureImpl() { VideoCaptureImpl::~VideoCaptureImpl() {}
STLDeleteValues(&cached_dibs_);
}
void VideoCaptureImpl::Init() { void VideoCaptureImpl::Init() {
if (!io_message_loop_proxy_->BelongsToCurrentThread()) { if (!io_message_loop_proxy_->BelongsToCurrentThread()) {
...@@ -99,12 +107,6 @@ void VideoCaptureImpl::StopCapture(media::VideoCapture::EventHandler* handler) { ...@@ -99,12 +107,6 @@ void VideoCaptureImpl::StopCapture(media::VideoCapture::EventHandler* handler) {
base::Unretained(this), handler)); base::Unretained(this), handler));
} }
void VideoCaptureImpl::FeedBuffer(scoped_refptr<VideoFrameBuffer> buffer) {
capture_message_loop_proxy_->PostTask(FROM_HERE,
base::Bind(&VideoCaptureImpl::DoFeedBufferOnCaptureThread,
base::Unretained(this), buffer));
}
void VideoCaptureImpl::OnBufferCreated( void VideoCaptureImpl::OnBufferCreated(
base::SharedMemoryHandle handle, base::SharedMemoryHandle handle,
int length, int buffer_id) { int length, int buffer_id) {
...@@ -235,25 +237,8 @@ void VideoCaptureImpl::DoStopCaptureOnCaptureThread( ...@@ -235,25 +237,8 @@ void VideoCaptureImpl::DoStopCaptureOnCaptureThread(
if (clients_.empty()) { if (clients_.empty()) {
DVLOG(1) << "StopCapture: No more client, stopping ..."; DVLOG(1) << "StopCapture: No more client, stopping ...";
StopDevice(); StopDevice();
} client_buffers_.clear();
} client_buffer_weak_this_factory_.InvalidateWeakPtrs();
void VideoCaptureImpl::DoFeedBufferOnCaptureThread(
scoped_refptr<VideoFrameBuffer> buffer) {
DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
CachedDIB::iterator it;
for (it = cached_dibs_.begin(); it != cached_dibs_.end(); ++it) {
if (buffer.get() == it->second->mapped_memory.get())
break;
}
if (it != cached_dibs_.end() && it->second) {
DCHECK_GT(it->second->references, 0);
--it->second->references;
if (it->second->references == 0) {
Send(new VideoCaptureHostMsg_BufferReady(device_id_, it->first));
}
} }
} }
...@@ -271,20 +256,21 @@ void VideoCaptureImpl::DoBufferCreatedOnCaptureThread( ...@@ -271,20 +256,21 @@ void VideoCaptureImpl::DoBufferCreatedOnCaptureThread(
DCHECK(device_info_available_); DCHECK(device_info_available_);
media::VideoCapture::VideoFrameBuffer* buffer; scoped_ptr<base::SharedMemory> shm(new base::SharedMemory(handle, false));
DCHECK(cached_dibs_.find(buffer_id) == cached_dibs_.end()); if (!shm->Map(length)) {
DLOG(ERROR) << "DoBufferCreatedOnCaptureThread: Map() failed.";
base::SharedMemory* dib = new base::SharedMemory(handle, false); return;
dib->Map(length); }
buffer = new VideoFrameBuffer();
buffer->memory_pointer = static_cast<uint8*>(dib->memory());
buffer->buffer_size = length;
buffer->width = device_info_.width;
buffer->height = device_info_.height;
buffer->stride = device_info_.width;
DIBBuffer* dib_buffer = new DIBBuffer(dib, buffer); bool inserted =
cached_dibs_[buffer_id] = dib_buffer; client_buffers_.insert(std::make_pair(
buffer_id,
new ClientBuffer(shm.Pass(),
length,
device_info_.width,
device_info_.height,
device_info_.width))).second;
DCHECK(inserted);
} }
void VideoCaptureImpl::DoBufferReceivedOnCaptureThread( void VideoCaptureImpl::DoBufferReceivedOnCaptureThread(
...@@ -296,15 +282,38 @@ void VideoCaptureImpl::DoBufferReceivedOnCaptureThread( ...@@ -296,15 +282,38 @@ void VideoCaptureImpl::DoBufferReceivedOnCaptureThread(
return; return;
} }
media::VideoCapture::VideoFrameBuffer* buffer; ClientBufferMap::iterator iter = client_buffers_.find(buffer_id);
DCHECK(cached_dibs_.find(buffer_id) != cached_dibs_.end()); DCHECK(iter != client_buffers_.end());
buffer = cached_dibs_[buffer_id]->mapped_memory.get(); scoped_refptr<ClientBuffer> buffer = iter->second;
buffer->timestamp = timestamp; scoped_refptr<media::VideoFrame> frame =
media::VideoFrame::WrapExternalSharedMemory(
for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); ++it) { media::VideoFrame::I420,
it->first->OnBufferReady(this, buffer); gfx::Size(buffer->frame_stride, buffer->frame_height),
} gfx::Rect(0, 0, buffer->frame_width, buffer->frame_height),
cached_dibs_[buffer_id]->references = clients_.size(); gfx::Size(buffer->frame_width, buffer->frame_height),
reinterpret_cast<uint8*>(buffer->buffer->memory()),
buffer->buffer_size,
buffer->buffer->handle(),
// TODO(sheu): convert VideoCaptureMessageFilter::Delegate to use
// base::TimeTicks instead of base::Time. http://crbug.com/249215
timestamp - base::Time::UnixEpoch(),
media::BindToLoop(
capture_message_loop_proxy_,
base::Bind(
&VideoCaptureImpl::DoClientBufferFinishedOnCaptureThread,
client_buffer_weak_this_factory_.GetWeakPtr(),
buffer_id,
buffer)));
for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); ++it)
it->first->OnFrameReady(this, frame);
}
void VideoCaptureImpl::DoClientBufferFinishedOnCaptureThread(
int buffer_id,
const scoped_refptr<ClientBuffer>& buffer) {
DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id));
} }
void VideoCaptureImpl::DoStateChangedOnCaptureThread(VideoCaptureState state) { void VideoCaptureImpl::DoStateChangedOnCaptureThread(VideoCaptureState state) {
...@@ -316,7 +325,8 @@ void VideoCaptureImpl::DoStateChangedOnCaptureThread(VideoCaptureState state) { ...@@ -316,7 +325,8 @@ void VideoCaptureImpl::DoStateChangedOnCaptureThread(VideoCaptureState state) {
case VIDEO_CAPTURE_STATE_STOPPED: case VIDEO_CAPTURE_STATE_STOPPED:
state_ = VIDEO_CAPTURE_STATE_STOPPED; state_ = VIDEO_CAPTURE_STATE_STOPPED;
DVLOG(1) << "OnStateChanged: stopped!, device_id = " << device_id_; DVLOG(1) << "OnStateChanged: stopped!, device_id = " << device_id_;
STLDeleteValues(&cached_dibs_); client_buffers_.clear();
client_buffer_weak_this_factory_.InvalidateWeakPtrs();
if (!clients_.empty() || !clients_pending_on_restart_.empty()) if (!clients_.empty() || !clients_pending_on_restart_.empty())
RestartCapture(); RestartCapture();
break; break;
...@@ -354,9 +364,7 @@ void VideoCaptureImpl::DoStateChangedOnCaptureThread(VideoCaptureState state) { ...@@ -354,9 +364,7 @@ void VideoCaptureImpl::DoStateChangedOnCaptureThread(VideoCaptureState state) {
void VideoCaptureImpl::DoDeviceInfoReceivedOnCaptureThread( void VideoCaptureImpl::DoDeviceInfoReceivedOnCaptureThread(
const media::VideoCaptureParams& device_info) { const media::VideoCaptureParams& device_info) {
DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
DCHECK(!ClientHasDIB()); DCHECK(client_buffers_.empty());
STLDeleteValues(&cached_dibs_);
device_info_ = device_info; device_info_ = device_info;
device_info_available_ = true; device_info_available_ = true;
...@@ -462,16 +470,6 @@ void VideoCaptureImpl::Send(IPC::Message* message) { ...@@ -462,16 +470,6 @@ void VideoCaptureImpl::Send(IPC::Message* message) {
message_filter_.get(), message)); message_filter_.get(), message));
} }
bool VideoCaptureImpl::ClientHasDIB() const {
DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread());
for (CachedDIB::const_iterator it = cached_dibs_.begin();
it != cached_dibs_.end(); ++it) {
if (it->second->references > 0)
return true;
}
return false;
}
bool VideoCaptureImpl::RemoveClient( bool VideoCaptureImpl::RemoveClient(
media::VideoCapture::EventHandler* handler, media::VideoCapture::EventHandler* handler,
ClientInfo* clients) { ClientInfo* clients) {
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <list> #include <list>
#include <map> #include <map>
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "content/common/media/video_capture.h" #include "content/common/media/video_capture.h"
#include "content/renderer/media/video_capture_message_filter.h" #include "content/renderer/media/video_capture_message_filter.h"
...@@ -53,7 +54,6 @@ class CONTENT_EXPORT VideoCaptureImpl ...@@ -53,7 +54,6 @@ class CONTENT_EXPORT VideoCaptureImpl
media::VideoCapture::EventHandler* handler, media::VideoCapture::EventHandler* handler,
const media::VideoCaptureCapability& capability) OVERRIDE; const media::VideoCaptureCapability& capability) OVERRIDE;
virtual void StopCapture(media::VideoCapture::EventHandler* handler) OVERRIDE; virtual void StopCapture(media::VideoCapture::EventHandler* handler) OVERRIDE;
virtual void FeedBuffer(scoped_refptr<VideoFrameBuffer> buffer) OVERRIDE;
virtual bool CaptureStarted() OVERRIDE; virtual bool CaptureStarted() OVERRIDE;
virtual int CaptureWidth() OVERRIDE; virtual int CaptureWidth() OVERRIDE;
virtual int CaptureHeight() OVERRIDE; virtual int CaptureHeight() OVERRIDE;
...@@ -78,9 +78,9 @@ class CONTENT_EXPORT VideoCaptureImpl ...@@ -78,9 +78,9 @@ class CONTENT_EXPORT VideoCaptureImpl
friend class VideoCaptureImplTest; friend class VideoCaptureImplTest;
friend class MockVideoCaptureImpl; friend class MockVideoCaptureImpl;
struct DIBBuffer; class ClientBuffer;
typedef std::map<media::VideoCapture::EventHandler*, typedef std::map<media::VideoCapture::EventHandler*,
media::VideoCaptureCapability> ClientInfo; media::VideoCaptureCapability> ClientInfo;
VideoCaptureImpl(media::VideoCaptureSessionId id, VideoCaptureImpl(media::VideoCaptureSessionId id,
base::MessageLoopProxy* capture_message_loop_proxy, base::MessageLoopProxy* capture_message_loop_proxy,
...@@ -91,11 +91,12 @@ class CONTENT_EXPORT VideoCaptureImpl ...@@ -91,11 +91,12 @@ class CONTENT_EXPORT VideoCaptureImpl
media::VideoCapture::EventHandler* handler, media::VideoCapture::EventHandler* handler,
const media::VideoCaptureCapability& capability); const media::VideoCaptureCapability& capability);
void DoStopCaptureOnCaptureThread(media::VideoCapture::EventHandler* handler); void DoStopCaptureOnCaptureThread(media::VideoCapture::EventHandler* handler);
void DoFeedBufferOnCaptureThread(scoped_refptr<VideoFrameBuffer> buffer);
void DoBufferCreatedOnCaptureThread(base::SharedMemoryHandle handle, void DoBufferCreatedOnCaptureThread(base::SharedMemoryHandle handle,
int length, int buffer_id); int length, int buffer_id);
void DoBufferReceivedOnCaptureThread(int buffer_id, base::Time timestamp); void DoBufferReceivedOnCaptureThread(int buffer_id, base::Time timestamp);
void DoClientBufferFinishedOnCaptureThread(
int buffer_id,
const scoped_refptr<ClientBuffer>& buffer);
void DoStateChangedOnCaptureThread(VideoCaptureState state); void DoStateChangedOnCaptureThread(VideoCaptureState state);
void DoDeviceInfoReceivedOnCaptureThread( void DoDeviceInfoReceivedOnCaptureThread(
const media::VideoCaptureParams& device_info); const media::VideoCaptureParams& device_info);
...@@ -116,7 +117,6 @@ class CONTENT_EXPORT VideoCaptureImpl ...@@ -116,7 +117,6 @@ class CONTENT_EXPORT VideoCaptureImpl
virtual void Send(IPC::Message* message); virtual void Send(IPC::Message* message);
// Helpers. // Helpers.
bool ClientHasDIB() const;
bool RemoveClient(media::VideoCapture::EventHandler* handler, bool RemoveClient(media::VideoCapture::EventHandler* handler,
ClientInfo* clients); ClientInfo* clients);
...@@ -125,9 +125,13 @@ class CONTENT_EXPORT VideoCaptureImpl ...@@ -125,9 +125,13 @@ class CONTENT_EXPORT VideoCaptureImpl
const scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_; const scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
int device_id_; int device_id_;
// Pool of DIBs. The key is buffer_id. // Buffers available for sending to the client.
typedef std::map<int, DIBBuffer*> CachedDIB; typedef std::map<int32, scoped_refptr<ClientBuffer> > ClientBufferMap;
CachedDIB cached_dibs_; ClientBufferMap client_buffers_;
// WeakPtrFactory pointing back to |this| object, for use with
// media::VideoFrames constructed in OnBufferReceived() from buffers cached
// in |client_buffers_|.
base::WeakPtrFactory<VideoCaptureImpl> client_buffer_weak_this_factory_;
ClientInfo clients_; ClientInfo clients_;
......
...@@ -40,9 +40,9 @@ class MockVideoCaptureClient : public media::VideoCapture::EventHandler { ...@@ -40,9 +40,9 @@ class MockVideoCaptureClient : public media::VideoCapture::EventHandler {
MOCK_METHOD1(OnPaused, void(media::VideoCapture* capture)); MOCK_METHOD1(OnPaused, void(media::VideoCapture* capture));
MOCK_METHOD2(OnError, void(media::VideoCapture* capture, int error_code)); MOCK_METHOD2(OnError, void(media::VideoCapture* capture, int error_code));
MOCK_METHOD1(OnRemoved, void(media::VideoCapture* capture)); MOCK_METHOD1(OnRemoved, void(media::VideoCapture* capture));
MOCK_METHOD2(OnBufferReady, MOCK_METHOD2(OnFrameReady,
void(media::VideoCapture* capture, void(media::VideoCapture* capture,
scoped_refptr<media::VideoCapture::VideoFrameBuffer> buf)); const scoped_refptr<media::VideoFrame>& frame));
MOCK_METHOD2(OnDeviceInfoReceived, MOCK_METHOD2(OnDeviceInfoReceived,
void(media::VideoCapture* capture, void(media::VideoCapture* capture,
const media::VideoCaptureParams& device_info)); const media::VideoCaptureParams& device_info));
......
...@@ -87,8 +87,7 @@ class CONTENT_EXPORT VideoCaptureMessageFilter ...@@ -87,8 +87,7 @@ class CONTENT_EXPORT VideoCaptureMessageFilter
int length, int buffer_id); int length, int buffer_id);
// Receive a buffer from browser process. // Receive a buffer from browser process.
void OnBufferReceived(int device_id, void OnBufferReceived(int device_id, int buffer_id, base::Time timestamp);
int buffer_id, base::Time timestamp);
// State of browser process' video capture device has changed. // State of browser process' video capture device has changed.
void OnDeviceStateChanged(int device_id, VideoCaptureState state); void OnDeviceStateChanged(int device_id, VideoCaptureState state);
......
...@@ -71,12 +71,6 @@ void PepperPlatformVideoCapture::StopCapture( ...@@ -71,12 +71,6 @@ void PepperPlatformVideoCapture::StopCapture(
} }
} }
void PepperPlatformVideoCapture::FeedBuffer(
scoped_refptr<VideoFrameBuffer> buffer) {
if (video_capture_)
video_capture_->FeedBuffer(buffer);
}
bool PepperPlatformVideoCapture::CaptureStarted() { bool PepperPlatformVideoCapture::CaptureStarted() {
return handler_proxy_->state().started; return handler_proxy_->state().started;
} }
...@@ -145,16 +139,11 @@ void PepperPlatformVideoCapture::OnRemoved(VideoCapture* capture) { ...@@ -145,16 +139,11 @@ void PepperPlatformVideoCapture::OnRemoved(VideoCapture* capture) {
Release(); // Balance the AddRef() in StartCapture(). Release(); // Balance the AddRef() in StartCapture().
} }
void PepperPlatformVideoCapture::OnBufferReady( void PepperPlatformVideoCapture::OnFrameReady(
VideoCapture* capture, VideoCapture* capture,
scoped_refptr<VideoFrameBuffer> buffer) { const scoped_refptr<media::VideoFrame>& frame) {
if (handler_) { if (handler_)
handler_->OnBufferReady(capture, buffer); handler_->OnFrameReady(capture, frame);
} 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( void PepperPlatformVideoCapture::OnDeviceInfoReceived(
......
...@@ -44,7 +44,6 @@ class PepperPlatformVideoCapture ...@@ -44,7 +44,6 @@ class PepperPlatformVideoCapture
media::VideoCapture::EventHandler* handler, media::VideoCapture::EventHandler* handler,
const media::VideoCaptureCapability& capability) OVERRIDE; const media::VideoCaptureCapability& capability) OVERRIDE;
virtual void StopCapture(media::VideoCapture::EventHandler* handler) OVERRIDE; virtual void StopCapture(media::VideoCapture::EventHandler* handler) OVERRIDE;
virtual void FeedBuffer(scoped_refptr<VideoFrameBuffer> buffer) OVERRIDE;
virtual bool CaptureStarted() OVERRIDE; virtual bool CaptureStarted() OVERRIDE;
virtual int CaptureWidth() OVERRIDE; virtual int CaptureWidth() OVERRIDE;
virtual int CaptureHeight() OVERRIDE; virtual int CaptureHeight() OVERRIDE;
...@@ -56,8 +55,9 @@ class PepperPlatformVideoCapture ...@@ -56,8 +55,9 @@ class PepperPlatformVideoCapture
virtual void OnPaused(VideoCapture* capture) OVERRIDE; virtual void OnPaused(VideoCapture* capture) OVERRIDE;
virtual void OnError(VideoCapture* capture, int error_code) OVERRIDE; virtual void OnError(VideoCapture* capture, int error_code) OVERRIDE;
virtual void OnRemoved(VideoCapture* capture) OVERRIDE; virtual void OnRemoved(VideoCapture* capture) OVERRIDE;
virtual void OnBufferReady(VideoCapture* capture, virtual void OnFrameReady(
scoped_refptr<VideoFrameBuffer> buffer) OVERRIDE; VideoCapture* capture,
const scoped_refptr<media::VideoFrame>& frame) OVERRIDE;
virtual void OnDeviceInfoReceived( virtual void OnDeviceInfoReceived(
VideoCapture* capture, VideoCapture* capture,
const media::VideoCaptureParams& device_info) OVERRIDE; const media::VideoCaptureParams& device_info) OVERRIDE;
......
...@@ -129,29 +129,40 @@ void PepperVideoCaptureHost::OnError(media::VideoCapture* capture, ...@@ -129,29 +129,40 @@ void PepperVideoCaptureHost::OnError(media::VideoCapture* capture,
void PepperVideoCaptureHost::OnRemoved(media::VideoCapture* capture) { void PepperVideoCaptureHost::OnRemoved(media::VideoCapture* capture) {
} }
void PepperVideoCaptureHost::OnBufferReady( void PepperVideoCaptureHost::OnFrameReady(
media::VideoCapture* capture, media::VideoCapture* capture,
scoped_refptr<media::VideoCapture::VideoFrameBuffer> buffer) { const scoped_refptr<media::VideoFrame>& frame) {
DCHECK(buffer.get()); DCHECK(frame.get());
for (uint32_t i = 0; i < buffers_.size(); ++i) { for (uint32_t i = 0; i < buffers_.size(); ++i) {
if (!buffers_[i].in_use) { if (!buffers_[i].in_use) {
// TODO(ihf): Switch to a size calculation based on stride. DCHECK_EQ(frame->format(), media::VideoFrame::I420);
// Stride is filled out now but not more meaningful than size if (buffers_[i].buffer->size() <
// until wjia unifies VideoFrameBuffer and media::VideoFrame. media::VideoFrame::AllocationSize(frame->format(),
size_t size = std::min(static_cast<size_t>(buffers_[i].buffer->size()), frame->coded_size())) {
buffer->buffer_size); // TODO(ihf): handle size mismatches gracefully here.
memcpy(buffers_[i].data, buffer->memory_pointer, size); return;
}
uint8* dst = reinterpret_cast<uint8*>(buffers_[i].data);
COMPILE_ASSERT(media::VideoFrame::kYPlane == 0, y_plane_should_be_0);
COMPILE_ASSERT(media::VideoFrame::kUPlane == 1, u_plane_should_be_1);
COMPILE_ASSERT(media::VideoFrame::kVPlane == 2, v_plane_should_be_2);
for (size_t j = 0; j < media::VideoFrame::NumPlanes(frame->format());
++j) {
const uint8* src = frame->data(j);
const size_t row_bytes = frame->row_bytes(j);
const size_t src_stride = frame->stride(j);
for (int k = 0; k < frame->rows(j); ++k) {
memcpy(dst, src, row_bytes);
dst += row_bytes;
src += src_stride;
}
}
buffers_[i].in_use = true; buffers_[i].in_use = true;
platform_video_capture_->FeedBuffer(buffer);
host()->SendUnsolicitedReply(pp_resource(), host()->SendUnsolicitedReply(pp_resource(),
PpapiPluginMsg_VideoCapture_OnBufferReady(i)); PpapiPluginMsg_VideoCapture_OnBufferReady(i));
return; return;
} }
} }
// No free slot, just discard the frame and tell the media layer it can
// re-use the buffer.
platform_video_capture_->FeedBuffer(buffer);
} }
void PepperVideoCaptureHost::OnDeviceInfoReceived( void PepperVideoCaptureHost::OnDeviceInfoReceived(
...@@ -164,10 +175,8 @@ void PepperVideoCaptureHost::OnDeviceInfoReceived( ...@@ -164,10 +175,8 @@ void PepperVideoCaptureHost::OnDeviceInfoReceived(
}; };
ReleaseBuffers(); ReleaseBuffers();
// YUV 4:2:0 const size_t size = media::VideoFrame::AllocationSize(
int uv_width = info.width / 2; media::VideoFrame::I420, gfx::Size(info.width, info.height));
int uv_height = info.height / 2;
size_t size = info.width * info.height + 2 * uv_width * uv_height;
ppapi::proxy::ResourceMessageReplyParams params(pp_resource(), 0); ppapi::proxy::ResourceMessageReplyParams params(pp_resource(), 0);
......
...@@ -44,9 +44,9 @@ class PepperVideoCaptureHost ...@@ -44,9 +44,9 @@ class PepperVideoCaptureHost
virtual void OnPaused(media::VideoCapture* capture) OVERRIDE; virtual void OnPaused(media::VideoCapture* capture) OVERRIDE;
virtual void OnError(media::VideoCapture* capture, int error_code) OVERRIDE; virtual void OnError(media::VideoCapture* capture, int error_code) OVERRIDE;
virtual void OnRemoved(media::VideoCapture* capture) OVERRIDE; virtual void OnRemoved(media::VideoCapture* capture) OVERRIDE;
virtual void OnBufferReady( virtual void OnFrameReady(
media::VideoCapture* capture, media::VideoCapture* capture,
scoped_refptr<media::VideoCapture::VideoFrameBuffer> buffer) OVERRIDE; const scoped_refptr<media::VideoFrame>& frame) OVERRIDE;
virtual void OnDeviceInfoReceived( virtual void OnDeviceInfoReceived(
media::VideoCapture* capture, media::VideoCapture* capture,
const media::VideoCaptureParams& device_info) OVERRIDE; const media::VideoCaptureParams& device_info) OVERRIDE;
......
...@@ -11,37 +11,14 @@ ...@@ -11,37 +11,14 @@
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "media/base/media_export.h" #include "media/base/media_export.h"
#include "media/base/video_frame.h"
#include "media/video/capture/video_capture_types.h" #include "media/video/capture/video_capture_types.h"
namespace media { namespace media {
class VideoFrame;
class MEDIA_EXPORT VideoCapture { class MEDIA_EXPORT VideoCapture {
public: public:
// TODO(wjia): consider merging with media::VideoFrame if possible.
class VideoFrameBuffer : public base::RefCountedThreadSafe<VideoFrameBuffer> {
public:
VideoFrameBuffer()
: width(0),
height(0),
stride(0),
buffer_size(0),
memory_pointer(NULL) {}
int width;
int height;
int stride;
size_t buffer_size;
uint8* memory_pointer;
base::Time timestamp;
private:
friend class base::RefCountedThreadSafe<VideoFrameBuffer>;
~VideoFrameBuffer() {}
DISALLOW_COPY_AND_ASSIGN(VideoFrameBuffer);
};
// TODO(wjia): add error codes. // TODO(wjia): add error codes.
// TODO(wjia): support weak ptr. // TODO(wjia): support weak ptr.
// Callbacks provided by client for notification of events. // Callbacks provided by client for notification of events.
...@@ -64,8 +41,9 @@ class MEDIA_EXPORT VideoCapture { ...@@ -64,8 +41,9 @@ class MEDIA_EXPORT VideoCapture {
virtual void OnRemoved(VideoCapture* capture) = 0; virtual void OnRemoved(VideoCapture* capture) = 0;
// Notify client that a buffer is available. // Notify client that a buffer is available.
virtual void OnBufferReady(VideoCapture* capture, virtual void OnFrameReady(
scoped_refptr<VideoFrameBuffer> buffer) = 0; VideoCapture* capture,
const scoped_refptr<media::VideoFrame>& frame) = 0;
// Notify client about device info. // Notify client about device info.
virtual void OnDeviceInfoReceived( virtual void OnDeviceInfoReceived(
...@@ -93,9 +71,6 @@ class MEDIA_EXPORT VideoCapture { ...@@ -93,9 +71,6 @@ class MEDIA_EXPORT VideoCapture {
// |handler| must remain valid until it has received |OnRemoved()|. // |handler| must remain valid until it has received |OnRemoved()|.
virtual void StopCapture(EventHandler* handler) = 0; virtual void StopCapture(EventHandler* handler) = 0;
// Feed buffer to video capture when done with it.
virtual void FeedBuffer(scoped_refptr<VideoFrameBuffer> buffer) = 0;
virtual bool CaptureStarted() = 0; virtual bool CaptureStarted() = 0;
virtual int CaptureWidth() = 0; virtual int CaptureWidth() = 0;
virtual int CaptureHeight() = 0; virtual int CaptureHeight() = 0;
......
...@@ -77,15 +77,16 @@ void VideoCaptureHandlerProxy::OnRemoved(VideoCapture* capture) { ...@@ -77,15 +77,16 @@ void VideoCaptureHandlerProxy::OnRemoved(VideoCapture* capture) {
GetState(capture))); GetState(capture)));
} }
void VideoCaptureHandlerProxy::OnBufferReady( void VideoCaptureHandlerProxy::OnFrameReady(
VideoCapture* capture, VideoCapture* capture,
scoped_refptr<VideoCapture::VideoFrameBuffer> buffer) { const scoped_refptr<VideoFrame>& frame) {
main_message_loop_->PostTask(FROM_HERE, base::Bind( main_message_loop_->PostTask(
&VideoCaptureHandlerProxy::OnBufferReadyOnMainThread, FROM_HERE,
base::Unretained(this), base::Bind(&VideoCaptureHandlerProxy::OnFrameReadyOnMainThread,
capture, base::Unretained(this),
GetState(capture), capture,
buffer)); GetState(capture),
frame));
} }
void VideoCaptureHandlerProxy::OnDeviceInfoReceived( void VideoCaptureHandlerProxy::OnDeviceInfoReceived(
...@@ -135,12 +136,12 @@ void VideoCaptureHandlerProxy::OnRemovedOnMainThread( ...@@ -135,12 +136,12 @@ void VideoCaptureHandlerProxy::OnRemovedOnMainThread(
proxied_->OnRemoved(capture); proxied_->OnRemoved(capture);
} }
void VideoCaptureHandlerProxy::OnBufferReadyOnMainThread( void VideoCaptureHandlerProxy::OnFrameReadyOnMainThread(
VideoCapture* capture, VideoCapture* capture,
const VideoCaptureState& state, const VideoCaptureState& state,
scoped_refptr<VideoCapture::VideoFrameBuffer> buffer) { const scoped_refptr<VideoFrame>& frame) {
state_ = state; state_ = state;
proxied_->OnBufferReady(capture, buffer); proxied_->OnFrameReady(capture, frame);
} }
void VideoCaptureHandlerProxy::OnDeviceInfoReceivedOnMainThread( void VideoCaptureHandlerProxy::OnDeviceInfoReceivedOnMainThread(
......
...@@ -50,9 +50,8 @@ class MEDIA_EXPORT VideoCaptureHandlerProxy ...@@ -50,9 +50,8 @@ class MEDIA_EXPORT VideoCaptureHandlerProxy
virtual void OnPaused(VideoCapture* capture) OVERRIDE; virtual void OnPaused(VideoCapture* capture) OVERRIDE;
virtual void OnError(VideoCapture* capture, int error_code) OVERRIDE; virtual void OnError(VideoCapture* capture, int error_code) OVERRIDE;
virtual void OnRemoved(VideoCapture* capture) OVERRIDE; virtual void OnRemoved(VideoCapture* capture) OVERRIDE;
virtual void OnBufferReady( virtual void OnFrameReady(VideoCapture* capture,
VideoCapture* capture, const scoped_refptr<VideoFrame>& frame) OVERRIDE;
scoped_refptr<VideoCapture::VideoFrameBuffer> buffer) OVERRIDE;
virtual void OnDeviceInfoReceived( virtual void OnDeviceInfoReceived(
VideoCapture* capture, VideoCapture* capture,
const VideoCaptureParams& device_info) OVERRIDE; const VideoCaptureParams& device_info) OVERRIDE;
...@@ -75,14 +74,12 @@ class MEDIA_EXPORT VideoCaptureHandlerProxy ...@@ -75,14 +74,12 @@ class MEDIA_EXPORT VideoCaptureHandlerProxy
void OnRemovedOnMainThread( void OnRemovedOnMainThread(
VideoCapture* capture, VideoCapture* capture,
const VideoCaptureState& state); const VideoCaptureState& state);
void OnBufferReadyOnMainThread( void OnFrameReadyOnMainThread(VideoCapture* capture,
VideoCapture* capture, const VideoCaptureState& state,
const VideoCaptureState& state, const scoped_refptr<VideoFrame>& frame);
scoped_refptr<VideoCapture::VideoFrameBuffer> buffer); void OnDeviceInfoReceivedOnMainThread(VideoCapture* capture,
void OnDeviceInfoReceivedOnMainThread( const VideoCaptureState& state,
VideoCapture* capture, const VideoCaptureParams& device_info);
const VideoCaptureState& state,
const VideoCaptureParams& device_info);
// Only accessed from main thread. // Only accessed from main thread.
VideoCapture::EventHandler* proxied_; VideoCapture::EventHandler* proxied_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment