mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-05-20 12:34:50 +08:00
camera: Windows support, through the Media Foundation API!
This commit is contained in:
@@ -397,6 +397,7 @@
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\camera\dummy\SDL_camera_dummy.c" />
|
||||
<ClCompile Include="..\..\src\camera\mediafoundation\SDL_camera_mediafoundation.c" />
|
||||
<ClCompile Include="..\..\src\camera\SDL_camera.c" />
|
||||
<ClCompile Include="..\..\src\main\generic\SDL_sysmain_callbacks.c" />
|
||||
<ClCompile Include="..\..\src\main\SDL_main_callbacks.c" />
|
||||
|
||||
@@ -184,6 +184,9 @@
|
||||
<Filter Include="camera\dummy">
|
||||
<UniqueIdentifier>{0000fc2700d453b3c8d79fe81e1c0000}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="camera\mediafoundation">
|
||||
<UniqueIdentifier>{0000fbfe2d21e4f451142e7d0e870000}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_begin_code.h">
|
||||
@@ -856,6 +859,9 @@
|
||||
<ClCompile Include="..\..\src\camera\dummy\SDL_camera_dummy.c">
|
||||
<Filter>camera\dummy</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\camera\mediafoundation\SDL_camera_mediafoundation.c">
|
||||
<Filter>camera\mediafoundation</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\camera\SDL_camera.c">
|
||||
<Filter>camera</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -499,6 +499,7 @@
|
||||
F3FA5A242B59ACE000FEAD97 /* yuv_rgb_lsx.h in Headers */ = {isa = PBXBuildFile; fileRef = F3FA5A1B2B59ACE000FEAD97 /* yuv_rgb_lsx.h */; };
|
||||
F3FA5A252B59ACE000FEAD97 /* yuv_rgb_common.h in Headers */ = {isa = PBXBuildFile; fileRef = F3FA5A1C2B59ACE000FEAD97 /* yuv_rgb_common.h */; };
|
||||
FA73671D19A540EF004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; platformFilters = (ios, maccatalyst, macos, tvos, watchos, ); };
|
||||
00009F560664255CCB6C0000 /* SDL_camera_mediafoundation.c in Sources */ = {isa = PBXBuildFile; fileRef = 0000C61C247BAAAF757D0000 /* SDL_camera_mediafoundation.c */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@@ -1027,6 +1028,7 @@
|
||||
F59C710600D5CB5801000001 /* SDL.info */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = SDL.info; sourceTree = "<group>"; };
|
||||
F5A2EF3900C6A39A01000001 /* BUGS.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = BUGS.txt; path = ../../BUGS.txt; sourceTree = SOURCE_ROOT; };
|
||||
FA73671C19A540EF004122E4 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; };
|
||||
0000C61C247BAAAF757D0000 /* SDL_camera_mediafoundation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_camera_mediafoundation.c; path = SDL_camera_mediafoundation.c; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -1068,6 +1070,7 @@
|
||||
0000035D38C3899C7EFD0000 /* SDL_camera.c */,
|
||||
00009003C7148E1126CA0000 /* SDL_camera_c.h */,
|
||||
00005D3EB902478835E20000 /* SDL_syscamera.h */,
|
||||
0000926F2501CA0BDD650000 /* mediafoundation */,
|
||||
);
|
||||
path = camera;
|
||||
sourceTree = "<group>";
|
||||
@@ -2175,6 +2178,14 @@
|
||||
path = resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0000926F2501CA0BDD650000 /* mediafoundation */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0000C61C247BAAAF757D0000 /* SDL_camera_mediafoundation.c */,
|
||||
);
|
||||
path = mediafoundation;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
@@ -2754,6 +2765,7 @@
|
||||
000098E9DAA43EF6FF7F0000 /* SDL_camera.c in Sources */,
|
||||
00001B2471F503DD3C1B0000 /* SDL_camera_dummy.c in Sources */,
|
||||
00002B20A48E055EB0350000 /* SDL_camera_coremedia.m in Sources */,
|
||||
00009F560664255CCB6C0000 /* SDL_camera_mediafoundation.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
@@ -472,7 +472,8 @@
|
||||
#cmakedefine SDL_CAMERA_DRIVER_V4L2 @SDL_CAMERA_DRIVER_V4L2@
|
||||
#cmakedefine SDL_CAMERA_DRIVER_COREMEDIA @SDL_CAMERA_DRIVER_COREMEDIA@
|
||||
#cmakedefine SDL_CAMERA_DRIVER_ANDROID @SDL_CAMERA_DRIVER_ANDROID@
|
||||
#cmakedefine SDL_CAMERA_DRIVER_EMSCRIPTEN @SDL_CAMERA_DRIVER_EMSCRIPTEND@
|
||||
#cmakedefine SDL_CAMERA_DRIVER_EMSCRIPTEN @SDL_CAMERA_DRIVER_EMSCRIPTEN@
|
||||
#cmakedefine SDL_CAMERA_DRIVER_MEDIAFOUNDATION @SDL_CAMERA_DRIVER_MEDIAFOUNDATION@
|
||||
|
||||
/* Enable misc subsystem */
|
||||
#cmakedefine SDL_MISC_DUMMY @SDL_MISC_DUMMY@
|
||||
|
||||
@@ -311,7 +311,8 @@ typedef unsigned int uintptr_t;
|
||||
/* Enable filesystem support */
|
||||
#define SDL_FILESYSTEM_WINDOWS 1
|
||||
|
||||
/* Enable the camera driver (src/camera/dummy/\*.c) */ /* !!! FIXME */
|
||||
#define SDL_CAMERA_DRIVER_DUMMY 1
|
||||
/* Enable the camera driver */
|
||||
#define SDL_CAMERA_DRIVER_MEDIAFOUNDATION 1
|
||||
#define SDL_CAMERA_DRIVER_DUMMY 1
|
||||
|
||||
#endif /* SDL_build_config_windows_h_ */
|
||||
|
||||
+39
-1
@@ -43,6 +43,9 @@ static const CameraBootStrap *const bootstrap[] = {
|
||||
#ifdef SDL_CAMERA_DRIVER_EMSCRIPTEN
|
||||
&EMSCRIPTENCAMERA_bootstrap,
|
||||
#endif
|
||||
#ifdef SDL_CAMERA_DRIVER_MEDIAFOUNDATION
|
||||
&MEDIAFOUNDATION_bootstrap,
|
||||
#endif
|
||||
#ifdef SDL_CAMERA_DRIVER_DUMMY
|
||||
&DUMMYCAMERA_bootstrap,
|
||||
#endif
|
||||
@@ -70,6 +73,32 @@ const char *SDL_GetCurrentCameraDriver(void)
|
||||
return camera_driver.name;
|
||||
}
|
||||
|
||||
int SDL_AddCameraFormat(CameraFormatAddData *data, Uint32 fmt, int w, int h, int interval_numerator, int interval_denominator)
|
||||
{
|
||||
SDL_assert(data != NULL);
|
||||
if (data->allocated_specs <= data->num_specs) {
|
||||
const int newalloc = data->allocated_specs ? (data->allocated_specs * 2) : 16;
|
||||
void *ptr = SDL_realloc(data->specs, sizeof (SDL_CameraSpec) * newalloc);
|
||||
if (!ptr) {
|
||||
return -1;
|
||||
}
|
||||
data->specs = (SDL_CameraSpec *) ptr;
|
||||
data->allocated_specs = newalloc;
|
||||
}
|
||||
|
||||
SDL_CameraSpec *spec = &data->specs[data->num_specs];
|
||||
spec->format = fmt;
|
||||
spec->width = w;
|
||||
spec->height = h;
|
||||
spec->interval_numerator = interval_numerator;
|
||||
spec->interval_denominator = interval_denominator;
|
||||
|
||||
data->num_specs++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void ClosePhysicalCameraDevice(SDL_CameraDevice *device)
|
||||
{
|
||||
if (!device) {
|
||||
@@ -610,10 +639,13 @@ SDL_bool SDL_CameraThreadIterate(SDL_CameraDevice *device)
|
||||
|
||||
if (rc == 1) { // new frame acquired!
|
||||
#if DEBUG_CAMERA
|
||||
SDL_Log("CAMERA: New frame available!");
|
||||
SDL_Log("CAMERA: New frame available! pixels=%p pitch=%d", device->acquire_surface->pixels, device->acquire_surface->pitch);
|
||||
#endif
|
||||
|
||||
if (device->drop_frames > 0) {
|
||||
#if DEBUG_CAMERA
|
||||
SDL_Log("CAMERA: Dropping an initial frame");
|
||||
#endif
|
||||
device->drop_frames--;
|
||||
camera_driver.impl.ReleaseFrame(device, device->acquire_surface);
|
||||
device->acquire_surface->pixels = NULL;
|
||||
@@ -662,9 +694,15 @@ SDL_bool SDL_CameraThreadIterate(SDL_CameraDevice *device)
|
||||
} else if (acquired) { // we have a new frame, scale/convert if necessary and queue it for the app!
|
||||
SDL_assert(slist != NULL);
|
||||
if (!device->needs_scaling && !device->needs_conversion) { // no conversion needed? Just move the pointer/pitch into the output surface.
|
||||
#if DEBUG_CAMERA
|
||||
SDL_Log("CAMERA: Frame is going through without conversion!");
|
||||
#endif
|
||||
output_surface->pixels = acquired->pixels;
|
||||
output_surface->pitch = acquired->pitch;
|
||||
} else { // convert/scale into a different surface.
|
||||
#if DEBUG_CAMERA
|
||||
SDL_Log("CAMERA: Frame is getting converted!");
|
||||
#endif
|
||||
SDL_Surface *srcsurf = acquired;
|
||||
if (device->needs_scaling == -1) { // downscaling? Do it first. -1: downscale, 0: no scaling, 1: upscale
|
||||
SDL_Surface *dstsurf = device->needs_conversion ? device->conversion_surface : output_surface;
|
||||
|
||||
@@ -58,6 +58,16 @@ extern void SDL_CameraThreadSetup(SDL_CameraDevice *device);
|
||||
extern SDL_bool SDL_CameraThreadIterate(SDL_CameraDevice *device);
|
||||
extern void SDL_CameraThreadShutdown(SDL_CameraDevice *device);
|
||||
|
||||
// common utility functionality to gather up camera specs. Not required!
|
||||
typedef struct CameraFormatAddData
|
||||
{
|
||||
SDL_CameraSpec *specs;
|
||||
int num_specs;
|
||||
int allocated_specs;
|
||||
} CameraFormatAddData;
|
||||
|
||||
int SDL_AddCameraFormat(CameraFormatAddData *data, Uint32 fmt, int w, int h, int interval_numerator, int interval_denominator);
|
||||
|
||||
typedef struct SurfaceList
|
||||
{
|
||||
SDL_Surface *surface;
|
||||
@@ -189,5 +199,6 @@ extern CameraBootStrap V4L2_bootstrap;
|
||||
extern CameraBootStrap COREMEDIA_bootstrap;
|
||||
extern CameraBootStrap ANDROIDCAMERA_bootstrap;
|
||||
extern CameraBootStrap EMSCRIPTENCAMERA_bootstrap;
|
||||
extern CameraBootStrap MEDIAFOUNDATION_bootstrap;
|
||||
|
||||
#endif // SDL_syscamera_h_
|
||||
|
||||
@@ -77,4 +77,4 @@ CameraBootStrap DUMMYCAMERA_bootstrap = {
|
||||
"dummy", "SDL dummy camera driver", DUMMYCAMERA_Init, SDL_TRUE
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // SDL_CAMERA_DRIVER_DUMMY
|
||||
|
||||
@@ -79,8 +79,6 @@ static int EMSCRIPTENCAMERA_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *
|
||||
static void EMSCRIPTENCAMERA_ReleaseFrame(SDL_CameraDevice *device, SDL_Surface *frame)
|
||||
{
|
||||
SDL_free(frame->pixels);
|
||||
frame->pixels = NULL;
|
||||
frame->pitch = 0;
|
||||
}
|
||||
|
||||
static void EMSCRIPTENCAMERA_CloseDevice(SDL_CameraDevice *device)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -631,39 +631,7 @@ static SDL_bool FindV4L2CameraDeviceByBusInfoCallback(SDL_CameraDevice *device,
|
||||
return (SDL_strcmp(handle->bus_info, (const char *) userdata) == 0);
|
||||
}
|
||||
|
||||
typedef struct FormatAddData
|
||||
{
|
||||
SDL_CameraSpec *specs;
|
||||
int num_specs;
|
||||
int allocated_specs;
|
||||
} FormatAddData;
|
||||
|
||||
static int AddCameraCompleteFormat(FormatAddData *data, Uint32 fmt, int w, int h, int interval_numerator, int interval_denominator)
|
||||
{
|
||||
SDL_assert(data != NULL);
|
||||
if (data->allocated_specs <= data->num_specs) {
|
||||
const int newalloc = data->allocated_specs ? (data->allocated_specs * 2) : 16;
|
||||
void *ptr = SDL_realloc(data->specs, sizeof (SDL_CameraSpec) * newalloc);
|
||||
if (!ptr) {
|
||||
return -1;
|
||||
}
|
||||
data->specs = (SDL_CameraSpec *) ptr;
|
||||
data->allocated_specs = newalloc;
|
||||
}
|
||||
|
||||
SDL_CameraSpec *spec = &data->specs[data->num_specs];
|
||||
spec->format = fmt;
|
||||
spec->width = w;
|
||||
spec->height = h;
|
||||
spec->interval_numerator = interval_numerator;
|
||||
spec->interval_denominator = interval_denominator;
|
||||
|
||||
data->num_specs++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int AddCameraFormat(const int fd, FormatAddData *data, Uint32 sdlfmt, Uint32 v4l2fmt, int w, int h)
|
||||
static int AddCameraFormat(const int fd, CameraFormatAddData *data, Uint32 sdlfmt, Uint32 v4l2fmt, int w, int h)
|
||||
{
|
||||
struct v4l2_frmivalenum frmivalenum;
|
||||
SDL_zero(frmivalenum);
|
||||
@@ -679,7 +647,7 @@ static int AddCameraFormat(const int fd, FormatAddData *data, Uint32 sdlfmt, Uin
|
||||
const float fps = (float) denominator / (float) numerator;
|
||||
SDL_Log("CAMERA: * Has discrete frame interval (%d / %d), fps=%f", numerator, denominator, fps);
|
||||
#endif
|
||||
if (AddCameraCompleteFormat(data, sdlfmt, w, h, numerator, denominator) == -1) {
|
||||
if (SDL_AddCameraFormat(data, sdlfmt, w, h, numerator, denominator) == -1) {
|
||||
return -1; // Probably out of memory; we'll go with what we have, if anything.
|
||||
}
|
||||
frmivalenum.index++; // set up for the next one.
|
||||
@@ -691,7 +659,7 @@ static int AddCameraFormat(const int fd, FormatAddData *data, Uint32 sdlfmt, Uin
|
||||
const float fps = (float) d / (float) n;
|
||||
SDL_Log("CAMERA: * Has %s frame interval (%d / %d), fps=%f", (frmivalenum.type == V4L2_FRMIVAL_TYPE_STEPWISE) ? "stepwise" : "continuous", n, d, fps);
|
||||
#endif
|
||||
if (AddCameraCompleteFormat(data, sdlfmt, w, h, n, d) == -1) {
|
||||
if (SDL_AddCameraFormat(data, sdlfmt, w, h, n, d) == -1) {
|
||||
return -1; // Probably out of memory; we'll go with what we have, if anything.
|
||||
}
|
||||
d += (int) frmivalenum.stepwise.step.denominator;
|
||||
@@ -739,7 +707,7 @@ static void MaybeAddDevice(const char *path)
|
||||
SDL_Log("CAMERA: V4L2 camera path='%s' bus_info='%s' name='%s'", path, (const char *) vcap.bus_info, vcap.card);
|
||||
#endif
|
||||
|
||||
FormatAddData add_data;
|
||||
CameraFormatAddData add_data;
|
||||
SDL_zero(add_data);
|
||||
|
||||
struct v4l2_fmtdesc fmtdesc;
|
||||
@@ -911,5 +879,5 @@ CameraBootStrap V4L2_bootstrap = {
|
||||
"v4l2", "SDL Video4Linux2 camera driver", V4L2_Init, SDL_FALSE
|
||||
};
|
||||
|
||||
#endif // SDL_CAMERA_V4L2
|
||||
#endif // SDL_CAMERA_DRIVER_V4L2
|
||||
|
||||
|
||||
Reference in New Issue
Block a user