├── .gitignore ├── Examples ├── SimpleFourSquareVideo │ ├── SimpleFourSquareVideo.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ ├── xcshareddata │ │ │ └── xcschemes │ │ │ │ └── SimpleFourSquareVideo.xcscheme │ │ └── xcuserdata │ │ │ └── renzhumacro.xcuserdatad │ │ │ └── xcschemes │ │ │ └── xcschememanagement.plist │ └── SimpleFourSquareVideo │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── SceneDelegate.swift │ │ ├── ViewController.swift │ │ ├── cute.mp4 │ │ ├── movie.mov │ │ ├── movie2.mp4 │ │ ├── movie3.mp4 │ │ └── out.mp4 ├── SimpleRealtimeFilterPlayback │ ├── SimpleRealtimeFilterPlayback.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── SimpleRealtimeFilterPlayback.xcscheme │ └── SimpleRealtimeFilterPlayback │ │ ├── 853.mp4 │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── PlaygroundVC.swift │ │ ├── SceneDelegate.swift │ │ ├── ViewController.swift │ │ └── cute.mp4 ├── SimpleVideoAnimation │ ├── Podfile │ ├── Podfile.lock │ ├── Pods │ │ ├── Manifest.lock │ │ ├── Pods.xcodeproj │ │ │ └── project.pbxproj │ │ ├── PryntTrimmerView │ │ │ ├── LICENSE │ │ │ ├── PryntTrimmerView │ │ │ │ └── Classes │ │ │ │ │ ├── Cropper │ │ │ │ │ ├── CropMaskView.swift │ │ │ │ │ ├── VideoCropView.swift │ │ │ │ │ └── VideoScrollView.swift │ │ │ │ │ ├── Parents │ │ │ │ │ ├── AVAssetTimeSelector.swift │ │ │ │ │ └── AssetVideoScrollView.swift │ │ │ │ │ ├── ThumbSelectorView.swift │ │ │ │ │ └── Trimmer │ │ │ │ │ ├── HandlerView.swift │ │ │ │ │ └── PryntTrimmerView.swift │ │ │ └── README.md │ │ └── Target Support Files │ │ │ ├── Pods-SimpleVideoAnimation │ │ │ ├── Pods-SimpleVideoAnimation-Info.plist │ │ │ ├── Pods-SimpleVideoAnimation-acknowledgements.markdown │ │ │ ├── Pods-SimpleVideoAnimation-acknowledgements.plist │ │ │ ├── Pods-SimpleVideoAnimation-dummy.m │ │ │ ├── Pods-SimpleVideoAnimation-frameworks-Debug-input-files.xcfilelist │ │ │ ├── Pods-SimpleVideoAnimation-frameworks-Debug-output-files.xcfilelist │ │ │ ├── Pods-SimpleVideoAnimation-frameworks-Release-input-files.xcfilelist │ │ │ ├── Pods-SimpleVideoAnimation-frameworks-Release-output-files.xcfilelist │ │ │ ├── Pods-SimpleVideoAnimation-frameworks.sh │ │ │ ├── Pods-SimpleVideoAnimation-umbrella.h │ │ │ ├── Pods-SimpleVideoAnimation.debug.xcconfig │ │ │ ├── Pods-SimpleVideoAnimation.modulemap │ │ │ └── Pods-SimpleVideoAnimation.release.xcconfig │ │ │ └── PryntTrimmerView │ │ │ ├── PryntTrimmerView-Info.plist │ │ │ ├── PryntTrimmerView-dummy.m │ │ │ ├── PryntTrimmerView-prefix.pch │ │ │ ├── PryntTrimmerView-umbrella.h │ │ │ ├── PryntTrimmerView.modulemap │ │ │ └── PryntTrimmerView.xcconfig │ ├── SimpleVIdeoAnimation.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── SimpleVideoAnimation.xcscheme │ ├── SimpleVIdeoAnimation │ │ ├── 853.mp4 │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── NavigateViewController.swift │ │ ├── SceneDelegate.swift │ │ ├── ViewController.swift │ │ └── cute.mp4 │ └── SimpleVideoAnimation.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── SimpleVideoEditor │ ├── SimpleVideoEditor.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ ├── xcshareddata │ │ │ └── xcschemes │ │ │ │ └── SimpleVideoEditor.xcscheme │ │ └── xcuserdata │ │ │ └── renzhumacro.xcuserdatad │ │ │ └── xcschemes │ │ │ └── xcschememanagement.plist │ └── SimpleVideoEditor │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Images.xcassets │ │ ├── Contents.json │ │ ├── gallery_picker_camera.imageset │ │ │ ├── Contents.json │ │ │ ├── baseline_camera_alt_black_24pt_1x.png │ │ │ ├── baseline_camera_alt_black_24pt_2x.png │ │ │ └── baseline_camera_alt_black_24pt_3x.png │ │ ├── gallery_picker_cloud.imageset │ │ │ ├── Contents.json │ │ │ ├── baseline_cloud_black_24pt_1x.png │ │ │ ├── baseline_cloud_black_24pt_2x.png │ │ │ └── baseline_cloud_black_24pt_3x.png │ │ └── gallery_picker_library.imageset │ │ │ ├── Contents.json │ │ │ ├── baseline_photo_library_black_24pt_1x.png │ │ │ ├── baseline_photo_library_black_24pt_2x.png │ │ │ └── baseline_photo_library_black_24pt_3x.png │ │ ├── Info.plist │ │ ├── Model │ │ └── ResourceItem.swift │ │ ├── ResourceItemEditView.swift │ │ ├── ResourceItemEditView.xib │ │ ├── ResourceItemTableViewCell.swift │ │ ├── SceneDelegate.swift │ │ ├── SimpleVideoEditor-Bridging-Header.h │ │ ├── Vender │ │ ├── DynamicBlurView │ │ │ ├── BlurLayer.swift │ │ │ ├── CGContext+CGImage.swift │ │ │ ├── CGImage+Accelerate.swift │ │ │ ├── CaptureQuality.swift │ │ │ ├── DynamicBlurView.h │ │ │ ├── DynamicBlurView.swift │ │ │ ├── TrackingMode.swift │ │ │ └── UIImage+Blur.swift │ │ ├── PopupDialog │ │ │ ├── InteractiveTransition.swift │ │ │ ├── PopupDialog+Keyboard.swift │ │ │ ├── PopupDialog.swift │ │ │ ├── PopupDialogButton.swift │ │ │ ├── PopupDialogContainerView.swift │ │ │ ├── PopupDialogDefaultButtons.swift │ │ │ ├── PopupDialogDefaultView.swift │ │ │ ├── PopupDialogDefaultViewController.swift │ │ │ ├── PopupDialogOverlayView.swift │ │ │ ├── PresentationController.swift │ │ │ ├── PresentationManager.swift │ │ │ ├── TransitionAnimations.swift │ │ │ ├── TransitionAnimator.swift │ │ │ ├── UIImageView+Calculations.swift │ │ │ ├── UIView+Animations.swift │ │ │ └── UIViewController+Visibility.swift │ │ └── TableViewDragger │ │ │ ├── ScrollRects.swift │ │ │ ├── TableViewDragger.swift │ │ │ ├── TableViewDraggerCell.swift │ │ │ └── UIScrollViewExtension.swift │ │ ├── ViewController+MetalVideoProcessPlayerDelegate.swift │ │ ├── ViewController+UIGestureRecognizerDelegate.swift │ │ ├── ViewController+UIImagePickerControllerDelegate.swift │ │ ├── ViewController+UITableViewDelegate.swift │ │ ├── ViewController.swift │ │ ├── cute.mp4 │ │ └── movie.mov ├── SimpleVideoExport │ ├── SimpleVideoExport.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ ├── xcshareddata │ │ │ └── xcschemes │ │ │ │ └── SimpleVideoExport.xcscheme │ │ └── xcuserdata │ │ │ └── renzhumacro.xcuserdatad │ │ │ └── xcschemes │ │ │ └── xcschememanagement.plist │ └── SimpleVideoExport │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── SceneDelegate.swift │ │ ├── SimpleVideoExport-Bridging-Header.h │ │ ├── UI │ │ ├── MBProgressHUD.h │ │ ├── MBProgressHUD.m │ │ ├── MBProgressHUDExtension.swift │ │ ├── ProgressHUD.bundle │ │ │ ├── progresshud-error@2x.png │ │ │ └── progresshud-success@2x.png │ │ ├── ProgressHUD.h │ │ └── ProgressHUD.m │ │ └── ViewController.swift ├── SimpleVideoTransition │ ├── SimpleVideoTransition.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── SimpleVideoTransition.xcscheme │ └── SimpleVideoTransition │ │ ├── 853.mp4 │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── Model │ │ └── ResourceItem.swift │ │ ├── NaviViewController.swift │ │ ├── ResourceItemEditView.swift │ │ ├── ResourceItemEditView.xib │ │ ├── ResourceItemTableViewCell.swift │ │ ├── SceneDelegate.swift │ │ ├── SimpleVideoEditor-Bridging-Header.h │ │ ├── Vender │ │ ├── DynamicBlurView │ │ │ ├── BlurLayer.swift │ │ │ ├── CGContext+CGImage.swift │ │ │ ├── CGImage+Accelerate.swift │ │ │ ├── CaptureQuality.swift │ │ │ ├── DynamicBlurView.h │ │ │ ├── DynamicBlurView.swift │ │ │ ├── TrackingMode.swift │ │ │ └── UIImage+Blur.swift │ │ ├── PopupDialog │ │ │ ├── InteractiveTransition.swift │ │ │ ├── PopupDialog+Keyboard.swift │ │ │ ├── PopupDialog.swift │ │ │ ├── PopupDialogButton.swift │ │ │ ├── PopupDialogContainerView.swift │ │ │ ├── PopupDialogDefaultButtons.swift │ │ │ ├── PopupDialogDefaultView.swift │ │ │ ├── PopupDialogDefaultViewController.swift │ │ │ ├── PopupDialogOverlayView.swift │ │ │ ├── PresentationController.swift │ │ │ ├── PresentationManager.swift │ │ │ ├── TransitionAnimations.swift │ │ │ ├── TransitionAnimator.swift │ │ │ ├── UIImageView+Calculations.swift │ │ │ ├── UIView+Animations.swift │ │ │ └── UIViewController+Visibility.swift │ │ └── TableViewDragger │ │ │ ├── ScrollRects.swift │ │ │ ├── TableViewDragger.swift │ │ │ ├── TableViewDraggerCell.swift │ │ │ └── UIScrollViewExtension.swift │ │ ├── ViewController+MetalVideoProcessPlayerDelegate.swift │ │ ├── ViewController+UIGestureRecognizerDelegate.swift │ │ ├── ViewController+UIImagePickerControllerDelegate.swift │ │ ├── ViewController+UITableViewDelegate.swift │ │ ├── ViewController.swift │ │ ├── cute.mp4 │ │ └── movie.mov └── SimpleVideoTransitionSwitch │ ├── SimpleVideoTransition │ ├── 853.mp4 │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Images.xcassets │ │ ├── Contents.json │ │ ├── gallery_picker_camera.imageset │ │ │ ├── Contents.json │ │ │ ├── baseline_camera_alt_black_24pt_1x.png │ │ │ ├── baseline_camera_alt_black_24pt_2x.png │ │ │ └── baseline_camera_alt_black_24pt_3x.png │ │ ├── gallery_picker_cloud.imageset │ │ │ ├── Contents.json │ │ │ ├── baseline_cloud_black_24pt_1x.png │ │ │ ├── baseline_cloud_black_24pt_2x.png │ │ │ └── baseline_cloud_black_24pt_3x.png │ │ └── gallery_picker_library.imageset │ │ │ ├── Contents.json │ │ │ ├── baseline_photo_library_black_24pt_1x.png │ │ │ ├── baseline_photo_library_black_24pt_2x.png │ │ │ └── baseline_photo_library_black_24pt_3x.png │ ├── Info.plist │ ├── Model │ │ └── ResourceItem.swift │ ├── ResourceItemEditView.swift │ ├── ResourceItemEditView.xib │ ├── ResourceItemTableViewCell.swift │ ├── SceneDelegate.swift │ ├── SimpleVideoEditor-Bridging-Header.h │ ├── Vender │ │ ├── DynamicBlurView │ │ │ ├── BlurLayer.swift │ │ │ ├── CGContext+CGImage.swift │ │ │ ├── CGImage+Accelerate.swift │ │ │ ├── CaptureQuality.swift │ │ │ ├── DynamicBlurView.h │ │ │ ├── DynamicBlurView.swift │ │ │ ├── TrackingMode.swift │ │ │ └── UIImage+Blur.swift │ │ ├── PopupDialog │ │ │ ├── InteractiveTransition.swift │ │ │ ├── PopupDialog+Keyboard.swift │ │ │ ├── PopupDialog.swift │ │ │ ├── PopupDialogButton.swift │ │ │ ├── PopupDialogContainerView.swift │ │ │ ├── PopupDialogDefaultButtons.swift │ │ │ ├── PopupDialogDefaultView.swift │ │ │ ├── PopupDialogDefaultViewController.swift │ │ │ ├── PopupDialogOverlayView.swift │ │ │ ├── PresentationController.swift │ │ │ ├── PresentationManager.swift │ │ │ ├── TransitionAnimations.swift │ │ │ ├── TransitionAnimator.swift │ │ │ ├── UIImageView+Calculations.swift │ │ │ ├── UIView+Animations.swift │ │ │ └── UIViewController+Visibility.swift │ │ └── TableViewDragger │ │ │ ├── ScrollRects.swift │ │ │ ├── TableViewDragger.swift │ │ │ ├── TableViewDraggerCell.swift │ │ │ └── UIScrollViewExtension.swift │ ├── ViewController+MetalVideoProcessPlayerDelegate.swift │ ├── ViewController+UIGestureRecognizerDelegate.swift │ ├── ViewController+UIImagePickerControllerDelegate.swift │ ├── ViewController+UITableViewDelegate.swift │ ├── ViewController.swift │ ├── ViewController_BACKUP_17810.swift │ ├── ViewController_BASE_17810.swift │ ├── ViewController_LOCAL_17810.swift │ ├── ViewController_REMOTE_17810.swift │ ├── cute.mp4 │ └── movie.mov │ └── SimpleVideoTransitionSwitch.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ ├── renzhumacro.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ └── ruanshengqiang.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ └── xcshareddata │ └── xcschemes │ └── SimpleVideoTransition.xcscheme ├── LICENSE ├── MetalVideoProcess.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── MetalVideoProcess.xcscheme ├── MetalVideoProcess ├── Info.plist ├── MetalVideoProcess.h ├── Vender │ ├── Editor │ │ ├── Core │ │ │ ├── Audio │ │ │ │ ├── AudioMixer.swift │ │ │ │ ├── AudioProcessingChain.swift │ │ │ │ └── AudioProcessingTapHolder.swift │ │ │ ├── CompositionGenerator.swift │ │ │ ├── Model │ │ │ │ ├── AudioTransition.swift │ │ │ │ ├── CompositionProvider.swift │ │ │ │ ├── Timeline.swift │ │ │ │ └── VideoTransition.swift │ │ │ └── Video │ │ │ │ ├── VideoCompositionInstruction.swift │ │ │ │ └── VideoCompositor.swift │ │ ├── Resource │ │ │ └── black_empty.mp4 │ │ ├── Track │ │ │ ├── Configuration │ │ │ │ └── TrackConfiguration.swift │ │ │ ├── ImageCompositionGroupProvider.swift │ │ │ ├── ImageOverlayItem.swift │ │ │ ├── Resource │ │ │ │ ├── AVAssetReaderImageResource.swift │ │ │ │ ├── AVAssetReverseImageResource.swift │ │ │ │ ├── AVAssetTrackResource.swift │ │ │ │ ├── ImageResource.swift │ │ │ │ ├── PHAssetImageResource.swift │ │ │ │ ├── PHAssetLivePhotoResource.swift │ │ │ │ ├── PHAssetTrackResource.swift │ │ │ │ └── Resource.swift │ │ │ └── TrackItem.swift │ │ └── Uitl │ │ │ ├── CGMathFunctions.swift │ │ │ ├── CMTimeExtensition.swift │ │ │ ├── CoreImageExtension.swift │ │ │ ├── ImageGeneratorExtension.swift │ │ │ ├── Log.swift │ │ │ ├── TimeRangeExtension.swift │ │ │ └── TimingFunctionFactory.swift │ └── Render │ │ ├── Base │ │ ├── Color.swift │ │ ├── ImageOrientation.swift │ │ ├── Matrix.swift │ │ ├── MetalRendering.swift │ │ ├── MetalRenderingDevice.swift │ │ ├── OperationShaderTypes.h │ │ ├── Pipeline.swift │ │ ├── Position.swift │ │ ├── ShaderUniformSettings.swift │ │ ├── Size.swift │ │ ├── Texture.swift │ │ ├── Timestamp.swift │ │ └── default.metal │ │ ├── Inputs │ │ ├── Camera.swift │ │ ├── ImageGenerator.swift │ │ ├── PictureInput.swift │ │ ├── SolidColorGenerator.swift │ │ ├── YUVToRGBConversion.metal │ │ └── YUVToRGBConversion.swift │ │ └── Outputs │ │ ├── PictureOutput.swift │ │ └── RenderView.swift └── VideoProcess │ ├── Base │ ├── MetalVideoProcessCompositionRequestCache.swift │ ├── MetalVideoProcessCompositor.swift │ ├── MetalVideoProcessMotion.swift │ ├── MetalVideoProcessOperation.swift │ └── MetalVideoProcessTransition.swift │ ├── Filters │ ├── MetalVideoProcessBackground.swift │ ├── MetalVideoProcessBeautyFilter.metal │ ├── MetalVideoProcessBeautyFilter.swift │ ├── MetalVideoProcessBlendFilter.metal │ ├── MetalVideoProcessBlendFilter.swift │ ├── MetalVideoProcessColorFilter.metal │ ├── MetalVideoProcessColorFilter.swift │ ├── MetalVideoProcessFilterGroup.swift │ ├── MetalVideoProcessGaussianBlurFilter.swift │ ├── MetalVideoProcessLuminance.metal │ ├── MetalVideoProcessLuminance.swift │ ├── MetalVideoProcessTransformFilter.metal │ └── MetalVideoProcessTransformFilter.swift │ ├── MetalVideoEditor.swift │ ├── MetalVideoProcessMovieWriter.swift │ ├── MetalVideoProcessPlayer+CompositorDelegate.swift │ ├── MetalVideoProcessPlayer.swift │ ├── MetalVideoProcessRenderView.swift │ ├── Motions │ ├── MetalVideoProcessFadeInMotion.swift │ ├── MetalVideoProcessFadeMotion.metal │ ├── MetalVideoProcessFadeOutMotion.swift │ ├── MetalVideoProcessMirrorRotateMotion.metal │ ├── MetalVideoProcessMirrorRotateMotion.swift │ ├── MetalVideoProcessMoveDownMotion.metal │ ├── MetalVideoProcessMoveDownMotion.swift │ ├── MetalVideoProcessMoveLeftMotion.metal │ ├── MetalVideoProcessMoveLeftMotion.swift │ ├── MetalVideoProcessMoveRightMotion.metal │ ├── MetalVideoProcessMoveRightMotion.swift │ ├── MetalVideoProcessMoveUpMotion.metal │ ├── MetalVideoProcessMoveUpMotion.swift │ ├── MetalVideoProcessPendulumMotion.metal │ ├── MetalVideoProcessPendulumMotion.swift │ ├── MetalVideoProcessRightDropMotion.metal │ ├── MetalVideoProcessRightDropMotion.swift │ ├── MetalVideoProcessRotateInRightMotion.metal │ ├── MetalVideoProcessRotateInRightMotion.swift │ ├── MetalVideoProcessRotateMotion.metal │ ├── MetalVideoProcessRotateMotion.swift │ ├── MetalVideoProcessSlimZoomInMotion.metal │ ├── MetalVideoProcessSlimZoomInMotion.swift │ ├── MetalVideoProcessSwirlMotion.metal │ ├── MetalVideoProcessSwirlMotion.swift │ ├── MetalVideoProcessUpDropMotion.metal │ ├── MetalVideoProcessUpDropMotion.swift │ ├── MetalVideoProcessUpMoveInBlurIIMotion.metal │ ├── MetalVideoProcessUpMoveInBlurIIMotion.swift │ ├── MetalVideoProcessUpMoveInBlurMotion.metal │ ├── MetalVideoProcessUpMoveInBlurMotion.swift │ ├── MetalVideoProcessWiperMotion.metal │ ├── MetalVideoProcessWiperMotion.swift │ ├── MetalVideoProcessZoomInBlurMotion.metal │ ├── MetalVideoProcessZoomInBlurMotion.swift │ ├── MetalVideoProcessZoomInMotion.metal │ ├── MetalVideoProcessZoomInMotion.swift │ ├── MetalVideoProcessZoomOutBlurMotion.metal │ ├── MetalVideoProcessZoomOutBlurMotion.swift │ ├── MetalVideoProcessZoomOutMotion.metal │ └── MetalVideoProcessZoomOutMotion.swift │ └── Transitions │ ├── MetalVideoProcessBurnTransition.metal │ ├── MetalVideoProcessBurnTransition.swift │ ├── MetalVideoProcessCircleEraseTransition.metal │ ├── MetalVideoProcessCircleEraseTransition.swift │ ├── MetalVideoProcessCubeTransition.metal │ ├── MetalVideoProcessCubeTransition.swift │ ├── MetalVideoProcessEraseDownTransition.metal │ ├── MetalVideoProcessEraseDownTransition.swift │ ├── MetalVideoProcessEraseLeftTransition.metal │ ├── MetalVideoProcessEraseLeftTransition.swift │ ├── MetalVideoProcessEraseRightTransition.metal │ ├── MetalVideoProcessEraseRightTransition.swift │ ├── MetalVideoProcessEraseUpTransition.metal │ ├── MetalVideoProcessEraseUpTransition.swift │ ├── MetalVideoProcessFadeTransition.metal │ ├── MetalVideoProcessFadeTransition.swift │ ├── MetalVideoProcessMirrorRotateTransition.metal │ ├── MetalVideoProcessMirrorRotateTransition.swift │ ├── MetalVideoProcessMorphTransition.metal │ ├── MetalVideoProcessMorphTransition.swift │ ├── MetalVideoProcessReflectTransition.metal │ ├── MetalVideoProcessReflectTransition.swift │ ├── MetalVideoProcessShanBaiTransition.metal │ ├── MetalVideoProcessShanBaiTransition.swift │ ├── MetalVideoProcessVerticalUpGlitchTransition.metal │ └── MetalVideoProcessVerticalUpGlitchTransition.swift ├── README.md └── Readme ├── Layer.png └── videoTransitionDesign.png /.gitignore: -------------------------------------------------------------------------------- 1 | MetalVideoProcess.xcodeproj/project.xcworkspace/xcshareddata 2 | MetalVideoProcess.xcodeproj/project.xcworkspace/xcuserdata 3 | MetalVideoProcess.xcodeproj/xcuserdata 4 | Examples/SimpleRealtimeFilterPlayback/SimpleRealtimeFilterPlayback.xcodeproj/project.xcworkspace/xcuserdata 5 | Examples/SimpleFourSquareVideo/SimpleFourSquareVideo.xcodeproj/project.xcworkspace/xcuserdata/renzhumacro.xcuserdatad 6 | Examples/SimpleVideoExport/SimpleVideoExport.xcodeproj/project.xcworkspace/xcuserdata 7 | Examples/SimpleRealtimeFilterPlayback/SimpleRealtimeFilterPlayback.xcodeproj/xcuserdata 8 | Examples/SimpleVideoTransition/SimpleVideoTransition.xcodeproj/project.xcworkspace/xcuserdata/renzhumacro.xcuserdatad 9 | Examples/SimpleVideoTransition/SimpleVideoTransition.xcodeproj/xcuserdata/renzhumacro.xcuserdatad 10 | Examples/SimpleVideoAnimation/Pods/Pods.xcodeproj/xcuserdata/renzhumacro.xcuserdatad 11 | Examples/SimpleVideoAnimation/SimpleVIdeoAnimation.xcodeproj/project.xcworkspace/xcuserdata 12 | Examples/SimpleVideoAnimation/SimpleVIdeoAnimation.xcodeproj/xcuserdata 13 | Examples/SimpleVideoAnimation/SimpleVideoAnimation.xcworkspace/xcuserdata 14 | Examples/SimpleVideoTransitionSwitch/SimpleVideoTransitionSwitch.xcodeproj/xcuserdata 15 | Examples/SimpleVideoEditor/SimpleVideoEditor.xcodeproj/project.xcworkspace/xcuserdata 16 | -------------------------------------------------------------------------------- /Examples/SimpleFourSquareVideo/SimpleFourSquareVideo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Examples/SimpleFourSquareVideo/SimpleFourSquareVideo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Examples/SimpleFourSquareVideo/SimpleFourSquareVideo.xcodeproj/xcuserdata/renzhumacro.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SimpleFourSquareVideo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 6ADB07EB24AF120E0010A817 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Examples/SimpleFourSquareVideo/SimpleFourSquareVideo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SimpleFourSquareVideo 4 | // 5 | // Created by RenZhu Macro on 2020/7/3. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /Examples/SimpleFourSquareVideo/SimpleFourSquareVideo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Examples/SimpleFourSquareVideo/SimpleFourSquareVideo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Examples/SimpleFourSquareVideo/SimpleFourSquareVideo/cute.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleFourSquareVideo/SimpleFourSquareVideo/cute.mp4 -------------------------------------------------------------------------------- /Examples/SimpleFourSquareVideo/SimpleFourSquareVideo/movie.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleFourSquareVideo/SimpleFourSquareVideo/movie.mov -------------------------------------------------------------------------------- /Examples/SimpleFourSquareVideo/SimpleFourSquareVideo/movie2.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleFourSquareVideo/SimpleFourSquareVideo/movie2.mp4 -------------------------------------------------------------------------------- /Examples/SimpleFourSquareVideo/SimpleFourSquareVideo/movie3.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleFourSquareVideo/SimpleFourSquareVideo/movie3.mp4 -------------------------------------------------------------------------------- /Examples/SimpleFourSquareVideo/SimpleFourSquareVideo/out.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleFourSquareVideo/SimpleFourSquareVideo/out.mp4 -------------------------------------------------------------------------------- /Examples/SimpleRealtimeFilterPlayback/SimpleRealtimeFilterPlayback.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Examples/SimpleRealtimeFilterPlayback/SimpleRealtimeFilterPlayback.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Examples/SimpleRealtimeFilterPlayback/SimpleRealtimeFilterPlayback/853.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleRealtimeFilterPlayback/SimpleRealtimeFilterPlayback/853.mp4 -------------------------------------------------------------------------------- /Examples/SimpleRealtimeFilterPlayback/SimpleRealtimeFilterPlayback/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SimpleRealtimeFilterPlayback 4 | // 5 | // Created by RenZhu Macro on 2020/7/2. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application: didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /Examples/SimpleRealtimeFilterPlayback/SimpleRealtimeFilterPlayback/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Examples/SimpleRealtimeFilterPlayback/SimpleRealtimeFilterPlayback/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Examples/SimpleRealtimeFilterPlayback/SimpleRealtimeFilterPlayback/cute.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleRealtimeFilterPlayback/SimpleRealtimeFilterPlayback/cute.mp4 -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | target 'SimpleVideoAnimation' do 5 | # Comment the next line if you don't want to use dynamic frameworks 6 | use_frameworks! 7 | 8 | # Pods for SimpleVideoAnimation 9 | pod 'PryntTrimmerView' 10 | 11 | end 12 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - PryntTrimmerView (4.0.0) 3 | 4 | DEPENDENCIES: 5 | - PryntTrimmerView 6 | 7 | SPEC REPOS: 8 | trunk: 9 | - PryntTrimmerView 10 | 11 | SPEC CHECKSUMS: 12 | PryntTrimmerView: 67e67573ffd4c073f1308effa66aefd0cfa667a0 13 | 14 | PODFILE CHECKSUM: 4473f02a1528566660f9c5ed79ea1d9d7df2096d 15 | 16 | COCOAPODS: 1.8.4 17 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - PryntTrimmerView (4.0.0) 3 | 4 | DEPENDENCIES: 5 | - PryntTrimmerView 6 | 7 | SPEC REPOS: 8 | trunk: 9 | - PryntTrimmerView 10 | 11 | SPEC CHECKSUMS: 12 | PryntTrimmerView: 67e67573ffd4c073f1308effa66aefd0cfa667a0 13 | 14 | PODFILE CHECKSUM: 4473f02a1528566660f9c5ed79ea1d9d7df2096d 15 | 16 | COCOAPODS: 1.8.4 17 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/Pods/PryntTrimmerView/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Prynt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/Pods/PryntTrimmerView/PryntTrimmerView/Classes/Trimmer/HandlerView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HandlerView.swift 3 | // PryntTrimmerView 4 | // 5 | // Created by HHK on 27/03/2017. 6 | // Copyright © 2017 Prynt. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class HandlerView: UIView { 13 | 14 | override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { 15 | let hitFrame = bounds.insetBy(dx: -20, dy: -20) 16 | return hitFrame.contains(point) ? self : nil 17 | } 18 | override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { 19 | let hitFrame = bounds.insetBy(dx: -20, dy: -20) 20 | return hitFrame.contains(point) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/Pods/Target Support Files/Pods-SimpleVideoAnimation/Pods-SimpleVideoAnimation-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/Pods/Target Support Files/Pods-SimpleVideoAnimation/Pods-SimpleVideoAnimation-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## PryntTrimmerView 5 | 6 | MIT License 7 | 8 | Copyright (c) 2017 Prynt 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | Generated by CocoaPods - https://cocoapods.org 29 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/Pods/Target Support Files/Pods-SimpleVideoAnimation/Pods-SimpleVideoAnimation-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_SimpleVideoAnimation : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_SimpleVideoAnimation 5 | @end 6 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/Pods/Target Support Files/Pods-SimpleVideoAnimation/Pods-SimpleVideoAnimation-frameworks-Debug-input-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${PODS_ROOT}/Target Support Files/Pods-SimpleVideoAnimation/Pods-SimpleVideoAnimation-frameworks.sh 2 | ${BUILT_PRODUCTS_DIR}/PryntTrimmerView/PryntTrimmerView.framework -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/Pods/Target Support Files/Pods-SimpleVideoAnimation/Pods-SimpleVideoAnimation-frameworks-Debug-output-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PryntTrimmerView.framework -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/Pods/Target Support Files/Pods-SimpleVideoAnimation/Pods-SimpleVideoAnimation-frameworks-Release-input-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${PODS_ROOT}/Target Support Files/Pods-SimpleVideoAnimation/Pods-SimpleVideoAnimation-frameworks.sh 2 | ${BUILT_PRODUCTS_DIR}/PryntTrimmerView/PryntTrimmerView.framework -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/Pods/Target Support Files/Pods-SimpleVideoAnimation/Pods-SimpleVideoAnimation-frameworks-Release-output-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PryntTrimmerView.framework -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/Pods/Target Support Files/Pods-SimpleVideoAnimation/Pods-SimpleVideoAnimation-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_SimpleVideoAnimationVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_SimpleVideoAnimationVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/Pods/Target Support Files/Pods-SimpleVideoAnimation/Pods-SimpleVideoAnimation.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/PryntTrimmerView" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/PryntTrimmerView/PryntTrimmerView.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "PryntTrimmerView" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/Pods/Target Support Files/Pods-SimpleVideoAnimation/Pods-SimpleVideoAnimation.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_SimpleVideoAnimation { 2 | umbrella header "Pods-SimpleVideoAnimation-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/Pods/Target Support Files/Pods-SimpleVideoAnimation/Pods-SimpleVideoAnimation.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/PryntTrimmerView" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/PryntTrimmerView/PryntTrimmerView.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "PryntTrimmerView" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/Pods/Target Support Files/PryntTrimmerView/PryntTrimmerView-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 4.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/Pods/Target Support Files/PryntTrimmerView/PryntTrimmerView-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_PryntTrimmerView : NSObject 3 | @end 4 | @implementation PodsDummy_PryntTrimmerView 5 | @end 6 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/Pods/Target Support Files/PryntTrimmerView/PryntTrimmerView-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/Pods/Target Support Files/PryntTrimmerView/PryntTrimmerView-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double PryntTrimmerViewVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char PryntTrimmerViewVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/Pods/Target Support Files/PryntTrimmerView/PryntTrimmerView.modulemap: -------------------------------------------------------------------------------- 1 | framework module PryntTrimmerView { 2 | umbrella header "PryntTrimmerView-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/Pods/Target Support Files/PryntTrimmerView/PryntTrimmerView.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/PryntTrimmerView 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 4 | PODS_BUILD_DIR = ${BUILD_DIR} 5 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 6 | PODS_ROOT = ${SRCROOT} 7 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/PryntTrimmerView 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 11 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/SimpleVIdeoAnimation.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/SimpleVIdeoAnimation.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/SimpleVIdeoAnimation/853.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoAnimation/SimpleVIdeoAnimation/853.mp4 -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/SimpleVIdeoAnimation/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SimpleVideoAnimation 4 | // 5 | // Created by RenZhu Macro on 2020/7/20. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/SimpleVIdeoAnimation/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/SimpleVIdeoAnimation/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/SimpleVIdeoAnimation/cute.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoAnimation/SimpleVIdeoAnimation/cute.mp4 -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/SimpleVideoAnimation.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Examples/SimpleVideoAnimation/SimpleVideoAnimation.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor.xcodeproj/xcuserdata/renzhumacro.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SimpleVideoEditor.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 1 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 6ADB07BD24ADE0730010A817 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SimpleVideoEditor 4 | // 5 | // Created by RenZhu Macro on 2020/7/2. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/Images.xcassets/gallery_picker_camera.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "baseline_camera_alt_black_24pt_1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "baseline_camera_alt_black_24pt_2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "baseline_camera_alt_black_24pt_3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/Images.xcassets/gallery_picker_camera.imageset/baseline_camera_alt_black_24pt_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoEditor/SimpleVideoEditor/Images.xcassets/gallery_picker_camera.imageset/baseline_camera_alt_black_24pt_1x.png -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/Images.xcassets/gallery_picker_camera.imageset/baseline_camera_alt_black_24pt_2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoEditor/SimpleVideoEditor/Images.xcassets/gallery_picker_camera.imageset/baseline_camera_alt_black_24pt_2x.png -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/Images.xcassets/gallery_picker_camera.imageset/baseline_camera_alt_black_24pt_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoEditor/SimpleVideoEditor/Images.xcassets/gallery_picker_camera.imageset/baseline_camera_alt_black_24pt_3x.png -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/Images.xcassets/gallery_picker_cloud.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "baseline_cloud_black_24pt_1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "baseline_cloud_black_24pt_2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "baseline_cloud_black_24pt_3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/Images.xcassets/gallery_picker_cloud.imageset/baseline_cloud_black_24pt_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoEditor/SimpleVideoEditor/Images.xcassets/gallery_picker_cloud.imageset/baseline_cloud_black_24pt_1x.png -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/Images.xcassets/gallery_picker_cloud.imageset/baseline_cloud_black_24pt_2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoEditor/SimpleVideoEditor/Images.xcassets/gallery_picker_cloud.imageset/baseline_cloud_black_24pt_2x.png -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/Images.xcassets/gallery_picker_cloud.imageset/baseline_cloud_black_24pt_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoEditor/SimpleVideoEditor/Images.xcassets/gallery_picker_cloud.imageset/baseline_cloud_black_24pt_3x.png -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/Images.xcassets/gallery_picker_library.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "baseline_photo_library_black_24pt_1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "baseline_photo_library_black_24pt_2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "baseline_photo_library_black_24pt_3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/Images.xcassets/gallery_picker_library.imageset/baseline_photo_library_black_24pt_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoEditor/SimpleVideoEditor/Images.xcassets/gallery_picker_library.imageset/baseline_photo_library_black_24pt_1x.png -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/Images.xcassets/gallery_picker_library.imageset/baseline_photo_library_black_24pt_2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoEditor/SimpleVideoEditor/Images.xcassets/gallery_picker_library.imageset/baseline_photo_library_black_24pt_2x.png -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/Images.xcassets/gallery_picker_library.imageset/baseline_photo_library_black_24pt_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoEditor/SimpleVideoEditor/Images.xcassets/gallery_picker_library.imageset/baseline_photo_library_black_24pt_3x.png -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/Model/ResourceItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ResourceItem.swift 3 | // SimpleVideoEditor 4 | // 5 | // Created by RenZhu Macro on 2020/7/7. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import MetalVideoProcess 11 | 12 | class ResourceItem: MetalVideoEditorItem { 13 | 14 | public var rotate = 0.0 15 | public var scale = Position(1.0, 1.0) 16 | //translation 为归一化 17 | public var translation = Position(0.0, 0.0) 18 | 19 | var orientation : UIInterfaceOrientation = .portrait 20 | weak var transformFilter: MetalVideoProcessTransformFilter? 21 | weak var currentLayer: MetalVideoProcessBlendFilter? 22 | var roi: CGRect = CGRect.zero 23 | var fillType: MetalVideoProcessTransformFilter.StretchType = .aspectToFill 24 | 25 | var isSelected: Bool = false 26 | 27 | var startTimeText: NSString { 28 | get { 29 | return NSString(format: "%.2f", self.startTime.seconds) 30 | } 31 | } 32 | 33 | var durationText: NSString { 34 | get { 35 | return NSString(format: "%.2f", self.duration.seconds) 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/ResourceItemTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ResourceItemTableViewCell.swift 3 | // SimpleVideoEditor 4 | // 5 | // Created by RenZhu Macro on 2020/7/8. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ResourceItemTableViewCell: UITableViewCell { 12 | @IBOutlet weak var trackIdLabel: UILabel! 13 | 14 | override func awakeFromNib() { 15 | super.awakeFromNib() 16 | // Initialization code 17 | } 18 | 19 | override func setSelected(_ selected: Bool, animated: Bool) { 20 | super.setSelected(selected, animated: animated) 21 | 22 | // Configure the view for the selected state 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/SimpleVideoEditor-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Header.h 3 | // SimpleVideoExport 4 | // 5 | // Created by RenZhu Macro on 2020/7/7. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | #import "ProgressHUD.h" 10 | #import "MBProgressHUD.h" 11 | -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/Vender/DynamicBlurView/CGContext+CGImage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CGContext+CGImage.swift 3 | // DynamicBlurView 4 | // 5 | // Created by Kyohei Ito on 2017/08/17. 6 | // Copyright © 2017年 kyohei_ito. All rights reserved. 7 | // 8 | 9 | extension CGContext { 10 | static func imageContext(with quality: CaptureQuality, rect: CGRect, opaque: Bool) -> CGContext? { 11 | UIGraphicsBeginImageContextWithOptions(rect.size, opaque, quality.imageScale) 12 | guard let context = UIGraphicsGetCurrentContext() else { 13 | return nil 14 | } 15 | 16 | context.translateBy(x: -rect.origin.x, y: -rect.origin.y) 17 | context.interpolationQuality = quality.interpolationQuality 18 | 19 | return context 20 | } 21 | 22 | func makeImage(with blendColor: UIColor?, blendMode: CGBlendMode, size: CGSize) -> CGImage? { 23 | if let color = blendColor { 24 | setFillColor(color.cgColor) 25 | setBlendMode(blendMode) 26 | fill(CGRect(origin: .zero, size: size)) 27 | } 28 | 29 | return makeImage() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/Vender/DynamicBlurView/CaptureQuality.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CaptureQuality.swift 3 | // DynamicBlurView 4 | // 5 | // Created by Kyohei Ito on 2017/08/17. 6 | // Copyright © 2017年 kyohei_ito. All rights reserved. 7 | // 8 | 9 | public enum CaptureQuality { 10 | case `default` 11 | case low 12 | case medium 13 | case high 14 | 15 | var imageScale: CGFloat { 16 | switch self { 17 | case .default, .high: 18 | return 0 19 | case .low, .medium: 20 | return 1 21 | } 22 | } 23 | 24 | var interpolationQuality: CGInterpolationQuality { 25 | switch self { 26 | case .default, .low: 27 | return .none 28 | case .medium, .high: 29 | return .default 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/Vender/DynamicBlurView/DynamicBlurView.h: -------------------------------------------------------------------------------- 1 | // 2 | // DynamicBlurView.h 3 | // DynamicBlurView 4 | // 5 | // Created by Kyohei Ito on 2015/04/08. 6 | // Copyright (c) 2015年 kyohei_ito. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for DynamicBlurView. 12 | FOUNDATION_EXPORT double DynamicBlurViewVersionNumber; 13 | 14 | //! Project version string for DynamicBlurView. 15 | FOUNDATION_EXPORT const unsigned char DynamicBlurViewVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/Vender/DynamicBlurView/TrackingMode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TrackingMode.swift 3 | // DynamicBlurView 4 | // 5 | // Created by Kyohei Ito on 2017/08/17. 6 | // Copyright © 2017年 kyohei_ito. All rights reserved. 7 | // 8 | 9 | public enum TrackingMode: CustomStringConvertible { 10 | case tracking 11 | case common 12 | case none 13 | 14 | public var description: String { 15 | switch self { 16 | case .tracking: 17 | return RunLoop.Mode.tracking.rawValue 18 | case .common: 19 | return RunLoop.Mode.common.rawValue 20 | case .none: 21 | return "" 22 | } 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/Vender/DynamicBlurView/UIImage+Blur.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Blur.swift 3 | // DynamicBlurView 4 | // 5 | // Created by Kyohei Ito on 2017/08/11. 6 | // Copyright © 2017年 kyohei_ito. All rights reserved. 7 | // 8 | 9 | public extension UIImage { 10 | func blurred(radius: CGFloat, iterations: Int, ratio: CGFloat, blendColor color: UIColor?, blendMode mode: CGBlendMode) -> UIImage? { 11 | guard let cgImage = cgImage else { 12 | return nil 13 | } 14 | 15 | if cgImage.area <= 0 || radius <= 0 { 16 | return self 17 | } 18 | 19 | var boxSize = UInt32(radius * scale * ratio) 20 | if boxSize % 2 == 0 { 21 | boxSize += 1 22 | } 23 | 24 | return cgImage.blurred(with: boxSize, iterations: iterations, blendColor: color, blendMode: mode).map { 25 | UIImage(cgImage: $0, scale: scale, orientation: imageOrientation) 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/Vender/TableViewDragger/ScrollRects.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScrollRects.swift 3 | // TableViewDragger 4 | // 5 | // Created by Kyohei Ito on 2017/12/08. 6 | // Copyright © 2017年 kyohei_ito. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreImage 11 | 12 | struct ScrollRects { 13 | private let maxDistance: CGFloat = 10 14 | private let size: CGSize 15 | private let scrollRange: CGFloat 16 | 17 | let topRect: CGRect 18 | let bottomRect: CGRect 19 | 20 | init(size: CGSize) { 21 | self.size = size 22 | scrollRange = size.height / 2.5 23 | 24 | let scrollSize = CGSize(width: size.width, height: scrollRange) 25 | topRect = CGRect(origin: .zero, size: scrollSize) 26 | bottomRect = CGRect(origin: CGPoint(x: 0, y: size.height - scrollRange), size: scrollSize) 27 | } 28 | 29 | func distance(at point: CGPoint) -> CGFloat { 30 | let ratio: CGFloat 31 | if topRect.contains(point) { 32 | ratio = -(scrollRange - point.y) 33 | } else if bottomRect.contains(point) { 34 | ratio = point.y - (size.height - scrollRange) 35 | } else { 36 | ratio = 0 37 | } 38 | 39 | return max(min(ratio / 30, maxDistance), -maxDistance) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/Vender/TableViewDragger/UIScrollViewExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIScrollViewExtension.swift 3 | // Pods 4 | // 5 | // Created by Kyohei Ito on 2015/09/29. 6 | // 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIScrollView { 12 | enum DraggingDirection { 13 | case up 14 | case down 15 | } 16 | 17 | func preferredContentOffset(at point: CGPoint, velocity: CGFloat) -> CGPoint { 18 | let distance = ScrollRects(size: bounds.size).distance(at: point) / velocity 19 | var offset = contentOffset 20 | offset.y += distance 21 | 22 | let topOffset = -contentInset.top 23 | let bottomOffset = contentInset.bottom 24 | let height = floor(contentSize.height) - bounds.size.height 25 | 26 | if offset.y > height + bottomOffset { 27 | offset.y = height + bottomOffset 28 | } else if offset.y < topOffset { 29 | offset.y = topOffset 30 | } 31 | 32 | return offset 33 | } 34 | 35 | func draggingDirection(at point: @autoclosure () -> CGPoint) -> DraggingDirection? { 36 | let contentHeight = floor(contentSize.height) 37 | if bounds.size.height >= contentHeight { 38 | return nil 39 | } 40 | 41 | let rects = ScrollRects(size: bounds.size) 42 | let point = point() 43 | 44 | if rects.topRect.contains(point) { 45 | let topOffset = -contentInset.top 46 | if contentOffset.y > topOffset { 47 | return .up 48 | } 49 | } else if rects.bottomRect.contains(point) { 50 | let bottomOffset = contentHeight + contentInset.bottom - bounds.size.height 51 | if contentOffset.y < bottomOffset { 52 | return .down 53 | } 54 | } 55 | 56 | return nil 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/cute.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoEditor/SimpleVideoEditor/cute.mp4 -------------------------------------------------------------------------------- /Examples/SimpleVideoEditor/SimpleVideoEditor/movie.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoEditor/SimpleVideoEditor/movie.mov -------------------------------------------------------------------------------- /Examples/SimpleVideoExport/SimpleVideoExport.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Examples/SimpleVideoExport/SimpleVideoExport.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Examples/SimpleVideoExport/SimpleVideoExport.xcodeproj/xcuserdata/renzhumacro.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SimpleVideoExport.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 6A89623E24B30FAD0083B7AE 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Examples/SimpleVideoExport/SimpleVideoExport/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SimpleVideoExport 4 | // 5 | // Created by RenZhu Macro on 2020/7/6. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /Examples/SimpleVideoExport/SimpleVideoExport/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Examples/SimpleVideoExport/SimpleVideoExport/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Examples/SimpleVideoExport/SimpleVideoExport/SimpleVideoExport-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Header.h 3 | // SimpleVideoExport 4 | // 5 | // Created by RenZhu Macro on 2020/7/7. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | #import "ProgressHUD.h" 10 | #import "MBProgressHUD.h" 11 | -------------------------------------------------------------------------------- /Examples/SimpleVideoExport/SimpleVideoExport/UI/ProgressHUD.bundle/progresshud-error@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoExport/SimpleVideoExport/UI/ProgressHUD.bundle/progresshud-error@2x.png -------------------------------------------------------------------------------- /Examples/SimpleVideoExport/SimpleVideoExport/UI/ProgressHUD.bundle/progresshud-success@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoExport/SimpleVideoExport/UI/ProgressHUD.bundle/progresshud-success@2x.png -------------------------------------------------------------------------------- /Examples/SimpleVideoTransition/SimpleVideoTransition.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransition/SimpleVideoTransition.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransition/SimpleVideoTransition/853.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoTransition/SimpleVideoTransition/853.mp4 -------------------------------------------------------------------------------- /Examples/SimpleVideoTransition/SimpleVideoTransition/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SimpleVideoTransition 4 | // 5 | // Created by RenZhu Macro on 2020/7/2. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransition/SimpleVideoTransition/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransition/SimpleVideoTransition/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransition/SimpleVideoTransition/Model/ResourceItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ResourceItem.swift 3 | // SimpleVideoEditor 4 | // 5 | // Created by RenZhu Macro on 2020/7/7. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import MetalVideoProcess 11 | 12 | class ResourceItem: MetalVideoEditorItem { 13 | 14 | public var rotate = 0.0 15 | public var scale = Position(1.0, 1.0) 16 | //translation 为归一化 17 | public var translation = Position(0.0, 0.0) 18 | 19 | var orientation : UIInterfaceOrientation = .portrait 20 | weak var transformFilter: MetalVideoProcessTransformFilter? 21 | weak var currentLayer: MetalVideoProcessBlendFilter? 22 | var roi: CGRect = CGRect.zero 23 | var fillType: MetalVideoProcessTransformFilter.StretchType = .aspectToFill 24 | 25 | var isSelected: Bool = false 26 | 27 | var startTimeText: NSString { 28 | get { 29 | return NSString(format: "%.2f", self.startTime.seconds) 30 | } 31 | } 32 | 33 | var durationText: NSString { 34 | get { 35 | return NSString(format: "%.2f", self.duration.seconds) 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransition/SimpleVideoTransition/ResourceItemTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ResourceItemTableViewCell.swift 3 | // SimpleVideoEditor 4 | // 5 | // Created by RenZhu Macro on 2020/7/8. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ResourceItemTableViewCell: UITableViewCell { 12 | @IBOutlet weak var trackIdLabel: UILabel! 13 | 14 | override func awakeFromNib() { 15 | super.awakeFromNib() 16 | // Initialization code 17 | } 18 | 19 | override func setSelected(_ selected: Bool, animated: Bool) { 20 | super.setSelected(selected, animated: animated) 21 | 22 | // Configure the view for the selected state 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransition/SimpleVideoTransition/SimpleVideoEditor-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Header.h 3 | // SimpleVideoExport 4 | // 5 | // Created by RenZhu Macro on 2020/7/7. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | #import "ProgressHUD.h" 10 | #import "MBProgressHUD.h" 11 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransition/SimpleVideoTransition/Vender/DynamicBlurView/CGContext+CGImage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CGContext+CGImage.swift 3 | // DynamicBlurView 4 | // 5 | // Created by Kyohei Ito on 2017/08/17. 6 | // Copyright © 2017年 kyohei_ito. All rights reserved. 7 | // 8 | 9 | extension CGContext { 10 | static func imageContext(with quality: CaptureQuality, rect: CGRect, opaque: Bool) -> CGContext? { 11 | UIGraphicsBeginImageContextWithOptions(rect.size, opaque, quality.imageScale) 12 | guard let context = UIGraphicsGetCurrentContext() else { 13 | return nil 14 | } 15 | 16 | context.translateBy(x: -rect.origin.x, y: -rect.origin.y) 17 | context.interpolationQuality = quality.interpolationQuality 18 | 19 | return context 20 | } 21 | 22 | func makeImage(with blendColor: UIColor?, blendMode: CGBlendMode, size: CGSize) -> CGImage? { 23 | if let color = blendColor { 24 | setFillColor(color.cgColor) 25 | setBlendMode(blendMode) 26 | fill(CGRect(origin: .zero, size: size)) 27 | } 28 | 29 | return makeImage() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransition/SimpleVideoTransition/Vender/DynamicBlurView/CaptureQuality.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CaptureQuality.swift 3 | // DynamicBlurView 4 | // 5 | // Created by Kyohei Ito on 2017/08/17. 6 | // Copyright © 2017年 kyohei_ito. All rights reserved. 7 | // 8 | 9 | public enum CaptureQuality { 10 | case `default` 11 | case low 12 | case medium 13 | case high 14 | 15 | var imageScale: CGFloat { 16 | switch self { 17 | case .default, .high: 18 | return 0 19 | case .low, .medium: 20 | return 1 21 | } 22 | } 23 | 24 | var interpolationQuality: CGInterpolationQuality { 25 | switch self { 26 | case .default, .low: 27 | return .none 28 | case .medium, .high: 29 | return .default 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransition/SimpleVideoTransition/Vender/DynamicBlurView/DynamicBlurView.h: -------------------------------------------------------------------------------- 1 | // 2 | // DynamicBlurView.h 3 | // DynamicBlurView 4 | // 5 | // Created by Kyohei Ito on 2015/04/08. 6 | // Copyright (c) 2015年 kyohei_ito. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for DynamicBlurView. 12 | FOUNDATION_EXPORT double DynamicBlurViewVersionNumber; 13 | 14 | //! Project version string for DynamicBlurView. 15 | FOUNDATION_EXPORT const unsigned char DynamicBlurViewVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransition/SimpleVideoTransition/Vender/DynamicBlurView/TrackingMode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TrackingMode.swift 3 | // DynamicBlurView 4 | // 5 | // Created by Kyohei Ito on 2017/08/17. 6 | // Copyright © 2017年 kyohei_ito. All rights reserved. 7 | // 8 | 9 | public enum TrackingMode: CustomStringConvertible { 10 | case tracking 11 | case common 12 | case none 13 | 14 | public var description: String { 15 | switch self { 16 | case .tracking: 17 | return RunLoop.Mode.tracking.rawValue 18 | case .common: 19 | return RunLoop.Mode.common.rawValue 20 | case .none: 21 | return "" 22 | } 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransition/SimpleVideoTransition/Vender/DynamicBlurView/UIImage+Blur.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Blur.swift 3 | // DynamicBlurView 4 | // 5 | // Created by Kyohei Ito on 2017/08/11. 6 | // Copyright © 2017年 kyohei_ito. All rights reserved. 7 | // 8 | 9 | public extension UIImage { 10 | func blurred(radius: CGFloat, iterations: Int, ratio: CGFloat, blendColor color: UIColor?, blendMode mode: CGBlendMode) -> UIImage? { 11 | guard let cgImage = cgImage else { 12 | return nil 13 | } 14 | 15 | if cgImage.area <= 0 || radius <= 0 { 16 | return self 17 | } 18 | 19 | var boxSize = UInt32(radius * scale * ratio) 20 | if boxSize % 2 == 0 { 21 | boxSize += 1 22 | } 23 | 24 | return cgImage.blurred(with: boxSize, iterations: iterations, blendColor: color, blendMode: mode).map { 25 | UIImage(cgImage: $0, scale: scale, orientation: imageOrientation) 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransition/SimpleVideoTransition/Vender/TableViewDragger/ScrollRects.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScrollRects.swift 3 | // TableViewDragger 4 | // 5 | // Created by Kyohei Ito on 2017/12/08. 6 | // Copyright © 2017年 kyohei_ito. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreImage 11 | 12 | struct ScrollRects { 13 | private let maxDistance: CGFloat = 10 14 | private let size: CGSize 15 | private let scrollRange: CGFloat 16 | 17 | let topRect: CGRect 18 | let bottomRect: CGRect 19 | 20 | init(size: CGSize) { 21 | self.size = size 22 | scrollRange = size.height / 2.5 23 | 24 | let scrollSize = CGSize(width: size.width, height: scrollRange) 25 | topRect = CGRect(origin: .zero, size: scrollSize) 26 | bottomRect = CGRect(origin: CGPoint(x: 0, y: size.height - scrollRange), size: scrollSize) 27 | } 28 | 29 | func distance(at point: CGPoint) -> CGFloat { 30 | let ratio: CGFloat 31 | if topRect.contains(point) { 32 | ratio = -(scrollRange - point.y) 33 | } else if bottomRect.contains(point) { 34 | ratio = point.y - (size.height - scrollRange) 35 | } else { 36 | ratio = 0 37 | } 38 | 39 | return max(min(ratio / 30, maxDistance), -maxDistance) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransition/SimpleVideoTransition/Vender/TableViewDragger/UIScrollViewExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIScrollViewExtension.swift 3 | // Pods 4 | // 5 | // Created by Kyohei Ito on 2015/09/29. 6 | // 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIScrollView { 12 | enum DraggingDirection { 13 | case up 14 | case down 15 | } 16 | 17 | func preferredContentOffset(at point: CGPoint, velocity: CGFloat) -> CGPoint { 18 | let distance = ScrollRects(size: bounds.size).distance(at: point) / velocity 19 | var offset = contentOffset 20 | offset.y += distance 21 | 22 | let topOffset = -contentInset.top 23 | let bottomOffset = contentInset.bottom 24 | let height = floor(contentSize.height) - bounds.size.height 25 | 26 | if offset.y > height + bottomOffset { 27 | offset.y = height + bottomOffset 28 | } else if offset.y < topOffset { 29 | offset.y = topOffset 30 | } 31 | 32 | return offset 33 | } 34 | 35 | func draggingDirection(at point: @autoclosure () -> CGPoint) -> DraggingDirection? { 36 | let contentHeight = floor(contentSize.height) 37 | if bounds.size.height >= contentHeight { 38 | return nil 39 | } 40 | 41 | let rects = ScrollRects(size: bounds.size) 42 | let point = point() 43 | 44 | if rects.topRect.contains(point) { 45 | let topOffset = -contentInset.top 46 | if contentOffset.y > topOffset { 47 | return .up 48 | } 49 | } else if rects.bottomRect.contains(point) { 50 | let bottomOffset = contentHeight + contentInset.bottom - bounds.size.height 51 | if contentOffset.y < bottomOffset { 52 | return .down 53 | } 54 | } 55 | 56 | return nil 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransition/SimpleVideoTransition/cute.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoTransition/SimpleVideoTransition/cute.mp4 -------------------------------------------------------------------------------- /Examples/SimpleVideoTransition/SimpleVideoTransition/movie.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoTransition/SimpleVideoTransition/movie.mov -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/853.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/853.mp4 -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SimpleVideoTransition 4 | // 5 | // Created by RenZhu Macro on 2020/7/2. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Images.xcassets/gallery_picker_camera.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "baseline_camera_alt_black_24pt_1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "baseline_camera_alt_black_24pt_2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "baseline_camera_alt_black_24pt_3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Images.xcassets/gallery_picker_camera.imageset/baseline_camera_alt_black_24pt_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Images.xcassets/gallery_picker_camera.imageset/baseline_camera_alt_black_24pt_1x.png -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Images.xcassets/gallery_picker_camera.imageset/baseline_camera_alt_black_24pt_2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Images.xcassets/gallery_picker_camera.imageset/baseline_camera_alt_black_24pt_2x.png -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Images.xcassets/gallery_picker_camera.imageset/baseline_camera_alt_black_24pt_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Images.xcassets/gallery_picker_camera.imageset/baseline_camera_alt_black_24pt_3x.png -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Images.xcassets/gallery_picker_cloud.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "baseline_cloud_black_24pt_1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "baseline_cloud_black_24pt_2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "baseline_cloud_black_24pt_3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Images.xcassets/gallery_picker_cloud.imageset/baseline_cloud_black_24pt_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Images.xcassets/gallery_picker_cloud.imageset/baseline_cloud_black_24pt_1x.png -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Images.xcassets/gallery_picker_cloud.imageset/baseline_cloud_black_24pt_2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Images.xcassets/gallery_picker_cloud.imageset/baseline_cloud_black_24pt_2x.png -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Images.xcassets/gallery_picker_cloud.imageset/baseline_cloud_black_24pt_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Images.xcassets/gallery_picker_cloud.imageset/baseline_cloud_black_24pt_3x.png -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Images.xcassets/gallery_picker_library.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "baseline_photo_library_black_24pt_1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "baseline_photo_library_black_24pt_2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "baseline_photo_library_black_24pt_3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Images.xcassets/gallery_picker_library.imageset/baseline_photo_library_black_24pt_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Images.xcassets/gallery_picker_library.imageset/baseline_photo_library_black_24pt_1x.png -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Images.xcassets/gallery_picker_library.imageset/baseline_photo_library_black_24pt_2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Images.xcassets/gallery_picker_library.imageset/baseline_photo_library_black_24pt_2x.png -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Images.xcassets/gallery_picker_library.imageset/baseline_photo_library_black_24pt_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Images.xcassets/gallery_picker_library.imageset/baseline_photo_library_black_24pt_3x.png -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Model/ResourceItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ResourceItem.swift 3 | // SimpleVideoEditor 4 | // 5 | // Created by RenZhu Macro on 2020/7/7. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import MetalVideoProcess 11 | 12 | class ResourceItem: MetalVideoEditorItem { 13 | 14 | public var rotate = 0.0 15 | public var scale = Position(1.0, 1.0) 16 | //translation 为归一化 17 | public var translation = Position(0.0, 0.0) 18 | 19 | var orientation : UIInterfaceOrientation = .portrait 20 | weak var transformFilter: MetalVideoProcessTransformFilter? 21 | weak var currentLayer: MetalVideoProcessBlendFilter? 22 | var roi: CGRect = CGRect.zero 23 | var fillType: MetalVideoProcessTransformFilter.StretchType = .aspectToFill 24 | 25 | var isSelected: Bool = false 26 | 27 | var startTimeText: NSString { 28 | get { 29 | return NSString(format: "%.2f", self.startTime.seconds) 30 | } 31 | } 32 | 33 | var durationText: NSString { 34 | get { 35 | return NSString(format: "%.2f", self.duration.seconds) 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/ResourceItemTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ResourceItemTableViewCell.swift 3 | // SimpleVideoEditor 4 | // 5 | // Created by RenZhu Macro on 2020/7/8. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ResourceItemTableViewCell: UITableViewCell { 12 | @IBOutlet weak var trackIdLabel: UILabel! 13 | 14 | override func awakeFromNib() { 15 | super.awakeFromNib() 16 | // Initialization code 17 | } 18 | 19 | override func setSelected(_ selected: Bool, animated: Bool) { 20 | super.setSelected(selected, animated: animated) 21 | 22 | // Configure the view for the selected state 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/SimpleVideoEditor-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Header.h 3 | // SimpleVideoExport 4 | // 5 | // Created by RenZhu Macro on 2020/7/7. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | #import "ProgressHUD.h" 10 | #import "MBProgressHUD.h" 11 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Vender/DynamicBlurView/CGContext+CGImage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CGContext+CGImage.swift 3 | // DynamicBlurView 4 | // 5 | // Created by Kyohei Ito on 2017/08/17. 6 | // Copyright © 2017年 kyohei_ito. All rights reserved. 7 | // 8 | 9 | extension CGContext { 10 | static func imageContext(with quality: CaptureQuality, rect: CGRect, opaque: Bool) -> CGContext? { 11 | UIGraphicsBeginImageContextWithOptions(rect.size, opaque, quality.imageScale) 12 | guard let context = UIGraphicsGetCurrentContext() else { 13 | return nil 14 | } 15 | 16 | context.translateBy(x: -rect.origin.x, y: -rect.origin.y) 17 | context.interpolationQuality = quality.interpolationQuality 18 | 19 | return context 20 | } 21 | 22 | func makeImage(with blendColor: UIColor?, blendMode: CGBlendMode, size: CGSize) -> CGImage? { 23 | if let color = blendColor { 24 | setFillColor(color.cgColor) 25 | setBlendMode(blendMode) 26 | fill(CGRect(origin: .zero, size: size)) 27 | } 28 | 29 | return makeImage() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Vender/DynamicBlurView/CaptureQuality.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CaptureQuality.swift 3 | // DynamicBlurView 4 | // 5 | // Created by Kyohei Ito on 2017/08/17. 6 | // Copyright © 2017年 kyohei_ito. All rights reserved. 7 | // 8 | 9 | public enum CaptureQuality { 10 | case `default` 11 | case low 12 | case medium 13 | case high 14 | 15 | var imageScale: CGFloat { 16 | switch self { 17 | case .default, .high: 18 | return 0 19 | case .low, .medium: 20 | return 1 21 | } 22 | } 23 | 24 | var interpolationQuality: CGInterpolationQuality { 25 | switch self { 26 | case .default, .low: 27 | return .none 28 | case .medium, .high: 29 | return .default 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Vender/DynamicBlurView/DynamicBlurView.h: -------------------------------------------------------------------------------- 1 | // 2 | // DynamicBlurView.h 3 | // DynamicBlurView 4 | // 5 | // Created by Kyohei Ito on 2015/04/08. 6 | // Copyright (c) 2015年 kyohei_ito. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for DynamicBlurView. 12 | FOUNDATION_EXPORT double DynamicBlurViewVersionNumber; 13 | 14 | //! Project version string for DynamicBlurView. 15 | FOUNDATION_EXPORT const unsigned char DynamicBlurViewVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Vender/DynamicBlurView/TrackingMode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TrackingMode.swift 3 | // DynamicBlurView 4 | // 5 | // Created by Kyohei Ito on 2017/08/17. 6 | // Copyright © 2017年 kyohei_ito. All rights reserved. 7 | // 8 | 9 | public enum TrackingMode: CustomStringConvertible { 10 | case tracking 11 | case common 12 | case none 13 | 14 | public var description: String { 15 | switch self { 16 | case .tracking: 17 | return RunLoop.Mode.tracking.rawValue 18 | case .common: 19 | return RunLoop.Mode.common.rawValue 20 | case .none: 21 | return "" 22 | } 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Vender/DynamicBlurView/UIImage+Blur.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Blur.swift 3 | // DynamicBlurView 4 | // 5 | // Created by Kyohei Ito on 2017/08/11. 6 | // Copyright © 2017年 kyohei_ito. All rights reserved. 7 | // 8 | 9 | public extension UIImage { 10 | func blurred(radius: CGFloat, iterations: Int, ratio: CGFloat, blendColor color: UIColor?, blendMode mode: CGBlendMode) -> UIImage? { 11 | guard let cgImage = cgImage else { 12 | return nil 13 | } 14 | 15 | if cgImage.area <= 0 || radius <= 0 { 16 | return self 17 | } 18 | 19 | var boxSize = UInt32(radius * scale * ratio) 20 | if boxSize % 2 == 0 { 21 | boxSize += 1 22 | } 23 | 24 | return cgImage.blurred(with: boxSize, iterations: iterations, blendColor: color, blendMode: mode).map { 25 | UIImage(cgImage: $0, scale: scale, orientation: imageOrientation) 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Vender/TableViewDragger/ScrollRects.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScrollRects.swift 3 | // TableViewDragger 4 | // 5 | // Created by Kyohei Ito on 2017/12/08. 6 | // Copyright © 2017年 kyohei_ito. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreImage 11 | 12 | struct ScrollRects { 13 | private let maxDistance: CGFloat = 10 14 | private let size: CGSize 15 | private let scrollRange: CGFloat 16 | 17 | let topRect: CGRect 18 | let bottomRect: CGRect 19 | 20 | init(size: CGSize) { 21 | self.size = size 22 | scrollRange = size.height / 2.5 23 | 24 | let scrollSize = CGSize(width: size.width, height: scrollRange) 25 | topRect = CGRect(origin: .zero, size: scrollSize) 26 | bottomRect = CGRect(origin: CGPoint(x: 0, y: size.height - scrollRange), size: scrollSize) 27 | } 28 | 29 | func distance(at point: CGPoint) -> CGFloat { 30 | let ratio: CGFloat 31 | if topRect.contains(point) { 32 | ratio = -(scrollRange - point.y) 33 | } else if bottomRect.contains(point) { 34 | ratio = point.y - (size.height - scrollRange) 35 | } else { 36 | ratio = 0 37 | } 38 | 39 | return max(min(ratio / 30, maxDistance), -maxDistance) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/Vender/TableViewDragger/UIScrollViewExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIScrollViewExtension.swift 3 | // Pods 4 | // 5 | // Created by Kyohei Ito on 2015/09/29. 6 | // 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIScrollView { 12 | enum DraggingDirection { 13 | case up 14 | case down 15 | } 16 | 17 | func preferredContentOffset(at point: CGPoint, velocity: CGFloat) -> CGPoint { 18 | let distance = ScrollRects(size: bounds.size).distance(at: point) / velocity 19 | var offset = contentOffset 20 | offset.y += distance 21 | 22 | let topOffset = -contentInset.top 23 | let bottomOffset = contentInset.bottom 24 | let height = floor(contentSize.height) - bounds.size.height 25 | 26 | if offset.y > height + bottomOffset { 27 | offset.y = height + bottomOffset 28 | } else if offset.y < topOffset { 29 | offset.y = topOffset 30 | } 31 | 32 | return offset 33 | } 34 | 35 | func draggingDirection(at point: @autoclosure () -> CGPoint) -> DraggingDirection? { 36 | let contentHeight = floor(contentSize.height) 37 | if bounds.size.height >= contentHeight { 38 | return nil 39 | } 40 | 41 | let rects = ScrollRects(size: bounds.size) 42 | let point = point() 43 | 44 | if rects.topRect.contains(point) { 45 | let topOffset = -contentInset.top 46 | if contentOffset.y > topOffset { 47 | return .up 48 | } 49 | } else if rects.bottomRect.contains(point) { 50 | let bottomOffset = contentHeight + contentInset.bottom - bounds.size.height 51 | if contentOffset.y < bottomOffset { 52 | return .down 53 | } 54 | } 55 | 56 | return nil 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/ViewController_BASE_17810.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // SimpleVideoTransition 4 | // 5 | // Created by RenZhu Macro on 2020/7/2. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view. 16 | } 17 | 18 | 19 | } 20 | 21 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/cute.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/cute.mp4 -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/movie.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoTransitionSwitch/SimpleVideoTransition/movie.mov -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransitionSwitch.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransitionSwitch.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransitionSwitch.xcodeproj/project.xcworkspace/xcuserdata/renzhumacro.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoTransitionSwitch/SimpleVideoTransitionSwitch.xcodeproj/project.xcworkspace/xcuserdata/renzhumacro.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Examples/SimpleVideoTransitionSwitch/SimpleVideoTransitionSwitch.xcodeproj/project.xcworkspace/xcuserdata/ruanshengqiang.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Examples/SimpleVideoTransitionSwitch/SimpleVideoTransitionSwitch.xcodeproj/project.xcworkspace/xcuserdata/ruanshengqiang.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Wangrenzhu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MetalVideoProcess.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MetalVideoProcess/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /MetalVideoProcess/MetalVideoProcess.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcess.h 3 | // MetalVideoProcess 4 | // 5 | // Created by RenZhu Macro on 2020/7/2. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for MetalVideoProcess. 12 | FOUNDATION_EXPORT double MetalVideoProcessVersionNumber; 13 | 14 | //! Project version string for MetalVideoProcess. 15 | FOUNDATION_EXPORT const unsigned char MetalVideoProcessVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /MetalVideoProcess/Vender/Editor/Core/Audio/AudioMixer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AudioMixer.swift 3 | // Cabbage 4 | // 5 | // Created by Vito on 2018/6/30. 6 | // Copyright © 2018 Vito. All rights reserved. 7 | // 8 | 9 | import AVFoundation 10 | import Accelerate 11 | 12 | public class AudioMixer { 13 | public static func changeVolume(for bufferList: UnsafeMutablePointer, volume: Float) { 14 | let bufferList = UnsafeMutableAudioBufferListPointer(bufferList) 15 | for bufferIndex in 0...size) 20 | var volume = volume 21 | vDSP_vsmul(floatRawPointer, 1, &volume, floatRawPointer, 1, frameCount) 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /MetalVideoProcess/Vender/Editor/Core/Audio/AudioProcessingChain.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AudioProcessingChain.swift 3 | // Cabbage 4 | // 5 | // Created by Vito on 2018/6/30. 6 | // Copyright © 2018 Vito. All rights reserved. 7 | // 8 | 9 | import AVFoundation 10 | 11 | public protocol AudioProcessingNode: class { 12 | func process(timeRange: CMTimeRange, bufferListInOut: UnsafeMutablePointer) 13 | } 14 | 15 | public class AudioProcessingChain: NSObject, NSCopying { 16 | public var nodes: [AudioProcessingNode] = [] 17 | 18 | public func process(timeRange: CMTimeRange, bufferListInOut: UnsafeMutablePointer) { 19 | nodes.forEach { (node) in 20 | node.process(timeRange: timeRange, bufferListInOut: bufferListInOut) 21 | } 22 | } 23 | 24 | // MARK: - NSCopying 25 | public required override init() { 26 | super.init() 27 | } 28 | 29 | public func copy(with zone: NSZone? = nil) -> Any { 30 | let chain = type(of: self).init() 31 | chain.nodes = nodes 32 | return chain 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /MetalVideoProcess/Vender/Editor/Core/Model/VideoTransition.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VideoTransition.swift 3 | // Cabbage 4 | // 5 | // Created by Vito on 01/03/2018. 6 | // Copyright © 2018 Vito. All rights reserved. 7 | // 8 | 9 | import CoreImage 10 | import CoreMedia 11 | 12 | public protocol VideoTransition: class { 13 | var identifier: String { get } 14 | var duration: CMTime { get } 15 | func renderImage(foregroundImage: CIImage, 16 | backgroundImage: CIImage, 17 | forTweenFactor tween: Float64, 18 | renderSize: CGSize) -> CIImage 19 | } 20 | 21 | open class TransitionDuration: VideoTransition { 22 | public var identifier: String { 23 | return String(describing: self) 24 | } 25 | 26 | open var duration: CMTime 27 | 28 | public init(duration: CMTime = CMTime.zero) { 29 | self.duration = duration 30 | } 31 | 32 | open func renderImage(foregroundImage: CIImage, backgroundImage: CIImage, forTweenFactor tween: Float64, renderSize: CGSize) -> CIImage { 33 | return foregroundImage.composited(over: backgroundImage) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /MetalVideoProcess/Vender/Editor/Resource/black_empty.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/MetalVideoProcess/Vender/Editor/Resource/black_empty.mp4 -------------------------------------------------------------------------------- /MetalVideoProcess/Vender/Editor/Track/ImageCompositionGroupProvider.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImageCompositionGroupProvider.swift 3 | // Cabbage 4 | // 5 | // Created by Vito on 2018/10/2. 6 | // Copyright © 2018 Vito. All rights reserved. 7 | // 8 | 9 | import CoreImage 10 | import CoreMedia 11 | 12 | public protocol ImageCompositionProvider: CompositionTimeRangeProvider, VideoCompositionProvider {} 13 | 14 | public class ImageCompositionGroupProvider: VideoCompositionProvider { 15 | 16 | public var passingThroughVideoCompositionProvider: VideoCompositionProvider? 17 | public var imageCompositionProviders: [ImageCompositionProvider] = [] 18 | 19 | public func applyEffect(to sourceImage: CIImage, at time: CMTime, renderSize: CGSize) -> CIImage { 20 | var sourceImage = sourceImage 21 | 22 | imageCompositionProviders.forEach { (provider) in 23 | if provider.timeRange.containsTime(time) { 24 | sourceImage = provider.applyEffect(to: sourceImage, at: time, renderSize: renderSize) 25 | } 26 | } 27 | 28 | if let provider = passingThroughVideoCompositionProvider { 29 | sourceImage = provider.applyEffect(to: sourceImage, at: time, renderSize: renderSize) 30 | } 31 | 32 | return sourceImage 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /MetalVideoProcess/Vender/Editor/Track/Resource/ImageResource.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImageResource.swift 3 | // Cabbage 4 | // 5 | // Created by Vito on 2018/7/27. 6 | // Copyright © 2018 Vito. All rights reserved. 7 | // 8 | 9 | import AVFoundation 10 | import CoreImage 11 | 12 | 13 | /// Provide a Image as video frame 14 | open class ImageResource: Resource { 15 | 16 | public init(image: CIImage, duration: CMTime) { 17 | super.init() 18 | self.image = image 19 | self.status = .avaliable 20 | self.duration = duration 21 | self.selectedTimeRange = CMTimeRange(start: CMTime.zero, duration: duration) 22 | } 23 | 24 | public init(texture: MTLTexture, duration: CMTime) { 25 | super.init() 26 | self.texture = texture 27 | self.status = .avaliable 28 | self.duration = duration 29 | self.selectedTimeRange = CMTimeRange(start: CMTime.zero, duration: duration) 30 | } 31 | 32 | required public init() { 33 | super.init() 34 | } 35 | 36 | open var texture: MTLTexture? = nil 37 | open var image: CIImage? = nil 38 | 39 | open override func image(at time: CMTime, renderSize: CGSize) -> CIImage? { 40 | return image 41 | } 42 | 43 | open override func sourceTexture(at time: CMTime) -> MTLTexture? { 44 | return texture 45 | } 46 | 47 | // MARK: - NSCopying 48 | open override func copy(with zone: NSZone? = nil) -> Any { 49 | let resource = super.copy(with: zone) as! ImageResource 50 | resource.image = image 51 | return resource 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /MetalVideoProcess/Vender/Editor/Uitl/CoreImageExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CoreImageExtension.swift 3 | // Cabbage 4 | // 5 | // Created by Vito on 2018/11/11. 6 | // Copyright © 2018 Vito. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreImage 11 | 12 | extension CIImage { 13 | 14 | func apply(alpha: CGFloat) -> CIImage { 15 | let filter = CIFilter(name: "CIColorMatrix") 16 | filter?.setDefaults() 17 | filter?.setValue(self, forKey: kCIInputImageKey) 18 | let alphaVector = CIVector.init(x: 0, y: 0, z: 0, w: alpha) 19 | filter?.setValue(alphaVector, forKey: "inputAVector") 20 | if let outputImage = filter?.outputImage { 21 | return outputImage 22 | } 23 | return self 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /MetalVideoProcess/Vender/Render/Base/Color.swift: -------------------------------------------------------------------------------- 1 | public struct Color { 2 | public let redComponent: Float 3 | public let greenComponent: Float 4 | public let blueComponent: Float 5 | public let alphaComponent: Float 6 | 7 | public init(red: Float, green: Float, blue: Float, alpha: Float = 1.0) { 8 | self.redComponent = red 9 | self.greenComponent = green 10 | self.blueComponent = blue 11 | self.alphaComponent = alpha 12 | } 13 | 14 | public static let black = Color(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0) 15 | public static let white = Color(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0) 16 | public static let red = Color(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0) 17 | public static let green = Color(red: 0.0, green: 1.0, blue: 0.0, alpha: 1.0) 18 | public static let blue = Color(red: 0.0, green: 0.0, blue: 1.0, alpha: 1.0) 19 | public static let transparent = Color(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.0) 20 | } 21 | -------------------------------------------------------------------------------- /MetalVideoProcess/Vender/Render/Base/OperationShaderTypes.h: -------------------------------------------------------------------------------- 1 | // 2 | // OperationShaderTypes.h 3 | // MetalVideoProcess 4 | // 5 | // Created by RenZhu Macro on 2020/4/15. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | #include 9 | using namespace metal; 10 | 11 | #ifndef OperationShaderTypes_h 12 | #define OperationShaderTypes_h 13 | 14 | // Luminance Constants 15 | constant half3 luminanceWeighting = half3(0.2125, 0.7154, 0.0721); // Values from "Graphics Shaders: Theory and Practice" by Bailey and Cunningham 16 | 17 | struct SingleInputVertexIO 18 | { 19 | float4 position [[position]]; 20 | float2 textureCoordinate [[user(texturecoord)]]; 21 | }; 22 | 23 | struct TwoInputVertexIO 24 | { 25 | float4 position [[position]]; 26 | float2 textureCoordinate [[user(texturecoord)]]; 27 | float2 textureCoordinate2 [[user(texturecoord2)]]; 28 | }; 29 | 30 | #endif /* OperationShaderTypes_h */ 31 | -------------------------------------------------------------------------------- /MetalVideoProcess/Vender/Render/Base/Position.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | #if os(iOS) 4 | import UIKit 5 | #endif 6 | 7 | public struct Position { 8 | public let x: Float 9 | public let y: Float 10 | public let z: Float? 11 | 12 | public init (_ x: Float, _ y: Float, _ z: Float? = nil) { 13 | self.x = x 14 | self.y = y 15 | self.z = z 16 | } 17 | 18 | public static let center = Position(0.5, 0.5) 19 | public static let zero = Position(0.0, 0.0) 20 | } 21 | 22 | 23 | public struct Position2D { 24 | public let x: Float 25 | public let y: Float 26 | 27 | public init (_ x: Float, _ y: Float) { 28 | self.x = x 29 | self.y = y 30 | } 31 | 32 | public static let center = Position(0.5, 0.5) 33 | public static let zero = Position(0.0, 0.0) 34 | } 35 | -------------------------------------------------------------------------------- /MetalVideoProcess/Vender/Render/Base/Size.swift: -------------------------------------------------------------------------------- 1 | public struct Size { 2 | public let width: Float 3 | public let height: Float 4 | 5 | public init(width: Float, height: Float) { 6 | self.width = width 7 | self.height = height 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MetalVideoProcess/Vender/Render/Inputs/ImageGenerator.swift: -------------------------------------------------------------------------------- 1 | public class ImageGenerator: ImageSource { 2 | public var trackID: Int32 3 | 4 | public func transmitPreviousImage(to target: ImageConsumer, atIndex: UInt, trackID: Int32) { 5 | target.newTextureAvailable(internalTexture, 6 | fromSourceIndex: atIndex, 7 | trackID: trackID) 8 | } 9 | 10 | public var size: Size 11 | 12 | public let targets = TargetContainer() 13 | var internalTexture: Texture! 14 | 15 | public init(size: Size, 16 | trackID: Int32) { 17 | self.size = size 18 | internalTexture = Texture(device: sharedMetalRenderingDevice.device, orientation: .portrait, width: Int(size.width), height: Int(size.height), timingStyle: .stillImage) 19 | self.trackID = trackID 20 | } 21 | 22 | func notifyTargets() { 23 | updateTargetsWithTexture(internalTexture, trackID: self.trackID) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /MetalVideoProcess/Vender/Render/Inputs/SolidColorGenerator.swift: -------------------------------------------------------------------------------- 1 | public class SolidColorGenerator: ImageGenerator { 2 | 3 | public func renderColor(_ color: Color) { 4 | guard let commandBuffer = sharedMetalRenderingDevice.commandQueue.makeCommandBuffer() else {return} 5 | 6 | commandBuffer.clear(with: color, outputTexture: internalTexture) 7 | 8 | notifyTargets() 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Base/MetalVideoProcessMotion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessMotion.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by RenZhu Macro on 2020/7/20. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | import AVFoundation 10 | 11 | public class MetalVideoProcessMotion: MetalVideoProcessOperation { 12 | 13 | public var factor: Float = 1.0 { 14 | didSet { uniformSettings["factor"] = factor } } 15 | 16 | public var roi: CGRect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0) { 17 | didSet { 18 | uniformSettings["roi"] = Color(red: Float(roi.origin.x), green: Float(roi.origin.y), blue: Float(roi.width), alpha: Float(roi.height)) 19 | } 20 | } 21 | 22 | public var timingType: TimingFunctionType = .linearInterpolation 23 | 24 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 25 | 26 | if self.timelineRange.containsTime(texture.timingStyle.timestamp?.asCMTime ?? CMTime.invalid) { 27 | let distance = CMTime(seconds: texture.frameTime, preferredTimescale: 1000) - self.timelineRange.start 28 | let progress = Float(distance.seconds / self.timelineRange.duration.seconds) 29 | self.factor = self.timingType.timingValue(p: progress) 30 | } 31 | 32 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Base/MetalVideoProcessTransition.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessTransition.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by RenZhu Macro on 2020/7/14. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | import Metal 10 | import AVFoundation 11 | 12 | public class MetalVideoProcessTransition: MetalVideoProcessOperation { 13 | //Transition factor 14 | public var tweenFactor: Float = 1.0 { didSet { uniformSettings["tweenFactor"] = tweenFactor } } 15 | 16 | public var timingType: TimingFunctionType = .linearInterpolation 17 | 18 | open var mainTrackIDs: [Int32] = [] 19 | 20 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 21 | guard let sourceIndex = mainTrackIDs.firstIndex(of: trackID) else { 22 | updateTargetsWithTexture(texture, trackID: trackID) 23 | return 24 | } 25 | 26 | if self.timelineRange.containsTime(texture.timingStyle.timestamp?.asCMTime ?? CMTime.invalid) { 27 | let distance = CMTime(seconds: texture.frameTime, preferredTimescale: 1000) - self.timelineRange.start 28 | let progress = Float(distance.seconds / self.timelineRange.duration.seconds) 29 | self.tweenFactor = self.timingType.timingValue(p: progress) 30 | super.newTextureAvailable(texture, fromSourceIndex: UInt(sourceIndex), trackID: trackID) 31 | } else { 32 | updateTargetsWithTexture(texture, trackID: trackID) 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Filters/MetalVideoProcessBlendFilter.metal: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace metal; 3 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 4 | 5 | typedef struct 6 | { 7 | float mixturePercent; 8 | float blendMode; 9 | } AlphaBlendUniform; 10 | 11 | fragment half4 alphaBlend(TwoInputVertexIO fragmentInput [[stage_in]], 12 | texture2d inputTexture [[texture(0)]], 13 | texture2d inputTexture2 [[texture(1)]], 14 | constant AlphaBlendUniform& uniform [[ buffer(1) ]]) 15 | { 16 | 17 | constexpr sampler quadSampler(mag_filter:: linear, 18 | min_filter:: linear, 19 | address:: clamp_to_zero); 20 | 21 | half4 textureColor = inputTexture.sample(quadSampler, fragmentInput.textureCoordinate); 22 | constexpr sampler quadSampler2(mag_filter:: linear, 23 | min_filter:: linear, 24 | address:: clamp_to_zero); 25 | 26 | half4 textureColor2 = inputTexture2.sample(quadSampler, fragmentInput.textureCoordinate2); 27 | half4 outputCol = half4(0.0); 28 | switch(int(uniform.blendMode)) { 29 | case 0: 30 | outputCol = textureColor * (1. - textureColor2.a) + textureColor2;//mix(textureColor, textureColor2, textureColor2.a); 31 | break; 32 | case 1: 33 | outputCol = half4(textureColor.rgb * textureColor2.a, textureColor.a * textureColor2.a); 34 | break; 35 | default: 36 | outputCol = mix(textureColor, textureColor2, textureColor2.a); 37 | break; 38 | } 39 | return outputCol; 40 | } 41 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Filters/MetalVideoProcessBlendFilter.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessAlphaBlend.swift 3 | // MetalVideoProcessAlphaBlend 4 | // Created by RenZhu Macro on 2020/5/15. 5 | // Copyright © 2020 wangrenzhu Macro. All rights reserved. 6 | // 7 | 8 | import AVFoundation 9 | 10 | public class MetalVideoProcessBlendFilter: MetalVideoProcessOperation { 11 | public var mix: Float = 1.0 { didSet { uniformSettings["mixturePercent"] = mix } } 12 | public var blendMode: Blendmode = .Alpha { didSet { 13 | uniformSettings["blendMode"] = blendMode.rawValue } } 14 | 15 | public enum Blendmode: Float { 16 | case Alpha = 0.0 17 | case Mask = 1.0 18 | } 19 | public var renderSize: CGSize? = nil 20 | public init() { 21 | super.init(fragmentFunctionName: "alphaBlend", numberOfInputs: 2, device: sharedMetalRenderingDevice) 22 | ({mix = 1.0})() 23 | ({blendMode = .Alpha})() 24 | } 25 | 26 | public override func newTextureAvailable(_ inputTexture: Texture, fromSourceIndex: UInt, trackID: Int32) { 27 | self.renderSize = CGSize(width: CGFloat(inputTexture.texture.width), height: CGFloat(inputTexture.texture.height)) 28 | 29 | super.newTextureWithSize(inputTexture, fromSourceIndex: fromSourceIndex, renderSize: renderSize!, trackID: trackID) 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Filters/MetalVideoProcessColorFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessColorFilter.metal 3 | // MetalVideoProcessColorFilter 4 | // 5 | // Created by wangrenzhu Macro on 2020/5/15. 6 | // Copyright © 2020 wangrenzhu Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | 13 | #define vec4 float4 14 | #define vec3 float3 15 | #define vec2 float2 16 | #define mat2 float2x2 17 | #define mat3 float3x3 18 | 19 | using namespace metal; 20 | 21 | typedef struct 22 | { 23 | float strength; 24 | float4 color; 25 | } Uniform; 26 | 27 | fragment half4 colorFragment(SingleInputVertexIO fragmentInput [[stage_in]], 28 | texture2d inputTexture [[texture(0)]], 29 | constant Uniform &uniform [[ buffer(1) ]]) 30 | { 31 | constexpr sampler textureSampler(mag_filter:: linear, 32 | min_filter:: linear, 33 | address:: clamp_to_zero); 34 | half4 bgCol = inputTexture.sample(textureSampler, fragmentInput.textureCoordinate); 35 | 36 | return mix(bgCol, half4(uniform.color), half(uniform.strength)); 37 | } 38 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Filters/MetalVideoProcessColorFilter.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessColorFilter.swift 3 | // MetalVideoProcessColorFilter 4 | // 5 | // Created by wangrenzhu Macro on 2020/5/15. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | import AVFoundation 10 | 11 | public class MetalVideoProcessColorFilter: MetalVideoProcessOperation { 12 | public var renderSize: CGSize? = nil 13 | 14 | public var color: Color 15 | { 16 | get { 17 | return uniformSettings["color"] 18 | } 19 | set { 20 | uniformSettings["color"] = newValue 21 | } 22 | } 23 | 24 | public var strength: Float 25 | { 26 | get { 27 | return uniformSettings["strength"] 28 | } 29 | set { 30 | uniformSettings["strength"] = newValue 31 | } 32 | } 33 | 34 | public init() { 35 | super.init(fragmentFunctionName: "colorFragment", 36 | numberOfInputs: 1, device: sharedMetalRenderingDevice) 37 | strength = 1.0 38 | renderSize = MetalVideoProcessBackground.canvasSize 39 | } 40 | 41 | public override func newTextureAvailable(_ inputTexture: Texture, fromSourceIndex: UInt, trackID: Int32) { 42 | renderSize = MetalVideoProcessBackground.canvasSize 43 | super.newTextureWithSize(inputTexture, fromSourceIndex: fromSourceIndex, renderSize: renderSize!, trackID: trackID) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Filters/MetalVideoProcessLuminance.metal: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 4 | using namespace metal; 5 | 6 | fragment half4 luminanceFragment(SingleInputVertexIO fragmentInput [[stage_in]], 7 | texture2d inputTexture [[texture(0)]]) 8 | { 9 | constexpr sampler quadSampler; 10 | half4 color = inputTexture.sample(quadSampler, fragmentInput.textureCoordinate); 11 | half luminance = dot(color.rgb, luminanceWeighting); 12 | 13 | return half4(half3(luminance), color.a); 14 | } 15 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Filters/MetalVideoProcessLuminance.swift: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // OrpheusMetalRenderLuminance.swift 4 | // OrpheusMetalRenderLuminance 5 | // 6 | // Created by Ruanshengqiang Macro on 2020/5/15. 7 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 8 | // 9 | import Foundation 10 | 11 | public class MetalVideoProcessLuminance: MetalVideoProcessOperation { 12 | public init() { 13 | super.init(fragmentFunctionName: "luminanceFragment", numberOfInputs: 1, device: sharedMetalRenderingDevice) 14 | } 15 | 16 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 17 | 18 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/MetalVideoProcessPlayer+CompositorDelegate.swift: -------------------------------------------------------------------------------- 1 | // MetalVideoProcessPlayer+CompositorDelegate.swift 2 | // MetalVideoProcessPlayer 3 | // 4 | // Created by RenZhu Macro on 2020/6/11. 5 | // Copyright © 2020 RenZhu Macro. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | import AVFoundation 10 | 11 | extension MetalVideoProcessPlayer: MetalVideoProcessCompositorDelegate { 12 | 13 | public func renderRequest(request: AVAsynchronousVideoCompositionRequest) { 14 | if self.isPlaying { 15 | self.requestCache.addRequest(time: request.compositionTime, request: request) 16 | } else { 17 | self.currentRequest = request 18 | } 19 | } 20 | 21 | public func exportRequest(request: AVAsynchronousVideoCompositionRequest) { 22 | let _ = self.audioEncodingTarget?.renderVideoFramesemaphore.wait(timeout: .distantFuture) 23 | self.videoFrameProcessingQueue.async { [weak self] in 24 | autoreleasepool { 25 | guard let `self` = self else { return } 26 | 27 | //这里开始通过request去纹理并process 28 | debugPrint("export:", request.compositionTime.seconds) 29 | self.process(request: request, newTime: request.compositionTime) 30 | 31 | } 32 | } 33 | 34 | 35 | } 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessFadeInMotion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessFadeInMotion.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by RenZhu Macro on 2020/7/21. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public class MetalVideoProcessFadeInMotion: MetalVideoProcessMotion { 12 | 13 | public init() { 14 | super.init(fragmentFunctionName: "fadeInMotion", numberOfInputs: 2, device: sharedMetalRenderingDevice) 15 | self.timingType = .quadraticEaseOut 16 | self.factor = 0.0 17 | } 18 | 19 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 20 | if let time = texture.timingStyle.timestamp?.asCMTime { 21 | if time < timelineRange.start { 22 | factor = 0.0 23 | } 24 | debugPrint("fadein:", factor, " frameTime:", texture.frameTime) 25 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 26 | } 27 | } 28 | 29 | 30 | /// before fade in, we need the texture alpha keep to zero 31 | /// - Parameter texture: texture 32 | /// - Returns: result 33 | public override func checkTimelineRange(with texture: Texture) -> (Bool) { 34 | return true 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessFadeOutMotion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessFadeOutMotion.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by RenZhu Macro on 2020/7/21. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public class MetalVideoProcessFadeOutMotion: MetalVideoProcessMotion { 12 | 13 | public init() { 14 | super.init(fragmentFunctionName: "fadeOutMotion", numberOfInputs: 2, device: sharedMetalRenderingDevice) 15 | self.timingType = .quadraticEaseOut 16 | } 17 | // 18 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 19 | // if let time = texture.timingStyle.timestamp?.asCMTime { 20 | // if time > timelineRange.end { 21 | // factor = 1.0 22 | // } 23 | // 24 | // 25 | // debugPrint("fadeout:", factor, " frameTime:", texture.frameTime) 26 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 27 | // } 28 | } 29 | 30 | /// after fade out, we need the texture alpha keep to zero 31 | /// - Parameter texture: texture 32 | /// - Returns: result 33 | public override func checkTimelineRange(with texture: Texture) -> (Bool) { 34 | return true 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessMirrorRotateMotion.metal: -------------------------------------------------------------------------------- 1 | // 2 | // mirrorRotateMotion.metal 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | 13 | namespace mirrorRotateMotion { 14 | typedef struct 15 | { 16 | float factor; 17 | float4 roi; 18 | } MotionUniform; 19 | 20 | fragment half4 mirrorRotateMotion(TwoInputVertexIO fragmentInput [[stage_in]], 21 | texture2d inputTexture [[texture(0)]], 22 | texture2d inputTexture2 [[texture(1)]], 23 | constant MotionUniform& uniform [[ buffer(1) ]]) 24 | { 25 | constexpr sampler quadSampler(mip_filter::linear, min_filter::linear, mag_filter::linear, address::clamp_to_zero); 26 | 27 | half4 bgCol = inputTexture.sample(quadSampler, fragmentInput.textureCoordinate); 28 | float2 center = float2(uniform.roi.r + uniform.roi.b * 0.5, uniform.roi.g + uniform.roi.a * 0.5); 29 | float2 uv = fragmentInput.textureCoordinate2; 30 | 31 | float2 tempUv = uv; 32 | float curve = uniform.factor; 33 | half4 outCol = half4(0.0); 34 | if (curve < 0.5) { 35 | tempUv = float2((tempUv.x - center.x) * -(1. + curve * 200.0) + center.x, uv.y); 36 | outCol = inputTexture2.sample(quadSampler, tempUv.xy); 37 | } else { 38 | tempUv = float2((tempUv.x - center.x) * (1. + (1.0 - curve) * 200.0) + center.x, uv.y); 39 | outCol = inputTexture2.sample(quadSampler, tempUv.xy); 40 | } 41 | 42 | return half4(bgCol.rgb * (1. - outCol.a) + outCol.rgb, outCol.a); 43 | } 44 | } 45 | 46 | 47 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessMirrorRotateMotion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessMirrorRotateMotion.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public class MetalVideoProcessMirrorRotateMotion: MetalVideoProcessMotion { 12 | 13 | public init() { 14 | super.init(fragmentFunctionName: "mirrorRotateMotion", numberOfInputs: 2, device: sharedMetalRenderingDevice) 15 | self.timingType = .linearInterpolation 16 | self.factor = 0.0 17 | } 18 | 19 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 20 | if let time = texture.timingStyle.timestamp?.asCMTime { 21 | if time < timelineRange.start { 22 | factor = 0.0 23 | } 24 | 25 | debugPrint("mirrorRotateMotion:", factor, " frameTime:", texture.frameTime) 26 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 27 | } 28 | } 29 | 30 | /// before fade in, we need the texture alpha keep to zero 31 | /// - Parameter texture: texture 32 | /// - Returns: result 33 | 34 | public override func checkTimelineRange(with texture: Texture) -> (Bool) { 35 | return true 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessMoveDownMotion.metal: -------------------------------------------------------------------------------- 1 | // 2 | // moveDownMotion.metal 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | 13 | namespace moveDownMotion { 14 | typedef struct 15 | { 16 | float factor; 17 | float4 roi; 18 | } MotionUniform; 19 | 20 | fragment half4 moveDownMotion(TwoInputVertexIO fragmentInput [[stage_in]], 21 | texture2d inputTexture [[texture(0)]], 22 | texture2d inputTexture2 [[texture(1)]], 23 | constant MotionUniform& uniform [[ buffer(1) ]]) 24 | { 25 | 26 | constexpr sampler quadSampler(mip_filter::linear, min_filter::linear, mag_filter::linear, address::clamp_to_zero); 27 | 28 | half4 bgCol = inputTexture.sample(quadSampler, fragmentInput.textureCoordinate); 29 | 30 | float2 uv = fragmentInput.textureCoordinate2; 31 | 32 | half4 fgCol = inputTexture2.sample(quadSampler, uv + float2(0.0, uniform.roi.a) - float2(0.0, uniform.roi.a * uniform.factor)); 33 | 34 | return half4(bgCol.rgb * (1. - fgCol.a) + fgCol.rgb, fgCol.a); 35 | } 36 | } 37 | 38 | 39 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessMoveDownMotion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessMoveDownMotion.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public class MetalVideoProcessMoveDownMotion: MetalVideoProcessMotion { 12 | 13 | public init() { 14 | super.init(fragmentFunctionName: "moveDownMotion", numberOfInputs: 2, device: sharedMetalRenderingDevice) 15 | self.timingType = .quadraticEaseIn 16 | self.factor = 0.0 17 | } 18 | 19 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 20 | if let time = texture.timingStyle.timestamp?.asCMTime { 21 | if time < timelineRange.start { 22 | factor = 0.0 23 | } 24 | 25 | debugPrint("moveUpMotion:", factor, " frameTime:", texture.frameTime) 26 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 27 | } 28 | } 29 | 30 | /// before fade in, we need the texture alpha keep to zero 31 | /// - Parameter texture: texture 32 | /// - Returns: result 33 | public override func checkTimelineRange(with texture: Texture) -> (Bool) { 34 | return true 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessMoveLeftMotion.metal: -------------------------------------------------------------------------------- 1 | // 2 | // rotateMotion.metal 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | 13 | namespace moveLeftMotion { 14 | typedef struct 15 | { 16 | float factor; 17 | float4 roi; 18 | } MotionUniform; 19 | 20 | fragment half4 moveLeftMotion(TwoInputVertexIO fragmentInput [[stage_in]], 21 | texture2d inputTexture [[texture(0)]], 22 | texture2d inputTexture2 [[texture(1)]], 23 | constant MotionUniform& uniform [[ buffer(1) ]]) 24 | { 25 | 26 | constexpr sampler quadSampler(mip_filter::linear, min_filter::linear, mag_filter::linear, address::clamp_to_zero); 27 | 28 | half4 bgCol = inputTexture.sample(quadSampler, fragmentInput.textureCoordinate); 29 | 30 | float2 uv = fragmentInput.textureCoordinate2; 31 | 32 | half4 fgCol = inputTexture2.sample(quadSampler, uv - float2(uniform.roi.b, 0.0) + float2(uniform.roi.b * uniform.factor, 0.0)); 33 | 34 | return half4(bgCol.rgb * (1. - fgCol.a) + fgCol.rgb, fgCol.a); 35 | } 36 | } 37 | 38 | 39 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessMoveLeftMotion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessMoveLeftMotion.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public class MetalVideoProcessMoveLeftMotion: MetalVideoProcessMotion { 12 | 13 | public init() { 14 | super.init(fragmentFunctionName: "moveLeftMotion", numberOfInputs: 2, device: sharedMetalRenderingDevice) 15 | self.timingType = .linearInterpolation 16 | self.factor = 0.0 17 | } 18 | 19 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 20 | if let time = texture.timingStyle.timestamp?.asCMTime { 21 | if time < timelineRange.start { 22 | factor = 0.0 23 | } 24 | 25 | debugPrint("moveLeftMotion:", factor, " frameTime:", texture.frameTime) 26 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 27 | } 28 | } 29 | 30 | /// before fade in, we need the texture alpha keep to zero 31 | /// - Parameter texture: texture 32 | /// - Returns: result 33 | public override func checkTimelineRange(with texture: Texture) -> (Bool) { 34 | return true 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessMoveRightMotion.metal: -------------------------------------------------------------------------------- 1 | // 2 | // moveRightMotion.metal 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | 13 | namespace moveRightMotion { 14 | typedef struct 15 | { 16 | float factor; 17 | float4 roi; 18 | } MotionUniform; 19 | 20 | fragment half4 moveRightMotion(TwoInputVertexIO fragmentInput [[stage_in]], 21 | texture2d inputTexture [[texture(0)]], 22 | texture2d inputTexture2 [[texture(1)]], 23 | constant MotionUniform& uniform [[ buffer(1) ]]) 24 | { 25 | 26 | constexpr sampler quadSampler(mip_filter::linear, min_filter::linear, mag_filter::linear, address::clamp_to_zero); 27 | 28 | half4 bgCol = inputTexture.sample(quadSampler, fragmentInput.textureCoordinate); 29 | 30 | float2 uv = fragmentInput.textureCoordinate2; 31 | 32 | half4 fgCol = inputTexture2.sample(quadSampler, uv + float2(uniform.roi.b, 0.0) - float2(uniform.roi.b * uniform.factor, 0.0)); 33 | 34 | return half4(bgCol.rgb * (1. - fgCol.a) + fgCol.rgb, fgCol.a); 35 | } 36 | } 37 | 38 | 39 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessMoveRightMotion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessMoveRightMotion.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public class MetalVideoProcessMoveRightMotion: MetalVideoProcessMotion { 12 | 13 | public init() { 14 | super.init(fragmentFunctionName: "moveRightMotion", numberOfInputs: 2, device: sharedMetalRenderingDevice) 15 | self.timingType = .linearInterpolation 16 | self.factor = 0.0 17 | } 18 | 19 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 20 | if let time = texture.timingStyle.timestamp?.asCMTime { 21 | if time < timelineRange.start { 22 | factor = 0.0 23 | } 24 | 25 | debugPrint("moveLeftMotion:", factor, " frameTime:", texture.frameTime) 26 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 27 | } 28 | } 29 | 30 | /// before fade in, we need the texture alpha keep to zero 31 | /// - Parameter texture: texture 32 | /// - Returns: result 33 | public override func checkTimelineRange(with texture: Texture) -> (Bool) { 34 | return true 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessMoveUpMotion.metal: -------------------------------------------------------------------------------- 1 | // 2 | // rotateMotion.metal 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | 13 | namespace moveUpMotion { 14 | typedef struct 15 | { 16 | float factor; 17 | float4 roi; 18 | } MotionUniform; 19 | 20 | fragment half4 moveUpMotion(TwoInputVertexIO fragmentInput [[stage_in]], 21 | texture2d inputTexture [[texture(0)]], 22 | texture2d inputTexture2 [[texture(1)]], 23 | constant MotionUniform& uniform [[ buffer(1) ]]) 24 | { 25 | 26 | constexpr sampler quadSampler(mip_filter::linear, min_filter::linear, mag_filter::linear, address::clamp_to_zero); 27 | 28 | half4 bgCol = inputTexture.sample(quadSampler, fragmentInput.textureCoordinate); 29 | 30 | float2 uv = fragmentInput.textureCoordinate2; 31 | 32 | half4 fgCol = inputTexture2.sample(quadSampler, uv - float2(0.0, uniform.roi.a) + float2(0.0, uniform.roi.a * uniform.factor)); 33 | 34 | return half4(bgCol.rgb * (1. - fgCol.a) + fgCol.rgb, fgCol.a); 35 | } 36 | } 37 | 38 | 39 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessMoveUpMotion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessMoveUpMotion.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public class MetalVideoProcessMoveUpMotion: MetalVideoProcessMotion { 12 | 13 | public init() { 14 | super.init(fragmentFunctionName: "moveUpMotion", numberOfInputs: 2, device: sharedMetalRenderingDevice) 15 | self.timingType = .quadraticEaseIn 16 | self.factor = 0.0 17 | } 18 | 19 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 20 | if let time = texture.timingStyle.timestamp?.asCMTime { 21 | if time < timelineRange.start { 22 | factor = 0.0 23 | } 24 | 25 | debugPrint("moveUpMotion:", factor, " frameTime:", texture.frameTime) 26 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 27 | } 28 | } 29 | 30 | /// before fade in, we need the texture alpha keep to zero 31 | /// - Parameter texture: texture 32 | /// - Returns: result 33 | public override func checkTimelineRange(with texture: Texture) -> (Bool) { 34 | return true 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessPendulumMotion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessPendulumMotion.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public class MetalVideoProcessPendulumMotion: MetalVideoProcessMotion { 12 | 13 | var iResolution: Position { 14 | set { 15 | uniformSettings["iResolution"] = newValue 16 | } 17 | get { 18 | return uniformSettings["iResolution"] 19 | } 20 | } 21 | 22 | public init() { 23 | super.init(fragmentFunctionName: "pendulumMotion", numberOfInputs: 2, device: sharedMetalRenderingDevice) 24 | self.timingType = .linearInterpolation 25 | self.factor = 0.0 26 | } 27 | 28 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 29 | if let time = texture.timingStyle.timestamp?.asCMTime { 30 | if time < timelineRange.start { 31 | factor = 0.0 32 | } 33 | 34 | self.iResolution = Position(Float(texture.texture.width), Float(texture.texture.height)) 35 | debugPrint("pendulumMotion:", factor, " frameTime:", texture.frameTime) 36 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 37 | } 38 | } 39 | 40 | /// before fade in, we need the texture alpha keep to zero 41 | /// - Parameter texture: texture 42 | /// - Returns: result 43 | public override func checkTimelineRange(with texture: Texture) -> (Bool) { 44 | return true 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessRightDropMotion.metal: -------------------------------------------------------------------------------- 1 | // 2 | // pendulumMotion.metal 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | #define PI 3.1415926 13 | namespace rightDropMotion { 14 | typedef struct 15 | { 16 | float factor; 17 | float4 roi; 18 | float2 iResolution; 19 | } MotionUniform; 20 | 21 | fragment half4 rightDropMotion(TwoInputVertexIO fragmentInput [[stage_in]], 22 | texture2d inputTexture [[texture(0)]], 23 | texture2d inputTexture2 [[texture(1)]], 24 | constant MotionUniform& uniform [[ buffer(1) ]]) 25 | { 26 | 27 | constexpr sampler quadSampler(mip_filter::linear, min_filter::linear, mag_filter::linear, address::clamp_to_zero); 28 | 29 | half4 bgCol = inputTexture.sample(quadSampler, fragmentInput.textureCoordinate); 30 | 31 | float2 center = float2(uniform.roi.r + uniform.roi.b * 0.5, uniform.roi.g); 32 | float time = cos(uniform.factor * PI * 2.5) * exp(-uniform.factor); 33 | float2 uv = fragmentInput.textureCoordinate2 + float2(0.5, 0.0) * time; 34 | 35 | float2 dir = float2(0.1, 0.0) * time; 36 | 37 | half4 fgCol = half4(0.0); 38 | for(float i = 0.0; i < 1.0; i = i + 0.1) { 39 | fgCol += inputTexture2.sample(quadSampler, uv + dir * i); 40 | } 41 | 42 | fgCol /= 10.0; 43 | return half4(bgCol.rgb * (1. - fgCol.a) + fgCol.rgb, fgCol.a); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessRightDropMotion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessRightDropMotion.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public class MetalVideoProcessRightDropMotion: MetalVideoProcessMotion { 12 | 13 | var iResolution: Position { 14 | set { 15 | uniformSettings["iResolution"] = newValue 16 | } 17 | get { 18 | return uniformSettings["iResolution"] 19 | } 20 | } 21 | 22 | public init() { 23 | super.init(fragmentFunctionName: "rightDropMotion", numberOfInputs: 2, device: sharedMetalRenderingDevice) 24 | self.timingType = .linearInterpolation 25 | self.factor = 0.0 26 | } 27 | 28 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 29 | if let time = texture.timingStyle.timestamp?.asCMTime { 30 | if time < timelineRange.start { 31 | factor = 0.0 32 | } 33 | 34 | self.iResolution = Position(Float(texture.texture.width), Float(texture.texture.height)) 35 | debugPrint("rightDropMotion:", factor, " frameTime:", texture.frameTime) 36 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 37 | } 38 | } 39 | 40 | /// before fade in, we need the texture alpha keep to zero 41 | /// - Parameter texture: texture 42 | /// - Returns: result 43 | public override func checkTimelineRange(with texture: Texture) -> (Bool) { 44 | return true 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessRotateInRightMotion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessRotateMotion.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public class MetalVideoProcessRotateInRightMotion: MetalVideoProcessMotion { 12 | 13 | var iResolution: Position { 14 | set { 15 | uniformSettings["iResolution"] = newValue 16 | } 17 | get { 18 | return uniformSettings["iResolution"] 19 | } 20 | } 21 | 22 | public init() { 23 | super.init(fragmentFunctionName: "rotateInRightMotion", numberOfInputs: 2, device: sharedMetalRenderingDevice) 24 | self.timingType = .quadraticEaseOut 25 | self.factor = 0.0 26 | } 27 | 28 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 29 | if let time = texture.timingStyle.timestamp?.asCMTime { 30 | if time < timelineRange.start { 31 | factor = 0.0 32 | } 33 | 34 | self.iResolution = Position(Float(texture.texture.width), Float(texture.texture.height)) 35 | debugPrint("rotateMotion:", factor, " frameTime:", texture.frameTime) 36 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 37 | } 38 | } 39 | 40 | /// before fade in, we need the texture alpha keep to zero 41 | /// - Parameter texture: texture 42 | /// - Returns: result 43 | public override func checkTimelineRange(with texture: Texture) -> (Bool) { 44 | return true 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessRotateMotion.metal: -------------------------------------------------------------------------------- 1 | // 2 | // rotateMotion.metal 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | 13 | namespace rotateMotion { 14 | typedef struct 15 | { 16 | float factor; 17 | float4 roi; 18 | float2 iResolution; 19 | 20 | } MotionUniform; 21 | 22 | fragment half4 rotateMotion(TwoInputVertexIO fragmentInput [[stage_in]], 23 | texture2d inputTexture [[texture(0)]], 24 | texture2d inputTexture2 [[texture(1)]], 25 | constant MotionUniform& uniform [[ buffer(1) ]]) 26 | { 27 | 28 | constexpr sampler quadSampler(mip_filter::linear, min_filter::linear, mag_filter::linear, address::clamp_to_zero); 29 | float2 center = float2(uniform.roi.r + uniform.roi.b * 0.5, uniform.roi.g + uniform.roi.a * 0.5); 30 | 31 | half4 bgCol = inputTexture.sample(quadSampler, fragmentInput.textureCoordinate); 32 | 33 | float2 uv = fragmentInput.textureCoordinate2; 34 | 35 | float rotCorner = uniform.factor * 25.1327408; 36 | float2 rot = float2(cos(rotCorner), sin(rotCorner)); 37 | 38 | uv = (uv - center) * uniform.iResolution; 39 | uv = float2(rot.x * uv.x + rot.y * uv.y, -rot.y * uv.x + rot.x * uv.y); 40 | uv = uv / uniform.iResolution + center; 41 | 42 | half4 fgCol = inputTexture2.sample(quadSampler, uv); 43 | 44 | return half4(bgCol.rgb * (1. - fgCol.a) + fgCol.rgb, fgCol.a); 45 | } 46 | } 47 | 48 | 49 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessRotateMotion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessRotateMotion.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public class MetalVideoProcessRotateMotion: MetalVideoProcessMotion { 12 | 13 | var iResolution: Position { 14 | set { 15 | uniformSettings["iResolution"] = newValue 16 | } 17 | get { 18 | return uniformSettings["iResolution"] 19 | } 20 | } 21 | 22 | public init() { 23 | super.init(fragmentFunctionName: "rotateMotion", numberOfInputs: 2, device: sharedMetalRenderingDevice) 24 | self.timingType = .quadraticEaseOut 25 | self.factor = 0.0 26 | } 27 | 28 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 29 | if let time = texture.timingStyle.timestamp?.asCMTime { 30 | if time < timelineRange.start { 31 | factor = 0.0 32 | } 33 | 34 | self.iResolution = Position(Float(texture.texture.width), Float(texture.texture.height)) 35 | debugPrint("rotateMotion:", factor, " frameTime:", texture.frameTime) 36 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 37 | } 38 | } 39 | 40 | /// before fade in, we need the texture alpha keep to zero 41 | /// - Parameter texture: texture 42 | /// - Returns: result 43 | public override func checkTimelineRange(with texture: Texture) -> (Bool) { 44 | return true 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessSlimZoomInMotion.metal: -------------------------------------------------------------------------------- 1 | // 2 | // slimZoomInMotion.metal 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | 13 | namespace slimZoomInMotion { 14 | typedef struct 15 | { 16 | float factor; 17 | float4 roi; 18 | } MotionUniform; 19 | 20 | fragment half4 slimZoomInMotion(TwoInputVertexIO fragmentInput [[stage_in]], 21 | texture2d inputTexture [[texture(0)]], 22 | texture2d inputTexture2 [[texture(1)]], 23 | constant MotionUniform& uniform [[ buffer(1) ]]) 24 | { 25 | constexpr sampler quadSampler(mip_filter::linear, min_filter::linear, mag_filter::linear, address::clamp_to_zero); 26 | 27 | half4 bgCol = inputTexture.sample(quadSampler, fragmentInput.textureCoordinate); 28 | float2 center = float2(uniform.roi.r + uniform.roi.b * 0.5, uniform.roi.g + uniform.roi.a * 0.5); 29 | float2 uv = fragmentInput.textureCoordinate2; 30 | 31 | half4 fgCol = inputTexture2.sample(quadSampler, (uv - center) * (1.2 - uniform.factor * 0.2) + center); 32 | return half4(bgCol.rgb * (1. - fgCol.a) + fgCol.rgb, fgCol.a); 33 | } 34 | } 35 | 36 | 37 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessSlimZoomInMotion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessSlimZoomInMotion.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public class MetalVideoProcessSlimZoomInMotion: MetalVideoProcessMotion { 12 | 13 | public init() { 14 | super.init(fragmentFunctionName: "slimZoomInMotion", numberOfInputs: 2, device: sharedMetalRenderingDevice) 15 | self.timingType = .quadraticEaseIn 16 | self.factor = 0.0 17 | } 18 | 19 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 20 | if let time = texture.timingStyle.timestamp?.asCMTime { 21 | if time < timelineRange.start { 22 | factor = 0.0 23 | } 24 | 25 | debugPrint("slimZoomInMotion:", factor, " frameTime:", texture.frameTime) 26 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 27 | } 28 | } 29 | 30 | /// before fade in, we need the texture alpha keep to zero 31 | /// - Parameter texture: texture 32 | /// - Returns: result 33 | 34 | public override func checkTimelineRange(with texture: Texture) -> (Bool) { 35 | return true 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessSwirlMotion.metal: -------------------------------------------------------------------------------- 1 | // 2 | // swirlMotion.metal 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | 13 | namespace swirlMotion { 14 | typedef struct 15 | { 16 | float factor; 17 | float4 roi; 18 | float2 iResolution; 19 | 20 | } MotionUniform; 21 | 22 | fragment half4 swirlMotion(TwoInputVertexIO fragmentInput [[stage_in]], 23 | texture2d inputTexture [[texture(0)]], 24 | texture2d inputTexture2 [[texture(1)]], 25 | constant MotionUniform& uniform [[ buffer(1) ]]) 26 | { 27 | 28 | constexpr sampler quadSampler(mip_filter::linear, min_filter::linear, mag_filter::linear, address::clamp_to_zero); 29 | float2 center = float2(uniform.roi.r + uniform.roi.b * 0.5, uniform.roi.g + uniform.roi.a * 0.5); 30 | 31 | half4 bgCol = inputTexture.sample(quadSampler, fragmentInput.textureCoordinate); 32 | 33 | float2 uv = fragmentInput.textureCoordinate2; 34 | 35 | float2 tempUv = uv - center; 36 | float theta = atan2(tempUv.y, tempUv.x); 37 | float r = length(tempUv); 38 | theta = theta + r * 20.0 * (1. - uniform.factor); 39 | uv = float2(r * cos(theta), r * sin(theta)) + center; 40 | 41 | half4 fgCol = inputTexture2.sample(quadSampler, uv); 42 | 43 | return half4(bgCol.rgb * (1. - fgCol.a) + fgCol.rgb, fgCol.a); 44 | } 45 | } 46 | 47 | 48 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessSwirlMotion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessSwirlMotion.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public class MetalVideoProcessSwirlMotion: MetalVideoProcessMotion { 12 | 13 | var iResolution: Position { 14 | set { 15 | uniformSettings["iResolution"] = newValue 16 | } 17 | get { 18 | return uniformSettings["iResolution"] 19 | } 20 | } 21 | 22 | public init() { 23 | super.init(fragmentFunctionName: "swirlMotion", numberOfInputs: 2, device: sharedMetalRenderingDevice) 24 | self.timingType = .quadraticEaseOut 25 | self.factor = 0.0 26 | } 27 | 28 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 29 | if let time = texture.timingStyle.timestamp?.asCMTime { 30 | if time < timelineRange.start { 31 | factor = 0.0 32 | } 33 | 34 | self.iResolution = Position(Float(texture.texture.width), Float(texture.texture.height)) 35 | debugPrint("rotateMotion:", factor, " frameTime:", texture.frameTime) 36 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 37 | } 38 | } 39 | 40 | /// before fade in, we need the texture alpha keep to zero 41 | /// - Parameter texture: texture 42 | /// - Returns: result 43 | public override func checkTimelineRange(with texture: Texture) -> (Bool) { 44 | return true 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessUpDropMotion.metal: -------------------------------------------------------------------------------- 1 | // 2 | // pendulumMotion.metal 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | #define PI 3.1415926 13 | namespace upDropMotion { 14 | typedef struct 15 | { 16 | float factor; 17 | float4 roi; 18 | float2 iResolution; 19 | } MotionUniform; 20 | 21 | fragment half4 upDropMotion(TwoInputVertexIO fragmentInput [[stage_in]], 22 | texture2d inputTexture [[texture(0)]], 23 | texture2d inputTexture2 [[texture(1)]], 24 | constant MotionUniform& uniform [[ buffer(1) ]]) 25 | { 26 | 27 | constexpr sampler quadSampler(mip_filter::linear, min_filter::linear, mag_filter::linear, address::clamp_to_zero); 28 | 29 | half4 bgCol = inputTexture.sample(quadSampler, fragmentInput.textureCoordinate); 30 | 31 | float2 center = float2(uniform.roi.r + uniform.roi.b * 0.5, uniform.roi.g); 32 | float time = cos(uniform.factor * PI * 2.5) * exp(-uniform.factor); 33 | float2 uv = fragmentInput.textureCoordinate2 + float2(0.0, 0.5) * time; 34 | 35 | float2 dir = float2(0.0, 0.1) * time; 36 | 37 | half4 fgCol = half4(0.0); 38 | for(float i = 0.0; i < 1.0; i = i + 0.1) { 39 | fgCol += inputTexture2.sample(quadSampler, uv + dir * i); 40 | } 41 | 42 | fgCol /= 10.0; 43 | return half4(bgCol.rgb * (1. - fgCol.a) + fgCol.rgb, fgCol.a); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessUpDropMotion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessUpDropMotion.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public class MetalVideoProcessUpDropMotion: MetalVideoProcessMotion { 12 | 13 | var iResolution: Position { 14 | set { 15 | uniformSettings["iResolution"] = newValue 16 | } 17 | get { 18 | return uniformSettings["iResolution"] 19 | } 20 | } 21 | 22 | public init() { 23 | super.init(fragmentFunctionName: "upDropMotion", numberOfInputs: 2, device: sharedMetalRenderingDevice) 24 | self.timingType = .linearInterpolation 25 | self.factor = 0.0 26 | } 27 | 28 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 29 | if let time = texture.timingStyle.timestamp?.asCMTime { 30 | if time < timelineRange.start { 31 | factor = 0.0 32 | } 33 | 34 | self.iResolution = Position(Float(texture.texture.width), Float(texture.texture.height)) 35 | debugPrint("upDropMotion:", factor, " frameTime:", texture.frameTime) 36 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 37 | } 38 | } 39 | 40 | /// before fade in, we need the texture alpha keep to zero 41 | /// - Parameter texture: texture 42 | /// - Returns: result 43 | public override func checkTimelineRange(with texture: Texture) -> (Bool) { 44 | return true 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessUpMoveInBlurIIMotion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessUpMoveInBlurIIMotion.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public class MetalVideoProcessUpMoveInBlurIIMotion: MetalVideoProcessMotion { 12 | 13 | var iResolution: Position { 14 | set { 15 | uniformSettings["iResolution"] = newValue 16 | } 17 | get { 18 | return uniformSettings["iResolution"] 19 | } 20 | } 21 | 22 | public init() { 23 | super.init(fragmentFunctionName: "upMoveInBlurIIMotion", numberOfInputs: 2, device: sharedMetalRenderingDevice) 24 | self.timingType = .quadraticEaseOut 25 | self.factor = 0.0 26 | } 27 | 28 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 29 | if let time = texture.timingStyle.timestamp?.asCMTime { 30 | if time < timelineRange.start { 31 | factor = 0.0 32 | } 33 | 34 | self.iResolution = Position(Float(texture.texture.width), Float(texture.texture.height)) 35 | debugPrint("upMoveInBlurMotion:", factor, " frameTime:", texture.frameTime) 36 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 37 | } 38 | } 39 | 40 | /// before fade in, we need the texture alpha keep to zero 41 | /// - Parameter texture: texture 42 | /// - Returns: result 43 | public override func checkTimelineRange(with texture: Texture) -> (Bool) { 44 | return true 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessUpMoveInBlurMotion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessUpMoveInBlurMotion.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public class MetalVideoProcessUpMoveInBlurMotion: MetalVideoProcessMotion { 12 | 13 | var iResolution: Position { 14 | set { 15 | uniformSettings["iResolution"] = newValue 16 | } 17 | get { 18 | return uniformSettings["iResolution"] 19 | } 20 | } 21 | 22 | public init() { 23 | super.init(fragmentFunctionName: "upMoveInBlurMotion", numberOfInputs: 2, device: sharedMetalRenderingDevice) 24 | self.timingType = .quadraticEaseOut 25 | self.factor = 0.0 26 | } 27 | 28 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 29 | if let time = texture.timingStyle.timestamp?.asCMTime { 30 | if time < timelineRange.start { 31 | factor = 0.0 32 | } 33 | 34 | self.iResolution = Position(Float(texture.texture.width), Float(texture.texture.height)) 35 | debugPrint("upMoveInBlurMotion:", factor, " frameTime:", texture.frameTime) 36 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 37 | } 38 | } 39 | 40 | /// before fade in, we need the texture alpha keep to zero 41 | /// - Parameter texture: texture 42 | /// - Returns: result 43 | public override func checkTimelineRange(with texture: Texture) -> (Bool) { 44 | return true 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessWiperMotion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessUpMoveInBlurIIMotion.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public class MetalVideoProcessWiperMotion: MetalVideoProcessMotion { 12 | 13 | var iResolution: Position { 14 | set { 15 | uniformSettings["iResolution"] = newValue 16 | } 17 | get { 18 | return uniformSettings["iResolution"] 19 | } 20 | } 21 | 22 | public init() { 23 | super.init(fragmentFunctionName: "wiperMotion", numberOfInputs: 2, device: sharedMetalRenderingDevice) 24 | self.timingType = .linearInterpolation 25 | self.factor = 0.0 26 | } 27 | 28 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 29 | if let time = texture.timingStyle.timestamp?.asCMTime { 30 | if time < timelineRange.start { 31 | factor = 0.0 32 | } 33 | 34 | self.iResolution = Position(Float(texture.texture.width), Float(texture.texture.height)) 35 | debugPrint("wiperMotion:", factor, " frameTime:", texture.frameTime) 36 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 37 | } 38 | } 39 | 40 | /// before fade in, we need the texture alpha keep to zero 41 | /// - Parameter texture: texture 42 | /// - Returns: result 43 | public override func checkTimelineRange(with texture: Texture) -> (Bool) { 44 | return true 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessZoomInBlurMotion.metal: -------------------------------------------------------------------------------- 1 | // 2 | // zoomOutBluMotion.metal 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | 13 | namespace zoomInBlurMotion { 14 | typedef struct 15 | { 16 | float factor; 17 | float4 roi; 18 | float2 iResolution; 19 | } MotionUniform; 20 | 21 | fragment half4 zoomInBlurMotion(TwoInputVertexIO fragmentInput [[stage_in]], 22 | texture2d inputTexture [[texture(0)]], 23 | texture2d inputTexture2 [[texture(1)]], 24 | constant MotionUniform& uniform [[ buffer(1) ]]) 25 | { 26 | 27 | constexpr sampler quadSampler(mip_filter::linear, min_filter::linear, mag_filter::linear, address::clamp_to_zero); 28 | 29 | half4 bgCol = inputTexture.sample(quadSampler, fragmentInput.textureCoordinate); 30 | 31 | float2 center = float2(uniform.roi.r + uniform.roi.b * 0.5, uniform.roi.g + uniform.roi.a * 0.5); 32 | float time = clamp(uniform.factor * 2.0, 0.0, 1.0); 33 | float2 uv = fragmentInput.textureCoordinate2; 34 | 35 | uv = (uv - center); 36 | uv = uv * (3.0 - 2.0 * uniform.factor) + center; 37 | 38 | float2 dir = float2(uv - center) * 0.5 * (1. - time); 39 | 40 | half4 fgCol = half4(0.0); 41 | for(float i = 0.0; i < 1.0; i = i + 0.1) { 42 | fgCol += inputTexture2.sample(quadSampler, uv + dir * i); 43 | } 44 | 45 | fgCol /= 10.0; 46 | return half4(bgCol.rgb * (1. - fgCol.a) + fgCol.rgb, fgCol.a); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessZoomInBlurMotion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessZoomOutBlurMotion.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public class MetalVideoProcessZoomInBlurMotion: MetalVideoProcessMotion { 12 | 13 | var iResolution: Position { 14 | set { 15 | uniformSettings["iResolution"] = newValue 16 | } 17 | get { 18 | return uniformSettings["iResolution"] 19 | } 20 | } 21 | 22 | public init() { 23 | super.init(fragmentFunctionName: "zoomInBlurMotion", numberOfInputs: 2, device: sharedMetalRenderingDevice) 24 | self.timingType = .quadraticEaseOut 25 | self.factor = 0.0 26 | } 27 | 28 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 29 | if let time = texture.timingStyle.timestamp?.asCMTime { 30 | if time < timelineRange.start { 31 | factor = 0.0 32 | } 33 | 34 | self.iResolution = Position(Float(texture.texture.width), Float(texture.texture.height)) 35 | debugPrint("zoomInBlurMotion:", factor, " frameTime:", texture.frameTime) 36 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 37 | } 38 | } 39 | 40 | /// before fade in, we need the texture alpha keep to zero 41 | /// - Parameter texture: texture 42 | /// - Returns: result 43 | public override func checkTimelineRange(with texture: Texture) -> (Bool) { 44 | return true 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessZoomInMotion.metal: -------------------------------------------------------------------------------- 1 | // 2 | // rotateMotion.metal 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | 13 | namespace zoomInMotion { 14 | typedef struct 15 | { 16 | float factor; 17 | float4 roi; 18 | //float2 iResolution; 19 | } MotionUniform; 20 | 21 | fragment half4 zoomInMotion(TwoInputVertexIO fragmentInput [[stage_in]], 22 | texture2d inputTexture [[texture(0)]], 23 | texture2d inputTexture2 [[texture(1)]], 24 | constant MotionUniform& uniform [[ buffer(1) ]]) 25 | { 26 | 27 | constexpr sampler quadSampler(mip_filter::linear, min_filter::linear, mag_filter::linear, address::clamp_to_zero); 28 | 29 | half4 bgCol = inputTexture.sample(quadSampler, fragmentInput.textureCoordinate); 30 | float2 center = float2(uniform.roi.r + uniform.roi.b * 0.5, uniform.roi.g + uniform.roi.a * 0.5); 31 | float2 uv = fragmentInput.textureCoordinate2; 32 | 33 | half4 fgCol = inputTexture2.sample(quadSampler, (uv - center) * (2. - uniform.factor) + center); 34 | 35 | return half4(bgCol.rgb * (1. - fgCol.a) + fgCol.rgb, fgCol.a); 36 | } 37 | } 38 | 39 | 40 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessZoomInMotion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessMoveInMotion.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public class MetalVideoProcessZoomInMotion: MetalVideoProcessMotion { 12 | 13 | public init() { 14 | super.init(fragmentFunctionName: "zoomInMotion", numberOfInputs: 2, device: sharedMetalRenderingDevice) 15 | self.timingType = .quadraticEaseIn 16 | self.factor = 0.0 17 | } 18 | 19 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 20 | if let time = texture.timingStyle.timestamp?.asCMTime { 21 | if time < timelineRange.start { 22 | factor = 0.0 23 | } 24 | 25 | debugPrint("moveInMotion:", factor, " frameTime:", texture.frameTime) 26 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 27 | } 28 | } 29 | 30 | /// before fade in, we need the texture alpha keep to zero 31 | /// - Parameter texture: texture 32 | /// - Returns: result 33 | public override func checkTimelineRange(with texture: Texture) -> (Bool) { 34 | return true 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessZoomOutBlurMotion.metal: -------------------------------------------------------------------------------- 1 | // 2 | // zoomOutBluMotion.metal 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | 13 | namespace zoomOutBlurMotion { 14 | typedef struct 15 | { 16 | float factor; 17 | float4 roi; 18 | float2 iResolution; 19 | } MotionUniform; 20 | 21 | fragment half4 zoomOutBlurMotion(TwoInputVertexIO fragmentInput [[stage_in]], 22 | texture2d inputTexture [[texture(0)]], 23 | texture2d inputTexture2 [[texture(1)]], 24 | constant MotionUniform& uniform [[ buffer(1) ]]) 25 | { 26 | 27 | constexpr sampler quadSampler(mip_filter::linear, min_filter::linear, mag_filter::linear, address::clamp_to_zero); 28 | 29 | half4 bgCol = inputTexture.sample(quadSampler, fragmentInput.textureCoordinate); 30 | 31 | float2 center = float2(uniform.roi.r + uniform.roi.b * 0.5, uniform.roi.g + uniform.roi.a * 0.5); 32 | float time = clamp(uniform.factor * 2.0, 0.0, 1.0); 33 | float2 uv = fragmentInput.textureCoordinate2; 34 | 35 | uv = (uv - center); 36 | uv = uv * (0.4 + 0.6 * uniform.factor) + center; 37 | 38 | float2 dir = float2(uv - center) * 0.5 * (1. - time); 39 | 40 | half4 fgCol = half4(0.0); 41 | for(float i = 0.0; i < 1.0; i = i + 0.1) { 42 | fgCol += inputTexture2.sample(quadSampler, uv + dir * i); 43 | } 44 | 45 | fgCol /= 10.0; 46 | return half4(bgCol.rgb * (1. - fgCol.a) + fgCol.rgb, fgCol.a); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessZoomOutBlurMotion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessZoomOutBlurMotion.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public class MetalVideoProcessZoomOutBlurMotion: MetalVideoProcessMotion { 12 | 13 | var iResolution: Position { 14 | set { 15 | uniformSettings["iResolution"] = newValue 16 | } 17 | get { 18 | return uniformSettings["iResolution"] 19 | } 20 | } 21 | 22 | public init() { 23 | super.init(fragmentFunctionName: "zoomOutBlurMotion", numberOfInputs: 2, device: sharedMetalRenderingDevice) 24 | self.timingType = .quadraticEaseOut 25 | self.factor = 0.0 26 | } 27 | 28 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 29 | if let time = texture.timingStyle.timestamp?.asCMTime { 30 | if time < timelineRange.start { 31 | factor = 0.0 32 | } 33 | 34 | self.iResolution = Position(Float(texture.texture.width), Float(texture.texture.height)) 35 | debugPrint("zoomOutBlurMotion:", factor, " frameTime:", texture.frameTime) 36 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 37 | } 38 | } 39 | 40 | /// before fade in, we need the texture alpha keep to zero 41 | /// - Parameter texture: texture 42 | /// - Returns: result 43 | public override func checkTimelineRange(with texture: Texture) -> (Bool) { 44 | return true 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessZoomOutMotion.metal: -------------------------------------------------------------------------------- 1 | // 2 | // zoomOutMotion.metal 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | 13 | namespace zoomOutMotion { 14 | typedef struct 15 | { 16 | float factor; 17 | float4 roi; 18 | //float2 iResolution; 19 | } MotionUniform; 20 | 21 | fragment half4 zoomOutMotion(TwoInputVertexIO fragmentInput [[stage_in]], 22 | texture2d inputTexture [[texture(0)]], 23 | texture2d inputTexture2 [[texture(1)]], 24 | constant MotionUniform& uniform [[ buffer(1) ]]) 25 | { 26 | 27 | constexpr sampler quadSampler(mip_filter::linear, min_filter::linear, mag_filter::linear, address::clamp_to_zero); 28 | 29 | half4 bgCol = inputTexture.sample(quadSampler, fragmentInput.textureCoordinate); 30 | float2 center = float2(uniform.roi.r + uniform.roi.b * 0.5, uniform.roi.g + uniform.roi.a * 0.5); 31 | float2 uv = fragmentInput.textureCoordinate2; 32 | 33 | half4 fgCol = inputTexture2.sample(quadSampler, (uv - center) * (1. + uniform.factor) + center); 34 | 35 | return half4(bgCol.rgb * (1. - fgCol.a) + fgCol.rgb, fgCol.a); 36 | } 37 | } 38 | 39 | 40 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Motions/MetalVideoProcessZoomOutMotion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessZoomOutMotion.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/21. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public class MetalVideoProcessZoomOutMotion: MetalVideoProcessMotion { 12 | 13 | public init() { 14 | super.init(fragmentFunctionName: "zoomOutMotion", numberOfInputs: 2, device: sharedMetalRenderingDevice) 15 | self.timingType = .quadraticEaseIn 16 | self.factor = 0.0 17 | } 18 | 19 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 20 | if let time = texture.timingStyle.timestamp?.asCMTime { 21 | if time < timelineRange.start { 22 | factor = 0.0 23 | } 24 | 25 | debugPrint("moveInMotion:", factor, " frameTime:", texture.frameTime) 26 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 27 | } 28 | } 29 | 30 | /// before fade in, we need the texture alpha keep to zero 31 | /// - Parameter texture: texture 32 | /// - Returns: result 33 | public override func checkTimelineRange(with texture: Texture) -> (Bool) { 34 | return true 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Transitions/MetalVideoProcessBurnTransition.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessBurnTransition.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/16. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import AVFoundation 10 | 11 | public class MetalVideoProcessBurnTransition: MetalVideoProcessTransition { 12 | 13 | public init() { 14 | super.init(fragmentFunctionName: "burnTransition", numberOfInputs: 2, device: sharedMetalRenderingDevice) 15 | self.timingType = .linearInterpolation 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Transitions/MetalVideoProcessCircleEraseTransition.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessCircleEraseTransition.metal 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/16. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | 13 | namespace morph { 14 | #define vec2 float2 15 | #define vec3 float3 16 | #define vec4 float4 17 | 18 | typedef struct 19 | { 20 | float tweenFactor; 21 | float2 iResolution; 22 | } FadeTransitionUniform; 23 | 24 | fragment half4 circleErase(TwoInputVertexIO fragmentInput [[stage_in]], 25 | texture2d inputTexture [[texture(0)]], 26 | texture2d inputTexture2 [[texture(1)]], 27 | constant FadeTransitionUniform& uniform [[ buffer(1) ]]) 28 | { 29 | 30 | constexpr sampler quadSampler(mag_filter:: linear, 31 | min_filter:: linear, 32 | address:: clamp_to_zero); 33 | float progress = uniform.tweenFactor; 34 | float2 uv = fragmentInput.textureCoordinate; 35 | 36 | float mProgress = 1.0 - progress; 37 | vec2 resolution = uniform.iResolution; 38 | if(distance(uv * resolution, vec2(0.5,0.5) * resolution) < mProgress * length(resolution) * 0.5) 39 | return inputTexture.sample(quadSampler, uv); 40 | else 41 | return inputTexture2.sample(quadSampler, uv); 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Transitions/MetalVideoProcessCircleEraseTransition.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessCircleEraseTransition.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/16. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import AVFoundation 10 | 11 | public class MetalVideoProcessCircleEraseTransition: MetalVideoProcessTransition { 12 | public var iResolution: Size = Size(width: 1, height: 1) { didSet { uniformSettings["iResolution"] = iResolution } } 13 | 14 | public init() { 15 | super.init(fragmentFunctionName: "circleErase", numberOfInputs: 2, device: sharedMetalRenderingDevice) 16 | self.timingType = .linearInterpolation 17 | iResolution = Size(width: 1, height: 1) 18 | } 19 | 20 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 21 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 22 | self.iResolution = Size(width: Float(texture.texture.width), height: Float(texture.texture.height)) 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Transitions/MetalVideoProcessCubeTransition.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessCubeTransition.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/16. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | import AVFoundation 10 | 11 | public class MetalVideoProcessCubeTransition: MetalVideoProcessTransition { 12 | 13 | public init() { 14 | super.init(fragmentFunctionName: "cubeTransition", numberOfInputs: 2, device: sharedMetalRenderingDevice) 15 | self.timingType = .linearInterpolation 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Transitions/MetalVideoProcessEraseDownTransition.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessEraseDownTransition.metal 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/16. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | 13 | typedef struct 14 | { 15 | float tweenFactor; 16 | } FadeTransitionUniform; 17 | 18 | fragment half4 eraseDownTransition(TwoInputVertexIO fragmentInput [[stage_in]], 19 | texture2d inputTexture [[texture(0)]], 20 | texture2d inputTexture2 [[texture(1)]], 21 | constant FadeTransitionUniform& uniform [[ buffer(1) ]]) 22 | { 23 | 24 | constexpr sampler quadSampler(mag_filter:: linear, 25 | min_filter:: linear, 26 | address:: clamp_to_zero); 27 | float2 uv = fragmentInput.textureCoordinate; 28 | half4 input0 = inputTexture.sample(quadSampler, uv); 29 | half4 input1 = inputTexture2.sample(quadSampler, uv); 30 | float process = uniform.tweenFactor; 31 | 32 | float curve0 = process * process; 33 | float curve1 = 3. * curve0 - 2. * curve0 * process; 34 | return mix(input0, input1, step(uv.y, process)); 35 | } 36 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Transitions/MetalVideoProcessEraseDownTransition.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessEraseDownTransition.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/16. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import AVFoundation 10 | ///向下擦除转场 11 | public class MetalVideoProcessEraseDownTransition: MetalVideoProcessTransition { 12 | 13 | required public init() { 14 | super.init(fragmentFunctionName: "eraseDownTransition", numberOfInputs: 2, device: sharedMetalRenderingDevice) 15 | self.timingType = .quadraticEaseOut 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Transitions/MetalVideoProcessEraseLeftTransition.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessEraseLeftTransition.metal 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/16. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | 13 | namespace eraseLeft { 14 | typedef struct 15 | { 16 | float tweenFactor; 17 | } FadeTransitionUniform; 18 | 19 | fragment half4 eraseLeft(TwoInputVertexIO fragmentInput [[stage_in]], 20 | texture2d inputTexture [[texture(0)]], 21 | texture2d inputTexture2 [[texture(1)]], 22 | constant FadeTransitionUniform& uniform [[ buffer(1) ]]) 23 | { 24 | 25 | constexpr sampler quadSampler(mag_filter:: linear, 26 | min_filter:: linear, 27 | address:: clamp_to_zero); 28 | float2 uv = fragmentInput.textureCoordinate; 29 | half4 input0 = inputTexture.sample(quadSampler, uv); 30 | half4 input1 = inputTexture2.sample(quadSampler, uv); 31 | float process = uniform.tweenFactor; 32 | 33 | float curve0 = process * process; 34 | float curve1 = 3. * curve0 - 2. * curve0 * process; 35 | return mix(input0, input1, step(1. - uv.x, process)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Transitions/MetalVideoProcessEraseLeftTransition.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessEraseLeftTransition.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/16. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import AVFoundation 10 | 11 | public class MetalVideoProcessEraseLeftTransition: MetalVideoProcessTransition { 12 | 13 | public init() { 14 | super.init(fragmentFunctionName: "eraseLeft", numberOfInputs: 2, device: sharedMetalRenderingDevice) 15 | self.timingType = .linearInterpolation 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Transitions/MetalVideoProcessEraseRightTransition.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessEraseRightTransition.metal 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/16. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | 13 | namespace eraseLeft { 14 | typedef struct 15 | { 16 | float tweenFactor; 17 | } FadeTransitionUniform; 18 | 19 | fragment half4 eraseRight(TwoInputVertexIO fragmentInput [[stage_in]], 20 | texture2d inputTexture [[texture(0)]], 21 | texture2d inputTexture2 [[texture(1)]], 22 | constant FadeTransitionUniform& uniform [[ buffer(1) ]]) 23 | { 24 | 25 | constexpr sampler quadSampler(mag_filter:: linear, 26 | min_filter:: linear, 27 | address:: clamp_to_zero); 28 | float2 uv = fragmentInput.textureCoordinate; 29 | half4 input0 = inputTexture.sample(quadSampler, uv); 30 | half4 input1 = inputTexture2.sample(quadSampler, uv); 31 | float process = uniform.tweenFactor; 32 | 33 | float curve0 = process * process; 34 | float curve1 = 3. * curve0 - 2. * curve0 * process; 35 | return mix(input0, input1, step(uv.x, process)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Transitions/MetalVideoProcessEraseRightTransition.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessEraseRightTransition.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/16. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import AVFoundation 10 | 11 | public class MetalVideoProcessEraseRightTransition: MetalVideoProcessTransition { 12 | 13 | public init() { 14 | super.init(fragmentFunctionName: "eraseRight", numberOfInputs: 2, device: sharedMetalRenderingDevice) 15 | self.timingType = .linearInterpolation 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Transitions/MetalVideoProcessEraseUpTransition.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessEraseUpTransition.metal 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/16. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | 13 | namespace eraseUp { 14 | typedef struct 15 | { 16 | float tweenFactor; 17 | } FadeTransitionUniform; 18 | 19 | fragment half4 eraseUpTransition(TwoInputVertexIO fragmentInput [[stage_in]], 20 | texture2d inputTexture [[texture(0)]], 21 | texture2d inputTexture2 [[texture(1)]], 22 | constant FadeTransitionUniform& uniform [[ buffer(1) ]]) 23 | { 24 | 25 | constexpr sampler quadSampler(mag_filter:: linear, 26 | min_filter:: linear, 27 | address:: clamp_to_zero); 28 | float2 uv = fragmentInput.textureCoordinate; 29 | half4 input0 = inputTexture.sample(quadSampler, uv); 30 | half4 input1 = inputTexture2.sample(quadSampler, uv); 31 | float process = uniform.tweenFactor; 32 | 33 | float curve0 = process * process; 34 | float curve1 = 3. * curve0 - 2. * curve0 * process; 35 | return mix(input0, input1, step(1. - uv.y, process)); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Transitions/MetalVideoProcessEraseUpTransition.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessEraseUpTransition.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/16. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import AVFoundation 10 | 11 | public class MetalVideoProcessEraseUpTransition: MetalVideoProcessTransition { 12 | 13 | public init() { 14 | super.init(fragmentFunctionName: "eraseUpTransition", numberOfInputs: 2, device: sharedMetalRenderingDevice) 15 | self.timingType = .linearInterpolation 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Transitions/MetalVideoProcessFadeTransition.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessFadeTransition.metal 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/16. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | 13 | typedef struct 14 | { 15 | float tweenFactor; 16 | } FadeTransitionUniform; 17 | 18 | fragment half4 fadeTransition(TwoInputVertexIO fragmentInput [[stage_in]], 19 | texture2d inputTexture [[texture(0)]], 20 | texture2d inputTexture2 [[texture(1)]], 21 | constant FadeTransitionUniform& uniform [[ buffer(1) ]]) 22 | { 23 | 24 | constexpr sampler quadSampler; 25 | half4 textureColor = inputTexture.sample(quadSampler, fragmentInput.textureCoordinate); 26 | constexpr sampler quadSampler2; 27 | half4 textureColor2 = inputTexture2.sample(quadSampler, fragmentInput.textureCoordinate2); 28 | 29 | return half4(mix(textureColor.rgb, textureColor2.rgb, textureColor2.a * half(uniform.tweenFactor)), textureColor.a); 30 | } 31 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Transitions/MetalVideoProcessFadeTransition.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessFadeTransition.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/16. 6 | // Copyright © 2020 RenZhu Macro. All rights reserved. 7 | // 8 | 9 | import AVFoundation 10 | 11 | public class MetalVideoProcessFadeTransition: MetalVideoProcessTransition { 12 | 13 | public init() { 14 | super.init(fragmentFunctionName: "fadeTransition", numberOfInputs: 2, device: sharedMetalRenderingDevice) 15 | self.timingType = .quadraticEaseOut 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Transitions/MetalVideoProcessMirrorRotateTransition.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessMirrorRotateTransition.metal 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/16. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | 13 | typedef struct 14 | { 15 | float tweenFactor; 16 | } FadeTransitionUniform; 17 | 18 | fragment half4 mirrorRotateTransition(TwoInputVertexIO fragmentInput [[stage_in]], 19 | texture2d inputTexture [[texture(0)]], 20 | texture2d inputTexture2 [[texture(1)]], 21 | constant FadeTransitionUniform& uniform [[ buffer(1) ]]) 22 | { 23 | 24 | constexpr sampler quadSampler(mag_filter:: linear, 25 | min_filter:: linear, 26 | address:: clamp_to_zero); 27 | float2 uv = fragmentInput.textureCoordinate; 28 | 29 | float process = uniform.tweenFactor; 30 | 31 | float curve0 = process * process; 32 | float curve1 = 3. * curve0 - 2. * curve0 * process; 33 | float2 tempUv = uv; 34 | 35 | half4 outCol = half4(0.0); 36 | if (curve1 < 0.5) { 37 | tempUv = float2((tempUv.x - 0.5) * (1. + curve1 * 100.0) + 0.5, uv.y); 38 | outCol = inputTexture.sample(quadSampler, tempUv.xy); 39 | } else { 40 | tempUv = float2((tempUv.x - 0.5) * (1. + (1.0 - curve1) * 100.0) + 0.5, uv.y); 41 | outCol = inputTexture2.sample(quadSampler, tempUv.xy); 42 | } 43 | 44 | return outCol; 45 | } 46 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Transitions/MetalVideoProcessMirrorRotateTransition.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessMirrorRotateTransition.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/16. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import AVFoundation 10 | ///镜像翻转转场 11 | public class MetalVideoProcessMirrorRotateTransition: MetalVideoProcessTransition { 12 | 13 | required public init() { 14 | super.init(fragmentFunctionName: "mirrorRotateTransition", numberOfInputs: 2, device: sharedMetalRenderingDevice) 15 | 16 | self.timingType = .linearInterpolation 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Transitions/MetalVideoProcessMorphTransition.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessEraseRightTransition.metal 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/16. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | 13 | namespace morph { 14 | #define vec2 float2 15 | #define vec3 float3 16 | #define vec4 float4 17 | 18 | typedef struct 19 | { 20 | float tweenFactor; 21 | } FadeTransitionUniform; 22 | 23 | constant float strength=0.1; 24 | 25 | fragment half4 morph(TwoInputVertexIO fragmentInput [[stage_in]], 26 | texture2d inputTexture [[texture(0)]], 27 | texture2d inputTexture2 [[texture(1)]], 28 | constant FadeTransitionUniform& uniform [[ buffer(1) ]]) 29 | { 30 | 31 | constexpr sampler quadSampler(mag_filter:: linear, 32 | min_filter:: linear, 33 | address:: clamp_to_zero); 34 | float progress = uniform.tweenFactor; 35 | float2 uv = fragmentInput.textureCoordinate; 36 | vec2 p = uv; 37 | 38 | vec4 ca = vec4(inputTexture.sample(quadSampler, p)); 39 | vec4 cb = vec4(inputTexture2.sample(quadSampler, p)); 40 | 41 | vec2 oa = (((ca.rg + ca.b) * 0.5) * 2.0 - 1.0); 42 | vec2 ob = (((cb.rg + cb.b) * 0.5) * 2.0 - 1.0); 43 | vec2 oc = mix(oa,ob,0.5) * strength; 44 | // float progress = clamp(timer, 0.0, 1.0); 45 | float w0 = progress; 46 | float w1 = 1.0 - w0; 47 | 48 | return mix(inputTexture.sample(quadSampler, p + oc * w0), inputTexture2.sample(quadSampler, p - oc * w1), progress); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Transitions/MetalVideoProcessMorphTransition.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessEraseRightTransition.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/16. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import AVFoundation 10 | 11 | public class MetalVideoProcessMorphTransition: MetalVideoProcessTransition { 12 | 13 | public init() { 14 | super.init(fragmentFunctionName: "morph", numberOfInputs: 2, device: sharedMetalRenderingDevice) 15 | self.timingType = .linearInterpolation 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Transitions/MetalVideoProcessReflectTransition.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessReflectTransition.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/16. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import AVFoundation 10 | ///向下擦除转场 11 | public class MetalVideoProcessReflectTransition: MetalVideoProcessTransition { 12 | 13 | public init() { 14 | super.init(fragmentFunctionName: "reflectTransition", numberOfInputs: 2, device: sharedMetalRenderingDevice) 15 | self.timingType = .linearInterpolation 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Transitions/MetalVideoProcessShanBaiTransition.metal: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace metal; 3 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 4 | 5 | typedef struct 6 | { 7 | float tweenFactor; 8 | } FadeTransitionUniform; 9 | 10 | fragment half4 shanBai(TwoInputVertexIO fragmentInput [[stage_in]], 11 | texture2d inputTexture [[texture(0)]], 12 | texture2d inputTexture2 [[texture(1)]], 13 | constant FadeTransitionUniform& uniform [[ buffer(1) ]]) 14 | { 15 | 16 | constexpr sampler quadSampler(mag_filter:: linear, 17 | min_filter:: linear, 18 | address:: clamp_to_zero); 19 | 20 | half4 moveInText = inputTexture.sample(quadSampler, fragmentInput.textureCoordinate); 21 | 22 | half4 moveOutTex = inputTexture2.sample(quadSampler, fragmentInput.textureCoordinate2); 23 | float curve = 0.0; 24 | half4 outputTex = moveInText; 25 | 26 | float process = uniform.tweenFactor * 2.0; 27 | if (process < 1.0) { 28 | curve = process; 29 | outputTex = half4(moveInText.rgb + curve, moveInText.a); 30 | } else { 31 | curve = 2.0 - process; 32 | outputTex = half4(moveOutTex.rgb + curve, moveOutTex.a); 33 | } 34 | return outputTex; 35 | } 36 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Transitions/MetalVideoProcessShanBaiTransition.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessShanBai.swift 3 | // MetalVideoProcessShanBai 4 | // Created by Ruanshengqiang Macro on 2020/5/15. 5 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 6 | // 7 | import AVFoundation 8 | /// 闪白转场 9 | public class MetalVideoProcessShanBaiTransition: MetalVideoProcessTransition { 10 | public var renderSize: CGSize? = nil 11 | public init() { 12 | super.init(fragmentFunctionName: "shanBai", numberOfInputs: 2, device: sharedMetalRenderingDevice) 13 | } 14 | 15 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 16 | if self.timelineRange.containsTime(texture.timingStyle.timestamp?.asCMTime ?? CMTime.invalid) { 17 | let distance = CMTime(seconds: texture.frameTime, preferredTimescale: 1000) - self.timelineRange.start 18 | let progress = distance.seconds / self.timelineRange.duration.seconds 19 | self.tweenFactor = TimingFunctionFactory.quadraticEaseOut(p: Float(progress)) 20 | } 21 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Transitions/MetalVideoProcessVerticalUpGlitchTransition.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessVerticalGlitchTransition.metal 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/16. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | #include "../../Vender/Render/Base/OperationShaderTypes.h" 12 | 13 | namespace morph { 14 | #define vec2 float2 15 | #define vec3 float3 16 | #define vec4 float4 17 | 18 | typedef struct 19 | { 20 | float tweenFactor; 21 | float2 iResolution; 22 | } FadeTransitionUniform; 23 | 24 | float easeInOutQuint(float t) 25 | { 26 | return t < 0.5 ? 16.0 * t * t * t * t * t : 1.0 + 16.0 * (--t) * t * t * t * t; 27 | } 28 | 29 | void main() { 30 | 31 | } 32 | 33 | 34 | fragment half4 verticalupGlitch(TwoInputVertexIO fragmentInput [[stage_in]], 35 | texture2d inputTexture [[texture(0)]], 36 | texture2d inputTexture2 [[texture(1)]], 37 | constant FadeTransitionUniform& uniform [[ buffer(1) ]]) 38 | { 39 | 40 | constexpr sampler quadSampler(mag_filter:: linear, 41 | min_filter:: linear, 42 | address:: clamp_to_zero); 43 | float progress = uniform.tweenFactor; 44 | float2 uv = fragmentInput.textureCoordinate; 45 | vec2 resolution = uniform.iResolution; 46 | 47 | float mProgress = 1.0 - easeInOutQuint(progress); 48 | if(uv.y < mProgress) 49 | return inputTexture.sample(quadSampler, uv + vec2(0.0, 1.0 - mProgress)); 50 | else 51 | return inputTexture2.sample(quadSampler, uv - vec2(0.0, mProgress)); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /MetalVideoProcess/VideoProcess/Transitions/MetalVideoProcessVerticalUpGlitchTransition.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MetalVideoProcessVerticalGlitchTransition.swift 3 | // MetalVideoProcess 4 | // 5 | // Created by Ruanshengqiang Macro on 2020/7/16. 6 | // Copyright © 2020 Ruanshengqiang Macro. All rights reserved. 7 | // 8 | 9 | import AVFoundation 10 | 11 | public class MetalVideoProcessVerticalUpGlitchTransition: MetalVideoProcessTransition { 12 | public var iResolution: Size = Size(width: 1, height: 1) { didSet { uniformSettings["iResolution"] = iResolution } } 13 | 14 | public init() { 15 | super.init(fragmentFunctionName: "verticalupGlitch", numberOfInputs: 2, device: sharedMetalRenderingDevice) 16 | self.timingType = .linearInterpolation 17 | iResolution = Size(width: 1, height: 1) 18 | } 19 | 20 | public override func newTextureAvailable(_ texture: Texture, fromSourceIndex: UInt, trackID: Int32) { 21 | super.newTextureAvailable(texture, fromSourceIndex: fromSourceIndex, trackID: trackID) 22 | self.iResolution = Size(width: Float(texture.texture.width), height: Float(texture.texture.height)) 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Readme/Layer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Readme/Layer.png -------------------------------------------------------------------------------- /Readme/videoTransitionDesign.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GhostZephyr/MetalVideoProcess/3e298925f6edc2fcf8c91cd90fa34729afaaabea/Readme/videoTransitionDesign.png --------------------------------------------------------------------------------