Backed out changeset a5723795cd1f (bug 1036653)

This commit is contained in:
Carsten "Tomcat" Book 2014-08-27 09:20:37 +02:00
parent d716c30b2f
commit c4623a42c6
6 changed files with 47 additions and 463 deletions

View File

@ -7,16 +7,11 @@
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/modules/desktop_capture/window_capturer.h"
#include "webrtc/modules/desktop_capture/app_capturer.h"
#include "webrtc/modules/desktop_capture/screen_capturer.h"
#include "webrtc/modules/desktop_capture/shared_desktop_frame.h"
#include "webrtc/modules/desktop_capture/win/win_shared.h"
#include <assert.h>
#include <windows.h>
#include <vector>
#include <cassert>
#include "webrtc/modules/desktop_capture/desktop_frame_win.h"
#include "webrtc/system_wrappers/interface/logging.h"
@ -26,130 +21,59 @@ namespace webrtc {
namespace {
// Proxy over the WebRTC window capturer, to allow post-processing
// of the frame to merge multiple window capture frames into a single frame
class WindowsCapturerProxy : DesktopCapturer::Callback {
public:
WindowsCapturerProxy() :
window_capturer_(WindowCapturer::Create()) {
window_capturer_->Start(this);
}
~WindowsCapturerProxy(){}
std::string Utf16ToUtf8(const WCHAR* str) {
int len_utf8 = WideCharToMultiByte(CP_UTF8, 0, str, -1,
NULL, 0, NULL, NULL);
if (len_utf8 <= 0)
return std::string();
std::string result(len_utf8, '\0');
int rv = WideCharToMultiByte(CP_UTF8, 0, str, -1,
&*(result.begin()), len_utf8, NULL, NULL);
if (rv != len_utf8)
assert(false);
void SelectWindow(HWND hwnd) { window_capturer_->SelectWindow(reinterpret_cast<WindowId>(hwnd)); }
scoped_ptr<DesktopFrame>& GetFrame() { return frame_; }
void Capture(const DesktopRegion& region) { window_capturer_->Capture(region); }
return result;
}
// Callback interface
virtual SharedMemory *CreateSharedMemory(size_t) OVERRIDE { return NULL; }
virtual void OnCaptureCompleted(DesktopFrame *frame) OVERRIDE { frame_.reset(frame); }
private:
scoped_ptr<WindowCapturer> window_capturer_;
scoped_ptr<DesktopFrame> frame_;
};
// Proxy over the WebRTC screen capturer, to allow post-processing
// of the frame to mask out non-application windows
class ScreenCapturerProxy : DesktopCapturer::Callback {
public:
ScreenCapturerProxy(const DesktopCaptureOptions& options) :
screen_capturer_(ScreenCapturer::Create(options)) {
screen_capturer_->SelectScreen(kFullDesktopScreenId);
screen_capturer_->Start(this);
}
void Capture(const DesktopRegion& region) { screen_capturer_->Capture(region); }
scoped_ptr<DesktopFrame>& GetFrame() { return frame_; }
// Callback interface
virtual SharedMemory *CreateSharedMemory(size_t) OVERRIDE { return NULL; }
virtual void OnCaptureCompleted(DesktopFrame *frame) OVERRIDE { frame_.reset(frame); }
protected:
scoped_ptr<ScreenCapturer> screen_capturer_;
scoped_ptr<DesktopFrame> frame_;
};
class AppCapturerWin : public AppCapturer {
public:
AppCapturerWin(const DesktopCaptureOptions& options);
AppCapturerWin();
virtual ~AppCapturerWin();
// AppCapturer interface.
virtual bool GetAppList(AppList* apps) OVERRIDE;
virtual bool SelectApp(ProcessId processId) OVERRIDE;
virtual bool SelectApp(ProcessId id) OVERRIDE;
virtual bool BringAppToFront() OVERRIDE;
// DesktopCapturer interface.
virtual void Start(Callback* callback) OVERRIDE;
virtual void Capture(const DesktopRegion& region) OVERRIDE;
struct WindowItem {
HWND handle;
RECT bounds;
bool owned;
};
struct EnumWindowsCtx {
ProcessId process_id;
std::vector<WindowItem> windows;
bool list_all;
};
static BOOL CALLBACK EnumWindowsProc(HWND handle, LPARAM lParam);
protected:
void CaptureByWebRTC(const DesktopRegion& region);
void CaptureBySample(const DesktopRegion& region);
private:
Callback* callback_;
ProcessId processId_;
// Sample Mode
ScreenCapturerProxy screen_capturer_proxy_;
// Mask of foreground (non-app windows in front of selected)
HRGN hrgn_foreground_;
// Mask of background (desktop, non-app windows behind selected)
HRGN hrgn_background_;
// Region of selected windows
HRGN hrgn_visual_;
void UpdateRegions();
// WebRTC Window mode
WindowsCapturerProxy window_capturer_proxy_;
DISALLOW_COPY_AND_ASSIGN(AppCapturerWin);
};
AppCapturerWin::AppCapturerWin(const DesktopCaptureOptions& options)
AppCapturerWin::AppCapturerWin()
: callback_(NULL),
screen_capturer_proxy_(options),
processId_(NULL) {
// Initialize regions to zero
hrgn_foreground_ = CreateRectRgn(0, 0, 0, 0);
hrgn_background_ = CreateRectRgn(0, 0, 0, 0);
hrgn_visual_ = CreateRectRgn(0, 0, 0, 0);
}
AppCapturerWin::~AppCapturerWin() {
if (hrgn_foreground_) {
DeleteObject(hrgn_foreground_);
}
if (hrgn_background_) {
DeleteObject(hrgn_background_);
}
if (hrgn_visual_) {
DeleteObject(hrgn_visual_);
}
}
// AppCapturer interface.
bool AppCapturerWin::GetAppList(AppList* apps){
// Implemented via DesktopDeviceInfo
// Not implemented yet: See Bug 1036653
return true;
}
bool AppCapturerWin::SelectApp(ProcessId processId) {
processId_ = processId;
bool AppCapturerWin::SelectApp(ProcessId id) {
// Not implemented yet: See Bug 1036653
return true;
}
@ -166,251 +90,14 @@ void AppCapturerWin::Start(Callback* callback) {
callback_ = callback;
}
void AppCapturerWin::Capture(const DesktopRegion& region) {
CaptureBySample(region);
}
BOOL CALLBACK AppCapturerWin::EnumWindowsProc(HWND handle, LPARAM lParam) {
EnumWindowsCtx *pEnumWindowsCtx = reinterpret_cast<EnumWindowsCtx *>(lParam);
if (!pEnumWindowsCtx) {
return FALSE;
}
DWORD procId = -1;
GetWindowThreadProcessId(handle, &procId);
if (procId == pEnumWindowsCtx->process_id || pEnumWindowsCtx->list_all) {
WindowItem window_item;
window_item.handle = handle;
if (!IsWindowVisible(handle) || IsIconic(handle)) {
return TRUE;
}
GetWindowRect(handle, &window_item.bounds);
window_item.owned = (procId == pEnumWindowsCtx->process_id);
pEnumWindowsCtx->windows.push_back(window_item);
}
return TRUE;
}
void AppCapturerWin::CaptureByWebRTC(const DesktopRegion& region) {
// List Windows of selected application
EnumWindowsCtx lParamEnumWindows;
lParamEnumWindows.process_id = processId_;
lParamEnumWindows.list_all = false;
EnumWindows(EnumWindowsProc, (LPARAM)&lParamEnumWindows);
// Prepare capture dc context
// TODO: handle multi-monitor setups; see Bug 1037997
DesktopRect rcDesktop(DesktopRect::MakeXYWH(
GetSystemMetrics(SM_XVIRTUALSCREEN),
GetSystemMetrics(SM_YVIRTUALSCREEN),
GetSystemMetrics(SM_CXVIRTUALSCREEN),
GetSystemMetrics(SM_CYVIRTUALSCREEN)
));
HDC dcScreen = GetDC(NULL);
HDC memDcCapture = CreateCompatibleDC(dcScreen);
if (dcScreen) {
ReleaseDC(NULL, dcScreen);
}
scoped_ptr<DesktopFrameWin> frameCapture(DesktopFrameWin::Create(
DesktopSize(rcDesktop.width(), rcDesktop.height()),
NULL, memDcCapture));
HBITMAP bmpOrigin = static_cast<HBITMAP>(SelectObject(memDcCapture, frameCapture->bitmap()));
BOOL bCaptureAppResult = false;
// Capture and Combine all windows into memDcCapture
std::vector<WindowItem>::reverse_iterator itItem;
for (itItem = lParamEnumWindows.windows.rbegin(); itItem != lParamEnumWindows.windows.rend(); itItem++) {
WindowItem window_item = *itItem;
HWND hWndCapturer = window_item.handle;
if (!IsWindow(hWndCapturer) || !IsWindowVisible(hWndCapturer) || IsIconic(hWndCapturer)) {
continue;
}
HDC memDcWin = NULL;
HBITMAP bmpOriginWin = NULL;
HBITMAP hBitmapFrame = NULL;
HDC dcWin = NULL;
RECT rcWin = window_item.bounds;
bool bCaptureResult = false;
scoped_ptr<DesktopFrameWin> frame;
do {
if (rcWin.left == rcWin.right || rcWin.top == rcWin.bottom) {
break;
}
dcWin = GetWindowDC(hWndCapturer);
if (!dcWin) {
break;
}
memDcWin = CreateCompatibleDC(dcWin);
// Capture
window_capturer_proxy_.SelectWindow(hWndCapturer);
window_capturer_proxy_.Capture(region);
if (window_capturer_proxy_.GetFrame() != NULL) {
DesktopFrameWin *pDesktopFrameWin = reinterpret_cast<DesktopFrameWin *>(
window_capturer_proxy_.GetFrame().get());
if (pDesktopFrameWin) {
hBitmapFrame = pDesktopFrameWin->bitmap();
}
if (GetObjectType(hBitmapFrame) != OBJ_BITMAP) {
hBitmapFrame = NULL;
}
}
if (!hBitmapFrame) {
break;
}
bmpOriginWin = static_cast<HBITMAP>(SelectObject(memDcWin, hBitmapFrame));
} while(0);
// bitblt to capture memDcCapture
if (bmpOriginWin) {
BitBlt(memDcCapture,
rcWin.left, rcWin.top, rcWin.right - rcWin.left, rcWin.bottom - rcWin.top,
memDcWin, 0, 0, SRCCOPY);
bCaptureAppResult = true;
}
// Clean resource
if (memDcWin) {
SelectObject(memDcWin, bmpOriginWin);
DeleteDC(memDcWin);
}
if (dcWin) {
ReleaseDC(hWndCapturer, dcWin);
}
}
// Clean resource
if (memDcCapture) {
SelectObject(memDcCapture, bmpOrigin);
DeleteDC(memDcCapture);
}
// trigger event
if (bCaptureAppResult) {
callback_->OnCaptureCompleted(frameCapture.release());
}
}
// Application Capturer by sample and region
void AppCapturerWin::CaptureBySample(const DesktopRegion& region){
// capture entire screen
screen_capturer_proxy_.Capture(region);
HBITMAP hBitmapFrame = NULL;
if (screen_capturer_proxy_.GetFrame() != NULL) {
SharedDesktopFrame* pSharedDesktopFrame = reinterpret_cast<SharedDesktopFrame*>(
screen_capturer_proxy_.GetFrame().get());
if (pSharedDesktopFrame) {
DesktopFrameWin *pDesktopFrameWin =reinterpret_cast<DesktopFrameWin *>(
pSharedDesktopFrame->GetUnderlyingFrame());
if (pDesktopFrameWin) {
hBitmapFrame = pDesktopFrameWin->bitmap();
}
if (GetObjectType(hBitmapFrame) != OBJ_BITMAP) {
hBitmapFrame = NULL;
}
}
}
if (hBitmapFrame) {
// calculate app visual/foreground region
UpdateRegions();
HDC dcScreen = GetDC(NULL);
HDC memDcCapture = CreateCompatibleDC(dcScreen);
RECT rcScreen = {0, 0,
screen_capturer_proxy_.GetFrame()->size().width(),
screen_capturer_proxy_.GetFrame()->size().height()
};
HBITMAP bmpOriginCapture = (HBITMAP)SelectObject(memDcCapture, hBitmapFrame);
// TODO: background/foreground mask colors should be configurable; see Bug 1054503
// fill background
SelectClipRgn(memDcCapture, hrgn_background_);
SelectObject(memDcCapture, GetStockObject(DC_BRUSH));
SetDCBrushColor(memDcCapture, RGB(0, 0, 0));
FillRect(memDcCapture, &rcScreen, (HBRUSH)GetStockObject(DC_BRUSH));
// fill foreground
SelectClipRgn(memDcCapture, hrgn_foreground_);
SelectObject(memDcCapture, GetStockObject(DC_BRUSH));
SetDCBrushColor(memDcCapture, RGB(0xff, 0xff, 0));
FillRect(memDcCapture, &rcScreen, (HBRUSH)GetStockObject(DC_BRUSH));
if (dcScreen) {
ReleaseDC(NULL, dcScreen);
}
SelectObject(memDcCapture, bmpOriginCapture);
DeleteDC(memDcCapture);
}
// trigger event
if (callback_) {
callback_->OnCaptureCompleted(screen_capturer_proxy_.GetFrame().release());
}
}
void AppCapturerWin::UpdateRegions() {
// List Windows of selected application
EnumWindowsCtx lParamEnumWindows;
lParamEnumWindows.process_id = processId_;
lParamEnumWindows.list_all = true;
EnumWindows(EnumWindowsProc, (LPARAM)&lParamEnumWindows);
SetRectRgn(hrgn_foreground_, 0, 0, 0, 0);
SetRectRgn(hrgn_visual_, 0, 0, 0, 0);
SetRectRgn(hrgn_background_, 0, 0, 0, 0);
HRGN hrgn_screen_ = CreateRectRgn(0, 0,
GetSystemMetrics(SM_CXVIRTUALSCREEN),
GetSystemMetrics(SM_CYVIRTUALSCREEN));
HRGN hrgn_window = CreateRectRgn(0, 0, 0, 0);
HRGN hrgn_internsect = CreateRectRgn(0, 0, 0, 0);
std::vector<WindowItem>::reverse_iterator itItem;
for (itItem = lParamEnumWindows.windows.rbegin(); itItem != lParamEnumWindows.windows.rend(); itItem++) {
WindowItem window_item = *itItem;
SetRectRgn(hrgn_window, 0, 0, 0, 0);
if (GetWindowRgn(window_item.handle, hrgn_window) == ERROR) {
SetRectRgn(hrgn_window, window_item.bounds.left,
window_item.bounds.top,
window_item.bounds.right,
window_item.bounds.bottom);
}
if (window_item.owned) {
CombineRgn(hrgn_visual_, hrgn_visual_, hrgn_window, RGN_OR);
CombineRgn(hrgn_foreground_, hrgn_foreground_, hrgn_window, RGN_DIFF);
} else {
SetRectRgn(hrgn_internsect, 0, 0, 0, 0);
CombineRgn(hrgn_internsect, hrgn_visual_, hrgn_window, RGN_AND);
CombineRgn(hrgn_visual_, hrgn_visual_, hrgn_internsect, RGN_DIFF);
CombineRgn(hrgn_foreground_, hrgn_foreground_, hrgn_internsect, RGN_OR);
}
}
CombineRgn(hrgn_background_, hrgn_screen_, hrgn_visual_, RGN_DIFF);
if (hrgn_window) {
DeleteObject(hrgn_window);
}
if (hrgn_internsect) {
DeleteObject(hrgn_internsect);
}
// Not implemented yet: See Bug 1036653
}
} // namespace
// static
AppCapturer* AppCapturer::Create(const DesktopCaptureOptions& options) {
return new AppCapturerWin(options);
return new AppCapturerWin();
}
} // namespace webrtc

View File

@ -149,8 +149,6 @@
"win/scoped_gdi_object.h",
"win/scoped_thread_desktop.cc",
"win/scoped_thread_desktop.h",
"win/win_shared.h",
"win/win_shared.cc",
"win/desktop_device_info_win.h",
"win/desktop_device_info_win.cc",
"window_capturer_win.cc",

View File

@ -3,18 +3,8 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "webrtc/modules/desktop_capture/win/desktop_device_info_win.h"
#include "webrtc/modules/desktop_capture/win/win_shared.h"
#include <stdio.h>
// Duplicating declaration so that it always resolves in decltype use
// typedef BOOL (WINAPI *QueryFullProcessImageNameProc)(HANDLE hProcess, DWORD dwFlags, LPTSTR lpExeName, PDWORD lpdwSize);
BOOL WINAPI QueryFullProcessImageName(HANDLE hProcess, DWORD dwFlags, LPTSTR lpExeName, PDWORD lpdwSize);
// Duplicating declaration so that it always resolves in decltype use
// typedoef DWORD (WINAPI *GetProcessImageFileNameProc)(HANDLE hProcess, LPTSTR lpImageFileName, DWORD nSize);
DWORD WINAPI GetProcessImageFileName(HANDLE hProcess, LPTSTR lpImageFileName, DWORD nSize);
namespace webrtc {
namespace webrtc{
DesktopDeviceInfo * DesktopDeviceInfoImpl::Create() {
DesktopDeviceInfoWin * pDesktopDeviceInfo = new DesktopDeviceInfoWin();
@ -32,7 +22,7 @@ DesktopDeviceInfoWin::~DesktopDeviceInfoWin() {
}
#if !defined(MULTI_MONITOR_SCREENSHARE)
void DesktopDeviceInfoWin::MultiMonitorScreenshare()
int32_t DesktopDeviceInfoWin::MultiMonitorScreenshare()
{
DesktopDisplayDevice *pDesktopDeviceInfo = new DesktopDisplayDevice;
if (pDesktopDeviceInfo) {
@ -42,86 +32,35 @@ void DesktopDeviceInfoWin::MultiMonitorScreenshare()
desktop_display_list_[pDesktopDeviceInfo->getScreenId()] = pDesktopDeviceInfo;
}
return 0;
}
#endif
void DesktopDeviceInfoWin::InitializeScreenList() {
int32_t DesktopDeviceInfoWin::Init() {
#if !defined(MULTI_MONITOR_SCREENSHARE)
MultiMonitorScreenshare();
#endif
initializeWindowList();
return 0;
}
void DesktopDeviceInfoWin::InitializeApplicationList() {
// List all running applications exclude background process.
HWND hWnd;
for (hWnd = GetWindow(GetDesktopWindow(), GW_CHILD); hWnd; hWnd = GetWindow(hWnd, GW_HWNDNEXT)) {
if (!IsWindowVisible(hWnd))
continue;
DWORD dwProcessId = 0;
GetWindowThreadProcessId(hWnd, &dwProcessId);
// filter out non-process, current process, or any already seen processes
if (dwProcessId == 0 || dwProcessId == GetCurrentProcessId() ||
desktop_application_list_.find(dwProcessId) != desktop_application_list_.end()) {
continue;
}
// Add one application
DesktopApplication *pDesktopApplication = new DesktopApplication;
if (!pDesktopApplication) {
continue;
}
// process id
pDesktopApplication->setProcessId(dwProcessId);
// process path name
WCHAR szFilePathName[MAX_PATH]={0};
decltype(QueryFullProcessImageName) *lpfnQueryFullProcessImageNameProc =
reinterpret_cast<decltype(QueryFullProcessImageName) *>(GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "QueryFullProcessImageNameW"));
if (lpfnQueryFullProcessImageNameProc) {
// After Vista
DWORD dwMaxSize = _MAX_PATH;
HANDLE hWndPro = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, dwProcessId);
if(hWndPro) {
lpfnQueryFullProcessImageNameProc(hWndPro, 0, szFilePathName, &dwMaxSize);
CloseHandle(hWndPro);
}
} else {
HMODULE hModPSAPI = LoadLibrary(TEXT("PSAPI.dll"));
if (hModPSAPI) {
decltype(GetProcessImageFileName) *pfnGetProcessImageFileName =
reinterpret_cast<decltype(GetProcessImageFileName) *>(GetProcAddress(hModPSAPI, "GetProcessImageFileNameW"));
if (pfnGetProcessImageFileName) {
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, 0, dwProcessId);
if (hProcess) {
DWORD dwMaxSize = _MAX_PATH;
pfnGetProcessImageFileName(hProcess, szFilePathName, dwMaxSize);
CloseHandle(hProcess);
}
}
FreeLibrary(hModPSAPI);
}
}
pDesktopApplication->setProcessPathName(Utf16ToUtf8(szFilePathName).c_str());
// application name
WCHAR szWndTitle[_MAX_PATH]={0};
GetWindowText(hWnd, szWndTitle, MAX_PATH);
if (lstrlen(szWndTitle) <= 0) {
pDesktopApplication->setProcessAppName(Utf16ToUtf8(szFilePathName).c_str());
} else {
pDesktopApplication->setProcessAppName(Utf16ToUtf8(szWndTitle).c_str());
}
// unique id name
char idStr[64];
_snprintf_s(idStr, sizeof(idStr), sizeof(idStr) - 1, "%ld", pDesktopApplication->getProcessId());
pDesktopApplication->setUniqueIdName(idStr);
desktop_application_list_[pDesktopApplication->getProcessId()] = pDesktopApplication;
int32_t DesktopDeviceInfoWin::Refresh() {
#if !defined(MULTI_MONITOR_SCREENSHARE)
std::map<intptr_t,DesktopDisplayDevice*>::iterator iterDevice;
for (iterDevice=desktop_display_list_.begin(); iterDevice!=desktop_display_list_.end(); iterDevice++){
DesktopDisplayDevice * pDesktopDisplayDevice = iterDevice->second;
delete pDesktopDisplayDevice;
iterDevice->second = NULL;
}
desktop_display_list_.clear();
MultiMonitorScreenshare();
#endif
RefreshWindowList();
return 0;
}
} // namespace webrtc
} //namespace webrtc

View File

@ -15,14 +15,13 @@ public:
DesktopDeviceInfoWin();
~DesktopDeviceInfoWin();
protected:
//DesktopDeviceInfo Interfaces
virtual void InitializeApplicationList() OVERRIDE;
virtual void InitializeScreenList() OVERRIDE;
virtual int32_t Init();
virtual int32_t Refresh();
private:
#if !defined(MULTI_MONITOR_SCREENSHARE)
void MultiMonitorScreenshare();
int32_t MultiMonitorScreenshare();
#endif
};

View File

@ -1,27 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <windows.h>
#include "webrtc/modules/desktop_capture/win/win_shared.h"
namespace webrtc {
std::string Utf16ToUtf8(const WCHAR* str) {
int len_utf8 = WideCharToMultiByte(CP_UTF8, 0, str, -1,
NULL, 0, NULL, NULL);
if (len_utf8 <= 0) {
return std::string();
}
std::string result(len_utf8, '\0');
int rv = WideCharToMultiByte(CP_UTF8, 0, str, -1,
&*(result.begin()), len_utf8,
NULL, NULL);
if (rv != len_utf8) {
assert(false);
}
return result;
}
};

View File

@ -1,12 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <windows.h>
#include <string>
namespace webrtc {
std::string Utf16ToUtf8(const WCHAR* str);
};