Fix DesktopAndCursorComposer not to crash

DesktopAndCursorComposer was crashing when screen/window
capturer returns a NULL frame due to an error.

BUG=crbug.com/344093
R=jiayl@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/8769004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5573 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
sergeyu@chromium.org 2014-02-18 23:26:34 +00:00
parent 5cf3e8f0f0
commit e384104166
2 changed files with 37 additions and 19 deletions

View File

@ -147,7 +147,7 @@ SharedMemory* DesktopAndCursorComposer::CreateSharedMemory(size_t size) {
}
void DesktopAndCursorComposer::OnCaptureCompleted(DesktopFrame* frame) {
if (cursor_.get() && cursor_state_ == MouseCursorMonitor::INSIDE) {
if (frame && cursor_.get() && cursor_state_ == MouseCursorMonitor::INSIDE) {
DesktopFrameWithCursor* frame_with_cursor =
new DesktopFrameWithCursor(frame, *cursor_, cursor_position_);
frame = frame_with_cursor;

View File

@ -58,6 +58,18 @@ uint32_t BlendPixels(uint32_t dest, uint32_t src) {
return b + (g << 8) + (r << 16) + 0xff000000;
}
DesktopFrame* CreateTestFrame() {
DesktopFrame* frame =
new BasicDesktopFrame(DesktopSize(kScreenWidth, kScreenHeight));
uint32_t* data = reinterpret_cast<uint32_t*>(frame->data());
for (int y = 0; y < kScreenHeight; ++y) {
for (int x = 0; x < kScreenWidth; ++x) {
*(data++) = GetFakeFramePixelValue(DesktopVector(x, y));
}
}
return frame;
}
class FakeScreenCapturer : public DesktopCapturer {
public:
FakeScreenCapturer() {}
@ -67,27 +79,17 @@ class FakeScreenCapturer : public DesktopCapturer {
}
virtual void Capture(const DesktopRegion& region) OVERRIDE {
DesktopFrame* frame =
new BasicDesktopFrame(DesktopSize(kScreenWidth, kScreenHeight));
uint32_t* data = reinterpret_cast<uint32_t*>(frame->data());
for (int y = 0; y < kScreenHeight; ++y) {
for (int x = 0; x < kScreenWidth; ++x) {
*(data++) = GetFakeFramePixelValue(DesktopVector(x, y));
}
callback_->OnCaptureCompleted(next_frame_.release());
}
last_frame_.reset(SharedDesktopFrame::Wrap(frame));
callback_->OnCaptureCompleted(last_frame_->Share());
void SetNextFrame(DesktopFrame* next_frame) {
next_frame_.reset(next_frame);
}
// Returns last fake captured frame.
SharedDesktopFrame* last_frame() { return last_frame_.get(); }
private:
Callback* callback_;
scoped_ptr<SharedDesktopFrame> last_frame_;
scoped_ptr<DesktopFrame> next_frame_;
};
class FakeMouseMonitor : public MouseCursorMonitor {
@ -187,6 +189,20 @@ class DesktopAndCursorComposerTest : public testing::Test,
scoped_ptr<DesktopFrame> frame_;
};
// Verify DesktopAndCursorComposer can handle the case when the screen capturer
// fails.
TEST_F(DesktopAndCursorComposerTest, Error) {
blender_.Start(this);
fake_cursor_->SetHotspot(DesktopVector());
fake_cursor_->SetState(MouseCursorMonitor::INSIDE, DesktopVector());
fake_screen_->SetNextFrame(NULL);
blender_.Capture(DesktopRegion());
EXPECT_EQ(frame_, static_cast<DesktopFrame*>(NULL));
}
TEST_F(DesktopAndCursorComposerTest, Blend) {
struct {
int x, y;
@ -222,6 +238,10 @@ TEST_F(DesktopAndCursorComposerTest, Blend) {
DesktopVector pos(tests[i].x, tests[i].y);
fake_cursor_->SetState(state, pos);
scoped_ptr<SharedDesktopFrame> frame(
SharedDesktopFrame::Wrap(CreateTestFrame()));
fake_screen_->SetNextFrame(frame->Share());
blender_.Capture(DesktopRegion());
VerifyFrame(*frame_, state, pos);
@ -229,9 +249,7 @@ TEST_F(DesktopAndCursorComposerTest, Blend) {
// Verify that the cursor is erased before the frame buffer is returned to
// the screen capturer.
frame_.reset();
VerifyFrame(*fake_screen_->last_frame(),
MouseCursorMonitor::OUTSIDE,
DesktopVector());
VerifyFrame(*frame, MouseCursorMonitor::OUTSIDE, DesktopVector());
}
}