15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/web_contents_video_capture_device.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/debug/debugger.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/run_loop.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/test/test_timeouts.h" 11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/timer/timer.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/browser_thread_impl.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/renderer_host/media/video_capture_buffer_pool.h" 15a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "content/browser/renderer_host/media/video_capture_oracle.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/renderer_host/media/web_contents_capture_util.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/renderer_host/render_view_host_factory.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/render_widget_host_impl.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/renderer_host/test_render_view_host.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/port/browser/render_widget_host_view_frame_subscriber.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/notification_service.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/notification_types.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/mock_render_process_host.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_browser_context.h" 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/public/test/test_browser_thread_bundle.h" 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/test/test_utils.h" 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/test/test_web_contents.h" 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/video_util.h" 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/yuv_convert.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/video/capture/video_capture_types.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "skia/ext/platform_canvas.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkColor.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kTestWidth = 320; 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kTestHeight = 240; 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kTestFramesPerSecond = 20; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SkColor kNothingYet = 0xdeadbeef; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SkColor kNotInterested = ~kNothingYet; 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DeadlineExceeded(base::Closure quit_closure) { 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!base::debug::BeingDebugged()) { 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) quit_closure.Run(); 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FAIL() << "Deadline exceeded while waiting, quitting"; 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(WARNING) << "Deadline exceeded; test would fail if debugger weren't " 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "attached."; 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RunCurrentLoopWithDeadline() { 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Timer deadline(false, false); 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) deadline.Start(FROM_HERE, TestTimeouts::action_max_timeout(), base::Bind( 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &DeadlineExceeded, base::MessageLoop::current()->QuitClosure())); 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->Run(); 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) deadline.Stop(); 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SkColor ConvertRgbToYuv(SkColor rgb) { 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8 yuv[3]; 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) media::ConvertRGB32ToYUV(reinterpret_cast<uint8*>(&rgb), 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) yuv, yuv + 1, yuv + 2, 1, 1, 1, 1, 1); 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return SkColorSetRGB(yuv[0], yuv[1], yuv[2]); 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Thread-safe class that controls the source pattern to be captured by the 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// system under test. The lifetime of this class is greater than the lifetime 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// of all objects that reference it, so it does not need to be reference 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// counted. 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class CaptureTestSourceController { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CaptureTestSourceController() 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : color_(SK_ColorMAGENTA), 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) copy_result_size_(kTestWidth, kTestHeight), 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) can_copy_to_video_frame_(false), 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) use_frame_subscriber_(false) {} 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetSolidColor(SkColor color) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock guard(lock_); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) color_ = color; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkColor GetSolidColor() { 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock guard(lock_); 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return color_; 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void SetCopyResultSize(int width, int height) { 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock guard(lock_); 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) copy_result_size_ = gfx::Size(width, height); 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Size GetCopyResultSize() { 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock guard(lock_); 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return copy_result_size_; 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void SignalCopy() { 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(nick): This actually should always be happening on the UI thread. 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock guard(lock_); 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!copy_done_.is_null()) { 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, copy_done_); 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) copy_done_.Reset(); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void SetCanCopyToVideoFrame(bool value) { 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock guard(lock_); 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) can_copy_to_video_frame_ = value; 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool CanCopyToVideoFrame() { 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock guard(lock_); 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return can_copy_to_video_frame_; 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void SetUseFrameSubscriber(bool value) { 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock guard(lock_); 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) use_frame_subscriber_ = value; 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool CanUseFrameSubscriber() { 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock guard(lock_); 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return use_frame_subscriber_; 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void WaitForNextCopy() { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock guard(lock_); 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) copy_done_ = base::MessageLoop::current()->QuitClosure(); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RunCurrentLoopWithDeadline(); 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Lock lock_; // Guards changes to all members. 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkColor color_; 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Size copy_result_size_; 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool can_copy_to_video_frame_; 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool use_frame_subscriber_; 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Closure copy_done_; 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(CaptureTestSourceController); 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// A stub implementation which returns solid-color bitmaps in calls to 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// CopyFromCompositingSurfaceToVideoFrame(), and which allows the video-frame 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// readback path to be switched on and off. The behavior is controlled by a 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// CaptureTestSourceController. 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class CaptureTestView : public TestRenderWidgetHostView { 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) explicit CaptureTestView(RenderWidgetHostImpl* rwh, 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CaptureTestSourceController* controller) 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : TestRenderWidgetHostView(rwh), 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) controller_(controller) {} 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~CaptureTestView() {} 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TestRenderWidgetHostView overrides. 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual gfx::Rect GetViewBounds() const OVERRIDE { 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return gfx::Rect(100, 100, 100 + kTestWidth, 100 + kTestHeight); 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool CanCopyToVideoFrame() const OVERRIDE { 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return controller_->CanCopyToVideoFrame(); 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void CopyFromCompositingSurfaceToVideoFrame( 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Rect& src_subrect, 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const scoped_refptr<media::VideoFrame>& target, 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::Callback<void(bool)>& callback) OVERRIDE { 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkColor c = ConvertRgbToYuv(controller_->GetSolidColor()); 178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) media::FillYUV( 179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) target.get(), SkColorGetR(c), SkColorGetG(c), SkColorGetB(c)); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(true); 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) controller_->SignalCopy(); 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void BeginFrameSubscription( 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) OVERRIDE { 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) subscriber_.reset(subscriber.release()); 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void EndFrameSubscription() OVERRIDE { 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) subscriber_.reset(); 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Simulate a compositor paint event for our subscriber. 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void SimulateUpdate() { 195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::Time present_time = base::Time::Now(); 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback; 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<media::VideoFrame> target; 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (subscriber_ && subscriber_->ShouldCaptureFrame(present_time, 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &target, &callback)) { 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkColor c = ConvertRgbToYuv(controller_->GetSolidColor()); 201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) media::FillYUV( 202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) target.get(), SkColorGetR(c), SkColorGetG(c), SkColorGetB(c)); 203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, 204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FROM_HERE, 205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Bind(callback, present_time, true)); 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) controller_->SignalCopy(); 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber_; 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CaptureTestSourceController* const controller_; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTestView); 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(COMPILER_MSVC) 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// MSVC warns on diamond inheritance. See comment for same warning on 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// RenderViewHostImpl. 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#pragma warning(push) 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#pragma warning(disable: 4250) 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// A stub implementation which returns solid-color bitmaps in calls to 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// CopyFromBackingStore(). The behavior is controlled by a 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// CaptureTestSourceController. 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class CaptureTestRenderViewHost : public TestRenderViewHost { 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CaptureTestRenderViewHost(SiteInstance* instance, 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RenderViewHostDelegate* delegate, 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RenderWidgetHostDelegate* widget_delegate, 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int routing_id, 233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int main_frame_routing_id, 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool swapped_out, 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CaptureTestSourceController* controller) 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : TestRenderViewHost(instance, delegate, widget_delegate, routing_id, 237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) main_frame_routing_id, swapped_out), 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) controller_(controller) { 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Override the default view installed by TestRenderViewHost; we need 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // our special subclass which has mocked-out tab capture support. 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RenderWidgetHostView* old_view = GetView(); 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetView(new CaptureTestView(this, controller)); 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete old_view; 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TestRenderViewHost overrides. 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void CopyFromBackingStore( 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Rect& src_rect, 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Size& accelerated_dst_size, 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::Callback<void(bool, const SkBitmap&)>& callback) OVERRIDE { 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Size size = controller_->GetCopyResultSize(); 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkColor color = controller_->GetSolidColor(); 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Although it's not necessary, use a PlatformBitmap here (instead of a 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // regular SkBitmap) to exercise possible threading issues. 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) skia::PlatformBitmap output; 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(output.Allocate(size.width(), size.height(), false)); 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkAutoLockPixels locker(output.GetBitmap()); 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output.GetBitmap().eraseColor(color); 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback.Run(true, output.GetBitmap()); 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) controller_->SignalCopy(); 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CaptureTestSourceController* controller_; 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTestRenderViewHost); 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(COMPILER_MSVC) 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Re-enable warning 4250 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#pragma warning(pop) 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class CaptureTestRenderViewHostFactory : public RenderViewHostFactory { 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) explicit CaptureTestRenderViewHostFactory( 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CaptureTestSourceController* controller) : controller_(controller) { 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RegisterFactory(this); 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~CaptureTestRenderViewHostFactory() { 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UnregisterFactory(); 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // RenderViewHostFactory implementation. 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual RenderViewHost* CreateRenderViewHost( 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SiteInstance* instance, 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RenderViewHostDelegate* delegate, 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RenderWidgetHostDelegate* widget_delegate, 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int routing_id, 294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int main_frame_routing_id, 295a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch bool swapped_out) OVERRIDE { 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return new CaptureTestRenderViewHost(instance, delegate, widget_delegate, 297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) routing_id, main_frame_routing_id, 298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) swapped_out, controller_); 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CaptureTestSourceController* controller_; 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTestRenderViewHostFactory); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A stub consumer of captured video frames, which checks the output of 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WebContentsVideoCaptureDevice. 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class StubConsumer : public media::VideoCaptureDevice::EventHandler { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StubConsumer() 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : error_encountered_(false), 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) wait_color_yuv_(0xcafe1950) { 313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch buffer_pool_ = 314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch new VideoCaptureBufferPool(kTestWidth * kTestHeight * 3 / 2, 2); 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(buffer_pool_->Allocate()); 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~StubConsumer() {} 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void QuitIfConditionMet(SkColor color) { 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock guard(lock_); 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (wait_color_yuv_ == color || error_encountered_) 323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->Quit(); 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void WaitForNextColor(SkColor expected_color) { 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock guard(lock_); 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) wait_color_yuv_ = ConvertRgbToYuv(expected_color); 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) error_encountered_ = false; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RunCurrentLoopWithDeadline(); 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock guard(lock_); 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_FALSE(error_encountered_); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void WaitForError() { 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock guard(lock_); 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) wait_color_yuv_ = kNotInterested; 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) error_encountered_ = false; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RunCurrentLoopWithDeadline(); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock guard(lock_); 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(error_encountered_); 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool HasError() { 353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::AutoLock guard(lock_); 354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return error_encountered_; 355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual scoped_refptr<media::VideoFrame> ReserveOutputBuffer() OVERRIDE { 358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return buffer_pool_->ReserveI420VideoFrame(gfx::Size(kTestWidth, 359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kTestHeight), 360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 0); 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnIncomingCapturedFrame( 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const uint8* data, 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int length, 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time timestamp, 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int rotation, 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool flip_vert, 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool flip_horiz) OVERRIDE { 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FAIL(); 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnIncomingCapturedVideoFrame( 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const scoped_refptr<media::VideoFrame>& frame, 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time timestamp) OVERRIDE { 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(gfx::Size(kTestWidth, kTestHeight), frame->coded_size()); 3774311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch EXPECT_EQ(media::VideoFrame::I420, frame->format()); 378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_LE( 379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 0, 380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch buffer_pool_->RecognizeReservedBuffer(frame->shared_memory_handle())); 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8 yuv[3]; 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int plane = 0; plane < 3; ++plane) { 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) yuv[plane] = frame->data(plane)[0]; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(nick): We just look at the first pixel presently, because if 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the analysis is too slow, the backlog of frames will grow without bound 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // and trouble erupts. http://crbug.com/174519 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PostColorOrError(SkColorSetRGB(yuv[0], yuv[1], yuv[2])); 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void PostColorOrError(SkColor new_color) { 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &StubConsumer::QuitIfConditionMet, base::Unretained(this), new_color)); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnError() OVERRIDE { 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock guard(lock_); 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) error_encountered_ = true; 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PostColorOrError(kNothingYet); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnFrameInfo(const media::VideoCaptureCapability& info) OVERRIDE { 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kTestWidth, info.width); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kTestHeight, info.height); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kTestFramesPerSecond, info.frame_rate); 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(media::VideoCaptureCapability::kI420, info.color); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Lock lock_; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool error_encountered_; 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkColor wait_color_yuv_; 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<VideoCaptureBufferPool> buffer_pool_; 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(StubConsumer); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test harness that sets up a minimal environment with necessary stubs. 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class WebContentsVideoCaptureDeviceTest : public testing::Test { 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // This is public because C++ method pointer scoping rules are silly and make 424868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // this hard to use with Bind(). 4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void ResetWebContents() { 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) web_contents_.reset(); 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetUp() { 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(nick): Sadness and woe! Much "mock-the-world" boilerplate could be 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // eliminated here, if only we could use RenderViewHostTestHarness. The 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // catch is that we need our TestRenderViewHost to support a 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // CopyFromBackingStore operation that we control. To accomplish that, 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // either RenderViewHostTestHarness would have to support installing a 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // custom RenderViewHostFactory, or else we implant some kind of delegated 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // CopyFromBackingStore functionality into TestRenderViewHost itself. 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) render_process_host_factory_.reset(new MockRenderProcessHostFactory()); 4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create our (self-registering) RVH factory, so that when we create a 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // WebContents, it in turn creates CaptureTestRenderViewHosts. 4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) render_view_host_factory_.reset( 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new CaptureTestRenderViewHostFactory(&controller_)); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_context_.reset(new TestBrowserContext()); 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<SiteInstance> site_instance = 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SiteInstance::Create(browser_context_.get()); 449868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SiteInstanceImpl::set_render_process_host_factory( 450868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) render_process_host_factory_.get()); 4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) web_contents_.reset( 452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) TestWebContents::Create(browser_context_.get(), site_instance.get())); 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This is actually a CaptureTestRenderViewHost. 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RenderWidgetHostImpl* rwh = 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RenderWidgetHostImpl::From(web_contents_->GetRenderViewHost()); 4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string device_id = 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebContentsCaptureUtil::AppendWebContentsDeviceScheme( 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::StringPrintf("%d:%d", rwh->GetProcess()->GetID(), 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rwh->GetRoutingID())); 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) device_.reset(WebContentsVideoCaptureDevice::Create(device_id)); 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 465868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::RunLoop().RunUntilIdle(); 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void TearDown() { 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tear down in opposite order of set-up. 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The device is destroyed asynchronously, and will notify the 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // CaptureTestSourceController when it finishes destruction. 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Trigger this, and wait. 474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (device_) { 475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) device_->DeAllocate(); 476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) device_.reset(); 477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::RunLoop().RunUntilIdle(); 4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Destroy the browser objects. 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) web_contents_.reset(); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_context_.reset(); 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 485868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::RunLoop().RunUntilIdle(); 4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 487868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SiteInstanceImpl::set_render_process_host_factory(NULL); 4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) render_view_host_factory_.reset(); 4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) render_process_host_factory_.reset(); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Accessors. 4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CaptureTestSourceController* source() { return &controller_; } 4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) media::VideoCaptureDevice* device() { return device_.get(); } 4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StubConsumer* consumer() { return &consumer_; } 4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void SimulateDrawEvent() { 4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (source()->CanUseFrameSubscriber()) { 4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Print 5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CaptureTestView* test_view = static_cast<CaptureTestView*>( 5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) web_contents_->GetRenderViewHost()->GetView()); 5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) test_view->SimulateUpdate(); 5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Simulate a non-accelerated paint. 5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NotificationService::current()->Notify( 5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE, 5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Source<RenderWidgetHost>(web_contents_->GetRenderViewHost()), 5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NotificationService::NoDetails()); 5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void DestroyVideoCaptureDevice() { device_.reset(); } 513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The consumer is the ultimate recipient of captured pixel data. 5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StubConsumer consumer_; 5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The controller controls which pixel patterns to produce. 5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CaptureTestSourceController controller_; 5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Self-registering RenderProcessHostFactory. 5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<MockRenderProcessHostFactory> render_process_host_factory_; 5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Creates capture-capable RenderViewHosts whose pixel content production is 5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // under the control of |controller_|. 5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<CaptureTestRenderViewHostFactory> render_view_host_factory_; 5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // A mocked-out browser and tab. 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<TestBrowserContext> browser_context_; 5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<WebContents> web_contents_; 5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Finally, the WebContentsVideoCaptureDevice under test. 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<media::VideoCaptureDevice> device_; 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) TestBrowserThreadBundle thread_bundle_; 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(WebContentsVideoCaptureDeviceTest, InvalidInitialWebContentsError) { 5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Before the installs itself on the UI thread up to start capturing, we'll 5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // delete the web contents. This should trigger an error which can happen in 5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // practice; we should be able to recover gracefully. 5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ResetWebContents(); 5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 544a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::VideoCaptureCapability capture_format( 545a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kTestWidth, 546a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kTestHeight, 547a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kTestFramesPerSecond, 548a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::VideoCaptureCapability::kI420, 549a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 0, 550a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) false, 551a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::ConstantResolutionVideoCaptureDevice); 552a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) device()->Allocate(capture_format, consumer()); 5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) device()->Start(); 5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_NO_FATAL_FAILURE(consumer()->WaitForError()); 5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) device()->DeAllocate(); 5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(WebContentsVideoCaptureDeviceTest, WebContentsDestroyed) { 5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We'll simulate the tab being closed after the capture pipeline is up and 5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // running. 561a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::VideoCaptureCapability capture_format( 562a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kTestWidth, 563a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kTestHeight, 564a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kTestFramesPerSecond, 565a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::VideoCaptureCapability::kI420, 566a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 0, 567a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) false, 568a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::ConstantResolutionVideoCaptureDevice); 569a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) device()->Allocate(capture_format, consumer()); 5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) device()->Start(); 5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Do one capture to prove 5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source()->SetSolidColor(SK_ColorRED); 5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SimulateDrawEvent(); 5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorRED)); 5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 577868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::RunLoop().RunUntilIdle(); 5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Post a task to close the tab. We should see an error reported to the 5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // consumer. 5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&WebContentsVideoCaptureDeviceTest::ResetWebContents, 5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this))); 5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_NO_FATAL_FAILURE(consumer()->WaitForError()); 5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) device()->DeAllocate(); 5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WebContentsVideoCaptureDeviceTest, 589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StopDeviceBeforeCaptureMachineCreation) { 590a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::VideoCaptureCapability capture_format( 591a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kTestWidth, 592a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kTestHeight, 593a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kTestFramesPerSecond, 594a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::VideoCaptureCapability::kI420, 595a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 0, 596a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) false, 597a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::ConstantResolutionVideoCaptureDevice); 598a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) device()->Allocate(capture_format, consumer()); 599c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) device()->Start(); 600c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Make a point of not running the UI messageloop here. 601c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) device()->Stop(); 602c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) device()->DeAllocate(); 603c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DestroyVideoCaptureDevice(); 604c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Currently, there should be CreateCaptureMachineOnUIThread() and 606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // DestroyCaptureMachineOnUIThread() tasks pending on the current (UI) message 607c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // loop. These should both succeed without crashing, and the machine should 608c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // wind up in the idle state. 609868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::RunLoop().RunUntilIdle(); 610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 611c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 612c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WebContentsVideoCaptureDeviceTest, StopWithRendererWorkToDo) { 613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Set up the test to use RGB copies and an normal 614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) source()->SetCanCopyToVideoFrame(false); 615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) source()->SetUseFrameSubscriber(false); 616a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::VideoCaptureCapability capture_format( 617a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kTestWidth, 618a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kTestHeight, 619a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kTestFramesPerSecond, 620a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::VideoCaptureCapability::kI420, 621a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 0, 622a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) false, 623a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::ConstantResolutionVideoCaptureDevice); 624a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) device()->Allocate(capture_format, consumer()); 625a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) device()->Start(); 627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Make a point of not running the UI messageloop here. 628868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // TODO(ajwong): Why do we care? 629868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::RunLoop().RunUntilIdle(); 630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 631c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (int i = 0; i < 10; ++i) 632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SimulateDrawEvent(); 633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 634c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) device()->Stop(); 635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) device()->DeAllocate(); 636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Currently, there should be CreateCaptureMachineOnUIThread() and 637c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // DestroyCaptureMachineOnUIThread() tasks pending on the current message 638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // loop. These should both succeed without crashing, and the machine should 639c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // wind up in the idle state. 640c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_FALSE(consumer()->HasError()); 641868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::RunLoop().RunUntilIdle(); 642c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_FALSE(consumer()->HasError()); 643c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 645c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WebContentsVideoCaptureDeviceTest, DeviceRestart) { 646a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::VideoCaptureCapability capture_format( 647a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kTestWidth, 648a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kTestHeight, 649a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kTestFramesPerSecond, 650a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::VideoCaptureCapability::kI420, 651a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 0, 652a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) false, 653a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::ConstantResolutionVideoCaptureDevice); 654a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) device()->Allocate(capture_format, consumer()); 655c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) device()->Start(); 656868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::RunLoop().RunUntilIdle(); 657c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) source()->SetSolidColor(SK_ColorRED); 658c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SimulateDrawEvent(); 659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SimulateDrawEvent(); 660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorRED)); 661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SimulateDrawEvent(); 662c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SimulateDrawEvent(); 663c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) source()->SetSolidColor(SK_ColorGREEN); 664c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SimulateDrawEvent(); 665c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorGREEN)); 666c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) device()->Stop(); 667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Device is stopped, but content can still be animating. 669c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SimulateDrawEvent(); 670c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SimulateDrawEvent(); 671868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::RunLoop().RunUntilIdle(); 672c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 673c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) device()->Start(); 674c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) source()->SetSolidColor(SK_ColorBLUE); 675c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SimulateDrawEvent(); 676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorBLUE)); 677c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) source()->SetSolidColor(SK_ColorYELLOW); 678c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SimulateDrawEvent(); 679c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorYELLOW)); 680c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) device()->DeAllocate(); 681c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 682c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The "happy case" test. No scaling is needed, so we should be able to change 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the picture emitted from the source and expect to see each delivered to the 6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// consumer. The test will alternate between the three capture paths, simulating 6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// falling in and out of accelerated compositing. 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(WebContentsVideoCaptureDeviceTest, GoesThroughAllTheMotions) { 688a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::VideoCaptureCapability capture_format( 689a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kTestWidth, 690a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kTestHeight, 691a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kTestFramesPerSecond, 692a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::VideoCaptureCapability::kI420, 693a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 0, 694a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) false, 695a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::ConstantResolutionVideoCaptureDevice); 696a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) device()->Allocate(capture_format, consumer()); 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) device()->Start(); 6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < 6; i++) { 7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char* name = NULL; 7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (i % 3) { 7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case 0: 7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source()->SetCanCopyToVideoFrame(true); 7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source()->SetUseFrameSubscriber(false); 7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) name = "VideoFrame"; 7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case 1: 7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source()->SetCanCopyToVideoFrame(false); 7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source()->SetUseFrameSubscriber(true); 7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) name = "Subscriber"; 7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case 2: 7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source()->SetCanCopyToVideoFrame(false); 7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source()->SetUseFrameSubscriber(false); 7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) name = "SkBitmap"; 7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FAIL(); 7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SCOPED_TRACE(base::StringPrintf("Using %s path, iteration #%d", name, i)); 7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source()->SetSolidColor(SK_ColorRED); 7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SimulateDrawEvent(); 7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorRED)); 7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source()->SetSolidColor(SK_ColorGREEN); 7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SimulateDrawEvent(); 7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorGREEN)); 7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source()->SetSolidColor(SK_ColorBLUE); 7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SimulateDrawEvent(); 7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorBLUE)); 7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source()->SetSolidColor(SK_ColorBLACK); 7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SimulateDrawEvent(); 7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorBLACK)); 7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) device()->DeAllocate(); 7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(WebContentsVideoCaptureDeviceTest, RejectsInvalidAllocateParams) { 744a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::VideoCaptureCapability capture_format( 745a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1280, 746a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 720, 747a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) -2, 748a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::VideoCaptureCapability::kI420, 749a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 0, 750a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) false, 751a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::ConstantResolutionVideoCaptureDevice); 752a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, 753a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) FROM_HERE, 754a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Bind(&media::VideoCaptureDevice::Allocate, 755a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Unretained(device()), 756a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) capture_format, 757a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) consumer())); 7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_NO_FATAL_FAILURE(consumer()->WaitForError()); 7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(WebContentsVideoCaptureDeviceTest, BadFramesGoodFrames) { 762a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::VideoCaptureCapability capture_format( 763a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kTestWidth, 764a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kTestHeight, 765a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kTestFramesPerSecond, 766a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::VideoCaptureCapability::kI420, 767a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 0, 768a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) false, 769a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) media::ConstantResolutionVideoCaptureDevice); 770a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) device()->Allocate(capture_format, consumer()); 7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 1x1 is too small to process; we intend for this to result in an error. 7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source()->SetCopyResultSize(1, 1); 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source()->SetSolidColor(SK_ColorRED); 7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) device()->Start(); 7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // These frames ought to be dropped during the Render stage. Let 7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // several captures to happen. 7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_NO_FATAL_FAILURE(source()->WaitForNextCopy()); 7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_NO_FATAL_FAILURE(source()->WaitForNextCopy()); 7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_NO_FATAL_FAILURE(source()->WaitForNextCopy()); 7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_NO_FATAL_FAILURE(source()->WaitForNextCopy()); 7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_NO_FATAL_FAILURE(source()->WaitForNextCopy()); 7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Now push some good frames through; they should be processed normally. 7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source()->SetCopyResultSize(kTestWidth, kTestHeight); 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source()->SetSolidColor(SK_ColorGREEN); 7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorGREEN)); 7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source()->SetSolidColor(SK_ColorRED); 7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_NO_FATAL_FAILURE(consumer()->WaitForNextColor(SK_ColorRED)); 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) device()->Stop(); 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) device()->DeAllocate(); 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 796c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 797c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace content 798