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

Side by Side Diff: content/browser/media/capture/web_contents_video_capture_device.cc

Issue 1825633002: Adds UMA histograms for desktop tab and audio capture through (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 9 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 // 4 //
5 // Implementation notes: This needs to work on a variety of hardware 5 // Implementation notes: This needs to work on a variety of hardware
6 // configurations where the speed of the CPU and GPU greatly affect overall 6 // configurations where the speed of the CPU and GPU greatly affect overall
7 // performance. Spanning several threads, the process of capturing has been 7 // performance. Spanning several threads, the process of capturing has been
8 // split up into four conceptual stages: 8 // split up into four conceptual stages:
9 // 9 //
10 // 1. Reserve Buffer: Before a frame can be captured, a slot in the client's 10 // 1. Reserve Buffer: Before a frame can be captured, a slot in the client's
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 #include "base/memory/scoped_ptr.h" 62 #include "base/memory/scoped_ptr.h"
63 #include "base/memory/weak_ptr.h" 63 #include "base/memory/weak_ptr.h"
64 #include "base/metrics/histogram.h" 64 #include "base/metrics/histogram.h"
65 #include "base/sequenced_task_runner.h" 65 #include "base/sequenced_task_runner.h"
66 #include "base/single_thread_task_runner.h" 66 #include "base/single_thread_task_runner.h"
67 #include "base/threading/thread.h" 67 #include "base/threading/thread.h"
68 #include "base/threading/thread_checker.h" 68 #include "base/threading/thread_checker.h"
69 #include "base/time/time.h" 69 #include "base/time/time.h"
70 #include "build/build_config.h" 70 #include "build/build_config.h"
71 #include "content/browser/media/capture/cursor_renderer.h" 71 #include "content/browser/media/capture/cursor_renderer.h"
72 #include "content/browser/media/capture/desktop_capture_device_uma_types.h"
72 #include "content/browser/media/capture/web_contents_tracker.h" 73 #include "content/browser/media/capture/web_contents_tracker.h"
73 #include "content/browser/media/capture/window_activity_tracker.h" 74 #include "content/browser/media/capture/window_activity_tracker.h"
74 #include "content/browser/renderer_host/render_widget_host_impl.h" 75 #include "content/browser/renderer_host/render_widget_host_impl.h"
75 #include "content/browser/renderer_host/render_widget_host_view_base.h" 76 #include "content/browser/renderer_host/render_widget_host_view_base.h"
76 #include "content/public/browser/browser_thread.h" 77 #include "content/public/browser/browser_thread.h"
77 #include "content/public/browser/render_process_host.h" 78 #include "content/public/browser/render_process_host.h"
78 #include "content/public/browser/render_widget_host_view.h" 79 #include "content/public/browser/render_widget_host_view.h"
79 #include "content/public/browser/render_widget_host_view_frame_subscriber.h" 80 #include "content/public/browser/render_widget_host_view_frame_subscriber.h"
80 #include "content/public/browser/web_contents.h" 81 #include "content/public/browser/web_contents.h"
81 #include "content/public/browser/web_contents_media_capture_id.h" 82 #include "content/public/browser/web_contents_media_capture_id.h"
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 const SkBitmap& input, 254 const SkBitmap& input,
254 const scoped_refptr<media::VideoFrame>& output, 255 const scoped_refptr<media::VideoFrame>& output,
255 const base::Callback<void(const gfx::Rect&, bool)>& done_cb); 256 const base::Callback<void(const gfx::Rect&, bool)>& done_cb);
256 257
257 // Renews capture subscriptions based on feedback from WebContentsTracker, and 258 // Renews capture subscriptions based on feedback from WebContentsTracker, and
258 // also executes copying of the backing store on the UI BrowserThread. 259 // also executes copying of the backing store on the UI BrowserThread.
259 class WebContentsCaptureMachine : public media::VideoCaptureMachine { 260 class WebContentsCaptureMachine : public media::VideoCaptureMachine {
260 public: 261 public:
261 WebContentsCaptureMachine(int render_process_id, 262 WebContentsCaptureMachine(int render_process_id,
262 int main_render_frame_id, 263 int main_render_frame_id,
263 bool enable_auto_throttling); 264 bool enable_auto_throttling,
265 WebContentsVideoCaptureDevice::JavaScriptType type);
264 ~WebContentsCaptureMachine() override; 266 ~WebContentsCaptureMachine() override;
265 267
266 // VideoCaptureMachine overrides. 268 // VideoCaptureMachine overrides.
267 void Start(const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy, 269 void Start(const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy,
268 const media::VideoCaptureParams& params, 270 const media::VideoCaptureParams& params,
269 const base::Callback<void(bool)> callback) override; 271 const base::Callback<void(bool)> callback) override;
270 void Stop(const base::Closure& callback) override; 272 void Stop(const base::Closure& callback) override;
271 bool IsAutoThrottlingEnabled() const override { 273 bool IsAutoThrottlingEnabled() const override {
272 return auto_throttling_enabled_; 274 return auto_throttling_enabled_;
273 } 275 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 324
323 // Tracks events and calls back to RenewFrameSubscription() to maintain 325 // Tracks events and calls back to RenewFrameSubscription() to maintain
324 // capture on the correct RenderWidgetHost. 326 // capture on the correct RenderWidgetHost.
325 const scoped_refptr<WebContentsTracker> tracker_; 327 const scoped_refptr<WebContentsTracker> tracker_;
326 328
327 // Set to false to prevent the capture size from automatically adjusting in 329 // Set to false to prevent the capture size from automatically adjusting in
328 // response to end-to-end utilization. This is enabled via the throttling 330 // response to end-to-end utilization. This is enabled via the throttling
329 // option in the WebContentsVideoCaptureDevice device ID. 331 // option in the WebContentsVideoCaptureDevice device ID.
330 const bool auto_throttling_enabled_; 332 const bool auto_throttling_enabled_;
331 333
334 bool is_first_capture_;
335 const WebContentsVideoCaptureDevice::JavaScriptType js_type_;
336
332 // A dedicated worker thread on which SkBitmap->VideoFrame conversion will 337 // A dedicated worker thread on which SkBitmap->VideoFrame conversion will
333 // occur. Only used when this activity cannot be done on the GPU. 338 // occur. Only used when this activity cannot be done on the GPU.
334 scoped_ptr<base::Thread> render_thread_; 339 scoped_ptr<base::Thread> render_thread_;
335 340
336 // Makes all the decisions about which frames to copy, and how. 341 // Makes all the decisions about which frames to copy, and how.
337 scoped_refptr<media::ThreadSafeCaptureOracle> oracle_proxy_; 342 scoped_refptr<media::ThreadSafeCaptureOracle> oracle_proxy_;
338 343
339 // Video capture parameters that this machine is started with. 344 // Video capture parameters that this machine is started with.
340 media::VideoCaptureParams capture_params_; 345 media::VideoCaptureParams capture_params_;
341 346
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 << "WebContentsVideoCaptureDevice is " << measured_fps << " FPS."; 627 << "WebContentsVideoCaptureDevice is " << measured_fps << " FPS.";
623 last_frame_rate_log_time_ = frame_time; 628 last_frame_rate_log_time_ = frame_time;
624 count_frames_rendered_ = 0; 629 count_frames_rendered_ = 0;
625 } 630 }
626 } 631 }
627 } 632 }
628 633
629 WebContentsCaptureMachine::WebContentsCaptureMachine( 634 WebContentsCaptureMachine::WebContentsCaptureMachine(
630 int render_process_id, 635 int render_process_id,
631 int main_render_frame_id, 636 int main_render_frame_id,
632 bool enable_auto_throttling) 637 bool enable_auto_throttling,
638 WebContentsVideoCaptureDevice::JavaScriptType type)
633 : initial_render_process_id_(render_process_id), 639 : initial_render_process_id_(render_process_id),
634 initial_main_render_frame_id_(main_render_frame_id), 640 initial_main_render_frame_id_(main_render_frame_id),
635 tracker_(new WebContentsTracker(true)), 641 tracker_(new WebContentsTracker(true)),
636 auto_throttling_enabled_(enable_auto_throttling), 642 auto_throttling_enabled_(enable_auto_throttling),
643 js_type_(type),
637 weak_ptr_factory_(this) { 644 weak_ptr_factory_(this) {
638 DVLOG(1) << "Created WebContentsCaptureMachine for " 645 DVLOG(1) << "Created WebContentsCaptureMachine for "
639 << render_process_id << ':' << main_render_frame_id 646 << render_process_id << ':' << main_render_frame_id
640 << (auto_throttling_enabled_ ? " with auto-throttling enabled" : ""); 647 << (auto_throttling_enabled_ ? " with auto-throttling enabled" : "");
641 } 648 }
642 649
643 WebContentsCaptureMachine::~WebContentsCaptureMachine() {} 650 WebContentsCaptureMachine::~WebContentsCaptureMachine() {}
644 651
645 bool WebContentsCaptureMachine::IsStarted() const { 652 bool WebContentsCaptureMachine::IsStarted() const {
646 DCHECK_CURRENTLY_ON(BrowserThread::UI); 653 DCHECK_CURRENTLY_ON(BrowserThread::UI);
647 return weak_ptr_factory_.HasWeakPtrs(); 654 return weak_ptr_factory_.HasWeakPtrs();
648 } 655 }
649 656
650 void WebContentsCaptureMachine::Start( 657 void WebContentsCaptureMachine::Start(
651 const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy, 658 const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy,
652 const media::VideoCaptureParams& params, 659 const media::VideoCaptureParams& params,
653 const base::Callback<void(bool)> callback) { 660 const base::Callback<void(bool)> callback) {
661 is_first_capture_ = true;
662
654 // Starts the capture machine asynchronously. 663 // Starts the capture machine asynchronously.
655 BrowserThread::PostTaskAndReplyWithResult( 664 BrowserThread::PostTaskAndReplyWithResult(
656 BrowserThread::UI, 665 BrowserThread::UI,
657 FROM_HERE, 666 FROM_HERE,
658 base::Bind(&WebContentsCaptureMachine::InternalStart, 667 base::Bind(&WebContentsCaptureMachine::InternalStart,
659 base::Unretained(this), 668 base::Unretained(this),
660 oracle_proxy, 669 oracle_proxy,
661 params), 670 params),
662 callback); 671 callback);
663 } 672 }
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
859 "Render"); 868 "Render");
860 render_thread_->task_runner()->PostTask( 869 render_thread_->task_runner()->PostTask(
861 FROM_HERE, media::BindToCurrentLoop( 870 FROM_HERE, media::BindToCurrentLoop(
862 base::Bind(&RenderVideoFrame, bitmap, target, 871 base::Bind(&RenderVideoFrame, bitmap, target,
863 base::Bind(deliver_frame_cb, start_time)))); 872 base::Bind(deliver_frame_cb, start_time))));
864 } else { 873 } else {
865 // Capture can fail due to transient issues, so just skip this frame. 874 // Capture can fail due to transient issues, so just skip this frame.
866 DVLOG(1) << "CopyFromBackingStore failed; skipping frame."; 875 DVLOG(1) << "CopyFromBackingStore failed; skipping frame.";
867 deliver_frame_cb.Run(start_time, gfx::Rect(), false); 876 deliver_frame_cb.Run(start_time, gfx::Rect(), false);
868 } 877 }
878
879 if (is_first_capture_) {
880 is_first_capture_ = false;
881 if (js_type_ ==
882 WebContentsVideoCaptureDevice::CHROME_CHOOSE_DESKTOP_MEDIA) {
883 if (response == READBACK_SUCCESS)
miu 2016/03/24 20:51:02 It's very possible for the first few frames to fai
GeorgeZ 2016/03/25 16:35:04 Very valuable comments. I guess this is why a owne
884 IncrementDesktopCaptureCounter(FIRST_TAB_CAPTURE_SUCCEEDED);
885 else
886 IncrementDesktopCaptureCounter(FIRST_TAB_CAPTURE_FAILED);
887 }
888 }
869 } 889 }
870 890
871 void WebContentsCaptureMachine::DidCopyFromCompositingSurfaceToVideoFrame( 891 void WebContentsCaptureMachine::DidCopyFromCompositingSurfaceToVideoFrame(
872 const base::TimeTicks& start_time, 892 const base::TimeTicks& start_time,
873 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& 893 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&
874 deliver_frame_cb, 894 deliver_frame_cb,
875 const gfx::Rect& region_in_frame, 895 const gfx::Rect& region_in_frame,
876 bool success) { 896 bool success) {
877 DCHECK_CURRENTLY_ON(BrowserThread::UI); 897 DCHECK_CURRENTLY_ON(BrowserThread::UI);
878 base::TimeTicks now = base::TimeTicks::Now(); 898 base::TimeTicks now = base::TimeTicks::Now();
879 899
880 if (success) { 900 if (success) {
881 UMA_HISTOGRAM_TIMES("TabCapture.CopyTimeVideoFrame", now - start_time); 901 UMA_HISTOGRAM_TIMES("TabCapture.CopyTimeVideoFrame", now - start_time);
882 } else { 902 } else {
883 // Capture can fail due to transient issues, so just skip this frame. 903 // Capture can fail due to transient issues, so just skip this frame.
884 DVLOG(1) << "CopyFromCompositingSurface failed; skipping frame."; 904 DVLOG(1) << "CopyFromCompositingSurface failed; skipping frame.";
885 } 905 }
906
907 if (is_first_capture_) {
908 is_first_capture_ = false;
909 if (js_type_ ==
910 WebContentsVideoCaptureDevice::CHROME_CHOOSE_DESKTOP_MEDIA) {
911 if (success)
912 IncrementDesktopCaptureCounter(FIRST_TAB_CAPTURE_SUCCEEDED);
913 else
914 IncrementDesktopCaptureCounter(FIRST_TAB_CAPTURE_FAILED);
915 }
916 }
917
886 deliver_frame_cb.Run(start_time, region_in_frame, success); 918 deliver_frame_cb.Run(start_time, region_in_frame, success);
887 } 919 }
888 920
889 void WebContentsCaptureMachine::RenewFrameSubscription(bool had_target) { 921 void WebContentsCaptureMachine::RenewFrameSubscription(bool had_target) {
890 DCHECK_CURRENTLY_ON(BrowserThread::UI); 922 DCHECK_CURRENTLY_ON(BrowserThread::UI);
891 923
892 RenderWidgetHost* const rwh = 924 RenderWidgetHost* const rwh =
893 had_target ? tracker_->GetTargetRenderWidgetHost() : nullptr; 925 had_target ? tracker_->GetTargetRenderWidgetHost() : nullptr;
894 926
895 // Always destroy the old subscription before creating a new one. 927 // Always destroy the old subscription before creating a new one.
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
940 << ") from view size (" << view_size.ToString() << ")."; 972 << ") from view size (" << view_size.ToString() << ").";
941 973
942 oracle_proxy_->UpdateCaptureSize(physical_size); 974 oracle_proxy_->UpdateCaptureSize(physical_size);
943 } 975 }
944 976
945 } // namespace 977 } // namespace
946 978
947 WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice( 979 WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice(
948 int render_process_id, 980 int render_process_id,
949 int main_render_frame_id, 981 int main_render_frame_id,
950 bool enable_auto_throttling) 982 bool enable_auto_throttling,
983 JavaScriptType type)
951 : core_(new media::ScreenCaptureDeviceCore( 984 : core_(new media::ScreenCaptureDeviceCore(
952 scoped_ptr<media::VideoCaptureMachine>(new WebContentsCaptureMachine( 985 scoped_ptr<media::VideoCaptureMachine>(
953 render_process_id, 986 new WebContentsCaptureMachine(render_process_id,
954 main_render_frame_id, 987 main_render_frame_id,
955 enable_auto_throttling)))) {} 988 enable_auto_throttling,
989 type)))) {}
956 990
957 WebContentsVideoCaptureDevice::~WebContentsVideoCaptureDevice() { 991 WebContentsVideoCaptureDevice::~WebContentsVideoCaptureDevice() {
958 DVLOG(2) << "WebContentsVideoCaptureDevice@" << this << " destroying."; 992 DVLOG(2) << "WebContentsVideoCaptureDevice@" << this << " destroying.";
959 } 993 }
960 994
961 // static 995 // static
962 media::VideoCaptureDevice* WebContentsVideoCaptureDevice::Create( 996 media::VideoCaptureDevice* WebContentsVideoCaptureDevice::Create(
963 const std::string& device_id) { 997 const std::string& device_id,
998 JavaScriptType type) {
964 // Parse device_id into render_process_id and main_render_frame_id. 999 // Parse device_id into render_process_id and main_render_frame_id.
965 int render_process_id = -1; 1000 int render_process_id = -1;
966 int main_render_frame_id = -1; 1001 int main_render_frame_id = -1;
967 if (!WebContentsMediaCaptureId::ExtractTabCaptureTarget( 1002 if (!WebContentsMediaCaptureId::ExtractTabCaptureTarget(
968 device_id, &render_process_id, &main_render_frame_id)) { 1003 device_id, &render_process_id, &main_render_frame_id)) {
969 return NULL; 1004 return NULL;
970 } 1005 }
971 1006
1007 if (type == CHROME_CHOOSE_DESKTOP_MEDIA)
1008 IncrementDesktopCaptureCounter(TAB_VIDEO_CAPTURER_CREATED);
1009
972 return new WebContentsVideoCaptureDevice( 1010 return new WebContentsVideoCaptureDevice(
973 render_process_id, main_render_frame_id, 1011 render_process_id, main_render_frame_id,
974 WebContentsMediaCaptureId::IsAutoThrottlingOptionSet(device_id)); 1012 WebContentsMediaCaptureId::IsAutoThrottlingOptionSet(device_id), type);
975 } 1013 }
976 1014
977 void WebContentsVideoCaptureDevice::AllocateAndStart( 1015 void WebContentsVideoCaptureDevice::AllocateAndStart(
978 const media::VideoCaptureParams& params, 1016 const media::VideoCaptureParams& params,
979 scoped_ptr<Client> client) { 1017 scoped_ptr<Client> client) {
980 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString(); 1018 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString();
981 core_->AllocateAndStart(params, std::move(client)); 1019 core_->AllocateAndStart(params, std::move(client));
982 } 1020 }
983 1021
984 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { 1022 void WebContentsVideoCaptureDevice::StopAndDeAllocate() {
985 core_->StopAndDeAllocate(); 1023 core_->StopAndDeAllocate();
986 } 1024 }
987 1025
988 } // namespace content 1026 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698