This source file includes following definitions.
- DeadlineExceeded
- RunCurrentLoopWithDeadline
- ConvertRgbToYuv
- use_frame_subscriber_
- SetSolidColor
- GetSolidColor
- SetCopyResultSize
- GetCopyResultSize
- SignalCopy
- SetCanCopyToVideoFrame
- CanCopyToVideoFrame
- SetUseFrameSubscriber
- CanUseFrameSubscriber
- WaitForNextCopy
- controller_
- GetViewBounds
- CanCopyToVideoFrame
- CopyFromCompositingSurfaceToVideoFrame
- BeginFrameSubscription
- EndFrameSubscription
- SimulateUpdate
- controller_
- CopyFromBackingStore
- CreateRenderViewHost
- error_callback_
- ReserveOutputBuffer
- OnIncomingCapturedData
- OnIncomingCapturedVideoFrame
- OnError
- pool_
- wait_color_yuv_
- PassClient
- QuitIfConditionMet
- WaitForNextColor
- WaitForError
- HasError
- OnError
- OnColor
- ResetWebContents
- SetUp
- TearDown
- source
- device
- SimulateDrawEvent
- DestroyVideoCaptureDevice
- client_observer
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include "content/browser/media/capture/web_contents_video_capture_device.h"
#include "base/bind_helpers.h"
#include "base/debug/debugger.h"
#include "base/run_loop.h"
#include "base/test/test_timeouts.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/media/capture/video_capture_oracle.h"
#include "content/browser/media/capture/web_contents_capture_util.h"
#include "content/browser/renderer_host/media/video_capture_buffer_pool.h"
#include "content/browser/renderer_host/render_view_host_factory.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/port/browser/render_widget_host_view_frame_subscriber.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
#include "media/base/yuv_convert.h"
#include "media/video/capture/video_capture_types.h"
#include "skia/ext/platform_canvas.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkColor.h"
namespace content {
namespace {
const int kTestWidth = 320;
const int kTestHeight = 240;
const int kTestFramesPerSecond = 20;
const SkColor kNothingYet = 0xdeadbeef;
const SkColor kNotInterested = ~kNothingYet;
void DeadlineExceeded(base::Closure quit_closure) {
if (!base::debug::BeingDebugged()) {
quit_closure.Run();
FAIL() << "Deadline exceeded while waiting, quitting";
} else {
LOG(WARNING) << "Deadline exceeded; test would fail if debugger weren't "
<< "attached.";
}
}
void RunCurrentLoopWithDeadline() {
base::Timer deadline(false, false);
deadline.Start(FROM_HERE, TestTimeouts::action_max_timeout(), base::Bind(
&DeadlineExceeded, base::MessageLoop::current()->QuitClosure()));
base::MessageLoop::current()->Run();
deadline.Stop();
}
SkColor ConvertRgbToYuv(SkColor rgb) {
uint8 yuv[3];
media::ConvertRGB32ToYUV(reinterpret_cast<uint8*>(&rgb),
yuv, yuv + 1, yuv + 2, 1, 1, 1, 1, 1);
return SkColorSetRGB(yuv[0], yuv[1], yuv[2]);
}
class CaptureTestSourceController {
public:
CaptureTestSourceController()
: color_(SK_ColorMAGENTA),
copy_result_size_(kTestWidth, kTestHeight),
can_copy_to_video_frame_(false),
use_frame_subscriber_(false) {}
void SetSolidColor(SkColor color) {
base::AutoLock guard(lock_);
color_ = color;
}
SkColor GetSolidColor() {
base::AutoLock guard(lock_);
return color_;
}
void SetCopyResultSize(int width, int height) {
base::AutoLock guard(lock_);
copy_result_size_ = gfx::Size(width, height);
}
gfx::Size GetCopyResultSize() {
base::AutoLock guard(lock_);
return copy_result_size_;
}
void SignalCopy() {
base::AutoLock guard(lock_);
if (!copy_done_.is_null()) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, copy_done_);
copy_done_.Reset();
}
}
void SetCanCopyToVideoFrame(bool value) {
base::AutoLock guard(lock_);
can_copy_to_video_frame_ = value;
}
bool CanCopyToVideoFrame() {
base::AutoLock guard(lock_);
return can_copy_to_video_frame_;
}
void SetUseFrameSubscriber(bool value) {
base::AutoLock guard(lock_);
use_frame_subscriber_ = value;
}
bool CanUseFrameSubscriber() {
base::AutoLock guard(lock_);
return use_frame_subscriber_;
}
void WaitForNextCopy() {
{
base::AutoLock guard(lock_);
copy_done_ = base::MessageLoop::current()->QuitClosure();
}
RunCurrentLoopWithDeadline();
}
private:
base::Lock lock_;
SkColor color_;
gfx::Size copy_result_size_;
bool can_copy_to_video_frame_;
bool use_frame_subscriber_;
base::Closure copy_done_;
DISALLOW_COPY_AND_ASSIGN(CaptureTestSourceController);
};
class CaptureTestView : public TestRenderWidgetHostView {
public:
explicit CaptureTestView(RenderWidgetHostImpl* rwh,
CaptureTestSourceController* controller)
: TestRenderWidgetHostView(rwh),
controller_(controller) {}
virtual ~CaptureTestView() {}
virtual gfx::Rect GetViewBounds() const OVERRIDE {
return gfx::Rect(100, 100, 100 + kTestWidth, 100 + kTestHeight);
}
virtual bool CanCopyToVideoFrame() const OVERRIDE {
return controller_->CanCopyToVideoFrame();
}
virtual void CopyFromCompositingSurfaceToVideoFrame(
const gfx::Rect& src_subrect,
const scoped_refptr<media::VideoFrame>& target,
const base::Callback<void(bool)>& callback) OVERRIDE {
SkColor c = ConvertRgbToYuv(controller_->GetSolidColor());
media::FillYUV(
target.get(), SkColorGetR(c), SkColorGetG(c), SkColorGetB(c));
callback.Run(true);
controller_->SignalCopy();
}
virtual void BeginFrameSubscription(
scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) OVERRIDE {
subscriber_.reset(subscriber.release());
}
virtual void EndFrameSubscription() OVERRIDE {
subscriber_.reset();
}
void SimulateUpdate() {
const base::TimeTicks present_time = base::TimeTicks::Now();
RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback;
scoped_refptr<media::VideoFrame> target;
if (subscriber_ && subscriber_->ShouldCaptureFrame(present_time,
&target, &callback)) {
SkColor c = ConvertRgbToYuv(controller_->GetSolidColor());
media::FillYUV(
target.get(), SkColorGetR(c), SkColorGetG(c), SkColorGetB(c));
BrowserThread::PostTask(BrowserThread::UI,
FROM_HERE,
base::Bind(callback, present_time, true));
controller_->SignalCopy();
}
}
private:
scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber_;
CaptureTestSourceController* const controller_;
DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTestView);
};
#if defined(COMPILER_MSVC)
#pragma warning(push)
#pragma warning(disable: 4250)
#endif
class CaptureTestRenderViewHost : public TestRenderViewHost {
public:
CaptureTestRenderViewHost(SiteInstance* instance,
RenderViewHostDelegate* delegate,
RenderWidgetHostDelegate* widget_delegate,
int routing_id,
int main_frame_routing_id,
bool swapped_out,
CaptureTestSourceController* controller)
: TestRenderViewHost(instance, delegate, widget_delegate, routing_id,
main_frame_routing_id, swapped_out),
controller_(controller) {
RenderWidgetHostView* old_view = GetView();
SetView(new CaptureTestView(this, controller));
delete old_view;
}
virtual void CopyFromBackingStore(
const gfx::Rect& src_rect,
const gfx::Size& accelerated_dst_size,
const base::Callback<void(bool, const SkBitmap&)>& callback,
const SkBitmap::Config& bitmap_config) OVERRIDE {
gfx::Size size = controller_->GetCopyResultSize();
SkColor color = controller_->GetSolidColor();
skia::PlatformBitmap output;
EXPECT_TRUE(output.Allocate(size.width(), size.height(), false));
{
SkAutoLockPixels locker(output.GetBitmap());
output.GetBitmap().eraseColor(color);
}
callback.Run(true, output.GetBitmap());
controller_->SignalCopy();
}
private:
CaptureTestSourceController* controller_;
DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTestRenderViewHost);
};
#if defined(COMPILER_MSVC)
#pragma warning(pop)
#endif
class CaptureTestRenderViewHostFactory : public RenderViewHostFactory {
public:
explicit CaptureTestRenderViewHostFactory(
CaptureTestSourceController* controller) : controller_(controller) {
RegisterFactory(this);
}
virtual ~CaptureTestRenderViewHostFactory() {
UnregisterFactory();
}
virtual RenderViewHost* CreateRenderViewHost(
SiteInstance* instance,
RenderViewHostDelegate* delegate,
RenderWidgetHostDelegate* widget_delegate,
int routing_id,
int main_frame_routing_id,
bool swapped_out) OVERRIDE {
return new CaptureTestRenderViewHost(instance, delegate, widget_delegate,
routing_id, main_frame_routing_id,
swapped_out, controller_);
}
private:
CaptureTestSourceController* controller_;
DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTestRenderViewHostFactory);
};
class StubClient : public media::VideoCaptureDevice::Client {
public:
StubClient(const base::Callback<void(SkColor)>& color_callback,
const base::Closure& error_callback)
: color_callback_(color_callback),
error_callback_(error_callback) {
buffer_pool_ = new VideoCaptureBufferPool(2);
}
virtual ~StubClient() {}
virtual scoped_refptr<media::VideoCaptureDevice::Client::Buffer>
ReserveOutputBuffer(media::VideoFrame::Format format,
const gfx::Size& dimensions) OVERRIDE {
CHECK_EQ(format, media::VideoFrame::I420);
const size_t frame_bytes =
media::VideoFrame::AllocationSize(media::VideoFrame::I420, dimensions);
int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId;
int buffer_id =
buffer_pool_->ReserveForProducer(frame_bytes, &buffer_id_to_drop);
if (buffer_id == VideoCaptureBufferPool::kInvalidId)
return NULL;
void* data;
size_t size;
buffer_pool_->GetBufferInfo(buffer_id, &data, &size);
return scoped_refptr<media::VideoCaptureDevice::Client::Buffer>(
new PoolBuffer(buffer_pool_, buffer_id, data, size));
}
virtual void OnIncomingCapturedData(
const uint8* data,
int length,
const media::VideoCaptureFormat& frame_format,
int rotation,
base::TimeTicks timestamp) OVERRIDE {
FAIL();
}
virtual void OnIncomingCapturedVideoFrame(
const scoped_refptr<Buffer>& buffer,
const media::VideoCaptureFormat& buffer_format,
const scoped_refptr<media::VideoFrame>& frame,
base::TimeTicks timestamp) OVERRIDE {
EXPECT_EQ(gfx::Size(kTestWidth, kTestHeight), buffer_format.frame_size);
EXPECT_EQ(media::PIXEL_FORMAT_I420, buffer_format.pixel_format);
EXPECT_EQ(media::VideoFrame::I420, frame->format());
uint8 yuv[3];
for (int plane = 0; plane < 3; ++plane)
yuv[plane] = frame->data(plane)[0];
color_callback_.Run((SkColorSetRGB(yuv[0], yuv[1], yuv[2])));
}
virtual void OnError(const std::string& reason) OVERRIDE {
error_callback_.Run();
}
private:
class PoolBuffer : public media::VideoCaptureDevice::Client::Buffer {
public:
PoolBuffer(const scoped_refptr<VideoCaptureBufferPool>& pool,
int buffer_id,
void* data,
size_t size)
: Buffer(buffer_id, data, size), pool_(pool) {}
private:
virtual ~PoolBuffer() { pool_->RelinquishProducerReservation(id()); }
const scoped_refptr<VideoCaptureBufferPool> pool_;
};
scoped_refptr<VideoCaptureBufferPool> buffer_pool_;
base::Callback<void(SkColor)> color_callback_;
base::Closure error_callback_;
DISALLOW_COPY_AND_ASSIGN(StubClient);
};
class StubClientObserver {
public:
StubClientObserver()
: error_encountered_(false),
wait_color_yuv_(0xcafe1950) {
client_.reset(new StubClient(
base::Bind(&StubClientObserver::OnColor, base::Unretained(this)),
base::Bind(&StubClientObserver::OnError, base::Unretained(this))));
}
virtual ~StubClientObserver() {}
scoped_ptr<media::VideoCaptureDevice::Client> PassClient() {
return client_.PassAs<media::VideoCaptureDevice::Client>();
}
void QuitIfConditionMet(SkColor color) {
base::AutoLock guard(lock_);
if (wait_color_yuv_ == color || error_encountered_)
base::MessageLoop::current()->Quit();
}
void WaitForNextColor(SkColor expected_color) {
{
base::AutoLock guard(lock_);
wait_color_yuv_ = ConvertRgbToYuv(expected_color);
error_encountered_ = false;
}
RunCurrentLoopWithDeadline();
{
base::AutoLock guard(lock_);
ASSERT_FALSE(error_encountered_);
}
}
void WaitForError() {
{
base::AutoLock guard(lock_);
wait_color_yuv_ = kNotInterested;
error_encountered_ = false;
}
RunCurrentLoopWithDeadline();
{
base::AutoLock guard(lock_);
ASSERT_TRUE(error_encountered_);
}
}
bool HasError() {
base::AutoLock guard(lock_);
return error_encountered_;
}
void OnError() {
{
base::AutoLock guard(lock_);
error_encountered_ = true;
}
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
&StubClientObserver::QuitIfConditionMet,
base::Unretained(this),
kNothingYet));
}
void OnColor(SkColor color) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
&StubClientObserver::QuitIfConditionMet,
base::Unretained(this),
color));
}
private:
base::Lock lock_;
bool error_encountered_;
SkColor wait_color_yuv_;
scoped_ptr<StubClient> client_;
DISALLOW_COPY_AND_ASSIGN(StubClientObserver);
};
class WebContentsVideoCaptureDeviceTest : public testing::Test {
public:
void ResetWebContents() {
web_contents_.reset();
}
protected:
virtual void SetUp() {
render_process_host_factory_.reset(new MockRenderProcessHostFactory());
render_view_host_factory_.reset(
new CaptureTestRenderViewHostFactory(&controller_));
browser_context_.reset(new TestBrowserContext());
scoped_refptr<SiteInstance> site_instance =
SiteInstance::Create(browser_context_.get());
SiteInstanceImpl::set_render_process_host_factory(
render_process_host_factory_.get());
web_contents_.reset(
TestWebContents::Create(browser_context_.get(), site_instance.get()));
RenderWidgetHostImpl* rwh =
RenderWidgetHostImpl::From(web_contents_->GetRenderViewHost());
std::string device_id =
WebContentsCaptureUtil::AppendWebContentsDeviceScheme(
base::StringPrintf("%d:%d", rwh->GetProcess()->GetID(),
rwh->GetRoutingID()));
device_.reset(WebContentsVideoCaptureDevice::Create(device_id));
base::RunLoop().RunUntilIdle();
}
virtual void TearDown() {
if (device_) {
device_->StopAndDeAllocate();
device_.reset();
}
base::RunLoop().RunUntilIdle();
web_contents_.reset();
browser_context_.reset();
base::RunLoop().RunUntilIdle();
SiteInstanceImpl::set_render_process_host_factory(NULL);
render_view_host_factory_.reset();
render_process_host_factory_.reset();
}
CaptureTestSourceController* source() { return &controller_; }
media::VideoCaptureDevice* device() { return device_.get(); }
void SimulateDrawEvent() {
if (source()->CanUseFrameSubscriber()) {
CaptureTestView* test_view = static_cast<CaptureTestView*>(
web_contents_->GetRenderViewHost()->GetView());
test_view->SimulateUpdate();
} else {
NotificationService::current()->Notify(
NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
Source<RenderWidgetHost>(web_contents_->GetRenderViewHost()),
NotificationService::NoDetails());
}
}
void DestroyVideoCaptureDevice() { device_.reset(); }
StubClientObserver* client_observer() {
return &client_observer_;
}
private:
StubClientObserver client_observer_;
CaptureTestSourceController controller_;
scoped_ptr<MockRenderProcessHostFactory> render_process_host_factory_;
scoped_ptr<CaptureTestRenderViewHostFactory> render_view_host_factory_;
scoped_ptr<TestBrowserContext> browser_context_;
scoped_ptr<WebContents> web_contents_;
scoped_ptr<media::VideoCaptureDevice> device_;
TestBrowserThreadBundle thread_bundle_;
};
TEST_F(WebContentsVideoCaptureDeviceTest, InvalidInitialWebContentsError) {
ResetWebContents();
media::VideoCaptureParams capture_params;
capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
capture_params.requested_format.frame_rate = kTestFramesPerSecond;
capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
capture_params.allow_resolution_change = false;
device()->AllocateAndStart(capture_params, client_observer()->PassClient());
ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForError());
device()->StopAndDeAllocate();
}
TEST_F(WebContentsVideoCaptureDeviceTest, WebContentsDestroyed) {
media::VideoCaptureParams capture_params;
capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
capture_params.requested_format.frame_rate = kTestFramesPerSecond;
capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
capture_params.allow_resolution_change = false;
device()->AllocateAndStart(capture_params, client_observer()->PassClient());
source()->SetSolidColor(SK_ColorRED);
SimulateDrawEvent();
ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED));
base::RunLoop().RunUntilIdle();
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&WebContentsVideoCaptureDeviceTest::ResetWebContents,
base::Unretained(this)));
ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForError());
device()->StopAndDeAllocate();
}
TEST_F(WebContentsVideoCaptureDeviceTest,
StopDeviceBeforeCaptureMachineCreation) {
media::VideoCaptureParams capture_params;
capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
capture_params.requested_format.frame_rate = kTestFramesPerSecond;
capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
capture_params.allow_resolution_change = false;
device()->AllocateAndStart(capture_params, client_observer()->PassClient());
device()->StopAndDeAllocate();
DestroyVideoCaptureDevice();
base::RunLoop().RunUntilIdle();
}
TEST_F(WebContentsVideoCaptureDeviceTest, StopWithRendererWorkToDo) {
source()->SetCanCopyToVideoFrame(false);
source()->SetUseFrameSubscriber(false);
media::VideoCaptureParams capture_params;
capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
capture_params.requested_format.frame_rate = kTestFramesPerSecond;
capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
capture_params.allow_resolution_change = false;
device()->AllocateAndStart(capture_params, client_observer()->PassClient());
base::RunLoop().RunUntilIdle();
for (int i = 0; i < 10; ++i)
SimulateDrawEvent();
ASSERT_FALSE(client_observer()->HasError());
device()->StopAndDeAllocate();
ASSERT_FALSE(client_observer()->HasError());
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(client_observer()->HasError());
}
TEST_F(WebContentsVideoCaptureDeviceTest, DeviceRestart) {
media::VideoCaptureParams capture_params;
capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
capture_params.requested_format.frame_rate = kTestFramesPerSecond;
capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
capture_params.allow_resolution_change = false;
device()->AllocateAndStart(capture_params, client_observer()->PassClient());
base::RunLoop().RunUntilIdle();
source()->SetSolidColor(SK_ColorRED);
SimulateDrawEvent();
SimulateDrawEvent();
ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED));
SimulateDrawEvent();
SimulateDrawEvent();
source()->SetSolidColor(SK_ColorGREEN);
SimulateDrawEvent();
ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorGREEN));
device()->StopAndDeAllocate();
SimulateDrawEvent();
SimulateDrawEvent();
base::RunLoop().RunUntilIdle();
StubClientObserver observer2;
device()->AllocateAndStart(capture_params, observer2.PassClient());
source()->SetSolidColor(SK_ColorBLUE);
SimulateDrawEvent();
ASSERT_NO_FATAL_FAILURE(observer2.WaitForNextColor(SK_ColorBLUE));
source()->SetSolidColor(SK_ColorYELLOW);
SimulateDrawEvent();
ASSERT_NO_FATAL_FAILURE(observer2.WaitForNextColor(SK_ColorYELLOW));
device()->StopAndDeAllocate();
}
TEST_F(WebContentsVideoCaptureDeviceTest, GoesThroughAllTheMotions) {
media::VideoCaptureParams capture_params;
capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
capture_params.requested_format.frame_rate = kTestFramesPerSecond;
capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
capture_params.allow_resolution_change = false;
device()->AllocateAndStart(capture_params, client_observer()->PassClient());
for (int i = 0; i < 6; i++) {
const char* name = NULL;
switch (i % 3) {
case 0:
source()->SetCanCopyToVideoFrame(true);
source()->SetUseFrameSubscriber(false);
name = "VideoFrame";
break;
case 1:
source()->SetCanCopyToVideoFrame(false);
source()->SetUseFrameSubscriber(true);
name = "Subscriber";
break;
case 2:
source()->SetCanCopyToVideoFrame(false);
source()->SetUseFrameSubscriber(false);
name = "SkBitmap";
break;
default:
FAIL();
}
SCOPED_TRACE(base::StringPrintf("Using %s path, iteration #%d", name, i));
source()->SetSolidColor(SK_ColorRED);
SimulateDrawEvent();
ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED));
source()->SetSolidColor(SK_ColorGREEN);
SimulateDrawEvent();
ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorGREEN));
source()->SetSolidColor(SK_ColorBLUE);
SimulateDrawEvent();
ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorBLUE));
source()->SetSolidColor(SK_ColorBLACK);
SimulateDrawEvent();
ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorBLACK));
}
device()->StopAndDeAllocate();
}
TEST_F(WebContentsVideoCaptureDeviceTest, RejectsInvalidAllocateParams) {
media::VideoCaptureParams capture_params;
capture_params.requested_format.frame_size.SetSize(1280, 720);
capture_params.requested_format.frame_rate = -2;
capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
capture_params.allow_resolution_change = false;
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
base::Bind(&media::VideoCaptureDevice::AllocateAndStart,
base::Unretained(device()),
capture_params,
base::Passed(client_observer()->PassClient())));
ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForError());
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
base::Bind(&media::VideoCaptureDevice::StopAndDeAllocate,
base::Unretained(device())));
base::RunLoop().RunUntilIdle();
}
TEST_F(WebContentsVideoCaptureDeviceTest, BadFramesGoodFrames) {
media::VideoCaptureParams capture_params;
capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
capture_params.requested_format.frame_rate = kTestFramesPerSecond;
capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
capture_params.allow_resolution_change = false;
source()->SetCopyResultSize(1, 1);
source()->SetSolidColor(SK_ColorRED);
device()->AllocateAndStart(capture_params, client_observer()->PassClient());
ASSERT_NO_FATAL_FAILURE(source()->WaitForNextCopy());
ASSERT_NO_FATAL_FAILURE(source()->WaitForNextCopy());
ASSERT_NO_FATAL_FAILURE(source()->WaitForNextCopy());
ASSERT_NO_FATAL_FAILURE(source()->WaitForNextCopy());
ASSERT_NO_FATAL_FAILURE(source()->WaitForNextCopy());
source()->SetCopyResultSize(kTestWidth, kTestHeight);
source()->SetSolidColor(SK_ColorGREEN);
ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorGREEN));
source()->SetSolidColor(SK_ColorRED);
ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED));
device()->StopAndDeAllocate();
}
}
}