├── README.md ├── VTEncodeDemo.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── dev.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── dev.xcuserdatad │ └── xcschemes │ ├── VTEncodeDemo.xcscheme │ └── xcschememanagement.plist └── VTEncodeDemo ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets └── AppIcon.appiconset │ └── Contents.json ├── Base.lproj ├── LaunchScreen.storyboard └── Main.storyboard ├── Info.plist ├── ViewController.h ├── ViewController.m └── main.m /README.md: -------------------------------------------------------------------------------- 1 | # iOS VideoToolbox encode demo 2 | 详细中文注释版 3 | -------------------------------------------------------------------------------- /VTEncodeDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | D7DEBCF31D49F45A006AF714 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D7DEBCF21D49F45A006AF714 /* main.m */; }; 11 | D7DEBCF61D49F45A006AF714 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D7DEBCF51D49F45A006AF714 /* AppDelegate.m */; }; 12 | D7DEBCF91D49F45A006AF714 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D7DEBCF81D49F45A006AF714 /* ViewController.m */; }; 13 | D7DEBCFC1D49F45A006AF714 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D7DEBCFA1D49F45A006AF714 /* Main.storyboard */; }; 14 | D7DEBCFE1D49F45A006AF714 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D7DEBCFD1D49F45A006AF714 /* Assets.xcassets */; }; 15 | D7DEBD011D49F45A006AF714 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D7DEBCFF1D49F45A006AF714 /* LaunchScreen.storyboard */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXFileReference section */ 19 | D7DEBCEE1D49F45A006AF714 /* VTEncodeDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = VTEncodeDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 20 | D7DEBCF21D49F45A006AF714 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 21 | D7DEBCF41D49F45A006AF714 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 22 | D7DEBCF51D49F45A006AF714 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 23 | D7DEBCF71D49F45A006AF714 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 24 | D7DEBCF81D49F45A006AF714 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 25 | D7DEBCFB1D49F45A006AF714 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 26 | D7DEBCFD1D49F45A006AF714 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 27 | D7DEBD001D49F45A006AF714 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 28 | D7DEBD021D49F45A006AF714 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 29 | /* End PBXFileReference section */ 30 | 31 | /* Begin PBXFrameworksBuildPhase section */ 32 | D7DEBCEB1D49F45A006AF714 /* Frameworks */ = { 33 | isa = PBXFrameworksBuildPhase; 34 | buildActionMask = 2147483647; 35 | files = ( 36 | ); 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXFrameworksBuildPhase section */ 40 | 41 | /* Begin PBXGroup section */ 42 | D7DEBCE51D49F45A006AF714 = { 43 | isa = PBXGroup; 44 | children = ( 45 | D7DEBCF01D49F45A006AF714 /* VTEncodeDemo */, 46 | D7DEBCEF1D49F45A006AF714 /* Products */, 47 | ); 48 | sourceTree = ""; 49 | }; 50 | D7DEBCEF1D49F45A006AF714 /* Products */ = { 51 | isa = PBXGroup; 52 | children = ( 53 | D7DEBCEE1D49F45A006AF714 /* VTEncodeDemo.app */, 54 | ); 55 | name = Products; 56 | sourceTree = ""; 57 | }; 58 | D7DEBCF01D49F45A006AF714 /* VTEncodeDemo */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | D7DEBCF71D49F45A006AF714 /* ViewController.h */, 62 | D7DEBCF81D49F45A006AF714 /* ViewController.m */, 63 | D7DEBCFA1D49F45A006AF714 /* Main.storyboard */, 64 | D7DEBCF11D49F45A006AF714 /* Supporting Files */, 65 | ); 66 | path = VTEncodeDemo; 67 | sourceTree = ""; 68 | }; 69 | D7DEBCF11D49F45A006AF714 /* Supporting Files */ = { 70 | isa = PBXGroup; 71 | children = ( 72 | D7DEBCF21D49F45A006AF714 /* main.m */, 73 | D7DEBCF41D49F45A006AF714 /* AppDelegate.h */, 74 | D7DEBCF51D49F45A006AF714 /* AppDelegate.m */, 75 | D7DEBCFD1D49F45A006AF714 /* Assets.xcassets */, 76 | D7DEBCFF1D49F45A006AF714 /* LaunchScreen.storyboard */, 77 | D7DEBD021D49F45A006AF714 /* Info.plist */, 78 | ); 79 | name = "Supporting Files"; 80 | sourceTree = ""; 81 | }; 82 | /* End PBXGroup section */ 83 | 84 | /* Begin PBXNativeTarget section */ 85 | D7DEBCED1D49F45A006AF714 /* VTEncodeDemo */ = { 86 | isa = PBXNativeTarget; 87 | buildConfigurationList = D7DEBD051D49F45A006AF714 /* Build configuration list for PBXNativeTarget "VTEncodeDemo" */; 88 | buildPhases = ( 89 | D7DEBCEA1D49F45A006AF714 /* Sources */, 90 | D7DEBCEB1D49F45A006AF714 /* Frameworks */, 91 | D7DEBCEC1D49F45A006AF714 /* Resources */, 92 | ); 93 | buildRules = ( 94 | ); 95 | dependencies = ( 96 | ); 97 | name = VTEncodeDemo; 98 | productName = VTEncodeDemo; 99 | productReference = D7DEBCEE1D49F45A006AF714 /* VTEncodeDemo.app */; 100 | productType = "com.apple.product-type.application"; 101 | }; 102 | /* End PBXNativeTarget section */ 103 | 104 | /* Begin PBXProject section */ 105 | D7DEBCE61D49F45A006AF714 /* Project object */ = { 106 | isa = PBXProject; 107 | attributes = { 108 | LastUpgradeCheck = 0730; 109 | ORGANIZATIONNAME = Shawn; 110 | TargetAttributes = { 111 | D7DEBCED1D49F45A006AF714 = { 112 | CreatedOnToolsVersion = 7.3.1; 113 | }; 114 | }; 115 | }; 116 | buildConfigurationList = D7DEBCE91D49F45A006AF714 /* Build configuration list for PBXProject "VTEncodeDemo" */; 117 | compatibilityVersion = "Xcode 3.2"; 118 | developmentRegion = English; 119 | hasScannedForEncodings = 0; 120 | knownRegions = ( 121 | en, 122 | Base, 123 | ); 124 | mainGroup = D7DEBCE51D49F45A006AF714; 125 | productRefGroup = D7DEBCEF1D49F45A006AF714 /* Products */; 126 | projectDirPath = ""; 127 | projectRoot = ""; 128 | targets = ( 129 | D7DEBCED1D49F45A006AF714 /* VTEncodeDemo */, 130 | ); 131 | }; 132 | /* End PBXProject section */ 133 | 134 | /* Begin PBXResourcesBuildPhase section */ 135 | D7DEBCEC1D49F45A006AF714 /* Resources */ = { 136 | isa = PBXResourcesBuildPhase; 137 | buildActionMask = 2147483647; 138 | files = ( 139 | D7DEBD011D49F45A006AF714 /* LaunchScreen.storyboard in Resources */, 140 | D7DEBCFE1D49F45A006AF714 /* Assets.xcassets in Resources */, 141 | D7DEBCFC1D49F45A006AF714 /* Main.storyboard in Resources */, 142 | ); 143 | runOnlyForDeploymentPostprocessing = 0; 144 | }; 145 | /* End PBXResourcesBuildPhase section */ 146 | 147 | /* Begin PBXSourcesBuildPhase section */ 148 | D7DEBCEA1D49F45A006AF714 /* Sources */ = { 149 | isa = PBXSourcesBuildPhase; 150 | buildActionMask = 2147483647; 151 | files = ( 152 | D7DEBCF91D49F45A006AF714 /* ViewController.m in Sources */, 153 | D7DEBCF61D49F45A006AF714 /* AppDelegate.m in Sources */, 154 | D7DEBCF31D49F45A006AF714 /* main.m in Sources */, 155 | ); 156 | runOnlyForDeploymentPostprocessing = 0; 157 | }; 158 | /* End PBXSourcesBuildPhase section */ 159 | 160 | /* Begin PBXVariantGroup section */ 161 | D7DEBCFA1D49F45A006AF714 /* Main.storyboard */ = { 162 | isa = PBXVariantGroup; 163 | children = ( 164 | D7DEBCFB1D49F45A006AF714 /* Base */, 165 | ); 166 | name = Main.storyboard; 167 | sourceTree = ""; 168 | }; 169 | D7DEBCFF1D49F45A006AF714 /* LaunchScreen.storyboard */ = { 170 | isa = PBXVariantGroup; 171 | children = ( 172 | D7DEBD001D49F45A006AF714 /* Base */, 173 | ); 174 | name = LaunchScreen.storyboard; 175 | sourceTree = ""; 176 | }; 177 | /* End PBXVariantGroup section */ 178 | 179 | /* Begin XCBuildConfiguration section */ 180 | D7DEBD031D49F45A006AF714 /* Debug */ = { 181 | isa = XCBuildConfiguration; 182 | buildSettings = { 183 | ALWAYS_SEARCH_USER_PATHS = NO; 184 | CLANG_ANALYZER_NONNULL = YES; 185 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 186 | CLANG_CXX_LIBRARY = "libc++"; 187 | CLANG_ENABLE_MODULES = YES; 188 | CLANG_ENABLE_OBJC_ARC = YES; 189 | CLANG_WARN_BOOL_CONVERSION = YES; 190 | CLANG_WARN_CONSTANT_CONVERSION = YES; 191 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 192 | CLANG_WARN_EMPTY_BODY = YES; 193 | CLANG_WARN_ENUM_CONVERSION = YES; 194 | CLANG_WARN_INT_CONVERSION = YES; 195 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 196 | CLANG_WARN_UNREACHABLE_CODE = YES; 197 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 198 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 199 | COPY_PHASE_STRIP = NO; 200 | DEBUG_INFORMATION_FORMAT = dwarf; 201 | ENABLE_STRICT_OBJC_MSGSEND = YES; 202 | ENABLE_TESTABILITY = YES; 203 | GCC_C_LANGUAGE_STANDARD = gnu99; 204 | GCC_DYNAMIC_NO_PIC = NO; 205 | GCC_NO_COMMON_BLOCKS = YES; 206 | GCC_OPTIMIZATION_LEVEL = 0; 207 | GCC_PREPROCESSOR_DEFINITIONS = ( 208 | "DEBUG=1", 209 | "$(inherited)", 210 | ); 211 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 212 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 213 | GCC_WARN_UNDECLARED_SELECTOR = YES; 214 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 215 | GCC_WARN_UNUSED_FUNCTION = YES; 216 | GCC_WARN_UNUSED_VARIABLE = YES; 217 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 218 | MTL_ENABLE_DEBUG_INFO = YES; 219 | ONLY_ACTIVE_ARCH = YES; 220 | SDKROOT = iphoneos; 221 | TARGETED_DEVICE_FAMILY = "1,2"; 222 | }; 223 | name = Debug; 224 | }; 225 | D7DEBD041D49F45A006AF714 /* Release */ = { 226 | isa = XCBuildConfiguration; 227 | buildSettings = { 228 | ALWAYS_SEARCH_USER_PATHS = NO; 229 | CLANG_ANALYZER_NONNULL = YES; 230 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 231 | CLANG_CXX_LIBRARY = "libc++"; 232 | CLANG_ENABLE_MODULES = YES; 233 | CLANG_ENABLE_OBJC_ARC = YES; 234 | CLANG_WARN_BOOL_CONVERSION = YES; 235 | CLANG_WARN_CONSTANT_CONVERSION = YES; 236 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 237 | CLANG_WARN_EMPTY_BODY = YES; 238 | CLANG_WARN_ENUM_CONVERSION = YES; 239 | CLANG_WARN_INT_CONVERSION = YES; 240 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 241 | CLANG_WARN_UNREACHABLE_CODE = YES; 242 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 243 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 244 | COPY_PHASE_STRIP = NO; 245 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 246 | ENABLE_NS_ASSERTIONS = NO; 247 | ENABLE_STRICT_OBJC_MSGSEND = YES; 248 | GCC_C_LANGUAGE_STANDARD = gnu99; 249 | GCC_NO_COMMON_BLOCKS = YES; 250 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 251 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 252 | GCC_WARN_UNDECLARED_SELECTOR = YES; 253 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 254 | GCC_WARN_UNUSED_FUNCTION = YES; 255 | GCC_WARN_UNUSED_VARIABLE = YES; 256 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 257 | MTL_ENABLE_DEBUG_INFO = NO; 258 | SDKROOT = iphoneos; 259 | TARGETED_DEVICE_FAMILY = "1,2"; 260 | VALIDATE_PRODUCT = YES; 261 | }; 262 | name = Release; 263 | }; 264 | D7DEBD061D49F45A006AF714 /* Debug */ = { 265 | isa = XCBuildConfiguration; 266 | buildSettings = { 267 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 268 | INFOPLIST_FILE = VTEncodeDemo/Info.plist; 269 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 270 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 271 | PRODUCT_BUNDLE_IDENTIFIER = cn.shawn.VTEncodeDemo; 272 | PRODUCT_NAME = "$(TARGET_NAME)"; 273 | }; 274 | name = Debug; 275 | }; 276 | D7DEBD071D49F45A006AF714 /* Release */ = { 277 | isa = XCBuildConfiguration; 278 | buildSettings = { 279 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 280 | INFOPLIST_FILE = VTEncodeDemo/Info.plist; 281 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 282 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 283 | PRODUCT_BUNDLE_IDENTIFIER = cn.shawn.VTEncodeDemo; 284 | PRODUCT_NAME = "$(TARGET_NAME)"; 285 | }; 286 | name = Release; 287 | }; 288 | /* End XCBuildConfiguration section */ 289 | 290 | /* Begin XCConfigurationList section */ 291 | D7DEBCE91D49F45A006AF714 /* Build configuration list for PBXProject "VTEncodeDemo" */ = { 292 | isa = XCConfigurationList; 293 | buildConfigurations = ( 294 | D7DEBD031D49F45A006AF714 /* Debug */, 295 | D7DEBD041D49F45A006AF714 /* Release */, 296 | ); 297 | defaultConfigurationIsVisible = 0; 298 | defaultConfigurationName = Release; 299 | }; 300 | D7DEBD051D49F45A006AF714 /* Build configuration list for PBXNativeTarget "VTEncodeDemo" */ = { 301 | isa = XCConfigurationList; 302 | buildConfigurations = ( 303 | D7DEBD061D49F45A006AF714 /* Debug */, 304 | D7DEBD071D49F45A006AF714 /* Release */, 305 | ); 306 | defaultConfigurationIsVisible = 0; 307 | }; 308 | /* End XCConfigurationList section */ 309 | }; 310 | rootObject = D7DEBCE61D49F45A006AF714 /* Project object */; 311 | } 312 | -------------------------------------------------------------------------------- /VTEncodeDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /VTEncodeDemo.xcodeproj/project.xcworkspace/xcuserdata/dev.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shawn7com/VTEncodeDemo/fe387fb1fdf9f39b3606b5753f50c57cb2da18c6/VTEncodeDemo.xcodeproj/project.xcworkspace/xcuserdata/dev.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /VTEncodeDemo.xcodeproj/xcuserdata/dev.xcuserdatad/xcschemes/VTEncodeDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /VTEncodeDemo.xcodeproj/xcuserdata/dev.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | VTEncodeDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | D7DEBCED1D49F45A006AF714 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /VTEncodeDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // VTEncodeDemo 4 | // 5 | // Created by DevKS on 7/28/16. 6 | // Copyright © 2016 Shawn. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /VTEncodeDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // VTEncodeDemo 4 | // 5 | // Created by DevKS on 7/28/16. 6 | // Copyright © 2016 Shawn. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /VTEncodeDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /VTEncodeDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /VTEncodeDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 28 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /VTEncodeDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UIFileSharingEnabled 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /VTEncodeDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // VTEncodeDemo 4 | // 5 | // Created by DevKS on 7/28/16. 6 | // Copyright © 2016 Shawn. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /VTEncodeDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // VTEncodeDemo 4 | // 5 | // Created by DevKS on 7/28/16. 6 | // Copyright © 2016 Shawn. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | #import 12 | 13 | #import 14 | 15 | // 需实现 AVCaptureVideoDataOutputSampleBufferDelegate 用于获取摄像头数据 16 | @interface ViewController () 17 | { 18 | VTCompressionSessionRef _encodeSesion; 19 | dispatch_queue_t _encodeQueue; 20 | long _frameCount; 21 | FILE *_h264File; 22 | int _spsppsFound; 23 | } 24 | 25 | @property (nonatomic, strong)NSString *documentDictionary; 26 | 27 | @property (nonatomic, strong)AVCaptureSession *videoCaptureSession; 28 | //@property (nonatomic, strong)AVCaptureDeviceInput *videoDeviceInput; 29 | //@property (nonatomic, strong)AVCaptureVideoDataOutput *videoDataOutput; 30 | @end 31 | 32 | @implementation ViewController 33 | 34 | - (void)viewDidLoad { 35 | [super viewDidLoad]; 36 | 37 | _encodeQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 38 | [self initVideoCaptrue]; 39 | 40 | self.documentDictionary = [(NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES)) objectAtIndex:0]; 41 | } 42 | 43 | 44 | - (IBAction)startButton:(UIButton *)sender 45 | { 46 | // 文件保存在document文件夹下,可以直接通过iTunes将文件导出到电脑,在plist文件中添加Application supports iTunes file sharing = YES 47 | _h264File = fopen([[NSString stringWithFormat:@"%@/vt_encode.h264", self.documentDictionary] UTF8String], "wb"); 48 | 49 | [self startEncodeSession:480 height:640 framerate:25 bitrate:640*1000]; 50 | [self.videoCaptureSession startRunning];// 开始录像 51 | } 52 | 53 | 54 | - (IBAction)stopButton:(UIButton *)sender 55 | { 56 | [self.videoCaptureSession stopRunning]; 57 | 58 | [self stopEncodeSession]; 59 | 60 | fclose(_h264File); 61 | } 62 | 63 | #pragma mark - camera 64 | #pragma mark - video capture output delegate 65 | - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection 66 | { 67 | [self encodeFrame:sampleBuffer]; 68 | } 69 | 70 | - (void)initVideoCaptrue 71 | { 72 | self.videoCaptureSession = [[AVCaptureSession alloc] init]; 73 | 74 | // 设置录像分辨率 75 | [self.videoCaptureSession setSessionPreset:AVCaptureSessionPreset640x480]; 76 | 77 | AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 78 | if (!device) { 79 | NSLog(@"No Video device found"); 80 | return; 81 | } 82 | 83 | AVCaptureDeviceInput *inputDevice = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil]; 84 | 85 | if ([self.videoCaptureSession canAddInput:inputDevice]) { 86 | NSLog(@"add video input to video session: %@", inputDevice); 87 | [self.videoCaptureSession addInput:inputDevice]; 88 | } 89 | 90 | AVCaptureVideoDataOutput *dataOutput = [[AVCaptureVideoDataOutput alloc] init]; 91 | 92 | /* ONLY support pixel format : 420v, 420f, BGRA */ 93 | dataOutput.videoSettings = [NSDictionary dictionaryWithObject: 94 | [NSNumber numberWithUnsignedInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange]forKey:(NSString *)kCVPixelBufferPixelFormatTypeKey]; 95 | [dataOutput setAlwaysDiscardsLateVideoFrames:YES]; 96 | 97 | if ([self.videoCaptureSession canAddOutput:dataOutput]) { 98 | NSLog(@"add video output to video session: %@", dataOutput); 99 | [self.videoCaptureSession addOutput:dataOutput]; 100 | } 101 | 102 | // 设置采集图像的方向,如果不设置,采集回来的图形会是旋转90度的 103 | AVCaptureConnection *connection = [dataOutput connectionWithMediaType:AVMediaTypeVideo]; 104 | connection.videoOrientation = AVCaptureVideoOrientationPortrait; 105 | 106 | [self.videoCaptureSession commitConfiguration]; 107 | 108 | // 添加预览 109 | CGRect frame = self.view.frame; 110 | frame.size.height -= 50; 111 | AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.videoCaptureSession]; 112 | [previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill]; 113 | [previewLayer setFrame:frame]; 114 | [self.view.layer addSublayer:previewLayer]; 115 | 116 | // 摄像头采集queue 117 | dispatch_queue_t queue = dispatch_queue_create("VideoCaptureQueue", DISPATCH_QUEUE_SERIAL); 118 | [dataOutput setSampleBufferDelegate:self queue:queue]; // 摄像头数据输出delegate 119 | } 120 | 121 | 122 | #pragma mark - videotoolbox methods 123 | - (int)startEncodeSession:(int)width height:(int)height framerate:(int)fps bitrate:(int)bt 124 | { 125 | OSStatus status; 126 | _frameCount = 0; 127 | 128 | VTCompressionOutputCallback cb = encodeOutputCallback; 129 | status = VTCompressionSessionCreate(kCFAllocatorDefault, width, height, kCMVideoCodecType_H264, NULL, NULL, NULL, cb, (__bridge void *)(self), &_encodeSesion); 130 | 131 | if (status != noErr) { 132 | NSLog(@"VTCompressionSessionCreate failed. ret=%d", (int)status); 133 | return -1; 134 | } 135 | 136 | // 设置实时编码输出,降低编码延迟 137 | status = VTSessionSetProperty(_encodeSesion, kVTCompressionPropertyKey_RealTime, kCFBooleanTrue); 138 | NSLog(@"set realtime return: %d", (int)status); 139 | 140 | // h264 profile, 直播一般使用baseline,可减少由于b帧带来的延时 141 | status = VTSessionSetProperty(_encodeSesion, kVTCompressionPropertyKey_ProfileLevel, kVTProfileLevel_H264_Baseline_AutoLevel); 142 | NSLog(@"set profile return: %d", (int)status); 143 | 144 | // 设置编码码率(比特率),如果不设置,默认将会以很低的码率编码,导致编码出来的视频很模糊 145 | status = VTSessionSetProperty(_encodeSesion, kVTCompressionPropertyKey_AverageBitRate, (__bridge CFTypeRef)@(bt)); // bps 146 | status += VTSessionSetProperty(_encodeSesion, kVTCompressionPropertyKey_DataRateLimits, (__bridge CFArrayRef)@[@(bt*2/8), @1]); // Bps 147 | NSLog(@"set bitrate return: %d", (int)status); 148 | 149 | // 设置关键帧间隔,即gop size 150 | status = VTSessionSetProperty(_encodeSesion, kVTCompressionPropertyKey_MaxKeyFrameInterval, (__bridge CFTypeRef)@(fps*2)); 151 | 152 | // 设置帧率,只用于初始化session,不是实际FPS 153 | status = VTSessionSetProperty(_encodeSesion, kVTCompressionPropertyKey_ExpectedFrameRate, (__bridge CFTypeRef)@(fps)); 154 | NSLog(@"set framerate return: %d", (int)status); 155 | 156 | // 开始编码 157 | status = VTCompressionSessionPrepareToEncodeFrames(_encodeSesion); 158 | NSLog(@"start encode return: %d", (int)status); 159 | 160 | return 0; 161 | } 162 | 163 | 164 | // 编码一帧图像,使用queue,防止阻塞系统摄像头采集线程 165 | - (void) encodeFrame:(CMSampleBufferRef )sampleBuffer 166 | { 167 | dispatch_sync(_encodeQueue, ^{ 168 | CVImageBufferRef imageBuffer = (CVImageBufferRef)CMSampleBufferGetImageBuffer(sampleBuffer); 169 | 170 | // pts,必须设置,否则会导致编码出来的数据非常大,原因未知 171 | CMTime pts = CMTimeMake(_frameCount, 1000); 172 | CMTime duration = kCMTimeInvalid; 173 | 174 | VTEncodeInfoFlags flags; 175 | 176 | // 送入编码器编码 177 | OSStatus statusCode = VTCompressionSessionEncodeFrame(_encodeSesion, 178 | imageBuffer, 179 | pts, duration, 180 | NULL, NULL, &flags); 181 | 182 | if (statusCode != noErr) { 183 | NSLog(@"H264: VTCompressionSessionEncodeFrame failed with %d", (int)statusCode); 184 | 185 | [self stopEncodeSession]; 186 | return; 187 | } 188 | }); 189 | } 190 | 191 | - (void) stopEncodeSession 192 | { 193 | VTCompressionSessionCompleteFrames(_encodeSesion, kCMTimeInvalid); 194 | 195 | VTCompressionSessionInvalidate(_encodeSesion); 196 | 197 | CFRelease(_encodeSesion); 198 | _encodeSesion = NULL; 199 | } 200 | 201 | // 编码回调,每当系统编码完一帧之后,会异步掉用该方法,此为c语言方法 202 | void encodeOutputCallback(void *userData, void *sourceFrameRefCon, OSStatus status, VTEncodeInfoFlags infoFlags, 203 | CMSampleBufferRef sampleBuffer ) 204 | { 205 | if (status != noErr) { 206 | NSLog(@"didCompressH264 error: with status %d, infoFlags %d", (int)status, (int)infoFlags); 207 | return; 208 | } 209 | if (!CMSampleBufferDataIsReady(sampleBuffer)) 210 | { 211 | NSLog(@"didCompressH264 data is not ready "); 212 | return; 213 | } 214 | ViewController* vc = (__bridge ViewController*)userData; 215 | 216 | // 判断当前帧是否为关键帧 217 | bool keyframe = !CFDictionaryContainsKey( (CFArrayGetValueAtIndex(CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, true), 0)), kCMSampleAttachmentKey_NotSync); 218 | 219 | // 获取sps & pps数据. sps pps只需获取一次,保存在h264文件开头即可 220 | if (keyframe && !vc->_spsppsFound) 221 | { 222 | size_t spsSize, spsCount; 223 | size_t ppsSize, ppsCount; 224 | 225 | const uint8_t *spsData, *ppsData; 226 | 227 | CMFormatDescriptionRef formatDesc = CMSampleBufferGetFormatDescription(sampleBuffer); 228 | OSStatus err0 = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(formatDesc, 0, &spsData, &spsSize, &spsCount, 0 ); 229 | OSStatus err1 = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(formatDesc, 1, &ppsData, &ppsSize, &ppsCount, 0 ); 230 | 231 | if (err0==noErr && err1==noErr) 232 | { 233 | vc->_spsppsFound = 1; 234 | [vc writeH264Data:(void *)spsData length:spsSize addStartCode:YES]; 235 | [vc writeH264Data:(void *)ppsData length:ppsSize addStartCode:YES]; 236 | 237 | NSLog(@"got sps/pps data. Length: sps=%zu, pps=%zu", spsSize, ppsSize); 238 | } 239 | } 240 | 241 | size_t lengthAtOffset, totalLength; 242 | char *data; 243 | 244 | CMBlockBufferRef dataBuffer = CMSampleBufferGetDataBuffer(sampleBuffer); 245 | OSStatus error = CMBlockBufferGetDataPointer(dataBuffer, 0, &lengthAtOffset, &totalLength, &data); 246 | 247 | if (error == noErr) { 248 | size_t offset = 0; 249 | const int lengthInfoSize = 4; // 返回的nalu数据前四个字节不是0001的startcode,而是大端模式的帧长度length 250 | 251 | // 循环获取nalu数据 252 | while (offset < totalLength - lengthInfoSize) { 253 | uint32_t naluLength = 0; 254 | memcpy(&naluLength, data + offset, lengthInfoSize); // 获取nalu的长度, 255 | 256 | // 大端模式转化为系统端模式 257 | naluLength = CFSwapInt32BigToHost(naluLength); 258 | NSLog(@"got nalu data, length=%d, totalLength=%zu", naluLength, totalLength); 259 | 260 | // 保存nalu数据到文件 261 | [vc writeH264Data:data+offset+lengthInfoSize length:naluLength addStartCode:YES]; 262 | 263 | // 读取下一个nalu,一次回调可能包含多个nalu 264 | offset += lengthInfoSize + naluLength; 265 | } 266 | } 267 | } 268 | 269 | // 保存h264数据到文件 270 | - (void) writeH264Data:(void*)data length:(size_t)length addStartCode:(BOOL)b 271 | { 272 | // 添加4字节的 h264 协议 start code 273 | const Byte bytes[] = "\x00\x00\x00\x01"; 274 | 275 | if (_h264File) { 276 | if(b) 277 | fwrite(bytes, 1, 4, _h264File); 278 | 279 | fwrite(data, 1, length, _h264File); 280 | } else { 281 | NSLog(@"_h264File null error, check if it open successed"); 282 | } 283 | } 284 | 285 | 286 | 287 | - (void)didReceiveMemoryWarning { 288 | [super didReceiveMemoryWarning]; 289 | // Dispose of any resources that can be recreated. 290 | } 291 | 292 | @end 293 | -------------------------------------------------------------------------------- /VTEncodeDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // VTEncodeDemo 4 | // 5 | // Created by DevKS on 7/28/16. 6 | // Copyright © 2016 Shawn. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | --------------------------------------------------------------------------------