window_capturer_win.cc revision 12dc1a38ca54a000e4fecfbc6d41138b895c9ca5
1b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org/*
2b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org *
4b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org *  Use of this source code is governed by a BSD-style license
5b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org *  that can be found in the LICENSE file in the root of the source
6b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org *  tree. An additional intellectual property rights grant can be found
7b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org *  in the file PATENTS.  All contributing project authors may
8b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org *  be found in the AUTHORS file in the root of the source tree.
9b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org */
10b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
11b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org#include "webrtc/modules/desktop_capture/window_capturer.h"
12b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
1312dc1a38ca54a000e4fecfbc6d41138b895c9ca5pbos@webrtc.org#include <assert.h>
14b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org#include <windows.h>
15b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
16b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org#include "webrtc/modules/desktop_capture/desktop_frame_win.h"
17b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org#include "webrtc/system_wrappers/interface/logging.h"
18b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org#include "webrtc/system_wrappers/interface/scoped_ptr.h"
19b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
20b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgnamespace webrtc {
21b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
22b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgnamespace {
23b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
24b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgtypedef HRESULT (WINAPI *DwmIsCompositionEnabledFunc)(BOOL* enabled);
25b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
26b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org// Coverts a zero-terminated UTF-16 string to UTF-8. Returns an empty string if
27b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org// error occurs.
28b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgstd::string Utf16ToUtf8(const WCHAR* str) {
29b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  int len_utf8 = WideCharToMultiByte(CP_UTF8, 0, str, -1,
30b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org                                     NULL, 0, NULL, NULL);
31b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  if (len_utf8 <= 0)
32b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    return std::string();
33b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  std::string result(len_utf8, '\0');
34b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  int rv = WideCharToMultiByte(CP_UTF8, 0, str, -1,
35b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org                               &*(result.begin()), len_utf8, NULL, NULL);
36b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  if (rv != len_utf8)
37b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    assert(false);
38b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
39b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  return result;
40b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org}
41b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
42b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgBOOL CALLBACK WindowsEnumerationHandler(HWND hwnd, LPARAM param) {
43b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  WindowCapturer::WindowList* list =
44b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org      reinterpret_cast<WindowCapturer::WindowList*>(param);
45b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
46b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // Skip windows that are invisible, minimized, have no title, or are owned,
47b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // unless they have the app window style set.
48b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  int len = GetWindowTextLength(hwnd);
49b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  HWND owner = GetWindow(hwnd, GW_OWNER);
50b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
51b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  if (len == 0 || IsIconic(hwnd) || !IsWindowVisible(hwnd) ||
52b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org      (owner && !(exstyle & WS_EX_APPWINDOW))) {
53b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    return TRUE;
54b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  }
55b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
56b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // Skip the Program Manager window and the Start button.
57b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  const size_t kClassLength = 256;
58b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  WCHAR class_name[kClassLength];
59b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  GetClassName(hwnd, class_name, kClassLength);
60b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // Skip Program Manager window and the Start button. This is the same logic
61b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // that's used in Win32WindowPicker in libjingle. Consider filtering other
62b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // windows as well (e.g. toolbars).
63b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  if (wcscmp(class_name, L"Progman") == 0 || wcscmp(class_name, L"Button") == 0)
64b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    return TRUE;
65b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
66b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  WindowCapturer::Window window;
67a590b41c9ae8a41391a0556ae7d2aedbae7d3c38sergeyu@chromium.org  window.id = reinterpret_cast<WindowCapturer::WindowId>(hwnd);
68b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
69b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  const size_t kTitleLength = 500;
70b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  WCHAR window_title[kTitleLength];
71b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // Truncate the title if it's longer than kTitleLength.
72b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  GetWindowText(hwnd, window_title, kTitleLength);
73b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  window.title = Utf16ToUtf8(window_title);
74b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
75b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // Skip windows when we failed to convert the title or it is empty.
76b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  if (window.title.empty())
77b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    return TRUE;
78b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
79b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  list->push_back(window);
80b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
81b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  return TRUE;
82b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org}
83b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
84b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgclass WindowCapturerWin : public WindowCapturer {
85b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org public:
86b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  WindowCapturerWin();
87b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  virtual ~WindowCapturerWin();
88b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
89b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // WindowCapturer interface.
90b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  virtual bool GetWindowList(WindowList* windows) OVERRIDE;
91b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  virtual bool SelectWindow(WindowId id) OVERRIDE;
92b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
93b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // DesktopCapturer interface.
94b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  virtual void Start(Callback* callback) OVERRIDE;
95b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  virtual void Capture(const DesktopRegion& region) OVERRIDE;
96b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
97b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org private:
98b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  bool IsAeroEnabled();
99b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
100b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  Callback* callback_;
101b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
102b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // HWND and HDC for the currently selected window or NULL if window is not
103b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // selected.
104b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  HWND window_;
105b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  HDC window_dc_;
106b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
107b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // dwmapi.dll is used to determine if desktop compositing is enabled.
108b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  HMODULE dwmapi_library_;
109b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  DwmIsCompositionEnabledFunc is_composition_enabled_func_;
110b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
111b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  DISALLOW_COPY_AND_ASSIGN(WindowCapturerWin);
112b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org};
113b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
114b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgWindowCapturerWin::WindowCapturerWin()
115b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    : callback_(NULL),
116b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org      window_(NULL),
117b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org      window_dc_(NULL) {
118b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // Try to load dwmapi.dll dynamically since it is not available on XP.
119b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  dwmapi_library_ = LoadLibrary(L"dwmapi.dll");
120b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  if (dwmapi_library_) {
121b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    is_composition_enabled_func_ =
122b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org        reinterpret_cast<DwmIsCompositionEnabledFunc>(
123b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org            GetProcAddress(dwmapi_library_, "DwmIsCompositionEnabled"));
124b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    assert(is_composition_enabled_func_);
125b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  } else {
126b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    is_composition_enabled_func_ = NULL;
127b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  }
128b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org}
129b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
130b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgWindowCapturerWin::~WindowCapturerWin() {
131b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  if (dwmapi_library_)
132b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    FreeLibrary(dwmapi_library_);
133b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org}
134b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
135b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgbool WindowCapturerWin::IsAeroEnabled() {
136b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  BOOL result = FALSE;
137b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  if (is_composition_enabled_func_)
138b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    is_composition_enabled_func_(&result);
139b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  return result != FALSE;
140b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org}
141b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
142b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgbool WindowCapturerWin::GetWindowList(WindowList* windows) {
143b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  WindowList result;
144b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  LPARAM param = reinterpret_cast<LPARAM>(&result);
145b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  if (!EnumWindows(&WindowsEnumerationHandler, param))
146b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    return false;
147b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  windows->swap(result);
148b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  return true;
149b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org}
150b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
151b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgbool WindowCapturerWin::SelectWindow(WindowId id) {
152b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  if (window_dc_)
153b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    ReleaseDC(window_, window_dc_);
154b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
155b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  window_ = reinterpret_cast<HWND>(id);
156b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  window_dc_ = GetWindowDC(window_);
157b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  if (!window_dc_) {
158b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    LOG(LS_WARNING) << "Failed to select window: " << GetLastError();
159b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    window_ = NULL;
160b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    return false;
161b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  }
162b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
163b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  return true;
164b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org}
165b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
166b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgvoid WindowCapturerWin::Start(Callback* callback) {
167b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  assert(!callback_);
168b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  assert(callback);
169b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
170b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  callback_ = callback;
171b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org}
172b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
173b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgvoid WindowCapturerWin::Capture(const DesktopRegion& region) {
174b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  if (!window_dc_) {
175b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    LOG(LS_ERROR) << "Window hasn't been selected: " << GetLastError();
176b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    callback_->OnCaptureCompleted(NULL);
177b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    return;
178b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  }
179b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
180b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  assert(window_);
181b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
182b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  RECT rect;
183b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  if (!GetWindowRect(window_, &rect)) {
184b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    LOG(LS_WARNING) << "Failed to get window size: " << GetLastError();
185b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    callback_->OnCaptureCompleted(NULL);
186b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    return;
187b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  }
188b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
189b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  scoped_ptr<DesktopFrameWin> frame(DesktopFrameWin::Create(
190b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org      DesktopSize(rect.right - rect.left, rect.bottom - rect.top),
191b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org      NULL, window_dc_));
192b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
193b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  HDC mem_dc = CreateCompatibleDC(window_dc_);
194b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  SelectObject(mem_dc, frame->bitmap());
195b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  BOOL result = FALSE;
196b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
197b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // When desktop composition (Aero) is enabled each window is rendered to a
198b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // private buffer allowing BitBlt() to get the window content even if the
199b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // window is occluded. PrintWindow() is slower but lets rendering the window
200b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // contents to an off-screen device context when Aero is not available.
201b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // PrintWindow() is not supported by some applications.
202b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
203b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // If Aero is enabled, we prefer BitBlt() because it's faster and avoids
204b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // window flickering. Otherwise, we prefer PrintWindow() because BitBlt() may
205b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // render occluding windows on top of the desired window.
206b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
207b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  if (!IsAeroEnabled())
208b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    result = PrintWindow(window_, mem_dc, 0);
209b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
210b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  // Aero is enabled or PrintWindow() failed, use BitBlt.
211b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  if (!result) {
212b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    result = BitBlt(mem_dc, 0, 0, frame->size().width(), frame->size().height(),
213b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org                    window_dc_, 0, 0, SRCCOPY);
214b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  }
215b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
216b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  DeleteDC(mem_dc);
217b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
218b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  if (!result) {
219b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    LOG(LS_ERROR) << "Both PrintWindow() and BitBlt() failed.";
220b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org    frame.reset();
221b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  }
222b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
223b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  callback_->OnCaptureCompleted(frame.release());
224b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org}
225b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
226b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org}  // namespace
227b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
228b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org// static
229b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.orgWindowCapturer* WindowCapturer::Create() {
230b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org  return new WindowCapturerWin();
231b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org}
232b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org
233b10ccbec02db00fc17397afb72a115072590d391sergeyu@chromium.org}  // namespace webrtc
234