SDL video capture

This commit is contained in:
Sylvain 2023-02-10 10:53:50 +01:00
parent 7c4ec1867b
commit 87c4fe5690
No known key found for this signature in database
GPG key ID: 5F87E02E5BC0939E
17 changed files with 4424 additions and 0 deletions

View file

@ -2009,6 +2009,11 @@ elseif(APPLE)
set(HAVE_SDL_FILE TRUE)
endif()
if(IOS OR TVOS OR MACOSX OR DARWIN)
file(GLOB SDL_VIDEO_CAPTURE_SOURCES ${SDL3_SOURCE_DIR}/src/video/SDL_video_capture_apple.m)
list(APPEND SOURCE_FILES ${SDL_VIDEO_CAPTURE_SOURCES})
endif()
if(SDL_MISC)
if(IOS OR TVOS)
file(GLOB MISC_SOURCES ${SDL3_SOURCE_DIR}/src/misc/ios/*.m)
@ -2201,6 +2206,11 @@ 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)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DHAVE_COREMEDIA=1")
list(APPEND SDL_EXTRA_LDFLAGS "-Wl,-weak_framework,CoreMedia")
endif()
list(APPEND SDL_EXTRA_LDFLAGS "-Wl,-framework,CoreVideo")
endif()
if(SDL_FRAMEWORK_COCOA)

View file

@ -487,6 +487,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_yuv.c" />
<ClCompile Include="..\src\video\winrt\SDL_winrtevents.cpp">
<CompileAsWinRT>true</CompileAsWinRT>

View file

@ -756,6 +756,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\winrt\SDL_winrtevents.cpp">
<Filter>Source Files</Filter>
</ClCompile>

View file

@ -630,6 +630,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_vulkan_utils.c" />
<ClCompile Include="..\..\src\video\SDL_yuv.c" />
<ClCompile Include="..\..\src\video\windows\SDL_windowsclipboard.c" />

View file

@ -1144,6 +1144,9 @@
<ClCompile Include="..\..\src\video\SDL_video.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>

View file

@ -130,6 +130,54 @@
A1626A582617008D003F1973 /* SDL_triangle.h in Headers */ = {isa = PBXBuildFile; fileRef = A1626A512617008C003F1973 /* SDL_triangle.h */; };
A1626A592617008D003F1973 /* SDL_triangle.h in Headers */ = {isa = PBXBuildFile; fileRef = A1626A512617008C003F1973 /* SDL_triangle.h */; };
A1626A5A2617008D003F1973 /* SDL_triangle.h in Headers */ = {isa = PBXBuildFile; fileRef = A1626A512617008C003F1973 /* SDL_triangle.h */; };
A16680C229967B6900318FE2 /* SDL_video_capture.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C129967B6900318FE2 /* SDL_video_capture.h */; settings = {ATTRIBUTES = (Public, ); }; };
A16680C329967B6900318FE2 /* SDL_video_capture.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C129967B6900318FE2 /* SDL_video_capture.h */; settings = {ATTRIBUTES = (Public, ); }; };
A16680C429967B6900318FE2 /* SDL_video_capture.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C129967B6900318FE2 /* SDL_video_capture.h */; settings = {ATTRIBUTES = (Public, ); }; };
A16680CA29967BD100318FE2 /* SDL_video_capture.c in Sources */ = {isa = PBXBuildFile; fileRef = A16680C529967BD000318FE2 /* SDL_video_capture.c */; };
A16680CB29967BD100318FE2 /* SDL_video_capture.c in Sources */ = {isa = PBXBuildFile; fileRef = A16680C529967BD000318FE2 /* SDL_video_capture.c */; };
A16680CC29967BD100318FE2 /* SDL_video_capture.c in Sources */ = {isa = PBXBuildFile; fileRef = A16680C529967BD000318FE2 /* SDL_video_capture.c */; };
A16680CD29967BD100318FE2 /* SDL_sysvideocapture.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C629967BD000318FE2 /* SDL_sysvideocapture.h */; };
A16680CE29967BD100318FE2 /* SDL_sysvideocapture.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C629967BD000318FE2 /* SDL_sysvideocapture.h */; };
A16680CF29967BD100318FE2 /* SDL_sysvideocapture.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C629967BD000318FE2 /* SDL_sysvideocapture.h */; };
A16680D029967BD100318FE2 /* SDL_video_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C729967BD100318FE2 /* SDL_video_c.h */; };
A16680D129967BD100318FE2 /* SDL_video_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C729967BD100318FE2 /* SDL_video_c.h */; };
A16680D229967BD100318FE2 /* SDL_video_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C729967BD100318FE2 /* SDL_video_c.h */; };
A16680D329967BD100318FE2 /* SDL_video_capture_apple.m in Sources */ = {isa = PBXBuildFile; fileRef = A16680C829967BD100318FE2 /* SDL_video_capture_apple.m */; };
A16680D429967BD100318FE2 /* SDL_video_capture_apple.m in Sources */ = {isa = PBXBuildFile; fileRef = A16680C829967BD100318FE2 /* SDL_video_capture_apple.m */; };
A16680D529967BD100318FE2 /* SDL_video_capture_apple.m in Sources */ = {isa = PBXBuildFile; fileRef = A16680C829967BD100318FE2 /* SDL_video_capture_apple.m */; };
A16680D629967BD100318FE2 /* SDL_video_capture_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C929967BD100318FE2 /* SDL_video_capture_c.h */; };
A16680D729967BD100318FE2 /* SDL_video_capture_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C929967BD100318FE2 /* SDL_video_capture_c.h */; };
A16680D829967BD100318FE2 /* SDL_video_capture_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C929967BD100318FE2 /* SDL_video_capture_c.h */; };
A16680D929967BEE00318FE2 /* SDL_sysvideocapture.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C629967BD000318FE2 /* SDL_sysvideocapture.h */; };
A16680DA29967BEE00318FE2 /* SDL_sysvideocapture.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C629967BD000318FE2 /* SDL_sysvideocapture.h */; };
A16680DB29967BEF00318FE2 /* SDL_sysvideocapture.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C629967BD000318FE2 /* SDL_sysvideocapture.h */; };
A16680DC29967BEF00318FE2 /* SDL_sysvideocapture.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C629967BD000318FE2 /* SDL_sysvideocapture.h */; };
A16680DD29967BF000318FE2 /* SDL_sysvideocapture.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C629967BD000318FE2 /* SDL_sysvideocapture.h */; };
A16680DE29967BF000318FE2 /* SDL_sysvideocapture.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C629967BD000318FE2 /* SDL_sysvideocapture.h */; };
A16680DF29967C0A00318FE2 /* SDL_video_capture.c in Sources */ = {isa = PBXBuildFile; fileRef = A16680C529967BD000318FE2 /* SDL_video_capture.c */; };
A16680E029967C0A00318FE2 /* SDL_video_capture_apple.m in Sources */ = {isa = PBXBuildFile; fileRef = A16680C829967BD100318FE2 /* SDL_video_capture_apple.m */; };
A16680E129967C0A00318FE2 /* SDL_video_capture_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C929967BD100318FE2 /* SDL_video_capture_c.h */; };
A16680E229967C0A00318FE2 /* SDL_video_capture.c in Sources */ = {isa = PBXBuildFile; fileRef = A16680C529967BD000318FE2 /* SDL_video_capture.c */; };
A16680E329967C0A00318FE2 /* SDL_video_capture_apple.m in Sources */ = {isa = PBXBuildFile; fileRef = A16680C829967BD100318FE2 /* SDL_video_capture_apple.m */; };
A16680E429967C0A00318FE2 /* SDL_video_capture_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C929967BD100318FE2 /* SDL_video_capture_c.h */; };
A16680E529967C0B00318FE2 /* SDL_video_capture.c in Sources */ = {isa = PBXBuildFile; fileRef = A16680C529967BD000318FE2 /* SDL_video_capture.c */; };
A16680E629967C0B00318FE2 /* SDL_video_capture_apple.m in Sources */ = {isa = PBXBuildFile; fileRef = A16680C829967BD100318FE2 /* SDL_video_capture_apple.m */; };
A16680E729967C0B00318FE2 /* SDL_video_capture_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C929967BD100318FE2 /* SDL_video_capture_c.h */; };
A16680E829967C0B00318FE2 /* SDL_video_capture.c in Sources */ = {isa = PBXBuildFile; fileRef = A16680C529967BD000318FE2 /* SDL_video_capture.c */; };
A16680E929967C0B00318FE2 /* SDL_video_capture_apple.m in Sources */ = {isa = PBXBuildFile; fileRef = A16680C829967BD100318FE2 /* SDL_video_capture_apple.m */; };
A16680EA29967C0B00318FE2 /* SDL_video_capture_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C929967BD100318FE2 /* SDL_video_capture_c.h */; };
A16680EB29967C0C00318FE2 /* SDL_video_capture.c in Sources */ = {isa = PBXBuildFile; fileRef = A16680C529967BD000318FE2 /* SDL_video_capture.c */; };
A16680EC29967C0C00318FE2 /* SDL_video_capture_apple.m in Sources */ = {isa = PBXBuildFile; fileRef = A16680C829967BD100318FE2 /* SDL_video_capture_apple.m */; };
A16680ED29967C0C00318FE2 /* SDL_video_capture_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C929967BD100318FE2 /* SDL_video_capture_c.h */; };
A16680EE29967C0C00318FE2 /* SDL_video_capture.c in Sources */ = {isa = PBXBuildFile; fileRef = A16680C529967BD000318FE2 /* SDL_video_capture.c */; };
A16680EF29967C0C00318FE2 /* SDL_video_capture_apple.m in Sources */ = {isa = PBXBuildFile; fileRef = A16680C829967BD100318FE2 /* SDL_video_capture_apple.m */; };
A16680F029967C0C00318FE2 /* SDL_video_capture_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C929967BD100318FE2 /* SDL_video_capture_c.h */; };
A16680F129967C1B00318FE2 /* SDL_video_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C729967BD100318FE2 /* SDL_video_c.h */; };
A16680F229967C1C00318FE2 /* SDL_video_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C729967BD100318FE2 /* SDL_video_c.h */; };
A16680F329967C1C00318FE2 /* SDL_video_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C729967BD100318FE2 /* SDL_video_c.h */; };
A16680F429967C1C00318FE2 /* SDL_video_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C729967BD100318FE2 /* SDL_video_c.h */; };
A16680F529967C1D00318FE2 /* SDL_video_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C729967BD100318FE2 /* SDL_video_c.h */; };
A16680F629967C1D00318FE2 /* SDL_video_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A16680C729967BD100318FE2 /* SDL_video_c.h */; };
A1BB8B6327F6CF330057CFA8 /* SDL_list.c in Sources */ = {isa = PBXBuildFile; fileRef = A1BB8B6127F6CF320057CFA8 /* SDL_list.c */; };
A1BB8B6427F6CF330057CFA8 /* SDL_list.c in Sources */ = {isa = PBXBuildFile; fileRef = A1BB8B6127F6CF320057CFA8 /* SDL_list.c */; };
A1BB8B6527F6CF330057CFA8 /* SDL_list.c in Sources */ = {isa = PBXBuildFile; fileRef = A1BB8B6127F6CF320057CFA8 /* SDL_list.c */; };
@ -3490,6 +3538,12 @@
9846B07B287A9020000C35C8 /* SDL_hidapi_shield.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_shield.c; sourceTree = "<group>"; };
A1626A3D2617006A003F1973 /* SDL_triangle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_triangle.c; sourceTree = "<group>"; };
A1626A512617008C003F1973 /* SDL_triangle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_triangle.h; sourceTree = "<group>"; };
A16680C129967B6900318FE2 /* SDL_video_capture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_video_capture.h; path = SDL3/SDL_video_capture.h; sourceTree = "<group>"; };
A16680C529967BD000318FE2 /* SDL_video_capture.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_video_capture.c; sourceTree = "<group>"; };
A16680C629967BD000318FE2 /* SDL_sysvideocapture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sysvideocapture.h; sourceTree = "<group>"; };
A16680C729967BD100318FE2 /* SDL_video_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_video_c.h; sourceTree = "<group>"; };
A16680C829967BD100318FE2 /* SDL_video_capture_apple.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_video_capture_apple.m; sourceTree = "<group>"; };
A16680C929967BD100318FE2 /* SDL_video_capture_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_video_capture_c.h; sourceTree = "<group>"; };
A1BB8B6127F6CF320057CFA8 /* SDL_list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_list.c; sourceTree = "<group>"; };
A1BB8B6227F6CF330057CFA8 /* SDL_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_list.h; sourceTree = "<group>"; };
A7381E931D8B69C300B177DD /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
@ -4160,6 +4214,7 @@
F3F7D8AF2933074900816151 /* SDL_touch.h */,
F3F7D8E42933074D00816151 /* SDL_version.h */,
F3F7D8C52933074B00816151 /* SDL_video.h */,
A16680C129967B6900318FE2 /* SDL_video_capture.h */,
F3F7D8D42933074C00816151 /* SDL_vulkan.h */,
);
name = "Public Headers";
@ -4493,7 +4548,12 @@
A7D8A60323E2513D00DCD162 /* SDL_stretch.c */,
A7D8A61423E2513D00DCD162 /* SDL_surface.c */,
A7D8A61723E2513D00DCD162 /* SDL_sysvideo.h */,
A16680C629967BD000318FE2 /* SDL_sysvideocapture.h */,
A7D8A60E23E2513D00DCD162 /* SDL_video.c */,
A16680C729967BD100318FE2 /* SDL_video_c.h */,
A16680C829967BD100318FE2 /* SDL_video_capture_apple.m */,
A16680C929967BD100318FE2 /* SDL_video_capture_c.h */,
A16680C529967BD000318FE2 /* SDL_video_capture.c */,
A7D8A63E23E2513D00DCD162 /* SDL_vulkan_internal.h */,
A7D8A64023E2513D00DCD162 /* SDL_vulkan_utils.c */,
A7D8A76A23E2513E00DCD162 /* SDL_yuv_c.h */,
@ -5190,6 +5250,7 @@
A75FCDD623E25AB700529352 /* SDL_dynapi_procs.h in Headers */,
A75FCD1F23E25AB700529352 /* SDL_egl_c.h in Headers */,
A75FCD1923E25AB700529352 /* SDL_error_c.h in Headers */,
A16680DD29967BF000318FE2 /* SDL_sysvideocapture.h in Headers */,
A75FCD7923E25AB700529352 /* SDL_events_c.h in Headers */,
A75FCD8B23E25AB700529352 /* SDL_gamepad_db.h in Headers */,
A75FCDDB23E25AB700529352 /* SDL_gles2funcs.h in Headers */,
@ -5204,6 +5265,7 @@
A75FCDC823E25AB700529352 /* SDL_keyboard_c.h in Headers */,
A1BB8B7327F6CF330057CFA8 /* SDL_list.h in Headers */,
F386F6EE2884663E001840AA /* SDL_log_c.h in Headers */,
A16680ED29967C0C00318FE2 /* SDL_video_capture_c.h in Headers */,
F395C1C12569C6A000942BFF /* SDL_mfijoystick_c.h in Headers */,
A75FCDCC23E25AB700529352 /* SDL_mouse_c.h in Headers */,
A75FCD8523E25AB700529352 /* SDL_nullevents_c.h in Headers */,
@ -5221,6 +5283,7 @@
A75FCDBE23E25AB700529352 /* SDL_rwopsbundlesupport.h in Headers */,
A75FCD9623E25AB700529352 /* SDL_sensor_c.h in Headers */,
A75FCD4623E25AB700529352 /* SDL_shaders_gl.h in Headers */,
A16680F529967C1D00318FE2 /* SDL_video_c.h in Headers */,
A75FCD8023E25AB700529352 /* SDL_shaders_gles2.h in Headers */,
A75FCD0C23E25AB700529352 /* SDL_shaders_metal_ios.h in Headers */,
A75FCD0B23E25AB700529352 /* SDL_shaders_metal_macos.h in Headers */,
@ -5355,6 +5418,7 @@
A75FCF8F23E25AC700529352 /* SDL_dynapi_procs.h in Headers */,
A75FCED823E25AC700529352 /* SDL_egl_c.h in Headers */,
A75FCED223E25AC700529352 /* SDL_error_c.h in Headers */,
A16680DE29967BF000318FE2 /* SDL_sysvideocapture.h in Headers */,
A75FCF3223E25AC700529352 /* SDL_events_c.h in Headers */,
A75FCF4423E25AC700529352 /* SDL_gamepad_db.h in Headers */,
A75FCF9423E25AC700529352 /* SDL_gles2funcs.h in Headers */,
@ -5369,6 +5433,7 @@
A75FCF8123E25AC700529352 /* SDL_keyboard_c.h in Headers */,
A1BB8B7427F6CF330057CFA8 /* SDL_list.h in Headers */,
F386F6EF2884663E001840AA /* SDL_log_c.h in Headers */,
A16680F029967C0C00318FE2 /* SDL_video_capture_c.h in Headers */,
F395C1C22569C6A000942BFF /* SDL_mfijoystick_c.h in Headers */,
A75FCF8523E25AC700529352 /* SDL_mouse_c.h in Headers */,
A75FCF3E23E25AC700529352 /* SDL_nullevents_c.h in Headers */,
@ -5386,6 +5451,7 @@
A75FCF7723E25AC700529352 /* SDL_rwopsbundlesupport.h in Headers */,
A75FCF4F23E25AC700529352 /* SDL_sensor_c.h in Headers */,
A75FCEFF23E25AC700529352 /* SDL_shaders_gl.h in Headers */,
A16680F629967C1D00318FE2 /* SDL_video_c.h in Headers */,
A75FCF3923E25AC700529352 /* SDL_shaders_gles2.h in Headers */,
A75FCEC523E25AC700529352 /* SDL_shaders_metal_ios.h in Headers */,
A75FCEC423E25AC700529352 /* SDL_shaders_metal_macos.h in Headers */,
@ -5520,6 +5586,7 @@
A769B15D23E259AE00872273 /* SDL_dynapi_procs.h in Headers */,
A769B0A623E259AE00872273 /* SDL_egl_c.h in Headers */,
A769B0A023E259AE00872273 /* SDL_error_c.h in Headers */,
A16680DB29967BEF00318FE2 /* SDL_sysvideocapture.h in Headers */,
A769B10123E259AE00872273 /* SDL_events_c.h in Headers */,
A769B11123E259AE00872273 /* SDL_gamepad_db.h in Headers */,
A769B16323E259AE00872273 /* SDL_gles2funcs.h in Headers */,
@ -5534,6 +5601,7 @@
A769B14F23E259AE00872273 /* SDL_keyboard_c.h in Headers */,
A1BB8B7127F6CF330057CFA8 /* SDL_list.h in Headers */,
F386F6EC2884663E001840AA /* SDL_log_c.h in Headers */,
A16680E729967C0B00318FE2 /* SDL_video_capture_c.h in Headers */,
F395C1BF2569C6A000942BFF /* SDL_mfijoystick_c.h in Headers */,
A769B15323E259AE00872273 /* SDL_mouse_c.h in Headers */,
A769B10C23E259AE00872273 /* SDL_nullevents_c.h in Headers */,
@ -5551,6 +5619,7 @@
A769B14523E259AE00872273 /* SDL_rwopsbundlesupport.h in Headers */,
A769B11E23E259AE00872273 /* SDL_sensor_c.h in Headers */,
A769B0CC23E259AE00872273 /* SDL_shaders_gl.h in Headers */,
A16680F329967C1C00318FE2 /* SDL_video_c.h in Headers */,
A769B10723E259AE00872273 /* SDL_shaders_gles2.h in Headers */,
A769B09323E259AE00872273 /* SDL_shaders_metal_ios.h in Headers */,
A769B09223E259AE00872273 /* SDL_shaders_metal_macos.h in Headers */,
@ -5678,6 +5747,7 @@
A7D8AEE923E2514100DCD162 /* SDL_cocoavulkan.h in Headers */,
A7D8AEFB23E2514100DCD162 /* SDL_cocoawindow.h in Headers */,
F3F7D9D22933074E00816151 /* SDL_copying.h in Headers */,
A16680D129967BD100318FE2 /* SDL_video_c.h in Headers */,
A7D8B8CD23E2514400DCD162 /* SDL_coreaudio.h in Headers */,
A7D8A97023E2514000DCD162 /* SDL_coremotionsensor.h in Headers */,
F3F7D9BA2933074E00816151 /* SDL_cpuinfo.h in Headers */,
@ -5693,6 +5763,7 @@
A7D8A96423E2514000DCD162 /* SDL_dummysensor.h in Headers */,
A7D8AB0B23E2514100DCD162 /* SDL_dynapi.h in Headers */,
A7D8AB1123E2514100DCD162 /* SDL_dynapi_overrides.h in Headers */,
A16680C329967B6900318FE2 /* SDL_video_capture.h in Headers */,
A7D8AB1D23E2514100DCD162 /* SDL_dynapi_procs.h in Headers */,
F3F7D9262933074E00816151 /* SDL_egl.h in Headers */,
A7D8ABDA23E2514100DCD162 /* SDL_egl_c.h in Headers */,
@ -5765,6 +5836,7 @@
A7D8AC0423E2514100DCD162 /* SDL_rect_c.h in Headers */,
F3F7D9BE2933074E00816151 /* SDL_render.h in Headers */,
A7D8B9FC23E2514400DCD162 /* SDL_render_sw_c.h in Headers */,
A16680CE29967BD100318FE2 /* SDL_sysvideocapture.h in Headers */,
F3F7D9162933074E00816151 /* SDL_revision.h in Headers */,
A7D8BA3223E2514400DCD162 /* SDL_rotate.h in Headers */,
F3F7D9662933074E00816151 /* SDL_rwops.h in Headers */,
@ -5777,6 +5849,7 @@
A7D8B98D23E2514400DCD162 /* SDL_shaders_metal_ios.h in Headers */,
A7D8B99C23E2514400DCD162 /* SDL_shaders_metal_macos.h in Headers */,
A7D8B9A223E2514400DCD162 /* SDL_shaders_metal_tvos.h in Headers */,
A16680D729967BD100318FE2 /* SDL_video_capture_c.h in Headers */,
F3F7D92E2933074E00816151 /* SDL_shape.h in Headers */,
A7D8AC0A23E2514100DCD162 /* SDL_shape_internals.h in Headers */,
F3F7D8F62933074E00816151 /* SDL_stdinc.h in Headers */,
@ -5911,6 +5984,7 @@
A7D8AEEA23E2514100DCD162 /* SDL_cocoavulkan.h in Headers */,
A7D8AEFC23E2514100DCD162 /* SDL_cocoawindow.h in Headers */,
F3F7D9D32933074E00816151 /* SDL_copying.h in Headers */,
A16680D229967BD100318FE2 /* SDL_video_c.h in Headers */,
A7D8B8CE23E2514400DCD162 /* SDL_coreaudio.h in Headers */,
A7D8A97123E2514000DCD162 /* SDL_coremotionsensor.h in Headers */,
F3F7D9BB2933074E00816151 /* SDL_cpuinfo.h in Headers */,
@ -5926,6 +6000,7 @@
A7D8A96523E2514000DCD162 /* SDL_dummysensor.h in Headers */,
A7D8AB0C23E2514100DCD162 /* SDL_dynapi.h in Headers */,
A7D8AB1223E2514100DCD162 /* SDL_dynapi_overrides.h in Headers */,
A16680C429967B6900318FE2 /* SDL_video_capture.h in Headers */,
A7D8AB1E23E2514100DCD162 /* SDL_dynapi_procs.h in Headers */,
F3F7D9272933074E00816151 /* SDL_egl.h in Headers */,
A7D8ABDB23E2514100DCD162 /* SDL_egl_c.h in Headers */,
@ -5998,6 +6073,7 @@
A7D8AC0523E2514100DCD162 /* SDL_rect_c.h in Headers */,
F3F7D9BF2933074E00816151 /* SDL_render.h in Headers */,
A7D8B9FD23E2514400DCD162 /* SDL_render_sw_c.h in Headers */,
A16680CF29967BD100318FE2 /* SDL_sysvideocapture.h in Headers */,
F3F7D9172933074E00816151 /* SDL_revision.h in Headers */,
A7D8BA3323E2514400DCD162 /* SDL_rotate.h in Headers */,
F3F7D9672933074E00816151 /* SDL_rwops.h in Headers */,
@ -6010,6 +6086,7 @@
A7D8B98E23E2514400DCD162 /* SDL_shaders_metal_ios.h in Headers */,
A7D8B99D23E2514400DCD162 /* SDL_shaders_metal_macos.h in Headers */,
A7D8B9A323E2514400DCD162 /* SDL_shaders_metal_tvos.h in Headers */,
A16680D829967BD100318FE2 /* SDL_video_capture_c.h in Headers */,
F3F7D92F2933074E00816151 /* SDL_shape.h in Headers */,
A7D8AC0B23E2514100DCD162 /* SDL_shape_internals.h in Headers */,
F3F7D8F72933074E00816151 /* SDL_stdinc.h in Headers */,
@ -6151,6 +6228,7 @@
A7D8AB2023E2514100DCD162 /* SDL_dynapi_procs.h in Headers */,
A7D8ABDD23E2514100DCD162 /* SDL_egl_c.h in Headers */,
A7D8A96123E2514000DCD162 /* SDL_error_c.h in Headers */,
A16680DA29967BEE00318FE2 /* SDL_sysvideocapture.h in Headers */,
A7D8BBA923E2514500DCD162 /* SDL_events_c.h in Headers */,
A7D8B4B023E2514300DCD162 /* SDL_gamepad_db.h in Headers */,
A7D8BA5923E2514400DCD162 /* SDL_gles2funcs.h in Headers */,
@ -6165,6 +6243,7 @@
A7D8BB8B23E2514500DCD162 /* SDL_keyboard_c.h in Headers */,
A1BB8B7027F6CF330057CFA8 /* SDL_list.h in Headers */,
F386F6EB2884663E001840AA /* SDL_log_c.h in Headers */,
A16680E429967C0A00318FE2 /* SDL_video_capture_c.h in Headers */,
F395C1BE2569C6A000942BFF /* SDL_mfijoystick_c.h in Headers */,
A7D8BB1F23E2514500DCD162 /* SDL_mouse_c.h in Headers */,
A7D8AC0123E2514100DCD162 /* SDL_nullevents_c.h in Headers */,
@ -6182,6 +6261,7 @@
A7D8B5C723E2514300DCD162 /* SDL_rwopsbundlesupport.h in Headers */,
A7D8A99123E2514000DCD162 /* SDL_sensor_c.h in Headers */,
A7D8BA7723E2514400DCD162 /* SDL_shaders_gl.h in Headers */,
A16680F229967C1C00318FE2 /* SDL_video_c.h in Headers */,
A7D8BA5323E2514400DCD162 /* SDL_shaders_gles2.h in Headers */,
A7D8B99023E2514400DCD162 /* SDL_shaders_metal_ios.h in Headers */,
A7D8B99F23E2514400DCD162 /* SDL_shaders_metal_macos.h in Headers */,
@ -6309,6 +6389,7 @@
A7D8AEE823E2514100DCD162 /* SDL_cocoavulkan.h in Headers */,
A7D8AEFA23E2514100DCD162 /* SDL_cocoawindow.h in Headers */,
F3F7D9D12933074E00816151 /* SDL_copying.h in Headers */,
A16680D029967BD100318FE2 /* SDL_video_c.h in Headers */,
A7D8B8CC23E2514400DCD162 /* SDL_coreaudio.h in Headers */,
A7D8A96F23E2514000DCD162 /* SDL_coremotionsensor.h in Headers */,
F3F7D9B92933074E00816151 /* SDL_cpuinfo.h in Headers */,
@ -6324,6 +6405,7 @@
A7D8A96323E2514000DCD162 /* SDL_dummysensor.h in Headers */,
A7D8AB0A23E2514100DCD162 /* SDL_dynapi.h in Headers */,
A7D8AB1023E2514100DCD162 /* SDL_dynapi_overrides.h in Headers */,
A16680C229967B6900318FE2 /* SDL_video_capture.h in Headers */,
A7D8AB1C23E2514100DCD162 /* SDL_dynapi_procs.h in Headers */,
F3F7D9252933074E00816151 /* SDL_egl.h in Headers */,
A7D8ABD923E2514100DCD162 /* SDL_egl_c.h in Headers */,
@ -6396,6 +6478,7 @@
A7D8AC0323E2514100DCD162 /* SDL_rect_c.h in Headers */,
F3F7D9BD2933074E00816151 /* SDL_render.h in Headers */,
A7D8B9FB23E2514400DCD162 /* SDL_render_sw_c.h in Headers */,
A16680CD29967BD100318FE2 /* SDL_sysvideocapture.h in Headers */,
F3F7D9152933074E00816151 /* SDL_revision.h in Headers */,
A7D8BA3123E2514400DCD162 /* SDL_rotate.h in Headers */,
F3F7D9652933074E00816151 /* SDL_rwops.h in Headers */,
@ -6408,6 +6491,7 @@
A7D8B98C23E2514400DCD162 /* SDL_shaders_metal_ios.h in Headers */,
A7D8B99B23E2514400DCD162 /* SDL_shaders_metal_macos.h in Headers */,
A7D8B9A123E2514400DCD162 /* SDL_shaders_metal_tvos.h in Headers */,
A16680D629967BD100318FE2 /* SDL_video_capture_c.h in Headers */,
F3F7D92D2933074E00816151 /* SDL_shape.h in Headers */,
A7D8AC0923E2514100DCD162 /* SDL_shape_internals.h in Headers */,
F3F7D8F52933074E00816151 /* SDL_stdinc.h in Headers */,
@ -6549,6 +6633,7 @@
A7D8AB1F23E2514100DCD162 /* SDL_dynapi_procs.h in Headers */,
A7D8ABDC23E2514100DCD162 /* SDL_egl_c.h in Headers */,
A7D8A96023E2514000DCD162 /* SDL_error_c.h in Headers */,
A16680D929967BEE00318FE2 /* SDL_sysvideocapture.h in Headers */,
A7D8BBA823E2514500DCD162 /* SDL_events_c.h in Headers */,
A7D8B4AF23E2514300DCD162 /* SDL_gamepad_db.h in Headers */,
A7D8BA5823E2514400DCD162 /* SDL_gles2funcs.h in Headers */,
@ -6563,6 +6648,7 @@
A7D8BB8A23E2514500DCD162 /* SDL_keyboard_c.h in Headers */,
A1BB8B6F27F6CF330057CFA8 /* SDL_list.h in Headers */,
F386F6EA2884663E001840AA /* SDL_log_c.h in Headers */,
A16680E129967C0A00318FE2 /* SDL_video_capture_c.h in Headers */,
F395C1BD2569C6A000942BFF /* SDL_mfijoystick_c.h in Headers */,
A7D8BB1E23E2514500DCD162 /* SDL_mouse_c.h in Headers */,
A7D8AC0023E2514100DCD162 /* SDL_nullevents_c.h in Headers */,
@ -6580,6 +6666,7 @@
A7D8B5C623E2514300DCD162 /* SDL_rwopsbundlesupport.h in Headers */,
A7D8A99023E2514000DCD162 /* SDL_sensor_c.h in Headers */,
A7D8BA7623E2514400DCD162 /* SDL_shaders_gl.h in Headers */,
A16680F129967C1B00318FE2 /* SDL_video_c.h in Headers */,
A7D8BA5223E2514400DCD162 /* SDL_shaders_gles2.h in Headers */,
A7D8B98F23E2514400DCD162 /* SDL_shaders_metal_ios.h in Headers */,
A7D8B99E23E2514400DCD162 /* SDL_shaders_metal_macos.h in Headers */,
@ -6714,6 +6801,7 @@
A7D8AB2123E2514100DCD162 /* SDL_dynapi_procs.h in Headers */,
A7D8ABDE23E2514100DCD162 /* SDL_egl_c.h in Headers */,
A7D8A96223E2514000DCD162 /* SDL_error_c.h in Headers */,
A16680DC29967BEF00318FE2 /* SDL_sysvideocapture.h in Headers */,
A7D8BBAA23E2514500DCD162 /* SDL_events_c.h in Headers */,
A7D8B4B123E2514300DCD162 /* SDL_gamepad_db.h in Headers */,
A7D8BA5A23E2514400DCD162 /* SDL_gles2funcs.h in Headers */,
@ -6728,6 +6816,7 @@
A7D8BB8C23E2514500DCD162 /* SDL_keyboard_c.h in Headers */,
A1BB8B7227F6CF330057CFA8 /* SDL_list.h in Headers */,
F386F6ED2884663E001840AA /* SDL_log_c.h in Headers */,
A16680EA29967C0B00318FE2 /* SDL_video_capture_c.h in Headers */,
F395C1C02569C6A000942BFF /* SDL_mfijoystick_c.h in Headers */,
A7D8BB2023E2514500DCD162 /* SDL_mouse_c.h in Headers */,
A7D8AC0223E2514100DCD162 /* SDL_nullevents_c.h in Headers */,
@ -6745,6 +6834,7 @@
A7D8B5C823E2514300DCD162 /* SDL_rwopsbundlesupport.h in Headers */,
A7D8A99223E2514000DCD162 /* SDL_sensor_c.h in Headers */,
A7D8BA7823E2514400DCD162 /* SDL_shaders_gl.h in Headers */,
A16680F429967C1C00318FE2 /* SDL_video_c.h in Headers */,
A7D8BA5423E2514400DCD162 /* SDL_shaders_gles2.h in Headers */,
A7D8B99123E2514400DCD162 /* SDL_shaders_metal_ios.h in Headers */,
A7D8B9A023E2514400DCD162 /* SDL_shaders_metal_macos.h in Headers */,
@ -7301,6 +7391,7 @@
A75FCE4B23E25AB700529352 /* SDL_render.c in Sources */,
A75FCE4C23E25AB700529352 /* SDL_stretch.c in Sources */,
A75FCE4D23E25AB700529352 /* s_floor.c in Sources */,
A16680EC29967C0C00318FE2 /* SDL_video_capture_apple.m in Sources */,
A75FCE4E23E25AB700529352 /* SDL_blit_copy.c in Sources */,
A75FCE4F23E25AB700529352 /* e_fmod.c in Sources */,
A75FCE5023E25AB700529352 /* SDL_syspower.m in Sources */,
@ -7335,6 +7426,7 @@
A75FCE6F23E25AB700529352 /* SDL_surface.c in Sources */,
A75FCE7023E25AB700529352 /* SDL_hidapi_xboxone.c in Sources */,
A75FCE7123E25AB700529352 /* SDL_blit_auto.c in Sources */,
A16680EB29967C0C00318FE2 /* SDL_video_capture.c in Sources */,
A75FCE7323E25AB700529352 /* SDL_keyboard.c in Sources */,
A75FCE7523E25AB700529352 /* SDL_rect.c in Sources */,
A75FCE7623E25AB700529352 /* SDL_cocoaopengles.m in Sources */,
@ -7496,6 +7588,7 @@
A75FD00423E25AC700529352 /* SDL_render.c in Sources */,
A75FD00523E25AC700529352 /* SDL_stretch.c in Sources */,
A75FD00623E25AC700529352 /* s_floor.c in Sources */,
A16680EF29967C0C00318FE2 /* SDL_video_capture_apple.m in Sources */,
A75FD00723E25AC700529352 /* SDL_blit_copy.c in Sources */,
A75FD00823E25AC700529352 /* e_fmod.c in Sources */,
A75FD00923E25AC700529352 /* SDL_syspower.m in Sources */,
@ -7530,6 +7623,7 @@
A75FD02823E25AC700529352 /* SDL_surface.c in Sources */,
A75FD02923E25AC700529352 /* SDL_hidapi_xboxone.c in Sources */,
A75FD02A23E25AC700529352 /* SDL_blit_auto.c in Sources */,
A16680EE29967C0C00318FE2 /* SDL_video_capture.c in Sources */,
A75FD02C23E25AC700529352 /* SDL_keyboard.c in Sources */,
A75FD02E23E25AC700529352 /* SDL_rect.c in Sources */,
A75FD02F23E25AC700529352 /* SDL_cocoaopengles.m in Sources */,
@ -7691,6 +7785,7 @@
A769B1DF23E259AE00872273 /* SDL_blit_0.c in Sources */,
F36C7AD7294BA009004D61C3 /* SDL_runapp.c in Sources */,
A769B1E023E259AE00872273 /* k_tan.c in Sources */,
A16680E629967C0B00318FE2 /* SDL_video_capture_apple.m in Sources */,
A769B1E223E259AE00872273 /* SDL_diskaudio.c in Sources */,
A769B1E423E259AE00872273 /* SDL_egl.c in Sources */,
A769B1E523E259AE00872273 /* SDL_RLEaccel.c in Sources */,
@ -7725,6 +7820,7 @@
A769B20323E259AE00872273 /* SDL_qsort.c in Sources */,
A769B20423E259AE00872273 /* SDL_hidapi_switch.c in Sources */,
F3984CD525BCC92900374F43 /* SDL_hidapi_stadia.c in Sources */,
A16680E529967C0B00318FE2 /* SDL_video_capture.c in Sources */,
A769B20523E259AE00872273 /* SDL_strtokr.c in Sources */,
5605720B2473687A00B46B66 /* SDL_syslocale.m in Sources */,
F3820718284F3609004DD584 /* controller_type.c in Sources */,
@ -7886,6 +7982,7 @@
A7D8BAFE23E2514500DCD162 /* s_floor.c in Sources */,
A7D8AC3A23E2514100DCD162 /* SDL_blit_copy.c in Sources */,
A7D8BAE023E2514500DCD162 /* e_fmod.c in Sources */,
A16680D429967BD100318FE2 /* SDL_video_capture_apple.m in Sources */,
A7D8B5D023E2514300DCD162 /* SDL_syspower.m in Sources */,
A7D8BAEC23E2514500DCD162 /* e_log10.c in Sources */,
A7D8AC7023E2514100DCD162 /* SDL_uikitopenglview.m in Sources */,
@ -7920,6 +8017,7 @@
A7D8AD2423E2514100DCD162 /* SDL_blit_auto.c in Sources */,
A7D8BB6A23E2514500DCD162 /* SDL_keyboard.c in Sources */,
A7D8ACE823E2514100DCD162 /* SDL_rect.c in Sources */,
A16680CB29967BD100318FE2 /* SDL_video_capture.c in Sources */,
A7D8AE9B23E2514100DCD162 /* SDL_cocoaopengles.m in Sources */,
A7D8B96923E2514400DCD162 /* SDL_qsort.c in Sources */,
A7D8B55223E2514300DCD162 /* SDL_hidapi_switch.c in Sources */,
@ -8081,6 +8179,7 @@
A7D8BAFF23E2514500DCD162 /* s_floor.c in Sources */,
A7D8AC3B23E2514100DCD162 /* SDL_blit_copy.c in Sources */,
A7D8BAE123E2514500DCD162 /* e_fmod.c in Sources */,
A16680D529967BD100318FE2 /* SDL_video_capture_apple.m in Sources */,
A7D8B5D123E2514300DCD162 /* SDL_syspower.m in Sources */,
A7D8BAED23E2514500DCD162 /* e_log10.c in Sources */,
A7D8AC7123E2514100DCD162 /* SDL_uikitopenglview.m in Sources */,
@ -8115,6 +8214,7 @@
A7D8AD2523E2514100DCD162 /* SDL_blit_auto.c in Sources */,
A7D8BB6B23E2514500DCD162 /* SDL_keyboard.c in Sources */,
A7D8ACE923E2514100DCD162 /* SDL_rect.c in Sources */,
A16680CC29967BD100318FE2 /* SDL_video_capture.c in Sources */,
A7D8AE9C23E2514100DCD162 /* SDL_cocoaopengles.m in Sources */,
A7D8B96A23E2514400DCD162 /* SDL_qsort.c in Sources */,
A7D8B55323E2514300DCD162 /* SDL_hidapi_switch.c in Sources */,
@ -8276,6 +8376,7 @@
A7D8ADEA23E2514100DCD162 /* SDL_blit_0.c in Sources */,
F36C7AD6294BA009004D61C3 /* SDL_runapp.c in Sources */,
A7D8BB0D23E2514500DCD162 /* k_tan.c in Sources */,
A16680E329967C0A00318FE2 /* SDL_video_capture_apple.m in Sources */,
A7D8B8AC23E2514400DCD162 /* SDL_diskaudio.c in Sources */,
A7D8AFC423E2514200DCD162 /* SDL_egl.c in Sources */,
A7D8AC3723E2514100DCD162 /* SDL_RLEaccel.c in Sources */,
@ -8310,6 +8411,7 @@
A7D8B96C23E2514400DCD162 /* SDL_qsort.c in Sources */,
A7D8B55523E2514300DCD162 /* SDL_hidapi_switch.c in Sources */,
F3984CD425BCC92900374F43 /* SDL_hidapi_stadia.c in Sources */,
A16680E229967C0A00318FE2 /* SDL_video_capture.c in Sources */,
A7D8B96623E2514400DCD162 /* SDL_strtokr.c in Sources */,
560572092473687900B46B66 /* SDL_syslocale.m in Sources */,
F3820717284F3609004DD584 /* controller_type.c in Sources */,
@ -8418,6 +8520,7 @@
75E0915A241EA924004729E1 /* SDL_virtualjoystick.c in Sources */,
A7D8ABEB23E2514100DCD162 /* SDL_nullvideo.c in Sources */,
A7D8AB6723E2514100DCD162 /* SDL_offscreenevents.c in Sources */,
A16680CA29967BD100318FE2 /* SDL_video_capture.c in Sources */,
A7D8ABF123E2514100DCD162 /* SDL_nullevents.c in Sources */,
A7D8B81823E2514400DCD162 /* SDL_audiodev.c in Sources */,
A7D8AF0C23E2514100DCD162 /* SDL_cocoaclipboard.m in Sources */,
@ -8440,6 +8543,7 @@
A7D8AED623E2514100DCD162 /* SDL_cocoakeyboard.m in Sources */,
A7D8AB1623E2514100DCD162 /* SDL_dynapi.c in Sources */,
A7D8BA8523E2514400DCD162 /* SDL_shaders_gl.c in Sources */,
A16680D329967BD100318FE2 /* SDL_video_capture_apple.m in Sources */,
A7D8BAF123E2514500DCD162 /* e_log.c in Sources */,
A7D8AED023E2514100DCD162 /* SDL_cocoamessagebox.m in Sources */,
F376F6552559B4E300CFC0BC /* SDL_hidapi.c in Sources */,
@ -8612,6 +8716,7 @@
A7D8BA3A23E2514400DCD162 /* SDL_d3dmath.c in Sources */,
A7D8ABEE23E2514100DCD162 /* SDL_nullvideo.c in Sources */,
A7D8AB6A23E2514100DCD162 /* SDL_offscreenevents.c in Sources */,
A16680DF29967C0A00318FE2 /* SDL_video_capture.c in Sources */,
A7D8ABF423E2514100DCD162 /* SDL_nullevents.c in Sources */,
A7D8B81B23E2514400DCD162 /* SDL_audiodev.c in Sources */,
A7D8AF0F23E2514100DCD162 /* SDL_cocoaclipboard.m in Sources */,
@ -8634,6 +8739,7 @@
A7D8BAF423E2514500DCD162 /* e_log.c in Sources */,
A7D8AED323E2514100DCD162 /* SDL_cocoamessagebox.m in Sources */,
A7D8BA2E23E2514400DCD162 /* SDL_blendfillrect.c in Sources */,
A16680E029967C0A00318FE2 /* SDL_video_capture_apple.m in Sources */,
A7D8AEE523E2514100DCD162 /* SDL_cocoashape.m in Sources */,
A7D8AEBB23E2514100DCD162 /* SDL_cocoamouse.m in Sources */,
F376F6762559B4E500CFC0BC /* SDL_hidapi.c in Sources */,
@ -8806,6 +8912,7 @@
A7D8AB6C23E2514100DCD162 /* SDL_offscreenevents.c in Sources */,
A7D8ACAA23E2514100DCD162 /* SDL_uikitview.m in Sources */,
A7D8ABF623E2514100DCD162 /* SDL_nullevents.c in Sources */,
A16680E829967C0B00318FE2 /* SDL_video_capture.c in Sources */,
A7D8B81D23E2514400DCD162 /* SDL_audiodev.c in Sources */,
A7D8AF1123E2514100DCD162 /* SDL_cocoaclipboard.m in Sources */,
A7D8ABD223E2514100DCD162 /* SDL_blit_slow.c in Sources */,
@ -8828,6 +8935,7 @@
A7D8BA8A23E2514400DCD162 /* SDL_shaders_gl.c in Sources */,
A7D8BAF623E2514500DCD162 /* e_log.c in Sources */,
A7D8AED523E2514100DCD162 /* SDL_cocoamessagebox.m in Sources */,
A16680E929967C0B00318FE2 /* SDL_video_capture_apple.m in Sources */,
A7D8BA3023E2514400DCD162 /* SDL_blendfillrect.c in Sources */,
A7D8ACE023E2514100DCD162 /* SDL_uikitvideo.m in Sources */,
F376F68D2559B4E900CFC0BC /* SDL_hidapi.c in Sources */,

View file

@ -75,6 +75,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_ */

View file

@ -0,0 +1,302 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2022 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
/**
* SDL VideoCapture Device IDs.
*/
typedef Sint32 SDL_VideoCaptureDeviceID;
#define SDL_VIDEO_CAPTURE_INVALID -1
#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; /**< Video data format */
Uint32 width; /**< Width */
Uint32 height; /**< Height */
} SDL_VideoCaptureSpec;
/**
* SDL Video Capture Status
*/
typedef enum
{
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
{
int num_planes; /**< Number of planes */
Uint8 *data[3]; /**< Pointer to data of i-th plane */
int row_stride[3]; /**< Row stride of i-th plane */
int fd; /**< DMABUF file descriptor if available (-1 if not) */
void *clientbuffer; /**< Android clientbuffer if available (NULL if not) */
void *internal; /**< Private field */
} SDL_VideoCaptureFrame;
/**
* Open a Video Capture device
*
* \param device_name device name to open. Can be NULL.
*
* \returns device id, or SDL_VIDEO_CAPTURE_INVALID on error
*
* \sa SDL_GetVideoCaptureDeviceName
* \sa SDL_GetNumVideoCaptureDevices
*/
extern DECLSPEC SDL_VideoCaptureDeviceID SDLCALL SDL_OpenVideoCapture(const char *device_name);
/**
* Set specification
*
* \param id video capture opened device id
* \param desired desired video capture spec
* \param obtained obtained video capture spec
* \param allowed_changes allow changes or not
*
* \returns 0 on success, negative value on error
*/
extern DECLSPEC int SDLCALL SDL_SetVideoCaptureSpec(SDL_VideoCaptureDeviceID id,
const SDL_VideoCaptureSpec *desired,
SDL_VideoCaptureSpec *obtained,
int allowed_changes);
/**
* Open a Video Capture device and set specification
*
* \param device_name device name to open. Can be NULL.
* \param desired desired video capture spec
* \param obtained obtained video capture spec
* \param allowed_changes allow changes or not
*
* \returns device id, or SDL_VIDEO_CAPTURE_INVALID on error
*/
extern DECLSPEC SDL_VideoCaptureDeviceID SDLCALL SDL_OpenVideoCaptureWithSpec(
const char *device_name,
const SDL_VideoCaptureSpec *desired,
SDL_VideoCaptureSpec *obtained,
int allowed_changes);
/**
* Get device name
*
* \param index device index between 0 and num -1
*
* \returns device name, shouldn't be freed
*
* \sa SDL_GetNumVideoCaptureDevices
*/
extern DECLSPEC const char * SDLCALL SDL_GetVideoCaptureDeviceName(int index);
/**
* Use this function to get the number of video capture devices.
*
* \returns the number of video capture devices
*/
extern DECLSPEC int SDLCALL SDL_GetNumVideoCaptureDevices(void);
/**
* Get the obtained video capture spec
*
* \param id video capture opened device id
* \param spec The SDL_VideoCaptureSpec to be initialized by this function.
*
* \returns 0 on success, negative value on error
*/
extern DECLSPEC int SDLCALL SDL_GetVideoCaptureSpec(SDL_VideoCaptureDeviceID id, SDL_VideoCaptureSpec *spec);
#define SDL_VIDEO_CAPTURE_TYPE_COMPRESSED 1
#define SDL_VIDEO_CAPTURE_TYPE_EMULATED 2
/**
* Get frame format of video capture device.
* The value can be used to fill SDL_VideoCaptureSpec structure.
*
* \param id video capture opened device id
* \param index format between 0 and num -1
* \param format pointer output format (SDL_PixelFormatEnum)
* \param type pointer output type
*
* \returns 0 on success, negative value on error
*
* \sa SDL_GetNumVideoCaptureFormats
*/
extern DECLSPEC int SDLCALL SDL_GetVideoCaptureFormat(SDL_VideoCaptureDeviceID id, int index, Uint32 *format, Uint32 *type);
/**
* Number of available formats for the device
*
* \param id video capture opened device id
*
* \returns number of formats, negative value on error
*
* \sa SDL_GetVideoCaptureFormat
*/
extern DECLSPEC int SDLCALL SDL_GetNumVideoCaptureFormats(SDL_VideoCaptureDeviceID id);
/**
* Get frame sizes of the device and the specified input format.
* The value can be used to fill SDL_VideoCaptureSpec structure.
*
* \param id video capture opened device id
* \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, negative value on error
*
* \sa SDL_GetNumVideoCaptureFrameSizes
*/
extern DECLSPEC int SDLCALL SDL_GetVideoCaptureFrameSize(SDL_VideoCaptureDeviceID id, Uint32 format, int index, Uint32 *width, Uint32 *height);
/**
* Number of different framesizes available for the device and pixel format.
*
* \param id video capture opened device id
* \param format frame pixel format (SDL_PixelFormatEnum)
*
* \returns number of framesize, negative value on error
*
* \sa SDL_GetVideoCaptureFrameSize
*/
extern DECLSPEC int SDLCALL SDL_GetNumVideoCaptureFrameSizes(SDL_VideoCaptureDeviceID id, Uint32 format);
/**
* Get video capture status
*
* \param id video capture opened device id
*
* \returns 0 on success, negative value on error
*
* \sa SDL_VideoCaptureStatus
*/
extern DECLSPEC SDL_VideoCaptureStatus SDLCALL SDL_GetVideoCaptureStatus(SDL_VideoCaptureDeviceID id);
/**
* Start video capture
*
* \param id video capture opened device id
*
* \returns 0 on success, negative value on error
*
* \sa SDL_StopVideoCapture
*/
extern DECLSPEC int SDLCALL SDL_StartVideoCapture(SDL_VideoCaptureDeviceID id);
/**
* 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_VideoCaptureReleaseFrame
*
* \param id video capture opened device id
* \param frame pointer to get the frame
* \param ticks pointer to get the ticks when this was read from driver
*
* \returns 0 on success, negative value on error
*
* \sa SDL_VideoCaptureReleaseFrame
*/
extern DECLSPEC int SDLCALL SDL_VideoCaptureAcquireFrame(SDL_VideoCaptureDeviceID id, SDL_VideoCaptureFrame *frame, Uint64 *ticks);
/**
* Release a frame. Let the back-end re-use the internal buffer for video capture.
*
* \param id video capture opened device id
* \param frame frame pointer.
*
* \returns 0 on success, negative value on error
*
* \sa SDL_VideoCaptureAcquireFrame
*/
extern DECLSPEC int SDLCALL SDL_VideoCaptureReleaseFrame(SDL_VideoCaptureDeviceID id, SDL_VideoCaptureFrame *frame);
/**
* Stop Video Capture
*
* \param id video capture opened device id
*
* \returns 0 on success, negative value on error
*
* \sa SDL_StartVideoCapture
*/
extern DECLSPEC int SDLCALL SDL_StopVideoCapture(SDL_VideoCaptureDeviceID id);
/**
* Use this function to shut down video_capture processing and close the video_capture device.
*
* The device ID is invalid as soon as the device is closed, and is eligible
* for reuse in a new SDL_OpenVideoCaptureWithSpec() call immediately.
*
* \param id video capture opened device id
*
* \sa SDL_OpenVideoCaptureWithSpec
* \sa SDL_OpenVideoCapture
*/
extern DECLSPEC void SDLCALL SDL_CloseVideoCapture(SDL_VideoCaptureDeviceID id);
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}
#endif
#include <SDL3/SDL_close_code.h>
#endif /* SDL_video_capture_h_ */

View file

@ -199,6 +199,8 @@
#define SDL_VIDEO_METAL 1
#endif
#define HAVE_COREMEDIA 1
/* Enable system power support */
#define SDL_POWER_UIKIT 1

View file

@ -260,6 +260,8 @@
#endif
#endif
#define HAVE_COREMEDIA 1
/* Enable system power support */
#define SDL_POWER_MACOSX 1

View file

@ -0,0 +1,91 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2022 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"
#define _THIS SDL_VideoCaptureDevice *_this
/* 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 */
SDL_VideoCaptureDeviceID id;
/* The device's current video_capture specification */
SDL_VideoCaptureSpec spec;
/* Device name */
char *dev_name;
/* Current state flags */
SDL_atomic_t shutdown;
SDL_atomic_t 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(_THIS);
extern void CloseDevice(_THIS);
extern int InitDevice(_THIS);
extern int GetDeviceSpec(_THIS, SDL_VideoCaptureSpec *spec);
extern int StartCapture(_THIS);
extern int StopCapture(_THIS);
extern int AcquireFrame(_THIS, SDL_VideoCaptureFrame *frame, Uint64 *ticks);
extern int ReleaseFrame(_THIS, SDL_VideoCaptureFrame *frame);
extern int GetNumFormats(_THIS);
extern int GetFormat(_THIS, int index, Uint32 *format, Uint32 *type);
extern int GetNumFrameSizes(_THIS, Uint32 format);
extern int GetFrameSize(_THIS, Uint32 format, int index, Uint32 *width, Uint32 *height);
extern int GetDeviceName(int index, char *buf, int size);
extern int GetNumDevices(void);
#endif /* SDL_sysvideocapture_h_ */

View file

@ -30,6 +30,7 @@
#include "SDL_video_c.h"
#include "../events/SDL_events_c.h"
#include "../timer/SDL_timer_c.h"
#include "SDL_video_capture_c.h"
#include <SDL3/SDL_syswm.h>
@ -420,6 +421,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' */
@ -448,6 +450,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;
@ -541,6 +547,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();
}
@ -3260,6 +3269,7 @@ void SDL_VideoQuit(void)
}
/* Halt event processing before doing anything else */
SDL_QuitVideoCapture();
SDL_QuitTouch();
SDL_QuitMouse();
SDL_QuitKeyboard();

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,578 @@
/*
Simple DirectMedia Layer
Copyright (C) 2021 Valve Corporation
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 "SDL3/SDL.h"
#include "SDL3/SDL_video_capture.h"
#include "SDL_sysvideocapture.h"
#include "SDL_video_capture_c.h"
#include "../thread/SDL_systhread.h"
#if defined(__MACOS__) && (__MAC_OS_X_VERSION_MAX_ALLOWED < 101500)
/* AVCaptureDeviceTypeBuiltInWideAngleCamera requires macOS SDK 10.15 */
#undef HAVE_COREMEDIA
#endif
#if TARGET_OS_TV
#undef HAVE_COREMEDIA
#endif
#ifndef HAVE_COREMEDIA
int InitDevice(_THIS) {
return -1;
}
int OpenDevice(_THIS) {
return -1;
}
int AcquireFrame(_THIS, SDL_VideoCaptureFrame *frame, Uint64 *ticks) {
return -1;
}
void CloseDevice(_THIS) {
}
int GetDeviceName(int index, char *buf, int size) {
return -1;
}
int GetDeviceSpec(_THIS, SDL_VideoCaptureSpec *spec) {
return -1;
}
int GetFormat(_THIS, int index, Uint32 *format, Uint32 *type) {
return -1;
}
int GetFrameSize(_THIS, Uint32 format, int index, Uint32 *width, Uint32 *height) {
return -1;
}
int GetNumDevices(void) {
return 0;
}
int GetNumFormats(_THIS) {
return 0;
}
int GetNumFrameSizes(_THIS, Uint32 format) {
return 0;
}
int ReleaseFrame(_THIS, SDL_VideoCaptureFrame *frame) {
return 0;
}
int StartCapture(_THIS) {
return 0;
}
int StopCapture(_THIS) {
return 0;
}
#else
#import <AVFoundation/AVFoundation.h>
#import <CoreMedia/CoreMedia.h>
/*
* Need to link with:: CoreMedia CoreVideo
*
* Add in pInfo.list:
* <key>NSCameraUsageDescription</key> <string>Access camera</string>
*
*
* MACOSX:
* Add to the Code Sign Entitlement file:
* <key>com.apple.security.device.camera</key> <true/>
*
*/
@class MySampleBufferDelegate;
struct SDL_PrivateVideoCaptureData
{
dispatch_queue_t queue;
MySampleBufferDelegate *delegate;
AVCaptureSession *session;
CMSimpleQueueRef frame_queue;
};
static NSString *
fourcc_to_nstring(Uint32 code)
{
Uint8 buf[4];
*(Uint32 *)buf = code;
return [NSString stringWithFormat:@"%c%c%c%c", buf[3], buf[2], buf[1], buf[0]];
}
static NSArray<AVCaptureDevice *> *
discover_devices()
{
NSArray *deviceType = @[AVCaptureDeviceTypeBuiltInWideAngleCamera];
AVCaptureDeviceDiscoverySession *discoverySession = [AVCaptureDeviceDiscoverySession
discoverySessionWithDeviceTypes:deviceType
mediaType:AVMediaTypeVideo
position:AVCaptureDevicePositionUnspecified];
NSArray<AVCaptureDevice *> *devices = discoverySession.devices;
if ([devices count] > 0) {
return devices;
} else {
AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if (captureDevice == nil) {
return devices;
} else {
NSArray<AVCaptureDevice *> *default_device = @[ captureDevice ];
return default_device;
}
}
return devices;
}
static AVCaptureDevice *
get_device_by_name(const char *dev_name)
{
NSArray<AVCaptureDevice *> *devices = discover_devices();
for (AVCaptureDevice *device in devices) {
char buf[1024];
NSString *cameraID = [device localizedName];
const char *str = [cameraID UTF8String];
SDL_snprintf(buf, sizeof (buf) - 1, "%s", str);
if (SDL_strcmp(buf, dev_name) == 0) {
return device;
}
}
return nil;
}
static Uint32
nsfourcc_to_sdlformat(NSString *nsfourcc)
{
const char *str = [nsfourcc UTF8String];
if (SDL_strcmp("420v", str) == 0) return SDL_PIXELFORMAT_NV12;
if (SDL_strcmp("yuvs", str) == 0) return SDL_PIXELFORMAT_UYVY;
if (SDL_strcmp("420f", str) == 0) return SDL_PIXELFORMAT_UNKNOWN;
SDL_Log("Unknown format '%s'", str);
return SDL_PIXELFORMAT_UNKNOWN;
}
static NSString *
sdlformat_to_nsfourcc(Uint32 fmt)
{
const char *str = "";
if (fmt == SDL_PIXELFORMAT_NV12) str = "420v";
if (fmt == SDL_PIXELFORMAT_UYVY) str = "yuvs";
NSString *result = [[NSString alloc] initWithUTF8String: str];
return result;
}
@interface MySampleBufferDelegate : NSObject<AVCaptureVideoDataOutputSampleBufferDelegate>
@property struct SDL_PrivateVideoCaptureData *hidden;
- (void) set: (struct SDL_PrivateVideoCaptureData *) val;
@end
@implementation MySampleBufferDelegate
- (void) set: (struct SDL_PrivateVideoCaptureData *) val {
_hidden = val;
}
- (void) captureOutput:(AVCaptureOutput *)output
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
fromConnection:(AVCaptureConnection *) connection {
CFRetain(sampleBuffer);
CMSimpleQueueEnqueue(_hidden->frame_queue, sampleBuffer);
}
- (void)captureOutput:(AVCaptureOutput *)output
didDropSampleBuffer:(CMSampleBufferRef)sampleBuffer
fromConnection:(AVCaptureConnection *)connection {
SDL_Log("Drop frame..");
}
@end
int
OpenDevice(_THIS)
{
_this->hidden = (struct SDL_PrivateVideoCaptureData *) SDL_calloc(1, sizeof (struct SDL_PrivateVideoCaptureData));
if (_this->hidden == NULL) {
SDL_OutOfMemory();
goto error;
}
return 0;
error:
return -1;
}
void
CloseDevice(_THIS)
{
if (!_this) {
return;
}
if (_this->hidden) {
AVCaptureSession *session = _this->hidden->session;
if (session) {
AVCaptureInput *input = [session.inputs objectAtIndex:0];
[session removeInput:input];
AVCaptureVideoDataOutput *output = (AVCaptureVideoDataOutput*)[session.outputs objectAtIndex:0];
[session removeOutput:output];
// TODO clenaupp
}
if (_this->hidden->frame_queue) {
CFRelease(_this->hidden->frame_queue);
}
SDL_free(_this->hidden);
_this->hidden = NULL;
}
}
int
InitDevice(_THIS)
{
NSString *fmt = sdlformat_to_nsfourcc(_this->spec.format);
int w = _this->spec.width;
int h = _this->spec.height;
NSError *error = nil;
AVCaptureDevice *device = nil;
AVCaptureDeviceInput *input = nil;
AVCaptureVideoDataOutput *output = nil;
AVCaptureDeviceFormat *spec_format = nil;
#ifdef __MACOS__
if (@available(macOS 10.15, *)) {
/* good. */
} else {
return -1;
}
#endif
device = get_device_by_name(_this->dev_name);
if (!device) {
goto error;
}
_this->hidden->session = [[AVCaptureSession alloc] init];
if (_this->hidden->session == nil) {
goto error;
}
[_this->hidden->session setSessionPreset:AVCaptureSessionPresetHigh];
// Pick format that matches the spec
{
NSArray<AVCaptureDeviceFormat *> *formats = [device formats];
for (AVCaptureDeviceFormat *format in formats) {
CMFormatDescriptionRef formatDescription = [format formatDescription];
FourCharCode mediaSubType = CMFormatDescriptionGetMediaSubType(formatDescription);
NSString *str = fourcc_to_nstring(mediaSubType);
if (str == fmt) {
CMVideoDimensions dim = CMVideoFormatDescriptionGetDimensions(formatDescription);
if (dim.width == w && dim.height == h) {
spec_format = format;
break;
}
}
}
}
if (spec_format == nil) {
SDL_SetError("format not found");
goto error;
}
// Set format
if ([device lockForConfiguration:NULL] == YES) {
device.activeFormat = spec_format;
[device unlockForConfiguration];
} else {
SDL_SetError("Cannot lockForConfiguration");
goto error;
}
// Input
input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
if (!input) {
SDL_SetError("Cannot create AVCaptureDeviceInput");
goto error;
}
// Output
output = [[AVCaptureVideoDataOutput alloc] init];
// Specify the pixel format
output.videoSettings =
[NSDictionary dictionaryWithObject:
[NSNumber numberWithInt:kCVPixelFormatType_422YpCbCr8]
forKey:(id)kCVPixelBufferPixelFormatTypeKey];
_this->hidden->delegate = [[MySampleBufferDelegate alloc] init];
[_this->hidden->delegate set:_this->hidden];
CMSimpleQueueCreate(kCFAllocatorDefault, 30 /* buffers */, &_this->hidden->frame_queue);
if (_this->hidden->frame_queue == nil) {
goto error;
}
_this->hidden->queue = dispatch_queue_create("my_queue", NULL);
[output setSampleBufferDelegate:_this->hidden->delegate queue:_this->hidden->queue];
if ([_this->hidden->session canAddInput:input] ){
[_this->hidden->session addInput:input];
} else {
SDL_SetError("Cannot add AVCaptureDeviceInput");
goto error;
}
if ([_this->hidden->session canAddOutput:output] ){
[_this->hidden->session addOutput:output];
} else {
SDL_SetError("Cannot add AVCaptureVideoDataOutput");
goto error;
}
[_this->hidden->session commitConfiguration];
return 0;
error:
return -1;
}
int
GetDeviceSpec(_THIS, SDL_VideoCaptureSpec *spec)
{
if (spec) {
*spec = _this->spec;
return 0;
}
return -1;
}
int
StartCapture(_THIS)
{
[_this->hidden->session startRunning];
return 0;
}
int
StopCapture(_THIS)
{
[_this->hidden->session stopRunning];
return 0;
}
int
AcquireFrame(_THIS, SDL_VideoCaptureFrame *frame, Uint64 *ticks)
{
if (CMSimpleQueueGetCount(_this->hidden->frame_queue) > 0) {
CMSampleBufferRef sampleBuffer = (CMSampleBufferRef)CMSimpleQueueDequeue(_this->hidden->frame_queue);
frame->internal = (void *) sampleBuffer;
*ticks = SDL_GetTicks();
int i = 0;
CVImageBufferRef image = CMSampleBufferGetImageBuffer(sampleBuffer);
int numPlanes = CVPixelBufferGetPlaneCount(image);
int planar = CVPixelBufferIsPlanar(image);
#if 0
int w = CVPixelBufferGetWidth(image);
int h = CVPixelBufferGetHeight(image);
int sz = CVPixelBufferGetDataSize(image);
int pitch = CVPixelBufferGetBytesPerRow(image);
SDL_Log("buffer planar=%d count:%d %d x %d sz=%d pitch=%d", planar, numPlanes, w, h, sz, pitch);
#endif
CVPixelBufferLockBaseAddress(image, 0);
if (planar == 0 && numPlanes == 0) {
frame->row_stride[0] = CVPixelBufferGetBytesPerRow(image);
frame->data[0] = CVPixelBufferGetBaseAddress(image);
frame->num_planes = 1;
} else {
for (i = 0; i < numPlanes && i < 3; i++) {
int rowStride = 0;
uint8_t *data = NULL;
frame->num_planes += 1;
rowStride = CVPixelBufferGetBytesPerRowOfPlane(image, i);
data = CVPixelBufferGetBaseAddressOfPlane(image, i);
frame->data[i] = data;
frame->row_stride[i] = rowStride;
}
}
/* Unlocked when frame is released */
} else {
// no frame
SDL_Delay(20); // TODO fix some delay
}
return 0;
}
int
ReleaseFrame(_THIS, SDL_VideoCaptureFrame *frame)
{
if (frame->internal){
CMSampleBufferRef sampleBuffer = (CMSampleBufferRef) frame->internal;
CVImageBufferRef image = CMSampleBufferGetImageBuffer(sampleBuffer);
CVPixelBufferUnlockBaseAddress(image, 0);
CFRelease(sampleBuffer);
}
return 0;
}
int
GetNumFormats(_THIS)
{
AVCaptureDevice *device = get_device_by_name(_this->dev_name);
if (device) {
// LIST FORMATS
NSMutableOrderedSet<NSString *> *array_formats = [NSMutableOrderedSet new];
NSArray<AVCaptureDeviceFormat *> *formats = [device formats];
for (AVCaptureDeviceFormat *format in formats) {
// NSLog(@"%@", formats);
CMFormatDescriptionRef formatDescription = [format formatDescription];
//NSLog(@"%@", formatDescription);
FourCharCode mediaSubType = CMFormatDescriptionGetMediaSubType(formatDescription);
NSString *str = fourcc_to_nstring(mediaSubType);
[array_formats addObject:str];
}
return [array_formats count];
}
return 0;
}
int
GetFormat(_THIS, int index, Uint32 *format, Uint32 *type)
{
AVCaptureDevice *device = get_device_by_name(_this->dev_name);
if (device) {
// LIST FORMATS
NSMutableOrderedSet<NSString *> *array_formats = [NSMutableOrderedSet new];
NSArray<AVCaptureDeviceFormat *> *formats = [device formats];
for (AVCaptureDeviceFormat *f in formats) {
CMFormatDescriptionRef formatDescription = [f formatDescription];
FourCharCode mediaSubType = CMFormatDescriptionGetMediaSubType(formatDescription);
NSString *str = fourcc_to_nstring(mediaSubType);
[array_formats addObject:str];
}
NSString *str = array_formats[index];
*format = nsfourcc_to_sdlformat(str);
return 0;
}
return -1;
}
int
GetNumFrameSizes(_THIS, Uint32 format)
{
AVCaptureDevice *device = get_device_by_name(_this->dev_name);
if (device) {
NSString *fmt = sdlformat_to_nsfourcc(format);
int count = 0;
NSArray<AVCaptureDeviceFormat *> *formats = [device formats];
for (AVCaptureDeviceFormat *f in formats) {
CMFormatDescriptionRef formatDescription = [f formatDescription];
FourCharCode mediaSubType = CMFormatDescriptionGetMediaSubType(formatDescription);
NSString *str = fourcc_to_nstring(mediaSubType);
if (str == fmt) {
count += 1;
}
}
return count;
}
return 0;
}
int
GetFrameSize(_THIS, Uint32 format, int index, Uint32 *width, Uint32 *height)
{
AVCaptureDevice *device = get_device_by_name(_this->dev_name);
if (device) {
NSString *fmt = sdlformat_to_nsfourcc(format);
int count = 0;
NSArray<AVCaptureDeviceFormat *> *formats = [device formats];
for (AVCaptureDeviceFormat *f in formats) {
CMFormatDescriptionRef formatDescription = [f formatDescription];
FourCharCode mediaSubType = CMFormatDescriptionGetMediaSubType(formatDescription);
NSString *str = fourcc_to_nstring(mediaSubType);
if (str == fmt) {
if (index == count) {
CMVideoDimensions dim = CMVideoFormatDescriptionGetDimensions(formatDescription);
*width = dim.width;
*height = dim.height;
return 0;
}
count += 1;
}
}
}
return -1;
}
int
GetDeviceName(int index, char *buf, int size)
{
NSArray<AVCaptureDevice *> *devices = discover_devices();
if (index < [devices count]) {
AVCaptureDevice *device = devices[index];
NSString *cameraID = [device localizedName];
const char *str = [cameraID UTF8String];
SDL_snprintf(buf, size, "%s", str);
return 0;
}
return -1;
}
int
GetNumDevices(void)
{
NSArray<AVCaptureDevice *> *devices = discover_devices();
return [devices count];
}
#endif /* HAVE_COREMEDIA */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -0,0 +1,33 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2022 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 "../../include/SDL3/SDL_video_capture.h"
#ifndef SDL_video_capture_c_h_
#define SDL_video_capture_c_h_
/* Initialize the video_capture subsystem */
int SDL_VideoCaptureInit(void);
/* Shutdown the video_capture subsystem */
void SDL_QuitVideoCapture(void);
#endif /* SDL_video_capture_c_h_ */

View file

@ -190,6 +190,7 @@ add_sdl_test_executable(teststreaming NEEDS_RESOURCES TESTUTILS teststreaming.c)
add_sdl_test_executable(testtimer NONINTERACTIVE testtimer.c)
add_sdl_test_executable(testurl testurl.c)
add_sdl_test_executable(testver NONINTERACTIVE testver.c)
add_sdl_test_executable(testvideocapture testvideocapture.c)
add_sdl_test_executable(testviewport NEEDS_RESOURCES TESTUTILS testviewport.c)
add_sdl_test_executable(testwm testwm.c)
add_sdl_test_executable(testyuv NEEDS_RESOURCES testyuv.c testyuv_cvt.c)

787
test/testvideocapture.c Normal file
View file

@ -0,0 +1,787 @@
/*
Copyright (C) 1997-2022 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.
*/
#include "SDL3/SDL.h"
#include "SDL3/SDL_video_capture.h"
#include <stdio.h>
/* Enable DMABUF to compile (linux + v4l2) */
#define USE_DMABUF 0
#if USE_DMABUF
# include "SDL_egl.h"
# include "SDL_opengles2.h"
# include "drm/drm_fourcc.h"
#endif
#ifdef __EMSCRIPTEN__
#include <emscripten/emscripten.h>
#endif
static const char *usage = "\
\n\
=========================================================================\n\
\n\
Use keyboards:\n\
o: open first video capture device. (close previously opened)\n\
l: list video capture devices\n\
i: information about status (Init, Playing, Stopped)\n\
f: formats and resolutions available\n\
s: start / stop capture\n\
h: display help\n\
esc: exit \n\
\n\
=========================================================================\n\
\n\
";
typedef struct {
Uint64 next_check;
int frame_counter;
int check_delay;
double last_fps;
} measure_fps_t;
static void
update_fps(measure_fps_t *m, const char *str)
{
Uint64 now = SDL_GetTicks();
Uint64 deadline;
m->frame_counter++;
if (m->check_delay == 0) {
m->check_delay = 1500;
}
if (str == NULL) {
str = "";
}
deadline = m->next_check;
if (now >= deadline) {
/* Print out some timing information */
const Uint64 then = m->next_check - m->check_delay;
m->last_fps = ((double) m->frame_counter * 1000) / (now - then);
SDL_Log("%s %2.2f frames per second\n", str, m->last_fps);
m->next_check = now + m->check_delay;
m->frame_counter = 0;
}
}
/*
+--1--+
| |
4 6
|--2--|
5 7
| |
+--3--+
*/
static const
SDL_FPoint segments[9][2] = {
{ {0, 0}, {10, 1} }, /* 1 */
{ {0, 10}, {10, 11} }, /* 2 */
{ {0, 20}, {10, 21} }, /* 3 */
{ {0, 0}, {1, 11} }, /* 4 */
{ {0, 10}, {1, 21} }, /* 5 */
{ {9, 0}, {10, 11} }, /* 6 */
{ {9, 10}, {10, 21} }, /* 7 */
{ {3, 18}, {5, 21} }, /* . */
{ {4, 0}, {5, 21} } /* | */
};
static void
draw_string(SDL_Renderer *renderer, const char *c, float x0, float y0)
{
while (*c) {
int seg = 0;
int val = *c;
if (val >= 'A' && val <= 'Z') {
val = 'a' + val - 'A';
}
switch (val) {
case '0': seg = 167345; break;
case '1': seg = 67; break;
case '2': seg = 16253; break;
case '3': seg = 16732; break;
case '4': seg = 4267; break;
case '5': seg = 14273; break;
case '6': seg = 145372; break;
case '7': seg = 167; break;
case '8': seg = 1234567; break;
case '9': seg = 123467; break;
case '.': seg = 8; break;
case '-': seg = 2; break;
case '_': seg = 3; break;
case '+': seg = 29; break;
case '|': seg = 9; break;
case '[': seg = 1453; break;
case ']': seg = 1673; break;
case 'a': seg = 124567; break;
case 'b': seg = 1234567; break;
case 'c': seg = 1453; break;
case 'd': seg = 167345; break;
case 'e': seg = 12345; break;
case 'f': seg = 1425; break;
case 'g': seg = 123457; break;
case 'h': seg = 24567; break;
case 'i': seg = 9; break;
case 'j': seg = 6735; break;
case 'k': seg = 24567; break;
case 'l': seg = 453; break;
case 'm': seg = 145679; break;
case 'n': seg = 14567; break;
case 'o': seg = 134567; break;
case 'p': seg = 14256; break;
case 'q': seg = 134567; break;
case 'r': seg = 145; break;
case 's': seg = 14273; break;
case 't': seg = 19; break;
case 'u': seg = 45367; break;
case 'v': seg = 45367; break;
case 'w': seg = 345679; break;
case 'x': seg = 24567; break;
case 'y': seg = 23467; break;
case 'z': seg = 16253; break;
}
while (seg) {
SDL_FRect r;
SDL_FPoint p1, p2;
int s = seg - 10 * (seg/10);
p1 = segments[s - 1][0];
p2 = segments[s - 1][1];
r.x = p1.x + x0;
r.y = p1.y + y0;
r.w = p2.x - p1.x;
r.h = p2.y - p1.y;
SDL_RenderRect(renderer, &r);
seg /= 10;
}
x0 += 12;
c++;
}
}
#if defined(__linux__) && !defined(__ANDROID__)
static void load_average(float *val)
{
FILE *fp = 0;
char line[1024];
fp = fopen("/proc/loadavg", "rt");
if (fp) {
char *s = fgets(line, sizeof(line), fp);
if (s) {
SDL_sscanf(s, "%f", val);
}
fclose(fp);
}
}
#endif
int main(int argc, char **argv)
{
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
SDL_Texture *texture = NULL;
int texture_updated = 0;
SDL_Event evt;
int quit = 1;
SDL_VideoCaptureDeviceID id = 0;
SDL_VideoCaptureSpec obtained;
SDL_FRect r_playstop = { 50, 50, 120, 50 };
SDL_FRect r_close = { 50 + (120 + 50) * 1, 50, 120, 50 };
SDL_FRect r_open0 = { 50 + (120 + 50) * 2, 50, 120, 50 };
SDL_FRect r_open1 = { 50 + (120 + 50) * 2, 150, 120, 50 };
SDL_FRect r_format = { 50 + (120 + 50) * 3, 50, 120, 50 };
SDL_FRect r_listdev = { 50 + (120 + 50) * 4, 50, 120, 50 };
int start = 1;
SDL_VideoCaptureFrame frame_current;
#if USE_DMABUF
EGLDisplay display;
typedef EGLDisplay (*eglGetCurrentDisplay_t)();
typedef EGLImageKHR (*eglCreateImageKHR_t)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
typedef EGLBoolean (*eglDestroyImageKHR_t)(EGLDisplay dpy, EGLImageKHR image);
typedef void (*glActiveTexture_t)(GLenum texture);
typedef void (*glEGLImageTargetTexture2DOES_t)(GLenum target, GLeglImageOES image);
typedef EGLint (*eglGetError_t)(void);
eglGetCurrentDisplay_t eglGetCurrentDisplay;
eglCreateImageKHR_t eglCreateImageKHR;
eglDestroyImageKHR_t eglDestroyImageKHR;
glActiveTexture_t glActiveTexture;
glEGLImageTargetTexture2DOES_t glEGLImageTargetTexture2DOES;
eglGetError_t eglGetError;
#endif
measure_fps_t fps_main;
measure_fps_t fps_capture;
SDL_zero(fps_main);
SDL_zero(fps_capture);
SDL_zero(frame_current);
SDL_Log("%s", usage);
/* Enable standard application logging */
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
#if USE_DMABUF
SDL_SetHint("SDL_RENDER_OPENGL_NV12_RG_SHADER", "1");
SDL_SetHint("SDL_VIDEO_X11_FORCE_EGL", "1"); /* Don't use GLX */
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengles2");
#endif
/* Load the SDL library */
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s", SDL_GetError());
return 1;
}
if (!(window = SDL_CreateWindow("Local Video", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1000, 800, 0))) {
SDL_Log("Couldn't create window: %s", SDL_GetError());
return 1;
}
SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE);
renderer = SDL_CreateRenderer(window, NULL, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (renderer == NULL) {
SDL_Log("Couldn't create renderer: %s", SDL_GetError());
return 1;
}
#if USE_DMABUF
#define LOAL_FUNC(f) \
f = (f ##_t)SDL_GL_GetProcAddress(#f); \
if (f == NULL) { \
SDL_Log("Cannot load function: " #f ); \
return 0; \
} \
LOAL_FUNC(eglGetError)
LOAL_FUNC(eglGetCurrentDisplay)
LOAL_FUNC(eglCreateImageKHR)
LOAL_FUNC(eglDestroyImageKHR)
LOAL_FUNC(glActiveTexture)
LOAL_FUNC(glEGLImageTargetTexture2DOES)
display = eglGetCurrentDisplay();
if (display == EGL_NO_DISPLAY) {
SDL_Log("no dispay");
return 0;
}
#endif
SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE);
id = SDL_OpenVideoCapture(NULL);
if (id == SDL_VIDEO_CAPTURE_INVALID) {
SDL_Log("Error SDL_OpenVideoCapture: %s", SDL_GetError());
}
{
/* List formats */
int i, num = SDL_GetNumVideoCaptureFormats(id);
for (i = 0; i < num; i++) {
Uint32 format, type;
SDL_GetVideoCaptureFormat(id, i, &format, &type);
SDL_Log("format %d/%d type=%08" SDL_PRIx32 ": %s", i, num, type, SDL_GetPixelFormatName(format));
{
Uint32 w, h;
int j, num2 = SDL_GetNumVideoCaptureFrameSizes(id, format);
for (j = 0; j < num2; j++) {
SDL_GetVideoCaptureFrameSize(id, format, j, &w, &h);
SDL_Log(" framesizes %d/%d : %" SDL_PRIu32 " x %" SDL_PRIu32 "", j, num2, w, h);
}
}
}
}
/* Set Spec */
{
int ret;
/* forced_format */
SDL_VideoCaptureSpec desired;
SDL_zero(desired);
desired.width = 640 * 2;
desired.height = 360 * 2;
ret = SDL_SetVideoCaptureSpec(id, &desired, &obtained, SDL_VIDEO_CAPTURE_ALLOW_ANY_CHANGE);
if (ret < 0) {
SDL_SetVideoCaptureSpec(id, NULL, &obtained, 0);
}
}
SDL_Log("Open capture video device. Obtained spec: size=%" SDL_PRIu32 "x%" SDL_PRIu32 " format=%s",
obtained.width, obtained.height, SDL_GetPixelFormatName(obtained.format));
{
SDL_VideoCaptureSpec spec;
if (SDL_GetVideoCaptureSpec(id, &spec) == 0) {
SDL_Log("Read spec: size=%" SDL_PRIu32 "x%" SDL_PRIu32 " format=%s",
spec.width, spec.height, SDL_GetPixelFormatName(spec.format));
} else {
SDL_Log("Error read spec: %s", SDL_GetError());
}
}
if (SDL_StartVideoCapture(id) < 0) {
SDL_Log("error SDL_StartVideoCapture(): %s", SDL_GetError());
}
while (quit) {
SDL_SetRenderDrawColor(renderer, 0x99, 0x99, 0x99, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 0x33, 0x33, 0x33, 255);
SDL_RenderFillRect(renderer, &r_playstop);
SDL_RenderFillRect(renderer, &r_close);
SDL_RenderFillRect(renderer, &r_open0);
SDL_RenderFillRect(renderer, &r_open1);
SDL_RenderFillRect(renderer, &r_format);
SDL_RenderFillRect(renderer, &r_listdev);
SDL_SetRenderDrawColor(renderer, 0xcc, 0xcc, 0xcc, 255);
draw_string(renderer, "play stop", r_playstop.x + 5, r_playstop.y + 5);
draw_string(renderer, "close", r_close.x + 5, r_close.y + 5);
draw_string(renderer, "open dev0", r_open0.x + 5, r_open0.y + 5);
draw_string(renderer, "open dev1", r_open1.x + 5, r_open1.y + 5);
draw_string(renderer, "formats", r_format.x + 5, r_format.y + 5);
draw_string(renderer, "devices", r_listdev.x + 5, r_listdev.y + 5);
while (SDL_PollEvent(&evt) == 1) {
int sym = 0;
int opendev = 0;
switch (evt.type)
{
case SDL_EVENT_KEY_DOWN:
{
sym = evt.key.keysym.sym;
break;
}
case SDL_EVENT_QUIT:
{
quit = 0;
SDL_Log("Ctlr+C : Quit!");
}
break;
case SDL_EVENT_MOUSE_BUTTON_DOWN:
{
SDL_FRect *r = NULL;
SDL_FPoint pt;
pt.x = evt.button.x;
pt.y = evt.button.y;
if (SDL_PointInRectFloat(&pt, &r_playstop)) {
r = &r_playstop;
sym = SDLK_s;
}
if (SDL_PointInRectFloat(&pt, &r_close)) {
r = &r_close;
sym = SDLK_c;
}
if (SDL_PointInRectFloat(&pt, &r_open0)) {
r = &r_open0;
sym = SDLK_o;
opendev = 0;
}
if (SDL_PointInRectFloat(&pt, &r_open1)) {
r = &r_open1;
sym = SDLK_o;
opendev = 1;
}
if (SDL_PointInRectFloat(&pt, &r_format)) {
r = &r_format;
sym = SDLK_f;
}
if (SDL_PointInRectFloat(&pt, &r_listdev)) {
r = &r_listdev;
sym = SDLK_l;
}
if (r) {
SDL_SetRenderDrawColor(renderer, 0x33, 0, 0, 255);
SDL_RenderFillRect(renderer, r);
}
}
break;
}
if (sym == SDLK_c) {
if (frame_current.num_planes) {
SDL_VideoCaptureReleaseFrame(id, &frame_current);
}
SDL_CloseVideoCapture(id);
id = SDL_VIDEO_CAPTURE_INVALID;
SDL_Log("Close");
}
if (sym == SDLK_o) {
if (id != SDL_VIDEO_CAPTURE_INVALID) {
SDL_Log("Close previous ..");
if (frame_current.num_planes) {
SDL_VideoCaptureReleaseFrame(id, &frame_current);
}
SDL_CloseVideoCapture(id);
}
texture_updated = 0;
SDL_ClearError();
if (opendev == 0) {
id = SDL_OpenVideoCaptureWithSpec(NULL, &obtained, &obtained, SDL_VIDEO_CAPTURE_ALLOW_ANY_CHANGE);
} else {
SDL_Log("Try to open:%s", SDL_GetVideoCaptureDeviceName(opendev));
id = SDL_OpenVideoCaptureWithSpec(SDL_GetVideoCaptureDeviceName(opendev), &obtained, &obtained, SDL_VIDEO_CAPTURE_ALLOW_ANY_CHANGE);
}
/* spec may have changed because of re-open */
if (texture) {
SDL_DestroyTexture(texture);
texture = NULL;
}
SDL_Log("Open id:%" SDL_PRIu32 " %s", id, SDL_GetError());
start = 0;
}
if (sym == SDLK_l) {
int num = SDL_GetNumVideoCaptureDevices();
int i;
SDL_Log("Num devices : %d", num);
for (i = 0; i < num; i++) {
SDL_Log("Device %d/%d : %s", i, num, SDL_GetVideoCaptureDeviceName(i));
}
}
if (sym == SDLK_i) {
SDL_VideoCaptureStatus status = SDL_GetVideoCaptureStatus(id);
if (status == SDL_VIDEO_CAPTURE_STOPPED) SDL_Log("STOPPED");
if (status == SDL_VIDEO_CAPTURE_PLAYING) SDL_Log("PLAYING");
if (status == SDL_VIDEO_CAPTURE_INIT) SDL_Log("INIT");
}
if (sym == SDLK_s) {
start = !start;
if (start) {
SDL_Log("Start");
SDL_StartVideoCapture(id);
} else {
SDL_Log("Stop");
SDL_StopVideoCapture(id);
}
}
if (sym == SDLK_f) {
SDL_Log("List formats");
if (id == SDL_VIDEO_CAPTURE_INVALID) {
id = SDL_OpenVideoCapture(NULL);
}
/* List formats */
{
int i, num = SDL_GetNumVideoCaptureFormats(id);
for (i = 0; i < num; i++) {
Uint32 format, type;
SDL_GetVideoCaptureFormat(id, i, &format, &type);
SDL_Log("format %d/%d type=%08" SDL_PRIx32 ": %s", i, num, type, SDL_GetPixelFormatName(format));
{
Uint32 w, h;
int j, num2 = SDL_GetNumVideoCaptureFrameSizes(id, format);
for (j = 0; j < num2; j++) {
SDL_GetVideoCaptureFrameSize(id, format, j, &w, &h);
SDL_Log(" framesizes %d/%d : %" SDL_PRIu32 " x %" SDL_PRIu32 "", j, num2, w, h);
}
}
}
}
}
if (sym == SDLK_ESCAPE || sym == SDLK_AC_BACK) {
quit = 0;
SDL_Log("Key : Escape!");
}
if (sym == SDLK_h || sym == SDLK_F1) {
SDL_Log("%s", usage);
}
}
if (id == SDL_VIDEO_CAPTURE_INVALID) {
/* device has been closed */
frame_current.num_planes = 0;
texture_updated = 0;
} else {
Uint64 ticks;
int ret;
SDL_VideoCaptureFrame frame_next;
SDL_zero(frame_next);
ret = SDL_VideoCaptureAcquireFrame(id, &frame_next, &ticks);
if (ret < 0) {
SDL_Log("err SDL_VideoCaptureAcquireFrame: %s", SDL_GetError());
}
#if 1
if (frame_next.num_planes) {
SDL_Log("frame: %p at %" SDL_PRIu64, (void*)frame_next.data[0], ticks);
}
#endif
if (frame_next.num_planes) {
update_fps(&fps_capture, "Capture");
if (frame_current.num_planes) {
ret = SDL_VideoCaptureReleaseFrame(id, &frame_current);
if (ret < 0) {
SDL_Log("err SDL_VideoCaptureReleaseFrame: %s", SDL_GetError());
}
}
frame_current = frame_next;
texture_updated = 0;
}
}
/* Moving square */
SDL_SetRenderDrawColor(renderer, 0, 0xff, 0, 255);
{
SDL_FRect r;
static float x = 0;
x += 10;
if (x > 1000) {
x = 0;
}
r.x = x;
r.y = 100;
r.w = r.h = 10;
SDL_RenderFillRect(renderer, &r);
}
SDL_SetRenderDrawColor(renderer, 0x33, 0x33, 0x33, 255);
/* Update SDL_Texture with last video frame (only once per new frame) */
if (frame_current.num_planes && texture_updated == 0) {
#if USE_DMABUF
int use_sw = 0;
#else
int use_sw = 1;
#endif
/* Create texture with appropriate format (for DMABUF or not) */
if (texture == NULL) {
Uint32 format = obtained.format;
#if USE_DMABUF
if ((frame_current.fd == -1 && frame_current.clientbuffer == NULL) || use_sw) {
/* keep format */
} else {
format = SDL_PIXELFORMAT_EXTERNAL_OES;
}
#endif
texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC, obtained.width, obtained.height);
if (texture == NULL) {
SDL_Log("Couldn't create texture: %s", SDL_GetError());
return 1;
}
}
if ((frame_current.fd == -1 && frame_current.clientbuffer == NULL) || use_sw) {
/* Use software data */
if (frame_current.num_planes == 1) {
SDL_UpdateTexture(texture, NULL,
frame_current.data[0], frame_current.row_stride[0]);
} else if (frame_current.num_planes == 2) {
SDL_UpdateNVTexture(texture, NULL,
frame_current.data[0], frame_current.row_stride[0],
frame_current.data[1], frame_current.row_stride[1]);
} else if (frame_current.num_planes == 3) {
SDL_UpdateYUVTexture(texture, NULL, frame_current.data[0], frame_current.row_stride[0],
frame_current.data[1], frame_current.row_stride[1],
frame_current.data[2], frame_current.row_stride[2]);
}
texture_updated = 1;
} else {
/* Use DMABUF */
#if USE_DMABUF
int j = 0;
EGLImage image;
EGLint img_attr[64];
#if __ANDROID__
img_attr[j] = EGL_NONE;
image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, frame_current.clientbuffer, img_attr);
#else
/* V4L2_PIX_FMT_YUYV / SDL_PIXELFORMAT_EXTERNAL_OES */
img_attr[j++] = EGL_WIDTH;
img_attr[j++] = obtained.width;
img_attr[j++] = EGL_HEIGHT;
img_attr[j++] = obtained.height;
img_attr[j++] = EGL_LINUX_DRM_FOURCC_EXT;
img_attr[j++] = DRM_FORMAT_YUYV;
img_attr[j++] = EGL_DMA_BUF_PLANE0_FD_EXT;
img_attr[j++] = frame_current.fd;
img_attr[j++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
img_attr[j++] = 0;
img_attr[j++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
img_attr[j++] = frame_current.row_stride[0];
img_attr[j++] = EGL_NONE;
image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, img_attr);
#endif
if (image == EGL_NO_IMAGE_KHR) {
SDL_Log("error eglCreateImageKHR : eglGetError: %08" SDL_PRIx32 "", eglGetError());
} else {
SDL_Log("ImageKHR: %p fd: %" SDL_PRIu32 "", image, frame_current.fd);
SDL_GL_BindTexture(texture, NULL, NULL);
glActiveTexture(GL_TEXTURE0);
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image);
SDL_GL_UnbindTexture(texture);
eglDestroyImageKHR(display, image);
texture_updated = 1;
}
#endif
}
}
/* RenderCopy the SDL_Texture */
if (texture_updated == 1) {
#if 0
SDL_Rect dst;
dst.x = 10;
dst.y = 120;
dst.w = obtained.width;
dst.h = obtained.height;
SDL_RenderCopy(renderer, texture, NULL, &dst);
#else
{ /* Scale texture to fit the screen */
int w, h;
int tw, th;
SDL_FRect d;
SDL_GetWindowSize(window, &w, &h);
SDL_QueryTexture(texture, NULL, NULL, &tw, &th);
if (tw > w - 20) {
float scale = (float) (w - 20) / (float) tw;
tw = w - 20;
th = (int)((float) th * scale);
}
d.x = 10;
d.y = (float)(h - th);
d.w = (float)tw;
d.h = (float)(th - 10);
SDL_RenderTexture(renderer, texture, NULL, &d);
}
#endif
}
/* display FPS */
{
char buf[128];
SDL_snprintf(buf, sizeof(buf), "%2.2f fps", fps_capture.last_fps);
draw_string(renderer, buf, 10, 10);
}
/* display status */
{
const char *status = "no status";
if (id != SDL_VIDEO_CAPTURE_INVALID) {
SDL_VideoCaptureStatus s = SDL_GetVideoCaptureStatus(id);
if (s == SDL_VIDEO_CAPTURE_INIT) {
status = "init";
} else if (s == SDL_VIDEO_CAPTURE_PLAYING) {
status = "playing";
} else if (s == SDL_VIDEO_CAPTURE_STOPPED) {
status = "stopped";
}
}
draw_string(renderer, status, 200, 10);
}
/* display last error */
{
draw_string(renderer, SDL_GetError(), 400, 10);
}
/* display spec */
{
char buf[128];
SDL_snprintf(buf, sizeof(buf), "%" SDL_PRIu32 " x %" SDL_PRIu32 " %s", obtained.width, obtained.height, SDL_GetPixelFormatName(obtained.format));
draw_string(renderer, buf, 10, 200);
}
/* display load average */
#if defined(__linux__) && !defined(__ANDROID__)
{
float val = 0.0f;
char buf[128];
load_average(&val);
if (val != 0.0f) {
SDL_snprintf(buf, sizeof(buf), "load avg %2.2f percent", val);
draw_string(renderer, buf, 800, 10);
}
}
#endif
SDL_RenderPresent(renderer);
update_fps(&fps_main, "Main");
}
if (SDL_StopVideoCapture(id) < 0) {
SDL_Log("error SDL_StopVideoCapture(): %s", SDL_GetError());
}
if (frame_current.num_planes) {
SDL_VideoCaptureReleaseFrame(id, &frame_current);
}
SDL_CloseVideoCapture(id);
if (texture) SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}