Fix window capturer not to leak HDC.

Previously Windows window capturer kept DC handles between captures. As
result it was leaking DC handles in SelectWindow(). Fixed it so that it
calls GetWindowDC() for each capture.

R=alexeypa@chromium.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@4834 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
sergeyu@chromium.org
2013-09-24 23:13:51 +00:00
parent 958cdf68f3
commit 8d757ac0a2

View File

@@ -102,7 +102,6 @@ class WindowCapturerWin : public WindowCapturer {
// HWND and HDC for the currently selected window or NULL if window is not
// selected.
HWND window_;
HDC window_dc_;
// dwmapi.dll is used to determine if desktop compositing is enabled.
HMODULE dwmapi_library_;
@@ -113,8 +112,7 @@ class WindowCapturerWin : public WindowCapturer {
WindowCapturerWin::WindowCapturerWin()
: callback_(NULL),
window_(NULL),
window_dc_(NULL) {
window_(NULL) {
// Try to load dwmapi.dll dynamically since it is not available on XP.
dwmapi_library_ = LoadLibrary(L"dwmapi.dll");
if (dwmapi_library_) {
@@ -149,17 +147,10 @@ bool WindowCapturerWin::GetWindowList(WindowList* windows) {
}
bool WindowCapturerWin::SelectWindow(WindowId id) {
if (window_dc_)
ReleaseDC(window_, window_dc_);
window_ = reinterpret_cast<HWND>(id);
window_dc_ = GetWindowDC(window_);
if (!window_dc_) {
LOG(LS_WARNING) << "Failed to select window: " << GetLastError();
window_ = NULL;
HWND window = reinterpret_cast<HWND>(id);
if (!IsWindow(window) || !IsWindowVisible(window) || IsIconic(window))
return false;
}
window_ = window;
return true;
}
@@ -171,7 +162,7 @@ void WindowCapturerWin::Start(Callback* callback) {
}
void WindowCapturerWin::Capture(const DesktopRegion& region) {
if (!window_dc_) {
if (!window_) {
LOG(LS_ERROR) << "Window hasn't been selected: " << GetLastError();
callback_->OnCaptureCompleted(NULL);
return;
@@ -183,8 +174,6 @@ void WindowCapturerWin::Capture(const DesktopRegion& region) {
return;
}
assert(window_);
RECT rect;
if (!GetWindowRect(window_, &rect)) {
LOG(LS_WARNING) << "Failed to get window size: " << GetLastError();
@@ -192,15 +181,23 @@ void WindowCapturerWin::Capture(const DesktopRegion& region) {
return;
}
scoped_ptr<DesktopFrameWin> frame(DesktopFrameWin::Create(
DesktopSize(rect.right - rect.left, rect.bottom - rect.top),
NULL, window_dc_));
if (!frame.get()) {
HDC window_dc = GetWindowDC(window_);
if (!window_dc) {
LOG(LS_WARNING) << "Failed to get window DC: " << GetLastError();
callback_->OnCaptureCompleted(NULL);
return;
}
HDC mem_dc = CreateCompatibleDC(window_dc_);
scoped_ptr<DesktopFrameWin> frame(DesktopFrameWin::Create(
DesktopSize(rect.right - rect.left, rect.bottom - rect.top),
NULL, window_dc));
if (!frame.get()) {
ReleaseDC(window_, window_dc);
callback_->OnCaptureCompleted(NULL);
return;
}
HDC mem_dc = CreateCompatibleDC(window_dc);
SelectObject(mem_dc, frame->bitmap());
BOOL result = FALSE;
@@ -220,16 +217,18 @@ void WindowCapturerWin::Capture(const DesktopRegion& region) {
// Aero is enabled or PrintWindow() failed, use BitBlt.
if (!result) {
result = BitBlt(mem_dc, 0, 0, frame->size().width(), frame->size().height(),
window_dc_, 0, 0, SRCCOPY);
window_dc, 0, 0, SRCCOPY);
}
DeleteDC(mem_dc);
if (!result) {
LOG(LS_ERROR) << "Both PrintWindow() and BitBlt() failed.";
frame.reset();
}
SelectObject(mem_dc, NULL);
DeleteDC(mem_dc);
ReleaseDC(window_, window_dc);
callback_->OnCaptureCompleted(frame.release());
}