└── AVCustomEdit ├── AVCustomEdit.xcodeproj └── project.pbxproj ├── AVCustomEdit ├── APLAppDelegate.h ├── APLAppDelegate.m ├── APLCrossDissolveRenderer.h ├── APLCrossDissolveRenderer.m ├── APLCustomVideoCompositionInstruction.h ├── APLCustomVideoCompositionInstruction.m ├── APLCustomVideoCompositor.h ├── APLCustomVideoCompositor.m ├── APLDiagonalWipeRenderer.h ├── APLDiagonalWipeRenderer.m ├── APLOpenGLRenderer.h ├── APLOpenGLRenderer.m ├── APLSimpleEditor.h ├── APLSimpleEditor.m ├── APLTransitionTypeController.h ├── APLTransitionTypeController.m ├── APLViewController.h ├── APLViewController.m ├── AVCustomEdit-Info.plist ├── AVCustomEdit-Prefix.pch ├── Base.lproj │ ├── MainStoryboard_iPad.storyboard │ └── MainStoryboard_iPhone.storyboard ├── Default-568h@2x.png ├── Default.png ├── Default@2x.png ├── en.lproj │ └── InfoPlist.strings ├── main.m ├── sample_clip1.m4v └── sample_clip2.mov └── ReadMe.txt /AVCustomEdit/AVCustomEdit.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | EF0F4236175D69F600CDB976 /* sample_clip2.mov in Resources */ = {isa = PBXBuildFile; fileRef = EF0F4235175D69F600CDB976 /* sample_clip2.mov */; }; 11 | EF6787A316C4399500218F91 /* APLCustomVideoCompositor.m in Sources */ = {isa = PBXBuildFile; fileRef = EF6787A216C4399500218F91 /* APLCustomVideoCompositor.m */; }; 12 | EF6FC27416C1C7BF0037614C /* APLSimpleEditor.m in Sources */ = {isa = PBXBuildFile; fileRef = EF6FC27316C1C7BF0037614C /* APLSimpleEditor.m */; }; 13 | EF705AB616D6D86100EDD5FD /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EF705AB516D6D86100EDD5FD /* AssetsLibrary.framework */; }; 14 | EF91C3B316D2D960002DC710 /* APLCustomVideoCompositionInstruction.m in Sources */ = {isa = PBXBuildFile; fileRef = EF91C3B216D2D960002DC710 /* APLCustomVideoCompositionInstruction.m */; }; 15 | EF91C3BC16D2DCCB002DC710 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EF91C3BB16D2DCCB002DC710 /* QuartzCore.framework */; }; 16 | EF91C3BE16D2DD25002DC710 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EF91C3BD16D2DD25002DC710 /* OpenGLES.framework */; }; 17 | EF94C619173DB876001BEC20 /* APLDiagonalWipeRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = EF94C617173DB876001BEC20 /* APLDiagonalWipeRenderer.m */; }; 18 | EF94C61C173DBAA0001BEC20 /* APLCrossDissolveRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = EF94C61B173DBAA0001BEC20 /* APLCrossDissolveRenderer.m */; }; 19 | EF94C622173DD0C7001BEC20 /* APLTransitionTypeController.m in Sources */ = {isa = PBXBuildFile; fileRef = EF94C621173DD0C7001BEC20 /* APLTransitionTypeController.m */; }; 20 | EF9E0A6D16DBF07A00B23F52 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EF9E0A6C16DBF07A00B23F52 /* MobileCoreServices.framework */; }; 21 | EFB5E86916C0703900FA50C1 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EFB5E86816C0703900FA50C1 /* UIKit.framework */; }; 22 | EFB5E86B16C0703900FA50C1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EFB5E86A16C0703900FA50C1 /* Foundation.framework */; }; 23 | EFB5E86D16C0703900FA50C1 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EFB5E86C16C0703900FA50C1 /* CoreGraphics.framework */; }; 24 | EFB5E87316C0703900FA50C1 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = EFB5E87116C0703900FA50C1 /* InfoPlist.strings */; }; 25 | EFB5E87516C0703900FA50C1 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = EFB5E87416C0703900FA50C1 /* main.m */; }; 26 | EFB5E87916C0703900FA50C1 /* APLAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = EFB5E87816C0703900FA50C1 /* APLAppDelegate.m */; }; 27 | EFB5E87B16C0703900FA50C1 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = EFB5E87A16C0703900FA50C1 /* Default.png */; }; 28 | EFB5E87D16C0703900FA50C1 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = EFB5E87C16C0703900FA50C1 /* Default@2x.png */; }; 29 | EFB5E87F16C0703900FA50C1 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = EFB5E87E16C0703900FA50C1 /* Default-568h@2x.png */; }; 30 | EFB5E88216C0703900FA50C1 /* MainStoryboard_iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EFB5E88016C0703900FA50C1 /* MainStoryboard_iPhone.storyboard */; }; 31 | EFB5E88516C0703900FA50C1 /* MainStoryboard_iPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EFB5E88316C0703900FA50C1 /* MainStoryboard_iPad.storyboard */; }; 32 | EFB5E88816C0703900FA50C1 /* APLViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EFB5E88716C0703900FA50C1 /* APLViewController.m */; }; 33 | EFC5271117319FCF004C8188 /* sample_clip1.m4v in Resources */ = {isa = PBXBuildFile; fileRef = EFC5271017319CA8004C8188 /* sample_clip1.m4v */; }; 34 | EFF2C1BA16C5946900FA182B /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EFF2C1B916C5946900FA182B /* CoreVideo.framework */; }; 35 | EFF2C1BC16C5A11100FA182B /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EFF2C1BB16C5A11100FA182B /* AVFoundation.framework */; }; 36 | EFF2C1BE16C5A11E00FA182B /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EFF2C1BD16C5A11E00FA182B /* CoreMedia.framework */; }; 37 | FEBF211A1724D8D2008AA664 /* APLOpenGLRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = FEBF21191724D8CB008AA664 /* APLOpenGLRenderer.m */; }; 38 | /* End PBXBuildFile section */ 39 | 40 | /* Begin PBXFileReference section */ 41 | 282E41C71761624100F005BD /* ReadMe.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = ReadMe.txt; sourceTree = ""; }; 42 | EF0F4235175D69F600CDB976 /* sample_clip2.mov */ = {isa = PBXFileReference; lastKnownFileType = video.quicktime; path = sample_clip2.mov; sourceTree = ""; }; 43 | EF6787A116C4399500218F91 /* APLCustomVideoCompositor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APLCustomVideoCompositor.h; sourceTree = ""; }; 44 | EF6787A216C4399500218F91 /* APLCustomVideoCompositor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = APLCustomVideoCompositor.m; sourceTree = ""; }; 45 | EF6FC27216C1C7BF0037614C /* APLSimpleEditor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APLSimpleEditor.h; sourceTree = ""; }; 46 | EF6FC27316C1C7BF0037614C /* APLSimpleEditor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = APLSimpleEditor.m; sourceTree = ""; }; 47 | EF705AB516D6D86100EDD5FD /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; }; 48 | EF91C3B116D2D960002DC710 /* APLCustomVideoCompositionInstruction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APLCustomVideoCompositionInstruction.h; sourceTree = ""; }; 49 | EF91C3B216D2D960002DC710 /* APLCustomVideoCompositionInstruction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = APLCustomVideoCompositionInstruction.m; sourceTree = ""; }; 50 | EF91C3BB16D2DCCB002DC710 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 51 | EF91C3BD16D2DD25002DC710 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; 52 | EF94C616173DB876001BEC20 /* APLDiagonalWipeRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APLDiagonalWipeRenderer.h; sourceTree = ""; }; 53 | EF94C617173DB876001BEC20 /* APLDiagonalWipeRenderer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = APLDiagonalWipeRenderer.m; sourceTree = ""; }; 54 | EF94C61A173DBAA0001BEC20 /* APLCrossDissolveRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APLCrossDissolveRenderer.h; sourceTree = ""; }; 55 | EF94C61B173DBAA0001BEC20 /* APLCrossDissolveRenderer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = APLCrossDissolveRenderer.m; sourceTree = ""; }; 56 | EF94C620173DD0C7001BEC20 /* APLTransitionTypeController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APLTransitionTypeController.h; sourceTree = ""; }; 57 | EF94C621173DD0C7001BEC20 /* APLTransitionTypeController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = APLTransitionTypeController.m; sourceTree = ""; }; 58 | EF9E0A6C16DBF07A00B23F52 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; 59 | EFB5E86516C0703900FA50C1 /* AVCustomEdit.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AVCustomEdit.app; sourceTree = BUILT_PRODUCTS_DIR; }; 60 | EFB5E86816C0703900FA50C1 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 61 | EFB5E86A16C0703900FA50C1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 62 | EFB5E86C16C0703900FA50C1 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 63 | EFB5E87016C0703900FA50C1 /* AVCustomEdit-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "AVCustomEdit-Info.plist"; sourceTree = ""; }; 64 | EFB5E87216C0703900FA50C1 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 65 | EFB5E87416C0703900FA50C1 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 66 | EFB5E87616C0703900FA50C1 /* AVCustomEdit-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AVCustomEdit-Prefix.pch"; sourceTree = ""; }; 67 | EFB5E87716C0703900FA50C1 /* APLAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = APLAppDelegate.h; sourceTree = ""; }; 68 | EFB5E87816C0703900FA50C1 /* APLAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = APLAppDelegate.m; sourceTree = ""; }; 69 | EFB5E87A16C0703900FA50C1 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; 70 | EFB5E87C16C0703900FA50C1 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; 71 | EFB5E87E16C0703900FA50C1 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 72 | EFB5E88616C0703900FA50C1 /* APLViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = APLViewController.h; sourceTree = ""; }; 73 | EFB5E88716C0703900FA50C1 /* APLViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = APLViewController.m; sourceTree = ""; }; 74 | EFC5271017319CA8004C8188 /* sample_clip1.m4v */ = {isa = PBXFileReference; lastKnownFileType = file; path = sample_clip1.m4v; sourceTree = ""; }; 75 | EFF2C1B916C5946900FA182B /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; }; 76 | EFF2C1BB16C5A11100FA182B /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/Frameworks/AVFoundation.framework; sourceTree = ""; }; 77 | EFF2C1BD16C5A11E00FA182B /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/Frameworks/CoreMedia.framework; sourceTree = ""; }; 78 | FEBF21181724D8CB008AA664 /* APLOpenGLRenderer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = APLOpenGLRenderer.h; sourceTree = ""; }; 79 | FEBF21191724D8CB008AA664 /* APLOpenGLRenderer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = APLOpenGLRenderer.m; sourceTree = ""; }; 80 | FEDDB4AE1828484B00DB96EF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainStoryboard_iPhone.storyboard; sourceTree = ""; }; 81 | FEDDB4AF1828484C00DB96EF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainStoryboard_iPad.storyboard; sourceTree = ""; }; 82 | /* End PBXFileReference section */ 83 | 84 | /* Begin PBXFrameworksBuildPhase section */ 85 | EFB5E86216C0703900FA50C1 /* Frameworks */ = { 86 | isa = PBXFrameworksBuildPhase; 87 | buildActionMask = 2147483647; 88 | files = ( 89 | EF9E0A6D16DBF07A00B23F52 /* MobileCoreServices.framework in Frameworks */, 90 | EF705AB616D6D86100EDD5FD /* AssetsLibrary.framework in Frameworks */, 91 | EF91C3BE16D2DD25002DC710 /* OpenGLES.framework in Frameworks */, 92 | EF91C3BC16D2DCCB002DC710 /* QuartzCore.framework in Frameworks */, 93 | EFF2C1BE16C5A11E00FA182B /* CoreMedia.framework in Frameworks */, 94 | EFF2C1BC16C5A11100FA182B /* AVFoundation.framework in Frameworks */, 95 | EFF2C1BA16C5946900FA182B /* CoreVideo.framework in Frameworks */, 96 | EFB5E86916C0703900FA50C1 /* UIKit.framework in Frameworks */, 97 | EFB5E86B16C0703900FA50C1 /* Foundation.framework in Frameworks */, 98 | EFB5E86D16C0703900FA50C1 /* CoreGraphics.framework in Frameworks */, 99 | ); 100 | runOnlyForDeploymentPostprocessing = 0; 101 | }; 102 | /* End PBXFrameworksBuildPhase section */ 103 | 104 | /* Begin PBXGroup section */ 105 | EFB5E85C16C0703900FA50C1 = { 106 | isa = PBXGroup; 107 | children = ( 108 | 282E41C71761624100F005BD /* ReadMe.txt */, 109 | EFB5E86E16C0703900FA50C1 /* AVCustomEdit */, 110 | EFB5E86716C0703900FA50C1 /* Frameworks */, 111 | EFB5E86616C0703900FA50C1 /* Products */, 112 | ); 113 | sourceTree = ""; 114 | }; 115 | EFB5E86616C0703900FA50C1 /* Products */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | EFB5E86516C0703900FA50C1 /* AVCustomEdit.app */, 119 | ); 120 | name = Products; 121 | sourceTree = ""; 122 | }; 123 | EFB5E86716C0703900FA50C1 /* Frameworks */ = { 124 | isa = PBXGroup; 125 | children = ( 126 | EF9E0A6C16DBF07A00B23F52 /* MobileCoreServices.framework */, 127 | EF705AB516D6D86100EDD5FD /* AssetsLibrary.framework */, 128 | EF91C3BD16D2DD25002DC710 /* OpenGLES.framework */, 129 | EF91C3BB16D2DCCB002DC710 /* QuartzCore.framework */, 130 | EFF2C1BD16C5A11E00FA182B /* CoreMedia.framework */, 131 | EFF2C1BB16C5A11100FA182B /* AVFoundation.framework */, 132 | EFF2C1B916C5946900FA182B /* CoreVideo.framework */, 133 | EFB5E86816C0703900FA50C1 /* UIKit.framework */, 134 | EFB5E86A16C0703900FA50C1 /* Foundation.framework */, 135 | EFB5E86C16C0703900FA50C1 /* CoreGraphics.framework */, 136 | ); 137 | name = Frameworks; 138 | sourceTree = ""; 139 | }; 140 | EFB5E86E16C0703900FA50C1 /* AVCustomEdit */ = { 141 | isa = PBXGroup; 142 | children = ( 143 | EFB5E87716C0703900FA50C1 /* APLAppDelegate.h */, 144 | EFB5E87816C0703900FA50C1 /* APLAppDelegate.m */, 145 | EFC6485217443D5E00209021 /* View Controllers */, 146 | EFC6485317443D8A00209021 /* Custom Compositors */, 147 | EF6FC27216C1C7BF0037614C /* APLSimpleEditor.h */, 148 | EF6FC27316C1C7BF0037614C /* APLSimpleEditor.m */, 149 | EFC6485417443DB200209021 /* OpenGL Renderers */, 150 | EFB5E86F16C0703900FA50C1 /* Supporting Files */, 151 | ); 152 | path = AVCustomEdit; 153 | sourceTree = ""; 154 | }; 155 | EFB5E86F16C0703900FA50C1 /* Supporting Files */ = { 156 | isa = PBXGroup; 157 | children = ( 158 | EFC5271017319CA8004C8188 /* sample_clip1.m4v */, 159 | EF0F4235175D69F600CDB976 /* sample_clip2.mov */, 160 | EFB5E88016C0703900FA50C1 /* MainStoryboard_iPhone.storyboard */, 161 | EFB5E88316C0703900FA50C1 /* MainStoryboard_iPad.storyboard */, 162 | EFB5E87016C0703900FA50C1 /* AVCustomEdit-Info.plist */, 163 | EFB5E87116C0703900FA50C1 /* InfoPlist.strings */, 164 | EFB5E87416C0703900FA50C1 /* main.m */, 165 | EFB5E87616C0703900FA50C1 /* AVCustomEdit-Prefix.pch */, 166 | EFB5E87A16C0703900FA50C1 /* Default.png */, 167 | EFB5E87C16C0703900FA50C1 /* Default@2x.png */, 168 | EFB5E87E16C0703900FA50C1 /* Default-568h@2x.png */, 169 | ); 170 | name = "Supporting Files"; 171 | sourceTree = ""; 172 | }; 173 | EFC6485217443D5E00209021 /* View Controllers */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | EFB5E88616C0703900FA50C1 /* APLViewController.h */, 177 | EFB5E88716C0703900FA50C1 /* APLViewController.m */, 178 | EF94C620173DD0C7001BEC20 /* APLTransitionTypeController.h */, 179 | EF94C621173DD0C7001BEC20 /* APLTransitionTypeController.m */, 180 | ); 181 | name = "View Controllers"; 182 | sourceTree = ""; 183 | }; 184 | EFC6485317443D8A00209021 /* Custom Compositors */ = { 185 | isa = PBXGroup; 186 | children = ( 187 | EF6787A116C4399500218F91 /* APLCustomVideoCompositor.h */, 188 | EF6787A216C4399500218F91 /* APLCustomVideoCompositor.m */, 189 | EF91C3B116D2D960002DC710 /* APLCustomVideoCompositionInstruction.h */, 190 | EF91C3B216D2D960002DC710 /* APLCustomVideoCompositionInstruction.m */, 191 | ); 192 | name = "Custom Compositors"; 193 | sourceTree = ""; 194 | }; 195 | EFC6485417443DB200209021 /* OpenGL Renderers */ = { 196 | isa = PBXGroup; 197 | children = ( 198 | FEBF21181724D8CB008AA664 /* APLOpenGLRenderer.h */, 199 | FEBF21191724D8CB008AA664 /* APLOpenGLRenderer.m */, 200 | EF94C616173DB876001BEC20 /* APLDiagonalWipeRenderer.h */, 201 | EF94C617173DB876001BEC20 /* APLDiagonalWipeRenderer.m */, 202 | EF94C61A173DBAA0001BEC20 /* APLCrossDissolveRenderer.h */, 203 | EF94C61B173DBAA0001BEC20 /* APLCrossDissolveRenderer.m */, 204 | ); 205 | name = "OpenGL Renderers"; 206 | sourceTree = ""; 207 | }; 208 | /* End PBXGroup section */ 209 | 210 | /* Begin PBXNativeTarget section */ 211 | EFB5E86416C0703900FA50C1 /* AVCustomEdit */ = { 212 | isa = PBXNativeTarget; 213 | buildConfigurationList = EFB5E88B16C0703900FA50C1 /* Build configuration list for PBXNativeTarget "AVCustomEdit" */; 214 | buildPhases = ( 215 | EFB5E86116C0703900FA50C1 /* Sources */, 216 | EFB5E86216C0703900FA50C1 /* Frameworks */, 217 | EFB5E86316C0703900FA50C1 /* Resources */, 218 | ); 219 | buildRules = ( 220 | ); 221 | dependencies = ( 222 | ); 223 | name = AVCustomEdit; 224 | productName = AVCustomEdit; 225 | productReference = EFB5E86516C0703900FA50C1 /* AVCustomEdit.app */; 226 | productType = "com.apple.product-type.application"; 227 | }; 228 | /* End PBXNativeTarget section */ 229 | 230 | /* Begin PBXProject section */ 231 | EFB5E85D16C0703900FA50C1 /* Project object */ = { 232 | isa = PBXProject; 233 | attributes = { 234 | CLASSPREFIX = APL; 235 | LastUpgradeCheck = 0460; 236 | ORGANIZATIONNAME = Apple; 237 | }; 238 | buildConfigurationList = EFB5E86016C0703900FA50C1 /* Build configuration list for PBXProject "AVCustomEdit" */; 239 | compatibilityVersion = "Xcode 3.2"; 240 | developmentRegion = English; 241 | hasScannedForEncodings = 0; 242 | knownRegions = ( 243 | en, 244 | Base, 245 | ); 246 | mainGroup = EFB5E85C16C0703900FA50C1; 247 | productRefGroup = EFB5E86616C0703900FA50C1 /* Products */; 248 | projectDirPath = ""; 249 | projectRoot = ""; 250 | targets = ( 251 | EFB5E86416C0703900FA50C1 /* AVCustomEdit */, 252 | ); 253 | }; 254 | /* End PBXProject section */ 255 | 256 | /* Begin PBXResourcesBuildPhase section */ 257 | EFB5E86316C0703900FA50C1 /* Resources */ = { 258 | isa = PBXResourcesBuildPhase; 259 | buildActionMask = 2147483647; 260 | files = ( 261 | EFB5E87316C0703900FA50C1 /* InfoPlist.strings in Resources */, 262 | EFB5E87B16C0703900FA50C1 /* Default.png in Resources */, 263 | EFB5E87D16C0703900FA50C1 /* Default@2x.png in Resources */, 264 | EF0F4236175D69F600CDB976 /* sample_clip2.mov in Resources */, 265 | EFB5E87F16C0703900FA50C1 /* Default-568h@2x.png in Resources */, 266 | EFC5271117319FCF004C8188 /* sample_clip1.m4v in Resources */, 267 | EFB5E88216C0703900FA50C1 /* MainStoryboard_iPhone.storyboard in Resources */, 268 | EFB5E88516C0703900FA50C1 /* MainStoryboard_iPad.storyboard in Resources */, 269 | ); 270 | runOnlyForDeploymentPostprocessing = 0; 271 | }; 272 | /* End PBXResourcesBuildPhase section */ 273 | 274 | /* Begin PBXSourcesBuildPhase section */ 275 | EFB5E86116C0703900FA50C1 /* Sources */ = { 276 | isa = PBXSourcesBuildPhase; 277 | buildActionMask = 2147483647; 278 | files = ( 279 | EF91C3B316D2D960002DC710 /* APLCustomVideoCompositionInstruction.m in Sources */, 280 | EFB5E87516C0703900FA50C1 /* main.m in Sources */, 281 | EFB5E87916C0703900FA50C1 /* APLAppDelegate.m in Sources */, 282 | EF94C619173DB876001BEC20 /* APLDiagonalWipeRenderer.m in Sources */, 283 | EF94C61C173DBAA0001BEC20 /* APLCrossDissolveRenderer.m in Sources */, 284 | EF94C622173DD0C7001BEC20 /* APLTransitionTypeController.m in Sources */, 285 | EFB5E88816C0703900FA50C1 /* APLViewController.m in Sources */, 286 | EF6FC27416C1C7BF0037614C /* APLSimpleEditor.m in Sources */, 287 | EF6787A316C4399500218F91 /* APLCustomVideoCompositor.m in Sources */, 288 | FEBF211A1724D8D2008AA664 /* APLOpenGLRenderer.m in Sources */, 289 | ); 290 | runOnlyForDeploymentPostprocessing = 0; 291 | }; 292 | /* End PBXSourcesBuildPhase section */ 293 | 294 | /* Begin PBXVariantGroup section */ 295 | EFB5E87116C0703900FA50C1 /* InfoPlist.strings */ = { 296 | isa = PBXVariantGroup; 297 | children = ( 298 | EFB5E87216C0703900FA50C1 /* en */, 299 | ); 300 | name = InfoPlist.strings; 301 | sourceTree = ""; 302 | }; 303 | EFB5E88016C0703900FA50C1 /* MainStoryboard_iPhone.storyboard */ = { 304 | isa = PBXVariantGroup; 305 | children = ( 306 | FEDDB4AE1828484B00DB96EF /* Base */, 307 | ); 308 | name = MainStoryboard_iPhone.storyboard; 309 | sourceTree = ""; 310 | }; 311 | EFB5E88316C0703900FA50C1 /* MainStoryboard_iPad.storyboard */ = { 312 | isa = PBXVariantGroup; 313 | children = ( 314 | FEDDB4AF1828484C00DB96EF /* Base */, 315 | ); 316 | name = MainStoryboard_iPad.storyboard; 317 | sourceTree = ""; 318 | }; 319 | /* End PBXVariantGroup section */ 320 | 321 | /* Begin XCBuildConfiguration section */ 322 | EFB5E88916C0703900FA50C1 /* Debug */ = { 323 | isa = XCBuildConfiguration; 324 | buildSettings = { 325 | ALWAYS_SEARCH_USER_PATHS = NO; 326 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 327 | CLANG_CXX_LIBRARY = "libc++"; 328 | CLANG_ENABLE_OBJC_ARC = YES; 329 | CLANG_WARN_CONSTANT_CONVERSION = YES; 330 | CLANG_WARN_EMPTY_BODY = YES; 331 | CLANG_WARN_ENUM_CONVERSION = YES; 332 | CLANG_WARN_INT_CONVERSION = YES; 333 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 334 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 335 | COPY_PHASE_STRIP = NO; 336 | GCC_C_LANGUAGE_STANDARD = gnu99; 337 | GCC_DYNAMIC_NO_PIC = NO; 338 | GCC_OPTIMIZATION_LEVEL = 0; 339 | GCC_PREPROCESSOR_DEFINITIONS = ( 340 | "DEBUG=1", 341 | "$(inherited)", 342 | ); 343 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 344 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 345 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 346 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 347 | GCC_WARN_UNUSED_VARIABLE = YES; 348 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 349 | ONLY_ACTIVE_ARCH = YES; 350 | SDKROOT = iphoneos; 351 | TARGETED_DEVICE_FAMILY = "1,2"; 352 | }; 353 | name = Debug; 354 | }; 355 | EFB5E88A16C0703900FA50C1 /* Release */ = { 356 | isa = XCBuildConfiguration; 357 | buildSettings = { 358 | ALWAYS_SEARCH_USER_PATHS = NO; 359 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 360 | CLANG_CXX_LIBRARY = "libc++"; 361 | CLANG_ENABLE_OBJC_ARC = YES; 362 | CLANG_WARN_CONSTANT_CONVERSION = YES; 363 | CLANG_WARN_EMPTY_BODY = YES; 364 | CLANG_WARN_ENUM_CONVERSION = YES; 365 | CLANG_WARN_INT_CONVERSION = YES; 366 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 367 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 368 | COPY_PHASE_STRIP = YES; 369 | GCC_C_LANGUAGE_STANDARD = gnu99; 370 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 371 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 372 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 373 | GCC_WARN_UNUSED_VARIABLE = YES; 374 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 375 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 376 | SDKROOT = iphoneos; 377 | TARGETED_DEVICE_FAMILY = "1,2"; 378 | VALIDATE_PRODUCT = YES; 379 | }; 380 | name = Release; 381 | }; 382 | EFB5E88C16C0703900FA50C1 /* Debug */ = { 383 | isa = XCBuildConfiguration; 384 | buildSettings = { 385 | CLANG_ANALYZER_OBJC_RETAIN_COUNT = NO; 386 | CLANG_ENABLE_OBJC_ARC = YES; 387 | CLANG_WARN__ARC_BRIDGE_CAST_NONARC = NO; 388 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 389 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 390 | GCC_PREFIX_HEADER = "AVCustomEdit/AVCustomEdit-Prefix.pch"; 391 | INFOPLIST_FILE = "AVCustomEdit/AVCustomEdit-Info.plist"; 392 | LIBRARY_SEARCH_PATHS = ""; 393 | ONLY_ACTIVE_ARCH = YES; 394 | PRODUCT_NAME = "$(TARGET_NAME)"; 395 | WRAPPER_EXTENSION = app; 396 | }; 397 | name = Debug; 398 | }; 399 | EFB5E88D16C0703900FA50C1 /* Release */ = { 400 | isa = XCBuildConfiguration; 401 | buildSettings = { 402 | CLANG_ANALYZER_OBJC_RETAIN_COUNT = NO; 403 | CLANG_ENABLE_OBJC_ARC = YES; 404 | CLANG_WARN__ARC_BRIDGE_CAST_NONARC = NO; 405 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 406 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 407 | GCC_PREFIX_HEADER = "AVCustomEdit/AVCustomEdit-Prefix.pch"; 408 | INFOPLIST_FILE = "AVCustomEdit/AVCustomEdit-Info.plist"; 409 | LIBRARY_SEARCH_PATHS = ""; 410 | ONLY_ACTIVE_ARCH = YES; 411 | PRODUCT_NAME = "$(TARGET_NAME)"; 412 | WRAPPER_EXTENSION = app; 413 | }; 414 | name = Release; 415 | }; 416 | /* End XCBuildConfiguration section */ 417 | 418 | /* Begin XCConfigurationList section */ 419 | EFB5E86016C0703900FA50C1 /* Build configuration list for PBXProject "AVCustomEdit" */ = { 420 | isa = XCConfigurationList; 421 | buildConfigurations = ( 422 | EFB5E88916C0703900FA50C1 /* Debug */, 423 | EFB5E88A16C0703900FA50C1 /* Release */, 424 | ); 425 | defaultConfigurationIsVisible = 0; 426 | defaultConfigurationName = Release; 427 | }; 428 | EFB5E88B16C0703900FA50C1 /* Build configuration list for PBXNativeTarget "AVCustomEdit" */ = { 429 | isa = XCConfigurationList; 430 | buildConfigurations = ( 431 | EFB5E88C16C0703900FA50C1 /* Debug */, 432 | EFB5E88D16C0703900FA50C1 /* Release */, 433 | ); 434 | defaultConfigurationIsVisible = 0; 435 | defaultConfigurationName = Release; 436 | }; 437 | /* End XCConfigurationList section */ 438 | }; 439 | rootObject = EFB5E85D16C0703900FA50C1 /* Project object */; 440 | } 441 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/APLAppDelegate.h: -------------------------------------------------------------------------------- 1 | /* 2 | File: APLAppDelegate.h 3 | Abstract: Simple application delegate. 4 | Version: 1.2 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2014 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | #import 49 | 50 | @interface APLAppDelegate : UIResponder 51 | 52 | @property (strong, nonatomic) UIWindow *window; 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/APLAppDelegate.m: -------------------------------------------------------------------------------- 1 | /* 2 | File: APLAppDelegate.m 3 | Abstract: Simple application delegate. 4 | Version: 1.2 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2014 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | #import "APLAppDelegate.h" 49 | 50 | @implementation APLAppDelegate 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/APLCrossDissolveRenderer.h: -------------------------------------------------------------------------------- 1 | /* 2 | File: APLCrossDissolveRenderer.h 3 | Abstract: APLCrossDissolveRenderer subclass of APLOpenGLRenderer, renders the given source buffers to perform a cross dissolve over the time range of the transition. 4 | Version: 1.2 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2014 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | #import "APLOpenGLRenderer.h" 49 | 50 | @interface APLCrossDissolveRenderer : APLOpenGLRenderer 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/APLCrossDissolveRenderer.m: -------------------------------------------------------------------------------- 1 | /* 2 | File: APLCrossDissolveRenderer.m 3 | Abstract: APLCrossDissolveRenderer subclass of APLOpenGLRenderer, renders the given source buffers to perform a cross dissolve over the time range of the transition. 4 | Version: 1.2 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2014 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | #import "APLCrossDissolveRenderer.h" 49 | 50 | @implementation APLCrossDissolveRenderer 51 | 52 | - (void)renderPixelBuffer:(CVPixelBufferRef)destinationPixelBuffer usingForegroundSourceBuffer:(CVPixelBufferRef)foregroundPixelBuffer andBackgroundSourceBuffer:(CVPixelBufferRef)backgroundPixelBuffer forTweenFactor:(float)tween 53 | { 54 | [EAGLContext setCurrentContext:self.currentContext]; 55 | 56 | if (foregroundPixelBuffer != NULL || backgroundPixelBuffer != NULL) { 57 | 58 | CVOpenGLESTextureRef foregroundLumaTexture = [self lumaTextureForPixelBuffer:foregroundPixelBuffer]; 59 | CVOpenGLESTextureRef foregroundChromaTexture = [self chromaTextureForPixelBuffer:foregroundPixelBuffer]; 60 | 61 | CVOpenGLESTextureRef backgroundLumaTexture = [self lumaTextureForPixelBuffer:backgroundPixelBuffer]; 62 | CVOpenGLESTextureRef backgroundChromaTexture = [self chromaTextureForPixelBuffer:backgroundPixelBuffer]; 63 | 64 | CVOpenGLESTextureRef destLumaTexture = [self lumaTextureForPixelBuffer:destinationPixelBuffer]; 65 | CVOpenGLESTextureRef destChromaTexture = [self chromaTextureForPixelBuffer:destinationPixelBuffer]; 66 | 67 | glUseProgram(self.programY); 68 | 69 | // Set the render transform 70 | GLfloat preferredRenderTransform [] = { 71 | self.renderTransform.a, self.renderTransform.b, self.renderTransform.tx, 0.0, 72 | self.renderTransform.c, self.renderTransform.d, self.renderTransform.ty, 0.0, 73 | 0.0, 0.0, 1.0, 0.0, 74 | 0.0, 0.0, 0.0, 1.0, 75 | }; 76 | 77 | glUniformMatrix4fv(uniforms[UNIFORM_RENDER_TRANSFORM_Y], 1, GL_FALSE, preferredRenderTransform); 78 | 79 | glBindFramebuffer(GL_FRAMEBUFFER, self.offscreenBufferHandle); 80 | glViewport(0, 0, (int)CVPixelBufferGetWidthOfPlane(destinationPixelBuffer, 0), (int)CVPixelBufferGetHeightOfPlane(destinationPixelBuffer, 0)); 81 | 82 | // Y planes of foreground and background frame are used to render the Y plane of the destination frame 83 | glActiveTexture(GL_TEXTURE0); 84 | glBindTexture(CVOpenGLESTextureGetTarget(foregroundLumaTexture), CVOpenGLESTextureGetName(foregroundLumaTexture)); 85 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 86 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 87 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 88 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 89 | 90 | glActiveTexture(GL_TEXTURE1); 91 | glBindTexture(CVOpenGLESTextureGetTarget(backgroundLumaTexture), CVOpenGLESTextureGetName(backgroundLumaTexture)); 92 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 93 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 94 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 95 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 96 | 97 | // Attach the destination texture as a color attachment to the off screen frame buffer 98 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, CVOpenGLESTextureGetTarget(destLumaTexture), CVOpenGLESTextureGetName(destLumaTexture), 0); 99 | 100 | if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 101 | NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER)); 102 | goto bail; 103 | } 104 | 105 | glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 106 | glClear(GL_COLOR_BUFFER_BIT); 107 | 108 | GLfloat quadVertexData1 [] = { 109 | -1.0, 1.0, 110 | 1.0, 1.0, 111 | -1.0, -1.0, 112 | 1.0, -1.0, 113 | }; 114 | 115 | // texture data varies from 0 -> 1, whereas vertex data varies from -1 -> 1 116 | GLfloat quadTextureData1 [] = { 117 | 0.5 + quadVertexData1[0]/2, 0.5 + quadVertexData1[1]/2, 118 | 0.5 + quadVertexData1[2]/2, 0.5 + quadVertexData1[3]/2, 119 | 0.5 + quadVertexData1[4]/2, 0.5 + quadVertexData1[5]/2, 120 | 0.5 + quadVertexData1[6]/2, 0.5 + quadVertexData1[7]/2, 121 | }; 122 | 123 | glUniform1i(uniforms[UNIFORM_Y], 0); 124 | 125 | glVertexAttribPointer(ATTRIB_VERTEX_Y, 2, GL_FLOAT, 0, 0, quadVertexData1); 126 | glEnableVertexAttribArray(ATTRIB_VERTEX_Y); 127 | 128 | glVertexAttribPointer(ATTRIB_TEXCOORD_Y, 2, GL_FLOAT, 0, 0, quadTextureData1); 129 | glEnableVertexAttribArray(ATTRIB_TEXCOORD_Y); 130 | 131 | // Blend function to draw the foreground frame 132 | glEnable(GL_BLEND); 133 | glBlendFunc(GL_ONE, GL_ZERO); 134 | 135 | // Draw the foreground frame 136 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 137 | 138 | glUniform1i(uniforms[UNIFORM_Y], 1); 139 | 140 | glVertexAttribPointer(ATTRIB_VERTEX_Y, 2, GL_FLOAT, 0, 0, quadVertexData1); 141 | glEnableVertexAttribArray(ATTRIB_VERTEX_Y); 142 | 143 | glVertexAttribPointer(ATTRIB_TEXCOORD_Y, 2, GL_FLOAT, 0, 0, quadTextureData1); 144 | glEnableVertexAttribArray(ATTRIB_TEXCOORD_Y); 145 | 146 | // Blend function to draw the background frame 147 | glBlendColor(0, 0, 0, tween); 148 | glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA); 149 | 150 | // Draw the background frame 151 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 152 | 153 | // Perform similar operations as above for the UV plane 154 | glUseProgram(self.programUV); 155 | 156 | glUniformMatrix4fv(uniforms[UNIFORM_RENDER_TRANSFORM_UV], 1, GL_FALSE, preferredRenderTransform); 157 | 158 | // UV planes of foreground and background frame are used to render the UV plane of the destination frame 159 | glActiveTexture(GL_TEXTURE2); 160 | glBindTexture(CVOpenGLESTextureGetTarget(foregroundChromaTexture), CVOpenGLESTextureGetName(foregroundChromaTexture)); 161 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 162 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 163 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 164 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 165 | 166 | glActiveTexture(GL_TEXTURE3); 167 | glBindTexture(CVOpenGLESTextureGetTarget(backgroundChromaTexture), CVOpenGLESTextureGetName(backgroundChromaTexture)); 168 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 169 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 170 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 171 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 172 | 173 | glViewport(0, 0, (int)CVPixelBufferGetWidthOfPlane(destinationPixelBuffer, 1), (int)CVPixelBufferGetHeightOfPlane(destinationPixelBuffer, 1)); 174 | 175 | // Attach the destination texture as a color attachment to the off screen frame buffer 176 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, CVOpenGLESTextureGetTarget(destChromaTexture), CVOpenGLESTextureGetName(destChromaTexture), 0); 177 | 178 | if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 179 | NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER)); 180 | goto bail; 181 | } 182 | 183 | glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 184 | glClear(GL_COLOR_BUFFER_BIT); 185 | 186 | glUniform1i(uniforms[UNIFORM_UV], 2); 187 | 188 | glVertexAttribPointer(ATTRIB_VERTEX_UV, 2, GL_FLOAT, 0, 0, quadVertexData1); 189 | glEnableVertexAttribArray(ATTRIB_VERTEX_UV); 190 | 191 | glVertexAttribPointer(ATTRIB_TEXCOORD_UV, 2, GL_FLOAT, 0, 0, quadTextureData1); 192 | glEnableVertexAttribArray(ATTRIB_TEXCOORD_UV); 193 | 194 | glBlendFunc(GL_ONE, GL_ZERO); 195 | 196 | // Draw the foreground frame 197 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 198 | 199 | glUniform1i(uniforms[UNIFORM_UV], 3); 200 | 201 | glVertexAttribPointer(ATTRIB_VERTEX_UV, 2, GL_FLOAT, 0, 0, quadVertexData1); 202 | glEnableVertexAttribArray(ATTRIB_VERTEX_UV); 203 | 204 | glVertexAttribPointer(ATTRIB_TEXCOORD_UV, 2, GL_FLOAT, 0, 0, quadTextureData1); 205 | glEnableVertexAttribArray(ATTRIB_TEXCOORD_UV); 206 | 207 | glBlendColor(0, 0, 0, tween); 208 | glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA); 209 | 210 | // Draw the background frame 211 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 212 | 213 | glFlush(); 214 | 215 | bail: 216 | CFRelease(foregroundLumaTexture); 217 | CFRelease(foregroundChromaTexture); 218 | CFRelease(backgroundLumaTexture); 219 | CFRelease(backgroundChromaTexture); 220 | CFRelease(destLumaTexture); 221 | CFRelease(destChromaTexture); 222 | 223 | // Periodic texture cache flush every frame 224 | CVOpenGLESTextureCacheFlush(self.videoTextureCache, 0); 225 | 226 | [EAGLContext setCurrentContext:nil]; 227 | } 228 | 229 | } 230 | 231 | @end 232 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/APLCustomVideoCompositionInstruction.h: -------------------------------------------------------------------------------- 1 | /* 2 | File: APLCustomVideoCompositionInstruction.h 3 | Abstract: Custom video composition instruction class implementing AVVideoCompositionInstruction protocol. 4 | Version: 1.2 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2014 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | #import 49 | #import 50 | 51 | @interface APLCustomVideoCompositionInstruction : NSObject 52 | 53 | @property CMPersistentTrackID foregroundTrackID; 54 | @property CMPersistentTrackID backgroundTrackID; 55 | 56 | - (id)initPassThroughTrackID:(CMPersistentTrackID)passthroughTrackID forTimeRange:(CMTimeRange)timeRange; 57 | - (id)initTransitionWithSourceTrackIDs:(NSArray*)sourceTrackIDs forTimeRange:(CMTimeRange)timeRange; 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/APLCustomVideoCompositionInstruction.m: -------------------------------------------------------------------------------- 1 | /* 2 | File: APLCustomVideoCompositionInstruction.m 3 | Abstract: Custom video composition instruction class implementing AVVideoCompositionInstruction protocol. 4 | Version: 1.2 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2014 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | #import "APLCustomVideoCompositionInstruction.h" 49 | 50 | @implementation APLCustomVideoCompositionInstruction 51 | 52 | @synthesize timeRange = _timeRange; 53 | @synthesize enablePostProcessing = _enablePostProcessing; 54 | @synthesize containsTweening = _containsTweening; 55 | @synthesize requiredSourceTrackIDs = _requiredSourceTrackIDs; 56 | @synthesize passthroughTrackID = _passthroughTrackID; 57 | 58 | - (id)initPassThroughTrackID:(CMPersistentTrackID)passthroughTrackID forTimeRange:(CMTimeRange)timeRange 59 | { 60 | self = [super init]; 61 | if (self) { 62 | _passthroughTrackID = passthroughTrackID; 63 | _requiredSourceTrackIDs = nil; 64 | _timeRange = timeRange; 65 | _containsTweening = FALSE; 66 | _enablePostProcessing = FALSE; 67 | } 68 | 69 | return self; 70 | } 71 | 72 | - (id)initTransitionWithSourceTrackIDs:(NSArray *)sourceTrackIDs forTimeRange:(CMTimeRange)timeRange 73 | { 74 | self = [super init]; 75 | if (self) { 76 | _requiredSourceTrackIDs = sourceTrackIDs; 77 | _passthroughTrackID = kCMPersistentTrackID_Invalid; 78 | _timeRange = timeRange; 79 | _containsTweening = TRUE; 80 | _enablePostProcessing = FALSE; 81 | } 82 | 83 | return self; 84 | } 85 | 86 | @end 87 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/APLCustomVideoCompositor.h: -------------------------------------------------------------------------------- 1 | /* 2 | File: APLCustomVideoCompositor.h 3 | Abstract: Custom video compositor class implementing the AVVideoCompositing protocol. 4 | Version: 1.2 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2014 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | #import 49 | #import 50 | 51 | @interface APLCustomVideoCompositor : NSObject 52 | 53 | @end 54 | 55 | @interface APLCrossDissolveCompositor : APLCustomVideoCompositor 56 | 57 | @end 58 | 59 | @interface APLDiagonalWipeCompositor : APLCustomVideoCompositor 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/APLCustomVideoCompositor.m: -------------------------------------------------------------------------------- 1 | /* 2 | File: APLCustomVideoCompositor.m 3 | Abstract: Custom video compositor class implementing the AVVideoCompositing protocol. 4 | Version: 1.2 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2014 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | #import "APLCustomVideoCompositor.h" 49 | #import "APLCustomVideoCompositionInstruction.h" 50 | #import "APLDiagonalWipeRenderer.h" 51 | #import "APLCrossDissolveRenderer.h" 52 | 53 | #import 54 | 55 | @interface APLCustomVideoCompositor() 56 | { 57 | BOOL _shouldCancelAllRequests; 58 | BOOL _renderContextDidChange; 59 | dispatch_queue_t _renderingQueue; 60 | dispatch_queue_t _renderContextQueue; 61 | AVVideoCompositionRenderContext* _renderContext; 62 | CVPixelBufferRef _previousBuffer; 63 | } 64 | 65 | @property (nonatomic, strong) APLOpenGLRenderer *oglRenderer; 66 | 67 | @end 68 | 69 | @implementation APLCrossDissolveCompositor 70 | 71 | - (id)init 72 | { 73 | self = [super init]; 74 | 75 | if (self) { 76 | self.oglRenderer = [[APLCrossDissolveRenderer alloc] init]; 77 | } 78 | 79 | return self; 80 | } 81 | 82 | @end 83 | 84 | @implementation APLDiagonalWipeCompositor 85 | 86 | - (id)init 87 | { 88 | self = [super init]; 89 | 90 | if (self) { 91 | self.oglRenderer = [[APLDiagonalWipeRenderer alloc] init]; 92 | } 93 | 94 | return self; 95 | } 96 | 97 | @end 98 | 99 | @implementation APLCustomVideoCompositor 100 | 101 | #pragma mark - AVVideoCompositing protocol 102 | 103 | - (id)init 104 | { 105 | self = [super init]; 106 | if (self) 107 | { 108 | _renderingQueue = dispatch_queue_create("com.apple.aplcustomvideocompositor.renderingqueue", DISPATCH_QUEUE_SERIAL); 109 | _renderContextQueue = dispatch_queue_create("com.apple.aplcustomvideocompositor.rendercontextqueue", DISPATCH_QUEUE_SERIAL); 110 | _previousBuffer = nil; 111 | _renderContextDidChange = NO; 112 | } 113 | return self; 114 | } 115 | 116 | - (NSDictionary *)sourcePixelBufferAttributes 117 | { 118 | return @{ (NSString *)kCVPixelBufferPixelFormatTypeKey : [NSNumber numberWithUnsignedInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange], 119 | (NSString*)kCVPixelBufferOpenGLESCompatibilityKey : [NSNumber numberWithBool:YES]}; 120 | } 121 | 122 | - (NSDictionary *)requiredPixelBufferAttributesForRenderContext 123 | { 124 | return @{ (NSString *)kCVPixelBufferPixelFormatTypeKey : [NSNumber numberWithUnsignedInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange], 125 | (NSString*)kCVPixelBufferOpenGLESCompatibilityKey : [NSNumber numberWithBool:YES]}; 126 | } 127 | 128 | - (void)renderContextChanged:(AVVideoCompositionRenderContext *)newRenderContext 129 | { 130 | dispatch_sync(_renderContextQueue, ^() { 131 | _renderContext = newRenderContext; 132 | _renderContextDidChange = YES; 133 | }); 134 | } 135 | 136 | - (void)startVideoCompositionRequest:(AVAsynchronousVideoCompositionRequest *)request 137 | { 138 | @autoreleasepool { 139 | dispatch_async(_renderingQueue,^() { 140 | 141 | // Check if all pending requests have been cancelled 142 | if (_shouldCancelAllRequests) { 143 | [request finishCancelledRequest]; 144 | } else { 145 | NSError *err = nil; 146 | // Get the next rendererd pixel buffer 147 | CVPixelBufferRef resultPixels = [self newRenderedPixelBufferForRequest:request error:&err]; 148 | 149 | if (resultPixels) { 150 | // The resulting pixelbuffer from OpenGL renderer is passed along to the request 151 | [request finishWithComposedVideoFrame:resultPixels]; 152 | CFRelease(resultPixels); 153 | } else { 154 | [request finishWithError:err]; 155 | } 156 | } 157 | }); 158 | } 159 | } 160 | 161 | - (void)cancelAllPendingVideoCompositionRequests 162 | { 163 | // pending requests will call finishCancelledRequest, those already rendering will call finishWithComposedVideoFrame 164 | _shouldCancelAllRequests = YES; 165 | 166 | dispatch_barrier_async(_renderingQueue, ^() { 167 | // start accepting requests again 168 | _shouldCancelAllRequests = NO; 169 | }); 170 | } 171 | 172 | #pragma mark - Utilities 173 | 174 | static Float64 factorForTimeInRange(CMTime time, CMTimeRange range) /* 0.0 -> 1.0 */ 175 | { 176 | CMTime elapsed = CMTimeSubtract(time, range.start); 177 | return CMTimeGetSeconds(elapsed) / CMTimeGetSeconds(range.duration); 178 | } 179 | 180 | - (CVPixelBufferRef)newRenderedPixelBufferForRequest:(AVAsynchronousVideoCompositionRequest *)request error:(NSError **)errOut 181 | { 182 | CVPixelBufferRef dstPixels = nil; 183 | 184 | // tweenFactor indicates how far within that timeRange are we rendering this frame. This is normalized to vary between 0.0 and 1.0. 185 | // 0.0 indicates the time at first frame in that videoComposition timeRange 186 | // 1.0 indicates the time at last frame in that videoComposition timeRange 187 | float tweenFactor = factorForTimeInRange(request.compositionTime, request.videoCompositionInstruction.timeRange); 188 | 189 | APLCustomVideoCompositionInstruction *currentInstruction = request.videoCompositionInstruction; 190 | 191 | // Source pixel buffers are used as inputs while rendering the transition 192 | CVPixelBufferRef foregroundSourceBuffer = [request sourceFrameByTrackID:currentInstruction.foregroundTrackID]; 193 | CVPixelBufferRef backgroundSourceBuffer = [request sourceFrameByTrackID:currentInstruction.backgroundTrackID]; 194 | 195 | // Destination pixel buffer into which we render the output 196 | dstPixels = [_renderContext newPixelBuffer]; 197 | 198 | // Recompute normalized render transform everytime the render context changes 199 | if (_renderContextDidChange) { 200 | // The renderTransform returned by the renderContext is in X: [0, w] and Y: [0, h] coordinate system 201 | // But since in this sample we render using OpenGLES which has its coordinate system between [-1, 1] we compute a normalized transform 202 | CGSize renderSize = _renderContext.size; 203 | CGSize destinationSize = CGSizeMake(CVPixelBufferGetWidth(dstPixels), CVPixelBufferGetHeight(dstPixels)); 204 | CGAffineTransform renderContextTransform = {renderSize.width/2, 0, 0, renderSize.height/2, renderSize.width/2, renderSize.height/2}; 205 | CGAffineTransform destinationTransform = {2/destinationSize.width, 0, 0, 2/destinationSize.height, -1, -1}; 206 | CGAffineTransform normalizedRenderTransform = CGAffineTransformConcat(CGAffineTransformConcat(renderContextTransform, _renderContext.renderTransform), destinationTransform); 207 | _oglRenderer.renderTransform = normalizedRenderTransform; 208 | 209 | _renderContextDidChange = NO; 210 | } 211 | 212 | [_oglRenderer renderPixelBuffer:dstPixels usingForegroundSourceBuffer:foregroundSourceBuffer andBackgroundSourceBuffer:backgroundSourceBuffer forTweenFactor:tweenFactor]; 213 | 214 | return dstPixels; 215 | } 216 | 217 | @end 218 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/APLDiagonalWipeRenderer.h: -------------------------------------------------------------------------------- 1 | /* 2 | File: APLDiagonalWipeRenderer.h 3 | Abstract: APLDiagonalWipeRenderer subclass of APLOpenGLRenderer, renders the given source buffers to perform a diagonal wipe over the time range of the transition. 4 | Version: 1.2 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2014 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | #import "APLOpenGLRenderer.h" 49 | 50 | @interface APLDiagonalWipeRenderer : APLOpenGLRenderer 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/APLDiagonalWipeRenderer.m: -------------------------------------------------------------------------------- 1 | /* 2 | File: APLDiagonalWipeRenderer.m 3 | Abstract: APLDiagonalWipeRenderer subclass of APLOpenGLRenderer, renders the given source buffers to perform a diagonal wipe over the time range of the transition. 4 | Version: 1.2 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2014 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | #import "APLDiagonalWipeRenderer.h" 49 | 50 | #define kForegroundTrack 0 51 | #define kBackgroundTrack 1 52 | 53 | @interface APLDiagonalWipeRenderer () 54 | { 55 | CGPoint _diagonalEnd1; 56 | CGPoint _diagonalEnd2; 57 | } 58 | 59 | @end 60 | 61 | @implementation APLDiagonalWipeRenderer 62 | 63 | - (void)quadVertexCoordinates:(GLfloat *)vertexCoordinates forFrame:(int)trackID forTweenFactor:(float)tween 64 | { 65 | /* 66 | diagonalEnd1 and diagonalEnd2 represent the endpoints of a line which partitions the frame on screen into the two parts. 67 | 68 | diagonalEnd1 69 | ------------X----------- 70 | | | 71 | | X diagonalEnd2 72 | | | 73 | | | 74 | ------------------------ 75 | 76 | The below conditionals, use the tween factor as a measure to determine the size of the foreground and background quads. 77 | 78 | */ 79 | 80 | if (tween <= 0.5) { // The expectation here is that in half the timeRange of the transition we reach the diagonal of the frame 81 | _diagonalEnd2.x = 1.0; 82 | _diagonalEnd1.y = -1.0; 83 | _diagonalEnd1.x = 1.0 - tween * 4; 84 | _diagonalEnd2.y = -1.0 + tween * 4; 85 | 86 | vertexCoordinates[6] = _diagonalEnd2.x; 87 | vertexCoordinates[7] = _diagonalEnd2.y; 88 | vertexCoordinates[8] = _diagonalEnd1.x; 89 | vertexCoordinates[9] = _diagonalEnd1.y; 90 | 91 | } 92 | else if (tween > 0.5 && tween < 1.0) { 93 | if (trackID == kForegroundTrack) { 94 | _diagonalEnd1.x = -1.0; 95 | _diagonalEnd2.y = 1.0; 96 | _diagonalEnd2.x = 1.0 - (tween - 0.5) * 4; 97 | _diagonalEnd1.y = -1.0 + (tween - 0.5) * 4; 98 | 99 | vertexCoordinates[2] = _diagonalEnd2.x; 100 | vertexCoordinates[3] = _diagonalEnd2.y; 101 | vertexCoordinates[4] = _diagonalEnd1.x; 102 | vertexCoordinates[5] = _diagonalEnd1.y; 103 | vertexCoordinates[6] = _diagonalEnd1.x; 104 | vertexCoordinates[7] = _diagonalEnd1.y; 105 | vertexCoordinates[8] = _diagonalEnd1.x; 106 | vertexCoordinates[9] = _diagonalEnd1.y; 107 | } 108 | else if (trackID == kBackgroundTrack) { 109 | vertexCoordinates[4] = 1.0; 110 | vertexCoordinates[5] = 1.0; 111 | vertexCoordinates[6] = -1.0; 112 | vertexCoordinates[7] = -1.0; 113 | } 114 | } 115 | else if (tween >= 1.0) { 116 | _diagonalEnd1 = CGPointMake(1.0, -1.0); 117 | _diagonalEnd2 = CGPointMake(1.0, -1.0); 118 | } 119 | } 120 | 121 | - (void)renderPixelBuffer:(CVPixelBufferRef)destinationPixelBuffer usingForegroundSourceBuffer:(CVPixelBufferRef)foregroundPixelBuffer andBackgroundSourceBuffer:(CVPixelBufferRef)backgroundPixelBuffer forTweenFactor:(float)tween 122 | { 123 | [EAGLContext setCurrentContext:self.currentContext]; 124 | 125 | if (foregroundPixelBuffer != NULL || backgroundPixelBuffer != NULL) { 126 | 127 | CVOpenGLESTextureRef foregroundLumaTexture = [self lumaTextureForPixelBuffer:foregroundPixelBuffer]; 128 | CVOpenGLESTextureRef foregroundChromaTexture = [self chromaTextureForPixelBuffer:foregroundPixelBuffer]; 129 | 130 | CVOpenGLESTextureRef backgroundLumaTexture = [self lumaTextureForPixelBuffer:backgroundPixelBuffer]; 131 | CVOpenGLESTextureRef backgroundChromaTexture = [self chromaTextureForPixelBuffer:backgroundPixelBuffer]; 132 | 133 | CVOpenGLESTextureRef destLumaTexture = [self lumaTextureForPixelBuffer:destinationPixelBuffer]; 134 | CVOpenGLESTextureRef destChromaTexture = [self chromaTextureForPixelBuffer:destinationPixelBuffer]; 135 | 136 | glUseProgram(self.programY); 137 | 138 | // Set the render transform 139 | GLfloat preferredRenderTransform [] = { 140 | self.renderTransform.a, self.renderTransform.b, self.renderTransform.tx, 0.0, 141 | self.renderTransform.c, self.renderTransform.d, self.renderTransform.ty, 0.0, 142 | 0.0, 0.0, 1.0, 0.0, 143 | 0.0, 0.0, 0.0, 1.0, 144 | }; 145 | 146 | glUniformMatrix4fv(uniforms[UNIFORM_RENDER_TRANSFORM_Y], 1, GL_FALSE, preferredRenderTransform); 147 | 148 | glBindFramebuffer(GL_FRAMEBUFFER, self.offscreenBufferHandle); 149 | 150 | glViewport(0, 0, (int)CVPixelBufferGetWidthOfPlane(destinationPixelBuffer, 0), (int)CVPixelBufferGetHeightOfPlane(destinationPixelBuffer, 0)); 151 | 152 | // Y planes of foreground and background frame are used to render the Y plane of the destination frame 153 | glActiveTexture(GL_TEXTURE0); 154 | glBindTexture(CVOpenGLESTextureGetTarget(foregroundLumaTexture), CVOpenGLESTextureGetName(foregroundLumaTexture)); 155 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 156 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 157 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 158 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 159 | 160 | glActiveTexture(GL_TEXTURE1); 161 | glBindTexture(CVOpenGLESTextureGetTarget(backgroundLumaTexture), CVOpenGLESTextureGetName(backgroundLumaTexture)); 162 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 163 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 164 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 165 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 166 | 167 | // Attach the destination texture as a color attachment to the off screen frame buffer 168 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, CVOpenGLESTextureGetTarget(destLumaTexture), CVOpenGLESTextureGetName(destLumaTexture), 0); 169 | 170 | if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 171 | NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER)); 172 | goto bail; 173 | } 174 | 175 | glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 176 | glClear(GL_COLOR_BUFFER_BIT); 177 | 178 | GLfloat quadVertexData1 [] = { 179 | -1.0, 1.0, 180 | 1.0, 1.0, 181 | -1.0, -1.0, 182 | 1.0, -1.0, 183 | 1.0, -1.0, 184 | }; 185 | 186 | // Compute the vertex data for the foreground frame at this instructionLerp 187 | [self quadVertexCoordinates:quadVertexData1 forFrame:kForegroundTrack forTweenFactor:tween]; 188 | 189 | // texture data varies from 0 -> 1, whereas vertex data varies from -1 -> 1 190 | GLfloat quadTextureData1 [] = { 191 | 0.5 + quadVertexData1[0]/2, 0.5 + quadVertexData1[1]/2, 192 | 0.5 + quadVertexData1[2]/2, 0.5 + quadVertexData1[3]/2, 193 | 0.5 + quadVertexData1[4]/2, 0.5 + quadVertexData1[5]/2, 194 | 0.5 + quadVertexData1[6]/2, 0.5 + quadVertexData1[7]/2, 195 | 0.5 + quadVertexData1[8]/2, 0.5 + quadVertexData1[9]/2, 196 | }; 197 | 198 | glUniform1i(uniforms[UNIFORM_Y], 0); 199 | 200 | glVertexAttribPointer(ATTRIB_VERTEX_Y, 2, GL_FLOAT, 0, 0, quadVertexData1); 201 | glEnableVertexAttribArray(ATTRIB_VERTEX_Y); 202 | 203 | glVertexAttribPointer(ATTRIB_TEXCOORD_Y, 2, GL_FLOAT, 0, 0, quadTextureData1); 204 | glEnableVertexAttribArray(ATTRIB_TEXCOORD_Y); 205 | 206 | // Draw the foreground frame 207 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 5); 208 | 209 | GLfloat quadVertexData2 [] = { 210 | _diagonalEnd2.x, _diagonalEnd2.y, 211 | _diagonalEnd1.x, _diagonalEnd1.y, 212 | 1.0, -1.0, 213 | 1.0, -1.0, 214 | 1.0, -1.0, 215 | }; 216 | 217 | // Compute the vertex data for the background frame at this instructionLerp 218 | [self quadVertexCoordinates:quadVertexData2 forFrame:kBackgroundTrack forTweenFactor:tween]; 219 | 220 | GLfloat quadTextureData2 [] = { 221 | 0.5 + quadVertexData2[0]/2, 0.5 + quadVertexData2[1]/2, 222 | 0.5 + quadVertexData2[2]/2, 0.5 + quadVertexData2[3]/2, 223 | 0.5 + quadVertexData2[4]/2, 0.5 + quadVertexData2[5]/2, 224 | 0.5 + quadVertexData2[6]/2, 0.5 + quadVertexData2[7]/2, 225 | 0.5 + quadVertexData2[8]/2, 0.5 + quadVertexData2[9]/2, 226 | }; 227 | 228 | glUniform1i(uniforms[UNIFORM_Y], 1); 229 | 230 | glVertexAttribPointer(ATTRIB_VERTEX_Y, 2, GL_FLOAT, 0, 0, quadVertexData2); 231 | glEnableVertexAttribArray(ATTRIB_VERTEX_Y); 232 | 233 | glVertexAttribPointer(ATTRIB_TEXCOORD_Y, 2, GL_FLOAT, 0, 0, quadTextureData2); 234 | glEnableVertexAttribArray(ATTRIB_TEXCOORD_Y); 235 | 236 | // Draw the background frame 237 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 5); 238 | 239 | // Perform similar operations as above for the UV plane 240 | glUseProgram(self.programUV); 241 | 242 | glUniformMatrix4fv(uniforms[UNIFORM_RENDER_TRANSFORM_UV], 1, GL_FALSE, preferredRenderTransform); 243 | 244 | // UV planes of foreground and background frame are used to render the UV plane of the destination frame 245 | glActiveTexture(GL_TEXTURE2); 246 | glBindTexture(CVOpenGLESTextureGetTarget(foregroundChromaTexture), CVOpenGLESTextureGetName(foregroundChromaTexture)); 247 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 248 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 249 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 250 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 251 | 252 | glActiveTexture(GL_TEXTURE3); 253 | glBindTexture(CVOpenGLESTextureGetTarget(backgroundChromaTexture), CVOpenGLESTextureGetName(backgroundChromaTexture)); 254 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 255 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 256 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 257 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 258 | 259 | glViewport(0, 0, (int)CVPixelBufferGetWidthOfPlane(destinationPixelBuffer, 1), (int)CVPixelBufferGetHeightOfPlane(destinationPixelBuffer, 1)); 260 | 261 | // Attach the destination texture as a color attachment to the off screen frame buffer 262 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, CVOpenGLESTextureGetTarget(destChromaTexture), CVOpenGLESTextureGetName(destChromaTexture), 0); 263 | 264 | if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 265 | NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER)); 266 | goto bail; 267 | } 268 | 269 | glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 270 | glClear(GL_COLOR_BUFFER_BIT); 271 | 272 | glUniform1i(uniforms[UNIFORM_UV], 2); 273 | 274 | glVertexAttribPointer(ATTRIB_VERTEX_UV, 2, GL_FLOAT, 0, 0, quadVertexData1); 275 | glEnableVertexAttribArray(ATTRIB_VERTEX_UV); 276 | 277 | glVertexAttribPointer(ATTRIB_TEXCOORD_UV, 2, GL_FLOAT, 0, 0, quadTextureData1); 278 | glEnableVertexAttribArray(ATTRIB_TEXCOORD_UV); 279 | 280 | // Draw the foreground frame 281 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 5); 282 | 283 | glUniform1i(uniforms[UNIFORM_UV], 3); 284 | 285 | glVertexAttribPointer(ATTRIB_VERTEX_UV, 2, GL_FLOAT, 0, 0, quadVertexData2); 286 | glEnableVertexAttribArray(ATTRIB_VERTEX_UV); 287 | 288 | glVertexAttribPointer(ATTRIB_TEXCOORD_UV, 2, GL_FLOAT, 0, 0, quadTextureData2); 289 | glEnableVertexAttribArray(ATTRIB_TEXCOORD_UV); 290 | 291 | // Draw the background frame 292 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 5); 293 | 294 | glFlush(); 295 | 296 | bail: 297 | CFRelease(foregroundLumaTexture); 298 | CFRelease(foregroundChromaTexture); 299 | CFRelease(backgroundLumaTexture); 300 | CFRelease(backgroundChromaTexture); 301 | CFRelease(destLumaTexture); 302 | CFRelease(destChromaTexture); 303 | 304 | // Periodic texture cache flush every frame 305 | CVOpenGLESTextureCacheFlush(self.videoTextureCache, 0); 306 | 307 | [EAGLContext setCurrentContext:nil]; 308 | } 309 | } 310 | 311 | @end 312 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/APLOpenGLRenderer.h: -------------------------------------------------------------------------------- 1 | /* 2 | File: APLOpenGLRenderer.h 3 | Abstract: OpenGL base class renderer sets up an EAGLContext for rendering, it also loads, compiles and links the vertex and fragment shaders for both the Y and UV planes. 4 | Version: 1.2 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2014 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | #import 49 | #import 50 | #import 51 | #import 52 | 53 | enum 54 | { 55 | UNIFORM_Y, 56 | UNIFORM_UV, 57 | UNIFORM_RENDER_TRANSFORM_Y, 58 | UNIFORM_RENDER_TRANSFORM_UV, 59 | NUM_UNIFORMS 60 | }; 61 | GLint uniforms[NUM_UNIFORMS]; 62 | 63 | enum 64 | { 65 | ATTRIB_VERTEX_Y, 66 | ATTRIB_TEXCOORD_Y, 67 | ATTRIB_VERTEX_UV, 68 | ATTRIB_TEXCOORD_UV, 69 | NUM_ATTRIBUTES 70 | }; 71 | 72 | @interface APLOpenGLRenderer : NSObject 73 | 74 | @property GLuint programY; 75 | @property GLuint programUV; 76 | @property CGAffineTransform renderTransform; 77 | @property CVOpenGLESTextureCacheRef videoTextureCache; 78 | @property EAGLContext *currentContext; 79 | @property GLuint offscreenBufferHandle; 80 | 81 | - (CVOpenGLESTextureRef)lumaTextureForPixelBuffer:(CVPixelBufferRef)pixelBuffer; 82 | - (CVOpenGLESTextureRef)chromaTextureForPixelBuffer:(CVPixelBufferRef)pixelBuffer; 83 | - (void)renderPixelBuffer:(CVPixelBufferRef)destinationPixelBuffer usingForegroundSourceBuffer:(CVPixelBufferRef)foregroundPixelBuffer andBackgroundSourceBuffer:(CVPixelBufferRef)backgroundPixelBuffer forTweenFactor:(float)tween; 84 | 85 | @end 86 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/APLOpenGLRenderer.m: -------------------------------------------------------------------------------- 1 | /* 2 | File: APLOpenGLRenderer.m 3 | Abstract: OpenGL base class renderer sets up an EAGLContext for rendering, it also loads, compiles and links the vertex and fragment shaders for both the Y and UV planes. 4 | Version: 1.2 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2014 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | #import "APLOpenGLRenderer.h" 49 | 50 | static const char kPassThroughVertexShader[] = { 51 | "attribute vec4 position; \n \ 52 | attribute vec2 texCoord; \n \ 53 | uniform mat4 renderTransform; \n \ 54 | varying vec2 texCoordVarying; \n \ 55 | void main() \n \ 56 | { \n \ 57 | gl_Position = position * renderTransform; \n \ 58 | texCoordVarying = texCoord; \n \ 59 | }" 60 | }; 61 | 62 | static const char kPassThroughFragmentShaderY[] = { 63 | "varying highp vec2 texCoordVarying; \n \ 64 | uniform sampler2D SamplerY; \n \ 65 | void main() \n \ 66 | { \n \ 67 | gl_FragColor.r = texture2D(SamplerY, texCoordVarying).r; \n \ 68 | }" 69 | }; 70 | 71 | static const char kPassThroughFragmentShaderUV[] = { 72 | "varying highp vec2 texCoordVarying; \n \ 73 | uniform sampler2D SamplerUV; \n \ 74 | void main() \n \ 75 | { \n \ 76 | gl_FragColor.rg = texture2D(SamplerUV, texCoordVarying).rg; \n \ 77 | }" 78 | }; 79 | 80 | @interface APLOpenGLRenderer () 81 | 82 | - (void)setupOffscreenRenderContext; 83 | 84 | - (BOOL)loadShaders; 85 | - (BOOL)compileShader:(GLuint *)shader type:(GLenum)type source:(NSString *)source; 86 | - (BOOL)linkProgram:(GLuint)prog; 87 | - (BOOL)validateProgram:(GLuint)prog; 88 | 89 | @end 90 | 91 | @implementation APLOpenGLRenderer 92 | 93 | - (id)init 94 | { 95 | self = [super init]; 96 | if(self) { 97 | _currentContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; 98 | [EAGLContext setCurrentContext:_currentContext]; 99 | 100 | [self setupOffscreenRenderContext]; 101 | [self loadShaders]; 102 | 103 | [EAGLContext setCurrentContext:nil]; 104 | } 105 | 106 | return self; 107 | } 108 | 109 | - (void)dealloc 110 | { 111 | if (_videoTextureCache) { 112 | CFRelease(_videoTextureCache); 113 | } 114 | if (_offscreenBufferHandle) { 115 | glDeleteFramebuffers(1, &_offscreenBufferHandle); 116 | _offscreenBufferHandle = 0; 117 | } 118 | } 119 | 120 | - (void)renderPixelBuffer:(CVPixelBufferRef)destinationPixelBuffer usingForegroundSourceBuffer:(CVPixelBufferRef)foregroundPixelBuffer andBackgroundSourceBuffer:(CVPixelBufferRef)backgroundPixelBuffer forTweenFactor:(float)tween 121 | { 122 | [self doesNotRecognizeSelector:_cmd]; 123 | } 124 | 125 | - (void)setupOffscreenRenderContext 126 | { 127 | //-- Create CVOpenGLESTextureCacheRef for optimal CVPixelBufferRef to GLES texture conversion. 128 | if (_videoTextureCache) { 129 | CFRelease(_videoTextureCache); 130 | _videoTextureCache = NULL; 131 | } 132 | CVReturn err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, _currentContext, NULL, &_videoTextureCache); 133 | if (err != noErr) { 134 | NSLog(@"Error at CVOpenGLESTextureCacheCreate %d", err); 135 | } 136 | 137 | glDisable(GL_DEPTH_TEST); 138 | 139 | glGenFramebuffers(1, &_offscreenBufferHandle); 140 | glBindFramebuffer(GL_FRAMEBUFFER, _offscreenBufferHandle); 141 | } 142 | 143 | - (CVOpenGLESTextureRef)lumaTextureForPixelBuffer:(CVPixelBufferRef)pixelBuffer 144 | { 145 | CVOpenGLESTextureRef lumaTexture = NULL; 146 | CVReturn err; 147 | 148 | if (!_videoTextureCache) { 149 | NSLog(@"No video texture cache"); 150 | goto bail; 151 | } 152 | 153 | // Periodic texture cache flush every frame 154 | CVOpenGLESTextureCacheFlush(_videoTextureCache, 0); 155 | 156 | // CVOpenGLTextureCacheCreateTextureFromImage will create GL texture optimally from CVPixelBufferRef. 157 | // Y 158 | err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, 159 | _videoTextureCache, 160 | pixelBuffer, 161 | NULL, 162 | GL_TEXTURE_2D, 163 | GL_RED_EXT, 164 | (int)CVPixelBufferGetWidth(pixelBuffer), 165 | (int)CVPixelBufferGetHeight(pixelBuffer), 166 | GL_RED_EXT, 167 | GL_UNSIGNED_BYTE, 168 | 0, 169 | &lumaTexture); 170 | 171 | if (!lumaTexture || err) { 172 | NSLog(@"Error at creating luma texture using CVOpenGLESTextureCacheCreateTextureFromImage %d", err); 173 | } 174 | 175 | bail: 176 | return lumaTexture; 177 | } 178 | 179 | - (CVOpenGLESTextureRef)chromaTextureForPixelBuffer:(CVPixelBufferRef)pixelBuffer 180 | { 181 | CVOpenGLESTextureRef chromaTexture = NULL; 182 | CVReturn err; 183 | 184 | if (!_videoTextureCache) { 185 | NSLog(@"No video texture cache"); 186 | goto bail; 187 | } 188 | 189 | // Periodic texture cache flush every frame 190 | CVOpenGLESTextureCacheFlush(_videoTextureCache, 0); 191 | 192 | // CVOpenGLTextureCacheCreateTextureFromImage will create GL texture optimally from CVPixelBufferRef. 193 | // UV 194 | err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, 195 | _videoTextureCache, 196 | pixelBuffer, 197 | NULL, 198 | GL_TEXTURE_2D, 199 | GL_RG_EXT, 200 | (int)CVPixelBufferGetWidthOfPlane(pixelBuffer, 1), 201 | (int)CVPixelBufferGetHeightOfPlane(pixelBuffer, 1), 202 | GL_RG_EXT, 203 | GL_UNSIGNED_BYTE, 204 | 1, 205 | &chromaTexture); 206 | 207 | if (!chromaTexture || err) { 208 | NSLog(@"Error at creating chroma texture using CVOpenGLESTextureCacheCreateTextureFromImage %d", err); 209 | } 210 | 211 | bail: 212 | return chromaTexture; 213 | } 214 | 215 | #pragma mark - OpenGL ES 2 shader compilation 216 | 217 | - (BOOL)loadShaders 218 | { 219 | GLuint vertShader, fragShaderY, fragShaderUV; 220 | NSString *vertShaderSource, *fragShaderYSource, *fragShaderUVSource; 221 | 222 | // Create the shader program. 223 | _programY = glCreateProgram(); 224 | _programUV = glCreateProgram(); 225 | 226 | // Create and compile the vertex shader. 227 | vertShaderSource = [NSString stringWithCString:kPassThroughVertexShader encoding:NSUTF8StringEncoding]; 228 | if (![self compileShader:&vertShader type:GL_VERTEX_SHADER source:vertShaderSource]) { 229 | NSLog(@"Failed to compile vertex shader"); 230 | return NO; 231 | } 232 | 233 | // Create and compile Y fragment shader. 234 | fragShaderYSource = [NSString stringWithCString:kPassThroughFragmentShaderY encoding:NSUTF8StringEncoding]; 235 | if (![self compileShader:&fragShaderY type:GL_FRAGMENT_SHADER source:fragShaderYSource]) { 236 | NSLog(@"Failed to compile Y fragment shader"); 237 | return NO; 238 | } 239 | 240 | // Create and compile UV fragment shader. 241 | fragShaderUVSource = [NSString stringWithCString:kPassThroughFragmentShaderUV encoding:NSUTF8StringEncoding]; 242 | if (![self compileShader:&fragShaderUV type:GL_FRAGMENT_SHADER source:fragShaderUVSource]) { 243 | NSLog(@"Failed to compile UV fragment shader"); 244 | return NO; 245 | } 246 | 247 | // Attach vertex shader to programY. 248 | glAttachShader(_programY, vertShader); 249 | 250 | // Attach fragment shader to programY. 251 | glAttachShader(_programY, fragShaderY); 252 | 253 | // Attach vertex shader to programY. 254 | glAttachShader(_programUV, vertShader); 255 | 256 | // Attach fragment shader to programY. 257 | glAttachShader(_programUV, fragShaderUV); 258 | 259 | 260 | // Bind attribute locations. This needs to be done prior to linking. 261 | 262 | glBindAttribLocation(_programY, ATTRIB_VERTEX_Y, "position"); 263 | glBindAttribLocation(_programY, ATTRIB_TEXCOORD_Y, "texCoord"); 264 | glBindAttribLocation(_programUV, ATTRIB_VERTEX_UV, "position"); 265 | glBindAttribLocation(_programUV, ATTRIB_TEXCOORD_UV, "texCoord"); 266 | 267 | // Link the program. 268 | if (![self linkProgram:_programY] || ![self linkProgram:_programUV]) { 269 | NSLog(@"Failed to link program: %d and %d", _programY, _programUV); 270 | 271 | if (vertShader) { 272 | glDeleteShader(vertShader); 273 | vertShader = 0; 274 | } 275 | if (fragShaderY) { 276 | glDeleteShader(fragShaderY); 277 | fragShaderY = 0; 278 | } 279 | if (fragShaderUV) { 280 | glDeleteShader(fragShaderUV); 281 | fragShaderUV = 0; 282 | } 283 | if (_programY) { 284 | glDeleteProgram(_programY); 285 | _programY = 0; 286 | } 287 | if (_programUV) { 288 | glDeleteProgram(_programUV); 289 | _programUV = 0; 290 | } 291 | 292 | return NO; 293 | } 294 | 295 | // Get uniform locations. 296 | uniforms[UNIFORM_Y] = glGetUniformLocation(_programY, "SamplerY"); 297 | uniforms[UNIFORM_UV] = glGetUniformLocation(_programUV, "SamplerUV"); 298 | uniforms[UNIFORM_RENDER_TRANSFORM_Y] = glGetUniformLocation(_programY, "renderTransform"); 299 | uniforms[UNIFORM_RENDER_TRANSFORM_UV] = glGetUniformLocation(_programUV, "renderTransform"); 300 | 301 | // Release vertex and fragment shaders. 302 | if (vertShader) { 303 | glDetachShader(_programY, vertShader); 304 | glDetachShader(_programUV, vertShader); 305 | glDeleteShader(vertShader); 306 | } 307 | if (fragShaderY) { 308 | glDetachShader(_programY, fragShaderY); 309 | glDeleteShader(fragShaderY); 310 | } 311 | if (fragShaderUV) { 312 | glDetachShader(_programUV, fragShaderUV); 313 | glDeleteShader(fragShaderUV); 314 | } 315 | 316 | return YES; 317 | } 318 | 319 | - (BOOL)compileShader:(GLuint *)shader type:(GLenum)type source:(NSString *)sourceString 320 | { 321 | if (sourceString == nil) { 322 | NSLog(@"Failed to load vertex shader: Empty source string"); 323 | return NO; 324 | } 325 | 326 | GLint status; 327 | const GLchar *source; 328 | source = (GLchar *)[sourceString UTF8String]; 329 | 330 | *shader = glCreateShader(type); 331 | glShaderSource(*shader, 1, &source, NULL); 332 | glCompileShader(*shader); 333 | 334 | #if defined(DEBUG) 335 | GLint logLength; 336 | glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); 337 | if (logLength > 0) { 338 | GLchar *log = (GLchar *)malloc(logLength); 339 | glGetShaderInfoLog(*shader, logLength, &logLength, log); 340 | NSLog(@"Shader compile log:\n%s", log); 341 | free(log); 342 | } 343 | #endif 344 | 345 | glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); 346 | if (status == 0) { 347 | glDeleteShader(*shader); 348 | return NO; 349 | } 350 | 351 | return YES; 352 | } 353 | 354 | - (BOOL)linkProgram:(GLuint)prog 355 | { 356 | GLint status; 357 | glLinkProgram(prog); 358 | 359 | #if defined(DEBUG) 360 | GLint logLength; 361 | glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); 362 | if (logLength > 0) { 363 | GLchar *log = (GLchar *)malloc(logLength); 364 | glGetProgramInfoLog(prog, logLength, &logLength, log); 365 | NSLog(@"Program link log:\n%s", log); 366 | free(log); 367 | } 368 | #endif 369 | 370 | glGetProgramiv(prog, GL_LINK_STATUS, &status); 371 | if (status == 0) { 372 | return NO; 373 | } 374 | 375 | return YES; 376 | } 377 | 378 | #if defined(DEBUG) 379 | 380 | - (BOOL)validateProgram:(GLuint)prog 381 | { 382 | GLint logLength, status; 383 | 384 | glValidateProgram(prog); 385 | glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); 386 | if (logLength > 0) { 387 | GLchar *log = (GLchar *)malloc(logLength); 388 | glGetProgramInfoLog(prog, logLength, &logLength, log); 389 | NSLog(@"Program validate log:\n%s", log); 390 | free(log); 391 | } 392 | 393 | glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); 394 | if (status == 0) { 395 | return NO; 396 | } 397 | 398 | return YES; 399 | } 400 | 401 | #endif 402 | 403 | @end 404 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/APLSimpleEditor.h: -------------------------------------------------------------------------------- 1 | /* 2 | File: APLSimpleEditor.h 3 | Abstract: Simple editor sets up an AVMutableComposition using supplied clips and time ranges. It also sets up an AVVideoComposition to perform custom compositor rendering. 4 | Version: 1.2 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2014 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | #import 49 | 50 | #import 51 | 52 | @class AVPlayerItem, AVAssetExportSession; 53 | 54 | @interface APLSimpleEditor : NSObject 55 | 56 | // Set these properties before building the composition objects. 57 | @property (nonatomic, copy) NSArray *clips; // array of AVURLAssets 58 | @property (nonatomic, copy) NSArray *clipTimeRanges; // array of CMTimeRanges stored in NSValues. 59 | 60 | @property (nonatomic) NSInteger transitionType; 61 | @property (nonatomic) CMTime transitionDuration; 62 | 63 | // Builds the composition and videoComposition 64 | - (void)buildCompositionObjectsForPlayback:(BOOL)forPlayback; 65 | 66 | - (AVAssetExportSession*)assetExportSessionWithPreset:(NSString*)presetName; 67 | 68 | - (AVPlayerItem *)playerItem; 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/APLSimpleEditor.m: -------------------------------------------------------------------------------- 1 | /* 2 | File: APLSimpleEditor.m 3 | Abstract: Simple editor sets up an AVMutableComposition using supplied clips and time ranges. It also sets up an AVVideoComposition to perform custom compositor rendering. 4 | Version: 1.2 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2014 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | #import "APLSimpleEditor.h" 49 | #import "APLTransitionTypeController.h" 50 | #import "APLCustomVideoCompositor.h" 51 | #import "APLCustomVideoCompositionInstruction.h" 52 | #import 53 | #import 54 | 55 | 56 | @interface APLSimpleEditor () 57 | 58 | @property (nonatomic, strong) AVMutableComposition *composition; 59 | @property (nonatomic, strong) AVMutableVideoComposition *videoComposition; 60 | 61 | @end 62 | 63 | 64 | 65 | @implementation APLSimpleEditor 66 | 67 | 68 | - (void)buildTransitionComposition:(AVMutableComposition *)composition andVideoComposition:(AVMutableVideoComposition *)videoComposition 69 | { 70 | CMTime nextClipStartTime = kCMTimeZero; 71 | NSInteger i; 72 | NSUInteger clipsCount = [_clips count]; 73 | 74 | // Make transitionDuration no greater than half the shortest clip duration. 75 | CMTime transitionDuration = self.transitionDuration; 76 | for (i = 0; i < clipsCount; i++ ) { 77 | NSValue *clipTimeRange = [_clipTimeRanges objectAtIndex:i]; 78 | if (clipTimeRange) { 79 | CMTime halfClipDuration = [clipTimeRange CMTimeRangeValue].duration; 80 | halfClipDuration.timescale *= 2; // You can halve a rational by doubling its denominator. 81 | transitionDuration = CMTimeMinimum(transitionDuration, halfClipDuration); 82 | } 83 | } 84 | 85 | // Add two video tracks and two audio tracks. 86 | AVMutableCompositionTrack *compositionVideoTracks[2]; 87 | AVMutableCompositionTrack *compositionAudioTracks[2]; 88 | compositionVideoTracks[0] = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; 89 | compositionVideoTracks[1] = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; 90 | compositionAudioTracks[0] = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; 91 | compositionAudioTracks[1] = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; 92 | 93 | CMTimeRange *passThroughTimeRanges = alloca(sizeof(CMTimeRange) * clipsCount); 94 | CMTimeRange *transitionTimeRanges = alloca(sizeof(CMTimeRange) * clipsCount); 95 | 96 | // Place clips into alternating video & audio tracks in composition, overlapped by transitionDuration. 97 | for (i = 0; i < clipsCount; i++ ) { 98 | NSInteger alternatingIndex = i % 2; // alternating targets: 0, 1, 0, 1, ... 99 | AVURLAsset *asset = [_clips objectAtIndex:i]; 100 | NSValue *clipTimeRange = [_clipTimeRanges objectAtIndex:i]; 101 | CMTimeRange timeRangeInAsset; 102 | if (clipTimeRange) 103 | timeRangeInAsset = [clipTimeRange CMTimeRangeValue]; 104 | else 105 | timeRangeInAsset = CMTimeRangeMake(kCMTimeZero, [asset duration]); 106 | 107 | AVAssetTrack *clipVideoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; 108 | [compositionVideoTracks[alternatingIndex] insertTimeRange:timeRangeInAsset ofTrack:clipVideoTrack atTime:nextClipStartTime error:nil]; 109 | 110 | AVAssetTrack *clipAudioTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]; 111 | [compositionAudioTracks[alternatingIndex] insertTimeRange:timeRangeInAsset ofTrack:clipAudioTrack atTime:nextClipStartTime error:nil]; 112 | 113 | // Remember the time range in which this clip should pass through. 114 | // First clip ends with a transition. 115 | // Second clip begins with a transition. 116 | // Exclude that transition from the pass through time ranges. 117 | passThroughTimeRanges[i] = CMTimeRangeMake(nextClipStartTime, timeRangeInAsset.duration); 118 | if (i > 0) { 119 | passThroughTimeRanges[i].start = CMTimeAdd(passThroughTimeRanges[i].start, transitionDuration); 120 | passThroughTimeRanges[i].duration = CMTimeSubtract(passThroughTimeRanges[i].duration, transitionDuration); 121 | } 122 | if (i+1 < clipsCount) { 123 | passThroughTimeRanges[i].duration = CMTimeSubtract(passThroughTimeRanges[i].duration, transitionDuration); 124 | } 125 | 126 | // The end of this clip will overlap the start of the next by transitionDuration. 127 | // (Note: this arithmetic falls apart if timeRangeInAsset.duration < 2 * transitionDuration.) 128 | nextClipStartTime = CMTimeAdd(nextClipStartTime, timeRangeInAsset.duration); 129 | nextClipStartTime = CMTimeSubtract(nextClipStartTime, transitionDuration); 130 | 131 | // Remember the time range for the transition to the next item. 132 | if (i+1 < clipsCount) { 133 | transitionTimeRanges[i] = CMTimeRangeMake(nextClipStartTime, transitionDuration); 134 | } 135 | } 136 | 137 | // Set up the video composition to perform cross dissolve or diagonal wipe transitions between clips. 138 | NSMutableArray *instructions = [NSMutableArray array]; 139 | 140 | // Cycle between "pass through A", "transition from A to B", "pass through B" 141 | for (i = 0; i < clipsCount; i++ ) { 142 | NSInteger alternatingIndex = i % 2; // alternating targets 143 | 144 | if (videoComposition.customVideoCompositorClass) { 145 | APLCustomVideoCompositionInstruction *videoInstruction = [[APLCustomVideoCompositionInstruction alloc] initPassThroughTrackID:compositionVideoTracks[alternatingIndex].trackID forTimeRange:passThroughTimeRanges[i]]; 146 | [instructions addObject:videoInstruction]; 147 | } 148 | else { 149 | // Pass through clip i. 150 | AVMutableVideoCompositionInstruction *passThroughInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; 151 | passThroughInstruction.timeRange = passThroughTimeRanges[i]; 152 | AVMutableVideoCompositionLayerInstruction *passThroughLayer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:compositionVideoTracks[alternatingIndex]]; 153 | 154 | passThroughInstruction.layerInstructions = [NSArray arrayWithObject:passThroughLayer]; 155 | [instructions addObject:passThroughInstruction]; 156 | } 157 | 158 | if (i+1 < clipsCount) { 159 | // Add transition from clip i to clip i+1. 160 | 161 | if (videoComposition.customVideoCompositorClass) { 162 | APLCustomVideoCompositionInstruction *videoInstruction = [[APLCustomVideoCompositionInstruction alloc] initTransitionWithSourceTrackIDs:@[[NSNumber numberWithInt:compositionVideoTracks[0].trackID], [NSNumber numberWithInt:compositionVideoTracks[1].trackID]] forTimeRange:transitionTimeRanges[i]]; 163 | if (alternatingIndex == 0) { 164 | // First track -> Foreground track while compositing 165 | videoInstruction.foregroundTrackID = compositionVideoTracks[alternatingIndex].trackID; 166 | // Second track -> Background track while compositing 167 | videoInstruction.backgroundTrackID = compositionVideoTracks[1-alternatingIndex].trackID; 168 | } 169 | 170 | [instructions addObject:videoInstruction]; 171 | } 172 | else { 173 | AVMutableVideoCompositionInstruction *transitionInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; 174 | transitionInstruction.timeRange = transitionTimeRanges[i]; 175 | AVMutableVideoCompositionLayerInstruction *fromLayer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:compositionVideoTracks[alternatingIndex]]; 176 | AVMutableVideoCompositionLayerInstruction *toLayer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:compositionVideoTracks[1-alternatingIndex]]; 177 | 178 | transitionInstruction.layerInstructions = [NSArray arrayWithObjects:fromLayer, toLayer, nil]; 179 | [instructions addObject:transitionInstruction]; 180 | } 181 | } 182 | } 183 | 184 | videoComposition.instructions = instructions; 185 | } 186 | 187 | - (void)buildCompositionObjectsForPlayback:(BOOL)forPlayback 188 | { 189 | if ( (_clips == nil) || [_clips count] == 0 ) { 190 | self.composition = nil; 191 | self.videoComposition = nil; 192 | return; 193 | } 194 | 195 | CGSize videoSize = [[_clips objectAtIndex:0] naturalSize]; 196 | AVMutableComposition *composition = [AVMutableComposition composition]; 197 | AVMutableVideoComposition *videoComposition = nil; 198 | 199 | composition.naturalSize = videoSize; 200 | 201 | // With transitions: 202 | // Place clips into alternating video & audio tracks in composition, overlapped by transitionDuration. 203 | // Set up the video composition to cycle between "pass through A", "transition from A to B", 204 | // "pass through B". 205 | 206 | videoComposition = [AVMutableVideoComposition videoComposition]; 207 | 208 | if (self.transitionType == kDiagonalWipeTransition) { 209 | videoComposition.customVideoCompositorClass = [APLDiagonalWipeCompositor class]; 210 | } else { 211 | videoComposition.customVideoCompositorClass = [APLCrossDissolveCompositor class]; 212 | } 213 | 214 | [self buildTransitionComposition:composition andVideoComposition:videoComposition]; 215 | 216 | if (videoComposition) { 217 | // Every videoComposition needs these properties to be set: 218 | videoComposition.frameDuration = CMTimeMake(1, 30); // 30 fps 219 | videoComposition.renderSize = videoSize; 220 | } 221 | 222 | self.composition = composition; 223 | self.videoComposition = videoComposition; 224 | } 225 | 226 | - (AVAssetExportSession*)assetExportSessionWithPreset:(NSString*)presetName 227 | { 228 | AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:self.composition presetName:presetName]; 229 | session.videoComposition = self.videoComposition; 230 | return session; 231 | } 232 | 233 | - (AVPlayerItem *)playerItem 234 | { 235 | AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:self.composition]; 236 | playerItem.videoComposition = self.videoComposition; 237 | 238 | return playerItem; 239 | } 240 | 241 | @end 242 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/APLTransitionTypeController.h: -------------------------------------------------------------------------------- 1 | /* 2 | File: APLTransitionTypeController.h 3 | Abstract: UITableViewController subclass which lets the user select the type of transition for their composition. 4 | Version: 1.2 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2014 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | #import 49 | 50 | #define kDiagonalWipeTransition 0 51 | #define kCrossDissolveTransition 1 52 | 53 | @protocol APLTransitionTypePickerDelegate; 54 | 55 | @interface APLTransitionTypeController : UITableViewController 56 | 57 | @property IBOutlet UITableViewCell *diagonalWipeCell; 58 | @property IBOutlet UITableViewCell *crossDissolveCell; 59 | 60 | @property NSInteger currentTransition; 61 | 62 | @property id delegate; 63 | 64 | - (IBAction)transitionSelected:(id)sender; 65 | 66 | @end 67 | 68 | @protocol APLTransitionTypePickerDelegate 69 | 70 | - (void)transitionTypeController:(APLTransitionTypeController *)controller didPickTransitionType:(int)transitionType; 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/APLTransitionTypeController.m: -------------------------------------------------------------------------------- 1 | /* 2 | File: APLTransitionTypeController.m 3 | Abstract: UITableViewController subclass which lets the user select the type of transition for their composition. 4 | Version: 1.2 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2014 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | #import "APLTransitionTypeController.h" 49 | 50 | @implementation APLTransitionTypeController 51 | 52 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 53 | { 54 | UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath]; 55 | [selectedCell setAccessoryType:UITableViewCellAccessoryCheckmark]; 56 | 57 | switch ([selectedCell tag]) { 58 | case kDiagonalWipeTransition:{ 59 | [self.crossDissolveCell setAccessoryType:UITableViewCellAccessoryNone]; 60 | [self.delegate transitionTypeController:self didPickTransitionType:kDiagonalWipeTransition]; 61 | self.currentTransition = kDiagonalWipeTransition; 62 | break; 63 | } 64 | case kCrossDissolveTransition:{ 65 | [self.diagonalWipeCell setAccessoryType:UITableViewCellAccessoryNone]; 66 | [self.delegate transitionTypeController:self didPickTransitionType:kCrossDissolveTransition]; 67 | self.currentTransition = kCrossDissolveTransition; 68 | break; 69 | } 70 | default: 71 | break; 72 | } 73 | 74 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 75 | } 76 | 77 | - (IBAction)transitionSelected:(id)sender 78 | { 79 | [self.delegate transitionTypeController:self didPickTransitionType:(int)self.currentTransition]; 80 | } 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/APLViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | File: APLViewController.h 3 | Abstract: UIViewController subclasses which handles setup, playback and export of AVMutableComposition along with other user interactions like scrubbing, toggling play/pause, selecting transition type. 4 | Version: 1.2 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2014 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | #import 49 | #import "APLTransitionTypeController.h" 50 | 51 | @class AVPlayer, AVPlayerItem, APLSimpleEditor, APLPlayerView; 52 | 53 | @interface APLViewController : UIViewController 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/APLViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | File: APLViewController.m 3 | Abstract: UIViewController subclasses which handles setup, playback and export of AVMutableComposition along with other user interactions like scrubbing, toggling play/pause, selecting transition type. 4 | Version: 1.2 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2014 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | #import 49 | #import 50 | #import 51 | #import 52 | 53 | #import "APLViewController.h" 54 | #import "APLSimpleEditor.h" 55 | 56 | /* 57 | Player view backed by an AVPlayerLayer 58 | */ 59 | @interface APLPlayerView : UIView 60 | 61 | @property (nonatomic, strong) AVPlayer *player; 62 | 63 | @end 64 | 65 | 66 | 67 | @implementation APLPlayerView 68 | 69 | + (Class)layerClass 70 | { 71 | return [AVPlayerLayer class]; 72 | } 73 | 74 | - (AVPlayer *)player 75 | { 76 | return [(AVPlayerLayer *)[self layer] player]; 77 | } 78 | 79 | - (void)setPlayer:(AVPlayer *)player 80 | { 81 | [(AVPlayerLayer *)[self layer] setPlayer:player]; 82 | } 83 | 84 | @end 85 | /* 86 | */ 87 | 88 | static NSString* const AVCustomEditPlayerViewControllerStatusObservationContext = @"AVCustomEditPlayerViewControllerStatusObservationContext"; 89 | static NSString* const AVCustomEditPlayerViewControllerRateObservationContext = @"AVCustomEditPlayerViewControllerRateObservationContext"; 90 | 91 | @interface APLViewController () 92 | 93 | @property APLSimpleEditor *editor; 94 | @property NSMutableArray *clips; 95 | @property NSMutableArray *clipTimeRanges; 96 | 97 | @property AVPlayer *player; 98 | @property AVPlayerItem *playerItem; 99 | 100 | @property UIPopoverController *popover; 101 | 102 | - (void)updatePlayPauseButton; 103 | - (void)updateScrubber; 104 | - (void)updateTimeLabel; 105 | 106 | - (CMTime)playerItemDuration; 107 | 108 | - (void)synchronizePlayerWithEditor; 109 | 110 | @property IBOutlet APLPlayerView *playerView; 111 | 112 | @property IBOutlet UIToolbar *toolbar; 113 | @property IBOutlet UISlider *scrubber; 114 | @property IBOutlet UIBarButtonItem *playPauseButton; 115 | @property IBOutlet UIBarButtonItem *transitionButton; 116 | @property IBOutlet UIBarButtonItem *exportButton; 117 | @property IBOutlet UILabel *currentTimeLabel; 118 | @property IBOutlet UIProgressView *exportProgressView; 119 | 120 | - (IBAction)handleTapGesture:(UITapGestureRecognizer *)tapGestureRecognizer; 121 | - (IBAction)togglePlayPause:(id)sender; 122 | - (IBAction)exportToMovie:(id)sender; 123 | 124 | - (IBAction)beginScrubbing:(id)sender; 125 | - (IBAction)scrub:(id)sender; 126 | - (IBAction)endScrubbing:(id)sender; 127 | 128 | 129 | @end 130 | 131 | 132 | 133 | @implementation APLViewController 134 | { 135 | @private 136 | BOOL _playing; 137 | BOOL _scrubInFlight; 138 | BOOL _seekToZeroBeforePlaying; 139 | float _lastScrubSliderValue; 140 | float _playRateToRestore; 141 | id _timeObserver; 142 | 143 | float _transitionDuration; 144 | NSInteger _transitionType; 145 | BOOL _transitionsEnabled; 146 | 147 | NSTimer *_progressTimer; 148 | } 149 | 150 | 151 | #pragma mark - View loading 152 | 153 | - (void)viewDidLoad 154 | { 155 | [super viewDidLoad]; 156 | 157 | self.editor = [[APLSimpleEditor alloc] init]; 158 | self.clips = [[NSMutableArray alloc] initWithCapacity:2]; 159 | self.clipTimeRanges = [[NSMutableArray alloc] initWithCapacity:2]; 160 | 161 | // Defaults for the transition settings. 162 | _transitionType = kDiagonalWipeTransition; 163 | _transitionDuration = 2.0; 164 | _transitionsEnabled = YES; 165 | 166 | [self updateScrubber]; 167 | [self updateTimeLabel]; 168 | 169 | // Add the clips from the main bundle to create a composition using them 170 | [self setupEditingAndPlayback]; 171 | } 172 | 173 | - (void)viewDidAppear:(BOOL)animated 174 | { 175 | [super viewDidAppear:animated]; 176 | 177 | if (!self.player) { 178 | _seekToZeroBeforePlaying = NO; 179 | self.player = [[AVPlayer alloc] init]; 180 | [self.player addObserver:self forKeyPath:@"rate" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:(__bridge void *)(AVCustomEditPlayerViewControllerRateObservationContext)]; 181 | [self.playerView setPlayer:self.player]; 182 | } 183 | 184 | [self addTimeObserverToPlayer]; 185 | 186 | // Build AVComposition and AVVideoComposition objects for playback 187 | [self.editor buildCompositionObjectsForPlayback:YES]; 188 | [self synchronizePlayerWithEditor]; 189 | } 190 | 191 | - (void)viewWillDisappear:(BOOL)animated 192 | { 193 | [super viewWillDisappear:animated]; 194 | 195 | [self.player pause]; 196 | [self removeTimeObserverFromPlayer]; 197 | } 198 | 199 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 200 | { 201 | if ([segue.identifier isEqualToString:@"Transition"]) 202 | { 203 | // Setup transition type picker controller before it is shown. 204 | APLTransitionTypeController *transitionTypePickerController = (APLTransitionTypeController *)((UINavigationController *)segue.destinationViewController).topViewController; 205 | if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { 206 | self.popover = [(UIStoryboardPopoverSegue *)segue popoverController]; 207 | } 208 | transitionTypePickerController.delegate = self; 209 | transitionTypePickerController.currentTransition = _transitionType; 210 | if (_transitionType == kCrossDissolveTransition) { 211 | // Make sure the view is loaded first 212 | if (!transitionTypePickerController.crossDissolveCell) 213 | [transitionTypePickerController loadView]; 214 | [transitionTypePickerController.crossDissolveCell setAccessoryType:UITableViewCellAccessoryCheckmark]; 215 | } else { 216 | // Make sure the view is loaded first 217 | if (!transitionTypePickerController.diagonalWipeCell) 218 | [transitionTypePickerController loadView]; 219 | [transitionTypePickerController.diagonalWipeCell setAccessoryType:UITableViewCellAccessoryCheckmark]; 220 | } 221 | } 222 | } 223 | 224 | #pragma mark - Simple Editor 225 | 226 | - (void)setupEditingAndPlayback 227 | { 228 | AVURLAsset *asset1 = [AVURLAsset assetWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"sample_clip1" ofType:@"m4v"]]]; 229 | AVURLAsset *asset2 = [AVURLAsset assetWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"sample_clip2" ofType:@"mov"]]]; 230 | 231 | dispatch_group_t dispatchGroup = dispatch_group_create(); 232 | NSArray *assetKeysToLoadAndTest = @[@"tracks", @"duration", @"composable"]; 233 | 234 | [self loadAsset:asset1 withKeys:assetKeysToLoadAndTest usingDispatchGroup:dispatchGroup]; 235 | [self loadAsset:asset2 withKeys:assetKeysToLoadAndTest usingDispatchGroup:dispatchGroup]; 236 | 237 | // Wait until both assets are loaded 238 | dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^(){ 239 | [self synchronizeWithEditor]; 240 | }); 241 | } 242 | 243 | - (void)loadAsset:(AVAsset *)asset withKeys:(NSArray *)assetKeysToLoad usingDispatchGroup:(dispatch_group_t)dispatchGroup 244 | { 245 | dispatch_group_enter(dispatchGroup); 246 | [asset loadValuesAsynchronouslyForKeys:assetKeysToLoad completionHandler:^(){ 247 | // First test whether the values of each of the keys we need have been successfully loaded. 248 | for (NSString *key in assetKeysToLoad) { 249 | NSError *error; 250 | 251 | if ([asset statusOfValueForKey:key error:&error] == AVKeyValueStatusFailed) { 252 | NSLog(@"Key value loading failed for key:%@ with error: %@", key, error); 253 | goto bail; 254 | } 255 | } 256 | if (![asset isComposable]) { 257 | NSLog(@"Asset is not composable"); 258 | goto bail; 259 | } 260 | 261 | [self.clips addObject:asset]; 262 | // This code assumes that both assets are atleast 5 seconds long. 263 | [self.clipTimeRanges addObject:[NSValue valueWithCMTimeRange:CMTimeRangeMake(CMTimeMakeWithSeconds(0, 1), CMTimeMakeWithSeconds(5, 1))]]; 264 | bail: 265 | dispatch_group_leave(dispatchGroup); 266 | }]; 267 | } 268 | 269 | - (void)synchronizePlayerWithEditor 270 | { 271 | if ( self.player == nil ) 272 | return; 273 | 274 | AVPlayerItem *playerItem = [self.editor playerItem]; 275 | 276 | if (self.playerItem != playerItem) { 277 | if ( self.playerItem ) { 278 | [self.playerItem removeObserver:self forKeyPath:@"status"]; 279 | [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:self.playerItem]; 280 | } 281 | 282 | self.playerItem = playerItem; 283 | 284 | if ( self.playerItem ) { 285 | if ( [self.playerItem respondsToSelector:@selector(setSeekingWaitsForVideoCompositionRendering:)] ) 286 | self.playerItem.seekingWaitsForVideoCompositionRendering = YES; 287 | 288 | // Observe the player item "status" key to determine when it is ready to play 289 | [self.playerItem addObserver:self forKeyPath:@"status" options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionInitial) context:(__bridge void *)(AVCustomEditPlayerViewControllerStatusObservationContext)]; 290 | 291 | // When the player item has played to its end time we'll set a flag 292 | // so that the next time the play method is issued the player will 293 | // be reset to time zero first. 294 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerItemDidReachEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.playerItem]; 295 | } 296 | [self.player replaceCurrentItemWithPlayerItem:playerItem]; 297 | } 298 | } 299 | 300 | - (void)synchronizeWithEditor 301 | { 302 | // Clips 303 | [self synchronizeEditorClipsWithOurClips]; 304 | [self synchronizeEditorClipTimeRangesWithOurClipTimeRanges]; 305 | 306 | 307 | // Transitions 308 | if (_transitionsEnabled) { 309 | self.editor.transitionDuration = CMTimeMakeWithSeconds(_transitionDuration, 600); 310 | self.editor.transitionType = _transitionType; 311 | } else { 312 | self.editor.transitionDuration = kCMTimeInvalid; 313 | } 314 | 315 | // Build AVComposition and AVVideoComposition objects for playback 316 | [self.editor buildCompositionObjectsForPlayback:YES]; 317 | 318 | [self synchronizePlayerWithEditor]; 319 | } 320 | 321 | - (void)synchronizeEditorClipsWithOurClips 322 | { 323 | NSMutableArray *validClips = [NSMutableArray arrayWithCapacity:2]; 324 | for (AVURLAsset *asset in self.clips) { 325 | if (![asset isKindOfClass:[NSNull class]]) { 326 | [validClips addObject:asset]; 327 | } 328 | } 329 | 330 | self.editor.clips = validClips; 331 | } 332 | 333 | - (void)synchronizeEditorClipTimeRangesWithOurClipTimeRanges 334 | { 335 | NSMutableArray *validClipTimeRanges = [NSMutableArray arrayWithCapacity:2]; 336 | for (NSValue *timeRange in self.clipTimeRanges) { 337 | if (! [timeRange isKindOfClass:[NSNull class]]) { 338 | [validClipTimeRanges addObject:timeRange]; 339 | } 340 | } 341 | 342 | self.editor.clipTimeRanges = validClipTimeRanges; 343 | } 344 | 345 | #pragma mark - Utilities 346 | 347 | /* Update the scrubber and time label periodically. */ 348 | - (void)addTimeObserverToPlayer 349 | { 350 | if (_timeObserver) 351 | return; 352 | 353 | if (self.player == nil) 354 | return; 355 | 356 | if (self.player.currentItem.status != AVPlayerItemStatusReadyToPlay) 357 | return; 358 | 359 | double duration = CMTimeGetSeconds([self playerItemDuration]); 360 | 361 | if (isfinite(duration)) { 362 | CGFloat width = CGRectGetWidth([self.scrubber bounds]); 363 | double interval = 0.5 * duration / width; 364 | 365 | /* The time label needs to update at least once per second. */ 366 | if (interval > 1.0) 367 | interval = 1.0; 368 | __weak APLViewController *weakSelf = self; 369 | _timeObserver = [self.player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(interval, NSEC_PER_SEC) queue:dispatch_get_main_queue() usingBlock: 370 | ^(CMTime time) { 371 | [weakSelf updateScrubber]; 372 | [weakSelf updateTimeLabel]; 373 | }]; 374 | } 375 | } 376 | 377 | - (void)removeTimeObserverFromPlayer 378 | { 379 | if (_timeObserver) { 380 | [self.player removeTimeObserver:_timeObserver]; 381 | _timeObserver = nil; 382 | } 383 | } 384 | 385 | - (CMTime)playerItemDuration 386 | { 387 | AVPlayerItem *playerItem = [self.player currentItem]; 388 | CMTime itemDuration = kCMTimeInvalid; 389 | 390 | if (playerItem.status == AVPlayerItemStatusReadyToPlay) { 391 | itemDuration = [playerItem duration]; 392 | } 393 | 394 | /* Will be kCMTimeInvalid if the item is not ready to play. */ 395 | return itemDuration; 396 | } 397 | 398 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 399 | { 400 | if ( context == (__bridge void *)(AVCustomEditPlayerViewControllerRateObservationContext) ) { 401 | float newRate = [[change objectForKey:NSKeyValueChangeNewKey] floatValue]; 402 | NSNumber *oldRateNum = [change objectForKey:NSKeyValueChangeOldKey]; 403 | if ( [oldRateNum isKindOfClass:[NSNumber class]] && newRate != [oldRateNum floatValue] ) { 404 | _playing = ((newRate != 0.f) || (_playRateToRestore != 0.f)); 405 | [self updatePlayPauseButton]; 406 | [self updateScrubber]; 407 | [self updateTimeLabel]; 408 | } 409 | } 410 | else if ( context == (__bridge void *)(AVCustomEditPlayerViewControllerStatusObservationContext) ) { 411 | AVPlayerItem *playerItem = (AVPlayerItem *)object; 412 | if (playerItem.status == AVPlayerItemStatusReadyToPlay) { 413 | /* Once the AVPlayerItem becomes ready to play, i.e. 414 | [playerItem status] == AVPlayerItemStatusReadyToPlay, 415 | its duration can be fetched from the item. */ 416 | 417 | [self addTimeObserverToPlayer]; 418 | } 419 | else if (playerItem.status == AVPlayerItemStatusFailed) { 420 | [self reportError:playerItem.error]; 421 | } 422 | } 423 | else { 424 | [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; 425 | } 426 | } 427 | 428 | - (void)updatePlayPauseButton 429 | { 430 | UIBarButtonSystemItem style = _playing ? UIBarButtonSystemItemPause : UIBarButtonSystemItemPlay; 431 | UIBarButtonItem *newPlayPauseButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:style target:self action:@selector(togglePlayPause:)]; 432 | 433 | NSMutableArray *items = [NSMutableArray arrayWithArray:self.toolbar.items]; 434 | [items replaceObjectAtIndex:[items indexOfObject:self.playPauseButton] withObject:newPlayPauseButton]; 435 | [self.toolbar setItems:items]; 436 | 437 | self.playPauseButton = newPlayPauseButton; 438 | } 439 | 440 | - (void)updateTimeLabel 441 | { 442 | double seconds = CMTimeGetSeconds([self.player currentTime]); 443 | if (!isfinite(seconds)) { 444 | seconds = 0; 445 | } 446 | 447 | int secondsInt = round(seconds); 448 | int minutes = secondsInt/60; 449 | secondsInt -= minutes*60; 450 | 451 | self.currentTimeLabel.textColor = [UIColor colorWithWhite:1.0 alpha:1.0]; 452 | self.currentTimeLabel.textAlignment = NSTextAlignmentCenter; 453 | 454 | self.currentTimeLabel.text = [NSString stringWithFormat:@"%.2i:%.2i", minutes, secondsInt]; 455 | } 456 | 457 | - (void)updateScrubber 458 | { 459 | double duration = CMTimeGetSeconds([self playerItemDuration]); 460 | 461 | if (isfinite(duration)) { 462 | double time = CMTimeGetSeconds([self.player currentTime]); 463 | [self.scrubber setValue:time / duration]; 464 | } 465 | else { 466 | [self.scrubber setValue:0.0]; 467 | } 468 | } 469 | 470 | - (void)updateProgress:(NSTimer*)timer 471 | { 472 | AVAssetExportSession *session = (AVAssetExportSession *)[timer userInfo]; 473 | if (session.status == AVAssetExportSessionStatusExporting) { 474 | _exportProgressView.progress = session.progress; 475 | } 476 | } 477 | 478 | - (void)reportError:(NSError *)error 479 | { 480 | dispatch_async(dispatch_get_main_queue(), ^{ 481 | if (error) { 482 | UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[error localizedDescription] 483 | message:[error localizedRecoverySuggestion] 484 | delegate:nil 485 | cancelButtonTitle:NSLocalizedString(@"OK", nil) 486 | otherButtonTitles:nil]; 487 | 488 | [alertView show]; 489 | } 490 | }); 491 | } 492 | 493 | #pragma mark - IBActions 494 | 495 | - (IBAction)togglePlayPause:(id)sender 496 | { 497 | _playing = !_playing; 498 | if ( _playing ) { 499 | if ( _seekToZeroBeforePlaying ) { 500 | [self.player seekToTime:kCMTimeZero]; 501 | _seekToZeroBeforePlaying = NO; 502 | } 503 | [self.player play]; 504 | } 505 | else { 506 | [self.player pause]; 507 | } 508 | } 509 | 510 | - (IBAction)beginScrubbing:(id)sender 511 | { 512 | _seekToZeroBeforePlaying = NO; 513 | _playRateToRestore = [self.player rate]; 514 | [self.player setRate:0.0]; 515 | 516 | [self removeTimeObserverFromPlayer]; 517 | } 518 | 519 | - (IBAction)scrub:(id)sender 520 | { 521 | _lastScrubSliderValue = [self.scrubber value]; 522 | 523 | if ( ! _scrubInFlight ) 524 | [self scrubToSliderValue:_lastScrubSliderValue]; 525 | } 526 | 527 | - (void)scrubToSliderValue:(float)sliderValue 528 | { 529 | double duration = CMTimeGetSeconds([self playerItemDuration]); 530 | 531 | if (isfinite(duration)) { 532 | CGFloat width = CGRectGetWidth([self.scrubber bounds]); 533 | 534 | double time = duration*sliderValue; 535 | double tolerance = 1.0f * duration / width; 536 | 537 | _scrubInFlight = YES; 538 | 539 | [self.player seekToTime:CMTimeMakeWithSeconds(time, NSEC_PER_SEC) 540 | toleranceBefore:CMTimeMakeWithSeconds(tolerance, NSEC_PER_SEC) 541 | toleranceAfter:CMTimeMakeWithSeconds(tolerance, NSEC_PER_SEC) 542 | completionHandler:^(BOOL finished) { 543 | _scrubInFlight = NO; 544 | [self updateTimeLabel]; 545 | }]; 546 | } 547 | } 548 | 549 | - (IBAction)endScrubbing:(id)sender 550 | { 551 | if ( _scrubInFlight ) 552 | [self scrubToSliderValue:_lastScrubSliderValue]; 553 | [self addTimeObserverToPlayer]; 554 | 555 | [self.player setRate:_playRateToRestore]; 556 | _playRateToRestore = 0.f; 557 | } 558 | 559 | /* Called when the player item has played to its end time. */ 560 | - (void)playerItemDidReachEnd:(NSNotification *)notification 561 | { 562 | /* After the movie has played to its end time, seek back to time zero to play it again. */ 563 | _seekToZeroBeforePlaying = YES; 564 | } 565 | 566 | - (IBAction)handleTapGesture:(UITapGestureRecognizer *)tapGestureRecognizer 567 | { 568 | self.toolbar.hidden = !self.toolbar.hidden; 569 | self.currentTimeLabel.hidden = !self.currentTimeLabel.hidden; 570 | } 571 | 572 | - (IBAction)exportToMovie:(id)sender 573 | { 574 | _exportProgressView.hidden = NO; 575 | 576 | [self.player pause]; 577 | [self.playPauseButton setEnabled:NO]; 578 | [self.transitionButton setEnabled:NO]; 579 | [self.scrubber setEnabled:NO]; 580 | [self.exportButton setEnabled:NO]; 581 | 582 | [self.editor buildCompositionObjectsForPlayback:NO]; 583 | 584 | // Get the export session from the editor 585 | AVAssetExportSession *session = [self.editor assetExportSessionWithPreset:AVAssetExportPresetMediumQuality]; 586 | 587 | // Remove the file if it already exists 588 | NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"ExportedProject.mov"]; 589 | [[NSFileManager defaultManager] removeItemAtPath:filePath error:NULL]; 590 | 591 | // If a preset that is not compatible with AVFileTypeQuickTimeMovie is used, one can use -[AVAssetExportSession supportedFileTypes] to obtain a supported file type for the output file and UTTypeCreatePreferredIdentifierForTag to obtain an appropriate path extension for the output file type. 592 | session.outputURL = [NSURL fileURLWithPath:filePath]; 593 | session.outputFileType = AVFileTypeQuickTimeMovie; 594 | 595 | [session exportAsynchronouslyWithCompletionHandler:^{ 596 | dispatch_async(dispatch_get_main_queue(), ^{ 597 | [self exportCompleted:session]; 598 | }); 599 | }]; 600 | 601 | // Update progress view with export progress 602 | _progressTimer = [NSTimer timerWithTimeInterval:0.5 target:self selector:@selector(updateProgress:) userInfo:session repeats:YES]; 603 | [[NSRunLoop currentRunLoop] addTimer:_progressTimer forMode:NSDefaultRunLoopMode]; 604 | } 605 | 606 | - (void)exportCompleted:(AVAssetExportSession *)session 607 | { 608 | _exportProgressView.hidden = YES; 609 | _currentTimeLabel.hidden = NO; 610 | NSURL *outputURL = session.outputURL; 611 | 612 | [_progressTimer invalidate]; 613 | _progressTimer = nil; 614 | 615 | if ( session.status != AVAssetExportSessionStatusCompleted ) { 616 | NSLog(@"exportSession error:%@", session.error); 617 | [self reportError:session.error]; 618 | } 619 | 620 | if ( session.status != AVAssetExportSessionStatusCompleted ) { 621 | return; 622 | } 623 | 624 | _exportProgressView.progress = 1.0; 625 | 626 | // Save the exported movie to the camera roll 627 | ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; 628 | [library writeVideoAtPathToSavedPhotosAlbum:outputURL completionBlock:^(NSURL *assetURL, NSError *error) { 629 | if (error != NULL) { 630 | NSLog(@"writeVideoToAssestsLibrary failed: %@", error); 631 | [self reportError:error]; 632 | } 633 | }]; 634 | 635 | [self.player play]; 636 | [self.playPauseButton setEnabled:YES]; 637 | [self.transitionButton setEnabled:YES]; 638 | [self.scrubber setEnabled:YES]; 639 | [self.exportButton setEnabled:YES]; 640 | } 641 | 642 | #pragma mark - Gesture recognizer delegate 643 | 644 | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch 645 | { 646 | if (touch.view != self.playerView) { 647 | // Ignore touch on toolbar. 648 | return NO; 649 | } 650 | return YES; 651 | } 652 | 653 | #pragma mark - APLTransitionTypePickerDelegate 654 | 655 | - (void)transitionTypeController:(APLTransitionTypeController *)controller didPickTransitionType:(int)transitionType 656 | { 657 | _transitionType = transitionType; 658 | 659 | // Let the editor know of the change in transition type. 660 | [self synchronizeWithEditor]; 661 | 662 | if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { 663 | [self.popover dismissPopoverAnimated:YES]; 664 | } else { 665 | [self dismissViewControllerAnimated:YES completion:nil]; 666 | } 667 | } 668 | 669 | @end 670 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/AVCustomEdit-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.example.apple-samplecode.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.1 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.1 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | MainStoryboard_iPhone 29 | UIMainStoryboardFile~ipad 30 | MainStoryboard_iPad 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationLandscapeLeft 38 | UIInterfaceOrientationLandscapeRight 39 | 40 | UISupportedInterfaceOrientations~ipad 41 | 42 | UIInterfaceOrientationLandscapeLeft 43 | UIInterfaceOrientationLandscapeRight 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/AVCustomEdit-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'AVCustomEdit' target in the 'AVCustomEdit' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_7_0 8 | #warning "This project uses features only available in iOS SDK 7.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/Base.lproj/MainStoryboard_iPad.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 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 65 | 66 | 67 | 68 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/Base.lproj/MainStoryboard_iPhone.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grassel/AVCustomEdit/36df210c0e74a43c152c2bf67dc48b1aa5f0a8ae/AVCustomEdit/AVCustomEdit/Default-568h@2x.png -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grassel/AVCustomEdit/36df210c0e74a43c152c2bf67dc48b1aa5f0a8ae/AVCustomEdit/AVCustomEdit/Default.png -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grassel/AVCustomEdit/36df210c0e74a43c152c2bf67dc48b1aa5f0a8ae/AVCustomEdit/AVCustomEdit/Default@2x.png -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/main.m: -------------------------------------------------------------------------------- 1 | /* 2 | File: main.m 3 | Abstract: Simple main file. 4 | Version: 1.2 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2014 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | #import 49 | 50 | #import "APLAppDelegate.h" 51 | 52 | int main(int argc, char *argv[]) 53 | { 54 | @autoreleasepool { 55 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([APLAppDelegate class])); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/sample_clip1.m4v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grassel/AVCustomEdit/36df210c0e74a43c152c2bf67dc48b1aa5f0a8ae/AVCustomEdit/AVCustomEdit/sample_clip1.m4v -------------------------------------------------------------------------------- /AVCustomEdit/AVCustomEdit/sample_clip2.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grassel/AVCustomEdit/36df210c0e74a43c152c2bf67dc48b1aa5f0a8ae/AVCustomEdit/AVCustomEdit/sample_clip2.mov -------------------------------------------------------------------------------- /AVCustomEdit/ReadMe.txt: -------------------------------------------------------------------------------- 1 | 2 | AVCustomEdit 3 | ============ 4 | 5 | AVCustomEdit is a simple AVFoundation based movie editing application demonstrating custom compositing to add transitions. The sample demonstrates the use of custom compositors to add transitions to an AVMutableComposition. It implements the AVVideoCompositing and AVVideoCompositionInstruction protocols to have access to individual source frames, which are then be rendered using OpenGL off screen rendering. 6 | 7 | Note: The sample has been developed for iPhones 4S and above/iPods with 4-inch display and iPads. These developed transitions are not supported on simulator. 8 | 9 | ==================================================================================== 10 | 11 | The main classes are as follows: 12 | 13 | APLSimpleEditor 14 | This class setups an AVComposition with relevant AVVideoCompositions using the provided clips and time ranges. 15 | 16 | APLCustomVideoCompositionInstruction 17 | Custom video composition instruction class implementing AVVideoCompositionInstruction protocol. 18 | 19 | APLCustomVideoCompositor 20 | Custom video compositor class implementing AVVideoCompositing protocol. 21 | 22 | APLOpenGLRenderer 23 | Base class renderer setups an EAGLContext for rendering, it also loads, compiles and links the vertex and fragment shaders for both Y and UV plane. 24 | 25 | APLDiagonalWipeRenderer 26 | A subclass of APLOpenGLRenderer, renders the given source buffers to perform a diagonal wipe over the transition time range. 27 | 28 | APLCrossDissolveRenderer 29 | A subclass of APLOpenGLRenderer, renders the given source buffers to perform a cross dissolve over the transition time range. 30 | 31 | APLViewController 32 | A UIViewController subclass. This contains the view controller logic including playback and editing setup. 33 | 34 | APLTransitionTypeController 35 | A subclass of UITableViewController which controls UI for selecting transition type. 36 | 37 | ============================================================== 38 | Copyright © 2013 Apple Inc. All rights reserved. --------------------------------------------------------------------------------