Added GPU based deinterlacing and refactored interlacing code

Added deinterlacing modes:
- Blend (GPU)
- Linear (GPU)
- Yadif (GPU)
each with source framerate and double source framerate mode.
Also added GPU based Retro deinterlacing
This commit is contained in:
palana 2013-07-09 01:20:26 +02:00
parent 796a5b43c2
commit 7c29a61324
16 changed files with 801 additions and 134 deletions

View File

@ -30,6 +30,19 @@ extern "C" __declspec(dllexport) CTSTR GetPluginDescription();
LocaleStringLookup *pluginLocale = NULL; LocaleStringLookup *pluginLocale = NULL;
HINSTANCE hinstMain = NULL; HINSTANCE hinstMain = NULL;
extern DeinterlacerConfig deinterlacerConfigs[DEINTERLACING_TYPE_LAST];
CTSTR deinterlacerLocalizations[DEINTERLACING_TYPE_LAST] = {
TEXT("DeinterlacingType.None"),
TEXT("DeinterlacingType.Discard"),
TEXT("DeinterlacingType.Retro"),
TEXT("DeinterlacingType.Blend"),
TEXT("DeinterlacingType.Blend2x"),
TEXT("DeinterlacingType.Linear"),
TEXT("DeinterlacingType.Linear2x"),
TEXT("DeinterlacingType.Yadif"),
TEXT("DeinterlacingType.Yadif2x"),
TEXT("DeinterlacingType.Debug")
};
#define DSHOW_CLASSNAME TEXT("DeviceCapture") #define DSHOW_CLASSNAME TEXT("DeviceCapture")
@ -987,7 +1000,7 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
static bool bSelectingColor = false; static bool bSelectingColor = false;
static bool bMouseDown = false, bAudioDevicesPresent = true; static bool bMouseDown = false, bAudioDevicesPresent = true;
static ColorSelectionData colorData; static ColorSelectionData colorData;
static BYTE deinterlacingType; static DeinterlacerConfig deinterlacingConfig;
switch(message) switch(message)
{ {
@ -1021,13 +1034,13 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
int gammaVal = configData->data->GetInt(TEXT("gamma"), 100); int gammaVal = configData->data->GetInt(TEXT("gamma"), 100);
HWND hwndTemp = GetDlgItem(hwnd, IDC_GAMMA2); HWND hwndTemp = GetDlgItem(hwnd, IDC_GAMMA);
SendMessage(hwndTemp, TBM_CLEARTICS, FALSE, 0); SendMessage(hwndTemp, TBM_CLEARTICS, FALSE, 0);
SendMessage(hwndTemp, TBM_SETRANGE, FALSE, MAKELPARAM(50, 175)); SendMessage(hwndTemp, TBM_SETRANGE, FALSE, MAKELPARAM(50, 175));
SendMessage(hwndTemp, TBM_SETTIC, 0, 100); SendMessage(hwndTemp, TBM_SETTIC, 0, 100);
SendMessage(hwndTemp, TBM_SETPOS, TRUE, gammaVal); SendMessage(hwndTemp, TBM_SETPOS, TRUE, gammaVal);
SetSliderText(hwnd, IDC_GAMMA2, IDC_GAMMAVAL); SetSliderText(hwnd, IDC_GAMMA, IDC_GAMMAVAL);
//------------------------------------------ //------------------------------------------
@ -1037,17 +1050,58 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
UINT cy = configData->data->GetInt(TEXT("resolutionHeight")); UINT cy = configData->data->GetInt(TEXT("resolutionHeight"));
UINT64 frameInterval = configData->data->GetInt(TEXT("frameInterval")); UINT64 frameInterval = configData->data->GetInt(TEXT("frameInterval"));
//------------------------------------------
deinterlacingConfig.type = configData->data->GetInt(TEXT("deinterlacingType"));
deinterlacingConfig.fieldOrder = configData->data->GetInt(TEXT("deinterlacingFieldOrder"));
deinterlacingConfig.processor = configData->data->GetInt(TEXT("deinterlacingProcessor"));
if(deinterlacingConfig.type >= DEINTERLACING_TYPE_LAST)
deinterlacingConfig.type = DEINTERLACING_NONE;
hwndTemp = GetDlgItem(hwnd, IDC_DEINTERLACELIST); hwndTemp = GetDlgItem(hwnd, IDC_DEINTERLACELIST);
// Populate deinterlacing type list like this, since there's only one for now. // Populate deinterlacing type list
// Actually, there's more than one, but uhh... for(size_t i = 0; i < DEINTERLACING_TYPE_LAST; i++)
SendMessage(hwndTemp, CB_ADDSTRING, 0, (LPARAM)pluginLocale->LookupString(L"DeinterlacingType.None")); {
SendMessage(hwndTemp, CB_ADDSTRING, 0, (LPARAM)pluginLocale->LookupString(L"DeinterlacingType.Discard")); #ifndef _DEBUG
SendMessage(hwndTemp, CB_ADDSTRING, 0, (LPARAM)pluginLocale->LookupString(L"DeinterlacingType.RetroTFF")); if(i == DEINTERLACING__DEBUG)
SendMessage(hwndTemp, CB_ADDSTRING, 0, (LPARAM)pluginLocale->LookupString(L"DeinterlacingType.RetroBFF")); continue;
#endif
SendMessage(hwndTemp, CB_ADDSTRING, 0, (LPARAM)pluginLocale->LookupString(deinterlacerLocalizations[i]));
deinterlacingType = configData->data->GetInt(TEXT("deinterlacingType")); DeinterlacerConfig& config = deinterlacerConfigs[i];
SendMessage(hwndTemp, CB_SETCURSEL, deinterlacingType, 0); if(deinterlacingConfig.type != config.type)
continue;
const int deintProcBoth = (DEINTERLACING_PROCESSOR_CPU | DEINTERLACING_PROCESSOR_GPU);
HWND checkbox = GetDlgItem(hwnd, IDC_GPUDEINT);
EnableWindow(checkbox, config.processor == deintProcBoth);
if(config.processor != deintProcBoth && deinterlacingConfig.processor != config.processor)
{
configData->data->SetInt(TEXT("deinterlacingGPU"), config.processor);
deinterlacingConfig.processor = config.processor;
}
Button_SetCheck(checkbox, deinterlacingConfig.processor == DEINTERLACING_PROCESSOR_GPU);
const int deintFieldsBoth = (FIELD_ORDER_TFF | FIELD_ORDER_BFF);
HWND tff = GetDlgItem(hwnd, IDC_TFF),
bff = GetDlgItem(hwnd, IDC_BFF);
if(config.fieldOrder != deintFieldsBoth && deinterlacingConfig.fieldOrder != config.fieldOrder)
{
configData->data->SetInt(TEXT("deinterlacingFieldOrder"), config.fieldOrder);
deinterlacingConfig.fieldOrder = config.fieldOrder;
}
Button_SetCheck(tff, deinterlacingConfig.fieldOrder == FIELD_ORDER_TFF);
Button_SetCheck(bff, deinterlacingConfig.fieldOrder == FIELD_ORDER_BFF);
EnableWindow(tff, config.fieldOrder & FIELD_ORDER_TFF);
EnableWindow(bff, config.fieldOrder & FIELD_ORDER_BFF);
}
SendMessage(hwndTemp, CB_SETCURSEL, deinterlacingConfig.type, 0);
//------------------------------------------
BOOL bCustomResolution = configData->data->GetInt(TEXT("customResolution")); BOOL bCustomResolution = configData->data->GetInt(TEXT("customResolution"));
SendMessage(GetDlgItem(hwnd, IDC_CUSTOMRESOLUTION), BM_SETCHECK, bCustomResolution ? BST_CHECKED : BST_UNCHECKED, 0); SendMessage(GetDlgItem(hwnd, IDC_CUSTOMRESOLUTION), BM_SETCHECK, bCustomResolution ? BST_CHECKED : BST_UNCHECKED, 0);
@ -1246,9 +1300,9 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
case WM_HSCROLL: case WM_HSCROLL:
{ {
if(GetDlgCtrlID((HWND)lParam) == IDC_GAMMA2) if(GetDlgCtrlID((HWND)lParam) == IDC_GAMMA)
{ {
int gamma = SetSliderText(hwnd, IDC_GAMMA2, IDC_GAMMAVAL); int gamma = SetSliderText(hwnd, IDC_GAMMA, IDC_GAMMAVAL);
ConfigDialogData *info = (ConfigDialogData*)GetWindowLongPtr(hwnd, DWLP_USER); ConfigDialogData *info = (ConfigDialogData*)GetWindowLongPtr(hwnd, DWLP_USER);
ImageSource *source = API->GetSceneImageSource(info->lpName); ImageSource *source = API->GetSceneImageSource(info->lpName);
@ -1448,7 +1502,37 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
case IDC_DEINTERLACELIST: case IDC_DEINTERLACELIST:
if(HIWORD(wParam) == CBN_SELCHANGE) if(HIWORD(wParam) == CBN_SELCHANGE)
{ {
deinterlacingType = (BYTE)SendMessage(GetDlgItem(hwnd, IDC_DEINTERLACELIST), CB_GETCURSEL, 0, 0); ConfigDialogData *configData = (ConfigDialogData*)GetWindowLongPtr(hwnd, DWLP_USER);;
int confId = (int)SendMessage(GetDlgItem(hwnd, IDC_DEINTERLACELIST), CB_GETCURSEL, 0, 0);
deinterlacingConfig.type = configData->data->GetInt(TEXT("deinterlacingType"));
deinterlacingConfig.fieldOrder = configData->data->GetInt(TEXT("deinterlacingFieldOrder"));
deinterlacingConfig.processor = configData->data->GetInt(TEXT("deinterlacingGPU"));
if(deinterlacingConfig.type >= DEINTERLACING_TYPE_LAST)
deinterlacingConfig.type = DEINTERLACING_NONE;
DeinterlacerConfig& config = deinterlacerConfigs[confId];
const int deintProcBoth = (DEINTERLACING_PROCESSOR_CPU | DEINTERLACING_PROCESSOR_GPU);
HWND checkbox = GetDlgItem(hwnd, IDC_GPUDEINT);
EnableWindow(checkbox, config.processor == deintProcBoth);
if(config.processor != deintProcBoth && deinterlacingConfig.processor != config.processor)
deinterlacingConfig.processor = config.processor;
Button_SetCheck(checkbox, deinterlacingConfig.processor == DEINTERLACING_PROCESSOR_GPU);
const int deintFieldsBoth = (FIELD_ORDER_TFF | FIELD_ORDER_BFF);
HWND tff = GetDlgItem(hwnd, IDC_TFF),
bff = GetDlgItem(hwnd, IDC_BFF);
if(config.fieldOrder != deintFieldsBoth && deinterlacingConfig.fieldOrder != config.fieldOrder)
deinterlacingConfig.fieldOrder = config.fieldOrder;
else if(deinterlacingConfig.fieldOrder != config.fieldOrder && (config.fieldOrder & deinterlacingConfig.fieldOrder) == 0)
deinterlacingConfig.fieldOrder = config.fieldOrder & FIELD_ORDER_TFF ? FIELD_ORDER_TFF : FIELD_ORDER_BFF;
Button_SetCheck(tff, deinterlacingConfig.fieldOrder == FIELD_ORDER_TFF);
Button_SetCheck(bff, deinterlacingConfig.fieldOrder == FIELD_ORDER_BFF);
EnableWindow(tff, config.fieldOrder & FIELD_ORDER_TFF);
EnableWindow(bff, config.fieldOrder & FIELD_ORDER_BFF);
} }
break; break;
@ -1878,7 +1962,12 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
BOOL bCustomResolution = SendMessage(GetDlgItem(hwnd, IDC_CUSTOMRESOLUTION), BM_GETCHECK, 0, 0) == BST_CHECKED; BOOL bCustomResolution = SendMessage(GetDlgItem(hwnd, IDC_CUSTOMRESOLUTION), BM_GETCHECK, 0, 0) == BST_CHECKED;
BOOL bUsePointFiltering = SendMessage(GetDlgItem(hwnd, IDC_POINTFILTERING), BM_GETCHECK, 0, 0) == BST_CHECKED; BOOL bUsePointFiltering = SendMessage(GetDlgItem(hwnd, IDC_POINTFILTERING), BM_GETCHECK, 0, 0) == BST_CHECKED;
deinterlacingType = (BYTE)SendMessage(GetDlgItem(hwnd, IDC_DEINTERLACELIST), CB_GETCURSEL, 0, 0); int deintId = (int)SendMessage(GetDlgItem(hwnd, IDC_DEINTERLACELIST), CB_GETCURSEL, 0, 0);
deinterlacingConfig = deinterlacerConfigs[deintId];
bool tff = SendMessage(GetDlgItem(hwnd, IDC_TFF), BM_GETCHECK, 0, 0) == BST_CHECKED,
bff = SendMessage(GetDlgItem(hwnd, IDC_BFF), BM_GETCHECK, 0, 0) == BST_CHECKED;
deinterlacingConfig.fieldOrder = tff ? FIELD_ORDER_TFF : (bff ? FIELD_ORDER_BFF : FIELD_ORDER_NONE);
deinterlacingConfig.processor = SendMessage(GetDlgItem(hwnd, IDC_GPUDEINT), BM_GETCHECK, 0, 0) == BST_CHECKED ? DEINTERLACING_PROCESSOR_GPU : DEINTERLACING_PROCESSOR_CPU;
configData->data->SetString(TEXT("device"), strDevice); configData->data->SetString(TEXT("device"), strDevice);
configData->data->SetString(TEXT("deviceName"), configData->deviceNameList[deviceID]); configData->data->SetString(TEXT("deviceName"), configData->deviceNameList[deviceID]);
@ -1887,12 +1976,16 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
configData->data->SetInt(TEXT("customResolution"), bCustomResolution); configData->data->SetInt(TEXT("customResolution"), bCustomResolution);
configData->data->SetInt(TEXT("resolutionWidth"), resolution.cx); configData->data->SetInt(TEXT("resolutionWidth"), resolution.cx);
configData->data->SetInt(TEXT("resolutionHeight"), resolution.cy); configData->data->SetInt(TEXT("resolutionHeight"), resolution.cy);
configData->data->SetInt(TEXT("deinterlacingType"), deinterlacingType);
configData->data->SetInt(TEXT("frameInterval"), UINT(frameInterval)); configData->data->SetInt(TEXT("frameInterval"), UINT(frameInterval));
configData->data->SetInt(TEXT("flipImage"), bFlip); configData->data->SetInt(TEXT("flipImage"), bFlip);
configData->data->SetInt(TEXT("flipImageHorizontal"), bFlipHorizontal); configData->data->SetInt(TEXT("flipImageHorizontal"), bFlipHorizontal);
configData->data->SetInt(TEXT("usePointFiltering"), bUsePointFiltering); configData->data->SetInt(TEXT("usePointFiltering"), bUsePointFiltering);
configData->data->SetInt(TEXT("gamma"), (int)SendMessage(GetDlgItem(hwnd, IDC_GAMMA2), TBM_GETPOS, 0, 0)); configData->data->SetInt(TEXT("gamma"), (int)SendMessage(GetDlgItem(hwnd, IDC_GAMMA), TBM_GETPOS, 0, 0));
configData->data->SetInt(TEXT("deinterlacingType"), deinterlacingConfig.type);
configData->data->SetInt(TEXT("deinterlacingFieldOrder"), deinterlacingConfig.fieldOrder);
configData->data->SetInt(TEXT("deinterlacingProcessor"), deinterlacingConfig.processor);
configData->data->SetInt(TEXT("deinterlacingDoublesFramerate"), deinterlacingConfig.doublesFramerate);
//------------------------------------------ //------------------------------------------
@ -1994,6 +2087,9 @@ INT_PTR CALLBACK ConfigureDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPA
source->SetInt(TEXT("keySpillReduction"), configData->data->GetInt(TEXT("keySpillReduction"), 50)); source->SetInt(TEXT("keySpillReduction"), configData->data->GetInt(TEXT("keySpillReduction"), 50));
source->SetInt(TEXT("gamma"), configData->data->GetInt(TEXT("gamma"), 100)); source->SetInt(TEXT("gamma"), configData->data->GetInt(TEXT("gamma"), 100));
source->SetInt(TEXT("deinterlacingType"), configData->data->GetInt(TEXT("deinterlacingType"), 0)); source->SetInt(TEXT("deinterlacingType"), configData->data->GetInt(TEXT("deinterlacingType"), 0));
source->SetInt(TEXT("deinterlacingFieldOrder"), configData->data->GetInt(TEXT("deinterlacingFieldOrder"), 0));
source->SetInt(TEXT("deinterlacingProcessor"), configData->data->GetInt(TEXT("deinterlacingProcessor"), 0));
source->SetInt(TEXT("deinterlacingDoublesFramerate"), configData->data->GetInt(TEXT("deinterlacingDoublesFramerate"), 0));
} }
} }

View File

@ -42,9 +42,32 @@ bool GetClosestResolutionFPS(List<MediaOutputInfo> &outputList, SIZE &resolution
extern LocaleStringLookup *pluginLocale; extern LocaleStringLookup *pluginLocale;
#define PluginStr(text) pluginLocale->LookupString(TEXT2(text)) #define PluginStr(text) pluginLocale->LookupString(TEXT2(text))
enum deinterLacingTypes { enum DeinterlacingType {
deinterlacing_None, DEINTERLACING_NONE,
deinterlacing_Discard, DEINTERLACING_DISCARD,
deinterlacing_Retro_TFF, DEINTERLACING_RETRO,
deinterlacing_Retro_BFF, DEINTERLACING_BLEND,
DEINTERLACING_BLEND2x,
DEINTERLACING_LINEAR,
DEINTERLACING_LINEAR2x,
DEINTERLACING_YADIF,
DEINTERLACING_YADIF2x,
DEINTERLACING__DEBUG,
DEINTERLACING_TYPE_LAST
};
enum DeinterlacingFieldOrder {
FIELD_ORDER_NONE,
FIELD_ORDER_TFF = 1,
FIELD_ORDER_BFF,
};
enum DeinterlacingProcessor {
DEINTERLACING_PROCESSOR_CPU = 1,
DEINTERLACING_PROCESSOR_GPU,
};
struct DeinterlacerConfig {
int type, fieldOrder, processor;
bool doublesFramerate;
}; };

View File

@ -45,12 +45,29 @@ END
#endif // APSTUDIO_INVOKED #endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Cursor
//
IDC_COLORPICKER CURSOR "cursor1.cur"
#endif // Japanese (Japan) resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// English resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
#pragma code_page(1252)
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
// Dialog // Dialog
// //
IDD_CONFIG DIALOGEX 0, 0, 428, 281 IDD_CONFIG DIALOGEX 0, 0, 429, 295
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "DeviceSelection" CAPTION "DeviceSelection"
FONT 8, "MS Shell Dlg", 400, 0, 0x1 FONT 8, "MS Shell Dlg", 400, 0, 0x1
@ -68,51 +85,54 @@ BEGIN
RTEXT "DeviceSelection.Opacity",IDC_STATIC,144,38,117,8 RTEXT "DeviceSelection.Opacity",IDC_STATIC,144,38,117,8
EDITTEXT IDC_OPACITY_EDIT,264,35,40,14,ES_AUTOHSCROLL | ES_NUMBER EDITTEXT IDC_OPACITY_EDIT,264,35,40,14,ES_AUTOHSCROLL | ES_NUMBER
CONTROL "",IDC_OPACITY,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,304,35,11,14 CONTROL "",IDC_OPACITY,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,304,35,11,14
GROUPBOX "DeviceSelection.Video",IDC_STATIC,7,67,216,101 GROUPBOX "DeviceSelection.Video",IDC_STATIC,6,79,216,101
CONTROL "DeviceSelection.CustomResolution",IDC_CUSTOMRESOLUTION, CONTROL "DeviceSelection.CustomResolution",IDC_CUSTOMRESOLUTION,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,79,130,10,WS_EX_RIGHT "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,91,130,10,WS_EX_RIGHT
RTEXT "DeviceSelection.Resolution",IDC_STATIC,18,96,117,8 RTEXT "DeviceSelection.Resolution",IDC_STATIC,17,108,117,8
COMBOBOX IDC_RESOLUTION,138,93,76,72,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_RESOLUTION,137,105,76,72,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
RTEXT "DeviceSelection.FPS",IDC_STATIC,18,113,117,8 RTEXT "DeviceSelection.FPS",IDC_STATIC,17,125,117,8
COMBOBOX IDC_FPS,138,111,76,56,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_FPS,137,123,76,56,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
CONTROL "DeviceSelection.PreferredType",IDC_USEPREFERREDOUTPUT, CONTROL "DeviceSelection.PreferredType",IDC_USEPREFERREDOUTPUT,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,132,117,10,WS_EX_RIGHT "Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,144,117,10,WS_EX_RIGHT
COMBOBOX IDC_PREFERREDOUTPUT,138,130,76,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_PREFERREDOUTPUT,137,142,76,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
CONTROL "DeviceSelection.UseBuffering",IDC_USEBUFFERING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,151,117,10,WS_EX_RIGHT CONTROL "DeviceSelection.UseBuffering",IDC_USEBUFFERING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,163,117,10,WS_EX_RIGHT
EDITTEXT IDC_DELAY_EDIT,138,148,40,14,ES_AUTOHSCROLL EDITTEXT IDC_DELAY_EDIT,137,160,40,14,ES_AUTOHSCROLL
CONTROL "",IDC_DELAY,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,178,148,10,14 CONTROL "",IDC_DELAY,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,177,160,11,14
GROUPBOX "DeviceSelection.Sound",IDC_STATIC,234,67,187,136,WS_GROUP GROUPBOX "DeviceSelection.Sound",IDC_STATIC,233,79,187,136,WS_GROUP
LTEXT "DeviceSelection.AudioDevice",IDC_STATIC,243,84,117,8 LTEXT "DeviceSelection.AudioDevice",IDC_STATIC,242,96,117,8
COMBOBOX IDC_AUDIOLIST,243,96,169,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_AUDIOLIST,242,108,169,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "DeviceSelection.Config",IDC_CONFIGAUDIO,335,112,78,13 PUSHBUTTON "DeviceSelection.Config",IDC_CONFIGAUDIO,334,124,78,13
CONTROL "ƒJƒXƒ^ƒ€1",IDC_VOLUME,"OBSVolumeControl",WS_TABSTOP,243,131,118,19 CONTROL "OBSVolumeControl",IDC_VOLUME,"OBSVolumeControl",WS_TABSTOP,242,143,118,19
CONTROL "DeviceSelection.OutputSound",IDC_OUTPUTSOUND,"Button",BS_AUTORADIOBUTTON,243,156,163,10 CONTROL "DeviceSelection.OutputSound",IDC_OUTPUTSOUND,"Button",BS_AUTORADIOBUTTON,242,168,163,10
LTEXT "DeviceSelection.SoundOffset",IDC_STATIC,239,171,117,8,NOT WS_GROUP,WS_EX_RIGHT LTEXT "DeviceSelection.SoundOffset",IDC_STATIC,238,183,117,8,NOT WS_GROUP,WS_EX_RIGHT
EDITTEXT IDC_TIMEOFFSET_EDIT,361,168,40,14,ES_AUTOHSCROLL EDITTEXT IDC_TIMEOFFSET_EDIT,360,180,40,14,ES_AUTOHSCROLL
CONTROL "",IDC_TIMEOFFSET,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,401,168,11,14 CONTROL "",IDC_TIMEOFFSET,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,400,180,11,14
CONTROL "DeviceSelection.PlayToDesktop",IDC_PLAYDESKTOPSOUND, CONTROL "DeviceSelection.PlayToDesktop",IDC_PLAYDESKTOPSOUND,
"Button",BS_AUTORADIOBUTTON,243,186,163,10 "Button",BS_AUTORADIOBUTTON,242,198,163,10
GROUPBOX "DeviceSelection.ChromaKey",IDC_STATIC,7,174,216,99 GROUPBOX "DeviceSelection.ChromaKey",IDC_STATIC,6,186,216,99
CONTROL "DeviceSelection.UseChromaKey",IDC_USECHROMAKEY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,186,130,10,WS_EX_RIGHT CONTROL "DeviceSelection.UseChromaKey",IDC_USECHROMAKEY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,198,130,10,WS_EX_RIGHT
RTEXT "DeviceSelection.Color",IDC_STATIC,14,202,117,8 RTEXT "DeviceSelection.Color",IDC_STATIC,13,214,117,8
CONTROL "",IDC_COLOR,"OBSColorControl",WS_TABSTOP,133,199,28,14 CONTROL "",IDC_COLOR,"OBSColorControl",WS_TABSTOP,132,211,28,14
PUSHBUTTON "DeviceSelection.Select",IDC_SELECTCOLOR,166,199,50,14 PUSHBUTTON "DeviceSelection.Select",IDC_SELECTCOLOR,165,211,50,14
RTEXT "DeviceSelection.Similarity",IDC_STATIC,14,220,117,8 RTEXT "DeviceSelection.Similarity",IDC_STATIC,13,232,117,8
EDITTEXT IDC_BASETHRESHOLD_EDIT,132,218,40,14,ES_AUTOHSCROLL | ES_NUMBER EDITTEXT IDC_BASETHRESHOLD_EDIT,131,230,40,14,ES_AUTOHSCROLL | ES_NUMBER
CONTROL "",IDC_BASETHRESHOLD,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,173,218,10,14 CONTROL "",IDC_BASETHRESHOLD,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,172,230,11,14
RTEXT "DeviceSelection.Blend",IDC_STATIC,12,236,117,8 RTEXT "DeviceSelection.Blend",IDC_STATIC,11,248,117,8
EDITTEXT IDC_BLEND_EDIT,132,235,40,14,ES_AUTOHSCROLL | ES_NUMBER EDITTEXT IDC_BLEND_EDIT,131,247,40,14,ES_AUTOHSCROLL | ES_NUMBER
CONTROL "",IDC_BLEND,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,172,235,11,14 CONTROL "",IDC_BLEND,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,171,247,11,14
RTEXT "DeviceSelection.SpillReduction",IDC_STATIC,12,252,117,8 RTEXT "DeviceSelection.SpillReduction",IDC_STATIC,11,264,117,8
EDITTEXT IDC_SPILLREDUCTION_EDIT,132,251,40,14,ES_AUTOHSCROLL EDITTEXT IDC_SPILLREDUCTION_EDIT,131,263,40,14,ES_AUTOHSCROLL
CONTROL "",IDC_SPILLREDUCTION,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,172,251,11,14 CONTROL "",IDC_SPILLREDUCTION,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,171,263,11,14
DEFPUSHBUTTON "OK",IDOK,313,260,50,14 DEFPUSHBUTTON "OK",IDOK,312,272,50,14
PUSHBUTTON "Cancel",IDCANCEL,371,260,50,14 PUSHBUTTON "Cancel",IDCANCEL,370,272,50,14
RTEXT "DeviceSelection.Gamma",IDC_STATIC,235,208,95,8 RTEXT "DeviceSelection.Gamma",IDC_STATIC,234,220,95,8
CONTROL "",IDC_GAMMA2,"msctls_trackbar32",TBS_BOTH | WS_TABSTOP,230,220,191,26 CONTROL "",IDC_GAMMA,"msctls_trackbar32",TBS_BOTH | WS_TABSTOP,229,232,191,26
LTEXT ".numbers!",IDC_GAMMAVAL,336,208,54,8 LTEXT ".numbers!",IDC_GAMMAVAL,335,220,54,8
RTEXT "DeviceSelection.Deinterlacing",IDC_STATIC,3,54,117,8 RTEXT "DeviceSelection.Deinterlacing",IDC_STATIC,3,54,117,8
COMBOBOX IDC_DEINTERLACELIST,125,51,133,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_DEINTERLACELIST,125,51,133,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
CONTROL "DeviceSelection.TopFieldFirst",IDC_TFF,"Button",BS_AUTORADIOBUTTON | BS_RIGHT | WS_TABSTOP,14,68,119,10,WS_EX_RIGHT
CONTROL "DeviceSelection.BottomFieldFirst",IDC_BFF,"Button",BS_AUTORADIOBUTTON | BS_RIGHT | WS_TABSTOP,154,68,119,10,WS_EX_RIGHT
CONTROL "DeviceSelection.GPUDeinterlacing",IDC_GPUDEINT,"Button",BS_AUTOCHECKBOX | BS_RIGHT | WS_TABSTOP,294,68,119,10,WS_EX_RIGHT
END END
@ -127,21 +147,14 @@ BEGIN
IDD_CONFIG, DIALOG IDD_CONFIG, DIALOG
BEGIN BEGIN
LEFTMARGIN, 7 LEFTMARGIN, 7
RIGHTMARGIN, 421 RIGHTMARGIN, 422
TOPMARGIN, 7 TOPMARGIN, 7
BOTTOMMARGIN, 274 BOTTOMMARGIN, 288
END END
END END
#endif // APSTUDIO_INVOKED #endif // APSTUDIO_INVOKED
#endif // English resources
/////////////////////////////////////////////////////////////////////////////
//
// Cursor
//
IDC_COLORPICKER CURSOR "cursor1.cur"
#endif // Japanese (Japan) resources
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////

View File

@ -24,6 +24,18 @@ DWORD STDCALL PackPlanarThread(ConvertData *data);
#define NEAR_SILENT 3000 #define NEAR_SILENT 3000
#define NEAR_SILENTf 3000.0 #define NEAR_SILENTf 3000.0
DeinterlacerConfig deinterlacerConfigs[DEINTERLACING_TYPE_LAST] = {
{DEINTERLACING_NONE, FIELD_ORDER_NONE, DEINTERLACING_PROCESSOR_CPU},
{DEINTERLACING_DISCARD, FIELD_ORDER_TFF | FIELD_ORDER_BFF, DEINTERLACING_PROCESSOR_CPU},
{DEINTERLACING_RETRO, FIELD_ORDER_TFF | FIELD_ORDER_BFF, DEINTERLACING_PROCESSOR_CPU | DEINTERLACING_PROCESSOR_GPU, true},
{DEINTERLACING_BLEND, FIELD_ORDER_NONE, DEINTERLACING_PROCESSOR_GPU},
{DEINTERLACING_BLEND2x, FIELD_ORDER_TFF | FIELD_ORDER_BFF, DEINTERLACING_PROCESSOR_GPU, true},
{DEINTERLACING_LINEAR, FIELD_ORDER_TFF | FIELD_ORDER_BFF, DEINTERLACING_PROCESSOR_GPU},
{DEINTERLACING_LINEAR2x, FIELD_ORDER_TFF | FIELD_ORDER_BFF, DEINTERLACING_PROCESSOR_GPU, true},
{DEINTERLACING_YADIF, FIELD_ORDER_TFF | FIELD_ORDER_BFF, DEINTERLACING_PROCESSOR_GPU},
{DEINTERLACING_YADIF2x, FIELD_ORDER_TFF | FIELD_ORDER_BFF, DEINTERLACING_PROCESSOR_GPU, true},
{DEINTERLACING__DEBUG, FIELD_ORDER_TFF | FIELD_ORDER_BFF, DEINTERLACING_PROCESSOR_GPU},
};
bool DeviceSource::Init(XElement *data) bool DeviceSource::Init(XElement *data)
{ {
@ -89,13 +101,15 @@ DeviceSource::~DeviceSource()
OSCloseMutex(hSampleMutex); OSCloseMutex(hSampleMutex);
} }
#define SHADER_PATH TEXT("plugins/DShowPlugin/shaders/")
String DeviceSource::ChooseShader() String DeviceSource::ChooseShader()
{ {
if(colorType == DeviceOutputType_RGB && !bUseChromaKey) if(colorType == DeviceOutputType_RGB && !bUseChromaKey)
return String(); return String();
String strShader; String strShader;
strShader << TEXT("plugins/DShowPlugin/shaders/"); strShader << SHADER_PATH;
if(bUseChromaKey) if(bUseChromaKey)
strShader << TEXT("ChromaKey_"); strShader << TEXT("ChromaKey_");
@ -118,6 +132,35 @@ String DeviceSource::ChooseShader()
return strShader; return strShader;
} }
String DeviceSource::ChooseDeinterlacingShader()
{
String shader;
shader << SHADER_PATH << TEXT("Deinterlace_");
#ifdef _DEBUG
#define DEBUG__ _DEBUG
#undef _DEBUG
#endif
#define SELECT(x) case DEINTERLACING_##x: shader << String(TEXT(#x)).MakeLower(); break;
switch(deinterlacer.type)
{
SELECT(RETRO)
SELECT(BLEND)
SELECT(BLEND2x)
SELECT(LINEAR)
SELECT(LINEAR2x)
SELECT(YADIF)
SELECT(YADIF2x)
SELECT(_DEBUG)
}
return shader << TEXT(".pShader");
#undef SELECT
#ifdef DEBUG__
#define _DEBUG DEBUG__
#undef DEBUG__
#endif
}
const float yuv709Mat[16] = { 0.2126f, 0.7152f, 0.0722f, 0.0625f, const float yuv709Mat[16] = { 0.2126f, 0.7152f, 0.0722f, 0.0625f,
-0.1150f, -0.3850f, 0.5000f, 0.50f, -0.1150f, -0.3850f, 0.5000f, 0.50f,
0.5000f, -0.4540f, -0.0460f, 0.50f, 0.5000f, -0.4540f, -0.0460f, 0.50f,
@ -210,7 +253,10 @@ bool DeviceSource::LoadFilters()
keyBlend = data->GetInt(TEXT("keyBlend"), 80); keyBlend = data->GetInt(TEXT("keyBlend"), 80);
keySpillReduction = data->GetInt(TEXT("keySpillReduction"), 50); keySpillReduction = data->GetInt(TEXT("keySpillReduction"), 50);
deinterlacingType =data->GetInt(TEXT("deinterlacingType"), 0); deinterlacer.type = data->GetInt(TEXT("deinterlacingType"), 0);
deinterlacer.fieldOrder = data->GetInt(TEXT("deinterlacingFieldOrder"), 0);
deinterlacer.processor = data->GetInt(TEXT("deinterlacingProcessor"), 0);
deinterlacer.doublesFramerate = data->GetInt(TEXT("deinterlacingDoublesFramerate"), 0) != 0;
if(keyBaseColor.x < keyBaseColor.y && keyBaseColor.x < keyBaseColor.z) if(keyBaseColor.x < keyBaseColor.y && keyBaseColor.x < keyBaseColor.z)
keyBaseColor -= keyBaseColor.x; keyBaseColor -= keyBaseColor.x;
@ -637,20 +683,43 @@ bool DeviceSource::LoadFilters()
imageCX = renderCX; imageCX = renderCX;
imageCY = renderCY; imageCY = renderCY;
curField = false; deinterlacer.imageCX = renderCX;
switch(deinterlacingType) { deinterlacer.imageCY = renderCY;
case deinterlacing_Discard:
if(deinterlacer.doublesFramerate)
deinterlacer.imageCX *= 2;
switch(deinterlacer.type) {
case DEINTERLACING_DISCARD:
deinterlacer.imageCY = renderCY/2;
linePitch = lineSize * 2; linePitch = lineSize * 2;
renderCY /= 2; renderCY /= 2;
break; break;
case deinterlacing_Retro_BFF: case DEINTERLACING_RETRO:
curField = true; deinterlacer.imageCY = renderCY/2;
case deinterlacing_Retro_TFF: if(deinterlacer.processor != DEINTERLACING_PROCESSOR_GPU)
{
lineSize *= 2; lineSize *= 2;
linePitch = lineSize; linePitch = lineSize;
renderCY /= 2; renderCY /= 2;
renderCX *= 2; renderCX *= 2;
} }
case DEINTERLACING__DEBUG:
deinterlacer.imageCX *= 2;
deinterlacer.imageCY *= 2;
case DEINTERLACING_BLEND2x:
//case DEINTERLACING_MEAN2x:
case DEINTERLACING_YADIF:
case DEINTERLACING_YADIF2x:
deinterlacer.needsPreviousFrame = true;
break;
}
if(deinterlacer.type != DEINTERLACING_NONE && deinterlacer.processor == DEINTERLACING_PROCESSOR_GPU)
{
deinterlacer.vertexShader = CreateVertexShaderFromFile(TEXT("shaders/DrawTexture.vShader"));
deinterlacer.pixelShader = CreatePixelShaderFromFile(ChooseDeinterlacingShader());
}
int numThreads = MAX(OSGetTotalCores()-2, 1); int numThreads = MAX(OSGetTotalCores()-2, 1);
for(int i=0; i<numThreads; i++) for(int i=0; i<numThreads; i++)
@ -759,11 +828,19 @@ cleanFinish:
{ {
msetd(textureData, 0xFFFF0000, renderCX*renderCY*4); msetd(textureData, 0xFFFF0000, renderCX*renderCY*4);
texture = CreateTexture(renderCX, renderCY, GS_BGR, textureData, FALSE, FALSE); texture = CreateTexture(renderCX, renderCY, GS_BGR, textureData, FALSE, FALSE);
if(deinterlacer.needsPreviousFrame)
previousTexture = CreateTexture(renderCX, renderCY, GS_BGR, textureData, FALSE, FALSE);
if(deinterlacer.processor == DEINTERLACING_PROCESSOR_GPU)
deinterlacer.texture = CreateRenderTarget(deinterlacer.imageCX, deinterlacer.imageCY, GS_BGRA, FALSE);
} }
else //if we're working with planar YUV, we can just use regular RGB textures instead else //if we're working with planar YUV, we can just use regular RGB textures instead
{ {
msetd(textureData, 0xFF0000FF, renderCX*renderCY*4); msetd(textureData, 0xFF0000FF, renderCX*renderCY*4);
texture = CreateTexture(renderCX, renderCY, GS_RGB, textureData, FALSE, FALSE); texture = CreateTexture(renderCX, renderCY, GS_RGB, textureData, FALSE, FALSE);
if(deinterlacer.needsPreviousFrame)
previousTexture = CreateTexture(renderCX, renderCY, GS_RGB, textureData, FALSE, FALSE);
if(deinterlacer.processor == DEINTERLACING_PROCESSOR_GPU)
deinterlacer.texture = CreateRenderTarget(deinterlacer.imageCX, deinterlacer.imageCY, GS_BGRA, FALSE);
} }
if(bSucceeded && bUseThreadedConversion) if(bSucceeded && bUseThreadedConversion)
@ -802,6 +879,8 @@ void DeviceSource::UnloadFilters()
{ {
delete texture; delete texture;
texture = NULL; texture = NULL;
delete previousTexture;
previousTexture = NULL;
} }
int numThreads = MAX(OSGetTotalCores()-2, 1); int numThreads = MAX(OSGetTotalCores()-2, 1);
@ -1135,13 +1214,14 @@ void DeviceSource::Preprocess()
Log(TEXT("refTimeStart: %llu, refTimeFinish: %llu, offset = %llu"), refTimeStart, refTimeFinish, refTimeStart-lastRefTime); Log(TEXT("refTimeStart: %llu, refTimeFinish: %llu, offset = %llu"), refTimeStart, refTimeFinish, refTimeStart-lastRefTime);
lastRefTime = refTimeStart;*/ lastRefTime = refTimeStart;*/
switch(deinterlacingType) if(previousTexture)
{ {
case deinterlacing_Retro_BFF: Texture *tmp = texture;
case deinterlacing_Retro_TFF: texture = previousTexture;
curField = (deinterlacingType == deinterlacing_Retro_BFF); //select first field previousTexture = tmp;
bNewFrame = true;
} }
deinterlacer.curField = deinterlacer.processor == DEINTERLACING_PROCESSOR_GPU ? false : (deinterlacer.fieldOrder == FIELD_ORDER_BFF);
deinterlacer.bNewFrame = true;
if(colorType == DeviceOutputType_RGB) if(colorType == DeviceOutputType_RGB)
{ {
@ -1225,6 +1305,35 @@ void DeviceSource::Preprocess()
} }
lastSample->Release(); lastSample->Release();
if(bReadyToDraw && deinterlacer.type != DEINTERLACING_NONE && deinterlacer.processor == DEINTERLACING_PROCESSOR_GPU)
{
SetRenderTarget(deinterlacer.texture);
Shader *oldVertShader = GetCurrentVertexShader();
LoadVertexShader(deinterlacer.vertexShader);
Shader *oldShader = GetCurrentPixelShader();
LoadPixelShader(deinterlacer.pixelShader);
HANDLE hField = deinterlacer.pixelShader->GetParameterByName(TEXT("field_order"));
if(hField)
deinterlacer.pixelShader->SetBool(hField, deinterlacer.fieldOrder == FIELD_ORDER_BFF);
Ortho(0.0f, float(deinterlacer.imageCX), float(deinterlacer.imageCY), 0.0f, -100.0f, 100.0f);
SetViewport(0.0f, 0.0f, float(deinterlacer.imageCX), float(deinterlacer.imageCY));
if(previousTexture)
LoadTexture(previousTexture, 1);
DrawSpriteEx(texture, 0xFFFFFFFF, 0.0f, 0.0f, float(deinterlacer.imageCX), float(deinterlacer.imageCY), 0.0f, 0.0f, 1.0f, 1.0f);
if(previousTexture)
LoadTexture(nullptr, 1);
LoadPixelShader(oldShader);
LoadVertexShader(oldVertShader);
}
} }
} }
@ -1304,25 +1413,19 @@ void DeviceSource::Render(const Vect2 &pos, const Vect2 &size)
switch(deinterlacingType) { if(deinterlacer.doublesFramerate)
case deinterlacing_Retro_BFF:
case deinterlacing_Retro_TFF:
if(texture)
{ {
if(!curField) if(!deinterlacer.curField)
DrawSpriteEx(texture, (opacity255<<24) | 0xFFFFFF, x, y, x2, y2, 0.f, 0.0f, .5f, 1.f); DrawSpriteEx(deinterlacer.processor == DEINTERLACING_PROCESSOR_GPU ? deinterlacer.texture : texture, (opacity255<<24) | 0xFFFFFF, x, y, x2, y2, 0.f, 0.0f, .5f, 1.f);
else else
DrawSpriteEx(texture, (opacity255<<24) | 0xFFFFFF, x, y, x2, y2, .5f, 0.0f, 1.f, 1.f); DrawSpriteEx(deinterlacer.processor == DEINTERLACING_PROCESSOR_GPU ? deinterlacer.texture : texture, (opacity255<<24) | 0xFFFFFF, x, y, x2, y2, .5f, 0.0f, 1.f, 1.f);
} }
if(bNewFrame) else
DrawSprite(deinterlacer.processor == DEINTERLACING_PROCESSOR_GPU ? deinterlacer.texture : texture, (opacity255<<24) | 0xFFFFFF, x, y, x2, y2);
if(deinterlacer.bNewFrame)
{ {
curField = !curField; deinterlacer.curField = !deinterlacer.curField;
bNewFrame = false; //prevent switching from the second field to the first field deinterlacer.bNewFrame = false; //prevent switching from the second field to the first field
}
break;
default:
DrawSprite(texture, (opacity255<<24) | 0xFFFFFF, x, y, x2, y2);
break;
} }
if(bUsePointFiltering) delete(sampler); if(bUsePointFiltering) delete(sampler);
@ -1340,17 +1443,21 @@ void DeviceSource::UpdateSettings()
UINT newCX = data->GetInt(TEXT("resolutionWidth")); UINT newCX = data->GetInt(TEXT("resolutionWidth"));
UINT newCY = data->GetInt(TEXT("resolutionHeight")); UINT newCY = data->GetInt(TEXT("resolutionHeight"));
BOOL bNewCustom = data->GetInt(TEXT("customResolution")); BOOL bNewCustom = data->GetInt(TEXT("customResolution"));
UINT newDeinterlacingType = data->GetInt(TEXT("deinterlacingType"));
UINT newPreferredType = data->GetInt(TEXT("usePreferredType")) != 0 ? data->GetInt(TEXT("preferredType")) : -1; UINT newPreferredType = data->GetInt(TEXT("usePreferredType")) != 0 ? data->GetInt(TEXT("preferredType")) : -1;
UINT newSoundOutputType = data->GetInt(TEXT("soundOutputType")); UINT newSoundOutputType = data->GetInt(TEXT("soundOutputType"));
bool bNewUseBuffering = data->GetInt(TEXT("useBuffering")) != 0; bool bNewUseBuffering = data->GetInt(TEXT("useBuffering")) != 0;
UINT newGamma = data->GetInt(TEXT("gamma"), 100); UINT newGamma = data->GetInt(TEXT("gamma"), 100);
int newDeintType = data->GetInt(TEXT("deinterlacingType"));
int newDeintFieldOrder = data->GetInt(TEXT("deinterlacingFieldOrder"));
int newDeintProcessor = data->GetInt(TEXT("deinterlacingProcessor"));
if(newSoundOutputType != soundOutputType || imageCX != newCX || imageCY != newCY || if(newSoundOutputType != soundOutputType || imageCX != newCX || imageCY != newCY ||
frameInterval != newFrameInterval || newPreferredType != preferredOutputType || frameInterval != newFrameInterval || newPreferredType != preferredOutputType ||
!strDevice.CompareI(strNewDevice) || !strAudioDevice.CompareI(strNewAudioDevice) || !strDevice.CompareI(strNewDevice) || !strAudioDevice.CompareI(strNewAudioDevice) ||
bNewCustom != bUseCustomResolution || bNewUseBuffering != bUseBuffering || bNewCustom != bUseCustomResolution || bNewUseBuffering != bUseBuffering ||
newGamma != gamma || newDeinterlacingType != deinterlacingType) newGamma != gamma || newDeintType != deinterlacer.type ||
newDeintFieldOrder != deinterlacer.fieldOrder || newDeintProcessor != deinterlacer.processor)
{ {
API->EnterSceneMutex(); API->EnterSceneMutex();

View File

@ -135,8 +135,17 @@ class DeviceSource : public ImageSource
BOOL bUseCustomResolution; BOOL bUseCustomResolution;
UINT preferredOutputType; UINT preferredOutputType;
BYTE deinterlacingType; struct {
int type; //DeinterlacingType
char fieldOrder; //DeinterlacingFieldOrder
char processor; //DeinterlacingProcessor
bool curField, bNewFrame; bool curField, bNewFrame;
bool doublesFramerate;
bool needsPreviousFrame;
Texture *texture;
UINT imageCX, imageCY;
Shader *vertexShader, *pixelShader;
} deinterlacer;
bool bFirstFrame; bool bFirstFrame;
bool bUseThreadedConversion; bool bUseThreadedConversion;
@ -145,7 +154,7 @@ class DeviceSource : public ImageSource
int soundOutputType; int soundOutputType;
bool bOutputAudioToDesktop; bool bOutputAudioToDesktop;
Texture *texture; Texture *texture, *previousTexture;
XElement *data; XElement *data;
UINT texturePitch; UINT texturePitch;
bool bCapturing, bFiltersLoaded; bool bCapturing, bFiltersLoaded;
@ -183,6 +192,7 @@ class DeviceSource : public ImageSource
//--------------------------------- //---------------------------------
String ChooseShader(); String ChooseShader();
String ChooseDeinterlacingShader();
void Convert422To444(LPBYTE convertBuffer, LPBYTE lp422, UINT pitch, bool bLeadingY); void Convert422To444(LPBYTE convertBuffer, LPBYTE lp422, UINT pitch, bool bLeadingY);

View File

@ -35,7 +35,6 @@
#define IDC_BLEND 1022 #define IDC_BLEND 1022
#define IDC_GAMMA_EDIT 1023 #define IDC_GAMMA_EDIT 1023
#define IDC_SPILLREDUCTION_EDIT 1023 #define IDC_SPILLREDUCTION_EDIT 1023
#define IDC_GAMMA 1024
#define IDC_SPILLREDUCTION 1024 #define IDC_SPILLREDUCTION 1024
#define IDC_FLIPIMAGEH 1025 #define IDC_FLIPIMAGEH 1025
#define IDC_PREFERREDOUTPUT 1026 #define IDC_PREFERREDOUTPUT 1026
@ -47,14 +46,16 @@
#define IDC_TIMEOFFSET_EDIT 1032 #define IDC_TIMEOFFSET_EDIT 1032
#define IDC_TIMEOFFSET 1033 #define IDC_TIMEOFFSET 1033
#define IDC_CHECK1 1034 #define IDC_CHECK1 1034
#define IDC_CUSTOM1 1035 #define IDC_TFF 1034
#define IDC_VOLUME 1035 #define IDC_VOLUME 1035
#define IDC_VOLMETER 1036 #define IDC_VOLMETER 1036
#define IDC_POINTFILTERING 1036 #define IDC_POINTFILTERING 1036
#define IDC_DELAY_EDIT 1037 #define IDC_DELAY_EDIT 1037
#define IDC_VIDEODELAY 1038 #define IDC_VIDEODELAY 1038
#define IDC_DELAY 1038 #define IDC_DELAY 1038
#define IDC_GAMMA2 1039 #define IDC_GAMMA 1039
#define IDC_BFF 1040
#define IDC_GPUDEINT 1041
#define IDC_GAMMAVAL 1151 #define IDC_GAMMAVAL 1151
// Next default values for new objects // Next default values for new objects

View File

@ -5,8 +5,17 @@ OK "OK"
DeinterlacingType.None "None" DeinterlacingType.None "None"
DeinterlacingType.Discard "Field Discard" DeinterlacingType.Discard "Field Discard"
DeinterlacingType.RetroTFF "Retro/scandoubling (TFF)" DeinterlacingType.Retro "Retro/scandoubling"
DeinterlacingType.RetroBFF "Retro/scandoubling (BFF)" DeinterlacingType.Blend "Blend"
DeinterlacingType.Blend2x "Blend2x"
DeinterlacingType.Linear "Linear"
DeinterlacingType.Linear2x "Linear2x"
DeinterlacingType.Yadif "Yadif"
DeinterlacingType.Yadif2x "Yadif2x"
DeinterlacingType.Debug "Debug"
DeviceSelection.TopFieldFirst "Top Field First"
DeviceSelection.BottomFieldFirst "Bottom Field First"
DeviceSelection.GPUDeinterlacing "Use GPU"
CrossbarSelection.Open "Open Crossbar" CrossbarSelection.Open "Open Crossbar"

View File

@ -0,0 +1,44 @@
/********************************************************************************
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 "Deinterlace_base.pShader"
float4 main(VertData input) : SV_Target
{
//input.texCoord.x *= 2;
//return sample_pixel(fmod(input.texCoord, 1), 1*(input.texCoord<1), YADIF);
//return sample_pixel(input.texCoord, 1, YADIF);
//return sample_pixel(input.texCoord, 0, WEAVE);
float2 texCoord = input.texCoord;// * 2;
if(texCoord.y < .5)
{
input.texCoord.y *= 2;
return sample_pixel_2x(input.texCoord, field_order, BLEND2x);
/*if(texCoord.x < .5)
return sample_pixel(texCoord*2, 1*(texCoord.y < 1), YADIF*(texCoord.x<1));
else
return sample_pixel(float2(texCoord.x*2-1, texCoord.y*2), 0, YADIF);*/
}
else
{
if(texCoord.x < .5)
return sample_pixel(input.texCoord*2-float2(0, 1), 1, WEAVE);
else
return sample_pixel(input.texCoord*2-1, 0, WEAVE);
}
}

View File

@ -0,0 +1,196 @@
/********************************************************************************
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.
********************************************************************************/
uniform Texture2D diffuseTexture;
uniform Texture2D prevTex;
uniform bool field_order;
#define WEAVE 0
#define YADIF 1
#define BLEND 2
#define BLEND2x 3
#define LINEAR 4
#define LINEAR2x 5
#define DISCARD 6
#define DISCARD2x 7
int3 select(int2 texel, int x, int y)
{
return int3(texel+int2(x, y), 0);
}
float4 load_at(int2 texel, int x, int y, int field)
{
if(field == 0)
return diffuseTexture.Load(int3(texel+int2(x, y), 0));
else
return prevTex.Load(int3(texel+int2(x, y), 0));
}
#define YADIF_UPDATE(c, level)\
if(score.c < spatial_score.c)\
{\
spatial_score.c = score.c;\
spatial_pred.c = (load_at(texel, level, -1, field) + load_at(texel, -level, 1, field)).c/2;\
#define YADIF_CHECK_ONE(level, c)\
{\
float4 score = abs(load_at(texel, -1+level, 1, field) - load_at(texel, -1-level, -1, field))+\
abs(load_at(texel, level, 1, field) - load_at(texel, -level, -1, field))+\
abs(load_at(texel, 1+level, 1, field) - load_at(texel, 1-level, -1, field));\
YADIF_UPDATE(c, level) }\
}
#define YADIF_CHECK(level)\
{\
float4 score = abs(load_at(texel, -1+level, 1, field) - load_at(texel, -1-level, -1, field))+\
abs(load_at(texel, level, 1, field) - load_at(texel, -level, -1, field))+\
abs(load_at(texel, 1+level, 1, field) - load_at(texel, 1-level, -1, field));\
YADIF_UPDATE(r, level) YADIF_CHECK_ONE(level*2, r) }\
YADIF_UPDATE(g, level) YADIF_CHECK_ONE(level*2, g) }\
YADIF_UPDATE(b, level) YADIF_CHECK_ONE(level*2, b) }\
YADIF_UPDATE(a, level) YADIF_CHECK_ONE(level*2, a) }\
}
float4 texel_at_yadif(int2 texel, int field)
{
Texture2D tex = diffuseTexture;
if((texel.y%2) == field)
return load_at(texel, 0, 0, field);
float4 b = (prevTex.Load(select(texel, 0, 2)) + tex.Load(select(texel, 0, 2)))/2,
c = load_at(texel, 0, 1, field),
d = (prevTex.Load(select(texel, 0, 0)) + tex.Load(select(texel, 0, 0)))/2,
e = load_at(texel, 0, -1, field),
f = (prevTex.Load(select(texel, 0, -2)) + tex.Load(select(texel, 0, -2)))/2;
float4 temporal_diff0 = (abs(prevTex.Load(select(texel, 0, 0)) - tex.Load(select(texel, 0, 0))))/2,
temporal_diff1 = (abs(prevTex.Load(select(texel, 0, 1))-c) + abs(prevTex.Load(select(texel, 0, -1))-e))/2,
temporal_diff2 = (abs(tex.Load(select(texel, 0, 1))-c) + abs(tex.Load(select(texel, 0, -1))-e))/2,
diff = max(temporal_diff0, max(temporal_diff1, temporal_diff2));
float4 spatial_pred = (c+e)/2,
spatial_score = abs(load_at(texel, -1, 1, field)-load_at(texel, -1, -1, field))+
abs(c-e)+
abs(load_at(texel, 1, 1, field)-load_at(texel, 1, -1, field))-1;
YADIF_CHECK(-1)
YADIF_CHECK(1)
float4 max_ = max(d-e, max(d-c, min(b-c, f-e))),
min_ = min(d-e, min(d-c, max(b-c, f-e)));
diff = max(diff, max(min_, -max_));
#define YADIF_SPATIAL(c)\
{\
if(spatial_pred.c > d.c + diff.c)\
spatial_pred.c = d.c + diff.c;\
else if(spatial_pred.c < d.c - diff.c)\
spatial_pred.c = d.c - diff.c;\
}
YADIF_SPATIAL(r)
YADIF_SPATIAL(g)
YADIF_SPATIAL(b)
YADIF_SPATIAL(a)
return spatial_pred;
}
float4 texel_at_blend(int2 texel, int field)
{
return (diffuseTexture.Load(int3(texel, 0)) + diffuseTexture.Load(int3(texel.x, texel.y+1, 0)))/2;
}
float4 texel_at_blend_2x(int2 texel, int field)
{
if(field_order != field)
return (diffuseTexture.Load(int3(texel.x, texel.y, 0)) + prevTex.Load(int3(texel.x, texel.y+1, 0)))/2;
return (diffuseTexture.Load(int3(texel.x, texel.y, 0)) + diffuseTexture.Load(int3(texel.x, texel.y+1, 0)))/2;
}
float4 texel_at_linear(int2 texel, int field)
{
if(field == texel.y%2)
return diffuseTexture.Load(int3(texel, 0));
return (diffuseTexture.Load(int3(texel+int2(0, -1), 0))+diffuseTexture.Load(int3(texel+int2(0, 1), 0)))/2;
}
float4 texel_at_linear2x(int2 texel, int field)
{
return texel_at_linear(texel, 1-field);
}
float4 texel_at_discard(int2 texel, int field)
{
Texture2D tex = diffuseTexture;
return tex.Load(int3(texel.x, texel.y/2*2+field, 0));
}
float4 texel_at_discard2x(int2 texel, int field)
{
return texel_at_discard(texel, 1-field);
}
float4 texel_at_weave(int2 texel, int field)
{
if(field != 0)
return prevTex.Load(int3(texel, 0));
return diffuseTexture.Load(int3(texel, 0));
}
#define DISPATCH(name, func)\
case name: return func(coord, field); break;
float4 sample_texel(float2 coord, int field, int name)
{
switch(name)
{
DISPATCH(YADIF, texel_at_yadif)
DISPATCH(BLEND, texel_at_blend)
DISPATCH(BLEND2x, texel_at_blend_2x)
DISPATCH(LINEAR, texel_at_linear)
DISPATCH(LINEAR2x, texel_at_linear2x)
DISPATCH(DISCARD, texel_at_discard)
DISPATCH(DISCARD2x, texel_at_discard2x)
default: return texel_at_weave(coord, field); break;
}
}
#undef DISPATCH
float4 sample_pixel(float2 coord, bool field, int func)
{
Texture2D tex = diffuseTexture;
float2 size = 0;
float miplevels;
tex.GetDimensions(0, size.x, size.y, miplevels);
float2 uv = coord*size;
return sample_texel(uv, field, func);
}
float4 sample_pixel_2x(float2 coord, bool field, int func)
{
coord.x *= 2;
return sample_pixel(coord-floor(coord), field*(coord.x>1)+(1-field)*(coord.x<1), func);
}
struct VertData
{
float4 pos : SV_Position;
float2 texCoord : TexCoord0;
};

View File

@ -0,0 +1,24 @@
/********************************************************************************
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 "Deinterlace_base.pShader"
float4 main(VertData input) : SV_Target
{
return sample_pixel(input.texCoord, field_order, BLEND);
}

View File

@ -0,0 +1,24 @@
/********************************************************************************
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 "Deinterlace_base.pShader"
float4 main(VertData input) : SV_Target
{
return sample_pixel_2x(input.texCoord, field_order, BLEND2x);
}

View File

@ -0,0 +1,24 @@
/********************************************************************************
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 "Deinterlace_base.pShader"
float4 main(VertData input) : SV_Target
{
return sample_pixel(input.texCoord, field_order, LINEAR);
}

View File

@ -0,0 +1,24 @@
/********************************************************************************
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 "Deinterlace_base.pShader"
float4 main(VertData input) : SV_Target
{
return sample_pixel_2x(input.texCoord, field_order, LINEAR2x);
}

View File

@ -0,0 +1,24 @@
/********************************************************************************
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 "Deinterlace_base.pShader"
float4 main(VertData input) : SV_Target
{
return sample_pixel_2x(input.texCoord, field_order, DISCARD2x);
}

View File

@ -0,0 +1,24 @@
/********************************************************************************
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 "Deinterlace_base.pShader"
float4 main(VertData input) : SV_Target
{
return sample_pixel(input.texCoord, field_order, YADIF);
}

View File

@ -0,0 +1,24 @@
/********************************************************************************
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 "Deinterlace_base.pShader"
float4 main(VertData input) : SV_Target
{
return sample_pixel_2x(input.texCoord, field_order, YADIF);
}