mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Merge pull request #12580 from Florin9doi/v4l2b
Add camera support for linux (V4L2)
This commit is contained in:
@@ -1668,6 +1668,8 @@ add_library(${CoreLibName} ${CoreLinkType}
|
||||
Core/HW/SimpleAudioDec.h
|
||||
Core/HW/AsyncIOManager.cpp
|
||||
Core/HW/AsyncIOManager.h
|
||||
Core/HW/Camera.cpp
|
||||
Core/HW/Camera.h
|
||||
Core/HW/MediaEngine.cpp
|
||||
Core/HW/MediaEngine.h
|
||||
Core/HW/MpegDemux.cpp
|
||||
|
||||
+2
-2
@@ -707,8 +707,8 @@ static ConfigSetting graphicsSettings[] = {
|
||||
#ifdef _WIN32
|
||||
ConfigSetting("D3D11Device", &g_Config.sD3D11Device, "", true, false),
|
||||
#endif
|
||||
#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
|
||||
ConfigSetting("WinCameraDevice", &g_Config.sWinCameraDevice, "", true, false),
|
||||
#if (defined(_WIN32) && !PPSSPP_PLATFORM(UWP)) || PPSSPP_PLATFORM(LINUX)
|
||||
ConfigSetting("CameraDevice", &g_Config.sCameraDevice, "", true, false),
|
||||
#endif
|
||||
ConfigSetting("VendorBugChecksEnabled", &g_Config.bVendorBugChecksEnabled, true, false, false),
|
||||
ReportedConfigSetting("RenderingMode", &g_Config.iRenderingMode, 1, true, true),
|
||||
|
||||
+1
-1
@@ -128,7 +128,7 @@ public:
|
||||
// If not set, will use the "best" device.
|
||||
std::string sVulkanDevice;
|
||||
std::string sD3D11Device; // Windows only
|
||||
std::string sWinCameraDevice; // Windows only
|
||||
std::string sCameraDevice;
|
||||
|
||||
bool bSoftwareRendering;
|
||||
bool bHardwareTransform; // only used in the GLES backend
|
||||
|
||||
@@ -375,6 +375,7 @@
|
||||
<ClCompile Include="HLE\sceUsbAcc.cpp" />
|
||||
<ClCompile Include="HLE\sceUsbCam.cpp" />
|
||||
<ClCompile Include="HLE\sceUsbMic.cpp" />
|
||||
<ClCompile Include="HW\Camera.cpp" />
|
||||
<ClCompile Include="MIPS\IR\IRAsm.cpp" />
|
||||
<ClCompile Include="MIPS\IR\IRCompALU.cpp" />
|
||||
<ClCompile Include="MIPS\IR\IRCompBranch.cpp" />
|
||||
@@ -903,6 +904,7 @@
|
||||
<ClInclude Include="HLE\sceUsbAcc.h" />
|
||||
<ClInclude Include="HLE\sceUsbCam.h" />
|
||||
<ClInclude Include="HLE\sceUsbMic.h" />
|
||||
<ClInclude Include="HW\Camera.h" />
|
||||
<ClInclude Include="MIPS\IR\IRFrontend.h" />
|
||||
<ClInclude Include="MIPS\IR\IRInst.h" />
|
||||
<ClInclude Include="MIPS\IR\IRInterpreter.h" />
|
||||
|
||||
@@ -740,6 +740,9 @@
|
||||
<ClCompile Include="HLE\sceUsbMic.cpp">
|
||||
<Filter>HLE\Libraries</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HW\Camera.cpp">
|
||||
<Filter>HW</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ELF\ElfReader.h">
|
||||
@@ -1373,6 +1376,9 @@
|
||||
<ClInclude Include="HLE\sceUsbMic.h">
|
||||
<Filter>HLE\Libraries</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HW\Camera.h">
|
||||
<Filter>HW</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CMakeLists.txt" />
|
||||
|
||||
+12
-2
@@ -99,6 +99,16 @@ static int sceUsbDeactivate(u32 pid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sceUsbWaitState(int state, int waitMode, u32 timeoutAddr) {
|
||||
ERROR_LOG(HLE, "UNIMPL sceUsbWaitStat(%i, %i, %08x)", state, waitMode, timeoutAddr);
|
||||
return sceUsbGetState();
|
||||
}
|
||||
|
||||
static int sceUsbWaitStateCB(int state, int waitMode, u32 timeoutAddr) {
|
||||
ERROR_LOG(HLE, "UNIMPL sceUsbWaitStateCB(%i, %i, %08x)", state, waitMode, timeoutAddr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const HLEFunction sceUsb[] =
|
||||
{
|
||||
{0XAE5DE6AF, &WrapI_CUU<sceUsbStart>, "sceUsbStart", 'i', "sxx"},
|
||||
@@ -108,8 +118,8 @@ const HLEFunction sceUsb[] =
|
||||
{0X112CC951, nullptr, "sceUsbGetDrvState", '?', "" },
|
||||
{0X586DB82C, &WrapI_U<sceUsbActivate>, "sceUsbActivate", 'i', "x" },
|
||||
{0XC572A9C8, &WrapI_U<sceUsbDeactivate>, "sceUsbDeactivate", 'i', "x" },
|
||||
{0X5BE0E002, nullptr, "sceUsbWaitState", '?', "" },
|
||||
{0X616F2B61, nullptr, "sceUsbWaitStateCB", '?', "" },
|
||||
{0X5BE0E002, &WrapI_IIU<sceUsbWaitState>, "sceUsbWaitState", '?', "xxx"},
|
||||
{0X616F2B61, &WrapI_IIU<sceUsbWaitStateCB>, "sceUsbWaitStateCB", '?', "xxx"},
|
||||
{0X1C360735, nullptr, "sceUsbWaitCancel", '?', "" },
|
||||
};
|
||||
|
||||
|
||||
+156
-60
@@ -19,55 +19,95 @@
|
||||
#include <mutex>
|
||||
|
||||
#include "base/NativeApp.h"
|
||||
#include "ppsspp_config.h"
|
||||
#include "Common/ChunkFile.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "Core/HLE/FunctionWrappers.h"
|
||||
#include "Core/HLE/sceUsbCam.h"
|
||||
#include "Core/HW/Camera.h"
|
||||
#include "Core/MemMapHelpers.h"
|
||||
|
||||
#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#include "Windows/CaptureDevice.h"
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
|
||||
PspUsbCamSetupMicParam micParam;
|
||||
PspUsbCamSetupVideoParam videoParam;
|
||||
Camera::Config *config;
|
||||
|
||||
unsigned int videoBufferLength = 0;
|
||||
unsigned int nextVideoFrame = 0;
|
||||
uint8_t *videoBuffer;
|
||||
std::mutex videoBufferMutex;
|
||||
bool isShutDown = false;
|
||||
|
||||
enum {
|
||||
VIDEO_BUFFER_SIZE = 40 * 1000,
|
||||
};
|
||||
|
||||
void __UsbCamInit() {
|
||||
videoBuffer = new uint8_t[VIDEO_BUFFER_SIZE];
|
||||
isShutDown = false;
|
||||
config = new Camera::Config;
|
||||
config->mode = Camera::Mode::Unused;
|
||||
config->type = Camera::ConfigType::CfNone;
|
||||
videoBuffer = new uint8_t[VIDEO_BUFFER_SIZE];
|
||||
}
|
||||
|
||||
void __UsbCamDoState(PointerWrap &p) {
|
||||
auto s = p.Section("sceUsbCam", 0, 1);
|
||||
if (!s) {
|
||||
return;
|
||||
}
|
||||
|
||||
p.Do(*config);
|
||||
if (config->mode == Camera::Mode::Video) { // stillImage? TBD
|
||||
Camera::startCapture();
|
||||
}
|
||||
}
|
||||
|
||||
void __UsbCamShutdown() {
|
||||
#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
|
||||
if (winCamera) {
|
||||
winCamera->sendMessage({ CAPTUREDEVIDE_COMMAND::SHUTDOWN, nullptr });
|
||||
}
|
||||
#endif
|
||||
isShutDown = true;
|
||||
|
||||
Camera::stopCapture();
|
||||
delete[] videoBuffer;
|
||||
videoBuffer = nullptr;
|
||||
delete[] config;
|
||||
config = nullptr;
|
||||
}
|
||||
|
||||
// TODO: Technically, we should store the videoBuffer into the savestate, if this
|
||||
// module has been initialized.
|
||||
|
||||
static int getCameraResolution(Camera::ConfigType type, int *width, int *height) {
|
||||
if (type == Camera::ConfigType::CfStill || type == Camera::ConfigType::CfVideo) {
|
||||
switch(config->stillParam.resolution) {
|
||||
case 0: *width = 160; *height = 120; return 0;
|
||||
case 1: *width = 176; *height = 144; return 0;
|
||||
case 2: *width = 320; *height = 240; return 0;
|
||||
case 3: *width = 352; *height = 288; return 0;
|
||||
case 4: *width = 640; *height = 480; return 0;
|
||||
case 5: *width =1024; *height = 768; return 0;
|
||||
case 6: *width =1280; *height = 960; return 0;
|
||||
case 7: *width = 480; *height = 272; return 0;
|
||||
case 8: *width = 360; *height = 272; return 0;
|
||||
}
|
||||
} else if (type == Camera::ConfigType::CfStillEx || type == Camera::ConfigType::CfVideoEx) {
|
||||
switch(config->stillExParam.resolution) {
|
||||
case 0: *width = 160; *height = 120; return 0;
|
||||
case 1: *width = 176; *height = 144; return 0;
|
||||
case 2: *width = 320; *height = 240; return 0;
|
||||
case 3: *width = 352; *height = 288; return 0;
|
||||
case 4: *width = 360; *height = 272; return 0;
|
||||
case 5: *width = 480; *height = 272; return 0;
|
||||
case 6: *width = 640; *height = 480; return 0;
|
||||
case 7: *width =1024; *height = 768; return 0;
|
||||
case 8: *width =1280; *height = 960; return 0;
|
||||
}
|
||||
}
|
||||
*width = 0; *height = 0; return 1;
|
||||
}
|
||||
|
||||
|
||||
static int sceUsbCamSetupMic(u32 paramAddr, u32 workareaAddr, int wasize) {
|
||||
INFO_LOG(HLE, "UNIMPL sceUsbCamSetupMic");
|
||||
if (Memory::IsValidRange(paramAddr, sizeof(micParam))) {
|
||||
Memory::ReadStruct(paramAddr, &micParam);
|
||||
if (Memory::IsValidRange(paramAddr, sizeof(PspUsbCamSetupMicParam))) {
|
||||
Memory::ReadStruct(paramAddr, &config->micParam);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -89,59 +129,37 @@ static int sceUsbCamReadMicBlocking(u32 bufAddr, u32 size) {
|
||||
Memory::Write_U8(i & 0xFF, bufAddr + i);
|
||||
}
|
||||
}
|
||||
hleEatMicro(1000000 / micParam.frequency * (size / 2));
|
||||
hleEatMicro(1000000 / config->micParam.frequency * (size / 2));
|
||||
return size;
|
||||
}
|
||||
|
||||
static int sceUsbCamSetupVideo(u32 paramAddr, u32 workareaAddr, int wasize) {
|
||||
INFO_LOG(HLE, "UNIMPL sceUsbCamSetupVideo");
|
||||
if (Memory::IsValidRange(paramAddr, sizeof(videoParam))) {
|
||||
Memory::ReadStruct(paramAddr, &videoParam);
|
||||
if (Memory::IsValidRange(paramAddr, sizeof(PspUsbCamSetupVideoParam))) {
|
||||
Memory::ReadStruct(paramAddr, &config->videoParam);
|
||||
}
|
||||
config->type = Camera::ConfigType::CfVideo;
|
||||
return 0;
|
||||
}
|
||||
|
||||
INFO_LOG(HLE, "UNIMPL sceUsbCamSetupVideo - size: %d", videoParam.size);
|
||||
INFO_LOG(HLE, "UNIMPL sceUsbCamSetupVideo - resolution: %d", videoParam.resolution);
|
||||
INFO_LOG(HLE, "UNIMPL sceUsbCamSetupVideo - framesize: %d", videoParam.framesize);
|
||||
|
||||
std::lock_guard<std::mutex> lock(videoBufferMutex);
|
||||
videoBufferLength = sizeof(sceUsbCamDummyImage);
|
||||
memset(videoBuffer, 0, VIDEO_BUFFER_SIZE);
|
||||
memcpy(videoBuffer, sceUsbCamDummyImage, sizeof(sceUsbCamDummyImage));
|
||||
static int sceUsbCamSetupVideoEx(u32 paramAddr, u32 workareaAddr, int wasize) {
|
||||
if (Memory::IsValidRange(paramAddr, sizeof(PspUsbCamSetupVideoExParam))) {
|
||||
Memory::ReadStruct(paramAddr, &config->videoExParam);
|
||||
}
|
||||
config->type = Camera::ConfigType::CfVideoEx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sceUsbCamStartVideo() {
|
||||
INFO_LOG(HLE, "UNIMPL sceUsbCamStartVideo");
|
||||
#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
|
||||
if (winCamera) {
|
||||
if (winCamera->isShutDown()) {
|
||||
delete winCamera;
|
||||
winCamera = new WindowsCaptureDevice(CAPTUREDEVIDE_TYPE::VIDEO);
|
||||
winCamera->sendMessage({ CAPTUREDEVIDE_COMMAND::INITIALIZE, nullptr });
|
||||
}
|
||||
|
||||
winCamera->sendMessage({ CAPTUREDEVIDE_COMMAND::START, nullptr });
|
||||
}
|
||||
|
||||
#else
|
||||
System_SendMessage("camera_command", "startVideo");
|
||||
#endif
|
||||
std::lock_guard<std::mutex> lock(videoBufferMutex);
|
||||
videoBufferLength = sizeof(sceUsbCamDummyImage);
|
||||
memset(videoBuffer, 0, VIDEO_BUFFER_SIZE);
|
||||
memcpy(videoBuffer, sceUsbCamDummyImage, sizeof(sceUsbCamDummyImage));
|
||||
Camera::startCapture();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sceUsbCamStopVideo() {
|
||||
INFO_LOG(HLE, "UNIMPL sceUsbCamStopVideo");
|
||||
#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
|
||||
if (winCamera)
|
||||
winCamera->sendMessage({ CAPTUREDEVIDE_COMMAND::STOP, nullptr });
|
||||
#else
|
||||
System_SendMessage("camera_command", "stopVideo");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sceUsbCamAutoImageReverseSW(int rev) {
|
||||
INFO_LOG(HLE, "UNIMPL sceUsbCamAutoImageReverseSW");
|
||||
Camera::stopCapture();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -169,6 +187,29 @@ static int sceUsbCamPollReadVideoFrameEnd() {
|
||||
return nextVideoFrame;
|
||||
}
|
||||
|
||||
static int sceUsbCamSetupStill(u32 paramAddr) {
|
||||
INFO_LOG(HLE, "UNIMPL sceUsbCamSetupStill");
|
||||
if (Memory::IsValidRange(paramAddr, sizeof(PspUsbCamSetupStillParam))) {
|
||||
Memory::ReadStruct(paramAddr, &config->stillParam);
|
||||
}
|
||||
config->type = Camera::ConfigType::CfStill;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sceUsbCamSetupStillEx(u32 paramAddr) {
|
||||
INFO_LOG(HLE, "UNIMPL sceUsbCamSetupStillEx");
|
||||
if (Memory::IsValidRange(paramAddr, sizeof(PspUsbCamSetupStillExParam))) {
|
||||
Memory::ReadStruct(paramAddr, &config->stillExParam);
|
||||
}
|
||||
config->type = Camera::ConfigType::CfStillEx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sceUsbCamAutoImageReverseSW(int rev) {
|
||||
INFO_LOG(HLE, "UNIMPL sceUsbCamAutoImageReverseSW");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const HLEFunction sceUsbCam[] =
|
||||
{
|
||||
{ 0X03ED7A82, &WrapI_UUI<sceUsbCamSetupMic>, "sceUsbCamSetupMic", 'i', "xxi" },
|
||||
@@ -183,7 +224,7 @@ const HLEFunction sceUsbCam[] =
|
||||
{ 0X08AEE98A, nullptr, "sceUsbCamSetMicGain", '?', "" },
|
||||
|
||||
{ 0X17F7B2FB, &WrapI_UUI<sceUsbCamSetupVideo>, "sceUsbCamSetupVideo", 'i', "xxi" },
|
||||
{ 0XCFE9E999, nullptr, "sceUsbCamSetupVideoEx", '?', "" },
|
||||
{ 0XCFE9E999, &WrapI_UUI<sceUsbCamSetupVideoEx>, "sceUsbCamSetupVideoEx", 'i', "xxi" },
|
||||
{ 0X574A8C3F, &WrapI_V<sceUsbCamStartVideo>, "sceUsbCamStartVideo", 'i', "" },
|
||||
{ 0X6CF32CB9, &WrapI_V<sceUsbCamStopVideo>, "sceUsbCamStopVideo", 'i', "" },
|
||||
{ 0X7DAC0C71, &WrapI_UU<sceUsbCamReadVideoFrameBlocking>, "sceUsbCamReadVideoFrameBlocking", 'i', "xx" },
|
||||
@@ -192,8 +233,8 @@ const HLEFunction sceUsbCam[] =
|
||||
{ 0X41E73E95, &WrapI_V<sceUsbCamPollReadVideoFrameEnd>, "sceUsbCamPollReadVideoFrameEnd", 'i', "" },
|
||||
{ 0XDF9D0C92, nullptr, "sceUsbCamGetReadVideoFrameSize", '?', "" },
|
||||
|
||||
{ 0X3F0CF289, nullptr, "sceUsbCamSetupStill", '?', "" },
|
||||
{ 0X0A41A298, nullptr, "sceUsbCamSetupStillEx", '?', "" },
|
||||
{ 0X3F0CF289, &WrapI_U<sceUsbCamSetupStill>, "sceUsbCamSetupStill", 'i', "x" },
|
||||
{ 0X0A41A298, &WrapI_U<sceUsbCamSetupStillEx>, "sceUsbCamSetupStillEx", 'i', "x" },
|
||||
{ 0X61BE5CAC, nullptr, "sceUsbCamStillInputBlocking", '?', "" },
|
||||
{ 0XFB0A6C5D, nullptr, "sceUsbCamStillInput", '?', "" },
|
||||
{ 0X7563AFA1, nullptr, "sceUsbCamStillWaitInputEnd", '?', "" },
|
||||
@@ -233,10 +274,65 @@ void Register_sceUsbCam()
|
||||
RegisterModule("sceUsbCam", ARRAY_SIZE(sceUsbCam), sceUsbCam);
|
||||
}
|
||||
|
||||
std::vector<std::string> Camera::getDeviceList() {
|
||||
#if PPSSPP_PLATFORM(LINUX) && !PPSSPP_PLATFORM(ANDROID)
|
||||
return __v4l_getDeviceList();
|
||||
#elif defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
|
||||
if (winCamera) {
|
||||
return winCamera->getDeviceList();
|
||||
}
|
||||
#endif
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
|
||||
int Camera::startCapture() {
|
||||
int width, height;
|
||||
getCameraResolution(config->type, &width, &height);
|
||||
INFO_LOG(HLE, "%s resolution: %dx%d", __FUNCTION__, width, height);
|
||||
|
||||
config->mode = Camera::Mode::Video;
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
System_SendMessage("camera_command", "startVideo");
|
||||
#elif PPSSPP_PLATFORM(LINUX)
|
||||
__v4l_startCapture(width, height);
|
||||
#elif defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
|
||||
if (winCamera) {
|
||||
if (winCamera->isShutDown()) {
|
||||
delete winCamera;
|
||||
winCamera = new WindowsCaptureDevice(CAPTUREDEVIDE_TYPE::VIDEO);
|
||||
winCamera->sendMessage({ CAPTUREDEVIDE_COMMAND::INITIALIZE, nullptr });
|
||||
}
|
||||
winCamera->sendMessage({ CAPTUREDEVIDE_COMMAND::START, nullptr });
|
||||
}
|
||||
#else
|
||||
ERROR_LOG(HLE, "%s not implemented", __FUNCTION__);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Camera::stopCapture() {
|
||||
INFO_LOG(HLE, "%s", __FUNCTION__);
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
System_SendMessage("camera_command", "stopVideo");
|
||||
#elif PPSSPP_PLATFORM(LINUX)
|
||||
__v4l_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__);
|
||||
#endif
|
||||
config->mode = Camera::Mode::Unused;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Camera::pushCameraImage(long long length, unsigned char* image) {
|
||||
std::lock_guard<std::mutex> lock(videoBufferMutex);
|
||||
if (isShutDown)
|
||||
if (!videoBuffer) {
|
||||
return;
|
||||
}
|
||||
memset(videoBuffer, 0, VIDEO_BUFFER_SIZE);
|
||||
if (length > VIDEO_BUFFER_SIZE) {
|
||||
videoBufferLength = 0;
|
||||
|
||||
+79
-6
@@ -17,16 +17,18 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "Core/HLE/FunctionWrappers.h"
|
||||
|
||||
void Register_sceUsbCam();
|
||||
|
||||
void __UsbCamInit();
|
||||
void __UsbCamDoState(PointerWrap &p);
|
||||
void __UsbCamShutdown();
|
||||
|
||||
namespace Camera {
|
||||
void pushCameraImage(long long length, unsigned char *image);
|
||||
}
|
||||
|
||||
typedef struct PspUsbCamSetupMicParam {
|
||||
typedef struct {
|
||||
int size;
|
||||
u32 unk;
|
||||
int gain;
|
||||
@@ -34,7 +36,30 @@ typedef struct PspUsbCamSetupMicParam {
|
||||
int frequency;
|
||||
} PspUsbCamSetupMicParam;
|
||||
|
||||
typedef struct PspUsbCamSetupVideoParam {
|
||||
typedef struct {
|
||||
int size;
|
||||
int resolution;
|
||||
int jpegsize;
|
||||
int reverseflags;
|
||||
int delay;
|
||||
int complevel;
|
||||
} PspUsbCamSetupStillParam;
|
||||
|
||||
typedef struct {
|
||||
int size;
|
||||
u32 unk;
|
||||
int resolution;
|
||||
int jpegsize;
|
||||
int complevel;
|
||||
u32 unk2;
|
||||
u32 unk3;
|
||||
int flip;
|
||||
int mirror;
|
||||
int delay;
|
||||
u32 unk4[5];
|
||||
} PspUsbCamSetupStillExParam;
|
||||
|
||||
typedef struct {
|
||||
int size;
|
||||
int resolution;
|
||||
int framerate;
|
||||
@@ -49,6 +74,54 @@ typedef struct PspUsbCamSetupVideoParam {
|
||||
int evlevel;
|
||||
} PspUsbCamSetupVideoParam;
|
||||
|
||||
typedef struct {
|
||||
int size;
|
||||
u32 unk;
|
||||
int resolution;
|
||||
int framerate;
|
||||
u32 unk2;
|
||||
u32 unk3;
|
||||
int wb;
|
||||
int saturation;
|
||||
int brightness;
|
||||
int contrast;
|
||||
int sharpness;
|
||||
u32 unk4;
|
||||
u32 unk5;
|
||||
u32 unk6[3];
|
||||
int effectmode;
|
||||
u32 unk7;
|
||||
u32 unk8;
|
||||
u32 unk9;
|
||||
u32 unk10;
|
||||
u32 unk11;
|
||||
int framesize;
|
||||
u32 unk12;
|
||||
int evlevel;
|
||||
} PspUsbCamSetupVideoExParam;
|
||||
|
||||
namespace Camera {
|
||||
enum Mode { Unused, Still, Video };
|
||||
enum ConfigType { CfNone, CfStill, CfStillEx, CfVideo, CfVideoEx };
|
||||
|
||||
typedef struct {
|
||||
Mode mode;
|
||||
ConfigType type;
|
||||
PspUsbCamSetupMicParam micParam;
|
||||
union {
|
||||
PspUsbCamSetupStillParam stillParam;
|
||||
PspUsbCamSetupStillExParam stillExParam;
|
||||
PspUsbCamSetupVideoParam videoParam;
|
||||
PspUsbCamSetupVideoExParam videoExParam;
|
||||
};
|
||||
} Config;
|
||||
|
||||
std::vector<std::string> getDeviceList();
|
||||
int startCapture();
|
||||
int stopCapture();
|
||||
void pushCameraImage(long long length, unsigned char *image);
|
||||
}
|
||||
|
||||
static const unsigned char sceUsbCamDummyImage[] = {
|
||||
0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x00, 0x60,
|
||||
0x00, 0x60, 0x00, 0x00, 0xFF, 0xE1, 0x00, 0x68, 0x45, 0x78, 0x69, 0x66, 0x00, 0x00, 0x4D, 0x4D,
|
||||
|
||||
@@ -0,0 +1,314 @@
|
||||
// Copyright (c) 2020- PPSSPP Project.
|
||||
|
||||
// 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, version 2.0 or later versions.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include "Camera.h"
|
||||
|
||||
#if PPSSPP_PLATFORM(LINUX) && !PPSSPP_PLATFORM(ANDROID)
|
||||
|
||||
std::vector<std::string> __v4l_getDeviceList() {
|
||||
std::vector<std::string> deviceList;
|
||||
for (int i = 0; i < 64; i++) {
|
||||
char path[256];
|
||||
snprintf(path, sizeof(path), "/dev/video%d", i);
|
||||
if (access(path, F_OK) < 0) {
|
||||
break;
|
||||
}
|
||||
int fd = -1;
|
||||
if((fd = open(path, O_RDONLY)) < 0) {
|
||||
ERROR_LOG(HLE, "Cannot open '%s'; errno=%d(%s)", path, errno, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
struct v4l2_capability video_cap;
|
||||
if(ioctl(fd, VIDIOC_QUERYCAP, &video_cap) < 0) {
|
||||
ERROR_LOG(HLE, "VIDIOC_QUERYCAP");
|
||||
goto cont;
|
||||
} else {
|
||||
char device[256];
|
||||
snprintf(device, sizeof(device), "%d:%s", i, video_cap.card);
|
||||
deviceList.push_back(device);
|
||||
}
|
||||
cont:
|
||||
close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
void convert_frame(unsigned char *inData, AVPixelFormat inFormat, unsigned char **outData, int *outLen) {
|
||||
// resize
|
||||
uint8_t *src[4] = {0};
|
||||
uint8_t *dst[4] = {0};
|
||||
int srcStride[4], dstStride[4];
|
||||
|
||||
unsigned char *rgbData = (unsigned char*)malloc(v4l_ideal_width * v4l_ideal_height * 3);
|
||||
|
||||
av_image_fill_linesizes(srcStride, inFormat, v4l_hw_width);
|
||||
av_image_fill_linesizes(dstStride, AV_PIX_FMT_RGB24, v4l_ideal_width);
|
||||
|
||||
av_image_fill_pointers(src, inFormat, v4l_hw_height, inData, srcStride);
|
||||
av_image_fill_pointers(dst, AV_PIX_FMT_RGB24, v4l_ideal_height, rgbData, dstStride);
|
||||
|
||||
sws_scale(sws_context,
|
||||
src, srcStride, 0, v4l_height_fixed_aspect,
|
||||
dst, dstStride);
|
||||
|
||||
// compress jpeg
|
||||
*outLen = v4l_ideal_width * v4l_ideal_height * 3;
|
||||
*outData = (unsigned char*)malloc(*outLen);
|
||||
|
||||
jpge::params params;
|
||||
params.m_quality = 60;
|
||||
params.m_subsampling = jpge::H2V2;
|
||||
params.m_two_pass_flag = false;
|
||||
jpge::compress_image_to_jpeg_file_in_memory(
|
||||
*outData, *outLen, v4l_ideal_width, v4l_ideal_height, 3, rgbData, params);
|
||||
free(rgbData);
|
||||
}
|
||||
|
||||
void *v4l_loop(void *data) {
|
||||
setCurrentThreadName("v4l_loop");
|
||||
while (v4l_fd >= 0) {
|
||||
struct v4l2_buffer buf;
|
||||
memset(&buf, 0, sizeof(buf));
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
buf.memory = V4L2_MEMORY_MMAP;
|
||||
|
||||
if (ioctl(v4l_fd, VIDIOC_DQBUF, &buf) == -1) {
|
||||
ERROR_LOG(HLE, "VIDIOC_DQBUF; errno=%d(%s)", errno, strerror(errno));
|
||||
switch (errno) {
|
||||
case EAGAIN:
|
||||
continue;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char *jpegData;
|
||||
int jpegLen;
|
||||
|
||||
if (v4l_format == V4L2_PIX_FMT_YUYV) {
|
||||
convert_frame((unsigned char*)v4l_buffer, AV_PIX_FMT_YUYV422, &jpegData, &jpegLen);
|
||||
} else if (v4l_format == V4L2_PIX_FMT_MJPEG) {
|
||||
// decompress jpeg
|
||||
int width, height, req_comps;
|
||||
unsigned char *rgbData = jpgd::decompress_jpeg_image_from_memory(
|
||||
(unsigned char*)v4l_buffer, buf.bytesused, &width, &height, &req_comps, 3);
|
||||
|
||||
convert_frame(rgbData, AV_PIX_FMT_RGB24, &jpegData, &jpegLen);
|
||||
free(rgbData);
|
||||
}
|
||||
|
||||
Camera::pushCameraImage(jpegLen, jpegData);
|
||||
free(jpegData);
|
||||
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
buf.memory = V4L2_MEMORY_MMAP;
|
||||
if (ioctl(v4l_fd, VIDIOC_QBUF, &buf) == -1) {
|
||||
ERROR_LOG(HLE, "VIDIOC_QBUF");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int __v4l_startCapture(int ideal_width, int ideal_height) {
|
||||
if (v4l_fd >= 0) {
|
||||
__v4l_stopCapture();
|
||||
}
|
||||
v4l_ideal_width = ideal_width;
|
||||
v4l_ideal_height = ideal_height;
|
||||
|
||||
int dev_index = 0;
|
||||
char dev_name[64];
|
||||
sscanf(g_Config.sCameraDevice.c_str(), "%d:", &dev_index);
|
||||
snprintf(dev_name, sizeof(dev_name), "/dev/video%d", dev_index);
|
||||
|
||||
if ((v4l_fd = open(dev_name, O_RDWR)) == -1) {
|
||||
ERROR_LOG(HLE, "Cannot open '%s'; errno=%d(%s)", dev_name, errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct v4l2_capability cap;
|
||||
memset(&cap, 0, sizeof(cap));
|
||||
if (ioctl(v4l_fd, VIDIOC_QUERYCAP, &cap) == -1) {
|
||||
ERROR_LOG(HLE, "VIDIOC_QUERYCAP");
|
||||
return -1;
|
||||
}
|
||||
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
|
||||
ERROR_LOG(HLE, "V4L2_CAP_VIDEO_CAPTURE");
|
||||
return -1;
|
||||
}
|
||||
if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
|
||||
ERROR_LOG(HLE, "V4L2_CAP_STREAMING");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct v4l2_format fmt;
|
||||
memset(&fmt, 0, sizeof(fmt));
|
||||
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
fmt.fmt.pix.pixelformat = 0;
|
||||
|
||||
// select a pixel format
|
||||
struct v4l2_fmtdesc desc;
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
desc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
while (ioctl(v4l_fd, VIDIOC_ENUM_FMT, &desc) == 0) {
|
||||
desc.index++;
|
||||
INFO_LOG(HLE, "V4L2: pixel format supported: %s", desc.description);
|
||||
if (fmt.fmt.pix.pixelformat != 0) {
|
||||
continue;
|
||||
} else if (desc.pixelformat == V4L2_PIX_FMT_YUYV
|
||||
|| desc.pixelformat == V4L2_PIX_FMT_MJPEG) {
|
||||
INFO_LOG(HLE, "V4L2: %s selected", desc.description);
|
||||
fmt.fmt.pix.pixelformat = desc.pixelformat;
|
||||
v4l_format = desc.pixelformat;
|
||||
}
|
||||
}
|
||||
if (fmt.fmt.pix.pixelformat == 0) {
|
||||
ERROR_LOG(HLE, "V4L2: No supported format found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// select a frame size
|
||||
fmt.fmt.pix.width = 0;
|
||||
fmt.fmt.pix.height = 0;
|
||||
struct v4l2_frmsizeenum frmsize;
|
||||
memset(&frmsize, 0, sizeof(frmsize));
|
||||
frmsize.pixel_format = fmt.fmt.pix.pixelformat;
|
||||
while (ioctl(v4l_fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) == 0) {
|
||||
frmsize.index++;
|
||||
if (frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
|
||||
INFO_LOG(HLE, "V4L2: frame size supported: %dx%d", frmsize.discrete.width, frmsize.discrete.height);
|
||||
if (fmt.fmt.pix.width != 0 && fmt.fmt.pix.height != 0) {
|
||||
continue;
|
||||
} else if (frmsize.discrete.width >= ideal_width && frmsize.discrete.height >= ideal_height) {
|
||||
fmt.fmt.pix.width = frmsize.discrete.width;
|
||||
fmt.fmt.pix.height = frmsize.discrete.height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fmt.fmt.pix.width == 0 && fmt.fmt.pix.height == 0) {
|
||||
fmt.fmt.pix.width = ideal_width;
|
||||
fmt.fmt.pix.height = ideal_height;
|
||||
}
|
||||
INFO_LOG(HLE, "V4L2: asking for %dx%d", fmt.fmt.pix.width, fmt.fmt.pix.height);
|
||||
if (ioctl(v4l_fd, VIDIOC_S_FMT, &fmt) == -1) {
|
||||
ERROR_LOG(HLE, "VIDIOC_S_FMT");
|
||||
return -1;
|
||||
}
|
||||
v4l_hw_width = fmt.fmt.pix.width;
|
||||
v4l_hw_height = fmt.fmt.pix.height;
|
||||
INFO_LOG(HLE, "V4L2: will receive %dx%d", v4l_hw_width, v4l_hw_height);
|
||||
v4l_height_fixed_aspect = v4l_hw_width * ideal_height / ideal_width;
|
||||
INFO_LOG(HLE, "V4L2: will use %dx%d", v4l_hw_width, v4l_height_fixed_aspect);
|
||||
|
||||
// create a converter context
|
||||
if (v4l_format == V4L2_PIX_FMT_YUYV) {
|
||||
sws_context = sws_getContext(
|
||||
v4l_hw_width, v4l_height_fixed_aspect, AV_PIX_FMT_YUYV422,
|
||||
ideal_width, ideal_height, AV_PIX_FMT_RGB24,
|
||||
SWS_BICUBIC, NULL, NULL, NULL);
|
||||
} else if (v4l_format == V4L2_PIX_FMT_MJPEG) {
|
||||
sws_context = sws_getContext(
|
||||
v4l_hw_width, v4l_height_fixed_aspect, AV_PIX_FMT_RGB24,
|
||||
ideal_width, ideal_height, AV_PIX_FMT_RGB24,
|
||||
SWS_BICUBIC, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
struct v4l2_requestbuffers req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.count = 1;
|
||||
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
req.memory = V4L2_MEMORY_MMAP;
|
||||
if (ioctl(v4l_fd, VIDIOC_REQBUFS, &req) == -1) {
|
||||
ERROR_LOG(HLE, "VIDIOC_REQBUFS");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct v4l2_buffer buf;
|
||||
memset(&buf, 0, sizeof(buf));
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
buf.memory = V4L2_MEMORY_MMAP;
|
||||
buf.index = 0;
|
||||
if (ioctl(v4l_fd, VIDIOC_QUERYBUF, &buf) == -1) {
|
||||
ERROR_LOG(HLE, "VIDIOC_QUERYBUF");
|
||||
return -1;
|
||||
}
|
||||
|
||||
v4l_length = buf.length;
|
||||
v4l_buffer = mmap(NULL,
|
||||
v4l_length,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED,
|
||||
v4l_fd, buf.m.offset);
|
||||
if (v4l_buffer == MAP_FAILED) {
|
||||
ERROR_LOG(HLE, "MAP_FAILED");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&buf, 0, sizeof(buf));
|
||||
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
buf.type = type;
|
||||
buf.memory = V4L2_MEMORY_MMAP;
|
||||
buf.index = 0;
|
||||
if (ioctl(v4l_fd, VIDIOC_QBUF, &buf) == -1) {
|
||||
ERROR_LOG(HLE, "VIDIOC_QBUF");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ioctl(v4l_fd, VIDIOC_STREAMON, &type) == -1) {
|
||||
ERROR_LOG(HLE, "VIDIOC_STREAMON");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pthread_create(&v4l_thread, NULL, v4l_loop, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __v4l_stopCapture() {
|
||||
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
|
||||
if (v4l_fd < 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (ioctl(v4l_fd, VIDIOC_STREAMOFF, &type) == -1) {
|
||||
ERROR_LOG(HLE, "VIDIOC_STREAMOFF");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (munmap(v4l_buffer, v4l_length) == -1) {
|
||||
ERROR_LOG(HLE, "munmap");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (close(v4l_fd) == -1) {
|
||||
ERROR_LOG(HLE, "close");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
v4l_fd = -1;
|
||||
//pthread_join(v4l_thread, NULL);
|
||||
|
||||
exit:
|
||||
v4l_fd = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // PPSSPP_PLATFORM(LINUX) && !PPSSPP_PLATFORM(ANDROID)
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) 2020- PPSSPP Project.
|
||||
|
||||
// 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, version 2.0 or later versions.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ppsspp_config.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Log.h"
|
||||
|
||||
#if PPSSPP_PLATFORM(LINUX) && !PPSSPP_PLATFORM(ANDROID)
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <vector>
|
||||
|
||||
#include "thread/threadutil.h"
|
||||
#include "Core/HLE/sceUsbCam.h"
|
||||
|
||||
#include <linux/videodev2.h>
|
||||
#include "ext/jpge/jpgd.h"
|
||||
#include "ext/jpge/jpge.h"
|
||||
|
||||
extern "C" {
|
||||
#include "libswscale/swscale.h"
|
||||
#include "libavutil/imgutils.h"
|
||||
}
|
||||
|
||||
static int v4l_fd = -1;
|
||||
static uint32_t v4l_format;
|
||||
static int v4l_hw_width;
|
||||
static int v4l_hw_height;
|
||||
static int v4l_height_fixed_aspect;
|
||||
static int v4l_ideal_width;
|
||||
static int v4l_ideal_height;
|
||||
|
||||
static pthread_t v4l_thread;
|
||||
static void *v4l_buffer;
|
||||
static int v4l_length;
|
||||
static struct SwsContext *sws_context;
|
||||
|
||||
std::vector<std::string> __v4l_getDeviceList();
|
||||
int __v4l_startCapture(int width, int height);
|
||||
int __v4l_stopCapture();
|
||||
#endif
|
||||
@@ -58,6 +58,7 @@
|
||||
#include "Core/Reporting.h"
|
||||
#include "Core/TextureReplacer.h"
|
||||
#include "Core/WebServer.h"
|
||||
#include "Core/HLE/sceUsbCam.h"
|
||||
#include "GPU/Common/PostShader.h"
|
||||
#include "android/jni/TestRunner.h"
|
||||
#include "GPU/GPUInterface.h"
|
||||
@@ -68,7 +69,6 @@
|
||||
#include "Windows/MainWindow.h"
|
||||
#include <shlobj.h>
|
||||
#include "Windows/W32Util/ShellUtil.h"
|
||||
#include "Windows/CaptureDevice.h"
|
||||
#endif
|
||||
|
||||
GameSettingsScreen::GameSettingsScreen(std::string gamePath, std::string gameID, bool editThenRestore)
|
||||
@@ -263,14 +263,14 @@ void GameSettingsScreen::CreateViews() {
|
||||
softwareGPU->SetEnabled(false);
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
|
||||
if (winCamera && winCamera->getDeviceList().size() >= 1) {
|
||||
#if (defined(_WIN32) && !PPSSPP_PLATFORM(UWP)) || PPSSPP_PLATFORM(LINUX)
|
||||
std::vector<std::string> cameraList = Camera::getDeviceList();
|
||||
if (cameraList.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()));
|
||||
PopupMultiChoiceDynamic *cameraChoice = graphicsSettings->Add(new PopupMultiChoiceDynamic(&g_Config.sCameraDevice, gr->T("Camera Device"), cameraList, nullptr, screenManager()));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
graphicsSettings->Add(new ItemHeader(gr->T("Frame Rate Control")));
|
||||
static const char *frameSkip[] = {"Off", "1", "2", "3", "4", "5", "6", "7", "8"};
|
||||
graphicsSettings->Add(new PopupMultiChoice(&g_Config.iFrameSkip, gr->T("Frame Skipping"), frameSkip, 0, ARRAY_SIZE(frameSkip), gr->GetName(), screenManager()));
|
||||
|
||||
@@ -283,7 +283,7 @@ void ReaderCallback::imgConvert(
|
||||
void ReaderCallback::imgInvert(unsigned char *dst, unsigned char *src, const int &srcW, const int &srcH, const GUID &srcFormat, const int &srcStride) {
|
||||
AVPixelFormat srcAvFormat = getAVVideoFormatbyMFVideoFormat(srcFormat);
|
||||
int dstLineSizes[4] = { 0, 0, 0, 0 };
|
||||
|
||||
|
||||
av_image_fill_linesizes(dstLineSizes, srcAvFormat, srcW);
|
||||
|
||||
if(srcFormat == MFVideoFormat_RGB32)
|
||||
@@ -453,7 +453,7 @@ bool WindowsCaptureDevice::start() {
|
||||
switch (state) {
|
||||
case CAPTUREDEVIDE_STATE::STOPPED:
|
||||
for (auto &name : deviceList) {
|
||||
if (name == g_Config.sWinCameraDevice) {
|
||||
if (name == g_Config.sCameraDevice) {
|
||||
selection = count;
|
||||
break;
|
||||
}
|
||||
@@ -510,7 +510,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.
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = m_pReader->ReadSample(
|
||||
|
||||
@@ -1409,12 +1409,6 @@ public abstract class NativeActivity extends Activity implements SurfaceHolder.C
|
||||
// Only keep the screen bright ingame.
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
}
|
||||
} else if (command.equals("event")) {
|
||||
if (params.equals("exitgame")) {
|
||||
if (mCameraHelper != null) {
|
||||
mCameraHelper.stopCamera();
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user