diff --git a/Common/OSVersion.cpp b/Common/OSVersion.cpp index f66c441365..adc2f1d310 100644 --- a/Common/OSVersion.cpp +++ b/Common/OSVersion.cpp @@ -95,6 +95,25 @@ bool IsVistaOrHigher() { #endif } +bool IsWin7OrHigher() { +#if PPSSPP_PLATFORM(UWP) + return true; +#else + OSVERSIONINFOEX osvi; + DWORDLONG dwlConditionMask = 0; + int op = VER_GREATER_EQUAL; + ZeroMemory(&osvi, sizeof(osvi)); + osvi.dwOSVersionInfoSize = sizeof(osvi); + osvi.dwMajorVersion = 6; // Win7 is 6.1 + osvi.dwMinorVersion = 1; + + VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, op); + VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, op); + + return VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, dwlConditionMask) != FALSE; +#endif +} + std::string GetWindowsVersion() { const bool IsWindowsXPSP2 = DoesVersionMatchWindows(5, 1, 2, 0, false); const bool IsWindowsXPSP3 = DoesVersionMatchWindows(5, 1, 3, 0, false); diff --git a/Common/OSVersion.h b/Common/OSVersion.h index 1f441e412c..262cba05ac 100644 --- a/Common/OSVersion.h +++ b/Common/OSVersion.h @@ -5,6 +5,7 @@ #ifdef _WIN32 bool IsVistaOrHigher(); +bool IsWin7OrHigher(); bool DoesVersionMatchWindows(uint32_t major, uint32_t minor, uint32_t spMajor, uint32_t spMinor, bool acceptGreater); std::string GetWindowsVersion(); std::string GetWindowsSystemArchitecture(); diff --git a/Core/Config.cpp b/Core/Config.cpp index 8ae8b6f78f..3dd37d49c7 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -706,6 +706,8 @@ static ConfigSetting graphicsSettings[] = { ConfigSetting("VulkanDevice", &g_Config.sVulkanDevice, "", true, false), #ifdef _WIN32 ConfigSetting("D3D11Device", &g_Config.sD3D11Device, "", true, false), +#endif +#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP) ConfigSetting("WinCameraDevice", &g_Config.sWinCameraDevice, "", true, false), #endif ConfigSetting("VendorBugChecksEnabled", &g_Config.bVendorBugChecksEnabled, true, false, false), diff --git a/Core/HLE/sceUsbCam.cpp b/Core/HLE/sceUsbCam.cpp index 5d0bce11cb..3510985130 100644 --- a/Core/HLE/sceUsbCam.cpp +++ b/Core/HLE/sceUsbCam.cpp @@ -25,7 +25,7 @@ #include "Core/HLE/sceUsbCam.h" #include "Core/MemMapHelpers.h" -#ifdef _WIN32 +#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP) #include "Windows/CaptureDevice.h" #undef min #endif @@ -50,7 +50,7 @@ void __UsbCamInit() { } void __UsbCamShutdown() { -#ifdef _WIN32 +#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP) if (winCamera) { winCamera->sendMessage({ CAPTUREDEVIDE_COMMAND::SHUTDOWN, nullptr }); } @@ -112,7 +112,7 @@ static int sceUsbCamSetupVideo(u32 paramAddr, u32 workareaAddr, int wasize) { static int sceUsbCamStartVideo() { INFO_LOG(HLE, "UNIMPL sceUsbCamStartVideo"); -#ifdef _WIN32 +#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP) if (winCamera) { if (winCamera->isShutDown()) { delete winCamera; @@ -131,7 +131,7 @@ static int sceUsbCamStartVideo() { static int sceUsbCamStopVideo() { INFO_LOG(HLE, "UNIMPL sceUsbCamStopVideo"); -#ifdef _WIN32 +#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP) if (winCamera) winCamera->sendMessage({ CAPTUREDEVIDE_COMMAND::STOP, nullptr }); #else @@ -155,6 +155,7 @@ static int sceUsbCamReadVideoFrameBlocking(u32 bufAddr, u32 size) { } static int sceUsbCamReadVideoFrame(u32 bufAddr, u32 size) { + ERROR_LOG(HLE, "%s", winCamera->getErrorMessage().c_str()); std::lock_guard lock(videoBufferMutex); u32 transferSize = std::min(videoBufferLength, size); if (Memory::IsValidRange(bufAddr, size)) { diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index be60930581..ab5975c65e 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -68,13 +68,9 @@ #include "Windows/MainWindow.h" #include #include "Windows/W32Util/ShellUtil.h" -#endif - -#ifdef _WIN32 #include "Windows/CaptureDevice.h" #endif - GameSettingsScreen::GameSettingsScreen(std::string gamePath, std::string gameID, bool editThenRestore) : UIDialogScreenWithGameBackground(gamePath), gameID_(gameID), enableReports_(false), editThenRestore_(editThenRestore) { lastVertical_ = UseVerticalLayout(); @@ -267,7 +263,7 @@ void GameSettingsScreen::CreateViews() { softwareGPU->SetEnabled(false); } -#ifdef _WIN32 +#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP) if (winCamera && winCamera->getDeviceList().size() >= 1) { graphicsSettings->Add(new ItemHeader(gr->T("Camera"))); PopupMultiChoiceDynamic *cameraChoice = graphicsSettings->Add(new PopupMultiChoiceDynamic(&g_Config.sWinCameraDevice, gr->T("Camera Device"), winCamera->getDeviceList(), nullptr, screenManager())); diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 7de044f077..ff4531beb4 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -37,6 +37,9 @@ #if defined(_WIN32) #include "Windows/WindowsAudio.h" #include "Windows/MainWindow.h" +#endif + +#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP) #include "Windows/CaptureDevice.h" #endif @@ -857,8 +860,8 @@ bool NativeInitGraphics(GraphicsContext *graphicsContext) { #endif #endif -#ifdef _WIN32 - if (IsVistaOrHigher()) { +#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP) + if (IsWin7OrHigher()) { winCamera = new WindowsCaptureDevice(CAPTUREDEVIDE_TYPE::VIDEO); winCamera->sendMessage({ CAPTUREDEVIDE_COMMAND::INITIALIZE, nullptr }); } @@ -888,7 +891,7 @@ void NativeShutdownGraphics() { winAudioBackend = nullptr; #endif -#ifdef _WIN32 +#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP) if (winCamera) { delete winCamera; winCamera = nullptr; diff --git a/Windows/CaptureDevice.cpp b/Windows/CaptureDevice.cpp index d05f4bba4d..ef0907f19e 100644 --- a/Windows/CaptureDevice.cpp +++ b/Windows/CaptureDevice.cpp @@ -24,6 +24,66 @@ #include "Core/HLE/sceUsbCam.h" #include "Core/Config.h" +namespace MFAPI { + HINSTANCE Mflib; + HINSTANCE Mfplatlib; + HINSTANCE Mfreadwritelib; + + typedef HRESULT(WINAPI *MFEnumDeviceSourcesFunc)(IMFAttributes *, IMFActivate ***, UINT32 *); + typedef HRESULT(WINAPI *MFGetStrideForBitmapInfoHeaderFunc)(DWORD, DWORD, LONG *); + typedef HRESULT(WINAPI *MFCreateSourceReaderFromMediaSourceFunc)(IMFMediaSource *, IMFAttributes *, IMFSourceReader **); + typedef HRESULT(WINAPI *MFCopyImageFunc)(BYTE *, LONG, const BYTE *, LONG, DWORD, DWORD); + + MFEnumDeviceSourcesFunc EnumDeviceSources; + MFGetStrideForBitmapInfoHeaderFunc GetStrideForBitmapInfoHeader; + MFCreateSourceReaderFromMediaSourceFunc CreateSourceReaderFromMediaSource; + MFCopyImageFunc CopyImage; +} + +using namespace MFAPI; + +bool RegisterCMPTMFApis(){ + //For the compatibility,these funcs don't be supported on vista. + Mflib = LoadLibrary(L"Mf.dll"); + Mfplatlib = LoadLibrary(L"Mfplat.dll"); + Mfreadwritelib = LoadLibrary(L"Mfreadwrite.dll"); + if (!Mflib || !Mfplatlib || !Mfreadwritelib) + return false; + + EnumDeviceSources = (MFEnumDeviceSourcesFunc)GetProcAddress(Mflib, "MFEnumDeviceSources"); + GetStrideForBitmapInfoHeader = (MFGetStrideForBitmapInfoHeaderFunc)GetProcAddress(Mfplatlib, "MFGetStrideForBitmapInfoHeader"); + MFAPI::CopyImage = (MFCopyImageFunc)GetProcAddress(Mfplatlib, "MFCopyImage"); + CreateSourceReaderFromMediaSource = (MFCreateSourceReaderFromMediaSourceFunc)GetProcAddress(Mfreadwritelib, "MFCreateSourceReaderFromMediaSource"); + if (!EnumDeviceSources || !GetStrideForBitmapInfoHeader || !CreateSourceReaderFromMediaSource || !MFAPI::CopyImage) + return false; + + return true; +} + +bool unRegisterCMPTMFApis() { + if (Mflib) { + FreeLibrary(Mflib); + Mflib = nullptr; + } + + if (Mfplatlib) { + FreeLibrary(Mfplatlib); + Mfplatlib = nullptr; + } + + if (Mfreadwritelib) { + FreeLibrary(Mfreadwritelib); + Mfreadwritelib = nullptr; + } + + EnumDeviceSources = nullptr; + GetStrideForBitmapInfoHeader = nullptr; + CreateSourceReaderFromMediaSource = nullptr; + MFAPI::CopyImage = nullptr; + + return true; +} + WindowsCaptureDevice *winCamera; // TODO: Add more formats, but need some tests. @@ -237,7 +297,7 @@ void ReaderCallback::imgInvert(unsigned char *dst, unsigned char *src, const int } void ReaderCallback::imgInvertRGBA(unsigned char *dst, int &dstStride, unsigned char *src, const int &srcStride, const int &h) { - MFCopyImage(dst, dstStride, src, srcStride, dstStride, h); + MFAPI::CopyImage(dst, dstStride, src, srcStride, dstStride, h); } void ReaderCallback::imgInvertRGB(unsigned char *dst, int &dstStride, unsigned char *src, const int &srcStride, const int &h) { @@ -333,6 +393,11 @@ bool WindowsCaptureDevice::init() { param = { 0 }; IMFAttributes *pAttributes = nullptr; + if (!RegisterCMPTMFApis()) { + setError(CAPTUREDEVIDE_ERROR_INIT_FAILED, "Cannot register devices"); + return false; + } + hr = MFCreateAttributes(&pAttributes, 1); if (SUCCEEDED(hr)) { switch (type) { @@ -357,7 +422,7 @@ bool WindowsCaptureDevice::init() { } if (SUCCEEDED(hr)) - hr = MFEnumDeviceSources(pAttributes, ¶m.ppDevices, ¶m.count); + hr = EnumDeviceSources(pAttributes, ¶m.ppDevices, ¶m.count); if (FAILED(hr)) { setError(CAPTUREDEVIDE_ERROR_INIT_FAILED, "Cannot enumerate devices"); @@ -410,7 +475,7 @@ bool WindowsCaptureDevice::start() { hr = pAttributes->SetUINT32(MF_READWRITE_DISABLE_CONVERTERS, TRUE); if (SUCCEEDED(hr)) { - hr = MFCreateSourceReaderFromMediaSource( + hr = CreateSourceReaderFromMediaSource( m_pSource, pAttributes, &m_pReader @@ -423,13 +488,28 @@ bool WindowsCaptureDevice::start() { if (SUCCEEDED(hr)) { switch (type) { case CAPTUREDEVIDE_TYPE::VIDEO: + for (DWORD i = 0; ; i++) { + hr = m_pReader->GetNativeMediaType( + (DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, + i, + &pType + ); + + if (FAILED(hr)) { break; } + + hr = setDeviceParam(pType); + + if (SUCCEEDED(hr)) + break; + } + /* hr = m_pReader->GetNativeMediaType( (DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, (DWORD)0xFFFFFFFF,//MF_SOURCE_READER_CURRENT_TYPE_INDEX &pType ); if (SUCCEEDED(hr)) - hr = setDeviceParam(pType); + hr = setDeviceParam(pType);*/ // Don't support on Win7 // Request the first frame, in asnyc mode, OnReadSample will be called when ReadSample completed. if (SUCCEEDED(hr)) { @@ -644,6 +724,7 @@ void WindowsCaptureDevice::messageHandler() { SafeRelease(&m_pReader); CoTaskMemFree(param.ppDevices); delete m_pCallback; + unRegisterCMPTMFApis(); MFShutdown(); CoUninitialize(); @@ -680,7 +761,7 @@ HRESULT GetDefaultStride(IMFMediaType *pType, LONG *plStride) } if (SUCCEEDED(hr)) { - hr = MFGetStrideForBitmapInfoHeader(subtype.Data1, width, &lStride); + hr = GetStrideForBitmapInfoHeader(subtype.Data1, width, &lStride); } // Set the attribute for later reference.