From b679796a9d0d3ae153948cc592c9d74b6c7bf977 Mon Sep 17 00:00:00 2001 From: Omer Karisman Date: Tue, 29 Aug 2017 20:41:03 +0300 Subject: [PATCH] Remove SCNRenderer. Use CAMetalLayer insted. This way capturing the current frame is much faster and it oncludes animations too. Detect simulator 0.7.0 pod fix pod fix pod fix Pod fix metal Pod fix metal --- Example/Podfile | 11 - Example/Podfile.lock | 16 - .../SCNVideoWriter.xcodeproj/project.pbxproj | 657 ------------------ .../contents.xcworkspacedata | 7 - .../xcschemes/SCNVideoWriter-Example.xcscheme | 117 ---- .../contents.xcworkspacedata | 10 - Example/SCNVideoWriter/ARViewController.swift | 69 -- Example/SCNVideoWriter/AppDelegate.swift | 46 -- .../SCNVideoWriter/Base.lproj/AR.storyboard | 44 -- .../Base.lproj/LaunchScreen.xib | 41 -- .../AppIcon.appiconset/Contents.json | 38 - Example/SCNVideoWriter/Info.plist | 45 -- Example/SCNVideoWriter/Main.storyboard | 58 -- Example/SCNVideoWriter/SCN.storyboard | 43 -- .../SCNVideoWriter/SCNViewController.swift | 79 --- Example/SCNVideoWriter/ViewController.swift | 46 -- Example/Tests/Info.plist | 24 - Example/Tests/Tests.swift | 29 - README.md | 18 +- SCNVideoWriter.podspec | 20 - SCNVideoWriter/Classes/Error.swift | 13 - SCNVideoWriter/Classes/SCNVideoWriter.swift | 119 ---- SceneKitVideoRecorder.podspec | 142 ++++ .../Assets/.gitkeep | 0 .../Classes/.gitkeep | 0 SceneKitVideoRecorder/Classes/Error.swift | 12 + .../Classes/FileController.swift | 3 +- .../Classes/Options.swift | 5 +- .../Classes/PixelBufferFactory.swift | 3 +- .../Classes/SceneKitVideoRecorder.swift | 156 +++++ .../Classes/UIImage+Extensions.swift | 3 +- 31 files changed, 325 insertions(+), 1549 deletions(-) delete mode 100644 Example/Podfile delete mode 100644 Example/Podfile.lock delete mode 100644 Example/SCNVideoWriter.xcodeproj/project.pbxproj delete mode 100644 Example/SCNVideoWriter.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 Example/SCNVideoWriter.xcodeproj/xcshareddata/xcschemes/SCNVideoWriter-Example.xcscheme delete mode 100644 Example/SCNVideoWriter.xcworkspace/contents.xcworkspacedata delete mode 100644 Example/SCNVideoWriter/ARViewController.swift delete mode 100644 Example/SCNVideoWriter/AppDelegate.swift delete mode 100644 Example/SCNVideoWriter/Base.lproj/AR.storyboard delete mode 100644 Example/SCNVideoWriter/Base.lproj/LaunchScreen.xib delete mode 100644 Example/SCNVideoWriter/Images.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Example/SCNVideoWriter/Info.plist delete mode 100644 Example/SCNVideoWriter/Main.storyboard delete mode 100644 Example/SCNVideoWriter/SCN.storyboard delete mode 100644 Example/SCNVideoWriter/SCNViewController.swift delete mode 100644 Example/SCNVideoWriter/ViewController.swift delete mode 100644 Example/Tests/Info.plist delete mode 100644 Example/Tests/Tests.swift delete mode 100644 SCNVideoWriter.podspec delete mode 100644 SCNVideoWriter/Classes/Error.swift delete mode 100644 SCNVideoWriter/Classes/SCNVideoWriter.swift create mode 100644 SceneKitVideoRecorder.podspec rename {SCNVideoWriter => SceneKitVideoRecorder}/Assets/.gitkeep (100%) rename {SCNVideoWriter => SceneKitVideoRecorder}/Classes/.gitkeep (100%) create mode 100644 SceneKitVideoRecorder/Classes/Error.swift rename {SCNVideoWriter => SceneKitVideoRecorder}/Classes/FileController.swift (75%) rename {SCNVideoWriter => SceneKitVideoRecorder}/Classes/Options.swift (92%) rename {SCNVideoWriter => SceneKitVideoRecorder}/Classes/PixelBufferFactory.swift (94%) create mode 100644 SceneKitVideoRecorder/Classes/SceneKitVideoRecorder.swift rename {SCNVideoWriter => SceneKitVideoRecorder}/Classes/UIImage+Extensions.swift (95%) diff --git a/Example/Podfile b/Example/Podfile deleted file mode 100644 index d44107b..0000000 --- a/Example/Podfile +++ /dev/null @@ -1,11 +0,0 @@ -use_frameworks! - -target 'SCNVideoWriter_Example' do - pod 'SCNVideoWriter', :path => '../' - - target 'SCNVideoWriter_Tests' do - inherit! :search_paths - - - end -end diff --git a/Example/Podfile.lock b/Example/Podfile.lock deleted file mode 100644 index e0ef09d..0000000 --- a/Example/Podfile.lock +++ /dev/null @@ -1,16 +0,0 @@ -PODS: - - SCNVideoWriter (0.1.0) - -DEPENDENCIES: - - SCNVideoWriter (from `../`) - -EXTERNAL SOURCES: - SCNVideoWriter: - :path: "../" - -SPEC CHECKSUMS: - SCNVideoWriter: 29d821b31cef64659f204f9cc574242b95d8d538 - -PODFILE CHECKSUM: 82bad70245a28ecd3a0db4c94adf58fcf37db6d6 - -COCOAPODS: 1.3.0.beta.1 diff --git a/Example/SCNVideoWriter.xcodeproj/project.pbxproj b/Example/SCNVideoWriter.xcodeproj/project.pbxproj deleted file mode 100644 index 7b07a15..0000000 --- a/Example/SCNVideoWriter.xcodeproj/project.pbxproj +++ /dev/null @@ -1,657 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 1D342F4DFDA5CBB0F085909A /* Pods_SCNVideoWriter_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EF71FF0D77F00621C1B4BAD /* Pods_SCNVideoWriter_Tests.framework */; }; - 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; }; - 607FACD81AFB9204008FA782 /* ARViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD71AFB9204008FA782 /* ARViewController.swift */; }; - 607FACDB1AFB9204008FA782 /* AR.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* AR.storyboard */; }; - 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; }; - 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; }; - 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* Tests.swift */; }; - BFF9EAA01522EF3FAD03FDDC /* Pods_SCNVideoWriter_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C30EB50A8AEF0CBDEA13B25 /* Pods_SCNVideoWriter_Example.framework */; }; - D7C292FC1F33985300F88A39 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D7C292FB1F33985300F88A39 /* Main.storyboard */; }; - D7C292FE1F33985D00F88A39 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7C292FD1F33985D00F88A39 /* ViewController.swift */; }; - D7C293021F3398AB00F88A39 /* SCNViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7C293011F3398AB00F88A39 /* SCNViewController.swift */; }; - D7C293041F3398B200F88A39 /* SCN.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D7C293031F3398B200F88A39 /* SCN.storyboard */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 607FACC81AFB9204008FA782 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 607FACCF1AFB9204008FA782; - remoteInfo = SCNVideoWriter; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 079BC9F1D1BFB1B60C61DFC1 /* Pods-SCNVideoWriter_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SCNVideoWriter_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SCNVideoWriter_Example/Pods-SCNVideoWriter_Example.debug.xcconfig"; sourceTree = ""; }; - 25DBF12E7CE5BABAA1C7AD03 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; - 2AF23AF3810D881250001A04 /* Pods-SCNVideoWriter_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SCNVideoWriter_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-SCNVideoWriter_Tests/Pods-SCNVideoWriter_Tests.release.xcconfig"; sourceTree = ""; }; - 3C30EB50A8AEF0CBDEA13B25 /* Pods_SCNVideoWriter_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SCNVideoWriter_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 5BEA205436D94058F0635032 /* Pods-SCNVideoWriter_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SCNVideoWriter_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-SCNVideoWriter_Example/Pods-SCNVideoWriter_Example.release.xcconfig"; sourceTree = ""; }; - 607FACD01AFB9204008FA782 /* SCNVideoWriter_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SCNVideoWriter_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 607FACD71AFB9204008FA782 /* ARViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ARViewController.swift; sourceTree = ""; }; - 607FACDA1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/AR.storyboard; sourceTree = ""; }; - 607FACDC1AFB9204008FA782 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 607FACE51AFB9204008FA782 /* SCNVideoWriter_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SCNVideoWriter_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 607FACEB1AFB9204008FA782 /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = ""; }; - 9EF71FF0D77F00621C1B4BAD /* Pods_SCNVideoWriter_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SCNVideoWriter_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - ADCD4F58EC08C252163D4C30 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; - CA1102A2A2C4951411716431 /* SCNVideoWriter.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = SCNVideoWriter.podspec; path = ../SCNVideoWriter.podspec; sourceTree = ""; }; - D7C292FB1F33985300F88A39 /* Main.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; - D7C292FD1F33985D00F88A39 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - D7C293011F3398AB00F88A39 /* SCNViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SCNViewController.swift; sourceTree = ""; }; - D7C293031F3398B200F88A39 /* SCN.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = SCN.storyboard; sourceTree = ""; }; - EB1B46CC9FFA4CE345FBFE3A /* Pods-SCNVideoWriter_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SCNVideoWriter_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SCNVideoWriter_Tests/Pods-SCNVideoWriter_Tests.debug.xcconfig"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 607FACCD1AFB9204008FA782 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - BFF9EAA01522EF3FAD03FDDC /* Pods_SCNVideoWriter_Example.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 607FACE21AFB9204008FA782 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1D342F4DFDA5CBB0F085909A /* Pods_SCNVideoWriter_Tests.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 2C87611885C40D2CD81D2AFF /* Pods */ = { - isa = PBXGroup; - children = ( - 079BC9F1D1BFB1B60C61DFC1 /* Pods-SCNVideoWriter_Example.debug.xcconfig */, - 5BEA205436D94058F0635032 /* Pods-SCNVideoWriter_Example.release.xcconfig */, - EB1B46CC9FFA4CE345FBFE3A /* Pods-SCNVideoWriter_Tests.debug.xcconfig */, - 2AF23AF3810D881250001A04 /* Pods-SCNVideoWriter_Tests.release.xcconfig */, - ); - name = Pods; - sourceTree = ""; - }; - 4EDA5D320E5B6D47104991C4 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 3C30EB50A8AEF0CBDEA13B25 /* Pods_SCNVideoWriter_Example.framework */, - 9EF71FF0D77F00621C1B4BAD /* Pods_SCNVideoWriter_Tests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 607FACC71AFB9204008FA782 = { - isa = PBXGroup; - children = ( - 607FACF51AFB993E008FA782 /* Podspec Metadata */, - 607FACD21AFB9204008FA782 /* Example for SCNVideoWriter */, - 607FACE81AFB9204008FA782 /* Tests */, - 607FACD11AFB9204008FA782 /* Products */, - 2C87611885C40D2CD81D2AFF /* Pods */, - 4EDA5D320E5B6D47104991C4 /* Frameworks */, - ); - sourceTree = ""; - }; - 607FACD11AFB9204008FA782 /* Products */ = { - isa = PBXGroup; - children = ( - 607FACD01AFB9204008FA782 /* SCNVideoWriter_Example.app */, - 607FACE51AFB9204008FA782 /* SCNVideoWriter_Tests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 607FACD21AFB9204008FA782 /* Example for SCNVideoWriter */ = { - isa = PBXGroup; - children = ( - D7C293001F3398A200F88A39 /* SCN */, - D7C292FF1F33989800F88A39 /* AR */, - 607FACD51AFB9204008FA782 /* AppDelegate.swift */, - 607FACDC1AFB9204008FA782 /* Images.xcassets */, - 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */, - 607FACD31AFB9204008FA782 /* Supporting Files */, - D7C292FB1F33985300F88A39 /* Main.storyboard */, - D7C292FD1F33985D00F88A39 /* ViewController.swift */, - ); - name = "Example for SCNVideoWriter"; - path = SCNVideoWriter; - sourceTree = ""; - }; - 607FACD31AFB9204008FA782 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 607FACD41AFB9204008FA782 /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 607FACE81AFB9204008FA782 /* Tests */ = { - isa = PBXGroup; - children = ( - 607FACEB1AFB9204008FA782 /* Tests.swift */, - 607FACE91AFB9204008FA782 /* Supporting Files */, - ); - path = Tests; - sourceTree = ""; - }; - 607FACE91AFB9204008FA782 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 607FACEA1AFB9204008FA782 /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 607FACF51AFB993E008FA782 /* Podspec Metadata */ = { - isa = PBXGroup; - children = ( - CA1102A2A2C4951411716431 /* SCNVideoWriter.podspec */, - ADCD4F58EC08C252163D4C30 /* README.md */, - 25DBF12E7CE5BABAA1C7AD03 /* LICENSE */, - ); - name = "Podspec Metadata"; - sourceTree = ""; - }; - D7C292FF1F33989800F88A39 /* AR */ = { - isa = PBXGroup; - children = ( - 607FACD71AFB9204008FA782 /* ARViewController.swift */, - 607FACD91AFB9204008FA782 /* AR.storyboard */, - ); - name = AR; - sourceTree = ""; - }; - D7C293001F3398A200F88A39 /* SCN */ = { - isa = PBXGroup; - children = ( - D7C293011F3398AB00F88A39 /* SCNViewController.swift */, - D7C293031F3398B200F88A39 /* SCN.storyboard */, - ); - name = SCN; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 607FACCF1AFB9204008FA782 /* SCNVideoWriter_Example */ = { - isa = PBXNativeTarget; - buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "SCNVideoWriter_Example" */; - buildPhases = ( - F33B7A59D2A3759405CAAF38 /* [CP] Check Pods Manifest.lock */, - 607FACCC1AFB9204008FA782 /* Sources */, - 607FACCD1AFB9204008FA782 /* Frameworks */, - 607FACCE1AFB9204008FA782 /* Resources */, - CF95C6A3368ED2E216860FD3 /* [CP] Embed Pods Frameworks */, - A8740CFFDF34B86691D49509 /* [CP] Copy Pods Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = SCNVideoWriter_Example; - productName = SCNVideoWriter; - productReference = 607FACD01AFB9204008FA782 /* SCNVideoWriter_Example.app */; - productType = "com.apple.product-type.application"; - }; - 607FACE41AFB9204008FA782 /* SCNVideoWriter_Tests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "SCNVideoWriter_Tests" */; - buildPhases = ( - 34442463E1977BE1DF90A35F /* [CP] Check Pods Manifest.lock */, - 607FACE11AFB9204008FA782 /* Sources */, - 607FACE21AFB9204008FA782 /* Frameworks */, - 607FACE31AFB9204008FA782 /* Resources */, - 0ADDD054D3268F1438B4A9C4 /* [CP] Embed Pods Frameworks */, - A1B699F35D66F0339FC0E592 /* [CP] Copy Pods Resources */, - ); - buildRules = ( - ); - dependencies = ( - 607FACE71AFB9204008FA782 /* PBXTargetDependency */, - ); - name = SCNVideoWriter_Tests; - productName = Tests; - productReference = 607FACE51AFB9204008FA782 /* SCNVideoWriter_Tests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 607FACC81AFB9204008FA782 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0900; - ORGANIZATIONNAME = CocoaPods; - TargetAttributes = { - 607FACCF1AFB9204008FA782 = { - CreatedOnToolsVersion = 6.3.1; - DevelopmentTeam = FBQ6Z8AF3U; - LastSwiftMigration = 0820; - ProvisioningStyle = Manual; - }; - 607FACE41AFB9204008FA782 = { - CreatedOnToolsVersion = 6.3.1; - DevelopmentTeam = FBQ6Z8AF3U; - LastSwiftMigration = 0820; - ProvisioningStyle = Manual; - TestTargetID = 607FACCF1AFB9204008FA782; - }; - }; - }; - buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "SCNVideoWriter" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 607FACC71AFB9204008FA782; - productRefGroup = 607FACD11AFB9204008FA782 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 607FACCF1AFB9204008FA782 /* SCNVideoWriter_Example */, - 607FACE41AFB9204008FA782 /* SCNVideoWriter_Tests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 607FACCE1AFB9204008FA782 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 607FACDB1AFB9204008FA782 /* AR.storyboard in Resources */, - 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */, - 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */, - D7C293041F3398B200F88A39 /* SCN.storyboard in Resources */, - D7C292FC1F33985300F88A39 /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 607FACE31AFB9204008FA782 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 0ADDD054D3268F1438B4A9C4 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[CP] Embed Pods Frameworks"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SCNVideoWriter_Tests/Pods-SCNVideoWriter_Tests-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - 34442463E1977BE1DF90A35F /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[CP] Check Pods Manifest.lock"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; - showEnvVarsInLog = 0; - }; - A1B699F35D66F0339FC0E592 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[CP] Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SCNVideoWriter_Tests/Pods-SCNVideoWriter_Tests-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; - A8740CFFDF34B86691D49509 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[CP] Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SCNVideoWriter_Example/Pods-SCNVideoWriter_Example-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; - CF95C6A3368ED2E216860FD3 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[CP] Embed Pods Frameworks"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SCNVideoWriter_Example/Pods-SCNVideoWriter_Example-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - F33B7A59D2A3759405CAAF38 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[CP] Check Pods Manifest.lock"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 607FACCC1AFB9204008FA782 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - D7C292FE1F33985D00F88A39 /* ViewController.swift in Sources */, - D7C293021F3398AB00F88A39 /* SCNViewController.swift in Sources */, - 607FACD81AFB9204008FA782 /* ARViewController.swift in Sources */, - 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 607FACE11AFB9204008FA782 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 607FACE71AFB9204008FA782 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 607FACCF1AFB9204008FA782 /* SCNVideoWriter_Example */; - targetProxy = 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 607FACD91AFB9204008FA782 /* AR.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 607FACDA1AFB9204008FA782 /* Base */, - ); - name = AR.storyboard; - sourceTree = ""; - }; - 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 607FACDF1AFB9204008FA782 /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 607FACED1AFB9204008FA782 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.3; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 607FACEE1AFB9204008FA782 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.3; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 607FACF01AFB9204008FA782 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 079BC9F1D1BFB1B60C61DFC1 /* Pods-SCNVideoWriter_Example.debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Manual; - DEVELOPMENT_TEAM = FBQ6Z8AF3U; - INFOPLIST_FILE = SCNVideoWriter/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - MODULE_NAME = ExampleApp; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = "905ee6bd-d0b8-4820-ab2d-03b079ef72eb"; - PROVISIONING_PROFILE_SPECIFIER = "noppelabs-*"; - SWIFT_VERSION = 3.0; - }; - name = Debug; - }; - 607FACF11AFB9204008FA782 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 5BEA205436D94058F0635032 /* Pods-SCNVideoWriter_Example.release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Manual; - DEVELOPMENT_TEAM = FBQ6Z8AF3U; - INFOPLIST_FILE = SCNVideoWriter/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - MODULE_NAME = ExampleApp; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = "905ee6bd-d0b8-4820-ab2d-03b079ef72eb"; - PROVISIONING_PROFILE_SPECIFIER = "noppelabs-*"; - SWIFT_VERSION = 3.0; - }; - name = Release; - }; - 607FACF31AFB9204008FA782 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = EB1B46CC9FFA4CE345FBFE3A /* Pods-SCNVideoWriter_Tests.debug.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; - DEVELOPMENT_TEAM = FBQ6Z8AF3U; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - INFOPLIST_FILE = Tests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 3.0; - }; - name = Debug; - }; - 607FACF41AFB9204008FA782 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 2AF23AF3810D881250001A04 /* Pods-SCNVideoWriter_Tests.release.xcconfig */; - buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; - DEVELOPMENT_TEAM = FBQ6Z8AF3U; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); - INFOPLIST_FILE = Tests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 3.0; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "SCNVideoWriter" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 607FACED1AFB9204008FA782 /* Debug */, - 607FACEE1AFB9204008FA782 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "SCNVideoWriter_Example" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 607FACF01AFB9204008FA782 /* Debug */, - 607FACF11AFB9204008FA782 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "SCNVideoWriter_Tests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 607FACF31AFB9204008FA782 /* Debug */, - 607FACF41AFB9204008FA782 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 607FACC81AFB9204008FA782 /* Project object */; -} diff --git a/Example/SCNVideoWriter.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Example/SCNVideoWriter.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 469ee7e..0000000 --- a/Example/SCNVideoWriter.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/Example/SCNVideoWriter.xcodeproj/xcshareddata/xcschemes/SCNVideoWriter-Example.xcscheme b/Example/SCNVideoWriter.xcodeproj/xcshareddata/xcschemes/SCNVideoWriter-Example.xcscheme deleted file mode 100644 index 45d74c5..0000000 --- a/Example/SCNVideoWriter.xcodeproj/xcshareddata/xcschemes/SCNVideoWriter-Example.xcscheme +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Example/SCNVideoWriter.xcworkspace/contents.xcworkspacedata b/Example/SCNVideoWriter.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index bffe65d..0000000 --- a/Example/SCNVideoWriter.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/Example/SCNVideoWriter/ARViewController.swift b/Example/SCNVideoWriter/ARViewController.swift deleted file mode 100644 index 945db92..0000000 --- a/Example/SCNVideoWriter/ARViewController.swift +++ /dev/null @@ -1,69 +0,0 @@ -// -// ViewController.swift -// SCNVideoWriter -// -// Created by noppefoxwolf on 07/31/2017. -// Copyright (c) 2017 noppefoxwolf. All rights reserved. -// - -import UIKit -import ARKit -import SceneKit -import SCNVideoWriter -import Photos - -@available(iOS 11.0, *) -final class ARViewController: UIViewController { - static func make() -> ARViewController { - return UIStoryboard(name: "AR", bundle: nil).instantiateInitialViewController() as! ARViewController - } - - @IBOutlet private weak var sceneView: ARSCNView! - private var writer: SCNVideoWriter? = nil - - override func viewDidLoad() { - super.viewDidLoad() - sceneView.debugOptions = [ARSCNDebugOptions.showFeaturePoints, ARSCNDebugOptions.showWorldOrigin] - setupARScene() - } - - private func setupARScene() { - let box = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0.0) - let node = SCNNode(geometry: box) - sceneView.scene.rootNode.addChildNode(node) - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - sceneView.session.run(ARWorldTrackingSessionConfiguration()) - } - - override func viewDidDisappear(_ animated: Bool) { - super.viewDidDisappear(animated) - sceneView.session.pause() - } - - override func touchesBegan(_ touches: Set, with event: UIEvent?) { - do { - writer = try SCNVideoWriter(withARSCNView: sceneView) - writer?.startWriting() - } catch let e { - print(e) - } - } - - override func touchesEnded(_ touches: Set, with event: UIEvent?) { - writer?.finishWriting(completionHandler: { [weak self] (url) in - print("done", url) - self?.save(video: url) - }) - } - - private func save(video url: URL) { - PHPhotoLibrary.shared().performChanges({ - PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: url) - }) { (done, error) in - print(done, error as Any) - } - } -} diff --git a/Example/SCNVideoWriter/AppDelegate.swift b/Example/SCNVideoWriter/AppDelegate.swift deleted file mode 100644 index bf6791a..0000000 --- a/Example/SCNVideoWriter/AppDelegate.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// AppDelegate.swift -// SCNVideoWriter -// -// Created by noppefoxwolf on 07/31/2017. -// Copyright (c) 2017 noppefoxwolf. All rights reserved. -// - -import UIKit - -@UIApplicationMain -class AppDelegate: UIResponder, UIApplicationDelegate { - - var window: UIWindow? - - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { - // Override point for customization after application launch. - return true - } - - func applicationWillResignActive(_ application: UIApplication) { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. - } - - func applicationDidEnterBackground(_ application: UIApplication) { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. - } - - func applicationWillEnterForeground(_ application: UIApplication) { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. - } - - func applicationDidBecomeActive(_ application: UIApplication) { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. - } - - func applicationWillTerminate(_ application: UIApplication) { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. - } - - -} - diff --git a/Example/SCNVideoWriter/Base.lproj/AR.storyboard b/Example/SCNVideoWriter/Base.lproj/AR.storyboard deleted file mode 100644 index fe3c1b2..0000000 --- a/Example/SCNVideoWriter/Base.lproj/AR.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Example/SCNVideoWriter/Base.lproj/LaunchScreen.xib b/Example/SCNVideoWriter/Base.lproj/LaunchScreen.xib deleted file mode 100644 index c409ec3..0000000 --- a/Example/SCNVideoWriter/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Example/SCNVideoWriter/Images.xcassets/AppIcon.appiconset/Contents.json b/Example/SCNVideoWriter/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index d3942e9..0000000 --- a/Example/SCNVideoWriter/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/Example/SCNVideoWriter/Info.plist b/Example/SCNVideoWriter/Info.plist deleted file mode 100644 index ee8abe4..0000000 --- a/Example/SCNVideoWriter/Info.plist +++ /dev/null @@ -1,45 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - NSCameraUsageDescription - - NSPhotoLibraryUsageDescription - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeRight - - - diff --git a/Example/SCNVideoWriter/Main.storyboard b/Example/SCNVideoWriter/Main.storyboard deleted file mode 100644 index af7375d..0000000 --- a/Example/SCNVideoWriter/Main.storyboard +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Example/SCNVideoWriter/SCN.storyboard b/Example/SCNVideoWriter/SCN.storyboard deleted file mode 100644 index a3c2f13..0000000 --- a/Example/SCNVideoWriter/SCN.storyboard +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Example/SCNVideoWriter/SCNViewController.swift b/Example/SCNVideoWriter/SCNViewController.swift deleted file mode 100644 index deb44fa..0000000 --- a/Example/SCNVideoWriter/SCNViewController.swift +++ /dev/null @@ -1,79 +0,0 @@ -// -// SCNViewController.swift -// SCNVideoWriter_Example -// -// Created by Tomoya Hirano on 2017/08/04. -// Copyright © 2017年 CocoaPods. All rights reserved. -// - -import UIKit -import SceneKit -import SCNVideoWriter -import Photos - -final class SCNViewController: UIViewController { - static func make() -> SCNViewController { - return UIStoryboard(name: "SCN", bundle: nil).instantiateInitialViewController() as! SCNViewController - } - - @IBOutlet private weak var previewImageView: UIImageView! - private var writer: SCNVideoWriter? = nil - private let scene = SCNScene() - - override func viewDidLoad() { - super.viewDidLoad() - setupSceneView() - } - - private func setupSceneView() { - let box = SCNBox(width: 10.0, height: 10.0, length: 10.0, chamferRadius: 0.0) - let boxNode = SCNNode(geometry: box) - scene.rootNode.addChildNode(boxNode) - boxNode.rotation = SCNVector4Make(0, 1, 0, Float.pi / 5.0) - - let cameraNode = SCNNode() - let camera = SCNCamera() - cameraNode.camera = camera - cameraNode.position = SCNVector3Make(0, 10, 20) - cameraNode.rotation = SCNVector4Make(1, 0, 0, -atan2(10.0, 20.0)) - scene.rootNode.addChildNode(cameraNode) - - let light = SCNLight() - light.type = SCNLight.LightType.directional - light.color = UIColor.blue - let lightNode = SCNNode() - lightNode.light = light - cameraNode.addChildNode(lightNode) - - boxNode.runAction(SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 2, z: 0, duration: 1))) - } - - override func touchesBegan(_ touches: Set, with event: UIEvent?) { - do { - writer = try SCNVideoWriter(scene: scene) - writer?.updateFrameHandler = { [weak self] (image, time) in - DispatchQueue.main.async { - self?.previewImageView.image = image - } - } - writer?.startWriting() - } catch let e { - print(e) - } - } - - override func touchesEnded(_ touches: Set, with event: UIEvent?) { - writer?.finishWriting(completionHandler: { [weak self] (url) in - print("done", url) - self?.save(video: url) - }) - } - - private func save(video url: URL) { - PHPhotoLibrary.shared().performChanges({ - PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: url) - }) { (done, error) in - print(done, error as Any) - } - } -} diff --git a/Example/SCNVideoWriter/ViewController.swift b/Example/SCNVideoWriter/ViewController.swift deleted file mode 100644 index c953d72..0000000 --- a/Example/SCNVideoWriter/ViewController.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// ViewController.swift -// SCNVideoWriter_Example -// -// Created by Tomoya Hirano on 2017/08/04. -// Copyright © 2017年 CocoaPods. All rights reserved. -// - -import UIKit - -final class ViewController: UITableViewController { - enum SceneKitKind: Int { - case scn - case ar - - static var all: [SceneKitKind] { - return [scn, ar] - } - } - - override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return SceneKitKind.all.count - } - - override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "cell")! - switch SceneKitKind(rawValue: indexPath.row) { - case .some(.scn): cell.textLabel?.text = "SceneKit" - case .some(.ar): cell.textLabel?.text = "ARKit (iOS11 or later)" - default: break - } - return cell - } - - override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - switch SceneKitKind(rawValue: indexPath.row) { - case .some(.scn): - navigationController?.pushViewController(SCNViewController.make(), animated: true) - case .some(.ar): - if #available(iOS 11.0, *) { - navigationController?.pushViewController(ARViewController.make(), animated: true) - } - default: break - } - } -} diff --git a/Example/Tests/Info.plist b/Example/Tests/Info.plist deleted file mode 100644 index ba72822..0000000 --- a/Example/Tests/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - - diff --git a/Example/Tests/Tests.swift b/Example/Tests/Tests.swift deleted file mode 100644 index 0f628da..0000000 --- a/Example/Tests/Tests.swift +++ /dev/null @@ -1,29 +0,0 @@ -import UIKit -import XCTest - - -class Tests: XCTestCase { - - override func setUp() { - super.setUp() - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDown() { - // Put teardown code here. This method is called after the invocation of each test method in the class. - super.tearDown() - } - - func testExample() { - // This is an example of a functional test case. - XCTAssert(true, "Pass") - } - - func testPerformanceExample() { - // This is an example of a performance test case. - self.measure() { - // Put the code you want to measure the time of here. - } - } - -} diff --git a/README.md b/README.md index 5a04ecf..61a56da 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# SCNVideoWriter +# SceneKitVideoRecorder -[![Version](https://img.shields.io/cocoapods/v/SCNVideoWriter.svg?style=flat)](http://cocoapods.org/pods/SCNVideoWriter) -[![License](https://img.shields.io/cocoapods/l/SCNVideoWriter.svg?style=flat)](http://cocoapods.org/pods/SCNVideoWriter) -[![Platform](https://img.shields.io/cocoapods/p/SCNVideoWriter.svg?style=flat)](http://cocoapods.org/pods/SCNVideoWriter) +[![Version](https://img.shields.io/cocoapods/v/SceneKitVideoRecorder.svg?style=flat)](http://cocoapods.org/pods/SceneKitVideoRecorder) +[![License](https://img.shields.io/cocoapods/l/SceneKitVideoRecorder.svg?style=flat)](http://cocoapods.org/pods/SceneKitVideoRecorder) +[![Platform](https://img.shields.io/cocoapods/p/SceneKitVideoRecorder.svg?style=flat)](http://cocoapods.org/pods/SceneKitVideoRecorder) ## Example @@ -12,17 +12,17 @@ To run the example project, clone the repo, and run `pod install` from the Examp ## Installation -SCNVideoWriter is available through [CocoaPods](http://cocoapods.org). To install +SceneKitVideoRecorder is available through [CocoaPods](http://cocoapods.org). To install it, simply add the following line to your Podfile: ```ruby -pod "SCNVideoWriter" +pod "SceneKitVideoRecorder" ``` ## Usage ``` -let writer = try! SCNVideoWriter(scene: sceneView.scene) +let writer = try! SceneKitVideoRecorder(scene: sceneView.scene) writer.startWriting() writer.finishWriting(completionHandler: { [weak self] (url) in print("done", url) @@ -30,9 +30,11 @@ writer.finishWriting(completionHandler: { [weak self] (url) in ``` ## Author +okaris, ok@okaris.com +## Inspired from noppefoxwolf, noppelabs@gmail.com ## License -SCNVideoWriter is available under the MIT license. See the LICENSE file for more info. +SceneKitVideoRecorder is available under the MIT license. See the LICENSE file for more info. diff --git a/SCNVideoWriter.podspec b/SCNVideoWriter.podspec deleted file mode 100644 index a51d121..0000000 --- a/SCNVideoWriter.podspec +++ /dev/null @@ -1,20 +0,0 @@ -Pod::Spec.new do |s| - s.name = 'SCNVideoWriter' - s.version = '0.5.0' - s.summary = 'A simple recorder for SceneKit.' - - s.description = <<-DESC -SCNVideoWriter is a simple video writer for SCNScene. -It's support iOS10 or later on Metal supported device. -And support video and overlay of ARKit. - DESC - - s.homepage = 'https://github.com/noppefoxwolf/SCNVideoWriter' - s.license = { :type => 'MIT', :file => 'LICENSE' } - s.author = { 'noppefoxwolf' => 'noppelabs@gmail.com' } - s.source = { :git => 'https://github.com/noppefoxwolf/SCNVideoWriter.git', :tag => s.version.to_s } - - s.ios.deployment_target = '10.0' - - s.source_files = 'SCNVideoWriter/Classes/**/*' -end diff --git a/SCNVideoWriter/Classes/Error.swift b/SCNVideoWriter/Classes/Error.swift deleted file mode 100644 index d509e56..0000000 --- a/SCNVideoWriter/Classes/Error.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// Error.swift -// Pods-SCNVideoWriter_Example -// -// Created by Tomoya Hirano on 2017/08/20. -// - -import UIKit - -extension SCNVideoWriter { - public struct VideoSizeError: Error {} -} - diff --git a/SCNVideoWriter/Classes/SCNVideoWriter.swift b/SCNVideoWriter/Classes/SCNVideoWriter.swift deleted file mode 100644 index 2b9ee93..0000000 --- a/SCNVideoWriter/Classes/SCNVideoWriter.swift +++ /dev/null @@ -1,119 +0,0 @@ -// -// SCNVideoWriter.swift -// Pods-SCNVideoWriter_Example -// -// Created by Tomoya Hirano on 2017/07/31. -// - -import UIKit -import SceneKit -import ARKit -import AVFoundation - -public class SCNVideoWriter { - private let writer: AVAssetWriter - private let input: AVAssetWriterInput - private let pixelBufferAdaptor: AVAssetWriterInputPixelBufferAdaptor - private let renderer: SCNRenderer - private let options: Options - - private let frameQueue = DispatchQueue(label: "com.noppelabs.SCNVideoWriter.frameQueue") - private static let renderQueue = DispatchQueue(label: "com.noppelabs.SCNVideoWriter.renderQueue") - private static let renderSemaphore = DispatchSemaphore(value: 3) - private var displayLink: CADisplayLink? = nil - private var initialTime: CFTimeInterval = 0.0 - private var currentTime: CFTimeInterval = 0.0 - - public var updateFrameHandler: ((_ image: UIImage, _ time: CMTime) -> Void)? = nil - private var finishedCompletionHandler: ((_ url: URL) -> Void)? = nil - - @available(iOS 11.0, *) - public convenience init?(withARSCNView view: ARSCNView, options: Options = .default) throws { - var options = options - options.renderSize = CGSize(width: view.bounds.width * view.contentScaleFactor, height: view.bounds.height * view.contentScaleFactor) - try self.init(scene: view.scene, options: options) - } - - public init?(scene: SCNScene, options: Options = .default) throws { - self.options = options - self.renderer = SCNRenderer(device: nil, options: nil) - renderer.scene = scene - - self.writer = try AVAssetWriter(outputURL: options.outputUrl, - fileType: options.fileType) - self.input = AVAssetWriterInput(mediaType: AVMediaTypeVideo, - outputSettings: options.assetWriterInputSettings) - self.pixelBufferAdaptor = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: input, - sourcePixelBufferAttributes: options.sourcePixelBufferAttributes) - prepare(with: options) - } - - private func prepare(with options: Options) { - if options.deleteFileIfExists { - FileController.delete(file: options.outputUrl) - } - writer.add(input) - } - - public func startWriting() { - SCNVideoWriter.renderQueue.async { [weak self] in - SCNVideoWriter.renderSemaphore.wait() - self?.startDisplayLink() - self?.startInputPipeline() - } - } - - public func finishWriting(completionHandler: (@escaping (_ url: URL) -> Void)) { - let outputUrl = options.outputUrl - input.markAsFinished() - writer.finishWriting(completionHandler: { [weak self] in - completionHandler(outputUrl) - self?.stopDisplayLink() - SCNVideoWriter.renderSemaphore.signal() - }) - } - - private func startDisplayLink() { - currentTime = 0.0 - initialTime = CFAbsoluteTimeGetCurrent() - displayLink = CADisplayLink(target: self, selector: #selector(updateDisplayLink)) - displayLink?.preferredFramesPerSecond = options.fps - displayLink?.add(to: .main, forMode: .commonModes) - } - - @objc private func updateDisplayLink() { - frameQueue.async { [weak self] in - guard let input = self?.input, input.isReadyForMoreMediaData else { return } - guard let pool = self?.pixelBufferAdaptor.pixelBufferPool else { return } - guard let renderSize = self?.options.renderSize else { return } - guard let videoSize = self?.options.videoSize else { return } - self?.renderSnapshot(with: pool, renderSize: renderSize, videoSize: videoSize) - } - } - - private func startInputPipeline() { - writer.startWriting() - writer.startSession(atSourceTime: kCMTimeZero) - input.requestMediaDataWhenReady(on: frameQueue, using: {}) - } - - private func renderSnapshot(with pool: CVPixelBufferPool, renderSize: CGSize, videoSize: CGSize) { - autoreleasepool { - currentTime = CFAbsoluteTimeGetCurrent() - initialTime - let image = renderer.snapshot(atTime: currentTime, with: renderSize, antialiasingMode: .multisampling4X) - guard let croppedImage = image.fill(at: videoSize) else { return } - guard let pixelBuffer = PixelBufferFactory.make(with: videoSize, from: croppedImage, usingBuffer: pool) else { return } - let value: Int64 = Int64(currentTime * CFTimeInterval(options.timeScale)) - let presentationTime = CMTimeMake(value, options.timeScale) - pixelBufferAdaptor.append(pixelBuffer, withPresentationTime: presentationTime) - updateFrameHandler?(croppedImage, presentationTime) - } - } - - private func stopDisplayLink() { - displayLink?.invalidate() - displayLink = nil - } -} - - diff --git a/SceneKitVideoRecorder.podspec b/SceneKitVideoRecorder.podspec new file mode 100644 index 0000000..6a17a2e --- /dev/null +++ b/SceneKitVideoRecorder.podspec @@ -0,0 +1,142 @@ +# +# Be sure to run `pod spec lint SceneKitVideoRecorder.podspec' to ensure this is a +# valid spec and to remove all comments including this before submitting the spec. +# +# To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html +# To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/ +# + +Pod::Spec.new do |s| + + # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # + # + # These will help people to find your library, and whilst it + # can feel like a chore to fill in it's definitely to your advantage. The + # summary should be tweet-length, and the description more in depth. + # + + s.name = "SceneKitVideoRecorder" + s.version = "0.8.0" + s.summary = "Record videos of SceneKit and ARKit" + + # This description is used to generate tags and improve search results. + # * Think: What does it do? Why did you write it? What is the focus? + # * Try to keep it short, snappy and to the point. + # * Write the description between the DESC delimiters below. + # * Finally, don't worry about the indent, CocoaPods strips it! + s.description = <<-DESC + SceneKitVideoRecorder records videos of SceneKit and ARKit. +It supports iOS10 or later on Metal supported devices. + DESC + + s.homepage = "https://github.com/svtek/SceneKitVideoRecorder" + # s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif" + + + # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # + # + # Licensing your code is important. See http://choosealicense.com for more info. + # CocoaPods will detect a license file if there is a named LICENSE* + # Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'. + # + + s.license = { :type => 'MIT', :file => 'LICENSE' } + # s.license = { :type => "MIT", :file => "FILE_LICENSE" } + + + # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # + # + # Specify the authors of the library, with email addresses. Email addresses + # of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also + # accepts just a name if you'd rather not provide an email address. + # + # Specify a social_media_url where others can refer to, for example a twitter + # profile URL. + # + + s.author = { "okaris" => "ok@okaris.com" } + # Or just: s.author = "Omer Karisman" + # s.authors = { "Omer Karisman" => "ok@okaris.com" } + s.social_media_url = "http://twitter.com/okarisman" + + # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― # + # + # If this Pod runs only on iOS or OS X, then specify the platform and + # the deployment target. You can optionally include the target after the platform. + # + + # s.platform = :ios + # s.platform = :ios, "5.0" + + # When using multiple platforms + # s.ios.deployment_target = "5.0" + # s.osx.deployment_target = "10.7" + # s.watchos.deployment_target = "2.0" + # s.tvos.deployment_target = "9.0" + + + # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # + # + # Specify the location from where the source should be retrieved. + # Supports git, hg, bzr, svn and HTTP. + # + + s.source = { :git => "https://github.com/svtek/SceneKitVideoRecorder.git", :tag => "#{s.version}" } + + + # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # + # + # CocoaPods is smart about how it includes source code. For source files + # giving a folder will include any swift, h, m, mm, c & cpp files. + # For header files it will include any header in the folder. + # Not including the public_header_files will make all headers public. + # + + s.ios.deployment_target = '10.0' + + s.source_files = "SceneKitVideoRecorder/Classes/**/*" + s.exclude_files = "Classes/Exclude" + + # s.public_header_files = "Classes/**/*.h" + + + # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # + # + # A list of resources included with the Pod. These are copied into the + # target bundle with a build phase script. Anything else will be cleaned. + # You can preserve files from being cleaned, please don't preserve + # non-essential files like tests, examples and documentation. + # + + # s.resource = "icon.png" + # s.resources = "Resources/*.png" + + # s.preserve_paths = "FilesToSave", "MoreFilesToSave" + + + # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # + # + # Link your library with frameworks, or libraries. Libraries do not include + # the lib prefix of their name. + # + + s.framework = 'Metal', 'CoreGraphics', 'QuartzCore' + # s.framework = "SomeFramework" + # s.frameworks = "SomeFramework", "AnotherFramework" + + # s.library = "iconv" + # s.libraries = "iconv", "xml2" + + + # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # + # + # If your library depends on compiler flags you can set them in the xcconfig hash + # where they will only apply to your library. If you depend on other Podspecs + # you can include multiple dependencies to ensure it works. + + # s.requires_arc = true + + # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" } + # s.dependency "JSONKit", "~> 1.4" + +end diff --git a/SCNVideoWriter/Assets/.gitkeep b/SceneKitVideoRecorder/Assets/.gitkeep similarity index 100% rename from SCNVideoWriter/Assets/.gitkeep rename to SceneKitVideoRecorder/Assets/.gitkeep diff --git a/SCNVideoWriter/Classes/.gitkeep b/SceneKitVideoRecorder/Classes/.gitkeep similarity index 100% rename from SCNVideoWriter/Classes/.gitkeep rename to SceneKitVideoRecorder/Classes/.gitkeep diff --git a/SceneKitVideoRecorder/Classes/Error.swift b/SceneKitVideoRecorder/Classes/Error.swift new file mode 100644 index 0000000..62ea2d6 --- /dev/null +++ b/SceneKitVideoRecorder/Classes/Error.swift @@ -0,0 +1,12 @@ +// +// Error.swift +// +// Created by Omer Karisman on 2017/08/29. +// + +import UIKit + +extension SceneKitVideoRecorder { + public struct VideoSizeError: Error {} +} + diff --git a/SCNVideoWriter/Classes/FileController.swift b/SceneKitVideoRecorder/Classes/FileController.swift similarity index 75% rename from SCNVideoWriter/Classes/FileController.swift rename to SceneKitVideoRecorder/Classes/FileController.swift index d6863c7..7e40b9f 100644 --- a/SCNVideoWriter/Classes/FileController.swift +++ b/SceneKitVideoRecorder/Classes/FileController.swift @@ -1,8 +1,7 @@ // // FileController.swift -// Pods-SCNVideoWriter_Example // -// Created by Tomoya Hirano on 2017/08/02. +// Created by Omer Karisman on 2017/08/29. // import UIKit diff --git a/SCNVideoWriter/Classes/Options.swift b/SceneKitVideoRecorder/Classes/Options.swift similarity index 92% rename from SCNVideoWriter/Classes/Options.swift rename to SceneKitVideoRecorder/Classes/Options.swift index c8df7cf..5cf1331 100644 --- a/SCNVideoWriter/Classes/Options.swift +++ b/SceneKitVideoRecorder/Classes/Options.swift @@ -1,14 +1,13 @@ // // Options.swift -// Pods-SCNVideoWriter_Example // -// Created by Tomoya Hirano on 2017/08/20. +// Created by Omer Karisman on 2017/08/29. // import UIKit import AVFoundation -extension SCNVideoWriter { +extension SceneKitVideoRecorder { public struct Options { public var timeScale: Int32 public var renderSize: CGSize diff --git a/SCNVideoWriter/Classes/PixelBufferFactory.swift b/SceneKitVideoRecorder/Classes/PixelBufferFactory.swift similarity index 94% rename from SCNVideoWriter/Classes/PixelBufferFactory.swift rename to SceneKitVideoRecorder/Classes/PixelBufferFactory.swift index 7e348c1..da4cef0 100644 --- a/SCNVideoWriter/Classes/PixelBufferFactory.swift +++ b/SceneKitVideoRecorder/Classes/PixelBufferFactory.swift @@ -1,8 +1,7 @@ // // PixelBufferFactory.swift -// Pods-SCNVideoWriter_Example // -// Created by Tomoya Hirano on 2017/08/02. +// Created by Omer Karisman on 2017/08/29. // import UIKit diff --git a/SceneKitVideoRecorder/Classes/SceneKitVideoRecorder.swift b/SceneKitVideoRecorder/Classes/SceneKitVideoRecorder.swift new file mode 100644 index 0000000..b211a77 --- /dev/null +++ b/SceneKitVideoRecorder/Classes/SceneKitVideoRecorder.swift @@ -0,0 +1,156 @@ +// +// SceneKitVideoRecorder.swift +// +// Created by Omer Karisman on 2017/08/29. +// +#if arch(i386) || arch(x86_64) + import UIKit + import SceneKit + public class SceneKitVideoRecorder { + public init?(scene: SCNView, options: Options = .default) throws {} + public func startWriting() {} + public func finishWriting(completionHandler: (@escaping (_ url: URL) -> Void)) {} + } + //Metal does not work in simulator :( +#else + + import UIKit + import SceneKit + import ARKit + import AVFoundation + import Metal + import CoreImage + + public class SceneKitVideoRecorder { + private let writer: AVAssetWriter + private let input: AVAssetWriterInput + private let pixelBufferAdaptor: AVAssetWriterInputPixelBufferAdaptor + private let options: Options + + private let frameQueue = DispatchQueue(label: "com.svtek.SceneKitVideoRecorder.frameQueue") + private static let renderQueue = DispatchQueue(label: "com.svtek.SceneKitVideoRecorder.renderQueue") + private static let renderSemaphore = DispatchSemaphore(value: 3) + private var displayLink: CADisplayLink? = nil + private var initialTime: CFTimeInterval = 0.0 + private var currentTime: CFTimeInterval = 0.0 + + private var sceneView: SCNView + private var metalLayer: CAMetalLayer + + public var updateFrameHandler: ((_ image: UIImage, _ time: CMTime) -> Void)? = nil + private var finishedCompletionHandler: ((_ url: URL) -> Void)? = nil + private let context:CIContext + + @available(iOS 11.0, *) + public convenience init?(withARSCNView view: ARSCNView, options: Options = .default) throws { + var options = options + options.renderSize = CGSize(width: view.bounds.width * view.contentScaleFactor, height: view.bounds.height * view.contentScaleFactor) + try self.init(scene: view, options: options) + } + + public init?(scene: SCNView, options: Options = .default) throws { + + self.sceneView = scene + + self.context = CIContext.init(mtlDevice: MTLCreateSystemDefaultDevice()!) + + self.metalLayer = (sceneView.layer as? CAMetalLayer)! + self.metalLayer.framebufferOnly = false + + self.options = options + + self.writer = try AVAssetWriter(outputURL: options.outputUrl, + fileType: options.fileType) + self.input = AVAssetWriterInput(mediaType: AVMediaTypeVideo, + outputSettings: options.assetWriterInputSettings) + self.pixelBufferAdaptor = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: input, + sourcePixelBufferAttributes: options.sourcePixelBufferAttributes) + prepare(with: options) + } + + private func prepare(with options: Options) { + if options.deleteFileIfExists { + FileController.delete(file: options.outputUrl) + } + writer.add(input) + } + + public func startWriting() { + SceneKitVideoRecorder.renderQueue.async { [weak self] in + SceneKitVideoRecorder.renderSemaphore.wait() + self?.startDisplayLink() + self?.startInputPipeline() + } + } + + public func finishWriting(completionHandler: (@escaping (_ url: URL) -> Void)) { + let outputUrl = options.outputUrl + input.markAsFinished() + writer.finishWriting(completionHandler: { [weak self] in + completionHandler(outputUrl) + self?.stopDisplayLink() + SceneKitVideoRecorder.renderSemaphore.signal() + }) + } + + private func startDisplayLink() { + currentTime = 0.0 + initialTime = CFAbsoluteTimeGetCurrent() + displayLink = CADisplayLink(target: self, selector: #selector(updateDisplayLink)) + displayLink?.preferredFramesPerSecond = options.fps + displayLink?.add(to: .main, forMode: .commonModes) + } + + @objc private func updateDisplayLink() { + frameQueue.async { [weak self] in + guard let input = self?.input, input.isReadyForMoreMediaData else { return } + guard let pool = self?.pixelBufferAdaptor.pixelBufferPool else { return } + guard let renderSize = self?.options.renderSize else { return } + guard let videoSize = self?.options.videoSize else { return } + self?.renderSnapshot(with: pool, renderSize: renderSize, videoSize: videoSize) + } + } + + private func startInputPipeline() { + writer.startWriting() + writer.startSession(atSourceTime: kCMTimeZero) + input.requestMediaDataWhenReady(on: frameQueue, using: {}) + } + + private func renderSnapshot(with pool: CVPixelBufferPool, renderSize: CGSize, videoSize: CGSize) { + autoreleasepool { + + let texture = metalLayer.nextDrawable()?.texture + let ciimage = CIImage(mtlTexture: texture!, options: nil) + let image = convert(ciImage: ciimage!) + + currentTime = CFAbsoluteTimeGetCurrent() - initialTime + + let actualFramesPerSecond = 1 / ((displayLink?.targetTimestamp)! - (displayLink?.timestamp)!) + //`guard let croppedImage = image.fill(at: videoSize) else { return } + guard let pixelBuffer = PixelBufferFactory.make(with: videoSize, from: image, usingBuffer: pool) else { return } + let value: Int64 = Int64(currentTime * CFTimeInterval(options.timeScale)) + let presentationTime = CMTimeMake(value, options.timeScale) + pixelBufferAdaptor.append(pixelBuffer, withPresentationTime: presentationTime) + updateFrameHandler?(image, presentationTime) + } + } + + func convert(ciImage:CIImage) -> UIImage + { + var flippedImage: CIImage = ciImage.applying(CGAffineTransform(scaleX: 1, y: -1)) + flippedImage = flippedImage.applying(CGAffineTransform(translationX: 0, y: ciImage.extent.size.height)) + let cgImage:CGImage = context.createCGImage(flippedImage, from: flippedImage.extent)! + let image:UIImage = UIImage.init(cgImage: cgImage) + return image + } + + private func stopDisplayLink() { + displayLink?.invalidate() + displayLink = nil + } + } + +#endif + + diff --git a/SCNVideoWriter/Classes/UIImage+Extensions.swift b/SceneKitVideoRecorder/Classes/UIImage+Extensions.swift similarity index 95% rename from SCNVideoWriter/Classes/UIImage+Extensions.swift rename to SceneKitVideoRecorder/Classes/UIImage+Extensions.swift index 4262f04..5b88b17 100644 --- a/SCNVideoWriter/Classes/UIImage+Extensions.swift +++ b/SceneKitVideoRecorder/Classes/UIImage+Extensions.swift @@ -1,8 +1,7 @@ // // UIImage+Extensions.swift -// Pods-SCNVideoWriter_Example // -// Created by Tomoya Hirano on 2017/08/10. +// Created by Omer Karisman on 2017/08/29. // import UIKit