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 3a432d856c068ed7f638913321e573c37922f0ea..d69a0bc6ce3c8849d25d2cfadca262cac8d13c2d 100644 |
--- a/content/browser/media/capture/web_contents_video_capture_device.cc |
+++ b/content/browser/media/capture/web_contents_video_capture_device.cc |
@@ -68,6 +68,7 @@ |
#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/media/capture/window_activity_tracker.h" |
#include "content/browser/renderer_host/render_widget_host_impl.h" |
#include "content/browser/renderer_host/render_widget_host_view_base.h" |
#include "content/public/browser/browser_thread.h" |
@@ -77,6 +78,7 @@ |
#include "content/public/browser/web_contents.h" |
#include "media/base/bind_to_current_loop.h" |
#include "media/base/video_capture_types.h" |
+#include "media/base/video_frame_metadata.h" |
#include "media/base/video_util.h" |
#include "media/capture/content/screen_capture_device_core.h" |
#include "media/capture/content/thread_safe_capture_oracle.h" |
@@ -90,12 +92,21 @@ |
#if defined(USE_AURA) |
#include "content/browser/media/capture/cursor_renderer_aura.h" |
+#include "content/browser/media/capture/window_activity_tracker_aura.h" |
#endif |
namespace content { |
namespace { |
+enum InteractiveModeSettings { |
+ // Minimum amount of time for which there should be no animation detected |
+ // to consider interactive mode being active. This is to prevent very brief |
+ // periods of animated content not being detected (due to CPU fluctations for |
+ // example) from causing a flip-flop on interactive mode. |
+ kMinPeriodNoAnimationMillis = 3000 |
+}; |
+ |
void DeleteOnWorkerThread(scoped_ptr<base::Thread> render_thread, |
const base::Closure& callback) { |
render_thread.reset(); |
@@ -128,11 +139,13 @@ class FrameSubscriber : public RenderWidgetHostViewFrameSubscriber { |
FrameSubscriber(media::VideoCaptureOracle::Event event_type, |
const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle, |
VideoFrameDeliveryLog* delivery_log, |
- base::WeakPtr<content::CursorRenderer> cursor_renderer) |
+ base::WeakPtr<content::CursorRenderer> cursor_renderer, |
+ base::WeakPtr<content::WindowActivityTracker> tracker) |
: event_type_(event_type), |
oracle_proxy_(oracle), |
delivery_log_(delivery_log), |
cursor_renderer_(cursor_renderer), |
+ window_activity_tracker_(tracker), |
weak_ptr_factory_(this) {} |
bool ShouldCaptureFrame( |
@@ -151,6 +164,8 @@ class FrameSubscriber : public RenderWidgetHostViewFrameSubscriber { |
const gfx::Rect& region_in_frame, |
bool success); |
+ bool IsUserInteractingWithContent(); |
+ |
private: |
const media::VideoCaptureOracle::Event event_type_; |
scoped_refptr<media::ThreadSafeCaptureOracle> oracle_proxy_; |
@@ -158,6 +173,9 @@ class FrameSubscriber : public RenderWidgetHostViewFrameSubscriber { |
// We need a weak pointer since FrameSubscriber is owned externally and |
// may outlive the cursor renderer. |
base::WeakPtr<CursorRenderer> cursor_renderer_; |
+ // We need a weak pointer since FrameSubscriber is owned externally and |
+ // may outlive the ui activity tracker. |
+ base::WeakPtr<WindowActivityTracker> window_activity_tracker_; |
base::WeakPtrFactory<FrameSubscriber> weak_ptr_factory_; |
}; |
@@ -210,6 +228,10 @@ class ContentCaptureSubscription { |
// capture is completed. |
scoped_ptr<content::CursorRenderer> cursor_renderer_; |
+ // Responsible for tracking the UI events and making a decision on whether |
+ // user is actively interacting with content. |
+ scoped_ptr<content::WindowActivityTracker> window_activity_tracker_; |
+ |
DISALLOW_COPY_AND_ASSIGN(ContentCaptureSubscription); |
}; |
@@ -365,14 +387,38 @@ void FrameSubscriber::DidCaptureFrame( |
// experience in any particular scenarios. Doing it prior to capture may |
// require evaluating region_in_frame in this file. |
if (frame_subscriber_ && frame_subscriber_->cursor_renderer_) { |
- if (frame_subscriber_->cursor_renderer_->SnapshotCursorState( |
- region_in_frame)) |
- frame_subscriber_->cursor_renderer_->RenderOnVideoFrame(frame); |
+ CursorRenderer* cursor_renderer = |
+ frame_subscriber_->cursor_renderer_.get(); |
+ if (cursor_renderer->SnapshotCursorState(region_in_frame)) |
+ cursor_renderer->RenderOnVideoFrame(frame); |
+ frame->metadata()->SetBoolean( |
+ media::VideoFrameMetadata::INTERACTIVE_CONTENT, |
+ frame_subscriber_->IsUserInteractingWithContent()); |
} |
} |
capture_frame_cb.Run(frame, timestamp, success); |
} |
+bool FrameSubscriber::IsUserInteractingWithContent() { |
+ bool interactive_mode = false; |
+ bool ui_activity = false; |
+ if (window_activity_tracker_.get()) { |
+ ui_activity = window_activity_tracker_->IsUiInteractionActive(); |
+ } |
+ if (cursor_renderer_.get()) { |
+ bool animation_active = |
+ (base::TimeTicks::Now() - |
+ oracle_proxy_->last_time_animation_was_detected()) < |
+ base::TimeDelta::FromMilliseconds(kMinPeriodNoAnimationMillis); |
+ if (ui_activity && !animation_active) { |
+ interactive_mode = true; |
+ } else if (animation_active) { |
+ window_activity_tracker_->Reset(); |
+ } |
+ } |
+ return interactive_mode; |
+} |
+ |
ContentCaptureSubscription::ContentCaptureSubscription( |
const RenderWidgetHost& source, |
const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy, |
@@ -387,25 +433,36 @@ ContentCaptureSubscription::ContentCaptureSubscription( |
RenderWidgetHostView* const view = source.GetView(); |
// TODO(isheriff): Cursor resources currently only available on linux. Remove |
// this once we add the necessary resources for windows. |
+// https://crbug.com/554280 https://crbug.com/549182 |
#if defined(USE_AURA) && defined(OS_LINUX) |
- if (view) |
+ if (view) { |
cursor_renderer_.reset( |
new content::CursorRendererAura(view->GetNativeView())); |
+ } |
+#endif |
+// TODO(isheriff): Needs implementation on non-aura platforms. |
+// https://crbug.com/567735 |
+#if defined(USE_AURA) |
+ window_activity_tracker_.reset( |
+ new content::WindowActivityTrackerAura(view->GetNativeView())); |
#endif |
timer_subscriber_.reset(new FrameSubscriber( |
media::VideoCaptureOracle::kTimerPoll, oracle_proxy, &delivery_log_, |
cursor_renderer_ ? cursor_renderer_->GetWeakPtr() |
- : base::WeakPtr<CursorRenderer>())); |
+ : base::WeakPtr<CursorRenderer>(), |
+ window_activity_tracker_ ? window_activity_tracker_->GetWeakPtr() |
+ : base::WeakPtr<WindowActivityTracker>())); |
// 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_, |
- cursor_renderer_ |
- ? cursor_renderer_->GetWeakPtr() |
- : base::WeakPtr<CursorRenderer>())); |
+ new FrameSubscriber( |
+ media::VideoCaptureOracle::kCompositorUpdate, oracle_proxy, |
+ &delivery_log_, cursor_renderer_ ? cursor_renderer_->GetWeakPtr() |
+ : base::WeakPtr<CursorRenderer>(), |
+ window_activity_tracker_ ? window_activity_tracker_->GetWeakPtr() |
+ : base::WeakPtr<WindowActivityTracker>())); |
view->BeginFrameSubscription(subscriber.Pass()); |
} |