Added support for Motion JPEG camera capture

Fixes https://github.com/libsdl-org/SDL/issues/12183
This commit is contained in:
Sam Lantinga 2025-02-07 08:27:37 -08:00
parent 3bc53b9ade
commit 84b0c13c44
16 changed files with 8267 additions and 59 deletions

View file

@ -594,6 +594,7 @@
<ClInclude Include="..\..\src\video\SDL_pixels_c.h" /> <ClInclude Include="..\..\src\video\SDL_pixels_c.h" />
<ClInclude Include="..\..\src\video\SDL_rect_c.h" /> <ClInclude Include="..\..\src\video\SDL_rect_c.h" />
<ClInclude Include="..\..\src\video\SDL_RLEaccel_c.h" /> <ClInclude Include="..\..\src\video\SDL_RLEaccel_c.h" />
<ClInclude Include="..\..\src\video\SDL_stb_c.h" />
<ClInclude Include="..\..\src\video\SDL_surface_c.h" /> <ClInclude Include="..\..\src\video\SDL_surface_c.h" />
<ClInclude Include="..\..\src\video\SDL_sysvideo.h" /> <ClInclude Include="..\..\src\video\SDL_sysvideo.h" />
<ClInclude Include="..\..\src\video\SDL_vulkan_internal.h" /> <ClInclude Include="..\..\src\video\SDL_vulkan_internal.h" />
@ -868,6 +869,7 @@
<ClCompile Include="..\..\src\video\SDL_pixels.c" /> <ClCompile Include="..\..\src\video\SDL_pixels.c" />
<ClCompile Include="..\..\src\video\SDL_rect.c" /> <ClCompile Include="..\..\src\video\SDL_rect.c" />
<ClCompile Include="..\..\src\video\SDL_RLEaccel.c" /> <ClCompile Include="..\..\src\video\SDL_RLEaccel.c" />
<ClCompile Include="..\..\src\video\SDL_stb.c" />
<ClCompile Include="..\..\src\video\SDL_stretch.c" /> <ClCompile Include="..\..\src\video\SDL_stretch.c" />
<ClCompile Include="..\..\src\video\SDL_surface.c" /> <ClCompile Include="..\..\src\video\SDL_surface.c" />
<ClCompile Include="..\..\src\video\SDL_video.c" /> <ClCompile Include="..\..\src\video\SDL_video.c" />

View file

@ -175,6 +175,7 @@
<ClCompile Include="..\..\src\video\SDL_pixels.c" /> <ClCompile Include="..\..\src\video\SDL_pixels.c" />
<ClCompile Include="..\..\src\video\SDL_rect.c" /> <ClCompile Include="..\..\src\video\SDL_rect.c" />
<ClCompile Include="..\..\src\video\SDL_RLEaccel.c" /> <ClCompile Include="..\..\src\video\SDL_RLEaccel.c" />
<ClCompile Include="..\..\src\video\SDL_stb.c" />
<ClCompile Include="..\..\src\video\SDL_stretch.c" /> <ClCompile Include="..\..\src\video\SDL_stretch.c" />
<ClCompile Include="..\..\src\video\SDL_surface.c" /> <ClCompile Include="..\..\src\video\SDL_surface.c" />
<ClCompile Include="..\..\src\video\SDL_video.c" /> <ClCompile Include="..\..\src\video\SDL_video.c" />
@ -434,6 +435,7 @@
<ClInclude Include="..\..\src\video\SDL_pixels_c.h" /> <ClInclude Include="..\..\src\video\SDL_pixels_c.h" />
<ClInclude Include="..\..\src\video\SDL_rect_c.h" /> <ClInclude Include="..\..\src\video\SDL_rect_c.h" />
<ClInclude Include="..\..\src\video\SDL_RLEaccel_c.h" /> <ClInclude Include="..\..\src\video\SDL_RLEaccel_c.h" />
<ClInclude Include="..\..\src\video\SDL_stb_c.h" />
<ClInclude Include="..\..\src\video\SDL_surface_c.h" /> <ClInclude Include="..\..\src\video\SDL_surface_c.h" />
<ClInclude Include="..\..\src\video\SDL_sysvideo.h" /> <ClInclude Include="..\..\src\video\SDL_sysvideo.h" />
<ClInclude Include="..\..\src\video\SDL_vulkan_internal.h" /> <ClInclude Include="..\..\src\video\SDL_vulkan_internal.h" />

View file

@ -492,6 +492,7 @@
<ClInclude Include="..\..\src\video\SDL_pixels_c.h" /> <ClInclude Include="..\..\src\video\SDL_pixels_c.h" />
<ClInclude Include="..\..\src\video\SDL_rect_c.h" /> <ClInclude Include="..\..\src\video\SDL_rect_c.h" />
<ClInclude Include="..\..\src\video\SDL_RLEaccel_c.h" /> <ClInclude Include="..\..\src\video\SDL_RLEaccel_c.h" />
<ClInclude Include="..\..\src\video\SDL_stb_c.h" />
<ClInclude Include="..\..\src\video\SDL_surface_c.h" /> <ClInclude Include="..\..\src\video\SDL_surface_c.h" />
<ClInclude Include="..\..\src\video\SDL_sysvideo.h" /> <ClInclude Include="..\..\src\video\SDL_sysvideo.h" />
<ClInclude Include="..\..\src\video\SDL_vulkan_internal.h" /> <ClInclude Include="..\..\src\video\SDL_vulkan_internal.h" />
@ -703,6 +704,7 @@
<ClCompile Include="..\..\src\video\SDL_pixels.c" /> <ClCompile Include="..\..\src\video\SDL_pixels.c" />
<ClCompile Include="..\..\src\video\SDL_rect.c" /> <ClCompile Include="..\..\src\video\SDL_rect.c" />
<ClCompile Include="..\..\src\video\SDL_RLEaccel.c" /> <ClCompile Include="..\..\src\video\SDL_RLEaccel.c" />
<ClCompile Include="..\..\src\video\SDL_stb.c" />
<ClCompile Include="..\..\src\video\SDL_stretch.c" /> <ClCompile Include="..\..\src\video\SDL_stretch.c" />
<ClCompile Include="..\..\src\video\SDL_surface.c" /> <ClCompile Include="..\..\src\video\SDL_surface.c" />
<ClCompile Include="..\..\src\video\SDL_video.c" /> <ClCompile Include="..\..\src\video\SDL_video.c" />

View file

@ -666,6 +666,9 @@
<ClInclude Include="..\..\src\video\SDL_egl_c.h"> <ClInclude Include="..\..\src\video\SDL_egl_c.h">
<Filter>video</Filter> <Filter>video</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\video\SDL_stb_c.h">
<Filter>video</Filter>
</ClInclude>
<ClInclude Include="..\..\src\video\SDL_yuv_c.h"> <ClInclude Include="..\..\src\video\SDL_yuv_c.h">
<Filter>video</Filter> <Filter>video</Filter>
</ClInclude> </ClInclude>
@ -1283,6 +1286,9 @@
<ClCompile Include="..\..\src\video\SDL_rect.c"> <ClCompile Include="..\..\src\video\SDL_rect.c">
<Filter>video</Filter> <Filter>video</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\video\SDL_stb.c">
<Filter>video</Filter>
</ClCompile>
<ClCompile Include="..\..\src\video\SDL_stretch.c"> <ClCompile Include="..\..\src\video\SDL_stretch.c">
<Filter>video</Filter> <Filter>video</Filter>
</ClCompile> </ClCompile>

View file

@ -516,6 +516,10 @@
F3DDCC5B2AFD42B600B0842B /* SDL_video_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC522AFD42B600B0842B /* SDL_video_c.h */; }; F3DDCC5B2AFD42B600B0842B /* SDL_video_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC522AFD42B600B0842B /* SDL_video_c.h */; };
F3DDCC5D2AFD42B600B0842B /* SDL_rect_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC542AFD42B600B0842B /* SDL_rect_impl.h */; }; F3DDCC5D2AFD42B600B0842B /* SDL_rect_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC542AFD42B600B0842B /* SDL_rect_impl.h */; };
F3E5A6EB2AD5E0E600293D83 /* SDL_properties.c in Sources */ = {isa = PBXBuildFile; fileRef = F3E5A6EA2AD5E0E600293D83 /* SDL_properties.c */; }; F3E5A6EB2AD5E0E600293D83 /* SDL_properties.c in Sources */ = {isa = PBXBuildFile; fileRef = F3E5A6EA2AD5E0E600293D83 /* SDL_properties.c */; };
F3EFA5ED2D5AB97300BCF22F /* SDL_stb_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3EFA5EA2D5AB97300BCF22F /* SDL_stb_c.h */; };
F3EFA5EE2D5AB97300BCF22F /* stb_image.h in Headers */ = {isa = PBXBuildFile; fileRef = F3EFA5EC2D5AB97300BCF22F /* stb_image.h */; };
F3EFA5EF2D5AB97300BCF22F /* SDL_surface_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3EFA5EB2D5AB97300BCF22F /* SDL_surface_c.h */; };
F3EFA5F02D5AB97300BCF22F /* SDL_stb.c in Sources */ = {isa = PBXBuildFile; fileRef = F3EFA5E92D5AB97300BCF22F /* SDL_stb.c */; };
F3F07D5A269640160074468B /* SDL_hidapi_luna.c in Sources */ = {isa = PBXBuildFile; fileRef = F3F07D59269640160074468B /* SDL_hidapi_luna.c */; }; F3F07D5A269640160074468B /* SDL_hidapi_luna.c in Sources */ = {isa = PBXBuildFile; fileRef = F3F07D59269640160074468B /* SDL_hidapi_luna.c */; };
F3F15D7F2D011912007AE210 /* SDL_dialog.c in Sources */ = {isa = PBXBuildFile; fileRef = F3F15D7D2D011912007AE210 /* SDL_dialog.c */; }; F3F15D7F2D011912007AE210 /* SDL_dialog.c in Sources */ = {isa = PBXBuildFile; fileRef = F3F15D7D2D011912007AE210 /* SDL_dialog.c */; };
F3F15D802D011912007AE210 /* SDL_dialog_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F15D7E2D011912007AE210 /* SDL_dialog_utils.h */; }; F3F15D802D011912007AE210 /* SDL_dialog_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F15D7E2D011912007AE210 /* SDL_dialog_utils.h */; };
@ -1079,6 +1083,10 @@
F3DDCC522AFD42B600B0842B /* SDL_video_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_video_c.h; sourceTree = "<group>"; }; F3DDCC522AFD42B600B0842B /* SDL_video_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_video_c.h; sourceTree = "<group>"; };
F3DDCC542AFD42B600B0842B /* SDL_rect_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_rect_impl.h; sourceTree = "<group>"; }; F3DDCC542AFD42B600B0842B /* SDL_rect_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_rect_impl.h; sourceTree = "<group>"; };
F3E5A6EA2AD5E0E600293D83 /* SDL_properties.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_properties.c; sourceTree = "<group>"; }; F3E5A6EA2AD5E0E600293D83 /* SDL_properties.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_properties.c; sourceTree = "<group>"; };
F3EFA5E92D5AB97300BCF22F /* SDL_stb.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SDL_stb.c; sourceTree = "<group>"; };
F3EFA5EA2D5AB97300BCF22F /* SDL_stb_c.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDL_stb_c.h; sourceTree = "<group>"; };
F3EFA5EB2D5AB97300BCF22F /* SDL_surface_c.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDL_surface_c.h; sourceTree = "<group>"; };
F3EFA5EC2D5AB97300BCF22F /* stb_image.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = stb_image.h; sourceTree = "<group>"; };
F3F07D59269640160074468B /* SDL_hidapi_luna.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_luna.c; sourceTree = "<group>"; }; F3F07D59269640160074468B /* SDL_hidapi_luna.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_luna.c; sourceTree = "<group>"; };
F3F15D7C2D011912007AE210 /* SDL_dialog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDL_dialog.h; sourceTree = "<group>"; }; F3F15D7C2D011912007AE210 /* SDL_dialog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDL_dialog.h; sourceTree = "<group>"; };
F3F15D7D2D011912007AE210 /* SDL_dialog.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SDL_dialog.c; sourceTree = "<group>"; }; F3F15D7D2D011912007AE210 /* SDL_dialog.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SDL_dialog.c; sourceTree = "<group>"; };
@ -1586,43 +1594,47 @@
A7D8A60523E2513D00DCD162 /* dummy */, A7D8A60523E2513D00DCD162 /* dummy */,
A7D8A72123E2513E00DCD162 /* khronos */, A7D8A72123E2513E00DCD162 /* khronos */,
A7D8A5EC23E2513D00DCD162 /* offscreen */, A7D8A5EC23E2513D00DCD162 /* offscreen */,
A7D8A61823E2513D00DCD162 /* uikit */, A7D8A76B23E2513E00DCD162 /* SDL_blit.h */,
A7D8A76C23E2513E00DCD162 /* yuv2rgb */, A7D8A64C23E2513D00DCD162 /* SDL_blit.c */,
A7D8A66223E2513E00DCD162 /* SDL_blit_0.c */, A7D8A66223E2513E00DCD162 /* SDL_blit_0.c */,
A7D8A6FA23E2513E00DCD162 /* SDL_blit_1.c */, A7D8A6FA23E2513E00DCD162 /* SDL_blit_1.c */,
A7D8A66423E2513E00DCD162 /* SDL_blit_A.c */, A7D8A66423E2513E00DCD162 /* SDL_blit_A.c */,
A7D8A63F23E2513D00DCD162 /* SDL_blit_auto.c */,
A7D8A73F23E2513E00DCD162 /* SDL_blit_auto.h */, A7D8A73F23E2513E00DCD162 /* SDL_blit_auto.h */,
A7D8A61623E2513D00DCD162 /* SDL_blit_copy.c */, A7D8A63F23E2513D00DCD162 /* SDL_blit_auto.c */,
A7D8A76623E2513E00DCD162 /* SDL_blit_copy.h */, A7D8A76623E2513E00DCD162 /* SDL_blit_copy.h */,
A7D8A61623E2513D00DCD162 /* SDL_blit_copy.c */,
A7D8A64223E2513D00DCD162 /* SDL_blit_N.c */, A7D8A64223E2513D00DCD162 /* SDL_blit_N.c */,
A7D8A60223E2513D00DCD162 /* SDL_blit_slow.c */,
A7D8A66323E2513E00DCD162 /* SDL_blit_slow.h */, A7D8A66323E2513E00DCD162 /* SDL_blit_slow.h */,
A7D8A64C23E2513D00DCD162 /* SDL_blit.c */, A7D8A60223E2513D00DCD162 /* SDL_blit_slow.c */,
A7D8A76B23E2513E00DCD162 /* SDL_blit.h */,
A7D8A77323E2513E00DCD162 /* SDL_bmp.c */, A7D8A77323E2513E00DCD162 /* SDL_bmp.c */,
F3DDCC4D2AFD42B500B0842B /* SDL_clipboard_c.h */,
A7D8A67B23E2513E00DCD162 /* SDL_clipboard.c */, A7D8A67B23E2513E00DCD162 /* SDL_clipboard.c */,
A7D8A60423E2513D00DCD162 /* SDL_egl_c.h */, F3DDCC4D2AFD42B500B0842B /* SDL_clipboard_c.h */,
A7D8A6B623E2513E00DCD162 /* SDL_egl.c */, A7D8A6B623E2513E00DCD162 /* SDL_egl.c */,
A7D8A60423E2513D00DCD162 /* SDL_egl_c.h */,
A7D8A76823E2513E00DCD162 /* SDL_fillrect.c */, A7D8A76823E2513E00DCD162 /* SDL_fillrect.c */,
A7D8A74023E2513E00DCD162 /* SDL_pixels_c.h */,
A7D8A64D23E2513D00DCD162 /* SDL_pixels.c */, A7D8A64D23E2513D00DCD162 /* SDL_pixels.c */,
A7D8A74023E2513E00DCD162 /* SDL_pixels_c.h */,
A7D8A63423E2513D00DCD162 /* SDL_rect.c */,
A7D8A60C23E2513D00DCD162 /* SDL_rect_c.h */, A7D8A60C23E2513D00DCD162 /* SDL_rect_c.h */,
F3DDCC542AFD42B600B0842B /* SDL_rect_impl.h */, F3DDCC542AFD42B600B0842B /* SDL_rect_impl.h */,
A7D8A63423E2513D00DCD162 /* SDL_rect.c */,
A7D8A76723E2513E00DCD162 /* SDL_RLEaccel_c.h */,
A7D8A61523E2513D00DCD162 /* SDL_RLEaccel.c */, A7D8A61523E2513D00DCD162 /* SDL_RLEaccel.c */,
A7D8A76723E2513E00DCD162 /* SDL_RLEaccel_c.h */,
F3EFA5E92D5AB97300BCF22F /* SDL_stb.c */,
F3EFA5EA2D5AB97300BCF22F /* SDL_stb_c.h */,
A7D8A60323E2513D00DCD162 /* SDL_stretch.c */, A7D8A60323E2513D00DCD162 /* SDL_stretch.c */,
A7D8A61423E2513D00DCD162 /* SDL_surface.c */, A7D8A61423E2513D00DCD162 /* SDL_surface.c */,
F3EFA5EB2D5AB97300BCF22F /* SDL_surface_c.h */,
A7D8A61723E2513D00DCD162 /* SDL_sysvideo.h */, A7D8A61723E2513D00DCD162 /* SDL_sysvideo.h */,
A7D8A60E23E2513D00DCD162 /* SDL_video.c */,
F3DDCC522AFD42B600B0842B /* SDL_video_c.h */, F3DDCC522AFD42B600B0842B /* SDL_video_c.h */,
E4F7981F2AD8D87F00669F54 /* SDL_video_unsupported.c */, E4F7981F2AD8D87F00669F54 /* SDL_video_unsupported.c */,
A7D8A60E23E2513D00DCD162 /* SDL_video.c */,
A7D8A63E23E2513D00DCD162 /* SDL_vulkan_internal.h */, A7D8A63E23E2513D00DCD162 /* SDL_vulkan_internal.h */,
A7D8A64023E2513D00DCD162 /* SDL_vulkan_utils.c */, A7D8A64023E2513D00DCD162 /* SDL_vulkan_utils.c */,
A7D8A76A23E2513E00DCD162 /* SDL_yuv_c.h */,
A7D8A67C23E2513E00DCD162 /* SDL_yuv.c */, A7D8A67C23E2513E00DCD162 /* SDL_yuv.c */,
A7D8A76A23E2513E00DCD162 /* SDL_yuv_c.h */,
F3EFA5EC2D5AB97300BCF22F /* stb_image.h */,
A7D8A61823E2513D00DCD162 /* uikit */,
A7D8A76C23E2513E00DCD162 /* yuv2rgb */,
); );
path = video; path = video;
sourceTree = "<group>"; sourceTree = "<group>";
@ -2458,6 +2470,9 @@
A7D8BB6F23E2514500DCD162 /* SDL_clipboardevents_c.h in Headers */, A7D8BB6F23E2514500DCD162 /* SDL_clipboardevents_c.h in Headers */,
A7D8AECA23E2514100DCD162 /* SDL_cocoaclipboard.h in Headers */, A7D8AECA23E2514100DCD162 /* SDL_cocoaclipboard.h in Headers */,
A7D8AF1223E2514100DCD162 /* SDL_cocoaevents.h in Headers */, A7D8AF1223E2514100DCD162 /* SDL_cocoaevents.h in Headers */,
F3EFA5ED2D5AB97300BCF22F /* SDL_stb_c.h in Headers */,
F3EFA5EE2D5AB97300BCF22F /* stb_image.h in Headers */,
F3EFA5EF2D5AB97300BCF22F /* SDL_surface_c.h in Headers */,
A7D8AE8E23E2514100DCD162 /* SDL_cocoakeyboard.h in Headers */, A7D8AE8E23E2514100DCD162 /* SDL_cocoakeyboard.h in Headers */,
A7D8AF0623E2514100DCD162 /* SDL_cocoamessagebox.h in Headers */, A7D8AF0623E2514100DCD162 /* SDL_cocoamessagebox.h in Headers */,
A7D8AEB223E2514100DCD162 /* SDL_cocoametalview.h in Headers */, A7D8AEB223E2514100DCD162 /* SDL_cocoametalview.h in Headers */,
@ -2950,6 +2965,7 @@
566E26CF246274CC00718109 /* SDL_syslocale.m in Sources */, 566E26CF246274CC00718109 /* SDL_syslocale.m in Sources */,
A7D8AFC023E2514200DCD162 /* SDL_egl.c in Sources */, A7D8AFC023E2514200DCD162 /* SDL_egl.c in Sources */,
A7D8AC3323E2514100DCD162 /* SDL_RLEaccel.c in Sources */, A7D8AC3323E2514100DCD162 /* SDL_RLEaccel.c in Sources */,
F3EFA5F02D5AB97300BCF22F /* SDL_stb.c in Sources */,
A7D8BBB123E2514500DCD162 /* SDL_assert.c in Sources */, A7D8BBB123E2514500DCD162 /* SDL_assert.c in Sources */,
A7D8B3DA23E2514300DCD162 /* SDL_bmp.c in Sources */, A7D8B3DA23E2514300DCD162 /* SDL_bmp.c in Sources */,
A7D8B96E23E2514400DCD162 /* SDL_stdlib.c in Sources */, A7D8B96E23E2514400DCD162 /* SDL_stdlib.c in Sources */,

View file

@ -161,6 +161,7 @@ def find_symbols_in_file(file: pathlib.Path) -> int:
"src/libm", "src/libm",
"src/hidapi", "src/hidapi",
"src/video/khronos", "src/video/khronos",
"src/video/stb_image.h",
"include/SDL3", "include/SDL3",
"build-scripts/gen_audio_resampler_filter.c", "build-scripts/gen_audio_resampler_filter.c",
"build-scripts/gen_audio_channel_conversion.c", "build-scripts/gen_audio_channel_conversion.c",

View file

@ -676,6 +676,9 @@ typedef enum SDL_PixelFormat
SDL_PIXELFORMAT_EXTERNAL_OES = 0x2053454fu, /**< Android video texture format */ SDL_PIXELFORMAT_EXTERNAL_OES = 0x2053454fu, /**< Android video texture format */
/* SDL_DEFINE_PIXELFOURCC('O', 'E', 'S', ' ') */ /* SDL_DEFINE_PIXELFOURCC('O', 'E', 'S', ' ') */
SDL_PIXELFORMAT_MJPG = 0x47504a4du, /**< Motion JPEG */
/* SDL_DEFINE_PIXELFOURCC('M', 'J', 'P', 'G') */
/* Aliases for RGBA byte arrays of color data, for the current platform */ /* Aliases for RGBA byte arrays of color data, for the current platform */
#if SDL_BYTEORDER == SDL_BIG_ENDIAN #if SDL_BYTEORDER == SDL_BIG_ENDIAN
SDL_PIXELFORMAT_RGBA32 = SDL_PIXELFORMAT_RGBA8888, SDL_PIXELFORMAT_RGBA32 = SDL_PIXELFORMAT_RGBA8888,

View file

@ -191,6 +191,11 @@
#define SDL_VIDEO_RENDER_SW 1 #define SDL_VIDEO_RENDER_SW 1
#endif #endif
/* STB image conversion */
#if !defined(SDL_HAVE_STB) && !defined(SDL_LEAN_AND_MEAN)
#define SDL_HAVE_STB 1
#endif
/* YUV formats /* YUV formats
- handling of YUV surfaces - handling of YUV surfaces
- blitting and conversion functions */ - blitting and conversion functions */

View file

@ -76,6 +76,7 @@ SDL_DEFINE_MEDIATYPE_GUID(MFVideoFormat_UYVY, FCC('UYVY'));
SDL_DEFINE_MEDIATYPE_GUID(MFVideoFormat_YVYU, FCC('YVYU')); SDL_DEFINE_MEDIATYPE_GUID(MFVideoFormat_YVYU, FCC('YVYU'));
SDL_DEFINE_MEDIATYPE_GUID(MFVideoFormat_NV12, FCC('NV12')); SDL_DEFINE_MEDIATYPE_GUID(MFVideoFormat_NV12, FCC('NV12'));
SDL_DEFINE_MEDIATYPE_GUID(MFVideoFormat_NV21, FCC('NV21')); SDL_DEFINE_MEDIATYPE_GUID(MFVideoFormat_NV21, FCC('NV21'));
SDL_DEFINE_MEDIATYPE_GUID(MFVideoFormat_MJPG, FCC('MJPG'));
#undef SDL_DEFINE_MEDIATYPE_GUID #undef SDL_DEFINE_MEDIATYPE_GUID
#ifdef __GNUC__ #ifdef __GNUC__
@ -102,7 +103,8 @@ static const struct
{ &SDL_MFVideoFormat_UYVY, SDL_PIXELFORMAT_UYVY, SDL_COLORSPACE_BT709_LIMITED }, { &SDL_MFVideoFormat_UYVY, SDL_PIXELFORMAT_UYVY, SDL_COLORSPACE_BT709_LIMITED },
{ &SDL_MFVideoFormat_YVYU, SDL_PIXELFORMAT_YVYU, SDL_COLORSPACE_BT709_LIMITED }, { &SDL_MFVideoFormat_YVYU, SDL_PIXELFORMAT_YVYU, SDL_COLORSPACE_BT709_LIMITED },
{ &SDL_MFVideoFormat_NV12, SDL_PIXELFORMAT_NV12, SDL_COLORSPACE_BT709_LIMITED }, { &SDL_MFVideoFormat_NV12, SDL_PIXELFORMAT_NV12, SDL_COLORSPACE_BT709_LIMITED },
{ &SDL_MFVideoFormat_NV21, SDL_PIXELFORMAT_NV21, SDL_COLORSPACE_BT709_LIMITED } { &SDL_MFVideoFormat_NV21, SDL_PIXELFORMAT_NV21, SDL_COLORSPACE_BT709_LIMITED },
{ &SDL_MFVideoFormat_MJPG, SDL_PIXELFORMAT_MJPG, SDL_COLORSPACE_SRGB }
}; };
static SDL_Colorspace GetMediaTypeColorspace(IMFMediaType *mediatype, SDL_Colorspace default_colorspace) static SDL_Colorspace GetMediaTypeColorspace(IMFMediaType *mediatype, SDL_Colorspace default_colorspace)
@ -296,6 +298,13 @@ static void MediaTypeToSDLFmt(IMFMediaType *mediatype, SDL_PixelFormat *format,
} }
} }
} }
#if DEBUG_CAMERA
SDL_Log("Unknown media type: 0x%x (%c%c%c%c)", type.Data1,
(char)(Uint8)(type.Data1 >> 0),
(char)(Uint8)(type.Data1 >> 8),
(char)(Uint8)(type.Data1 >> 16),
(char)(Uint8)(type.Data1 >> 24));
#endif
*format = SDL_PIXELFORMAT_UNKNOWN; *format = SDL_PIXELFORMAT_UNKNOWN;
*colorspace = SDL_COLORSPACE_UNKNOWN; *colorspace = SDL_COLORSPACE_UNKNOWN;
} }
@ -467,7 +476,11 @@ static SDL_CameraFrameResult MEDIAFOUNDATION_AcquireFrame(SDL_Camera *device, SD
CleanupIMF2DBuffer2(NULL, objs); CleanupIMF2DBuffer2(NULL, objs);
} else { } else {
frame->pixels = pixels; frame->pixels = pixels;
frame->pitch = (int) pitch; if (frame->format == SDL_PIXELFORMAT_MJPG) {
frame->pitch = (int)buflen;
} else {
frame->pitch = (int)pitch;
}
if (!SDL_SetPointerPropertyWithCleanup(surfprops, PROP_SURFACE_IMFOBJS_POINTER, objs, CleanupIMF2DBuffer2, NULL)) { if (!SDL_SetPointerPropertyWithCleanup(surfprops, PROP_SURFACE_IMFOBJS_POINTER, objs, CleanupIMF2DBuffer2, NULL)) {
result = SDL_CAMERA_FRAME_ERROR; result = SDL_CAMERA_FRAME_ERROR;
} }
@ -491,10 +504,14 @@ static SDL_CameraFrameResult MEDIAFOUNDATION_AcquireFrame(SDL_Camera *device, SD
CleanupIMFMediaBuffer(NULL, objs); CleanupIMFMediaBuffer(NULL, objs);
result = SDL_CAMERA_FRAME_ERROR; result = SDL_CAMERA_FRAME_ERROR;
} else { } else {
pitch = (LONG) device->hidden->pitch; if (frame->format == SDL_PIXELFORMAT_MJPG) {
pitch = (LONG)currentlen;
} else {
pitch = (LONG)device->hidden->pitch;
if (pitch < 0) { // image rows are reversed. if (pitch < 0) { // image rows are reversed.
pixels += -pitch * (frame->h - 1); pixels += -pitch * (frame->h - 1);
} }
}
frame->pixels = pixels; frame->pixels = pixels;
frame->pitch = (int) pitch; frame->pitch = (int) pitch;
if (!SDL_SetPointerPropertyWithCleanup(surfprops, PROP_SURFACE_IMFOBJS_POINTER, objs, CleanupIMFMediaBuffer, NULL)) { if (!SDL_SetPointerPropertyWithCleanup(surfprops, PROP_SURFACE_IMFOBJS_POINTER, objs, CleanupIMFMediaBuffer, NULL)) {
@ -522,6 +539,18 @@ static void MEDIAFOUNDATION_ReleaseFrame(SDL_Camera *device, SDL_Surface *frame)
#else #else
static SDL_CameraFrameResult MEDIAFOUNDATION_CopyFrame(SDL_Surface *frame, const void *pixels, LONG pitch, DWORD buflen)
{
frame->pixels = SDL_aligned_alloc(SDL_GetSIMDAlignment(), buflen);
if (!frame->pixels) {
return SDL_CAMERA_FRAME_ERROR;
}
SDL_memcpy(frame->pixels, pixels, buflen);
frame->pitch = (int)pitch;
return SDL_CAMERA_FRAME_READY;
}
static SDL_CameraFrameResult MEDIAFOUNDATION_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS) static SDL_CameraFrameResult MEDIAFOUNDATION_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS)
{ {
SDL_assert(device->hidden->current_sample != NULL); SDL_assert(device->hidden->current_sample != NULL);
@ -563,12 +592,10 @@ static SDL_CameraFrameResult MEDIAFOUNDATION_AcquireFrame(SDL_Camera *device, SD
if (FAILED(ret)) { if (FAILED(ret)) {
result = SDL_CAMERA_FRAME_ERROR; result = SDL_CAMERA_FRAME_ERROR;
} else { } else {
frame->pixels = SDL_aligned_alloc(SDL_GetSIMDAlignment(), buflen); if (frame->format == SDL_PIXELFORMAT_MJPG) {
if (frame->pixels == NULL) { result = MEDIAFOUNDATION_CopyFrame(frame, pixels, (LONG)buflen, buflen);
result = SDL_CAMERA_FRAME_ERROR;
} else { } else {
SDL_memcpy(frame->pixels, pixels, buflen); result = MEDIAFOUNDATION_CopyFrame(frame, pixels, pitch, buflen);
frame->pitch = (int)pitch;
} }
IMF2DBuffer2_Unlock2D(buffer2d2); IMF2DBuffer2_Unlock2D(buffer2d2);
} }
@ -577,18 +604,18 @@ static SDL_CameraFrameResult MEDIAFOUNDATION_AcquireFrame(SDL_Camera *device, SD
ret = IMF2DBuffer_Lock2D(buffer2d, &pixels, &pitch); ret = IMF2DBuffer_Lock2D(buffer2d, &pixels, &pitch);
if (FAILED(ret)) { if (FAILED(ret)) {
result = SDL_CAMERA_FRAME_ERROR; result = SDL_CAMERA_FRAME_ERROR;
} else {
if (frame->format == SDL_PIXELFORMAT_MJPG) {
// FIXME: How big is this frame?
const DWORD buflen = 0;
result = MEDIAFOUNDATION_CopyFrame(frame, pixels, pitch, buflen);
} else { } else {
BYTE *bufstart = pixels; BYTE *bufstart = pixels;
const DWORD buflen = (SDL_abs((int)pitch) * frame->w) * frame->h; const DWORD buflen = (SDL_abs((int)pitch) * frame->w) * frame->h;
if (pitch < 0) { // image rows are reversed. if (pitch < 0) { // image rows are reversed.
bufstart += -pitch * (frame->h - 1); bufstart += -pitch * (frame->h - 1);
} }
frame->pixels = SDL_aligned_alloc(SDL_GetSIMDAlignment(), buflen); result = MEDIAFOUNDATION_CopyFrame(frame, bufstart, pitch, buflen);
if (frame->pixels == NULL) {
result = SDL_CAMERA_FRAME_ERROR;
} else {
SDL_memcpy(frame->pixels, bufstart, buflen);
frame->pitch = (int)pitch;
} }
IMF2DBuffer_Unlock2D(buffer2d); IMF2DBuffer_Unlock2D(buffer2d);
} }
@ -598,6 +625,9 @@ static SDL_CameraFrameResult MEDIAFOUNDATION_AcquireFrame(SDL_Camera *device, SD
ret = IMFMediaBuffer_Lock(buffer, &pixels, &maxlen, &currentlen); ret = IMFMediaBuffer_Lock(buffer, &pixels, &maxlen, &currentlen);
if (FAILED(ret)) { if (FAILED(ret)) {
result = SDL_CAMERA_FRAME_ERROR; result = SDL_CAMERA_FRAME_ERROR;
} else {
if (frame->format == SDL_PIXELFORMAT_MJPG) {
result = MEDIAFOUNDATION_CopyFrame(frame, pixels, (LONG)currentlen, currentlen);
} else { } else {
BYTE *bufstart = pixels; BYTE *bufstart = pixels;
pitch = (LONG)device->hidden->pitch; pitch = (LONG)device->hidden->pitch;
@ -605,12 +635,7 @@ static SDL_CameraFrameResult MEDIAFOUNDATION_AcquireFrame(SDL_Camera *device, SD
if (pitch < 0) { // image rows are reversed. if (pitch < 0) { // image rows are reversed.
bufstart += -pitch * (frame->h - 1); bufstart += -pitch * (frame->h - 1);
} }
frame->pixels = SDL_aligned_alloc(SDL_GetSIMDAlignment(), buflen); result = MEDIAFOUNDATION_CopyFrame(frame, bufstart, pitch, buflen);
if (frame->pixels == NULL) {
result = SDL_CAMERA_FRAME_ERROR;
} else {
SDL_memcpy(frame->pixels, bufstart, buflen);
frame->pitch = (int)pitch;
} }
IMFMediaBuffer_Unlock(buffer); IMFMediaBuffer_Unlock(buffer);
} }

View file

@ -128,10 +128,11 @@ static SDL_CameraFrameResult V4L2_AcquireFrame(SDL_Camera *device, SDL_Surface *
const io_method io = device->hidden->io; const io_method io = device->hidden->io;
size_t size = device->hidden->buffers[0].length; size_t size = device->hidden->buffers[0].length;
struct v4l2_buffer buf; struct v4l2_buffer buf;
ssize_t amount;
switch (io) { switch (io) {
case IO_METHOD_READ: case IO_METHOD_READ:
if (read(fd, device->hidden->buffers[0].start, size) == -1) { if ((amount = read(fd, device->hidden->buffers[0].start, size)) == -1) {
switch (errno) { switch (errno) {
case EAGAIN: case EAGAIN:
return SDL_CAMERA_FRAME_SKIP; return SDL_CAMERA_FRAME_SKIP;
@ -148,7 +149,11 @@ static SDL_CameraFrameResult V4L2_AcquireFrame(SDL_Camera *device, SDL_Surface *
*timestampNS = SDL_GetTicksNS(); // oh well, close enough. *timestampNS = SDL_GetTicksNS(); // oh well, close enough.
frame->pixels = device->hidden->buffers[0].start; frame->pixels = device->hidden->buffers[0].start;
if (device->hidden->driver_pitch) {
frame->pitch = device->hidden->driver_pitch; frame->pitch = device->hidden->driver_pitch;
} else {
frame->pitch = (int)amount;
}
break; break;
case IO_METHOD_MMAP: case IO_METHOD_MMAP:
@ -178,7 +183,11 @@ static SDL_CameraFrameResult V4L2_AcquireFrame(SDL_Camera *device, SDL_Surface *
} }
frame->pixels = device->hidden->buffers[buf.index].start; frame->pixels = device->hidden->buffers[buf.index].start;
if (device->hidden->driver_pitch) {
frame->pitch = device->hidden->driver_pitch; frame->pitch = device->hidden->driver_pitch;
} else {
frame->pitch = buf.bytesused;
}
device->hidden->buffers[buf.index].available = 1; device->hidden->buffers[buf.index].available = 1;
*timestampNS = (((Uint64) buf.timestamp.tv_sec) * SDL_NS_PER_SECOND) + SDL_US_TO_NS(buf.timestamp.tv_usec); *timestampNS = (((Uint64) buf.timestamp.tv_sec) * SDL_NS_PER_SECOND) + SDL_US_TO_NS(buf.timestamp.tv_usec);
@ -222,7 +231,11 @@ static SDL_CameraFrameResult V4L2_AcquireFrame(SDL_Camera *device, SDL_Surface *
} }
frame->pixels = (void*)buf.m.userptr; frame->pixels = (void*)buf.m.userptr;
if (device->hidden->driver_pitch) {
frame->pitch = device->hidden->driver_pitch; frame->pitch = device->hidden->driver_pitch;
} else {
frame->pitch = buf.bytesused;
}
device->hidden->buffers[i].available = 1; device->hidden->buffers[i].available = 1;
*timestampNS = (((Uint64) buf.timestamp.tv_sec) * SDL_NS_PER_SECOND) + SDL_US_TO_NS(buf.timestamp.tv_usec); *timestampNS = (((Uint64) buf.timestamp.tv_sec) * SDL_NS_PER_SECOND) + SDL_US_TO_NS(buf.timestamp.tv_usec);
@ -404,10 +417,15 @@ static void format_v4l2_to_sdl(Uint32 fmt, SDL_PixelFormat *format, SDL_Colorspa
switch (fmt) { switch (fmt) {
#define CASE(x, y, z) case x: *format = y; *colorspace = z; return #define CASE(x, y, z) case x: *format = y; *colorspace = z; return
CASE(V4L2_PIX_FMT_YUYV, SDL_PIXELFORMAT_YUY2, SDL_COLORSPACE_BT709_LIMITED); CASE(V4L2_PIX_FMT_YUYV, SDL_PIXELFORMAT_YUY2, SDL_COLORSPACE_BT709_LIMITED);
CASE(V4L2_PIX_FMT_MJPEG, SDL_PIXELFORMAT_MJPG, SDL_COLORSPACE_SRGB);
#undef CASE #undef CASE
default: default:
#if DEBUG_CAMERA #if DEBUG_CAMERA
SDL_Log("CAMERA: Unknown format V4L2_PIX_FORMAT '%d'", fmt); SDL_Log("CAMERA: Unknown format V4L2_PIX_FORMAT '%c%c%c%c' (0x%x)",
(char)(Uint8)(fmt >> 0),
(char)(Uint8)(fmt >> 8),
(char)(Uint8)(fmt >> 16),
(char)(Uint8)(fmt >> 24), fmt);
#endif #endif
break; break;
} }

View file

@ -1282,7 +1282,14 @@ static SDL_PixelFormat GetClosestSupportedFormat(SDL_Renderer *renderer, SDL_Pix
{ {
int i; int i;
if (SDL_ISPIXELFORMAT_FOURCC(format)) { if (format == SDL_PIXELFORMAT_MJPG) {
// We'll decode to SDL_PIXELFORMAT_RGBA32
for (i = 0; i < renderer->num_texture_formats; ++i) {
if (renderer->texture_formats[i] == SDL_PIXELFORMAT_RGBA32) {
return renderer->texture_formats[i];
}
}
} else if (SDL_ISPIXELFORMAT_FOURCC(format)) {
// Look for an exact match // Look for an exact match
for (i = 0; i < renderer->num_texture_formats; ++i) { for (i = 0; i < renderer->num_texture_formats; ++i) {
if (renderer->texture_formats[i] == format) { if (renderer->texture_formats[i] == format) {
@ -1444,7 +1451,9 @@ SDL_Texture *SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_Propert
texture->next = texture->native; texture->next = texture->native;
renderer->textures = texture; renderer->textures = texture;
if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { if (texture->format == SDL_PIXELFORMAT_MJPG) {
// We have a custom decode + upload path for this
} else if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
#ifdef SDL_HAVE_YUV #ifdef SDL_HAVE_YUV
texture->yuv = SDL_SW_CreateYUVTexture(texture->format, texture->colorspace, w, h); texture->yuv = SDL_SW_CreateYUVTexture(texture->format, texture->colorspace, w, h);
#else #else
@ -2030,9 +2039,9 @@ static bool SDL_UpdateTextureNative(SDL_Texture *texture, const SDL_Rect *rect,
if (!SDL_LockTexture(native, rect, &native_pixels, &native_pitch)) { if (!SDL_LockTexture(native, rect, &native_pixels, &native_pitch)) {
return false; return false;
} }
SDL_ConvertPixels(rect->w, rect->h, SDL_ConvertPixelsAndColorspace(rect->w, rect->h,
texture->format, pixels, pitch, texture->format, texture->colorspace, 0, pixels, pitch,
native->format, native_pixels, native_pitch); native->format, native->colorspace, 0, native_pixels, native_pitch);
SDL_UnlockTexture(native); SDL_UnlockTexture(native);
} else { } else {
// Use a temporary buffer for updating // Use a temporary buffer for updating
@ -2043,9 +2052,9 @@ static bool SDL_UpdateTextureNative(SDL_Texture *texture, const SDL_Rect *rect,
if (!temp_pixels) { if (!temp_pixels) {
return false; return false;
} }
SDL_ConvertPixels(rect->w, rect->h, SDL_ConvertPixelsAndColorspace(rect->w, rect->h,
texture->format, pixels, pitch, texture->format, texture->colorspace, 0, pixels, pitch,
native->format, temp_pixels, temp_pitch); native->format, native->colorspace, 0, temp_pixels, temp_pitch);
SDL_UpdateTexture(native, rect, temp_pixels, temp_pitch); SDL_UpdateTexture(native, rect, temp_pixels, temp_pitch);
SDL_free(temp_pixels); SDL_free(temp_pixels);
} }

View file

@ -155,6 +155,7 @@ const char *SDL_GetPixelFormatName(SDL_PixelFormat format)
CASE(SDL_PIXELFORMAT_NV21) CASE(SDL_PIXELFORMAT_NV21)
CASE(SDL_PIXELFORMAT_P010) CASE(SDL_PIXELFORMAT_P010)
CASE(SDL_PIXELFORMAT_EXTERNAL_OES) CASE(SDL_PIXELFORMAT_EXTERNAL_OES)
CASE(SDL_PIXELFORMAT_MJPG)
default: default:
return "SDL_PIXELFORMAT_UNKNOWN"; return "SDL_PIXELFORMAT_UNKNOWN";
@ -690,7 +691,9 @@ void SDL_QuitPixelFormatDetails(void)
SDL_Colorspace SDL_GetDefaultColorspaceForFormat(SDL_PixelFormat format) SDL_Colorspace SDL_GetDefaultColorspaceForFormat(SDL_PixelFormat format)
{ {
if (SDL_ISPIXELFORMAT_FOURCC(format)) { if (SDL_ISPIXELFORMAT_FOURCC(format)) {
if (format == SDL_PIXELFORMAT_P010) { if (format == SDL_PIXELFORMAT_MJPG) {
return SDL_COLORSPACE_SRGB;
} else if (format == SDL_PIXELFORMAT_P010) {
return SDL_COLORSPACE_HDR10; return SDL_COLORSPACE_HDR10;
} else { } else {
return SDL_COLORSPACE_YUV_DEFAULT; return SDL_COLORSPACE_YUV_DEFAULT;

92
src/video/SDL_stb.c Normal file
View file

@ -0,0 +1,92 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 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"
#include "SDL_stb_c.h"
// We currently only support JPEG, but we could add other image formats if we wanted
#ifdef SDL_HAVE_STB
#define malloc SDL_malloc
#define realloc SDL_realloc
#define free SDL_free
#undef memcpy
#define memcpy SDL_memcpy
#undef memset
#define memset SDL_memset
#undef strcmp
#define strcmp SDL_strcmp
#undef strncmp
#define strncmp SDL_strncmp
#define strtol SDL_strtol
#define abs SDL_abs
#define pow SDL_pow
#define ldexp SDL_scalbn
#define STB_INTERNAL_SDL
#define STB_IMAGE_STATIC
#define STBI_FAILURE_USERMSG
#if defined(__ARM_NEON)
#define STBI_NEON
#endif
#define STBI_ONLY_JPEG
#define STBI_NO_GIF
#define STBI_NO_PNG
#define STBI_NO_HDR
#define STBI_NO_LINEAR
#define STBI_NO_ZLIB
#define STBI_NO_STDIO
#define STBI_ASSERT SDL_assert
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#endif
bool SDL_ConvertPixels_STB(int width, int height,
SDL_PixelFormat src_format, SDL_Colorspace src_colorspace, SDL_PropertiesID src_properties, const void *src, int src_pitch,
SDL_PixelFormat dst_format, SDL_Colorspace dst_colorspace, SDL_PropertiesID dst_properties, void *dst, int dst_pitch)
{
#ifdef SDL_HAVE_STB
if (src_colorspace != dst_colorspace) {
return SDL_SetError("SDL_ConvertPixels_STB: colorspace conversion not supported");
}
if (src_format == dst_format) {
if (src == dst) {
// Nothing to do
return true;
}
}
int w = 0, h = 0, format = 0;
stbi_uc *pixels = stbi_load_from_memory((const stbi_uc *)src, src_pitch, &w, &h, &format, 4);
if (!pixels) {
return SDL_SetError("Couldn't decode image: %s", stbi_failure_reason());
}
bool result = SDL_ConvertPixelsAndColorspace(w, h, SDL_PIXELFORMAT_RGBA32, src_colorspace, src_properties, pixels, width * 4, dst_format, dst_colorspace, dst_properties, dst, dst_pitch);
stbi_image_free(pixels);
return result;
#else
return SDL_SetError("SDL not built with STB image support");
#endif
}

31
src/video/SDL_stb_c.h Normal file
View file

@ -0,0 +1,31 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 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.
*/
#ifndef SDL_stb_c_h_
#define SDL_stb_c_h_
#include "SDL_internal.h"
// Image conversion functions
extern bool SDL_ConvertPixels_STB(int width, int height, SDL_PixelFormat src_format, SDL_Colorspace src_colorspace, SDL_PropertiesID src_properties, const void *src, int src_pitch, SDL_PixelFormat dst_format, SDL_Colorspace dst_colorspace, SDL_PropertiesID dst_properties, void *dst, int dst_pitch);
#endif // SDL_stb_c_h_

View file

@ -24,6 +24,7 @@
#include "SDL_video_c.h" #include "SDL_video_c.h"
#include "SDL_RLEaccel_c.h" #include "SDL_RLEaccel_c.h"
#include "SDL_pixels_c.h" #include "SDL_pixels_c.h"
#include "SDL_stb_c.h"
#include "SDL_yuv_c.h" #include "SDL_yuv_c.h"
#include "../render/SDL_sysrender.h" #include "../render/SDL_sysrender.h"
@ -2277,6 +2278,10 @@ bool SDL_ConvertPixelsAndColorspace(int width, int height,
dst_colorspace = SDL_GetDefaultColorspaceForFormat(dst_format); dst_colorspace = SDL_GetDefaultColorspaceForFormat(dst_format);
} }
if (src_format == SDL_PIXELFORMAT_MJPG) {
return SDL_ConvertPixels_STB(width, height, src_format, src_colorspace, src_properties, src, src_pitch, dst_format, dst_colorspace, dst_properties, dst, dst_pitch);
}
#ifdef SDL_HAVE_YUV #ifdef SDL_HAVE_YUV
if (SDL_ISPIXELFORMAT_FOURCC(src_format) && SDL_ISPIXELFORMAT_FOURCC(dst_format)) { if (SDL_ISPIXELFORMAT_FOURCC(src_format) && SDL_ISPIXELFORMAT_FOURCC(dst_format)) {
return SDL_ConvertPixels_YUV_to_YUV(width, height, src_format, src_colorspace, src_properties, src, src_pitch, dst_format, dst_colorspace, dst_properties, dst, dst_pitch); return SDL_ConvertPixels_YUV_to_YUV(width, height, src_format, src_colorspace, src_properties, src, src_pitch, dst_format, dst_colorspace, dst_properties, dst, dst_pitch);

7988
src/video/stb_image.h Normal file

File diff suppressed because it is too large Load diff