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

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: Add missing cursor renderer files in repo 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..623823b4df1a48764ea6fac0ac8cd0264efdacd1 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>
xjz 2015/10/22 17:08:42 Still think no need to include this.
Irfan 2015/10/26 23:10:32 This was a lint error unrelated to my code change
+
#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"
@@ -84,6 +87,12 @@
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/geometry/size_conversions.h"
+#if defined(USE_AURA)
+#include "content/browser/media/capture/cursor_renderer_aura.h"
+#else
+#include "content/browser/media/capture/cursor_renderer_dummy.h"
miu 2015/10/23 01:55:13 Suggest you don't provide the #else clause. See c
Irfan 2015/10/26 23:10:31 Done.
+#endif
+
namespace content {
namespace {
@@ -119,10 +128,13 @@ class FrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
public:
FrameSubscriber(media::VideoCaptureOracle::Event event_type,
const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle,
- VideoFrameDeliveryLog* delivery_log)
+ VideoFrameDeliveryLog* delivery_log,
+ base::WeakPtr<content::CursorRenderer> cursor_renderer)
: event_type_(event_type),
oracle_proxy_(oracle),
- delivery_log_(delivery_log) {}
+ delivery_log_(delivery_log),
+ cursor_renderer_(cursor_renderer),
+ weak_ptr_factory_(this) {}
bool ShouldCaptureFrame(
const gfx::Rect& damage_rect,
@@ -131,10 +143,20 @@ class FrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback*
deliver_frame_cb) override;
+ static void DidCaptureFrame(
+ base::WeakPtr<FrameSubscriber> frame_subscriber_,
+ media::ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb,
miu 2015/10/23 01:55:13 Please pass the callback by const reference. The
Irfan 2015/10/26 23:10:32 Done.
+ const scoped_refptr<media::VideoFrame>& frame,
+ base::TimeTicks timestamp,
+ gfx::Rect region_in_frame,
miu 2015/10/23 01:55:13 The gfx::Rect should be passed by const reference
Irfan 2015/10/26 23:10:32 Done.
+ bool success);
+
private:
const media::VideoCaptureOracle::Event event_type_;
scoped_refptr<media::ThreadSafeCaptureOracle> oracle_proxy_;
VideoFrameDeliveryLog* const delivery_log_;
+ base::WeakPtr<content::CursorRenderer> cursor_renderer_;
miu 2015/10/23 01:55:13 Please document why we need a weak pointer to the
miu 2015/10/23 01:55:13 No need for content:: qualifier.
Irfan 2015/10/26 23:10:31 Done.
Irfan 2015/10/26 23:10:32 Done.
+ base::WeakPtrFactory<FrameSubscriber> weak_ptr_factory_;
};
// ContentCaptureSubscription is the relationship between a RenderWidgetHost
@@ -177,10 +199,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 +222,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 +276,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|
@@ -304,16 +332,34 @@ bool 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);
if (!capture_frame_cb.is_null())
- *deliver_frame_cb = base::Bind(capture_frame_cb, *storage);
+ *deliver_frame_cb =
+ base::Bind(&FrameSubscriber::DidCaptureFrame,
+ weak_ptr_factory_.GetWeakPtr(), capture_frame_cb, *storage);
if (oracle_decision)
delivery_log_->ChronicleFrameDelivery(present_time);
return oracle_decision;
}
+void FrameSubscriber::DidCaptureFrame(
+ base::WeakPtr<FrameSubscriber> frame_subscriber_,
+ media::ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb,
+ const scoped_refptr<media::VideoFrame>& frame,
+ base::TimeTicks timestamp,
+ gfx::Rect region_in_frame,
+ bool success) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (frame_subscriber_ && frame_subscriber_->cursor_renderer_ && success) {
+ if (frame_subscriber_->cursor_renderer_->Update(region_in_frame))
miu 2015/10/23 01:55:13 Some considerations on the timing of the call to U
Irfan 2015/10/26 23:10:32 I went with a comment to see if it affects any sce
+ frame_subscriber_->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 +367,30 @@ 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();
+ if (view)
+#if defined(USE_AURA)
+ cursor_renderer_.reset(
+ new content::CursorRendererAura(view->GetNativeView()));
+#else
+ cursor_renderer_.reset(
miu 2015/10/23 01:55:13 Please remove the #else clause here. In Chromium
Irfan 2015/10/26 23:10:32 Done.
+ new content::CursorRendererDummy(view->GetNativeView()));
+#endif
+ timer_subscriber_.reset(
+ new FrameSubscriber(media::VideoCaptureOracle::kTimerPoll, oracle_proxy,
+ &delivery_log_, cursor_renderer_->GetWeakPtr()));
// 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_->GetWeakPtr()));
view->BeginFrameSubscription(subscriber.Pass());
}
@@ -370,18 +426,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 +467,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 +507,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()
@@ -577,7 +631,7 @@ void WebContentsCaptureMachine::InternalStop(const base::Closure& callback) {
tracker_->Stop();
// The render thread cannot be stopped on the UI thread, so post a message
- // to the thread pool used for blocking operations.
+ // to the thread pool used; for blocking operations.
xjz 2015/10/22 17:08:42 nit: remove ';'.
if (render_thread_.get()) {
BrowserThread::PostBlockingPoolTask(
FROM_HERE,
@@ -597,7 +651,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 +776,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 +784,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 +795,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