fixed issues with game capture not acquiring

master
jp9000 2012-12-10 06:29:02 -07:00
parent 9f3f3c579c
commit 0fb0ce81f6
17 changed files with 381 additions and 296 deletions

View File

@ -20,17 +20,34 @@
#pragma once
#define RECEIVER_WINDOWCLASS TEXT("OBSGraphicsCaptureReceiver")
#define SENDER_WINDOWCLASS TEXT("OBSGraphicsCaptureSender")
#define OBS_WINDOW_CLASS TEXT("OBSWindowClass")
//events sent by receiver (OBS)
#define RESTART_CAPTURE_EVENT TEXT("OBS_RestartCapture")
#define END_CAPTURE_EVENT TEXT("OBS_EndCapture")
//events sent by sender (graphics app)
#define CAPTURE_READY_EVENT TEXT("OBS_CaptureReady")
#define APP_EXIT_EVENT TEXT("OBS_AppExit")
#define TEXTURE_MUTEX1 TEXT("OBSTextureMutex1")
#define TEXTURE_MUTEX2 TEXT("OBSTextureMutex2")
#define INFO_MEMORY TEXT("Local\\OBSInfoMemory")
#define TEXTURE_MEMORY TEXT("Local\\OBSTextureMemory")
#define CAPTURETYPE_MEMORY 1
#define CAPTURETYPE_SHAREDTEX 2
inline HANDLE GetEvent(LPCTSTR lpEvent)
{
HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, lpEvent);
if(!hEvent)
hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, lpEvent);
return hEvent;
}
struct MemoryCopyData
{
UINT lastRendered;
@ -50,7 +67,6 @@ struct CaptureInfo
UINT captureType;
DWORD format;
UINT cx, cy;
HWND hwndSender;
HWND hwndCapture;
BOOL bFlip;
@ -58,16 +74,3 @@ struct CaptureInfo
UINT mapID;
DWORD mapSize;
};
enum
{
RECEIVER_NEWCAPTURE=WM_USER+1,
RECEIVER_ENDCAPTURE,
};
enum
{
SENDER_RESTARTCAPTURE=WM_USER+1,
SENDER_ENDCAPTURE,
};

View File

@ -363,19 +363,6 @@ ImageSource* STDCALL CreateGraphicsCaptureSource(XElement *data)
bool LoadPlugin()
{
WNDCLASS wc;
zero(&wc, sizeof(wc));
wc.hInstance = hinstMain;
wc.cbWndExtra = sizeof(LPVOID);
wc.lpszClassName = RECEIVER_WINDOWCLASS;
wc.lpfnWndProc = (WNDPROC)GraphicsCaptureSource::ReceiverWindowProc;
if(!RegisterClass(&wc))
{
AppWarning(TEXT("Could not register window class for graphics plugin"));
return false;
}
textureMutexes[0] = CreateMutex(NULL, NULL, TEXTURE_MUTEX1);
if(!textureMutexes[0])
{

View File

@ -35,7 +35,7 @@ class GraphicsCaptureMethod
{
public:
virtual ~GraphicsCaptureMethod() {}
virtual bool Init(HANDLE hProcess, HWND hwndTarget, CaptureInfo &info)=0;
virtual bool Init(CaptureInfo &info)=0;
virtual void Destroy()=0;
virtual Texture* LockTexture()=0;

View File

@ -338,46 +338,46 @@ HRESULT STDMETHODCALLTYPE D3D101SwapPresentHook(IDXGISwapChain *swap, UINT syncI
if(bCapturing && bStopRequested)
{
ClearD3D101Data();
bCapturing = false;
bStopRequested = false;
}
if(!bCapturing && WaitForSingleObject(hSignalRestart, 0) == WAIT_OBJECT_0)
{
hwndOBS = FindWindow(OBS_WINDOW_CLASS, NULL);
if(hwndOBS)
bCapturing = true;
}
if(!bHasTextures && bCapturing)
{
if(dxgiFormat)
if(dxgiFormat && hwndOBS)
{
if(!hwndReceiver)
hwndReceiver = FindWindow(RECEIVER_WINDOWCLASS, NULL);
BOOL bSuccess = DoD3D101Hook(device);
if(hwndReceiver)
if(bSuccess)
{
BOOL bSuccess = DoD3D101Hook(device);
d3d101CaptureInfo.mapID = InitializeSharedMemoryGPUCapture(&texData);
if(!d3d101CaptureInfo.mapID)
bSuccess = false;
}
if(bSuccess)
{
d3d101CaptureInfo.mapID = InitializeSharedMemoryGPUCapture(&texData);
if(!d3d101CaptureInfo.mapID)
bSuccess = false;
}
if(bSuccess)
{
bHasTextures = true;
d3d101CaptureInfo.captureType = CAPTURETYPE_SHAREDTEX;
d3d101CaptureInfo.bFlip = FALSE;
texData->texHandles[0] = sharedHandles[0];
texData->texHandles[1] = sharedHandles[1];
if(bSuccess)
bSuccess = IsWindow(hwndReceiver);
memcpy(infoMem, &d3d101CaptureInfo, sizeof(CaptureInfo));
SetEvent(hSignalReady);
if(bSuccess)
{
bHasTextures = true;
d3d101CaptureInfo.captureType = CAPTURETYPE_SHAREDTEX;
d3d101CaptureInfo.hwndSender = hwndSender;
d3d101CaptureInfo.bFlip = FALSE;
texData->texHandles[0] = sharedHandles[0];
texData->texHandles[1] = sharedHandles[1];
PostMessage(hwndReceiver, RECEIVER_NEWCAPTURE, 0, (LPARAM)&d3d101CaptureInfo);
logOutput << "DoD3D101Hook: success";
}
else
{
ClearD3D101Data();
}
logOutput << "DoD3D101Hook: success";
}
else
{
ClearD3D101Data();
}
}
}
@ -396,6 +396,15 @@ HRESULT STDMETHODCALLTYPE D3D101SwapPresentHook(IDXGISwapChain *swap, UINT syncI
if(timeElapsed >= frameTime)
{
if(!IsWindow(hwndOBS))
{
hwndOBS = NULL;
bStopRequested = true;
}
if(WaitForSingleObject(hSignalEnd, 0) == WAIT_OBJECT_0)
bStopRequested = true;
lastTime += frameTime;
if(timeElapsed > frameTime*2)
lastTime = timeVal;

View File

@ -47,6 +47,7 @@ extern IDXGIKeyedMutex *keyedMutexes[2];
extern ID3D10Resource *sharedTextures[2];
void ClearD3D10Data()
{
bHasTextures = false;
@ -338,46 +339,46 @@ HRESULT STDMETHODCALLTYPE D3D10SwapPresentHook(IDXGISwapChain *swap, UINT syncIn
if(bCapturing && bStopRequested)
{
ClearD3D10Data();
bCapturing = false;
bStopRequested = false;
}
if(!bCapturing && WaitForSingleObject(hSignalRestart, 0) == WAIT_OBJECT_0)
{
hwndOBS = FindWindow(OBS_WINDOW_CLASS, NULL);
if(hwndOBS)
bCapturing = true;
}
if(!bHasTextures && bCapturing)
{
if(dxgiFormat)
if(dxgiFormat && hwndOBS)
{
if(!hwndReceiver)
hwndReceiver = FindWindow(RECEIVER_WINDOWCLASS, NULL);
BOOL bSuccess = DoD3D10Hook(device);
if(hwndReceiver)
if(bSuccess)
{
BOOL bSuccess = DoD3D10Hook(device);
d3d10CaptureInfo.mapID = InitializeSharedMemoryGPUCapture(&texData);
if(!d3d10CaptureInfo.mapID)
bSuccess = false;
}
if(bSuccess)
{
d3d10CaptureInfo.mapID = InitializeSharedMemoryGPUCapture(&texData);
if(!d3d10CaptureInfo.mapID)
bSuccess = false;
}
if(bSuccess)
{
bHasTextures = true;
d3d10CaptureInfo.captureType = CAPTURETYPE_SHAREDTEX;
d3d10CaptureInfo.bFlip = FALSE;
texData->texHandles[0] = sharedHandles[0];
texData->texHandles[1] = sharedHandles[1];
if(bSuccess)
bSuccess = IsWindow(hwndReceiver);
memcpy(infoMem, &d3d10CaptureInfo, sizeof(CaptureInfo));
SetEvent(hSignalReady);
if(bSuccess)
{
bHasTextures = true;
d3d10CaptureInfo.captureType = CAPTURETYPE_SHAREDTEX;
d3d10CaptureInfo.hwndSender = hwndSender;
d3d10CaptureInfo.bFlip = FALSE;
texData->texHandles[0] = sharedHandles[0];
texData->texHandles[1] = sharedHandles[1];
PostMessage(hwndReceiver, RECEIVER_NEWCAPTURE, 0, (LPARAM)&d3d10CaptureInfo);
logOutput << "DoD3D10Hook: success";
}
else
{
ClearD3D10Data();
}
logOutput << "DoD3D10Hook: success";
}
else
{
ClearD3D10Data();
}
}
}
@ -396,6 +397,15 @@ HRESULT STDMETHODCALLTYPE D3D10SwapPresentHook(IDXGISwapChain *swap, UINT syncIn
if(timeElapsed >= frameTime)
{
if(!IsWindow(hwndOBS))
{
hwndOBS = NULL;
bStopRequested = true;
}
if(WaitForSingleObject(hSignalEnd, 0) == WAIT_OBJECT_0)
bStopRequested = true;
lastTime += frameTime;
if(timeElapsed > frameTime*2)
lastTime = timeVal;

View File

@ -361,49 +361,49 @@ HRESULT STDMETHODCALLTYPE D3D11SwapPresentHook(IDXGISwapChain *swap, UINT syncIn
if(bCapturing && bStopRequested)
{
ClearD3D11Data();
bCapturing = false;
bStopRequested = false;
}
if(!bCapturing && WaitForSingleObject(hSignalRestart, 0) == WAIT_OBJECT_0)
{
hwndOBS = FindWindow(OBS_WINDOW_CLASS, NULL);
if(hwndOBS)
bCapturing = true;
}
if(!bHasTextures && bCapturing)
{
if(dxgiFormat)
if(dxgiFormat && hwndOBS)
{
if(!hwndReceiver)
hwndReceiver = FindWindow(RECEIVER_WINDOWCLASS, NULL);
BOOL bSuccess = DoD3D11Hook(device);
if(hwndReceiver)
if(bSuccess)
{
BOOL bSuccess = DoD3D11Hook(device);
if(bSuccess)
d3d11CaptureInfo.mapID = InitializeSharedMemoryGPUCapture(&texData);
if(!d3d11CaptureInfo.mapID)
{
d3d11CaptureInfo.mapID = InitializeSharedMemoryGPUCapture(&texData);
if(!d3d11CaptureInfo.mapID)
{
RUNONCE logOutput << "SwapPresentHook: creation of shared memory failed" << endl;
bSuccess = false;
}
RUNONCE logOutput << "SwapPresentHook: creation of shared memory failed" << endl;
bSuccess = false;
}
}
if(bSuccess)
bSuccess = IsWindow(hwndReceiver);
if(bSuccess)
{
bHasTextures = true;
d3d11CaptureInfo.captureType = CAPTURETYPE_SHAREDTEX;
d3d11CaptureInfo.bFlip = FALSE;
texData->texHandles[0] = sharedHandles[0];
texData->texHandles[1] = sharedHandles[1];
if(bSuccess)
{
bHasTextures = true;
d3d11CaptureInfo.captureType = CAPTURETYPE_SHAREDTEX;
d3d11CaptureInfo.hwndSender = hwndSender;
d3d11CaptureInfo.bFlip = FALSE;
texData->texHandles[0] = sharedHandles[0];
texData->texHandles[1] = sharedHandles[1];
PostMessage(hwndReceiver, RECEIVER_NEWCAPTURE, 0, (LPARAM)&d3d11CaptureInfo);
memcpy(infoMem, &d3d11CaptureInfo, sizeof(CaptureInfo));
SetEvent(hSignalReady);
logOutput << "DoD3D11Hook: success";
}
else
{
ClearD3D11Data();
}
logOutput << "DoD3D11Hook: success" << endl;
}
else
{
ClearD3D11Data();
}
}
}
@ -422,6 +422,15 @@ HRESULT STDMETHODCALLTYPE D3D11SwapPresentHook(IDXGISwapChain *swap, UINT syncIn
if(timeElapsed >= frameTime)
{
if(!IsWindow(hwndOBS))
{
hwndOBS = NULL;
bStopRequested = true;
}
if(WaitForSingleObject(hSignalEnd, 0) == WAIT_OBJECT_0)
bStopRequested = true;
lastTime += frameTime;
if(timeElapsed > frameTime*2)
lastTime = timeVal;

View File

@ -467,7 +467,7 @@ void DoD3D9GPUHook(IDirect3DDevice9 *device)
goto finishGPUHook;
}
bSuccess = IsWindow(hwndReceiver);
bSuccess = IsWindow(hwndOBS);
finishGPUHook:
@ -475,11 +475,12 @@ finishGPUHook:
{
bHasTextures = true;
d3d9CaptureInfo.captureType = CAPTURETYPE_SHAREDTEX;
d3d9CaptureInfo.hwndSender = hwndSender;
d3d9CaptureInfo.bFlip = FALSE;
texData->texHandles[0] = sharedHandles[0];
texData->texHandles[1] = sharedHandles[1];
PostMessage(hwndReceiver, RECEIVER_NEWCAPTURE, 0, (LPARAM)&d3d9CaptureInfo);
memcpy(infoMem, &d3d9CaptureInfo, sizeof(CaptureInfo));
SetEvent(hSignalReady);
logOutput << "DoD3D9GPUHook: success" << endl;
}
@ -576,16 +577,17 @@ void DoD3D9CPUHook(IDirect3DDevice9 *device)
}
if(bSuccess)
bSuccess = IsWindow(hwndReceiver);
bSuccess = IsWindow(hwndOBS);
if(bSuccess)
{
bHasTextures = true;
d3d9CaptureInfo.captureType = CAPTURETYPE_MEMORY;
d3d9CaptureInfo.pitch = pitch;
d3d9CaptureInfo.hwndSender = hwndSender;
d3d9CaptureInfo.bFlip = FALSE;
PostMessage(hwndReceiver, RECEIVER_NEWCAPTURE, 0, (LPARAM)&d3d9CaptureInfo);
memcpy(infoMem, &d3d9CaptureInfo, sizeof(CaptureInfo));
SetEvent(hSignalReady);
logOutput << "DoD3D9CPUHook: success" << endl;
}
@ -649,28 +651,30 @@ void DoD3D9DrawStuff(IDirect3DDevice9 *device)
if(bStopRequested)
{
ClearD3D9Data();
bCapturing = false;
bStopRequested = false;
}
if(!bCapturing && WaitForSingleObject(hSignalRestart, 0) == WAIT_OBJECT_0)
{
hwndOBS = FindWindow(OBS_WINDOW_CLASS, NULL);
if(hwndOBS)
bCapturing = true;
}
if(!bHasTextures && bCapturing)
{
if(d3d9Format)
if(d3d9Format && hwndOBS)
{
if(!hwndReceiver)
hwndReceiver = FindWindow(RECEIVER_WINDOWCLASS, NULL);
if(bD3D9Ex)
bUseSharedTextures = true;
else
bUseSharedTextures = (patchType = GetD3D9PatchType()) != 0;
if(hwndReceiver)
{
if(bD3D9Ex)
bUseSharedTextures = true;
else
bUseSharedTextures = (patchType = GetD3D9PatchType()) != 0;
if(bUseSharedTextures)
DoD3D9GPUHook(device);
else
DoD3D9CPUHook(device);
}
if(bUseSharedTextures)
DoD3D9GPUHook(device);
else
DoD3D9CPUHook(device);
}
}
@ -692,6 +696,17 @@ void DoD3D9DrawStuff(IDirect3DDevice9 *device)
if(timeElapsed >= frameTime)
{
if(!IsWindow(hwndOBS))
{
hwndOBS = NULL;
bStopRequested = true;
}
if(WaitForSingleObject(hSignalEnd, 0) == WAIT_OBJECT_0)
{
bStopRequested = true;
}
lastTime += frameTime;
if(timeElapsed > frameTime*2)
lastTime = timeVal;
@ -765,6 +780,15 @@ void DoD3D9DrawStuff(IDirect3DDevice9 *device)
if(timeElapsed >= frameTime)
{
if(!IsWindow(hwndOBS))
{
hwndOBS = NULL;
bStopRequested = true;
}
if(WaitForSingleObject(hSignalEnd, 0) == WAIT_OBJECT_0)
bStopRequested = true;
lastTime += frameTime;
if(timeElapsed > frameTime*2)
lastTime = timeVal;

View File

@ -21,8 +21,11 @@
#include <shlobj.h>
HANDLE hSignalRestart=NULL, hSignalEnd=NULL;
HANDLE hSignalReady=NULL, hSignalExit=NULL;
HINSTANCE hinstMain = NULL;
HWND hwndSender = NULL, hwndReceiver = NULL;
HWND hwndSender = NULL, hwndOBS = NULL;
HANDLE textureMutexes[2] = {NULL, NULL};
bool bStopRequested = false;
bool bCapturing = true;
@ -32,6 +35,9 @@ HANDLE hFileMap = NULL;
LPBYTE lpSharedMemory = NULL;
UINT sharedMemoryIDCounter = 0;
HANDLE hInfoFileMap = NULL;
CaptureInfo *infoMem = NULL;
LARGE_INTEGER clockFreq, startTime;
LONGLONG prevElapsedTime;
@ -198,27 +204,6 @@ void DestroySharedMemory()
}
LRESULT WINAPI SenderWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case SENDER_RESTARTCAPTURE:
bCapturing = true;
break;
case SENDER_ENDCAPTURE:
bStopRequested = true;
bCapturing = false;
hwndReceiver = NULL;
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
bool bD3D9Hooked = false;
bool bD3D10Hooked = false;
bool bD3D101Hooked = false;
@ -278,6 +263,7 @@ inline bool AttemptToHookSomething()
fstream logOutput;
#define SENDER_WINDOWCLASS TEXT("OBSGraphicsCaptureSender")
DWORD WINAPI CaptureThread(HANDLE hDllMainThread)
{
@ -301,7 +287,44 @@ DWORD WINAPI CaptureThread(HANDLE hDllMainThread)
ZeroMemory(&wc, sizeof(wc));
wc.hInstance = hinstMain;
wc.lpszClassName = SENDER_WINDOWCLASS;
wc.lpfnWndProc = (WNDPROC)SenderWindowProc;
wc.lpfnWndProc = (WNDPROC)DefWindowProc;
DWORD procID = GetCurrentProcessId();
wstringstream strRestartEvent, strEndEvent, strReadyEvent, strExitEvent, strInfoMemory;
strRestartEvent << RESTART_CAPTURE_EVENT << procID;
strEndEvent << END_CAPTURE_EVENT << procID;
strReadyEvent << CAPTURE_READY_EVENT << procID;
strExitEvent << APP_EXIT_EVENT << procID;
strInfoMemory << INFO_MEMORY << procID;
hSignalRestart = GetEvent(strRestartEvent.str().c_str());
hSignalEnd = GetEvent(strEndEvent.str().c_str());
hSignalReady = GetEvent(strReadyEvent.str().c_str());
hSignalExit = GetEvent(strExitEvent.str().c_str());
hInfoFileMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(CaptureInfo), strInfoMemory.str().c_str());
if(!hInfoFileMap)
{
logOutput << "CaptureThread: could not info file mapping" << endl;
return 0;
}
infoMem = (CaptureInfo*)MapViewOfFile(hInfoFileMap, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(CaptureInfo));
if(!infoMem)
{
logOutput << "CaptureThread: could not map view of info shared memory" << endl;
CloseHandle(hInfoFileMap);
hInfoFileMap = NULL;
return 0;
}
hwndOBS = FindWindow(OBS_WINDOW_CLASS, NULL);
if(!hwndOBS)
{
logOutput << "CaptureThread: could not find main application window? wtf? seriously?" << endl;
return 0;
}
if(RegisterClass(&wc))
{
@ -367,8 +390,26 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpBlah)
FreeD3D101Capture();
FreeD3D11Capture();*/
if(hwndReceiver)
PostMessage(hwndReceiver, RECEIVER_ENDCAPTURE, 0, 0);
if(hSignalRestart)
CloseHandle(hSignalRestart);
if(hSignalEnd)
CloseHandle(hSignalEnd);
if(hSignalReady)
CloseHandle(hSignalReady);
if(hSignalExit)
{
SetEvent(hSignalExit);
CloseHandle(hSignalExit);
}
if(infoMem)
{
UnmapViewOfFile(lpSharedMemory);
CloseHandle(hInfoFileMap);
}
hFileMap = NULL;
lpSharedMemory = NULL;
if(hwndSender)
DestroyWindow(hwndSender);

View File

@ -199,7 +199,6 @@ typedef ULONG (WINAPI *RELEASEPROC)(LPVOID);
enum GSColorFormat {GS_UNKNOWNFORMAT, GS_ALPHA, GS_GRAYSCALE, GS_RGB, GS_RGBA, GS_BGR, GS_BGRA, GS_RGBA16F, GS_RGBA32F, GS_B5G5R5A1, GS_B5G6R5, GS_R10G10B10A2, GS_DXT1, GS_DXT3, GS_DXT5};
extern HWND hwndSender, hwndReceiver;
extern HINSTANCE hinstMain;
extern HANDLE textureMutexes[2];
extern bool bCapturing;
@ -209,6 +208,14 @@ extern bool bTargetAcquired;
extern HANDLE hFileMap;
extern LPBYTE lpSharedMemory;
extern HANDLE hSignalRestart, hSignalEnd;
extern HANDLE hSignalReady, hSignalExit;
extern HWND hwndSender;
extern HWND hwndOBS;
extern CaptureInfo *infoMem;
extern fstream logOutput;
void WINAPI OSInitializeTimer();

View File

@ -68,7 +68,8 @@
AdditionalDependencies="dxguid.lib"
LinkIncremental="2"
GenerateDebugInformation="true"
ProgramDatabaseFile="..\rundir\pdb32\$(TargetName).pdb"
ProgramDatabaseFile="..\..\rundir\pdb32\$(TargetName).pdb"
StripPrivateSymbols=""
SubSystem="2"
TargetMachine="1"
/>
@ -146,7 +147,8 @@
OutputFile="$(OutDir)\$(ProjectName).dll"
LinkIncremental="2"
GenerateDebugInformation="true"
ProgramDatabaseFile="..\rundir\pdb64\$(TargetName).pdb"
ProgramDatabaseFile="..\..\rundir\pdb64\$(TargetName).pdb"
StripPrivateSymbols=""
SubSystem="2"
TargetMachine="17"
/>
@ -222,7 +224,8 @@
AdditionalDependencies="dxguid.lib"
LinkIncremental="1"
GenerateDebugInformation="true"
ProgramDatabaseFile="..\rundir\pdb32\$(TargetName).pdb"
ProgramDatabaseFile="..\..\rundir\pdb32\$(TargetName).pdb"
StripPrivateSymbols=""
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
@ -302,7 +305,8 @@
OutputFile="$(OutDir)\$(ProjectName).dll"
LinkIncremental="1"
GenerateDebugInformation="true"
ProgramDatabaseFile="..\rundir\pdb64\$(TargetName).pdb"
ProgramDatabaseFile="..\..\rundir\pdb64\$(TargetName).pdb"
StripPrivateSymbols=""
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"

View File

@ -274,18 +274,16 @@ void DoGLCPUHook(RECT &rc)
bSuccess = false;
}
if(bSuccess)
bSuccess = IsWindow(hwndReceiver);
if(bSuccess)
{
bHasTextures = true;
glcaptureInfo.captureType = CAPTURETYPE_MEMORY;
glcaptureInfo.hwndSender = hwndSender;
glcaptureInfo.hwndCapture = hwndTarget;
glcaptureInfo.pitch = glcaptureInfo.cx*4;
glcaptureInfo.bFlip = TRUE;
PostMessage(hwndReceiver, RECEIVER_NEWCAPTURE, 0, (LPARAM)&glcaptureInfo);
memcpy(infoMem, &glcaptureInfo, sizeof(CaptureInfo));
SetEvent(hSignalReady);
logOutput << "DoGLCPUHook: success" << endl;
@ -376,10 +374,18 @@ void HandleGLSceneUpdate(HDC hDC)
if(bCapturing && bStopRequested)
{
ClearGLData();
bCapturing = false;
bStopRequested = false;
bReacquiring = false;
}
if(!bCapturing && WaitForSingleObject(hSignalRestart, 0) == WAIT_OBJECT_0)
{
hwndOBS = FindWindow(OBS_WINDOW_CLASS, NULL);
if(hwndOBS)
bCapturing = true;
}
RECT rc;
GetClientRect(hwndTarget, &rc);
@ -403,9 +409,6 @@ void HandleGLSceneUpdate(HDC hDC)
if (!rc.right || !rc.bottom)
return;
if(!hwndReceiver)
hwndReceiver = FindWindow(RECEIVER_WINDOWCLASS, NULL);
if(bHasTextures) //resizing
{
ClearGLData();
@ -417,7 +420,7 @@ void HandleGLSceneUpdate(HDC hDC)
}
else
{
if(hwndReceiver)
if(hwndOBS)
DoGLCPUHook(rc);
else
ClearGLData();
@ -438,6 +441,15 @@ void HandleGLSceneUpdate(HDC hDC)
if(timeElapsed >= frameTime)
{
if(!IsWindow(hwndOBS))
{
hwndOBS = NULL;
bStopRequested = true;
}
if(WaitForSingleObject(hSignalEnd, 0) == WAIT_OBJECT_0)
bStopRequested = true;
lastTime += frameTime;
if(timeElapsed > frameTime*2)
lastTime = timeVal;

View File

@ -92,55 +92,36 @@ GraphicsCaptureSource::~GraphicsCaptureSource()
EndScene(); //should never actually need to be called, but doing it anyway just to be safe
}
LRESULT WINAPI GraphicsCaptureSource::ReceiverWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
bool GetCaptureInfo(CaptureInfo &ci, DWORD processID)
{
switch(message)
HANDLE hFileMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, String() << INFO_MEMORY << int(processID));
if(hFileMap == NULL)
{
case WM_CREATE:
{
CREATESTRUCT *cs = (CREATESTRUCT*)lParam;
SetWindowLongPtr(hwnd, 0, (LONG_PTR)cs->lpCreateParams);
}
break;
case RECEIVER_NEWCAPTURE:
{
CaptureWindowData *data = (CaptureWindowData*)GetWindowLongPtr(hwnd, 0);
if(data->source)
{
data->source->captureData = (LPVOID)lParam;
data->source->bNewCapture = true;
}
}
break;
case RECEIVER_ENDCAPTURE:
{
CaptureWindowData *data = (CaptureWindowData*)GetWindowLongPtr(hwnd, 0);
if(data->source)
data->source->bEndCapture = true;
}
break;
case WM_DESTROY:
{
CaptureWindowData *data = (CaptureWindowData*)GetWindowLongPtr(hwnd, 0);
delete data;
}
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
AppWarning(TEXT("GetCaptureInfo: Could not open file mapping"));
return false;
}
return 0;
CaptureInfo *infoIn;
infoIn = (CaptureInfo*)MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(CaptureInfo));
if(!infoIn)
{
AppWarning(TEXT("GetCaptureInfo: Could not map view of file"));
return false;
}
mcpy(&ci, infoIn, sizeof(CaptureInfo));
if(infoIn)
UnmapViewOfFile(infoIn);
if(hFileMap)
CloseHandle(hFileMap);
return true;
}
void GraphicsCaptureSource::NewCapture(LPVOID address)
void GraphicsCaptureSource::NewCapture()
{
if(!hProcess)
return;
if(capture)
{
capture->Destroy();
@ -148,15 +129,41 @@ void GraphicsCaptureSource::NewCapture(LPVOID address)
capture = NULL;
}
CaptureInfo info;
if(!ReadProcessMemory(hProcess, address, &info, sizeof(info), NULL))
if(!hSignalRestart)
{
API->LeaveSceneMutex();
hSignalRestart = GetEvent(String() << RESTART_CAPTURE_EVENT << int(targetProcessID));
if(!hSignalRestart)
{
RUNONCE AppWarning(TEXT("GraphicsCaptureSource::NewCapture: Could not create restart event"));
return;
}
}
RUNONCE AppWarning(TEXT("GraphicsCaptureSource::NewCapture: Could not read capture info from target process"));
hSignalEnd = GetEvent(String() << END_CAPTURE_EVENT << int(targetProcessID));
if(!hSignalEnd)
{
RUNONCE AppWarning(TEXT("GraphicsCaptureSource::NewCapture: Could not create end event"));
return;
}
hSignalReady = GetEvent(String() << CAPTURE_READY_EVENT << int(targetProcessID));
if(!hSignalReady)
{
RUNONCE AppWarning(TEXT("GraphicsCaptureSource::NewCapture: Could not create ready event"));
return;
}
hSignalExit = GetEvent(String() << APP_EXIT_EVENT << int(targetProcessID));
if(!hSignalExit)
{
RUNONCE AppWarning(TEXT("GraphicsCaptureSource::NewCapture: Could not create exit event"));
return;
}
CaptureInfo info;
if(!GetCaptureInfo(info, targetProcessID))
return;
bFlip = info.bFlip != 0;
hwndCapture = info.hwndCapture;
@ -173,7 +180,7 @@ void GraphicsCaptureSource::NewCapture(LPVOID address)
return;
}
if(!capture->Init(hProcess, hwndTarget, info))
if(!capture->Init(info))
{
capture->Destroy();
delete capture;
@ -190,10 +197,23 @@ void GraphicsCaptureSource::EndCapture()
capture = NULL;
}
if(hSignalRestart)
CloseHandle(hSignalRestart);
if(hSignalEnd)
CloseHandle(hSignalEnd);
if(hSignalReady)
CloseHandle(hSignalReady);
if(hSignalExit)
CloseHandle(hSignalExit);
hSignalRestart = hSignalEnd = hSignalReady = hSignalExit = NULL;
bErrorAcquiring = false;
bCapturing = false;
captureCheckInterval = -1.0f;
hwndCapture = NULL;
targetProcessID = 0;
if(warningID)
{
@ -204,39 +224,16 @@ void GraphicsCaptureSource::EndCapture()
void GraphicsCaptureSource::Preprocess()
{
if(bEndCapture)
if(hSignalExit && WaitForSingleObject(hSignalExit, 0) == WAIT_OBJECT_0)
{
EndCapture();
bEndCapture = false;
}
if(bNewCapture)
{
NewCapture(captureData);
bNewCapture = false;
}
}
if(bCapturing && !hSignalReady && targetProcessID)
hSignalReady = GetEvent(String() << CAPTURE_READY_EVENT << int(targetProcessID));
bool GraphicsCaptureSource::FindSenderWindow()
{
if(hwndSender)
{
if(!IsWindow(hwndSender))
hwndSender = NULL;
else
return true;
}
while(hwndSender = FindWindowEx(NULL, hwndSender, SENDER_WINDOWCLASS, NULL))
{
DWORD procID = 0;
GetWindowThreadProcessId(hwndSender, &procID);
if(procID == targetProcessID)
return true;
}
return false;
if(hSignalReady && (WaitForSingleObject(hSignalReady, 0) == WAIT_OBJECT_0))
NewCapture();
}
void GraphicsCaptureSource::BeginScene()
@ -255,7 +252,6 @@ void GraphicsCaptureSource::BeginScene()
invertShader = CreatePixelShaderFromFile(TEXT("shaders\\InvertTexture.pShader"));
windowData = new CaptureWindowData(this);
hwndReceiver = CreateWindow(RECEIVER_WINDOWCLASS, NULL, 0, 0, 0, 0, 0, 0, 0, hinstMain, windowData);
AttemptCapture();
}
@ -292,12 +288,15 @@ void GraphicsCaptureSource::AttemptCapture()
//-------------------------------------------
// see if we already hooked the process. if not, inject DLL
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetProcessID);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetProcessID);
if(hProcess)
{
if(FindSenderWindow())
hwndCapture = hwndTarget;
hSignalRestart = OpenEvent(EVENT_ALL_ACCESS, FALSE, String() << RESTART_CAPTURE_EVENT << int(targetProcessID));
if(hSignalRestart)
{
PostMessage(hwndSender, SENDER_RESTARTCAPTURE, 0, 0);
SetEvent(hSignalRestart);
bCapturing = true;
captureWaitCount = 0;
}
@ -330,6 +329,8 @@ void GraphicsCaptureSource::AttemptCapture()
AppWarning(TEXT("GraphicsCaptureSource::BeginScene: OpenProcess failed, GetLastError = %u"), GetLastError());
bErrorAcquiring = true;
}
CloseHandle(hProcess);
}
void GraphicsCaptureSource::EndScene()
@ -340,12 +341,6 @@ void GraphicsCaptureSource::EndScene()
windowData = NULL;
}
if(hwndReceiver)
{
DestroyWindow(hwndReceiver);
hwndReceiver = NULL;
}
if(capture)
{
capture->Destroy();
@ -366,21 +361,14 @@ void GraphicsCaptureSource::EndScene()
}
if(!bCapturing)
{
return;
}
bCapturing = false;
if(FindSenderWindow())
{
PostMessage(hwndSender, SENDER_ENDCAPTURE, 0, 0);
hwndSender = NULL;
}
if(hProcess)
{
CloseHandle(hProcess);
hProcess = NULL;
}
SetEvent(hSignalEnd);
EndCapture();
}
void GraphicsCaptureSource::Tick(float fSeconds)
@ -388,7 +376,9 @@ void GraphicsCaptureSource::Tick(float fSeconds)
if(bCapturing && !capture)
{
if(++captureWaitCount >= API->GetMaxFPS())
{
bCapturing = false;
}
}
if(!bCapturing && !bErrorAcquiring)
@ -402,7 +392,7 @@ void GraphicsCaptureSource::Tick(float fSeconds)
}
else
{
if(!FindSenderWindow())
if(!IsWindow(hwndCapture))
EndCapture();
}
}

View File

@ -38,11 +38,10 @@ class GraphicsCaptureSource : public ImageSource
XElement *data;
String strWindowClass;
HWND hwndTarget, hwndSender, hwndReceiver, hwndCapture;
HWND hwndTarget, hwndCapture;
bool bCapturing, bErrorAcquiring, bFlip, bStretch, bCaptureMouse;
UINT captureWaitCount;
DWORD targetProcessID;
HANDLE hProcess;
UINT warningID;
POINT cursorPos;
@ -52,16 +51,16 @@ class GraphicsCaptureSource : public ImageSource
Shader *invertShader;
Texture *cursorTexture;
bool bNewCapture, bEndCapture;
LPVOID captureData;
HANDLE hSignalRestart, hSignalEnd;
HANDLE hSignalReady, hSignalExit;
HANDLE hOBSIsAlive;
float captureCheckInterval;
void NewCapture(LPVOID address);
void NewCapture();
void EndCapture();
bool FindSenderWindow();
void AttemptCapture();
public:
@ -77,6 +76,4 @@ public:
Vect2 GetSize() const;
void UpdateSettings();
static LRESULT WINAPI ReceiverWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
};

View File

@ -46,10 +46,8 @@ void MemoryCapture::Destroy()
}
}
bool MemoryCapture::Init(HANDLE hProcess, HWND hwndTarget, CaptureInfo &info)
bool MemoryCapture::Init(CaptureInfo &info)
{
this->hwndTarget = hwndTarget;
this->hProcess = hProcess;
this->height = info.cy;
this->pitch = info.pitch;

View File

@ -31,8 +31,6 @@ class MemoryCapture : public GraphicsCaptureMethod
LPBYTE textureBuffers[2];
UINT pitch;
HWND hwndTarget;
HANDLE hProcess;
Texture *texture;
HANDLE hMutex;
@ -44,7 +42,7 @@ class MemoryCapture : public GraphicsCaptureMethod
public:
void Destroy();
virtual bool Init(HANDLE hProcess, HWND hwndTarget, CaptureInfo &info);
virtual bool Init(CaptureInfo &info);
virtual Texture* LockTexture();
virtual void UnlockTexture();

View File

@ -39,11 +39,8 @@ void SharedTexCapture::Destroy()
CloseHandle(hFileMap);
}
bool SharedTexCapture::Init(HANDLE hProcess, HWND hwndTarget, CaptureInfo &info)
bool SharedTexCapture::Init(CaptureInfo &info)
{
this->hwndTarget = hwndTarget;
this->hProcess = hProcess;
String strFileMapName;
strFileMapName << TEXTURE_MEMORY << UIntString(info.mapID);

View File

@ -26,7 +26,6 @@ class SharedTexCapture : public GraphicsCaptureMethod
Texture *curTexture;
HWND hwndTarget;
HANDLE hProcess;
HANDLE hFileMap;
LPBYTE sharedMemory;
@ -38,7 +37,7 @@ class SharedTexCapture : public GraphicsCaptureMethod
public:
void Destroy();
virtual bool Init(HANDLE hProcess, HWND hwndTarget, CaptureInfo &info);
virtual bool Init(CaptureInfo &info);
virtual Texture* LockTexture();
virtual void UnlockTexture();