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