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

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

Issue 514073002: Fix for ~ContentCaptureSubscription() after BrowserThreads are torn down. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 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 353 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 const CaptureCallback& capture_callback) 364 const CaptureCallback& capture_callback)
365 : render_process_id_(source.GetProcess()->GetID()), 365 : render_process_id_(source.GetProcess()->GetID()),
366 render_view_id_(source.GetRoutingID()), 366 render_view_id_(source.GetRoutingID()),
367 delivery_log_(), 367 delivery_log_(),
368 paint_subscriber_(VideoCaptureOracle::kSoftwarePaint, oracle_proxy, 368 paint_subscriber_(VideoCaptureOracle::kSoftwarePaint, oracle_proxy,
369 &delivery_log_), 369 &delivery_log_),
370 timer_subscriber_(VideoCaptureOracle::kTimerPoll, oracle_proxy, 370 timer_subscriber_(VideoCaptureOracle::kTimerPoll, oracle_proxy,
371 &delivery_log_), 371 &delivery_log_),
372 capture_callback_(capture_callback), 372 capture_callback_(capture_callback),
373 timer_(true, true) { 373 timer_(true, true) {
374 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 374 DCHECK_CURRENTLY_ON(BrowserThread::UI);
375 375
376 RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>( 376 RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
377 source.GetView()); 377 source.GetView());
378 378
379 // Subscribe to accelerated presents. These will be serviced directly by the 379 // Subscribe to accelerated presents. These will be serviced directly by the
380 // oracle. 380 // oracle.
381 if (view && kAcceleratedSubscriberIsSupported) { 381 if (view && kAcceleratedSubscriberIsSupported) {
382 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber( 382 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber(
383 new FrameSubscriber(VideoCaptureOracle::kCompositorUpdate, 383 new FrameSubscriber(VideoCaptureOracle::kCompositorUpdate,
384 oracle_proxy, &delivery_log_)); 384 oracle_proxy, &delivery_log_));
385 view->BeginFrameSubscription(subscriber.Pass()); 385 view->BeginFrameSubscription(subscriber.Pass());
386 } 386 }
387 387
388 // Subscribe to software paint events. This instance will service these by 388 // Subscribe to software paint events. This instance will service these by
389 // reflecting them back to the WebContentsCaptureMachine via 389 // reflecting them back to the WebContentsCaptureMachine via
390 // |capture_callback|. 390 // |capture_callback|.
391 registrar_.Add( 391 registrar_.Add(
392 this, content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE, 392 this, content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
393 Source<RenderWidgetHost>(&source)); 393 Source<RenderWidgetHost>(&source));
394 394
395 // Subscribe to timer events. This instance will service these as well. 395 // Subscribe to timer events. This instance will service these as well.
396 timer_.Start(FROM_HERE, oracle_proxy->min_capture_period(), 396 timer_.Start(FROM_HERE, oracle_proxy->min_capture_period(),
397 base::Bind(&ContentCaptureSubscription::OnTimer, 397 base::Bind(&ContentCaptureSubscription::OnTimer,
398 base::Unretained(this))); 398 base::Unretained(this)));
399 } 399 }
400 400
401 ContentCaptureSubscription::~ContentCaptureSubscription() { 401 ContentCaptureSubscription::~ContentCaptureSubscription() {
402 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 402 // If the BrowserThreads have been torn down, then the browser is in the final
403 // stages of exiting and it is dangerous to take any further action. We must
404 // return early. http://crbug.com/396413
405 if (!BrowserThread::IsMessageLoopValid(BrowserThread::UI))
miu 2014/08/28 01:59:56 This is the fix: Calling RenderViewHost::FromID(..
406 return;
407
408 DCHECK_CURRENTLY_ON(BrowserThread::UI);
403 if (kAcceleratedSubscriberIsSupported) { 409 if (kAcceleratedSubscriberIsSupported) {
404 RenderViewHost* source = RenderViewHost::FromID(render_process_id_, 410 RenderViewHost* source = RenderViewHost::FromID(render_process_id_,
405 render_view_id_); 411 render_view_id_);
406 if (source) { 412 if (source) {
407 RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>( 413 RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
408 source->GetView()); 414 source->GetView());
409 if (view) 415 if (view)
410 view->EndFrameSubscription(); 416 view->EndFrameSubscription();
411 } 417 }
412 } 418 }
413 } 419 }
414 420
415 void ContentCaptureSubscription::Observe( 421 void ContentCaptureSubscription::Observe(
416 int type, 422 int type,
417 const content::NotificationSource& source, 423 const content::NotificationSource& source,
418 const content::NotificationDetails& details) { 424 const content::NotificationDetails& details) {
419 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 425 DCHECK_CURRENTLY_ON(BrowserThread::UI);
420 DCHECK_EQ(NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE, type); 426 DCHECK_EQ(NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE, type);
421 427
422 RenderWidgetHostImpl* rwh = 428 RenderWidgetHostImpl* rwh =
423 RenderWidgetHostImpl::From(Source<RenderWidgetHost>(source).ptr()); 429 RenderWidgetHostImpl::From(Source<RenderWidgetHost>(source).ptr());
424 430
425 // This message occurs on window resizes and visibility changes even when 431 // This message occurs on window resizes and visibility changes even when
426 // accelerated compositing is active, so we need to filter out these cases. 432 // accelerated compositing is active, so we need to filter out these cases.
427 if (!rwh || !rwh->GetView()) 433 if (!rwh || !rwh->GetView())
428 return; 434 return;
429 // Mac sends DID_UPDATE_BACKING_STORE messages to inform the capture system 435 // Mac sends DID_UPDATE_BACKING_STORE messages to inform the capture system
(...skipping 18 matching lines...) Expand all
448 &deliver_frame_cb)) { 454 &deliver_frame_cb)) {
449 // This message happens just before paint. If we post a task to do the copy, 455 // This message happens just before paint. If we post a task to do the copy,
450 // it should run soon after the paint. 456 // it should run soon after the paint.
451 BrowserThread::PostTask( 457 BrowserThread::PostTask(
452 BrowserThread::UI, FROM_HERE, 458 BrowserThread::UI, FROM_HERE,
453 base::Bind(capture_callback_, start_time, frame, deliver_frame_cb)); 459 base::Bind(capture_callback_, start_time, frame, deliver_frame_cb));
454 } 460 }
455 } 461 }
456 462
457 void ContentCaptureSubscription::OnTimer() { 463 void ContentCaptureSubscription::OnTimer() {
458 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 464 DCHECK_CURRENTLY_ON(BrowserThread::UI);
459 TRACE_EVENT0("mirroring", "ContentCaptureSubscription::OnTimer"); 465 TRACE_EVENT0("mirroring", "ContentCaptureSubscription::OnTimer");
460 466
461 scoped_refptr<media::VideoFrame> frame; 467 scoped_refptr<media::VideoFrame> frame;
462 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback deliver_frame_cb; 468 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback deliver_frame_cb;
463 469
464 const base::TimeTicks start_time = base::TimeTicks::Now(); 470 const base::TimeTicks start_time = base::TimeTicks::Now();
465 if (timer_subscriber_.ShouldCaptureFrame(gfx::Rect(), 471 if (timer_subscriber_.ShouldCaptureFrame(gfx::Rect(),
466 start_time, 472 start_time,
467 &frame, 473 &frame,
468 &deliver_frame_cb)) { 474 &deliver_frame_cb)) {
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 } 574 }
569 } 575 }
570 576
571 WebContentsCaptureMachine::WebContentsCaptureMachine(int render_process_id, 577 WebContentsCaptureMachine::WebContentsCaptureMachine(int render_process_id,
572 int main_render_frame_id) 578 int main_render_frame_id)
573 : initial_render_process_id_(render_process_id), 579 : initial_render_process_id_(render_process_id),
574 initial_main_render_frame_id_(main_render_frame_id), 580 initial_main_render_frame_id_(main_render_frame_id),
575 fullscreen_widget_id_(MSG_ROUTING_NONE), 581 fullscreen_widget_id_(MSG_ROUTING_NONE),
576 weak_ptr_factory_(this) {} 582 weak_ptr_factory_(this) {}
577 583
578 WebContentsCaptureMachine::~WebContentsCaptureMachine() { 584 WebContentsCaptureMachine::~WebContentsCaptureMachine() {}
579 BrowserThread::PostBlockingPoolTask(
580 FROM_HERE,
581 base::Bind(&DeleteOnWorkerThread, base::Passed(&render_thread_),
582 base::Bind(&base::DoNothing)));
583 }
584 585
585 bool WebContentsCaptureMachine::Start( 586 bool WebContentsCaptureMachine::Start(
586 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy, 587 const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy,
587 const media::VideoCaptureParams& params) { 588 const media::VideoCaptureParams& params) {
588 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 589 DCHECK_CURRENTLY_ON(BrowserThread::UI);
589 DCHECK(!started_); 590 DCHECK(!weak_ptr_factory_.HasWeakPtrs()); // Should not be started.
590 591
591 DCHECK(oracle_proxy.get()); 592 DCHECK(oracle_proxy.get());
592 oracle_proxy_ = oracle_proxy; 593 oracle_proxy_ = oracle_proxy;
593 capture_params_ = params; 594 capture_params_ = params;
594 595
595 render_thread_.reset(new base::Thread("WebContentsVideo_RenderThread")); 596 render_thread_.reset(new base::Thread("WebContentsVideo_RenderThread"));
596 if (!render_thread_->Start()) { 597 if (!render_thread_->Start()) {
597 DVLOG(1) << "Failed to spawn render thread."; 598 DVLOG(1) << "Failed to spawn render thread.";
598 render_thread_.reset(); 599 render_thread_.reset();
599 return false; 600 return false;
600 } 601 }
601 602
602 if (!StartObservingWebContents()) { 603 if (!StartObservingWebContents()) {
603 DVLOG(1) << "Failed to observe web contents."; 604 DVLOG(1) << "Failed to observe web contents.";
604 render_thread_.reset(); 605 render_thread_.reset();
605 return false; 606 return false;
606 } 607 }
607 608
608 started_ = true;
609 return true; 609 return true;
610 } 610 }
611 611
612 void WebContentsCaptureMachine::Stop(const base::Closure& callback) { 612 void WebContentsCaptureMachine::Stop(const base::Closure& callback) {
613 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 613 DCHECK_CURRENTLY_ON(BrowserThread::UI);
614 subscription_.reset(); 614 subscription_.reset();
615 if (web_contents()) { 615 if (web_contents()) {
616 web_contents()->DecrementCapturerCount(); 616 web_contents()->DecrementCapturerCount();
617 Observe(NULL); 617 Observe(NULL);
618 } 618 }
619 619
620 // Any callback that intend to use render_thread_ will not work after it is 620 // Any callback that intend to use render_thread_ will not work after it is
621 // passed. 621 // passed.
622 weak_ptr_factory_.InvalidateWeakPtrs(); 622 weak_ptr_factory_.InvalidateWeakPtrs();
623 623
624 // The render thread cannot be stopped on the UI thread, so post a message 624 // The render thread cannot be stopped on the UI thread, so post a message
625 // to the thread pool used for blocking operations. 625 // to the thread pool used for blocking operations.
626 BrowserThread::PostBlockingPoolTask( 626 if (render_thread_.get()) {
627 FROM_HERE, 627 BrowserThread::PostBlockingPoolTask(
628 base::Bind(&DeleteOnWorkerThread, base::Passed(&render_thread_), 628 FROM_HERE,
629 callback)); 629 base::Bind(&DeleteOnWorkerThread, base::Passed(&render_thread_),
630 630 callback));
631 started_ = false; 631 }
632 } 632 }
633 633
634 void WebContentsCaptureMachine::Capture( 634 void WebContentsCaptureMachine::Capture(
635 const base::TimeTicks& start_time, 635 const base::TimeTicks& start_time,
636 const scoped_refptr<media::VideoFrame>& target, 636 const scoped_refptr<media::VideoFrame>& target,
637 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& 637 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&
638 deliver_frame_cb) { 638 deliver_frame_cb) {
639 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 639 DCHECK_CURRENTLY_ON(BrowserThread::UI);
640 640
641 RenderWidgetHost* rwh = GetTarget(); 641 RenderWidgetHost* rwh = GetTarget();
642 RenderWidgetHostViewBase* view = 642 RenderWidgetHostViewBase* view =
643 rwh ? static_cast<RenderWidgetHostViewBase*>(rwh->GetView()) : NULL; 643 rwh ? static_cast<RenderWidgetHostViewBase*>(rwh->GetView()) : NULL;
644 if (!view || !rwh) { 644 if (!view || !rwh) {
645 deliver_frame_cb.Run(base::TimeTicks(), false); 645 deliver_frame_cb.Run(base::TimeTicks(), false);
646 return; 646 return;
647 } 647 }
648 648
649 gfx::Size video_size = target->coded_size(); 649 gfx::Size video_size = target->coded_size();
(...skipping 26 matching lines...) Expand all
676 base::Bind(&WebContentsCaptureMachine::DidCopyFromBackingStore, 676 base::Bind(&WebContentsCaptureMachine::DidCopyFromBackingStore,
677 weak_ptr_factory_.GetWeakPtr(), 677 weak_ptr_factory_.GetWeakPtr(),
678 start_time, 678 start_time,
679 target, 679 target,
680 deliver_frame_cb), 680 deliver_frame_cb),
681 kN32_SkColorType); 681 kN32_SkColorType);
682 } 682 }
683 } 683 }
684 684
685 gfx::Size WebContentsCaptureMachine::ComputeOptimalTargetSize() const { 685 gfx::Size WebContentsCaptureMachine::ComputeOptimalTargetSize() const {
686 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 686 DCHECK_CURRENTLY_ON(BrowserThread::UI);
687 687
688 gfx::Size optimal_size = oracle_proxy_->GetCaptureSize(); 688 gfx::Size optimal_size = oracle_proxy_->GetCaptureSize();
689 689
690 // If the ratio between physical and logical pixels is greater than 1:1, 690 // If the ratio between physical and logical pixels is greater than 1:1,
691 // shrink |optimal_size| by that amount. Then, when external code resizes the 691 // shrink |optimal_size| by that amount. Then, when external code resizes the
692 // render widget to the "preferred size," the widget will be physically 692 // render widget to the "preferred size," the widget will be physically
693 // rendered at the exact capture size, thereby eliminating unnecessary scaling 693 // rendered at the exact capture size, thereby eliminating unnecessary scaling
694 // operations in the graphics pipeline. 694 // operations in the graphics pipeline.
695 RenderWidgetHost* const rwh = GetTarget(); 695 RenderWidgetHost* const rwh = GetTarget();
696 RenderWidgetHostView* const rwhv = rwh ? rwh->GetView() : NULL; 696 RenderWidgetHostView* const rwhv = rwh ? rwh->GetView() : NULL;
(...skipping 10 matching lines...) Expand all
707 optimal_size = shrunk_size; 707 optimal_size = shrunk_size;
708 } 708 }
709 } 709 }
710 } 710 }
711 711
712 VLOG(1) << "Computed optimal target size: " << optimal_size.ToString(); 712 VLOG(1) << "Computed optimal target size: " << optimal_size.ToString();
713 return optimal_size; 713 return optimal_size;
714 } 714 }
715 715
716 bool WebContentsCaptureMachine::StartObservingWebContents() { 716 bool WebContentsCaptureMachine::StartObservingWebContents() {
717 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 717 DCHECK_CURRENTLY_ON(BrowserThread::UI);
718 718
719 // Look-up the RenderFrameHost and, from that, the WebContents that wraps it. 719 // Look-up the RenderFrameHost and, from that, the WebContents that wraps it.
720 // If successful, begin observing the WebContents instance. 720 // If successful, begin observing the WebContents instance.
721 // 721 //
722 // Why this can be unsuccessful: The request for mirroring originates in a 722 // Why this can be unsuccessful: The request for mirroring originates in a
723 // render process, and this request is based on the current main RenderFrame 723 // render process, and this request is based on the current main RenderFrame
724 // associated with a tab. However, by the time we get up-and-running here, 724 // associated with a tab. However, by the time we get up-and-running here,
725 // there have been multiple back-and-forth IPCs between processes, as well as 725 // there have been multiple back-and-forth IPCs between processes, as well as
726 // a bit of indirection across threads. It's easily possible that, in the 726 // a bit of indirection across threads. It's easily possible that, in the
727 // meantime, the original RenderFrame may have gone away. 727 // meantime, the original RenderFrame may have gone away.
728 Observe(WebContents::FromRenderFrameHost(RenderFrameHost::FromID( 728 Observe(WebContents::FromRenderFrameHost(RenderFrameHost::FromID(
729 initial_render_process_id_, initial_main_render_frame_id_))); 729 initial_render_process_id_, initial_main_render_frame_id_)));
730 DVLOG_IF(1, !web_contents()) 730 DVLOG_IF(1, !web_contents())
731 << "Could not find WebContents associated with main RenderFrameHost " 731 << "Could not find WebContents associated with main RenderFrameHost "
732 << "referenced by render_process_id=" << initial_render_process_id_ 732 << "referenced by render_process_id=" << initial_render_process_id_
733 << ", routing_id=" << initial_main_render_frame_id_; 733 << ", routing_id=" << initial_main_render_frame_id_;
734 734
735 WebContentsImpl* contents = static_cast<WebContentsImpl*>(web_contents()); 735 WebContentsImpl* contents = static_cast<WebContentsImpl*>(web_contents());
736 if (contents) { 736 if (contents) {
737 contents->IncrementCapturerCount(ComputeOptimalTargetSize()); 737 contents->IncrementCapturerCount(ComputeOptimalTargetSize());
738 fullscreen_widget_id_ = contents->GetFullscreenWidgetRoutingID(); 738 fullscreen_widget_id_ = contents->GetFullscreenWidgetRoutingID();
739 RenewFrameSubscription(); 739 RenewFrameSubscription();
740 return true; 740 return true;
741 } 741 }
742 return false; 742 return false;
743 } 743 }
744 744
745 void WebContentsCaptureMachine::WebContentsDestroyed() { 745 void WebContentsCaptureMachine::WebContentsDestroyed() {
746 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 746 DCHECK_CURRENTLY_ON(BrowserThread::UI);
747 747
748 subscription_.reset(); 748 subscription_.reset();
749 web_contents()->DecrementCapturerCount(); 749 web_contents()->DecrementCapturerCount();
750 oracle_proxy_->ReportError("WebContentsDestroyed()"); 750 oracle_proxy_->ReportError("WebContentsDestroyed()");
751 } 751 }
752 752
753 RenderWidgetHost* WebContentsCaptureMachine::GetTarget() const { 753 RenderWidgetHost* WebContentsCaptureMachine::GetTarget() const {
754 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 754 DCHECK_CURRENTLY_ON(BrowserThread::UI);
755 if (!web_contents()) 755 if (!web_contents())
756 return NULL; 756 return NULL;
757 757
758 RenderWidgetHost* rwh = NULL; 758 RenderWidgetHost* rwh = NULL;
759 if (fullscreen_widget_id_ != MSG_ROUTING_NONE) { 759 if (fullscreen_widget_id_ != MSG_ROUTING_NONE) {
760 RenderProcessHost* process = web_contents()->GetRenderProcessHost(); 760 RenderProcessHost* process = web_contents()->GetRenderProcessHost();
761 if (process) 761 if (process)
762 rwh = RenderWidgetHost::FromID(process->GetID(), fullscreen_widget_id_); 762 rwh = RenderWidgetHost::FromID(process->GetID(), fullscreen_widget_id_);
763 } else { 763 } else {
764 rwh = web_contents()->GetRenderViewHost(); 764 rwh = web_contents()->GetRenderViewHost();
765 } 765 }
766 766
767 return rwh; 767 return rwh;
768 } 768 }
769 769
770 void WebContentsCaptureMachine::DidCopyFromBackingStore( 770 void WebContentsCaptureMachine::DidCopyFromBackingStore(
771 const base::TimeTicks& start_time, 771 const base::TimeTicks& start_time,
772 const scoped_refptr<media::VideoFrame>& target, 772 const scoped_refptr<media::VideoFrame>& target,
773 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& 773 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&
774 deliver_frame_cb, 774 deliver_frame_cb,
775 bool success, 775 bool success,
776 const SkBitmap& bitmap) { 776 const SkBitmap& bitmap) {
777 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 777 DCHECK_CURRENTLY_ON(BrowserThread::UI);
778 778
779 base::TimeTicks now = base::TimeTicks::Now(); 779 base::TimeTicks now = base::TimeTicks::Now();
780 DCHECK(render_thread_.get()); 780 DCHECK(render_thread_.get());
781 if (success) { 781 if (success) {
782 UMA_HISTOGRAM_TIMES("TabCapture.CopyTimeBitmap", now - start_time); 782 UMA_HISTOGRAM_TIMES("TabCapture.CopyTimeBitmap", now - start_time);
783 TRACE_EVENT_ASYNC_STEP_INTO0("mirroring", "Capture", target.get(), 783 TRACE_EVENT_ASYNC_STEP_INTO0("mirroring", "Capture", target.get(),
784 "Render"); 784 "Render");
785 render_thread_->message_loop_proxy()->PostTask(FROM_HERE, base::Bind( 785 render_thread_->message_loop_proxy()->PostTask(FROM_HERE, base::Bind(
786 &RenderVideoFrame, bitmap, target, 786 &RenderVideoFrame, bitmap, target,
787 base::Bind(deliver_frame_cb, start_time))); 787 base::Bind(deliver_frame_cb, start_time)));
788 } else { 788 } else {
789 // Capture can fail due to transient issues, so just skip this frame. 789 // Capture can fail due to transient issues, so just skip this frame.
790 DVLOG(1) << "CopyFromBackingStore failed; skipping frame."; 790 DVLOG(1) << "CopyFromBackingStore failed; skipping frame.";
791 deliver_frame_cb.Run(start_time, false); 791 deliver_frame_cb.Run(start_time, false);
792 } 792 }
793 } 793 }
794 794
795 void WebContentsCaptureMachine::DidCopyFromCompositingSurfaceToVideoFrame( 795 void WebContentsCaptureMachine::DidCopyFromCompositingSurfaceToVideoFrame(
796 const base::TimeTicks& start_time, 796 const base::TimeTicks& start_time,
797 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback& 797 const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&
798 deliver_frame_cb, 798 deliver_frame_cb,
799 bool success) { 799 bool success) {
800 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 800 DCHECK_CURRENTLY_ON(BrowserThread::UI);
801 base::TimeTicks now = base::TimeTicks::Now(); 801 base::TimeTicks now = base::TimeTicks::Now();
802 802
803 if (success) { 803 if (success) {
804 UMA_HISTOGRAM_TIMES("TabCapture.CopyTimeVideoFrame", now - start_time); 804 UMA_HISTOGRAM_TIMES("TabCapture.CopyTimeVideoFrame", now - start_time);
805 } else { 805 } else {
806 // Capture can fail due to transient issues, so just skip this frame. 806 // Capture can fail due to transient issues, so just skip this frame.
807 DVLOG(1) << "CopyFromCompositingSurface failed; skipping frame."; 807 DVLOG(1) << "CopyFromCompositingSurface failed; skipping frame.";
808 } 808 }
809 deliver_frame_cb.Run(start_time, success); 809 deliver_frame_cb.Run(start_time, success);
810 } 810 }
811 811
812 void WebContentsCaptureMachine::RenewFrameSubscription() { 812 void WebContentsCaptureMachine::RenewFrameSubscription() {
813 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 813 DCHECK_CURRENTLY_ON(BrowserThread::UI);
814 814
815 // Always destroy the old subscription before creating a new one. 815 // Always destroy the old subscription before creating a new one.
816 subscription_.reset(); 816 subscription_.reset();
817 817
818 RenderWidgetHost* rwh = GetTarget(); 818 RenderWidgetHost* rwh = GetTarget();
819 if (!rwh || !rwh->GetView()) 819 if (!rwh || !rwh->GetView())
820 return; 820 return;
821 821
822 subscription_.reset(new ContentCaptureSubscription(*rwh, oracle_proxy_, 822 subscription_.reset(new ContentCaptureSubscription(*rwh, oracle_proxy_,
823 base::Bind(&WebContentsCaptureMachine::Capture, 823 base::Bind(&WebContentsCaptureMachine::Capture,
824 weak_ptr_factory_.GetWeakPtr()))); 824 weak_ptr_factory_.GetWeakPtr())));
825 } 825 }
826 826
827 } // namespace 827 } // namespace
828 828
829 WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice( 829 WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice(
830 int render_process_id, int main_render_frame_id) 830 int render_process_id, int main_render_frame_id)
831 : core_(new ContentVideoCaptureDeviceCore(scoped_ptr<VideoCaptureMachine>( 831 : core_(new ContentVideoCaptureDeviceCore(scoped_ptr<VideoCaptureMachine>(
832 new WebContentsCaptureMachine( 832 new WebContentsCaptureMachine(
833 render_process_id, main_render_frame_id)))) {} 833 render_process_id, main_render_frame_id)))) {}
834 834
835 WebContentsVideoCaptureDevice::~WebContentsVideoCaptureDevice() { 835 WebContentsVideoCaptureDevice::~WebContentsVideoCaptureDevice() {
836 DVLOG(2) << "WebContentsVideoCaptureDevice@" << this << " destroying."; 836 DVLOG(2) << "WebContentsVideoCaptureDevice@" << this << " destroying.";
837 } 837 }
838 838
839 // static 839 // static
840 media::VideoCaptureDevice* WebContentsVideoCaptureDevice::Create( 840 media::VideoCaptureDevice* WebContentsVideoCaptureDevice::Create(
841 const std::string& device_id) { 841 const std::string& device_id) {
842 // Parse device_id into render_process_id and render_view_id. 842 // Parse device_id into render_process_id and main_render_frame_id.
843 int render_process_id = -1; 843 int render_process_id = -1;
844 int main_render_frame_id = -1; 844 int main_render_frame_id = -1;
845 if (!WebContentsCaptureUtil::ExtractTabCaptureTarget( 845 if (!WebContentsCaptureUtil::ExtractTabCaptureTarget(
846 device_id, &render_process_id, &main_render_frame_id)) { 846 device_id, &render_process_id, &main_render_frame_id)) {
847 return NULL; 847 return NULL;
848 } 848 }
849 849
850 return new WebContentsVideoCaptureDevice( 850 return new WebContentsVideoCaptureDevice(
851 render_process_id, main_render_frame_id); 851 render_process_id, main_render_frame_id);
852 } 852 }
853 853
854 void WebContentsVideoCaptureDevice::AllocateAndStart( 854 void WebContentsVideoCaptureDevice::AllocateAndStart(
855 const media::VideoCaptureParams& params, 855 const media::VideoCaptureParams& params,
856 scoped_ptr<Client> client) { 856 scoped_ptr<Client> client) {
857 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString(); 857 DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString();
858 core_->AllocateAndStart(params, client.Pass()); 858 core_->AllocateAndStart(params, client.Pass());
859 } 859 }
860 860
861 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { 861 void WebContentsVideoCaptureDevice::StopAndDeAllocate() {
862 core_->StopAndDeAllocate(); 862 core_->StopAndDeAllocate();
863 } 863 }
864 864
865 } // namespace content 865 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698