From 59f93e20a714cf4f6ff3dd3ed7daf3a73e7e7656 Mon Sep 17 00:00:00 2001
From: Sylvain <[EMAIL REDACTED]>
Date: Thu, 9 Nov 2023 11:11:07 +0100
Subject: [PATCH] Add SDL Video Capture, with back-end for
linux/macos/ios/android
---
CMakeLists.txt | 9 +
VisualC-WinRT/SDL-UWP.vcxproj | 3 +
VisualC-WinRT/SDL-UWP.vcxproj.filters | 9 +
VisualC/SDL/SDL.vcxproj | 1 +
VisualC/SDL/SDL.vcxproj.filters | 3 +
include/SDL3/SDL.h | 1 +
include/SDL3/SDL_video_capture.h | 369 +++++++
include/build_config/SDL_build_config.h.cmake | 4 +
include/build_config/SDL_build_config_ios.h | 2 +
include/build_config/SDL_build_config_macos.h | 2 +
src/dynapi/SDL_dynapi.sym | 16 +
src/dynapi/SDL_dynapi_overrides.h | 16 +
src/dynapi/SDL_dynapi_procs.h | 16 +
src/video/SDL_sysvideocapture.h | 90 ++
src/video/SDL_video.c | 10 +
src/video/SDL_video_capture.c | 948 +++++++++++++++++
src/video/SDL_video_capture_apple.m | 615 +++++++++++
src/video/SDL_video_capture_c.h | 33 +
src/video/SDL_video_capture_v4l2.c | 965 ++++++++++++++++++
src/video/android/SDL_android_video_capture.c | 678 ++++++++++++
test/CMakeLists.txt | 2 +
test/testvideocapture.c | 770 ++++++++++++++
test/testvideocaptureminimal.c | 206 ++++
23 files changed, 4768 insertions(+)
create mode 100644 include/SDL3/SDL_video_capture.h
create mode 100644 src/video/SDL_sysvideocapture.h
create mode 100644 src/video/SDL_video_capture.c
create mode 100644 src/video/SDL_video_capture_apple.m
create mode 100644 src/video/SDL_video_capture_c.h
create mode 100644 src/video/SDL_video_capture_v4l2.c
create mode 100644 src/video/android/SDL_android_video_capture.c
create mode 100644 test/testvideocapture.c
create mode 100644 test/testvideocaptureminimal.c
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ca03351edb19..5564c756014a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -343,6 +343,7 @@ set_option(SDL_METAL "Enable Metal support" ${APPLE})
set_option(SDL_KMSDRM "Use KMS DRM video driver" ${UNIX_SYS})
dep_option(SDL_KMSDRM_SHARED "Dynamically load KMS DRM support" ON "SDL_KMSDRM" OFF)
set_option(SDL_OFFSCREEN "Use offscreen video driver" ON)
+dep_option(SDL_VIDEO_CAPTURE "Enable video capturing" ON SDL_VIDEO OFF)
option_string(SDL_BACKGROUNDING_SIGNAL "number to use for magic backgrounding signal or 'OFF'" OFF)
option_string(SDL_FOREGROUNDING_SIGNAL "number to use for magic foregrounding signal or 'OFF'" OFF)
dep_option(SDL_HIDAPI "Enable the HIDAPI subsystem" ON "NOT VISIONOS" OFF)
@@ -2047,6 +2048,10 @@ elseif(APPLE)
set(HAVE_SDL_FILE TRUE)
endif()
+ if(IOS OR TVOS OR MACOSX OR DARWIN)
+ sdl_sources("${SDL3_SOURCE_DIR}/src/video/SDL_video_capture_apple.m")
+ endif()
+
if(SDL_MISC)
if(IOS OR TVOS OR VISIONOS)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/ios/*.m")
@@ -2230,6 +2235,10 @@ elseif(APPLE)
# Actually load the frameworks at the end so we don't duplicate include.
if(SDL_FRAMEWORK_COREVIDEO)
+ find_library(COREMEDIA CoreMedia)
+ if(COREMEDIA)
+ sdl_link_dependency(corevideo LINK_OPTIONS "-Wl,-framework,CoreMedia")
+ endif()
sdl_link_dependency(corevideo LINK_OPTIONS "-Wl,-framework,CoreVideo")
endif()
if(SDL_FRAMEWORK_COCOA)
diff --git a/VisualC-WinRT/SDL-UWP.vcxproj b/VisualC-WinRT/SDL-UWP.vcxproj
index 1085c0f45200..f7eca1ef796b 100644
--- a/VisualC-WinRT/SDL-UWP.vcxproj
+++ b/VisualC-WinRT/SDL-UWP.vcxproj
@@ -89,6 +89,7 @@
<ClInclude Include="..\include\SDL3\SDL_types.h" />
<ClInclude Include="..\include\SDL3\SDL_version.h" />
<ClInclude Include="..\include\SDL3\SDL_video.h" />
+ <ClInclude Include="..\include\SDL3\SDL_video_capture.h" />
<ClInclude Include="..\src\audio\disk\SDL_diskaudio.h" />
<ClInclude Include="..\src\audio\dummy\SDL_dummyaudio.h" />
<ClInclude Include="..\src\audio\SDL_audiodev_c.h" />
@@ -180,6 +181,7 @@
<ClInclude Include="..\src\video\SDL_RLEaccel_c.h" />
<ClInclude Include="..\src\video\SDL_shape_internals.h" />
<ClInclude Include="..\src\video\SDL_sysvideo.h" />
+ <ClInclude Include="..\src\video\SDL_sysvidocapture.h" />
<ClInclude Include="..\src\video\SDL_yuv_c.h" />
<ClInclude Include="..\src\video\winrt\SDL_winrtevents_c.h" />
<ClInclude Include="..\src\video\winrt\SDL_winrtgamebar_cpp.h" />
@@ -520,6 +522,7 @@
<ClCompile Include="..\src\video\SDL_stretch.c" />
<ClCompile Include="..\src\video\SDL_surface.c" />
<ClCompile Include="..\src\video\SDL_video.c" />
+ <ClCompile Include="..\src\video\SDL_video_capture.c" />
<ClCompile Include="..\src\video\SDL_video_unsupported.c" />
<ClCompile Include="..\src\video\SDL_yuv.c" />
<ClCompile Include="..\src\video\winrt\SDL_winrtevents.cpp">
diff --git a/VisualC-WinRT/SDL-UWP.vcxproj.filters b/VisualC-WinRT/SDL-UWP.vcxproj.filters
index ab0ca0cfb7ab..fc905ac9e852 100644
--- a/VisualC-WinRT/SDL-UWP.vcxproj.filters
+++ b/VisualC-WinRT/SDL-UWP.vcxproj.filters
@@ -165,6 +165,9 @@
<ClInclude Include="..\include\SDL3\SDL_video.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="..\include\SDL3\SDL_video_capture.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="..\src\joystick\SDL_gamepad_c.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -405,6 +408,9 @@
<ClInclude Include="..\src\video\SDL_sysvideo.h">
<Filter>Source Files</Filter>
</ClInclude>
+ <ClInclude Include="..\src\video\SDL_sysvideocapture.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
<ClInclude Include="..\src\video\winrt\SDL_winrtevents_c.h">
<Filter>Source Files</Filter>
</ClInclude>
@@ -807,6 +813,9 @@
<ClCompile Include="..\src\video\SDL_video.c">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\src\video\SDL_video_capture.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\src\video\SDL_video_unsupported.c">
<Filter>Source Files</Filter>
</ClCompile>
diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj
index 35edb9b8a6a4..fc53003e73fb 100644
--- a/VisualC/SDL/SDL.vcxproj
+++ b/VisualC/SDL/SDL.vcxproj
@@ -653,6 +653,7 @@
<ClCompile Include="..\..\src\video\SDL_surface.c" />
<ClCompile Include="..\..\src\video\SDL_video.c" />
<ClCompile Include="..\..\src\video\SDL_video_unsupported.c" />
+ <ClCompile Include="..\..\src\video\SDL_video_capture.c" />
<ClCompile Include="..\..\src\video\SDL_vulkan_utils.c" />
<ClCompile Include="..\..\src\video\SDL_yuv.c" />
<ClCompile Include="..\..\src\video\windows\SDL_windowsclipboard.c" />
diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters
index b367e7695fe6..c9d6f36e5d47 100644
--- a/VisualC/SDL/SDL.vcxproj.filters
+++ b/VisualC/SDL/SDL.vcxproj.filters
@@ -1185,6 +1185,9 @@
<ClCompile Include="..\..\src\video\SDL_video_unsupported.c">
<Filter>video</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\video\SDL_video_capture.c">
+ <Filter>video</Filter>
+ </ClCompile>
<ClCompile Include="..\..\src\video\SDL_yuv.c">
<Filter>video</Filter>
</ClCompile>
diff --git a/include/SDL3/SDL.h b/include/SDL3/SDL.h
index 498f0520c15c..6db0e69d47e5 100644
--- a/include/SDL3/SDL.h
+++ b/include/SDL3/SDL.h
@@ -76,6 +76,7 @@
#include <SDL3/SDL_touch.h>
#include <SDL3/SDL_version.h>
#include <SDL3/SDL_video.h>
+#include "SDL3/SDL_video_capture.h"
#include <SDL3/SDL_oldnames.h>
#endif /* SDL_h_ */
diff --git a/include/SDL3/SDL_video_capture.h b/include/SDL3/SDL_video_capture.h
new file mode 100644
index 000000000000..3d3ce7e64198
--- /dev/null
+++ b/include/SDL3/SDL_video_capture.h
@@ -0,0 +1,369 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_video_capture.h
+ *
+ * Video Capture for the SDL library.
+ */
+
+#ifndef SDL_video_capture_h_
+#define SDL_video_capture_h_
+
+#include "SDL3/SDL_video.h"
+
+#include <SDL3/SDL_begin_code.h>
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * This is a unique ID for a video capture device for the time it is connected to the system,
+ * and is never reused for the lifetime of the application. If the device is
+ * disconnected and reconnected, it will get a new ID.
+ *
+ * The ID value starts at 1 and increments from there. The value 0 is an invalid ID.
+ *
+ * \sa SDL_GetVideoCaptureDevices
+ */
+typedef Uint32 SDL_VideoCaptureDeviceID;
+
+
+/**
+ * The structure used to identify an SDL video capture device
+ */
+struct SDL_VideoCaptureDevice;
+typedef struct SDL_VideoCaptureDevice SDL_VideoCaptureDevice;
+
+#define SDL_VIDEO_CAPTURE_ALLOW_ANY_CHANGE 1
+
+/**
+ * SDL_VideoCaptureSpec structure
+ *
+ * Only those field can be 'desired' when configuring the device:
+ * - format
+ * - width
+ * - height
+ *
+ * \sa SDL_GetVideoCaptureFormat
+ * \sa SDL_GetVideoCaptureFrameSize
+ *
+ */
+typedef struct SDL_VideoCaptureSpec
+{
+ Uint32 format; /**< Frame SDL_PixelFormatEnum format */
+ int width; /**< Frame width */
+ int height; /**< Frame height */
+} SDL_VideoCaptureSpec;
+
+/**
+ * SDL Video Capture Status
+ *
+ * Change states but calling the function in this order:
+ *
+ * SDL_OpenVideoCapture()
+ * SDL_SetVideoCaptureSpec() -> Init
+ * SDL_StartVideoCapture() -> Playing
+ * SDL_StopVideoCapture() -> Stopped
+ * SDL_CloseVideoCapture()
+ *
+ */
+typedef enum
+{
+ SDL_VIDEO_CAPTURE_FAIL = -1, /**< Failed */
+ SDL_VIDEO_CAPTURE_INIT = 0, /**< Init, spec hasn't been set */
+ SDL_VIDEO_CAPTURE_STOPPED, /**< Stopped */
+ SDL_VIDEO_CAPTURE_PLAYING /**< Playing */
+} SDL_VideoCaptureStatus;
+
+/**
+ * SDL Video Capture Status
+ */
+typedef struct SDL_VideoCaptureFrame
+{
+ Uint64 timestampNS; /**< Frame timestamp in nanoseconds when read from the driver */
+ int num_planes; /**< Number of planes */
+ Uint8 *data[3]; /**< Pointer to data of i-th plane */
+ int pitch[3]; /**< Pitch of i-th plane */
+ void *internal; /**< Private field */
+} SDL_VideoCaptureFrame;
+
+
+/**
+ * Get a list of currently connected video capture devices.
+ *
+ * \param count a pointer filled in with the number of video capture devices
+ * \returns a 0 terminated array of video capture instance IDs which should be
+ * freed with SDL_free(), or NULL on error; call SDL_GetError() for
+ * more details.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_OpenVideoCapture
+ */
+extern DECLSPEC SDL_VideoCaptureDeviceID *SDLCALL SDL_GetVideoCaptureDevices(int *count);
+
+/**
+ * Open a Video Capture device
+ *
+ * \param instance_id the video capture device instance ID
+ * \returns device, or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetVideoCaptureDeviceName
+ * \sa SDL_GetVideoCaptureDevices
+ * \sa SDL_OpenVideoCaptureWithSpec
+ */
+extern DECLSPEC SDL_VideoCaptureDevice *SDLCALL SDL_OpenVideoCapture(SDL_VideoCaptureDeviceID instance_id);
+
+/**
+ * Set specification
+ *
+ * \param device opened video capture device
+ * \param desired desired video capture spec
+ * \param obtained obtained video capture spec
+ * \param allowed_changes allow changes or not
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_OpenVideoCapture
+ * \sa SDL_OpenVideoCaptureWithSpec
+ * \sa SDL_GetVideoCaptureSpec
+ */
+extern DECLSPEC int SDLCALL SDL_SetVideoCaptureSpec(SDL_VideoCaptureDevice *device,
+ const SDL_VideoCaptureSpec *desired,
+ SDL_VideoCaptureSpec *obtained,
+ int allowed_changes);
+
+/**
+ * Open a Video Capture device and set specification
+ *
+ * \param instance_id the video capture device instance ID
+ * \param desired desired video capture spec
+ * \param obtained obtained video capture spec
+ * \param allowed_changes allow changes or not
+ * \returns device, or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_OpenVideoCapture
+ * \sa SDL_SetVideoCaptureSpec
+ * \sa SDL_GetVideoCaptureSpec
+ */
+extern DECLSPEC SDL_VideoCaptureDevice *SDLCALL SDL_OpenVideoCaptureWithSpec(SDL_VideoCaptureDeviceID instance_id,
+ const SDL_VideoCaptureSpec *desired,
+ SDL_VideoCaptureSpec *obtained,
+ int allowed_changes);
+/**
+ * Get device name
+ *
+ * \param instance_id the video capture device instance ID
+ * \returns device name, shouldn't be freed
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetVideoCaptureDevices
+ */
+extern DECLSPEC const char * SDLCALL SDL_GetVideoCaptureDeviceName(SDL_VideoCaptureDeviceID instance_id);
+
+/**
+ * Get the obtained video capture spec
+ *
+ * \param device opened video capture device
+ * \param spec The SDL_VideoCaptureSpec to be initialized by this function.
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_SetVideoCaptureSpec
+ * \sa SDL_OpenVideoCaptureWithSpec
+ */
+extern DECLSPEC int SDLCALL SDL_GetVideoCaptureSpec(SDL_VideoCaptureDevice *device, SDL_VideoCaptureSpec *spec);
+
+
+/**
+ * Get frame format of video capture device.
+ * The value can be used to fill SDL_VideoCaptureSpec structure.
+ *
+ * \param device opened video capture device
+ * \param index format between 0 and num -1
+ * \param format pointer output format (SDL_PixelFormatEnum)
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetNumVideoCaptureFormats
+ */
+extern DECLSPEC int SDLCALL SDL_GetVideoCaptureFormat(SDL_VideoCaptureDevice *device,
+ int index,
+ Uint32 *format);
+
+/**
+ * Number of available formats for the device
+ *
+ * \param device opened video capture device
+ * \returns number of formats or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetVideoCaptureFormat
+ * \sa SDL_SetVideoCaptureSpec
+ */
+extern DECLSPEC int SDLCALL SDL_GetNumVideoCaptureFormats(SDL_VideoCaptureDevice *device);
+
+/**
+ * Get frame sizes of the device and the specified input format.
+ * The value can be used to fill SDL_VideoCaptureSpec structure.
+ *
+ * \param device opened video capture device
+ * \param format a format that can be used by the device (SDL_PixelFormatEnum)
+ * \param index framesize between 0 and num -1
+ * \param width output width
+ * \param height output height
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetNumVideoCaptureFrameSizes
+ */
+extern DECLSPEC int SDLCALL SDL_GetVideoCaptureFrameSize(SDL_VideoCaptureDevice *device, Uint32 format, int index, int *width, int *height);
+
+/**
+ * Number of different framesizes available for the device and pixel format.
+ *
+ * \param device opened video capture device
+ * \param format frame pixel format (SDL_PixelFormatEnum)
+ * \returns number of framesizes or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetVideoCaptureFrameSize
+ * \sa SDL_SetVideoCaptureSpec
+ */
+extern DECLSPEC int SDLCALL SDL_GetNumVideoCaptureFrameSizes(SDL_VideoCaptureDevice *device, Uint32 format);
+
+
+/**
+ * Get video capture status
+ *
+ * \param device opened video capture device
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_VideoCaptureStatus
+ */
+extern DECLSPEC SDL_VideoCaptureStatus SDLCALL SDL_GetVideoCaptureStatus(SDL_VideoCaptureDevice *device);
+
+/**
+ * Start video capture
+ *
+ * \param device opened video capture device
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_StopVideoCapture
+ */
+extern DECLSPEC int SDLCALL SDL_StartVideoCapture(SDL_VideoCaptureDevice *device);
+
+/**
+ * Acquire a frame.
+ * The frame is a memory pointer to the image data, whose size and format
+ * are given by the the obtained spec.
+ *
+ * Non blocking API. If there is a frame available, frame->num_planes is non 0.
+ * If frame->num_planes is 0 and returned code is 0, there is no frame at that time.
+ *
+ * After used, the frame should be released with SDL_ReleaseVideoCaptureFrame
+ *
+ * \param device opened video capture device
+ * \param frame pointer to get the frame
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_ReleaseVideoCaptureFrame
+ */
+extern DECLSPEC int SDLCALL SDL_AcquireVideoCaptureFrame(SDL_VideoCaptureDevice *device, SDL_VideoCaptureFrame *frame);
+
+/**
+ * Release a frame. Let the back-end re-use the internal buffer for video capture.
+ *
+ * All acquired frames should be released before closing the device.
+ *
+ * \param device opened video capture device
+ * \param frame frame pointer.
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_AcquireVideoCaptureFrame
+ */
+extern DECLSPEC int SDLCALL SDL_ReleaseVideoCaptureFrame(SDL_VideoCaptureDevice *device, SDL_VideoCaptureFrame *frame);
+
+/**
+ * Stop Video Capture
+ *
+ * \param device opened video capture device
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_StartVideoCapture
+ */
+extern DECLSPEC int SDLCALL SDL_StopVideoCapture(SDL_VideoCaptureDevice *device);
+
+/**
+ * Use this function to shut down video_capture processing and close the video_capture device.
+ *
+ * \param device opened video capture device
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_OpenVideoCaptureWithSpec
+ * \sa SDL_OpenVideoCapture
+ */
+extern DECLSPEC void SDLCALL SDL_CloseVideoCapture(SDL_VideoCaptureDevice *device);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include <SDL3/SDL_close_code.h>
+
+#endif /* SDL_video_capture_h_ */
diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake
index b776251f81e4..8b26e0dea929 100644
--- a/include/build_config/SDL_build_config.h.cmake
+++ b/include/build_config/SDL_build_config.h.cmake
@@ -244,11 +244,15 @@
#cmakedefine USE_POSIX_SPAWN @USE_POSIX_SPAWN@
+#cmakedefine HAVE_COREMEDIA
+
/* SDL internal assertion support */
#if @SDL_DEFAULT_ASSERT_LEVEL_CONFIGURED@
#cmakedefine SDL_DEFAULT_ASSERT_LEVEL @SDL_DEFAULT_ASSERT_LEVEL@
#endif
+#cmakedefine SDL_VIDEO_CAPTURE
+
/* Allow disabling of core subsystems */
#cmakedefine SDL_ATOMIC_DISABLED @SDL_ATOMIC_DISABLED@
#cmakedefine SDL_AUDIO_DISABLED @SDL_AUDIO_DISABLED@
diff --git a/include/build_config/SDL_build_config_ios.h b/include/build_config/SDL_build_config_ios.h
index 96391f848f57..340bbc0c2997 100644
--- a/include/build_config/SDL_build_config_ios.h
+++ b/include/build_config/SDL_build_config_ios.h
@@ -197,6 +197,8 @@
#define SDL_VIDEO_METAL 1
#endif
+#define HAVE_COREMEDIA 1
+
/* Enable system power support */
#define SDL_POWER_UIKIT 1
diff --git a/include/build_config/SDL_build_config_macos.h b/include/build_config/SDL_build_config_macos.h
index 43400d3f6ef4..bf1b682ed02b 100644
--- a/include/build_config/SDL_build_config_macos.h
+++ b/include/build_config/SDL_build_config_macos.h
@@ -260,6 +260,8 @@
#endif
#endif
+#define HAVE_COREMEDIA 1
+
/* Enable system power support */
#define SDL_POWER_MACOSX 1
diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym
index e6fd996c6429..96e662f2c51e 100644
--- a/src/dynapi/SDL_dynapi.sym
+++ b/src/dynapi/SDL_dynapi.sym
@@ -923,6 +923,22 @@ SDL3_0.0.0 {
SDL_SetPropertyWithCleanup;
SDL_SetX11EventHook;
SDL_GetGlobalProperties;
+ SDL_OpenVideoCapture;
+ SDL_SetVideoCaptureSpec;
+ SDL_OpenVideoCaptureWithSpec;
+ SDL_GetVideoCaptureDeviceName;
+ SDL_GetVideoCaptureSpec;
+ SDL_GetVideoCaptureFormat;
+ SDL_GetNumVideoCaptureFormats;
+ SDL_GetVideoCaptureFrameSize;
+ SDL_GetNumVideoCaptureFrameSizes;
+ SDL_GetVideoCaptureStatus;
+ SDL_StartVideoCapture;
+ SDL_AcquireVideoCaptureFrame;
+ SDL_ReleaseVideoCaptureFrame;
+ SDL_StopVideoCapture;
+ SDL_CloseVideoCapture;
+ SDL_GetVideoCaptureDevices;
# extra symbols go here (don't modify this line)
local: *;
};
diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h
index 97d05e88ba0b..adb202523cbc 100644
--- a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -948,3 +948,19 @@
#define SDL_SetPropertyWithCleanup SDL_SetPropertyWithCleanup_REAL
#define SDL_SetX11EventHook SDL_SetX11EventHook_REAL
#define SDL_GetGlobalProperties SDL_GetGlobalProperties_REAL
+#define SDL_OpenVideoCapture SDL_OpenVideoCapture_REAL
+#define SDL_SetVideoCaptureSpec SDL_SetVideoCaptureSpec_REAL
+#define SDL_OpenVideoCaptureWithSpec SDL_OpenVideoCaptureWithSpec_REAL
+#define SDL_GetVideoCaptureDeviceName SDL_GetVideoCaptureDeviceName_REAL
+#define SDL_GetVideoCaptureSpec SDL_GetVideoCaptureSpec_REAL
+#define SDL_GetVideoCaptureFormat SDL_GetVideoCaptureFormat_REAL
+#define SDL_GetNumVideoCaptureFormats SDL_GetNumVideoCaptureFormats_REAL
+#define SDL_GetVideoCaptureFrameSize SDL_GetVideoCaptureFrameSize_REAL
+#define SDL_GetNumVideoCaptureFrameSizes SDL_GetNumVideoCaptureFrameSizes_REAL
+#define SDL_GetVideoCaptureStatus SDL_GetVideoCaptureStatus_REAL
+#define SDL_StartVideoCapture SDL_StartVideoCapture_REAL
+#define SDL_AcquireVideoCaptureFrame SDL_AcquireVideoCaptureFrame_REAL
+#define SDL_ReleaseVideoCaptureFrame SDL_ReleaseVideoCaptureFrame_REAL
+#define SDL_StopVideoCapture SDL_StopVideoCapture_REAL
+#define SDL_CloseVideoCapture SDL_CloseVideoCapture_REAL
+#define SDL_GetVideoCaptureDevices SDL_GetVideoCaptureDevices_REAL
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index 64022522244f..7f3b0e521125 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -981,3 +981,19 @@ SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetDisplayProperties,(SDL_DisplayID a),(a),
SDL_DYNAPI_PROC(int,SDL_SetPropertyWithCleanup,(SDL_PropertiesID a, const char *b, void *c, void (SDLCALL *d)(void *userdata, void *value), void *e),(a,b,c,d,e),return)
SDL_DYNAPI_PROC(void,SDL_SetX11EventHook,(SDL_X11EventHook a, void *b),(a,b),)
SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetGlobalProperties,(void),(),return)
+SDL_DYNAPI_PROC(SDL_VideoCaptureDevice*,SDL_OpenVideoCapture,(SDL_VideoCaptureDeviceID a),(a),return)
+SDL_DYNAPI_PROC(int,SDL_SetVideoCaptureSpec,(SDL_VideoCaptureDevice *a, const SDL_VideoCaptureSpec *b, SDL_VideoCaptureSpec *c, int d),(a,b,c,d),return)
+SDL_DYNAPI_PROC(SDL_VideoCaptureDevice*,SDL_OpenVideoCaptureWithSpec,(SDL_VideoCaptureDeviceID a, const SDL_VideoCaptureSpec *b, SDL_VideoCaptureSpec *c, int d),(a,b,c,d),return)
+SDL_DYNAPI_PROC(const char*,SDL_GetVideoCaptureDeviceName,(SDL_VideoCaptureDeviceID a),(a),return)
+SDL_DYNAPI_PROC(int,SDL_GetVideoCaptureSpec,(SDL_VideoCaptureDevice *a, SDL_VideoCaptureSpec *b),(a,b),return)
+SDL_DYNAPI_PROC(int,SDL_GetVideoCaptureFormat,(SDL_VideoCaptureDevice *a, int b, Uint32 *c),(a,b,c),return)
+SDL_DYNAPI_PROC(int,SDL_GetNumVideoCaptureFormats,(SDL_VideoCaptureDevice *a),(a),return)
+SDL_DYNAPI_PROC(int,SDL_GetVideoCaptureFrameSize,(SDL_VideoCaptureDevice *a, Uint32 b, int c, int *d, int *e),(a,b,c,d,e),return)
+SDL_DYNAPI_PROC(int,SDL_GetNumVideoCaptureFrameSizes,(SDL_VideoCaptureDevice *a, Uint32 b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_VideoCaptureStatus,SDL_GetVideoCaptureStatus,(SDL_VideoCaptureDevice *a),(a),return)
+SDL_DYNAPI_PROC(int,SDL_StartVideoCapture,(SDL_VideoCaptureDevice *a),(a),return)
+SDL_DYNAPI_PROC(int,SDL_AcquireVideoCaptureFrame,(SDL_VideoCaptureDevice *a, SDL_VideoCaptureFrame *b),(a,b),return)
+SDL_DYNAPI_PROC(int,SDL_ReleaseVideoCaptureFrame,(SDL_VideoCaptureDevice *a, SDL_VideoCaptureFrame *b),(a,b),return)
+SDL_DYNAPI_PROC(int,SDL_StopVideoCapture,(SDL_VideoCaptureDevice *a),(a),return)
+SDL_DYNAPI_PROC(void,SDL_CloseVideoCapture,(SDL_VideoCaptureDevice *a),(a),)
+SDL_DYNAPI_PROC(SDL_VideoCaptureDeviceID*,SDL_GetVideoCaptureDevices,(int *a),(a),return)
diff --git a/src/video/SDL_sysvideocapture.h b/src/video/SDL_sysvideocapture.h
new file mode 100644
index 000000000000..fe71664f5195
--- /dev/null
+++ b/src/video/SDL_sysvideocapture.h
@@ -0,0 +1,90 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../SDL_internal.h"
+
+#ifndef SDL_sysvideocapture_h_
+#define SDL_sysvideocapture_h_
+
+#include "../SDL_list.h"
+
+/* The SDL video_capture driver */
+typedef struct SDL_VideoCaptureDevice SDL_VideoCaptureDevice;
+
+/* Define the SDL video_capture driver structure */
+struct SDL_VideoCaptureDevice
+{
+ /* * * */
+ /* Data common to all devices */
+
+ /* The device's current video_capture specification */
+ SDL_VideoCaptureSpec spec;
+
+ /* Device name */
+ char *dev_name;
+
+ /* Current state flags */
+ SDL_AtomicInt shutdown;
+ SDL_AtomicInt enabled;
+ SDL_bool is_spec_set;
+
+ /* A mutex for locking the queue buffers */
+ SDL_Mutex *device_lock;
+ SDL_Mutex *acquiring_lock;
+
+ /* A thread to feed the video_capture device */
+ SDL_Thread *thread;
+ SDL_threadID threadid;
+
+ /* Queued buffers (if app not using callback). */
+ SDL_ListNode *buffer_queue;
+
+ /* * * */
+ /* Data private to this driver */
+ struct SDL_PrivateVideoCaptureData *hidden;
+};
+
+extern int OpenDevice(SDL_VideoCaptureDevice *_this);
+extern void CloseDevice(SDL_VideoCaptureDevice *_this);
+
+extern int InitDevice(SDL_VideoCaptureDevice *_this);
+
+extern int GetDeviceSpec(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureSpec *spec);
+
+extern int StartCapture(SDL_VideoCaptureDevice *_this);
+extern int StopCapture(SDL_VideoCaptureDevice *_this);
+
+extern int AcquireFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame);
+extern int ReleaseFrame(SDL_VideoCaptureDevice *_this, SDL_VideoCaptureFrame *frame);
+
+extern int GetNumFormats(SDL_VideoCaptureDevice *_this);
+extern int GetFormat(SDL_VideoCaptureDevice *_this, int index, Uint32 *format);
+
+extern int GetNumFrameSizes(SDL_VideoCaptureDevice *_this, Uint32 format);
+extern int GetFrameSize(SDL_VideoCaptureDevice *_this, Uint32 format, int index, int *width, int *height);
+
+extern int GetDeviceName(int index, char *buf, int size);
+extern int GetNumDevices(void);
+
+
+extern SDL_bool check_all_device_closed(void);
+extern SDL_bool check_device_playing(void);
+
+#endif /* SDL_sysvideocapture_h_ */
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index df0ad2351137..d4ab9a475d1a 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -31,6 +31,7 @@
#include "SDL_video_c.h"
#include "../events/SDL_events_c.h"
#include "../timer/SDL_timer_c.h"
+#include "SDL_video_capture_c.h"
#ifdef SDL_VIDEO_OPENGL
#include <SDL3/SDL_opengl.h>
@@ -443,6 +444,7 @@ int SDL_VideoInit(const char *driver_name)
SDL_bool init_keyboard = SDL_FALSE;
SDL_bool init_mouse = SDL_FALSE;
SDL_bool init_touch = SDL_FALSE;
+ SDL_bool init_video_capture = SDL_FALSE;
int i = 0;
/* Check to make sure we don't overwrite '_this' */
@@ -471,6 +473,10 @@ int SDL_VideoInit(const char *driver_name)
goto pre_driver_error;
}
init_touch = SDL_TRUE;
+ if (SDL_VideoCaptureInit() < 0) {
+ goto pre_driver_error;
+ }
+ init_video_capture = SDL_TRUE;
/* Select the proper video driver */
video = NULL;
@@ -565,6 +571,9 @@ int SDL_VideoInit(const char *driver_name)
pre_driver_error:
SDL_assert(_this == NULL);
+ if (init_video_capture) {
+ SDL_QuitVideoCapture();
+ }
if (init_touch) {
SDL_QuitTouch();
}
@@ -3684,6 +3693,7 @@ void SDL_VideoQuit(void)
SDL_ClearClipboardData
(Patch may be truncated, please check the link at the top of this post.)