mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 13:30:02 +00:00
Merge pull request #12589 from shenweip/winCam-fix
Don't shut down camera when exiting games.
This commit is contained in:
commit
7305ae51f2
@ -319,7 +319,6 @@ int Camera::stopCapture() {
|
||||
#elif defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
|
||||
if (winCamera) {
|
||||
winCamera->sendMessage({ CAPTUREDEVIDE_COMMAND::STOP, nullptr });
|
||||
winCamera->sendMessage({ CAPTUREDEVIDE_COMMAND::SHUTDOWN, nullptr });
|
||||
}
|
||||
#else
|
||||
ERROR_LOG(HLE, "%s not implemented", __FUNCTION__);
|
||||
|
@ -893,6 +893,8 @@ void NativeShutdownGraphics() {
|
||||
|
||||
#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
|
||||
if (winCamera) {
|
||||
winCamera->sendMessage({ CAPTUREDEVIDE_COMMAND::SHUTDOWN, nullptr });
|
||||
while (!winCamera->isShutDown()) {};// Wait for shutting down.
|
||||
delete winCamera;
|
||||
winCamera = nullptr;
|
||||
}
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include "Core/HLE/sceUsbCam.h"
|
||||
#include "Core/Config.h"
|
||||
|
||||
bool isDeviceChanged = false;
|
||||
|
||||
namespace MFAPI {
|
||||
HINSTANCE Mflib;
|
||||
HINSTANCE Mfplatlib;
|
||||
@ -355,6 +357,7 @@ WindowsCaptureDevice::WindowsCaptureDevice(CAPTUREDEVIDE_TYPE type) :
|
||||
error(CAPTUREDEVIDE_ERROR_NO_ERROR),
|
||||
errorMessage(""),
|
||||
state(CAPTUREDEVIDE_STATE::UNINITIALIZED) {
|
||||
param = { 0 };
|
||||
|
||||
switch (type) {
|
||||
case CAPTUREDEVIDE_TYPE::VIDEO:
|
||||
@ -387,50 +390,26 @@ WindowsCaptureDevice::~WindowsCaptureDevice() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
void WindowsCaptureDevice::CheckDevices() {
|
||||
isDeviceChanged = true;
|
||||
}
|
||||
|
||||
bool WindowsCaptureDevice::init() {
|
||||
HRESULT hr = S_OK;
|
||||
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) {
|
||||
case CAPTUREDEVIDE_TYPE::VIDEO:
|
||||
hr = pAttributes->SetGUID(
|
||||
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
|
||||
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
|
||||
);
|
||||
|
||||
break;
|
||||
case CAPTUREDEVIDE_TYPE::AUDIO:
|
||||
hr = pAttributes->SetGUID(
|
||||
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
|
||||
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID
|
||||
);
|
||||
|
||||
break;
|
||||
default:
|
||||
setError(CAPTUREDEVIDE_ERROR_UNKNOWN_TYPE, "Unknown device type");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
hr = EnumDeviceSources(pAttributes, ¶m.ppDevices, ¶m.count);
|
||||
std::unique_lock<std::mutex> lock(paramMutex);
|
||||
hr = enumDevices();
|
||||
lock.unlock();
|
||||
|
||||
if (FAILED(hr)) {
|
||||
setError(CAPTUREDEVIDE_ERROR_INIT_FAILED, "Cannot enumerate devices");
|
||||
SafeRelease(&pAttributes);
|
||||
return false;
|
||||
}
|
||||
|
||||
SafeRelease(&pAttributes);
|
||||
updateState(CAPTUREDEVIDE_STATE::STOPPED);
|
||||
return true;
|
||||
}
|
||||
@ -441,7 +420,16 @@ bool WindowsCaptureDevice::start() {
|
||||
IMFMediaType *pType = nullptr;
|
||||
UINT32 selection = 0;
|
||||
UINT32 count = 0;
|
||||
std::vector<std::string> deviceList = getDeviceList();
|
||||
|
||||
// Release old sources first(if any).
|
||||
SafeRelease(&m_pSource);
|
||||
SafeRelease(&m_pReader);
|
||||
if (m_pCallback) {
|
||||
delete m_pCallback;
|
||||
m_pCallback = nullptr;
|
||||
}
|
||||
// Need to re-enumerate the list,because old sources were released.
|
||||
std::vector<std::string> deviceList = getDeviceList(true);
|
||||
|
||||
if (deviceList.size() < 1) {
|
||||
setError(CAPTUREDEVIDE_ERROR_START_FAILED, "Has no device");
|
||||
@ -511,7 +499,7 @@ bool WindowsCaptureDevice::start() {
|
||||
if (SUCCEEDED(hr))
|
||||
hr = setDeviceParam(pType);*/ // Don't support on Win7
|
||||
|
||||
// Request the first frame, in asnyc mode, OnReadSample will be called when ReadSample completed.
|
||||
// Request the first frame, in async mode, OnReadSample will be called when ReadSample completed.
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = m_pReader->ReadSample(
|
||||
(DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM,
|
||||
@ -572,7 +560,7 @@ bool WindowsCaptureDevice::stop() {
|
||||
return true;
|
||||
};
|
||||
|
||||
std::vector<std::string> WindowsCaptureDevice::getDeviceList(int *pActuallCount) {
|
||||
std::vector<std::string> WindowsCaptureDevice::getDeviceList(bool forceEnum, int *pActuallCount) {
|
||||
HRESULT hr = S_OK;
|
||||
UINT32 count = 0;
|
||||
LPWSTR pwstrName = nullptr;
|
||||
@ -581,6 +569,23 @@ std::vector<std::string> WindowsCaptureDevice::getDeviceList(int *pActuallCount)
|
||||
DWORD dwMinSize = 0;
|
||||
std::vector<std::string> deviceList;
|
||||
|
||||
if (isDeviceChanged || forceEnum) {
|
||||
std::unique_lock<std::mutex> lock(paramMutex);
|
||||
for (DWORD i = 0; i < param.count; i++) {
|
||||
SafeRelease(¶m.ppDevices[i]);
|
||||
}
|
||||
CoTaskMemFree(param.ppDevices); // Null pointer is okay.
|
||||
|
||||
hr = enumDevices();
|
||||
|
||||
lock.unlock();
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
isDeviceChanged = false;
|
||||
else
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
for (; count < param.count; count++) {
|
||||
hr = param.ppDevices[count]->GetAllocatedString(
|
||||
MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME,
|
||||
@ -722,17 +727,54 @@ void WindowsCaptureDevice::messageHandler() {
|
||||
std::lock_guard<std::mutex> lock(sdMutex);
|
||||
SafeRelease(&m_pSource);
|
||||
SafeRelease(&m_pReader);
|
||||
CoTaskMemFree(param.ppDevices);
|
||||
delete m_pCallback;
|
||||
unRegisterCMPTMFApis();
|
||||
|
||||
std::unique_lock<std::mutex> lock2(paramMutex);
|
||||
for (DWORD i = 0; i < param.count; i++) {
|
||||
SafeRelease(¶m.ppDevices[i]);
|
||||
}
|
||||
CoTaskMemFree(param.ppDevices); // Null pointer is okay.
|
||||
lock2.unlock();
|
||||
|
||||
MFShutdown();
|
||||
CoUninitialize();
|
||||
|
||||
updateState(CAPTUREDEVIDE_STATE::SHUTDOWN);
|
||||
}
|
||||
|
||||
// Make sure we don't try to loop through the devices later in getDeviceList()...
|
||||
param = {};
|
||||
HRESULT WindowsCaptureDevice::enumDevices() {
|
||||
HRESULT hr = S_OK;
|
||||
IMFAttributes *pAttributes = nullptr;
|
||||
|
||||
hr = MFCreateAttributes(&pAttributes, 1);
|
||||
if (SUCCEEDED(hr)) {
|
||||
switch (type) {
|
||||
case CAPTUREDEVIDE_TYPE::VIDEO:
|
||||
hr = pAttributes->SetGUID(
|
||||
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
|
||||
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
|
||||
);
|
||||
|
||||
break;
|
||||
case CAPTUREDEVIDE_TYPE::AUDIO:
|
||||
hr = pAttributes->SetGUID(
|
||||
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
|
||||
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID
|
||||
);
|
||||
|
||||
break;
|
||||
default:
|
||||
setError(CAPTUREDEVIDE_ERROR_UNKNOWN_TYPE, "Unknown device type");
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = EnumDeviceSources(pAttributes, ¶m.ppDevices, ¶m.count);
|
||||
}
|
||||
|
||||
SafeRelease(&pAttributes);
|
||||
return hr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -160,6 +160,8 @@ public:
|
||||
WindowsCaptureDevice(CAPTUREDEVIDE_TYPE type);
|
||||
~WindowsCaptureDevice();
|
||||
|
||||
static void CheckDevices();
|
||||
|
||||
bool init();
|
||||
bool start();
|
||||
bool stop();
|
||||
@ -168,7 +170,7 @@ public:
|
||||
std::string getErrorMessage() const { return errorMessage; }
|
||||
int getDeviceCounts() const { return param.count; }
|
||||
// Get a list contained friendly device name.
|
||||
std::vector<std::string> getDeviceList(int *pActuallCount = nullptr);
|
||||
std::vector<std::string> getDeviceList(bool forceEnum = false, int *pActuallCount = nullptr);
|
||||
|
||||
void setError(const CAPTUREDEVIDE_ERROR &newError, const std::string &newErrorMessage) { error = newError; errorMessage = newErrorMessage; }
|
||||
void setSelction(const UINT32 &selection) { param.selection = selection; }
|
||||
@ -180,6 +182,8 @@ public:
|
||||
void sendMessage(CAPTUREDEVIDE_MESSAGE message);
|
||||
CAPTUREDEVIDE_MESSAGE getMessage();
|
||||
|
||||
HRESULT enumDevices();
|
||||
|
||||
friend class ReaderCallback;
|
||||
|
||||
protected:
|
||||
@ -208,6 +212,9 @@ protected:
|
||||
// For the shutdown event safety.
|
||||
std::mutex sdMutex;
|
||||
|
||||
// Param updating synchronously.
|
||||
std::mutex paramMutex;
|
||||
|
||||
// Camera only
|
||||
unsigned char *imageRGB;
|
||||
int imgRGBLineSizes[4];
|
||||
|
@ -72,6 +72,7 @@
|
||||
#include "Windows/W32Util/ShellUtil.h"
|
||||
#include "Windows/W32Util/Misc.h"
|
||||
#include "Windows/RawInput.h"
|
||||
#include "Windows/CaptureDevice.h"
|
||||
#include "Windows/TouchInputHandler.h"
|
||||
#include "Windows/MainWindowMenu.h"
|
||||
#include "GPU/GPUInterface.h"
|
||||
@ -848,6 +849,7 @@ namespace MainWindow
|
||||
#ifndef _M_ARM
|
||||
DinputDevice::CheckDevices();
|
||||
#endif
|
||||
WindowsCaptureDevice::CheckDevices();
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
|
||||
case WM_VERYSLEEPY_MSG:
|
||||
|
Loading…
Reference in New Issue
Block a user