fixed threading, optimized some more things, some other adjustments

master
jim 2012-10-26 18:06:49 -07:00
parent 2f078a09e9
commit a5f8b3b901
30 changed files with 671 additions and 162 deletions

View File

@ -576,9 +576,99 @@ bool GetResolution(HWND hwndResolution, SIZE &resolution, BOOL bSelChange)
return true;
}
struct ColorSelectionData
{
HDC hdcDesktop;
HDC hdcDestination;
HBITMAP hBitmap;
bool bValid;
inline ColorSelectionData() : hdcDesktop(NULL), hdcDestination(NULL), hBitmap(NULL), bValid(false) {}
inline ~ColorSelectionData() {Clear();}
inline bool Init()
{
hdcDesktop = GetDC(NULL);
if(!hdcDesktop)
return false;
hdcDestination = CreateCompatibleDC(hdcDesktop);
if(!hdcDestination)
return false;
hBitmap = CreateCompatibleBitmap(hdcDesktop, 1, 1);
if(!hBitmap)
return false;
SelectObject(hdcDestination, hBitmap);
bValid = true;
return true;
}
inline void Clear()
{
if(hdcDesktop)
{
ReleaseDC(NULL, hdcDesktop);
hdcDesktop = NULL;
}
if(hdcDestination)
{
DeleteDC(hdcDestination);
hdcDestination = NULL;
}
if(hBitmap)
{
DeleteObject(hBitmap);
hBitmap = NULL;
}
bValid = false;
}
inline DWORD GetColor()
{
POINT p;
if(GetCursorPos(&p))
{
BITMAPINFO data;
zero(&data, sizeof(data));
data.bmiHeader.biSize = sizeof(data.bmiHeader);
data.bmiHeader.biWidth = 1;
data.bmiHeader.biHeight = 1;
data.bmiHeader.biPlanes = 1;
data.bmiHeader.biBitCount = 24;
data.bmiHeader.biCompression = BI_RGB;
data.bmiHeader.biSizeImage = 4;
if(BitBlt(hdcDestination, 0, 0, 1, 1, hdcDesktop, p.x, p.y, SRCCOPY|CAPTUREBLT))
{
DWORD buffer;
if(GetDIBits(hdcDestination, hBitmap, 0, 1, &buffer, &data, DIB_RGB_COLORS))
return 0xFF000000|buffer;
}
else
{
int err = GetLastError();
nop();
}
}
return 0xFF000000;
}
};
INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static bool bSelectingColor = false;
static bool bMouseDown = false;
static ColorSelectionData colorData;
switch(message)
{
case WM_INITDIALOG:
@ -670,6 +760,52 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
return TRUE;
}
case WM_DESTROY:
if(colorData.bValid)
{
CCSetColor(GetDlgItem(hwnd, IDC_COLOR), colorData.GetColor());
colorData.Clear();
}
break;
case WM_LBUTTONDOWN:
if(bSelectingColor)
{
bMouseDown = true;
CCSetColor(GetDlgItem(hwnd, IDC_COLOR), colorData.GetColor());
}
break;
case WM_MOUSEMOVE:
if(bSelectingColor && bMouseDown)
CCSetColor(GetDlgItem(hwnd, IDC_COLOR), colorData.GetColor());
break;
case WM_LBUTTONUP:
if(bSelectingColor)
{
colorData.Clear();
ReleaseCapture();
bMouseDown = false;
bSelectingColor = false;
}
break;
case WM_CAPTURECHANGED:
if(bSelectingColor)
{
if(colorData.bValid)
{
CCSetColor(GetDlgItem(hwnd, IDC_COLOR), colorData.GetColor());
colorData.Clear();
}
ReleaseCapture();
bMouseDown = false;
bSelectingColor = false;
}
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
@ -705,6 +841,24 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
break;
}
case IDC_SELECTCOLOR:
{
if(!bSelectingColor)
{
if(colorData.Init())
{
bMouseDown = false;
bSelectingColor = true;
SetCapture(hwnd);
HCURSOR hCursor = (HCURSOR)LoadImage(hinstMain, MAKEINTRESOURCE(IDC_COLORPICKER), IMAGE_CURSOR, 32, 32, 0);
SetCursor(hCursor);
}
else
colorData.Clear();
}
break;
}
case IDC_COLOR:
{
ConfigDialogData *configData = (ConfigDialogData*)GetWindowLongPtr(hwnd, DWLP_USER);

View File

@ -107,6 +107,13 @@ BEGIN
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Cursor
//
IDC_COLORPICKER CURSOR "cursor1.cur"
#endif // 日本語 resources
/////////////////////////////////////////////////////////////////////////////

View File

@ -396,6 +396,10 @@
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
<File
RelativePath="..\..\..\cursor1.cur"
>
</File>
<File
RelativePath=".\DShowPlugin.rc"
>

View File

@ -19,6 +19,8 @@
#include "DShowPlugin.h"
DWORD STDCALL PackPlanarThread(ConvertData *data);
bool DeviceSource::Init(XElement *data)
{
@ -48,12 +50,12 @@ bool DeviceSource::Init(XElement *data)
capture->SetFiltergraph(graph);
UINT numProcessors = OSGetProcessorCount();
hConvertThreads = (HANDLE*)Allocate(sizeof(HANDLE)*numProcessors);
convertData = (ConvertData*)Allocate(sizeof(ConvertData)*numProcessors);
int numThreads = MAX(OSGetTotalCores()-2, 1);
hConvertThreads = (HANDLE*)Allocate(sizeof(HANDLE)*numThreads);
convertData = (ConvertData*)Allocate(sizeof(ConvertData)*numThreads);
zero(hConvertThreads, sizeof(HANDLE)*numProcessors);
zero(convertData, sizeof(ConvertData)*numProcessors);
zero(hConvertThreads, sizeof(HANDLE)*numThreads);
zero(convertData, sizeof(ConvertData)*numThreads);
this->data = data;
UpdateSettings();
@ -76,8 +78,11 @@ DeviceSource::~DeviceSource()
SafeRelease(capture);
SafeRelease(graph);
Free(hConvertThreads);
Free(convertData);
if(hConvertThreads)
Free(hConvertThreads);
if(convertData)
Free(convertData);
if(hSampleMutex)
OSCloseMutex(hSampleMutex);
@ -131,6 +136,8 @@ bool DeviceSource::LoadFilters()
HRESULT err;
String strShader;
bUseThreadedConversion = API->UseMultithreadedOptimizations() && (OSGetTotalCores() > 1);
//------------------------------------------------
bUseCustomResolution = data->GetInt(TEXT("customResolution"));
@ -192,25 +199,27 @@ bool DeviceSource::LoadFilters()
goto cleanFinish;
}
UINT numProcessors = OSGetProcessorCount();
for(UINT i=0; i<numProcessors; i++)
int numThreads = MAX(OSGetTotalCores()-2, 1);
for(int i=0; i<numThreads; i++)
{
convertData[i].width = renderCX;
convertData[i].height = renderCY;
convertData[i].sample = NULL;
convertData[i].hSignalConvert = CreateEvent(NULL, FALSE, FALSE, NULL);
convertData[i].hSignalComplete = CreateEvent(NULL, FALSE, FALSE, NULL);
if(i == 0)
convertData[i].startY = 0;
else
convertData[i].startY = convertData[i-1].endY;
if(i == (numProcessors-1))
if(i == (numThreads-1))
convertData[i].endY = renderCY;
else
convertData[i].endY = ((renderCY/numProcessors)*(i+1)) & 0xFFFFFFFE;
convertData[i].endY = ((renderCY/numThreads)*(i+1)) & 0xFFFFFFFE;
}
bFirstFrame = true;
prevSample = NULL;
//------------------------------------------------
@ -240,9 +249,6 @@ bool DeviceSource::LoadFilters()
else
expectedVideoType = VideoOutputType_RGB32;
if(colorType != DeviceOutputType_RGB)
lpImageBuffer = (LPBYTE)Allocate(renderCX*renderCY*4);
strShader = ChooseShader();
if(strShader.IsValid())
colorConvertShader = CreatePixelShaderFromFile(strShader);
@ -253,6 +259,14 @@ bool DeviceSource::LoadFilters()
goto cleanFinish;
}
if(colorType == DeviceOutputType_YV12 || colorType == DeviceOutputType_I420)
{
for(int i=0; i<numThreads; i++)
hConvertThreads[i] = OSCreateThread((XTHREAD)PackPlanarThread, convertData+i);
}
//------------------------------------------------
if(FAILED(err = devicePin->QueryInterface(IID_IAMStreamConfig, (void**)&config)))
{
AppWarning(TEXT("DShowPlugin: Could not get IAMStreamConfig for device pin, result = %08lX"), err);
@ -276,6 +290,8 @@ bool DeviceSource::LoadFilters()
FreeMediaType(outputMediaType);
//------------------------------------------------
captureFilter = new CaptureFilter(this, expectedVideoType);
if(FAILED(err = graph->AddFilter(captureFilter, NULL)))
@ -294,6 +310,8 @@ bool DeviceSource::LoadFilters()
bAddedDevice = true;
//------------------------------------------------
//THANK THE NINE DIVINES I FINALLY GOT IT WORKING
bool bConnected = SUCCEEDED(err = capture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, deviceFilter, NULL, captureFilter));
if(!bConnected)
@ -365,6 +383,20 @@ cleanFinish:
texture = CreateTexture(renderCX, renderCY, GS_RGB, textureData, FALSE, FALSE);
}
if(bSucceeded && bUseThreadedConversion)
{
if(colorType == DeviceOutputType_I420 || colorType == DeviceOutputType_YV12)
{
LPBYTE lpData;
if(texture->Map(lpData, texturePitch))
texture->Unmap();
else
texturePitch = renderCX*4;
lpImageBuffer = (LPBYTE)Allocate(texturePitch*renderCY);
}
}
Free(textureData);
bFiltersLoaded = bSucceeded;
@ -400,25 +432,37 @@ void DeviceSource::UnloadFilters()
colorConvertShader = NULL;
}
int numThreads = MAX(OSGetTotalCores()-2, 1);
for(int i=0; i<numThreads; i++)
{
if(hConvertThreads[i])
{
convertData[i].bKillThread = true;
SetEvent(convertData[i].hSignalConvert);
OSTerminateThread(hConvertThreads[i], 10000);
hConvertThreads[i] = NULL;
}
if(convertData[i].hSignalConvert)
{
CloseHandle(convertData[i].hSignalConvert);
convertData[i].hSignalConvert = NULL;
}
if(convertData[i].hSignalComplete)
{
CloseHandle(convertData[i].hSignalComplete);
convertData[i].hSignalComplete = NULL;
}
}
if(lpImageBuffer)
{
Free(lpImageBuffer);
lpImageBuffer = NULL;
}
UINT numProcessors = OSGetProcessorCount();
for(UINT i=0; i<numProcessors; i++)
{
if(hConvertThreads[i])
{
WaitForSingleObject(hConvertThreads[i], INFINITE);
CloseHandle(hConvertThreads[i]);
hConvertThreads[i] = NULL;
}
}
SafeRelease(prevSample);
SafeRelease(control);
traceOut;
@ -491,8 +535,18 @@ void DeviceSource::Receive(IMediaSample *sample)
DWORD STDCALL PackPlanarThread(ConvertData *data)
{
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
PackPlanar(data->output, data->input, data->width, data->height, data->pitch, data->startY, data->endY);
do
{
WaitForSingleObject(data->hSignalConvert, INFINITE);
if(data->bKillThread) break;
IMediaSample *sample = data->sample;
PackPlanar(data->output, data->input, data->width, data->height, data->pitch, data->startY, data->endY);
SafeRelease(sample);
SetEvent(data->hSignalComplete);
}while(!data->bKillThread);
return 0;
}
@ -513,7 +567,7 @@ void DeviceSource::Preprocess()
}
OSLeaveMutex(hSampleMutex);
UINT numProcessors = OSGetProcessorCount();
int numThreads = MAX(OSGetTotalCores()-2, 1);
if(lastSample)
{
@ -525,37 +579,52 @@ void DeviceSource::Preprocess()
if(SUCCEEDED(lastSample->GetPointer(&lpImage)))
texture->SetImage(lpImage, GS_IMAGEFORMAT_BGRX, renderCX*4);
}
lastSample->Release();
}
else if(colorType == DeviceOutputType_I420 || colorType == DeviceOutputType_YV12)
{
if(prevSample)
if(bUseThreadedConversion)
{
WaitForMultipleObjects(numProcessors, hConvertThreads, TRUE, INFINITE);
for(UINT i=0; i<numProcessors; i++)
if(!bFirstFrame)
{
CloseHandle(hConvertThreads[i]);
hConvertThreads[i] = NULL;
List<HANDLE> events;
for(int i=0; i<numThreads; i++)
events << convertData[i].hSignalComplete;
WaitForMultipleObjects(numThreads, events.Array(), TRUE, INFINITE);
texture->SetImage(lpImageBuffer, GS_IMAGEFORMAT_RGBX, texturePitch);
}
prevSample->Release();
prevSample = NULL;
else
bFirstFrame = false;
texture->SetImage(lpImageBuffer, GS_IMAGEFORMAT_RGBX, renderCX*4);
}
if(SUCCEEDED(lastSample->GetPointer(&lpImage)))
{
for(UINT i=0; i<numProcessors; i++)
if(SUCCEEDED(lastSample->GetPointer(&lpImage)))
{
convertData[i].input = lpImage;
convertData[i].pitch = renderCX*4;
convertData[i].output = lpImageBuffer;
hConvertThreads[i] = OSCreateThread((XTHREAD)PackPlanarThread, (LPVOID)(convertData+i));
for(int i=0; i<numThreads; i++)
lastSample->AddRef();
for(int i=0; i<numThreads; i++)
{
convertData[i].input = lpImage;
convertData[i].pitch = texturePitch;
convertData[i].output = lpImageBuffer;
convertData[i].sample = lastSample;
SetEvent(convertData[i].hSignalConvert);
}
}
}
else
{
if(SUCCEEDED(lastSample->GetPointer(&lpImage)))
{
LPBYTE lpData;
UINT pitch;
prevSample = lastSample;
if(texture->Map(lpData, pitch))
{
PackPlanar(lpData, lpImage, renderCX, renderCY, pitch, 0, renderCY);
texture->Unmap();
}
}
}
}
else if(colorType == DeviceOutputType_YVYU || colorType == DeviceOutputType_YUY2)
{
@ -570,8 +639,6 @@ void DeviceSource::Preprocess()
texture->Unmap();
}
}
lastSample->Release();
}
else if(colorType == DeviceOutputType_UYVY || colorType == DeviceOutputType_HDYC)
{
@ -586,10 +653,10 @@ void DeviceSource::Preprocess()
texture->Unmap();
}
}
lastSample->Release();
}
lastSample->Release();
bReadyToDraw = true;
}

View File

@ -39,6 +39,9 @@ enum DeviceColorType
struct ConvertData
{
LPBYTE input, output;
IMediaSample *sample;
HANDLE hSignalConvert, hSignalComplete;
bool bKillThread;
UINT width, height;
UINT pitch;
UINT startY, endY;
@ -72,9 +75,9 @@ class DeviceSource : public ImageSource
Texture *texture;
HANDLE hSampleMutex;
XElement *data;
UINT texturePitch;
bool bCapturing, bFiltersLoaded;
IMediaSample *curSample;
IMediaSample *prevSample;
Shader *colorConvertShader;
//---------------------------------

BIN
DShowPlugin/cursor1.cur Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

View File

@ -13,6 +13,8 @@
#define IDC_BUTTON1 1015
#define IDC_CUSTOM 1015
#define IDC_SELECTCOLOR 1015
#define IDC_COLORPICKET 1015
#define IDC_COLORPICKER 1015
#define IDC_AUTOMATICRESOLUTION 1016
#define IDC_CUSTOMRESOLUTION 1016
#define IDC_USECHROMAKEY 1017
@ -24,14 +26,13 @@
#define IDC_BLEND_EDIT 1021
#define IDC_BLEND 1022
#define IDC_GAMMA_EDIT 1023
#define IDC_BASETHRESHOLD3 1024
#define IDC_GAMMA 1024
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_RESOURCE_VALUE 107
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1022
#define _APS_NEXT_SYMED_VALUE 101

View File

@ -26,7 +26,7 @@
#define TEXTURE_MUTEX1 TEXT("OBSTextureMutex1")
#define TEXTURE_MUTEX2 TEXT("OBSTextureMutex2")
#define TEXTURE_MEMORY TEXT("Global\\OBSTextureMemory")
#define TEXTURE_MEMORY TEXT("Local\\OBSTextureMemory")
#define CAPTURETYPE_MEMORY 1
#define CAPTURETYPE_SHAREDTEX 2

View File

@ -28,6 +28,7 @@ extern "C" __declspec(dllexport) CTSTR GetPluginDescription();
HINSTANCE hinstMain = NULL;
HANDLE textureMutexes[2] = {NULL, NULL};
#define GRAPHICSCAPTURE_CLASSNAME TEXT("GraphicsCapture")
void RefreshWindowList(HWND hwndCombobox, StringList &classList)
@ -130,7 +131,7 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
//--------------------------------------------
SendMessage(GetDlgItem(hwnd, IDC_STRETCHTOSCREEN), BM_SETCHECK, data->GetInt(TEXT("strechImage")) ? BST_CHECKED : BST_UNCHECKED, 0);
SendMessage(GetDlgItem(hwnd, IDC_STRETCHTOSCREEN), BM_SETCHECK, data->GetInt(TEXT("stretchImage")) ? BST_CHECKED : BST_UNCHECKED, 0);
return TRUE;
}
@ -232,8 +233,6 @@ ImageSource* STDCALL CreateGraphicsCaptureSource(XElement *data)
bool LoadPlugin()
{
traceIn(GraphicsPluginLoadPlugin);
WNDCLASS wc;
zero(&wc, sizeof(wc));
wc.hInstance = hinstMain;
@ -264,8 +263,6 @@ bool LoadPlugin()
API->RegisterImageSourceClass(GRAPHICSCAPTURE_CLASSNAME, Str("Sources.GameCaptureSource"), (OBSCREATEPROC)CreateGraphicsCaptureSource, (OBSCONFIGPROC)ConfigureGraphicsCaptureSource);
return true;
traceOut;
}
void UnloadPlugin()

View File

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

View File

@ -195,7 +195,7 @@
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
Optimization="3"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="../OBSApi"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;GRAPHICSCAPTURE_EXPORTS"
@ -274,7 +274,7 @@
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
Optimization="3"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="../OBSApi"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;GRAPHICSCAPTURE_EXPORTS"

View File

@ -341,6 +341,8 @@ bool InitD3D9Capture()
IDirect3DDevice9Ex *deviceEx;
if(SUCCEEDED(hRes = d3d9ex->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwndSender, D3DCREATE_HARDWARE_VERTEXPROCESSING|D3DCREATE_NOWINDOWCHANGES, &pp, NULL, &deviceEx)))
{
bSuccess = true;
UPARAM *vtable = *(UPARAM**)deviceEx;
d3d9EndScene.Hook((FARPROC)*(vtable+(168/4)), ConvertClassProcToFarproc((CLASSPROC)&D3D9Override::EndScene));

View File

@ -25,8 +25,8 @@ inline GSColorFormat ConvertGIBackBufferFormat(DXGI_FORMAT format)
switch(format)
{
case DXGI_FORMAT_R10G10B10A2_UNORM: return GS_R10G10B10A2;
case DXGI_FORMAT_R8G8B8A8_UNORM: return GS_RGB;
case DXGI_FORMAT_B8G8R8A8_UNORM: return GS_BGR;
case DXGI_FORMAT_R8G8B8A8_UNORM: return GS_RGBA;
case DXGI_FORMAT_B8G8R8A8_UNORM: return GS_BGRA;
case DXGI_FORMAT_B8G8R8X8_UNORM: return GS_BGR;
case DXGI_FORMAT_B5G5R5A1_UNORM: return GS_B5G5R5A1;
case DXGI_FORMAT_B5G6R5_UNORM: return GS_B5G6R5;

View File

@ -94,6 +94,57 @@ LRESULT WINAPI SenderWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM l
return 0;
}
bool bD3D9Hooked = false;
bool bD3D10Hooked = false;
bool bD3D101Hooked = false;
bool bD3D11Hooked = false;
bool bGLHooked = false;
bool bDirectDrawHooked = false;
inline bool AttemptToHookSomething()
{
bool bFoundSomethingToHook = false;
if(!bD3D11Hooked && InitD3D11Capture())
{
OutputDebugString(TEXT("D3D11 Present\r\n"));
bFoundSomethingToHook = true;
bD3D11Hooked = true;
}
if(!bD3D9Hooked && InitD3D9Capture())
{
OutputDebugString(TEXT("D3D9 Present\r\n"));
bFoundSomethingToHook = true;
bD3D9Hooked = true;
}
if(!bD3D101Hooked && InitD3D101Capture())
{
OutputDebugString(TEXT("D3D10.1 Present\r\n"));
bFoundSomethingToHook = true;
bD3D101Hooked = true;
}
if(!bD3D10Hooked && InitD3D10Capture())
{
OutputDebugString(TEXT("D3D10 Present\r\n"));
bFoundSomethingToHook = true;
bD3D10Hooked = true;
}
if(!bGLHooked && InitGLCapture())
{
OutputDebugString(TEXT("GL Present\r\n"));
bFoundSomethingToHook = true;
bGLHooked = true;
}
/*
if(!bDirectDrawHooked && InitDDrawCapture())
{
OutputDebugString(TEXT("DirectDraw Present\r\n"));
bFoundSomethingToHook = true;
bDirectDrawfHooked = true;
}*/
return bFoundSomethingToHook;
}
DWORD WINAPI CaptureThread(HANDLE hDllMainThread)
{
bool bSuccess = false;
@ -122,24 +173,16 @@ DWORD WINAPI CaptureThread(HANDLE hDllMainThread)
textureMutexes[1] = OpenMutex(MUTEX_ALL_ACCESS, FALSE, TEXTURE_MUTEX2);
if(textureMutexes[1])
{
if(InitD3D11Capture())
OutputDebugString(TEXT("D3D11 Present\r\n"));
if(InitD3D9Capture())
OutputDebugString(TEXT("D3D9 Present\r\n"));
if(InitD3D101Capture())
OutputDebugString(TEXT("D3D10.1 Present\r\n"));
if(InitD3D10Capture())
OutputDebugString(TEXT("D3D10 Present\r\n"));
if(InitGLCapture())
OutputDebugString(TEXT("GL Present\r\n"));
/*else if(!nitDDrawCapture())
OutputDebugString(TEXT("DirectDraw Present"));*/
while(!AttemptToHookSomething())
Sleep(50);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
AttemptToHookSomething();
}
CloseHandle(textureMutexes[1]);
@ -183,6 +226,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpBlah)
FreeD3D101Capture();
FreeD3D11Capture();*/
if(hwndReceiver)
PostMessage(hwndReceiver, RECEIVER_ENDCAPTURE, 0, 0);
if(hwndSender)
DestroyWindow(hwndSender);

View File

@ -49,6 +49,7 @@
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
AssemblerOutput="4"
WarningLevel="3"
DebugInformationFormat="4"
/>
@ -63,7 +64,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="dxgi.lib dxguid.lib d3d9.lib opengl32.lib"
AdditionalDependencies="dxguid.lib"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
@ -138,7 +139,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="dxgi.lib dxguid.lib d3d9.lib"
AdditionalDependencies="dxguid.lib"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
@ -192,7 +193,7 @@
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
Optimization="3"
EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;GRAPHICSCAPTUREHOOK_EXPORTS"
RuntimeLibrary="0"
@ -212,7 +213,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="dxgi.lib dxguid.lib d3d9.lib"
AdditionalDependencies="dxguid.lib"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
@ -269,7 +270,7 @@
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
Optimization="3"
EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;GRAPHICSCAPTUREHOOK_EXPORTS"
RuntimeLibrary="0"
@ -289,7 +290,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="dxgi.lib dxguid.lib d3d9.lib"
AdditionalDependencies="dxguid.lib"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
@ -329,6 +330,18 @@
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\D3D10.1Capture.cpp"
>
</File>
<File
RelativePath=".\D3D10Capture.cpp"
>
</File>
<File
RelativePath=".\D3D11Capture.cpp"
>
</File>
<File
RelativePath=".\D3D9Capture.cpp"
>
@ -351,6 +364,10 @@
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\DXGIStuff.h"
>
</File>
<File
RelativePath="..\GlobalCaptureStuff.h"
>

View File

@ -23,9 +23,9 @@ BOOL WINAPI InjectLibrary(HANDLE hProcess, CTSTR lpDLL)
{
UPARAM procAddress;
DWORD dwTemp,dwSize;
LPVOID lpStr;
LPVOID lpStr = NULL;
BOOL bWorks,bRet=0;
HANDLE hThread;
HANDLE hThread = NULL;
SIZE_T writtenSize;
if(!hProcess) return 0;
@ -129,8 +129,11 @@ void GraphicsCaptureSource::NewCapture(LPVOID address)
if(!hProcess)
return;
API->EnterSceneMutex();
if(capture)
{
capture->Destroy();
delete capture;
capture = NULL;
}
@ -138,6 +141,7 @@ void GraphicsCaptureSource::NewCapture(LPVOID address)
CaptureInfo info;
if(!ReadProcessMemory(hProcess, address, &info, sizeof(info), NULL))
{
API->LeaveSceneMutex();
AppWarning(TEXT("GraphicsCaptureSource::NewCapture: Could not read capture info from target process"));
return;
}
@ -150,28 +154,38 @@ void GraphicsCaptureSource::NewCapture(LPVOID address)
capture = new SharedTexCapture;*/
else
{
API->LeaveSceneMutex();
AppWarning(TEXT("GraphicsCaptureSource::NewCapture: wtf, bad data from the target process"));
return;
}
if(!capture->Init(hProcess, hwndTarget, info))
{
capture->Destroy();
delete capture;
capture = NULL;
}
API->LeaveSceneMutex();
}
void GraphicsCaptureSource::EndCapture()
{
API->EnterSceneMutex();
capture->Destroy();
delete capture;
capture = NULL;
bErrorAcquiring = false;
bCapturing = false;
if(warningID)
{
API->RemoveStreamInfo(warningID);
warningID = 0;
}
API->LeaveSceneMutex();
}
bool GraphicsCaptureSource::FindSenderWindow()
@ -225,6 +239,8 @@ void GraphicsCaptureSource::AttemptCapture()
if(!warningID)
warningID = API->AddStreamInfo(Str("Sources.SoftwareCaptureSource.WindowNotFound"), StreamInfoPriority_High);
bCapturing = false;
return;
}
@ -294,6 +310,7 @@ void GraphicsCaptureSource::EndScene()
if(capture)
{
capture->Destroy();
delete capture;
capture = NULL;
}
@ -357,12 +374,13 @@ void GraphicsCaptureSource::Render(const Vect2 &pos, const Vect2 &size)
outPos.x = (float)round(outPos.x);
outPos.y = (float)round(outPos.y);
outSize.x = (float)round(size.x);
outSize.y = (float)round(size.y);
outSize.x = (float)round(outSize.x);
outSize.y = (float)round(outSize.y);
}
outPos += pos;
lr += outSize;
lr += outPos;
outPos += pos;
if(bFlip)
DrawSprite(tex, 0xFFFFFFFF, outPos.x, lr.y, lr.x, outPos.y);
@ -382,9 +400,10 @@ void GraphicsCaptureSource::Render(const Vect2 &pos, const Vect2 &size)
DrawSprite(tex, 0xFFFFFFFF, center.x-texHalfSize.x, center.y+texHalfSize.y, center.x+texHalfSize.x, center.y-texHalfSize.y);
else
DrawSprite(tex, 0xFFFFFFFF, center.x-texHalfSize.x, center.y-texHalfSize.y, center.x+texHalfSize.x, center.y+texHalfSize.y);
capture->UnlockTexture();
}
capture->UnlockTexture();
BlendFunction(GS_BLEND_SRCALPHA, GS_BLEND_INVSRCALPHA);
}
}

View File

@ -20,14 +20,30 @@
#include "GraphicsCapture.h"
MemoryCapture::~MemoryCapture()
void MemoryCapture::Destroy()
{
bInitialized = false;
if(hMemoryMutex)
OSEnterMutex(hMemoryMutex);
copyData = NULL;
textureBuffers[0] = NULL;
textureBuffers[1] = NULL;
delete texture;
texture = NULL;
if(sharedMemory)
UnmapViewOfFile(sharedMemory);
if(hFileMap)
CloseHandle(hFileMap);
delete texture;
if(hMemoryMutex)
{
OSLeaveMutex(hMemoryMutex);
OSCloseMutex(hMemoryMutex);
}
}
bool MemoryCapture::Init(HANDLE hProcess, HWND hwndTarget, CaptureInfo &info)
@ -54,6 +70,13 @@ bool MemoryCapture::Init(HANDLE hProcess, HWND hwndTarget, CaptureInfo &info)
return false;
}
hMemoryMutex = OSCreateMutex();
if(!hMemoryMutex)
{
AppWarning(TEXT("MemoryCapture::Init: Could not create memory mutex"));
return false;
}
copyData = (MemoryCopyData*)sharedMemory;
textureBuffers[0] = sharedMemory+copyData->texture1Offset;
textureBuffers[1] = sharedMemory+copyData->texture2Offset;
@ -65,12 +88,17 @@ bool MemoryCapture::Init(HANDLE hProcess, HWND hwndTarget, CaptureInfo &info)
return false;
}
bInitialized = true;
return true;
}
Texture* MemoryCapture::LockTexture()
{
LPVOID address = NULL;
if(!bInitialized || !copyData || !texture)
return NULL;
OSEnterMutex(hMemoryMutex);
curTexture = copyData->lastRendered;
@ -107,17 +135,18 @@ Texture* MemoryCapture::LockTexture()
SSECopy(curOutput, curInput, bestPitch);
}
}
texture->Unmap();
}
ReleaseMutex(hMutex);
}
hMutex = NULL;
}
OSLeaveMutex(hMemoryMutex);
return texture;
}
void MemoryCapture::UnlockTexture()
{
texture->Unmap();
}

View File

@ -22,6 +22,8 @@
class MemoryCapture : public GraphicsCaptureMethod
{
HANDLE hMemoryMutex;
HANDLE hFileMap;
LPBYTE sharedMemory;
@ -34,11 +36,13 @@ class MemoryCapture : public GraphicsCaptureMethod
Texture *texture;
HANDLE hMutex;
bool bInitialized;
UINT height;
DWORD curTexture;
public:
~MemoryCapture();
void Destroy();
virtual bool Init(HANDLE hProcess, HWND hwndTarget, CaptureInfo &info);

View File

@ -89,6 +89,8 @@ public:
virtual void SetStreamInfoPriority(UINT infoID, StreamInfoPriority priority)=0;
virtual void RemoveStreamInfo(UINT infoID)=0;
virtual bool UseMultithreadedOptimizations() const=0;
inline bool SSE2Available() {return bSSE2Availabe;}
inline ImageSource* GetSceneImageSource(CTSTR lpImageSource)

View File

@ -120,7 +120,8 @@ BASE_EXPORT void STDCALL OSFreeLibrary(HANDLE hLibrary);
BASE_EXPORT void STDCALL OSSleep(DWORD dwMSeconds);
BASE_EXPORT UINT STDCALL OSGetProcessorCount();
BASE_EXPORT int STDCALL OSGetTotalCores();
BASE_EXPORT int STDCALL OSGetLogicalCores();
BASE_EXPORT HANDLE STDCALL OSCreateThread(XTHREAD lpThreadFunc, LPVOID param);
BASE_EXPORT BOOL STDCALL OSWaitForThread(HANDLE hThread, LPDWORD ret);
BASE_EXPORT BOOL STDCALL OSCloseThread(HANDLE hThread);

View File

@ -37,6 +37,8 @@ LARGE_INTEGER clockFreq, startTime;
LONGLONG prevElapsedTime;
DWORD startTick;
int coreCount = 1, logicalCores = 1;
void STDCALL InputProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
void STDCALL ResetCursorClip();
@ -46,6 +48,22 @@ BOOL bHidingCursor = 0;
HWND hwndMainAppWindow = NULL;
// Helper function to count set bits in the processor mask.
DWORD CountSetBits(ULONG_PTR bitMask)
{
DWORD LSHIFT = sizeof(ULONG_PTR)*8 - 1;
DWORD bitSetCount = 0;
ULONG_PTR bitTest = (ULONG_PTR)1 << LSHIFT;
DWORD i;
for (i = 0; i <= LSHIFT; ++i)
{
bitSetCount += ((bitMask & bitTest)?1:0);
bitTest/=2;
}
return bitSetCount;
}
void STDCALL OSInit()
{
@ -57,6 +75,38 @@ void STDCALL OSInit()
QueryPerformanceCounter(&startTime);
startTick = GetTickCount();
prevElapsedTime = 0;
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION pInfo = NULL, pTemp = NULL;
DWORD dwLen = 0;
if(!GetLogicalProcessorInformation(pInfo, &dwLen))
{
if(GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
pInfo = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(dwLen);
if(GetLogicalProcessorInformation(pInfo, &dwLen))
{
pTemp = pInfo;
DWORD dwNum = dwLen/sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
coreCount = 0;
logicalCores = 0;
for(UINT i=0; i<dwNum; i++)
{
if(pTemp->Relationship == RelationProcessorCore)
{
coreCount++;
logicalCores += CountSetBits(pTemp->ProcessorMask);
}
pTemp++;
}
}
free(pInfo);
}
}
}
void STDCALL OSExit()
@ -122,6 +172,17 @@ HANDLE STDCALL OSFindFirstFile(CTSTR lpFileName, OSFindData &findData)
return hFind;
}
int STDCALL OSGetTotalCores()
{
return coreCount;
}
int STDCALL OSGetLogicalCores()
{
return logicalCores;
}
BOOL STDCALL OSFindNextFile(HANDLE hFind, OSFindData &findData)
{
WIN32_FIND_DATA wfd;

View File

@ -202,7 +202,9 @@ bool MMDeviceAudioSource::Initialize(bool bMic, CTSTR lpID)
if(inputSamplesPerSec != 44100)
{
int errVal;
resampler = src_new(SRC_SINC_FASTEST, 2, &errVal);//SRC_SINC_FASTEST//SRC_ZERO_ORDER_HOLD
int converterType = AppConfig->GetInt(TEXT("Audio"), TEXT("UseHighQualityResampling"), FALSE) ? SRC_SINC_FASTEST : SRC_LINEAR;
resampler = src_new(converterType, 2, &errVal);//SRC_SINC_FASTEST//SRC_ZERO_ORDER_HOLD
if(!resampler)
{
CrashError(TEXT("MMDeviceAudioSource::Initialize(%d): Could not initiate resampler"), (BOOL)bMic);

View File

@ -97,7 +97,9 @@ void LogSystemStats()
BYTE cpuExtModel = (cpuInfo[0]>>17) & 0xF;
BYTE cpuExtFamily = (cpuInfo[0]>>21) & 0xFF;
Log(TEXT("stepping id: %u, model %u, family %u, type %u, extmodel %u, extfamily %u"), cpuSteppingID, cpuModel, cpuFamily, cpuType, cpuExtModel, cpuExtFamily);
BYTE cpuHTT = (cpuInfo[3]>>28) & 1;
Log(TEXT("stepping id: %u, model %u, family %u, type %u, extmodel %u, extfamily %u, HTT %u, logical cores %u, total cores %u"), cpuSteppingID, cpuModel, cpuFamily, cpuType, cpuExtModel, cpuExtFamily, cpuHTT, OSGetLogicalCores(), OSGetTotalCores());
LogVideoCardStats();
}

View File

@ -62,7 +62,7 @@ extern OBS *App;
extern TCHAR lpAppDataPath[MAX_PATH];
#define OBS_VERSION 0x000429
#define OBS_VERSION_STRING_ANSI "Open Broadcaster Software v0.43a [test version 1]"
#define OBS_VERSION_STRING_ANSI "Open Broadcaster Software v0.43a [test version 2]"
#define OBS_VERSION_STRING TEXT(OBS_VERSION_STRING_ANSI)
#define OBS_WINDOW_CLASS TEXT("OBSWindowClass")

View File

@ -423,6 +423,8 @@ public:
virtual void SetStreamInfo(UINT infoID, CTSTR lpInfo) {App->SetStreamInfo(infoID, lpInfo);}
virtual void SetStreamInfoPriority(UINT infoID, StreamInfoPriority priority) {App->SetStreamInfoPriority(infoID, priority);}
virtual void RemoveStreamInfo(UINT infoID) {App->RemoveStreamInfo(infoID);}
virtual bool UseMultithreadedOptimizations() const {return App->bUseMultithreadedOptimizations;}
};
@ -1143,6 +1145,9 @@ void OBS::Start()
outputCX = scaleCX & 0xFFFFFFFC;
outputCY = scaleCY & 0xFFFFFFFE;
bUseMultithreadedOptimizations = AppConfig->GetInt(TEXT("General"), TEXT("UseMultithreadedOptimizations"), TRUE) != 0;
Log(TEXT(" Multithreaded optimizations: %s"), (CTSTR)(bUseMultithreadedOptimizations ? TEXT("On") : TEXT("Off")));
//------------------------------------------------------------------
Log(TEXT(" Base resolution: %ux%u"), baseCX, baseCY);
@ -1728,13 +1733,23 @@ struct Convert444Data
{
LPBYTE input;
LPBYTE output[3];
bool bKillThread;
HANDLE hSignalConvert, hSignalComplete;
int width, height, pitch, startY, endY;
};
DWORD STDCALL Convert444Thread(Convert444Data *data)
{
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
Convert444to420(data->input, data->width, data->pitch, data->height, data->startY, data->endY, data->output, App->SSE2Available());
do
{
WaitForSingleObject(data->hSignalConvert, INFINITE);
if(data->bKillThread) break;
Convert444to420(data->input, data->width, data->pitch, data->height, data->startY, data->endY, data->output, App->SSE2Available());
SetEvent(data->hSignalComplete);
}while(!data->bKillThread);
return 0;
}
@ -1796,27 +1811,29 @@ void OBS::MainCaptureLoop()
float bpsTime = 0.0f;
double lastStrain = 0.0f;
UINT numProcessors = OSGetProcessorCount();
HANDLE *h420Threads = (HANDLE*)Allocate(sizeof(HANDLE)*numProcessors);
Convert444Data *convertInfo = (Convert444Data*)Allocate(sizeof(Convert444Data)*numProcessors);
int numThreads = MAX(OSGetTotalCores()-2, 1);
HANDLE *h420Threads = (HANDLE*)Allocate(sizeof(HANDLE)*numThreads);
Convert444Data *convertInfo = (Convert444Data*)Allocate(sizeof(Convert444Data)*numThreads);
zero(h420Threads, sizeof(HANDLE)*numProcessors);
zero(convertInfo, sizeof(Convert444Data)*numProcessors);
zero(h420Threads, sizeof(HANDLE)*numThreads);
zero(convertInfo, sizeof(Convert444Data)*numThreads);
for(UINT i=0; i<numProcessors; i++)
for(int i=0; i<numThreads; i++)
{
convertInfo[i].width = outputCX;
convertInfo[i].height = outputCY;
convertInfo[i].hSignalConvert = CreateEvent(NULL, FALSE, FALSE, NULL);
convertInfo[i].hSignalComplete = CreateEvent(NULL, FALSE, FALSE, NULL);
if(i == 0)
convertInfo[i].startY = 0;
else
convertInfo[i].startY = convertInfo[i-1].endY;
if(i == (numProcessors-1))
if(i == (numThreads-1))
convertInfo[i].endY = outputCY;
else
convertInfo[i].endY = ((outputCY/numProcessors)*(i+1)) & 0xFFFFFFFE;
convertInfo[i].endY = ((outputCY/numThreads)*(i+1)) & 0xFFFFFFFE;
}
DWORD fpsTimeNumerator = 1000-(frameTime*fps);
@ -1827,7 +1844,18 @@ void OBS::MainCaptureLoop()
bool bFirstFrame = true;
bool bFirst420Encode = true;
bool bUseThreaded420 = OSGetProcessorCount() > 1 && !bUsing444;
bool bUseThreaded420 = bUseMultithreadedOptimizations && (OSGetTotalCores() > 1) && !bUsing444;
List<HANDLE> completeEvents;
if(bUseThreaded420)
{
for(int i=0; i<numThreads; i++)
{
h420Threads[i] = OSCreateThread((XTHREAD)Convert444Thread, convertInfo+i);
completeEvents << convertInfo[i].hSignalComplete;
}
}
while(bRunning)
{
@ -2104,12 +2132,7 @@ void OBS::MainCaptureLoop()
if(!bFirst420Encode && bUseThreaded420)
{
WaitForMultipleObjects(numProcessors, h420Threads, TRUE, INFINITE);
for(UINT i=0; i<numProcessors; i++)
{
CloseHandle(h420Threads[i]);
h420Threads[i] = NULL;
}
WaitForMultipleObjects(completeEvents.Num(), completeEvents.Array(), TRUE, INFINITE);
copyTexture->Unmap(0);
}
@ -2135,15 +2158,18 @@ void OBS::MainCaptureLoop()
{
x264_picture_t &newPicOut = outPics[curCopyTexture];
for(UINT i=0; i<numProcessors; i++)
for(int i=0; i<numThreads; i++)
{
convertInfo[i].input = (LPBYTE)map.pData;
convertInfo[i].pitch = map.RowPitch;
convertInfo[i].output[0] = newPicOut.img.plane[0];
convertInfo[i].output[1] = newPicOut.img.plane[1];
convertInfo[i].output[2] = newPicOut.img.plane[2];
h420Threads[i] = OSCreateThread((XTHREAD)Convert444Thread, (LPVOID)(convertInfo+i));
SetEvent(convertInfo[i].hSignalConvert);
}
if(bFirst420Encode)
bFirst420Encode = bEncode = false;
}
else
{
@ -2151,9 +2177,6 @@ void OBS::MainCaptureLoop()
prevTexture->Unmap(0);
}
if(bFirst420Encode)
bFirst420Encode = bEncode = false;
profileOut;
}
else
@ -2331,19 +2354,39 @@ void OBS::MainCaptureLoop()
if(!bUsing444)
{
if(!bFirst420Encode && bUseThreaded420)
if(bUseThreaded420)
{
WaitForMultipleObjects(numProcessors, h420Threads, TRUE, INFINITE);
for(UINT i=0; i<numProcessors; i++)
for(int i=0; i<numThreads; i++)
{
if(h420Threads)
CloseHandle(h420Threads[i]);
h420Threads[i] = NULL;
if(h420Threads[i])
{
convertInfo[i].bKillThread = true;
SetEvent(convertInfo[i].hSignalConvert);
OSTerminateThread(h420Threads[i], 10000);
h420Threads[i] = NULL;
}
if(convertInfo[i].hSignalConvert)
{
CloseHandle(convertInfo[i].hSignalConvert);
convertInfo[i].hSignalConvert = NULL;
}
if(convertInfo[i].hSignalComplete)
{
CloseHandle(convertInfo[i].hSignalComplete);
convertInfo[i].hSignalComplete = NULL;
}
}
ID3D10Texture2D *copyTexture = copyTextures[curCopyTexture];
copyTexture->Unmap(0);
if(!bFirst420Encode)
{
ID3D10Texture2D *copyTexture = copyTextures[curCopyTexture];
copyTexture->Unmap(0);
}
}
x264_picture_clean(&outPics[0]);
x264_picture_clean(&outPics[1]);
}
@ -2391,10 +2434,6 @@ void OBS::MainAudioLoop()
//-----------------------------------------------
OSEnterMutex(hSoundDataMutex);
//-----------------------------------------------
float *desktopBuffer, *micBuffer;
UINT desktopAudioFrames, micAudioFrames;
@ -2510,6 +2549,8 @@ void OBS::MainAudioLoop()
DataPacket packet;
if(audioEncoder->Encode(desktopBuffer, totalFloats>>1, packet, timestamp))
{
OSEnterMutex(hSoundDataMutex);
FrameAudio *frameAudio = pendingAudioFrames.CreateNew();
frameAudio->audioData.CopyArray(packet.lpPacket, packet.size);
if(bUseSyncFix)
@ -2521,6 +2562,8 @@ void OBS::MainAudioLoop()
Log(TEXT("returned timestamp: %u, calculated timestamp: %u"), timestamp, calcTimestamp);*/
curAudioFrame++;
OSLeaveMutex(hSoundDataMutex);
}
}
@ -2528,10 +2571,6 @@ void OBS::MainAudioLoop()
if(!bRecievedFirstAudioFrame && pendingAudioFrames.Num())
bRecievedFirstAudioFrame = true;
//-----------------------------------------------
OSLeaveMutex(hSoundDataMutex);
}
for(UINT i=0; i<pendingAudioFrames.Num(); i++)

View File

@ -404,6 +404,7 @@ class OBS
String strLanguage;
bool bTestStream;
bool bUseMultithreadedOptimizations;
bool bRunning;
int renderFrameWidth, renderFrameHeight;
int borderXSize, borderYSize;

View File

@ -1508,6 +1508,11 @@ INT_PTR CALLBACK OBS::AdvancedSettingsProc(HWND hwnd, UINT message, WPARAM wPara
SendMessage(hwndToolTip, TTM_SETMAXTIPWIDTH, 0, 500);
SendMessage(hwndToolTip, TTM_SETDELAYTIME, TTDT_AUTOPOP, 14000);
//------------------------------------
bool bUseMTOptimizations = AppConfig->GetInt(TEXT("General"), TEXT("UseMultithreadedOptimizations"), TRUE) != 0;
SendMessage(GetDlgItem(hwnd, IDC_USEMULTITHREADEDOPTIMIZATIONS), BM_SETCHECK, bUseMTOptimizations ? BST_CHECKED : BST_UNCHECKED, 0);
//--------------------------------------------
HWND hwndTemp = GetDlgItem(hwnd, IDC_PRESET);
@ -1557,6 +1562,15 @@ INT_PTR CALLBACK OBS::AdvancedSettingsProc(HWND hwnd, UINT message, WPARAM wPara
//------------------------------------
bool bUseHQResampling = AppConfig->GetInt(TEXT("Audio"), TEXT("UseHighQualityResampling"), FALSE) != 0;
SendMessage(GetDlgItem(hwnd, IDC_USEHIGHQUALITYRESAMPLING), BM_SETCHECK, bUseHQResampling ? BST_CHECKED : BST_UNCHECKED, 0);
ti.lpszText = (LPWSTR)Str("Settings.Advanced.UseHighQualityResamplingTooltip");
ti.uId = (UINT_PTR)GetDlgItem(hwnd, IDC_USEHIGHQUALITYRESAMPLING);
SendMessage(hwndToolTip, TTM_ADDTOOL, 0, (LPARAM)&ti);
//------------------------------------
BOOL bUseSendBuffer = AppConfig->GetInt(TEXT("Publish"), TEXT("UseSendBuffer"), 1) != 0;
SendMessage(GetDlgItem(hwnd, IDC_USESENDBUFFER), BM_SETCHECK, bUseSendBuffer ? BST_CHECKED : BST_UNCHECKED, 0);
@ -1624,13 +1638,6 @@ INT_PTR CALLBACK OBS::AdvancedSettingsProc(HWND hwnd, UINT message, WPARAM wPara
break;
case IDC_SENDBUFFERSIZE:
if(HIWORD(wParam) == CBN_SELCHANGE)
{
ShowWindow(GetDlgItem(hwnd, IDC_INFO), SW_SHOW);
App->SetChangedSettings(true);
}
break;
case IDC_PRESET:
if(HIWORD(wParam) == CBN_SELCHANGE)
{
@ -1639,6 +1646,8 @@ INT_PTR CALLBACK OBS::AdvancedSettingsProc(HWND hwnd, UINT message, WPARAM wPara
}
break;
case IDC_USEHIGHQUALITYRESAMPLING:
case IDC_USEMULTITHREADEDOPTIMIZATIONS:
case IDC_USESYNCFIX:
if(HIWORD(wParam) == BN_CLICKED)
{
@ -1895,6 +1904,11 @@ void OBS::ApplySettings()
//--------------------------------------------------
bool bUseMTOptimizations = SendMessage(GetDlgItem(hwndCurrentSettings, IDC_USEMULTITHREADEDOPTIMIZATIONS), BM_GETCHECK, 0, 0) == BST_CHECKED;
AppConfig->SetInt(TEXT("General"), TEXT("UseMultithreadedOptimizations"), bUseMTOptimizations);
//--------------------------------------------------
BOOL bUseCustomX264Settings = SendMessage(GetDlgItem(hwndCurrentSettings, IDC_USEVIDEOENCODERSETTINGS), BM_GETCHECK, 0, 0) == BST_CHECKED;
String strCustomX264Settings = GetEditText(GetDlgItem(hwndCurrentSettings, IDC_VIDEOENCODERSETTINGS));
@ -1906,6 +1920,11 @@ void OBS::ApplySettings()
BOOL bUseVideoSyncFix = SendMessage(GetDlgItem(hwndCurrentSettings, IDC_USESYNCFIX), BM_GETCHECK, 0, 0) == BST_CHECKED;
AppConfig->SetInt (TEXT("Video Encoding"), TEXT("UseSyncFix"), bUseVideoSyncFix);
//------------------------------------
BOOL bUseHQResampling = SendMessage(GetDlgItem(hwndCurrentSettings, IDC_USEHIGHQUALITYRESAMPLING), BM_GETCHECK, 0, 0) == BST_CHECKED;
AppConfig->SetInt (TEXT("Audio"), TEXT("UseHighQualityResampling"), bUseHQResampling);
//--------------------------------------------------
/*BOOL bDisableD3DCompat = SendMessage(GetDlgItem(hwndCurrentSettings, IDC_DISABLED3DCOMPATIBILITY), BM_GETCHECK, 0, 0) == BST_CHECKED;

View File

@ -0,0 +1,32 @@
/********************************************************************************
Copyright (C) 2012 Hugh Bailey <obs.jim@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
********************************************************************************/
#include "Main.h"
/*
class TextOutputSource : public ImageSource
{
String strText;
String strFile;
Texture *texture;
public:
};
*/

View File

@ -74,7 +74,6 @@ Plugins.Filename "File name:"
Reconnecting.Retrying "Could not reconnect. Retrying"
RenderView.EnableView "Enable View"
RenderView.ShowFPS "Show FPS"
Scene.Hotkey "Scene Hotkey"
Scene.MissingSources "Was unable to load all image sources due to either invalid settings or missing plugins"
@ -84,7 +83,6 @@ Scene.Hotkey.Hotkey "Hotkey:"
Settings.Advanced "Advanced"
Settings.Audio "Audio"
Settings.DashboardLink "Dashboard Link (if any):"
Settings.Encoding "Encoding"
Settings.General "General"
Settings.Info "These settings won't be applied until the next time you begin streaming."
@ -93,18 +91,19 @@ Settings.SaveChangesPrompt "Would you like to save and apply your changes?"
Settings.SaveChangesTitle "Apply settings?"
Settings.Video "Video"
Settings.Advanced.DisableD3DCompatibilityMode "Disable Direct3D Compatibility Mode"
Settings.Advanced.DisableD3DCompatibilityModeTooltip "Disables the use of the Direct3D GPU compatibility mode"
Settings.Advanced.Network "Network"
Settings.Advanced.SendBufferSize "Send Buffer Size:"
Settings.Advanced.UseSendBuffer "Use Send Buffer"
Settings.Advanced.UseSendBufferTooltip "The send buffer causes all network data to be buffered up to specific packet sizes before sending. Using this greatly increases network throughput, but will make the stream a bit more delayed.\r\n\r\nRecommended: On, at 32768"
Settings.Advanced.UseSyncFix "Use Video/Audio Sync Fix"
Settings.Advanced.UseSyncFixTooltip "In rare cases, certain CPUs and motherboards can have timing bugs that can cause sync issues in the stream. This fix calculates timestamps instead of using CPU timing. It's pretty accurate, but just make sure to set your maximum FPS close to what you capture at to prevent any potential frame jitter."
Settings.Advanced.VideoEncoderCPUTradeoff "x264 CPU Preset:"
Settings.Advanced.VideoEncoderCPUTradeoffToolTip "Setting this value higher reduces CPU usage by sacrificing certain aspects of quality. On the other hand, setting this value lower increases quality at the cost of more CPU.\r\n\r\nRecommended: Very Fast"
Settings.Advanced.VideoEncoderSettings "Custom x264 Encoder Settings"
Settings.Advanced.VideoEncoderSettingsTooltip "This allows you to set custom x264 encoder settings. In the form of [parameter]=[value] (e.g. \"vbv-maxrate=1000 vbv-bufsize=1000\")."
Settings.Advanced.Network "Network"
Settings.Advanced.SendBufferSize "Send Buffer Size:"
Settings.Advanced.UseHighQualityResampling "Use Higher Quality Resampling"
Settings.Advanced.UseHighQualityResamplingTooltip "When the audio subsystem is forced to resample, uses sinc interpolation instead of linear interpolation to resample sound. Requires a little bit more CPU."
Settings.Advanced.UseMultithreadedOptimizations "Use Multithreaded Optimizations"
Settings.Advanced.UseSendBuffer "Use Send Buffer"
Settings.Advanced.UseSendBufferTooltip "The send buffer causes all network data to be buffered up to specific packet sizes before sending. Using this greatly increases network throughput, but will make the stream a bit more delayed.\r\n\r\nRecommended: On, at 32768"
Settings.Advanced.UseSyncFix "Use Video/Audio Sync Fix"
Settings.Advanced.UseSyncFixTooltip "In rare cases, certain CPUs and motherboards can have timing bugs that can cause sync issues in the stream. This fix calculates timestamps instead of using CPU timing. It's pretty accurate, but just make sure to set your maximum FPS close to what you capture at to prevent any potential frame jitter."
Settings.Advanced.VideoEncoderCPUTradeoff "x264 CPU Preset:"
Settings.Advanced.VideoEncoderCPUTradeoffToolTip "Setting this value higher reduces CPU usage by sacrificing certain aspects of quality. On the other hand, setting this value lower increases quality at the cost of more CPU.\r\n\r\nRecommended: Very Fast"
Settings.Advanced.VideoEncoderSettings "Custom x264 Encoder Settings"
Settings.Advanced.VideoEncoderSettingsTooltip "This allows you to set custom x264 encoder settings. In the form of [parameter]=[value] (e.g. \"vbv-maxrate=1000 vbv-bufsize=1000\")."
Settings.Audio.Device "Microphone/Auxilary Audio Device:"
Settings.Audio.ForceMicMono "Force Microphone/Auxilary to Mono:"

View File

@ -74,7 +74,6 @@ Plugins.Filename "ファイル名:"
Reconnecting.Retrying "再接続できませんでした。再び試みます"
RenderView.EnableView "ビューを有効にする"
RenderView.ShowFPS "FPSを表示する"
Scene.Hotkey "シーンのホットキー"
Scene.MissingSources "すべてソースは作成できませんでした"
@ -92,10 +91,11 @@ Settings.SaveChangesPrompt "設定を保存しますか?"
Settings.SaveChangesTitle "保存しますか?"
Settings.Video "動画"
Settings.Advanced.DisableD3DCompatibilityMode "D3D互換性モードを無効にする"
Settings.Advanced.Network "ネットワーク"
Settings.Advanced.SendBufferSize "送信バッファー大きさ:"
Settings.Advanced.UseSendBuffer "送信バッファーを使う"
Settings.Advanced.UseHighQualityResampling "より高品質のリサンプリングを使用"
Settings.Advanced.UseMultithreadedOptimizations "マルチスレッド最適化を使用"
Settings.Advanced.UseSendBuffer "送信バッファーを使用"
Settings.Advanced.UseSyncFix "サウンドと動画の同期解決"
Settings.Advanced.VideoEncoderCPUTradeoff "x264のCPUプリセット:"
Settings.Advanced.VideoEncoderCPUTradeoffTooltip "CPUの利用を調整するための設定です。「superfast」や「ultrafast」を使ってはCPU使用を減らすために品質を犠牲にするのです。一方、「faster」や「fast」以下はCPU利用を増やしますことで品質を優先しようとします。\r\n\r\n推奨:「veryfast」"