Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Unified Diff: content/browser/media/capture/web_contents_video_capture_device.cc

Issue 1412173003: cast: support cursor rendering for tab capture (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Removed left over logs Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/media/capture/web_contents_video_capture_device.cc
diff --git a/content/browser/media/capture/web_contents_video_capture_device.cc b/content/browser/media/capture/web_contents_video_capture_device.cc
index 64312d9a7c92fd296700e79464d0ecb1d8d004f6..265080ba181d383c910357418d9b0e2ba220ff8a 100644
--- a/content/browser/media/capture/web_contents_video_capture_device.cc
+++ b/content/browser/media/capture/web_contents_video_capture_device.cc
@@ -50,6 +50,8 @@
#include "content/browser/media/capture/web_contents_video_capture_device.h"
+#include <algorithm>
+
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/callback_helpers.h"
@@ -63,6 +65,7 @@
#include "base/threading/thread.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
+#include "content/browser/media/capture/cursor_renderer.h"
#include "content/browser/media/capture/web_contents_capture_util.h"
#include "content/browser/media/capture/web_contents_tracker.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
@@ -119,10 +122,12 @@ class FrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
public:
FrameSubscriber(media::VideoCaptureOracle::Event event_type,
const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle,
- VideoFrameDeliveryLog* delivery_log)
+ VideoFrameDeliveryLog* delivery_log,
+ content::CursorRenderer* cursor_renderer)
: event_type_(event_type),
oracle_proxy_(oracle),
- delivery_log_(delivery_log) {}
+ delivery_log_(delivery_log),
+ cursor_renderer_(cursor_renderer) {}
bool ShouldCaptureFrame(
const gfx::Rect& damage_rect,
@@ -131,10 +136,18 @@ class FrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback*
deliver_frame_cb) override;
+ void DidCaptureFrame(const scoped_refptr<media::VideoFrame>& frame,
+ base::TimeTicks timestamp,
+ gfx::Rect region_in_frame,
+ bool success);
+
private:
const media::VideoCaptureOracle::Event event_type_;
scoped_refptr<media::ThreadSafeCaptureOracle> oracle_proxy_;
VideoFrameDeliveryLog* const delivery_log_;
+ content::CursorRenderer* const cursor_renderer_;
+
+ media::ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb_;
};
// ContentCaptureSubscription is the relationship between a RenderWidgetHost
@@ -177,10 +190,15 @@ class ContentCaptureSubscription {
const int render_widget_id_;
VideoFrameDeliveryLog delivery_log_;
- FrameSubscriber timer_subscriber_;
+ scoped_ptr<FrameSubscriber> timer_subscriber_;
CaptureCallback capture_callback_;
base::Timer timer_;
+ // Responsible for tracking the cursor state and input events to make
+ // decisions and then render the mouse cursor on the video frame after
+ // capture is completed.
+ scoped_ptr<content::CursorRenderer> cursor_renderer_;
+
DISALLOW_COPY_AND_ASSIGN(ContentCaptureSubscription);
};
@@ -195,7 +213,7 @@ class ContentCaptureSubscription {
// thread where such a pause would cause UI jank.
void RenderVideoFrame(const SkBitmap& input,
const scoped_refptr<media::VideoFrame>& output,
- const base::Callback<void(bool)>& done_cb);
+ const base::Callback<void(gfx::Rect, bool)>& done_cb);
// Renews capture subscriptions based on feedback from WebContentsTracker, and
// also executes copying of the backing store on the UI BrowserThread.
@@ -249,6 +267,7 @@ class WebContentsCaptureMachine : public media::VideoCaptureMachine {
const base::TimeTicks& start_time,
const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&
deliver_frame_cb,
+ gfx::Rect region_in_frame,
bool success);
// Remove the old subscription, and attempt to start a new one if |had_target|
@@ -303,17 +322,29 @@ bool FrameSubscriber::ShouldCaptureFrame(
TRACE_EVENT1("gpu.capture", "FrameSubscriber::ShouldCaptureFrame",
"instance", this);
- media::ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb;
bool oracle_decision = oracle_proxy_->ObserveEventAndDecideCapture(
- event_type_, damage_rect, present_time, storage, &capture_frame_cb);
+ event_type_, damage_rect, present_time, storage, &capture_frame_cb_);
miu 2015/10/20 02:12:44 Unfortunately, you can't store this in a single |c
Irfan 2015/10/21 23:01:08 Done.
- if (!capture_frame_cb.is_null())
- *deliver_frame_cb = base::Bind(capture_frame_cb, *storage);
+ if (!capture_frame_cb_.is_null())
+ *deliver_frame_cb = base::Bind(&FrameSubscriber::DidCaptureFrame,
+ base::Unretained(this), *storage);
if (oracle_decision)
delivery_log_->ChronicleFrameDelivery(present_time);
return oracle_decision;
}
+void FrameSubscriber::DidCaptureFrame(
+ const scoped_refptr<media::VideoFrame>& frame,
+ base::TimeTicks timestamp,
+ gfx::Rect region_in_frame,
+ bool success) {
+ if (cursor_renderer_ && success) {
+ if (cursor_renderer_->Update(region_in_frame))
+ cursor_renderer_->RenderOnVideoFrame(frame);
+ }
+ capture_frame_cb_.Run(frame, timestamp, success);
+}
+
ContentCaptureSubscription::ContentCaptureSubscription(
const RenderWidgetHost& source,
const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy,
@@ -321,20 +352,24 @@ ContentCaptureSubscription::ContentCaptureSubscription(
: render_process_id_(source.GetProcess()->GetID()),
render_widget_id_(source.GetRoutingID()),
delivery_log_(),
- timer_subscriber_(media::VideoCaptureOracle::kTimerPoll, oracle_proxy,
- &delivery_log_),
capture_callback_(capture_callback),
timer_(true, true) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderWidgetHostView* const view = source.GetView();
+ cursor_renderer_.reset(new content::CursorRenderer(
miu 2015/10/20 02:12:44 nit: These can go back into the initializer list a
Irfan 2015/10/21 23:01:08 I retained this mainly because it depends on fetch
+ view->GetNativeView(), content::ENABLE_MOUSE_EVENTS));
+ timer_subscriber_.reset(
+ new FrameSubscriber(media::VideoCaptureOracle::kTimerPoll, oracle_proxy,
+ &delivery_log_, cursor_renderer_.get()));
// Subscribe to compositor updates. These will be serviced directly by the
// oracle.
if (view) {
scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber(
new FrameSubscriber(media::VideoCaptureOracle::kCompositorUpdate,
- oracle_proxy, &delivery_log_));
+ oracle_proxy, &delivery_log_,
+ cursor_renderer_.get()));
view->BeginFrameSubscription(subscriber.Pass());
}
@@ -370,18 +405,17 @@ void ContentCaptureSubscription::OnTimer() {
RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback deliver_frame_cb;
const base::TimeTicks start_time = base::TimeTicks::Now();
- if (timer_subscriber_.ShouldCaptureFrame(gfx::Rect(),
- start_time,
- &frame,
- &deliver_frame_cb)) {
+ if (timer_subscriber_->ShouldCaptureFrame(gfx::Rect(), start_time, &frame,
+ &deliver_frame_cb)) {
capture_callback_.Run(start_time, frame, deliver_frame_cb);
}
}
void RenderVideoFrame(const SkBitmap& input,
const scoped_refptr<media::VideoFrame>& output,
- const base::Callback<void(bool)>& done_cb) {
- base::ScopedClosureRunner failure_handler(base::Bind(done_cb, false));
+ const base::Callback<void(gfx::Rect, bool)>& done_cb) {
+ base::ScopedClosureRunner failure_handler(
+ base::Bind(done_cb, gfx::Rect(), false));
SkAutoLockPixels locker(input);
@@ -412,7 +446,6 @@ void RenderVideoFrame(const SkBitmap& input,
SkBitmap scaled_bitmap;
if (input.width() != region_in_frame.width() ||
input.height() != region_in_frame.height()) {
-
skia::ImageOperations::ResizeMethod method;
if (input.width() < region_in_frame.width() ||
input.height() < region_in_frame.height()) {
@@ -453,7 +486,7 @@ void RenderVideoFrame(const SkBitmap& input,
// The result is now ready.
ignore_result(failure_handler.Release());
- done_cb.Run(true);
+ done_cb.Run(region_in_frame, true);
}
VideoFrameDeliveryLog::VideoFrameDeliveryLog()
@@ -597,7 +630,7 @@ void WebContentsCaptureMachine::Capture(
RenderWidgetHostViewBase* view =
rwh ? static_cast<RenderWidgetHostViewBase*>(rwh->GetView()) : NULL;
if (!view) {
- deliver_frame_cb.Run(base::TimeTicks(), false);
+ deliver_frame_cb.Run(base::TimeTicks(), gfx::Rect(), false);
return;
}
@@ -722,7 +755,7 @@ void WebContentsCaptureMachine::DidCopyFromBackingStore(
} else {
// Capture can fail due to transient issues, so just skip this frame.
DVLOG(1) << "CopyFromBackingStore failed; skipping frame.";
- deliver_frame_cb.Run(start_time, false);
+ deliver_frame_cb.Run(start_time, gfx::Rect(), false);
}
}
@@ -730,6 +763,7 @@ void WebContentsCaptureMachine::DidCopyFromCompositingSurfaceToVideoFrame(
const base::TimeTicks& start_time,
const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&
deliver_frame_cb,
+ gfx::Rect region_in_frame,
bool success) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::TimeTicks now = base::TimeTicks::Now();
@@ -740,7 +774,7 @@ void WebContentsCaptureMachine::DidCopyFromCompositingSurfaceToVideoFrame(
// Capture can fail due to transient issues, so just skip this frame.
DVLOG(1) << "CopyFromCompositingSurface failed; skipping frame.";
}
- deliver_frame_cb.Run(start_time, success);
+ deliver_frame_cb.Run(start_time, region_in_frame, success);
}
void WebContentsCaptureMachine::RenewFrameSubscription(bool had_target) {

Powered by Google App Engine
This is Rietveld 408576698