diff --git a/.gitignore b/.gitignore index 00e2dbc..a1ac973 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ DerivedData/ .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata .netrc builds +scripts/ffmpeg diff --git a/Resources/ffmpeg b/Resources/ffmpeg index 28f3138..39be009 100755 Binary files a/Resources/ffmpeg and b/Resources/ffmpeg differ diff --git a/rem.xcodeproj/project.pbxproj b/rem.xcodeproj/project.pbxproj index e8d94f5..7ad8f43 100644 --- a/rem.xcodeproj/project.pbxproj +++ b/rem.xcodeproj/project.pbxproj @@ -14,19 +14,18 @@ 961C95EC2B2E19B40093F228 /* remTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961C95EB2B2E19B40093F228 /* remTests.swift */; }; 961C95F62B2E19B40093F228 /* remUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961C95F52B2E19B40093F228 /* remUITests.swift */; }; 961C95F82B2E19B40093F228 /* remUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961C95F72B2E19B40093F228 /* remUITestsLaunchTests.swift */; }; - 961C960F2B2E73840093F228 /* ffmpeg in Resources */ = {isa = PBXBuildFile; fileRef = 961C960D2B2E73840093F228 /* ffmpeg */; }; - 961C96102B2E73B00093F228 /* ffmpeg in CopyFiles */ = {isa = PBXBuildFile; fileRef = 961C960D2B2E73840093F228 /* ffmpeg */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 961C96132B2EB7DB0093F228 /* TimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961C96122B2EB7DB0093F228 /* TimelineView.swift */; }; 961C96152B2EBEE50093F228 /* DB.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961C96142B2EBEE50093F228 /* DB.swift */; }; 969BA2EC2B3D1D46009EE9C6 /* SettingsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 969BA2EB2B3D1D46009EE9C6 /* SettingsManager.swift */; }; 969F3EFF2B3A8C4D0085787B /* HotKey in Frameworks */ = {isa = PBXBuildFile; productRef = 969F3EFE2B3A8C4D0085787B /* HotKey */; }; - 969F3F052B3B70560085787B /* SQLite.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 96E66BBF2B2F5745006E1E97 /* SQLite.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 969F3F082B3B7C7C0085787B /* RemFileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 969F3F072B3B7C7C0085787B /* RemFileManager.swift */; }; 969F3F0B2B3CB2110085787B /* Field.swift in Sources */ = {isa = PBXBuildFile; fileRef = 969F3F0A2B3CB2110085787B /* Field.swift */; }; 969F3F0D2B3CCEC30085787B /* Ask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 969F3F0C2B3CCEC30085787B /* Ask.swift */; }; 96B0DA382B3A02530030E8AE /* ClipboardManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96B0DA372B3A02530030E8AE /* ClipboardManager.swift */; }; 96B0DA3A2B3A08280030E8AE /* TextMerger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96B0DA392B3A08280030E8AE /* TextMerger.swift */; }; 96B0DA3D2B3A87110030E8AE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 961C95DD2B2E19B40093F228 /* Assets.xcassets */; }; + 96DBA3182B3E7D3B0000CFBE /* SQLite.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 96E66BC32B2F5745006E1E97 /* SQLite.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 96DBA31C2B3E991B0000CFBE /* ffmpeg in Resources */ = {isa = PBXBuildFile; fileRef = 961C960D2B2E73840093F228 /* ffmpeg */; }; 96F062182B35111D00695621 /* Search.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96F062172B35111D00695621 /* Search.swift */; }; /* End PBXBuildFile section */ @@ -152,7 +151,6 @@ dstPath = ""; dstSubfolderSpec = 6; files = ( - 961C96102B2E73B00093F228 /* ffmpeg in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -162,7 +160,7 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 969F3F052B3B70560085787B /* SQLite.framework in Embed Frameworks */, + 96DBA3182B3E7D3B0000CFBE /* SQLite.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -344,10 +342,10 @@ isa = PBXNativeTarget; buildConfigurationList = 961C95FB2B2E19B40093F228 /* Build configuration list for PBXNativeTarget "rem" */; buildPhases = ( + 961C96092B2E71AB0093F228 /* CopyFiles */, 961C95D22B2E19B30093F228 /* Sources */, 961C95D32B2E19B30093F228 /* Frameworks */, 961C95D42B2E19B30093F228 /* Resources */, - 961C96092B2E71AB0093F228 /* CopyFiles */, 969F3F062B3B70570085787B /* Embed Frameworks */, ); buildRules = ( @@ -560,9 +558,9 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 96DBA31C2B3E991B0000CFBE /* ffmpeg in Resources */, 961C95E12B2E19B40093F228 /* Preview Assets.xcassets in Resources */, 96B0DA3D2B3A87110030E8AE /* Assets.xcassets in Resources */, - 961C960F2B2E73840093F228 /* ffmpeg in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/rem.xcodeproj/xcuserdata/jason.xcuserdatad/xcschemes/xcschememanagement.plist b/rem.xcodeproj/xcuserdata/jason.xcuserdatad/xcschemes/xcschememanagement.plist index a2ea57c..d39feb3 100644 --- a/rem.xcodeproj/xcuserdata/jason.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/rem.xcodeproj/xcuserdata/jason.xcuserdatad/xcschemes/xcschememanagement.plist @@ -28,7 +28,7 @@ rem.xcscheme_^#shared#^_ orderHint - 4 + 0 diff --git a/rem/rem.entitlements b/rem/rem.entitlements index 18aff0c..c05ff03 100644 --- a/rem/rem.entitlements +++ b/rem/rem.entitlements @@ -5,6 +5,8 @@ com.apple.security.app-sandbox com.apple.security.files.user-selected.read-only + + com.apple.security.inherit diff --git a/rem/remApp.swift b/rem/remApp.swift index 70ab518..b1b4bd0 100644 --- a/rem/remApp.swift +++ b/rem/remApp.swift @@ -333,15 +333,22 @@ class AppDelegate: NSObject, NSApplicationDelegate { imageBufferQueue.async(flags: .barrier) { [weak self] in guard let strongSelf = self else { return } - strongSelf.imageDataBuffer.append(data) - // If the buffer reaches the threshold, process the chunk + strongSelf.imageDataBuffer.append(data) + + // Quickly move the images to a temporary buffer if the threshold is reached + var tempBuffer: [Data] = [] if strongSelf.imageDataBuffer.count >= strongSelf.frameThreshold { - let chunk = Array(strongSelf.imageDataBuffer.prefix(strongSelf.frameThreshold)) + tempBuffer = Array(strongSelf.imageDataBuffer.prefix(strongSelf.frameThreshold)) strongSelf.imageDataBuffer.removeFirst(strongSelf.frameThreshold) - strongSelf.processChunk(chunk) + } + + // Process the images outside of the critical section + if !tempBuffer.isEmpty { + strongSelf.processChunk(tempBuffer) } } + } private func processChunk(_ chunk: [Data]) { @@ -360,10 +367,11 @@ class AppDelegate: NSObject, NSApplicationDelegate { ffmpegProcess.executableURL = URL(fileURLWithPath: ffmpegPath) ffmpegProcess.arguments = [ "-f", "image2pipe", + "-vcodec", "png", "-i", "-", "-color_trc", "iec61966_2_1", // Set transfer characteristics for sRGB (approximates 2.2 gamma) "-c:v", "h264_videotoolbox", - "-crf", "25", + "-q:v", "25", outputPath ] let ffmpegInputPipe = Pipe() diff --git a/scripts/build_ffmpeg.sh b/scripts/build_ffmpeg.sh new file mode 100644 index 0000000..1fc61f0 --- /dev/null +++ b/scripts/build_ffmpeg.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# Define the necessary flags for ARM64 architecture +export SDKROOT=$(xcrun --sdk macosx --show-sdk-path) +export MACOSX_DEPLOYMENT_TARGET=$(xcrun --sdk macosx --show-sdk-platform-version) +export CFLAGS="-arch arm64 -isysroot $SDKROOT" +export LDFLAGS="-arch arm64 -isysroot $SDKROOT" +export CC="clang -arch arm64" + +# Clone the FFmpeg repository +git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg +cd ffmpeg + +# Configure the build for ARM64 with VideoToolbox support +./configure \ + --prefix=/usr/local \ + --enable-static \ + --disable-shared \ + --disable-everything \ + --disable-xlib \ + --enable-encoder=hevc_videotoolbox,h264_videotoolbox \ + --enable-muxer=mp4 \ + --enable-demuxer=image2pipe \ + --enable-decoder=png \ + --enable-parser=png \ + --enable-protocol=file,pipe,fd \ + --enable-indev=lavfi \ + --enable-filter=scale \ + --enable-bsf=hevc_mp4toannexb \ + --target-os=darwin \ + --arch=arm64 + +# Compile and install +make clean +make && sudo make install