├── AVColletion ├── AVColletion.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── tgw.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── tgw.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── AVColletion.xcscheme │ │ └── xcschememanagement.plist ├── AVColletion │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── EncodeH264.h │ ├── EncodeH264.m │ ├── EncoderAAC.h │ ├── EncoderAAC.m │ ├── Info.plist │ ├── ViewController.h │ ├── ViewController.m │ └── main.m ├── AVColletionTests │ ├── AVColletionTests.m │ └── Info.plist ├── AVColletionUITests │ ├── AVColletionUITests.m │ └── Info.plist ├── MyCaptureSession.h └── MyCaptureSession.m └── README.md /AVColletion/AVColletion.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8B1189FE1E66EFC8002940C3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B1189FD1E66EFC8002940C3 /* main.m */; }; 11 | 8B118A011E66EFC9002940C3 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B118A001E66EFC9002940C3 /* AppDelegate.m */; }; 12 | 8B118A041E66EFC9002940C3 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B118A031E66EFC9002940C3 /* ViewController.m */; }; 13 | 8B118A071E66EFC9002940C3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8B118A051E66EFC9002940C3 /* Main.storyboard */; }; 14 | 8B118A091E66EFC9002940C3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8B118A081E66EFC9002940C3 /* Assets.xcassets */; }; 15 | 8B118A0C1E66EFC9002940C3 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8B118A0A1E66EFC9002940C3 /* LaunchScreen.storyboard */; }; 16 | 8B118A171E66EFC9002940C3 /* AVColletionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B118A161E66EFC9002940C3 /* AVColletionTests.m */; }; 17 | 8B118A221E66EFC9002940C3 /* AVColletionUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B118A211E66EFC9002940C3 /* AVColletionUITests.m */; }; 18 | 8B118A371E66F07D002940C3 /* MyCaptureSession.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B118A361E66F07D002940C3 /* MyCaptureSession.m */; }; 19 | 8B407F861E6B18D5002DACB4 /* EncoderAAC.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B407F851E6B18D5002DACB4 /* EncoderAAC.m */; }; 20 | 8B407F891E6B1963002DACB4 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B407F881E6B1963002DACB4 /* AudioToolbox.framework */; }; 21 | 8B407F8B1E6B196B002DACB4 /* VideoToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B407F8A1E6B196B002DACB4 /* VideoToolbox.framework */; }; 22 | 8B407F8E1E6BCA3A002DACB4 /* EncodeH264.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B407F8D1E6BCA3A002DACB4 /* EncodeH264.m */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXContainerItemProxy section */ 26 | 8B118A131E66EFC9002940C3 /* PBXContainerItemProxy */ = { 27 | isa = PBXContainerItemProxy; 28 | containerPortal = 8B1189F11E66EFC8002940C3 /* Project object */; 29 | proxyType = 1; 30 | remoteGlobalIDString = 8B1189F81E66EFC8002940C3; 31 | remoteInfo = AVColletion; 32 | }; 33 | 8B118A1E1E66EFC9002940C3 /* PBXContainerItemProxy */ = { 34 | isa = PBXContainerItemProxy; 35 | containerPortal = 8B1189F11E66EFC8002940C3 /* Project object */; 36 | proxyType = 1; 37 | remoteGlobalIDString = 8B1189F81E66EFC8002940C3; 38 | remoteInfo = AVColletion; 39 | }; 40 | /* End PBXContainerItemProxy section */ 41 | 42 | /* Begin PBXFileReference section */ 43 | 8B1189F91E66EFC8002940C3 /* AVColletion.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AVColletion.app; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | 8B1189FD1E66EFC8002940C3 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 45 | 8B1189FF1E66EFC9002940C3 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 46 | 8B118A001E66EFC9002940C3 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 47 | 8B118A021E66EFC9002940C3 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 48 | 8B118A031E66EFC9002940C3 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 49 | 8B118A061E66EFC9002940C3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 50 | 8B118A081E66EFC9002940C3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 51 | 8B118A0B1E66EFC9002940C3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 52 | 8B118A0D1E66EFC9002940C3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 53 | 8B118A121E66EFC9002940C3 /* AVColletionTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AVColletionTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | 8B118A161E66EFC9002940C3 /* AVColletionTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AVColletionTests.m; sourceTree = ""; }; 55 | 8B118A181E66EFC9002940C3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | 8B118A1D1E66EFC9002940C3 /* AVColletionUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AVColletionUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | 8B118A211E66EFC9002940C3 /* AVColletionUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AVColletionUITests.m; sourceTree = ""; }; 58 | 8B118A231E66EFC9002940C3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 59 | 8B118A351E66F07D002940C3 /* MyCaptureSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MyCaptureSession.h; path = ../MyCaptureSession.h; sourceTree = ""; }; 60 | 8B118A361E66F07D002940C3 /* MyCaptureSession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MyCaptureSession.m; path = ../MyCaptureSession.m; sourceTree = ""; }; 61 | 8B407F841E6B18D5002DACB4 /* EncoderAAC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EncoderAAC.h; sourceTree = ""; }; 62 | 8B407F851E6B18D5002DACB4 /* EncoderAAC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EncoderAAC.m; sourceTree = ""; }; 63 | 8B407F881E6B1963002DACB4 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; 64 | 8B407F8A1E6B196B002DACB4 /* VideoToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = VideoToolbox.framework; path = System/Library/Frameworks/VideoToolbox.framework; sourceTree = SDKROOT; }; 65 | 8B407F8C1E6BCA3A002DACB4 /* EncodeH264.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EncodeH264.h; sourceTree = ""; }; 66 | 8B407F8D1E6BCA3A002DACB4 /* EncodeH264.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EncodeH264.m; sourceTree = ""; }; 67 | /* End PBXFileReference section */ 68 | 69 | /* Begin PBXFrameworksBuildPhase section */ 70 | 8B1189F61E66EFC8002940C3 /* Frameworks */ = { 71 | isa = PBXFrameworksBuildPhase; 72 | buildActionMask = 2147483647; 73 | files = ( 74 | 8B407F8B1E6B196B002DACB4 /* VideoToolbox.framework in Frameworks */, 75 | 8B407F891E6B1963002DACB4 /* AudioToolbox.framework in Frameworks */, 76 | ); 77 | runOnlyForDeploymentPostprocessing = 0; 78 | }; 79 | 8B118A0F1E66EFC9002940C3 /* Frameworks */ = { 80 | isa = PBXFrameworksBuildPhase; 81 | buildActionMask = 2147483647; 82 | files = ( 83 | ); 84 | runOnlyForDeploymentPostprocessing = 0; 85 | }; 86 | 8B118A1A1E66EFC9002940C3 /* Frameworks */ = { 87 | isa = PBXFrameworksBuildPhase; 88 | buildActionMask = 2147483647; 89 | files = ( 90 | ); 91 | runOnlyForDeploymentPostprocessing = 0; 92 | }; 93 | /* End PBXFrameworksBuildPhase section */ 94 | 95 | /* Begin PBXGroup section */ 96 | 8B1189F01E66EFC8002940C3 = { 97 | isa = PBXGroup; 98 | children = ( 99 | 8B1189FB1E66EFC8002940C3 /* AVColletion */, 100 | 8B118A151E66EFC9002940C3 /* AVColletionTests */, 101 | 8B118A201E66EFC9002940C3 /* AVColletionUITests */, 102 | 8B1189FA1E66EFC8002940C3 /* Products */, 103 | 8B407F871E6B1963002DACB4 /* Frameworks */, 104 | ); 105 | sourceTree = ""; 106 | }; 107 | 8B1189FA1E66EFC8002940C3 /* Products */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 8B1189F91E66EFC8002940C3 /* AVColletion.app */, 111 | 8B118A121E66EFC9002940C3 /* AVColletionTests.xctest */, 112 | 8B118A1D1E66EFC9002940C3 /* AVColletionUITests.xctest */, 113 | ); 114 | name = Products; 115 | sourceTree = ""; 116 | }; 117 | 8B1189FB1E66EFC8002940C3 /* AVColletion */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 8B407F901E6C071C002DACB4 /* encode */, 121 | 8B407F8F1E6C06F4002DACB4 /* captureSession */, 122 | 8B1189FF1E66EFC9002940C3 /* AppDelegate.h */, 123 | 8B118A001E66EFC9002940C3 /* AppDelegate.m */, 124 | 8B118A021E66EFC9002940C3 /* ViewController.h */, 125 | 8B118A031E66EFC9002940C3 /* ViewController.m */, 126 | 8B118A051E66EFC9002940C3 /* Main.storyboard */, 127 | 8B118A081E66EFC9002940C3 /* Assets.xcassets */, 128 | 8B118A0A1E66EFC9002940C3 /* LaunchScreen.storyboard */, 129 | 8B118A0D1E66EFC9002940C3 /* Info.plist */, 130 | 8B1189FC1E66EFC8002940C3 /* Supporting Files */, 131 | ); 132 | path = AVColletion; 133 | sourceTree = ""; 134 | }; 135 | 8B1189FC1E66EFC8002940C3 /* Supporting Files */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | 8B1189FD1E66EFC8002940C3 /* main.m */, 139 | ); 140 | name = "Supporting Files"; 141 | sourceTree = ""; 142 | }; 143 | 8B118A151E66EFC9002940C3 /* AVColletionTests */ = { 144 | isa = PBXGroup; 145 | children = ( 146 | 8B118A161E66EFC9002940C3 /* AVColletionTests.m */, 147 | 8B118A181E66EFC9002940C3 /* Info.plist */, 148 | ); 149 | path = AVColletionTests; 150 | sourceTree = ""; 151 | }; 152 | 8B118A201E66EFC9002940C3 /* AVColletionUITests */ = { 153 | isa = PBXGroup; 154 | children = ( 155 | 8B118A211E66EFC9002940C3 /* AVColletionUITests.m */, 156 | 8B118A231E66EFC9002940C3 /* Info.plist */, 157 | ); 158 | path = AVColletionUITests; 159 | sourceTree = ""; 160 | }; 161 | 8B407F871E6B1963002DACB4 /* Frameworks */ = { 162 | isa = PBXGroup; 163 | children = ( 164 | 8B407F8A1E6B196B002DACB4 /* VideoToolbox.framework */, 165 | 8B407F881E6B1963002DACB4 /* AudioToolbox.framework */, 166 | ); 167 | name = Frameworks; 168 | sourceTree = ""; 169 | }; 170 | 8B407F8F1E6C06F4002DACB4 /* captureSession */ = { 171 | isa = PBXGroup; 172 | children = ( 173 | 8B118A351E66F07D002940C3 /* MyCaptureSession.h */, 174 | 8B118A361E66F07D002940C3 /* MyCaptureSession.m */, 175 | ); 176 | name = captureSession; 177 | sourceTree = ""; 178 | }; 179 | 8B407F901E6C071C002DACB4 /* encode */ = { 180 | isa = PBXGroup; 181 | children = ( 182 | 8B407F8C1E6BCA3A002DACB4 /* EncodeH264.h */, 183 | 8B407F8D1E6BCA3A002DACB4 /* EncodeH264.m */, 184 | 8B407F841E6B18D5002DACB4 /* EncoderAAC.h */, 185 | 8B407F851E6B18D5002DACB4 /* EncoderAAC.m */, 186 | ); 187 | name = encode; 188 | sourceTree = ""; 189 | }; 190 | /* End PBXGroup section */ 191 | 192 | /* Begin PBXNativeTarget section */ 193 | 8B1189F81E66EFC8002940C3 /* AVColletion */ = { 194 | isa = PBXNativeTarget; 195 | buildConfigurationList = 8B118A261E66EFC9002940C3 /* Build configuration list for PBXNativeTarget "AVColletion" */; 196 | buildPhases = ( 197 | 8B1189F51E66EFC8002940C3 /* Sources */, 198 | 8B1189F61E66EFC8002940C3 /* Frameworks */, 199 | 8B1189F71E66EFC8002940C3 /* Resources */, 200 | ); 201 | buildRules = ( 202 | ); 203 | dependencies = ( 204 | ); 205 | name = AVColletion; 206 | productName = AVColletion; 207 | productReference = 8B1189F91E66EFC8002940C3 /* AVColletion.app */; 208 | productType = "com.apple.product-type.application"; 209 | }; 210 | 8B118A111E66EFC9002940C3 /* AVColletionTests */ = { 211 | isa = PBXNativeTarget; 212 | buildConfigurationList = 8B118A291E66EFC9002940C3 /* Build configuration list for PBXNativeTarget "AVColletionTests" */; 213 | buildPhases = ( 214 | 8B118A0E1E66EFC9002940C3 /* Sources */, 215 | 8B118A0F1E66EFC9002940C3 /* Frameworks */, 216 | 8B118A101E66EFC9002940C3 /* Resources */, 217 | ); 218 | buildRules = ( 219 | ); 220 | dependencies = ( 221 | 8B118A141E66EFC9002940C3 /* PBXTargetDependency */, 222 | ); 223 | name = AVColletionTests; 224 | productName = AVColletionTests; 225 | productReference = 8B118A121E66EFC9002940C3 /* AVColletionTests.xctest */; 226 | productType = "com.apple.product-type.bundle.unit-test"; 227 | }; 228 | 8B118A1C1E66EFC9002940C3 /* AVColletionUITests */ = { 229 | isa = PBXNativeTarget; 230 | buildConfigurationList = 8B118A2C1E66EFC9002940C3 /* Build configuration list for PBXNativeTarget "AVColletionUITests" */; 231 | buildPhases = ( 232 | 8B118A191E66EFC9002940C3 /* Sources */, 233 | 8B118A1A1E66EFC9002940C3 /* Frameworks */, 234 | 8B118A1B1E66EFC9002940C3 /* Resources */, 235 | ); 236 | buildRules = ( 237 | ); 238 | dependencies = ( 239 | 8B118A1F1E66EFC9002940C3 /* PBXTargetDependency */, 240 | ); 241 | name = AVColletionUITests; 242 | productName = AVColletionUITests; 243 | productReference = 8B118A1D1E66EFC9002940C3 /* AVColletionUITests.xctest */; 244 | productType = "com.apple.product-type.bundle.ui-testing"; 245 | }; 246 | /* End PBXNativeTarget section */ 247 | 248 | /* Begin PBXProject section */ 249 | 8B1189F11E66EFC8002940C3 /* Project object */ = { 250 | isa = PBXProject; 251 | attributes = { 252 | LastUpgradeCheck = 0820; 253 | ORGANIZATIONNAME = oppsr; 254 | TargetAttributes = { 255 | 8B1189F81E66EFC8002940C3 = { 256 | CreatedOnToolsVersion = 8.2.1; 257 | DevelopmentTeam = E7P9CREU6H; 258 | ProvisioningStyle = Automatic; 259 | }; 260 | 8B118A111E66EFC9002940C3 = { 261 | CreatedOnToolsVersion = 8.2.1; 262 | DevelopmentTeam = E7P9CREU6H; 263 | ProvisioningStyle = Automatic; 264 | TestTargetID = 8B1189F81E66EFC8002940C3; 265 | }; 266 | 8B118A1C1E66EFC9002940C3 = { 267 | CreatedOnToolsVersion = 8.2.1; 268 | DevelopmentTeam = E7P9CREU6H; 269 | ProvisioningStyle = Automatic; 270 | TestTargetID = 8B1189F81E66EFC8002940C3; 271 | }; 272 | }; 273 | }; 274 | buildConfigurationList = 8B1189F41E66EFC8002940C3 /* Build configuration list for PBXProject "AVColletion" */; 275 | compatibilityVersion = "Xcode 3.2"; 276 | developmentRegion = English; 277 | hasScannedForEncodings = 0; 278 | knownRegions = ( 279 | en, 280 | Base, 281 | ); 282 | mainGroup = 8B1189F01E66EFC8002940C3; 283 | productRefGroup = 8B1189FA1E66EFC8002940C3 /* Products */; 284 | projectDirPath = ""; 285 | projectRoot = ""; 286 | targets = ( 287 | 8B1189F81E66EFC8002940C3 /* AVColletion */, 288 | 8B118A111E66EFC9002940C3 /* AVColletionTests */, 289 | 8B118A1C1E66EFC9002940C3 /* AVColletionUITests */, 290 | ); 291 | }; 292 | /* End PBXProject section */ 293 | 294 | /* Begin PBXResourcesBuildPhase section */ 295 | 8B1189F71E66EFC8002940C3 /* Resources */ = { 296 | isa = PBXResourcesBuildPhase; 297 | buildActionMask = 2147483647; 298 | files = ( 299 | 8B118A0C1E66EFC9002940C3 /* LaunchScreen.storyboard in Resources */, 300 | 8B118A091E66EFC9002940C3 /* Assets.xcassets in Resources */, 301 | 8B118A071E66EFC9002940C3 /* Main.storyboard in Resources */, 302 | ); 303 | runOnlyForDeploymentPostprocessing = 0; 304 | }; 305 | 8B118A101E66EFC9002940C3 /* Resources */ = { 306 | isa = PBXResourcesBuildPhase; 307 | buildActionMask = 2147483647; 308 | files = ( 309 | ); 310 | runOnlyForDeploymentPostprocessing = 0; 311 | }; 312 | 8B118A1B1E66EFC9002940C3 /* Resources */ = { 313 | isa = PBXResourcesBuildPhase; 314 | buildActionMask = 2147483647; 315 | files = ( 316 | ); 317 | runOnlyForDeploymentPostprocessing = 0; 318 | }; 319 | /* End PBXResourcesBuildPhase section */ 320 | 321 | /* Begin PBXSourcesBuildPhase section */ 322 | 8B1189F51E66EFC8002940C3 /* Sources */ = { 323 | isa = PBXSourcesBuildPhase; 324 | buildActionMask = 2147483647; 325 | files = ( 326 | 8B407F861E6B18D5002DACB4 /* EncoderAAC.m in Sources */, 327 | 8B118A041E66EFC9002940C3 /* ViewController.m in Sources */, 328 | 8B118A011E66EFC9002940C3 /* AppDelegate.m in Sources */, 329 | 8B1189FE1E66EFC8002940C3 /* main.m in Sources */, 330 | 8B118A371E66F07D002940C3 /* MyCaptureSession.m in Sources */, 331 | 8B407F8E1E6BCA3A002DACB4 /* EncodeH264.m in Sources */, 332 | ); 333 | runOnlyForDeploymentPostprocessing = 0; 334 | }; 335 | 8B118A0E1E66EFC9002940C3 /* Sources */ = { 336 | isa = PBXSourcesBuildPhase; 337 | buildActionMask = 2147483647; 338 | files = ( 339 | 8B118A171E66EFC9002940C3 /* AVColletionTests.m in Sources */, 340 | ); 341 | runOnlyForDeploymentPostprocessing = 0; 342 | }; 343 | 8B118A191E66EFC9002940C3 /* Sources */ = { 344 | isa = PBXSourcesBuildPhase; 345 | buildActionMask = 2147483647; 346 | files = ( 347 | 8B118A221E66EFC9002940C3 /* AVColletionUITests.m in Sources */, 348 | ); 349 | runOnlyForDeploymentPostprocessing = 0; 350 | }; 351 | /* End PBXSourcesBuildPhase section */ 352 | 353 | /* Begin PBXTargetDependency section */ 354 | 8B118A141E66EFC9002940C3 /* PBXTargetDependency */ = { 355 | isa = PBXTargetDependency; 356 | target = 8B1189F81E66EFC8002940C3 /* AVColletion */; 357 | targetProxy = 8B118A131E66EFC9002940C3 /* PBXContainerItemProxy */; 358 | }; 359 | 8B118A1F1E66EFC9002940C3 /* PBXTargetDependency */ = { 360 | isa = PBXTargetDependency; 361 | target = 8B1189F81E66EFC8002940C3 /* AVColletion */; 362 | targetProxy = 8B118A1E1E66EFC9002940C3 /* PBXContainerItemProxy */; 363 | }; 364 | /* End PBXTargetDependency section */ 365 | 366 | /* Begin PBXVariantGroup section */ 367 | 8B118A051E66EFC9002940C3 /* Main.storyboard */ = { 368 | isa = PBXVariantGroup; 369 | children = ( 370 | 8B118A061E66EFC9002940C3 /* Base */, 371 | ); 372 | name = Main.storyboard; 373 | sourceTree = ""; 374 | }; 375 | 8B118A0A1E66EFC9002940C3 /* LaunchScreen.storyboard */ = { 376 | isa = PBXVariantGroup; 377 | children = ( 378 | 8B118A0B1E66EFC9002940C3 /* Base */, 379 | ); 380 | name = LaunchScreen.storyboard; 381 | sourceTree = ""; 382 | }; 383 | /* End PBXVariantGroup section */ 384 | 385 | /* Begin XCBuildConfiguration section */ 386 | 8B118A241E66EFC9002940C3 /* Debug */ = { 387 | isa = XCBuildConfiguration; 388 | buildSettings = { 389 | ALWAYS_SEARCH_USER_PATHS = NO; 390 | CLANG_ANALYZER_NONNULL = YES; 391 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 392 | CLANG_CXX_LIBRARY = "libc++"; 393 | CLANG_ENABLE_MODULES = YES; 394 | CLANG_ENABLE_OBJC_ARC = YES; 395 | CLANG_WARN_BOOL_CONVERSION = YES; 396 | CLANG_WARN_CONSTANT_CONVERSION = YES; 397 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 398 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 399 | CLANG_WARN_EMPTY_BODY = YES; 400 | CLANG_WARN_ENUM_CONVERSION = YES; 401 | CLANG_WARN_INFINITE_RECURSION = YES; 402 | CLANG_WARN_INT_CONVERSION = YES; 403 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 404 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 405 | CLANG_WARN_UNREACHABLE_CODE = YES; 406 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 407 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 408 | COPY_PHASE_STRIP = NO; 409 | DEBUG_INFORMATION_FORMAT = dwarf; 410 | ENABLE_STRICT_OBJC_MSGSEND = YES; 411 | ENABLE_TESTABILITY = YES; 412 | GCC_C_LANGUAGE_STANDARD = gnu99; 413 | GCC_DYNAMIC_NO_PIC = NO; 414 | GCC_NO_COMMON_BLOCKS = YES; 415 | GCC_OPTIMIZATION_LEVEL = 0; 416 | GCC_PREPROCESSOR_DEFINITIONS = ( 417 | "DEBUG=1", 418 | "$(inherited)", 419 | ); 420 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 421 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 422 | GCC_WARN_UNDECLARED_SELECTOR = YES; 423 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 424 | GCC_WARN_UNUSED_FUNCTION = YES; 425 | GCC_WARN_UNUSED_VARIABLE = YES; 426 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 427 | MTL_ENABLE_DEBUG_INFO = YES; 428 | ONLY_ACTIVE_ARCH = YES; 429 | SDKROOT = iphoneos; 430 | TARGETED_DEVICE_FAMILY = "1,2"; 431 | }; 432 | name = Debug; 433 | }; 434 | 8B118A251E66EFC9002940C3 /* Release */ = { 435 | isa = XCBuildConfiguration; 436 | buildSettings = { 437 | ALWAYS_SEARCH_USER_PATHS = NO; 438 | CLANG_ANALYZER_NONNULL = YES; 439 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 440 | CLANG_CXX_LIBRARY = "libc++"; 441 | CLANG_ENABLE_MODULES = YES; 442 | CLANG_ENABLE_OBJC_ARC = YES; 443 | CLANG_WARN_BOOL_CONVERSION = YES; 444 | CLANG_WARN_CONSTANT_CONVERSION = YES; 445 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 446 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 447 | CLANG_WARN_EMPTY_BODY = YES; 448 | CLANG_WARN_ENUM_CONVERSION = YES; 449 | CLANG_WARN_INFINITE_RECURSION = YES; 450 | CLANG_WARN_INT_CONVERSION = YES; 451 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 452 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 453 | CLANG_WARN_UNREACHABLE_CODE = YES; 454 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 455 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 456 | COPY_PHASE_STRIP = NO; 457 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 458 | ENABLE_NS_ASSERTIONS = NO; 459 | ENABLE_STRICT_OBJC_MSGSEND = YES; 460 | GCC_C_LANGUAGE_STANDARD = gnu99; 461 | GCC_NO_COMMON_BLOCKS = YES; 462 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 463 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 464 | GCC_WARN_UNDECLARED_SELECTOR = YES; 465 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 466 | GCC_WARN_UNUSED_FUNCTION = YES; 467 | GCC_WARN_UNUSED_VARIABLE = YES; 468 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 469 | MTL_ENABLE_DEBUG_INFO = NO; 470 | SDKROOT = iphoneos; 471 | TARGETED_DEVICE_FAMILY = "1,2"; 472 | VALIDATE_PRODUCT = YES; 473 | }; 474 | name = Release; 475 | }; 476 | 8B118A271E66EFC9002940C3 /* Debug */ = { 477 | isa = XCBuildConfiguration; 478 | buildSettings = { 479 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 480 | DEVELOPMENT_TEAM = E7P9CREU6H; 481 | INFOPLIST_FILE = AVColletion/Info.plist; 482 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 483 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 484 | PRODUCT_BUNDLE_IDENTIFIER = xxx.AVColletion; 485 | PRODUCT_NAME = "$(TARGET_NAME)"; 486 | }; 487 | name = Debug; 488 | }; 489 | 8B118A281E66EFC9002940C3 /* Release */ = { 490 | isa = XCBuildConfiguration; 491 | buildSettings = { 492 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 493 | DEVELOPMENT_TEAM = E7P9CREU6H; 494 | INFOPLIST_FILE = AVColletion/Info.plist; 495 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 496 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 497 | PRODUCT_BUNDLE_IDENTIFIER = xxx.AVColletion; 498 | PRODUCT_NAME = "$(TARGET_NAME)"; 499 | }; 500 | name = Release; 501 | }; 502 | 8B118A2A1E66EFC9002940C3 /* Debug */ = { 503 | isa = XCBuildConfiguration; 504 | buildSettings = { 505 | BUNDLE_LOADER = "$(TEST_HOST)"; 506 | DEVELOPMENT_TEAM = E7P9CREU6H; 507 | INFOPLIST_FILE = AVColletionTests/Info.plist; 508 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 509 | PRODUCT_BUNDLE_IDENTIFIER = xxx.AVColletionTests; 510 | PRODUCT_NAME = "$(TARGET_NAME)"; 511 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AVColletion.app/AVColletion"; 512 | }; 513 | name = Debug; 514 | }; 515 | 8B118A2B1E66EFC9002940C3 /* Release */ = { 516 | isa = XCBuildConfiguration; 517 | buildSettings = { 518 | BUNDLE_LOADER = "$(TEST_HOST)"; 519 | DEVELOPMENT_TEAM = E7P9CREU6H; 520 | INFOPLIST_FILE = AVColletionTests/Info.plist; 521 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 522 | PRODUCT_BUNDLE_IDENTIFIER = xxx.AVColletionTests; 523 | PRODUCT_NAME = "$(TARGET_NAME)"; 524 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AVColletion.app/AVColletion"; 525 | }; 526 | name = Release; 527 | }; 528 | 8B118A2D1E66EFC9002940C3 /* Debug */ = { 529 | isa = XCBuildConfiguration; 530 | buildSettings = { 531 | DEVELOPMENT_TEAM = E7P9CREU6H; 532 | INFOPLIST_FILE = AVColletionUITests/Info.plist; 533 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 534 | PRODUCT_BUNDLE_IDENTIFIER = xxx.AVColletionUITests; 535 | PRODUCT_NAME = "$(TARGET_NAME)"; 536 | TEST_TARGET_NAME = AVColletion; 537 | }; 538 | name = Debug; 539 | }; 540 | 8B118A2E1E66EFC9002940C3 /* Release */ = { 541 | isa = XCBuildConfiguration; 542 | buildSettings = { 543 | DEVELOPMENT_TEAM = E7P9CREU6H; 544 | INFOPLIST_FILE = AVColletionUITests/Info.plist; 545 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 546 | PRODUCT_BUNDLE_IDENTIFIER = xxx.AVColletionUITests; 547 | PRODUCT_NAME = "$(TARGET_NAME)"; 548 | TEST_TARGET_NAME = AVColletion; 549 | }; 550 | name = Release; 551 | }; 552 | /* End XCBuildConfiguration section */ 553 | 554 | /* Begin XCConfigurationList section */ 555 | 8B1189F41E66EFC8002940C3 /* Build configuration list for PBXProject "AVColletion" */ = { 556 | isa = XCConfigurationList; 557 | buildConfigurations = ( 558 | 8B118A241E66EFC9002940C3 /* Debug */, 559 | 8B118A251E66EFC9002940C3 /* Release */, 560 | ); 561 | defaultConfigurationIsVisible = 0; 562 | defaultConfigurationName = Release; 563 | }; 564 | 8B118A261E66EFC9002940C3 /* Build configuration list for PBXNativeTarget "AVColletion" */ = { 565 | isa = XCConfigurationList; 566 | buildConfigurations = ( 567 | 8B118A271E66EFC9002940C3 /* Debug */, 568 | 8B118A281E66EFC9002940C3 /* Release */, 569 | ); 570 | defaultConfigurationIsVisible = 0; 571 | defaultConfigurationName = Release; 572 | }; 573 | 8B118A291E66EFC9002940C3 /* Build configuration list for PBXNativeTarget "AVColletionTests" */ = { 574 | isa = XCConfigurationList; 575 | buildConfigurations = ( 576 | 8B118A2A1E66EFC9002940C3 /* Debug */, 577 | 8B118A2B1E66EFC9002940C3 /* Release */, 578 | ); 579 | defaultConfigurationIsVisible = 0; 580 | defaultConfigurationName = Release; 581 | }; 582 | 8B118A2C1E66EFC9002940C3 /* Build configuration list for PBXNativeTarget "AVColletionUITests" */ = { 583 | isa = XCConfigurationList; 584 | buildConfigurations = ( 585 | 8B118A2D1E66EFC9002940C3 /* Debug */, 586 | 8B118A2E1E66EFC9002940C3 /* Release */, 587 | ); 588 | defaultConfigurationIsVisible = 0; 589 | defaultConfigurationName = Release; 590 | }; 591 | /* End XCConfigurationList section */ 592 | }; 593 | rootObject = 8B1189F11E66EFC8002940C3 /* Project object */; 594 | } 595 | -------------------------------------------------------------------------------- /AVColletion/AVColletion.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AVColletion/AVColletion.xcodeproj/project.xcworkspace/xcuserdata/tgw.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oopsr/AVDecode/40fb7efbb78b9a0129fd5532adde569c53796b34/AVColletion/AVColletion.xcodeproj/project.xcworkspace/xcuserdata/tgw.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /AVColletion/AVColletion.xcodeproj/xcuserdata/tgw.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /AVColletion/AVColletion.xcodeproj/xcuserdata/tgw.xcuserdatad/xcschemes/AVColletion.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /AVColletion/AVColletion.xcodeproj/xcuserdata/tgw.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | AVColletion.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 8B1189F81E66EFC8002940C3 16 | 17 | primary 18 | 19 | 20 | 8B118A111E66EFC9002940C3 21 | 22 | primary 23 | 24 | 25 | 8B118A1C1E66EFC9002940C3 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /AVColletion/AVColletion/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // AVColletion 4 | // 5 | // Created by Tg W on 2017/3/1. 6 | // Copyright © 2017年 oppsr. 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 | -------------------------------------------------------------------------------- /AVColletion/AVColletion/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // AVColletion 4 | // 5 | // Created by Tg W on 2017/3/1. 6 | // Copyright © 2017年 oppsr. 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 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // 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. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // 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. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // 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. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /AVColletion/AVColletion/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /AVColletion/AVColletion/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 | -------------------------------------------------------------------------------- /AVColletion/AVColletion/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 | 22 | 23 | 24 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /AVColletion/AVColletion/EncodeH264.h: -------------------------------------------------------------------------------- 1 | // 2 | // EncodeH264.h 3 | // AVColletion 4 | // 5 | // Created by Tg W on 2017/3/5. 6 | // Copyright © 2017年 oppsr. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | @interface EncodeH264 : NSObject 13 | 14 | 15 | /** 16 | 创建压缩视频帧的会话 17 | 18 | @param width 宽度(以像素为单位)。如果视频编码器不能支持所提供的宽度和高度,则可以更改它们。 19 | @param height 高度 20 | @param fps 帧速率 21 | @param bt 比特率,表示视频编码器。应该确定压缩数据的大小。 22 | @return 会话创建是否成功,成功返回YES。 23 | */ 24 | - (BOOL)createEncodeSession:(int)width height:(int)height fps:(int)fps bite:(int)bt; 25 | 26 | 27 | - (void)encodeSmapleBuffer:(CMSampleBufferRef)sampleBuffer; 28 | 29 | - (void)openfile; 30 | 31 | - (void)closefile; 32 | @end 33 | -------------------------------------------------------------------------------- /AVColletion/AVColletion/EncodeH264.m: -------------------------------------------------------------------------------- 1 | // 2 | // EncodeH264.m 3 | // AVColletion 4 | // 5 | // Created by Tg W on 2017/3/5. 6 | // Copyright © 2017年 oppsr. All rights reserved. 7 | // 8 | 9 | #import "EncodeH264.h" 10 | 11 | 12 | @interface EncodeH264 (){ 13 | 14 | dispatch_queue_t encodeQueue; 15 | FILE *file; 16 | long timeStamp; 17 | VTCompressionSessionRef encodeSesion;//压缩会话 18 | NSString *documentDic; 19 | } 20 | @property (nonatomic , assign) BOOL isObtainspspps;//判断是否已经获取到pps和sps 21 | - (void) writeH264Data:(void*)data length:(size_t)length addStartCode:(BOOL)b; 22 | 23 | @end 24 | 25 | /** 26 | 编码回调 27 | 28 | @param userData 回调参考值 29 | @param sourceFrameRefCon 帧的引用值 30 | @param status noErr代表压缩成功; 如果压缩不成功,则为错误代码。 31 | @param infoFlags 编码操作的信息 32 | @param sampleBuffer 包含压缩帧,如果压缩成功并且帧未被删除; 否则为NULL。 33 | 34 | */ 35 | void encodeOutputCallback(void *userData, void *sourceFrameRefCon, OSStatus status, VTEncodeInfoFlags infoFlags, 36 | CMSampleBufferRef sampleBuffer ) 37 | { 38 | if (status != noErr) { 39 | NSLog(@"didCompressH264 error: with status %d, infoFlags %d", (int)status, (int)infoFlags); 40 | return; 41 | } 42 | if (!CMSampleBufferDataIsReady(sampleBuffer)) 43 | { 44 | NSLog(@"didCompressH264 data is not ready "); 45 | return; 46 | } 47 | EncodeH264 *h264 = (__bridge EncodeH264*)userData; 48 | 49 | // 判断当前帧是否为关键帧 50 | bool keyframe = !CFDictionaryContainsKey( (CFArrayGetValueAtIndex(CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, true), 0)), kCMSampleAttachmentKey_NotSync); 51 | 52 | // 获取sps & pps数据. sps pps只需获取一次,保存在h264文件开头即可 53 | if (keyframe && !h264.isObtainspspps) 54 | { 55 | size_t spsSize, spsCount; 56 | size_t ppsSize, ppsCount; 57 | 58 | const uint8_t *spsData, *ppsData; 59 | 60 | CMFormatDescriptionRef formatDesc = CMSampleBufferGetFormatDescription(sampleBuffer); 61 | OSStatus err0 = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(formatDesc, 0, &spsData, &spsSize, &spsCount, 0 ); 62 | OSStatus err1 = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(formatDesc, 1, &ppsData, &ppsSize, &ppsCount, 0 ); 63 | 64 | if (err0==noErr && err1==noErr) 65 | { 66 | h264.isObtainspspps = YES; 67 | [h264 writeH264Data:(void *)spsData length:spsSize addStartCode:YES]; 68 | [h264 writeH264Data:(void *)ppsData length:ppsSize addStartCode:YES]; 69 | 70 | NSLog(@"got sps/pps data. Length: sps=%zu, pps=%zu", spsSize, ppsSize); 71 | } 72 | } 73 | 74 | size_t lengthAtOffset, totalLength; 75 | char *data; 76 | 77 | CMBlockBufferRef dataBuffer = CMSampleBufferGetDataBuffer(sampleBuffer); 78 | OSStatus error = CMBlockBufferGetDataPointer(dataBuffer, 0, &lengthAtOffset, &totalLength, &data); 79 | 80 | if (error == noErr) { 81 | size_t offset = 0; 82 | const int lengthInfoSize = 4; // 返回的nalu数据前四个字节不是0001的startcode,而是大端模式的帧长度length 83 | 84 | // 循环获取nalu数据 85 | while (offset < totalLength - lengthInfoSize) { 86 | uint32_t naluLength = 0; 87 | memcpy(&naluLength, data + offset, lengthInfoSize); // 获取nalu的长度, 88 | 89 | // 大端模式转化为系统端模式 90 | naluLength = CFSwapInt32BigToHost(naluLength); 91 | NSLog(@"got nalu data, length=%d, totalLength=%zu", naluLength, totalLength); 92 | 93 | // 保存nalu数据到文件 94 | [h264 writeH264Data:data+offset+lengthInfoSize length:naluLength addStartCode:YES]; 95 | 96 | // 读取下一个nalu,一次回调可能包含多个nalu 97 | offset += lengthInfoSize + naluLength; 98 | } 99 | } 100 | } 101 | 102 | @implementation EncodeH264 103 | 104 | - (instancetype)init { 105 | 106 | if ([super init]) { 107 | encodeQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 108 | timeStamp = 0; 109 | documentDic = [(NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES)) objectAtIndex:0]; 110 | } 111 | return self; 112 | } 113 | 114 | - (BOOL)createEncodeSession:(int)width height:(int)height fps:(int)fps bite:(int)bt { 115 | 116 | OSStatus status; 117 | 118 | //帧压缩完成时调用的回调原型。 119 | VTCompressionOutputCallback cb = encodeOutputCallback; 120 | //创建压缩视频帧的会话。 121 | status = VTCompressionSessionCreate(kCFAllocatorDefault, width, height, kCMVideoCodecType_H264, NULL, NULL, NULL, cb, (__bridge void *)(self), &encodeSesion); 122 | 123 | if (status != noErr) { 124 | NSLog(@"VTCompressionSessionCreate failed. ret=%d", (int)status); 125 | return NO; 126 | } 127 | 128 | //******设置会话的属性****** 129 | //提示视频编码器,压缩是否实时执行。 130 | status = VTSessionSetProperty(encodeSesion, kVTCompressionPropertyKey_RealTime, kCFBooleanTrue); 131 | NSLog(@"set realtime return: %d", (int)status); 132 | 133 | //指定编码比特流的配置文件和级别。直播一般使用baseline,可减少由于b帧带来的延时 134 | status = VTSessionSetProperty(encodeSesion, kVTCompressionPropertyKey_ProfileLevel, kVTProfileLevel_H264_Baseline_AutoLevel); 135 | NSLog(@"set profile return: %d", (int)status); 136 | 137 | //设置比特率。 比特率可以高于此。默认比特率为零,表示视频编码器。应该确定压缩数据的大小。注意,比特率设置只在定时时有效,为源帧提供信息,并且一些编解码器提供不支持限制到指定的比特率。 138 | status = VTSessionSetProperty(encodeSesion, kVTCompressionPropertyKey_AverageBitRate, (__bridge CFTypeRef)@(bt)); 139 | //速率的限制 140 | status += VTSessionSetProperty(encodeSesion, kVTCompressionPropertyKey_DataRateLimits, (__bridge CFArrayRef)@[@(bt*2/8), @1]); // Bps 141 | NSLog(@"set bitrate return: %d", (int)status); 142 | 143 | // 设置关键帧速率。 144 | status = VTSessionSetProperty(encodeSesion, kVTCompressionPropertyKey_MaxKeyFrameInterval, (__bridge CFTypeRef)@(fps*2)); 145 | 146 | // 设置预期的帧速率。 147 | status = VTSessionSetProperty(encodeSesion, kVTCompressionPropertyKey_ExpectedFrameRate, (__bridge CFTypeRef)@(fps)); 148 | NSLog(@"set framerate return: %d", (int)status); 149 | 150 | // 开始编码 151 | status = VTCompressionSessionPrepareToEncodeFrames(encodeSesion); 152 | NSLog(@"start encode return: %d", (int)status); 153 | 154 | return YES; 155 | 156 | } 157 | //保存h264数据到沙盒中document,可以下载TCL播放器播放 158 | - (void)writeH264Data:(void*)data length:(size_t)length addStartCode:(BOOL)b 159 | { 160 | // 添加start code 161 | const Byte bytes[] = "\x00\x00\x00\x01"; 162 | 163 | if (file) { 164 | if(b)fwrite(bytes, 1, 4, file); 165 | fwrite(data, 1, length, file); 166 | } else { 167 | NSLog(@"file null error, check if it open successed"); 168 | } 169 | } 170 | - (void) stopEncodeSession 171 | { 172 | VTCompressionSessionCompleteFrames(encodeSesion, kCMTimeInvalid); 173 | 174 | VTCompressionSessionInvalidate(encodeSesion); 175 | 176 | CFRelease(encodeSesion); 177 | encodeSesion = NULL; 178 | } 179 | 180 | - (void)encodeSmapleBuffer:(CMSampleBufferRef)sampleBuffer { 181 | 182 | dispatch_sync(encodeQueue, ^{ 183 | //CVImageBuffer的媒体数据。 184 | CVImageBufferRef imageBuffer = (CVImageBufferRef)CMSampleBufferGetImageBuffer(sampleBuffer); 185 | // 此帧的呈现时间戳,将附加到样本缓冲区,传递给会话的每个显示时间戳必须大于上一个。 186 | timeStamp ++; 187 | CMTime pts = CMTimeMake(timeStamp, 1000); 188 | //此帧的呈现持续时间 189 | CMTime duration = kCMTimeInvalid; 190 | VTEncodeInfoFlags flags; 191 | // 调用此函数可将帧呈现给压缩会话。 192 | OSStatus statusCode = VTCompressionSessionEncodeFrame(encodeSesion, 193 | imageBuffer, 194 | pts, duration, 195 | NULL, NULL, &flags); 196 | 197 | if (statusCode != noErr) { 198 | NSLog(@"H264: VTCompressionSessionEncodeFrame failed with %d", (int)statusCode); 199 | 200 | [self stopEncodeSession]; 201 | return; 202 | } 203 | }); 204 | } 205 | 206 | - (void)openfile { 207 | 208 | file = fopen([[NSString stringWithFormat:@"%@/video.h264",documentDic] UTF8String], "wb"); 209 | } 210 | - (void)closefile { 211 | 212 | fclose(file); 213 | } 214 | @end 215 | -------------------------------------------------------------------------------- /AVColletion/AVColletion/EncoderAAC.h: -------------------------------------------------------------------------------- 1 | // 2 | // EncoderAAC.h 3 | // AVColletion 4 | // 5 | // Created by Tg W on 2017/3/4. 6 | // Copyright © 2017年 oppsr. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | @interface EncoderAAC : NSObject 13 | -(void)encodeSmapleBuffer:(CMSampleBufferRef)sampleBuffer; 14 | @end 15 | -------------------------------------------------------------------------------- /AVColletion/AVColletion/EncoderAAC.m: -------------------------------------------------------------------------------- 1 | // 2 | // EncoderAAC.m 3 | // AVColletion 4 | // 5 | // Created by Tg W on 2017/3/4. 6 | // Copyright © 2017年 oppsr. All rights reserved. 7 | // 8 | 9 | #import "EncoderAAC.h" 10 | 11 | typedef struct { 12 | // pcm数据指针 13 | void *source; 14 | // pcm数据的长度 15 | UInt32 sourceSize; 16 | // 声道数 17 | UInt32 channelCount; 18 | 19 | AudioStreamPacketDescription *packetDescription; 20 | }FillComplexInputParm; 21 | 22 | typedef struct { 23 | AudioConverterRef converter; 24 | int samplerate; 25 | int channles; 26 | }ConverterContext; 27 | 28 | // AudioConverter的提供数据的回调函数 29 | OSStatus audioConverterComplexInputDataProc(AudioConverterRef inAudioConverter,UInt32 * ioNumberDataPacket,AudioBufferList *ioData,AudioStreamPacketDescription ** outDataPacketDescription,void *inUserData){ 30 | // ioData用来接受需要转换的pcm数据給converter进行编码 31 | 32 | FillComplexInputParm *param = (FillComplexInputParm *)inUserData; 33 | if (param->sourceSize <= 0) { 34 | *ioNumberDataPacket = 0; 35 | return - 1; 36 | } 37 | ioData->mBuffers[0].mData = param->source; 38 | ioData->mBuffers[0].mDataByteSize = param->sourceSize; 39 | ioData->mBuffers[0].mNumberChannels = param->channelCount; 40 | *ioNumberDataPacket = 1; 41 | param->sourceSize = 0; 42 | return noErr; 43 | } 44 | @interface EncoderAAC (){ 45 |  ConverterContext *convertContext; 46 | dispatch_queue_t encodeQueue; 47 | } 48 | @property (nonatomic, copy) NSString *path; 49 | @property (nonatomic, strong) NSFileHandle *handle; 50 | @end 51 | @implementation EncoderAAC 52 | 53 | - (instancetype)init { 54 | 55 | if ( self = [super init]) { 56 | encodeQueue = dispatch_queue_create("myencode", DISPATCH_QUEUE_SERIAL); 57 | //保存aac数据到沙盒中document,可以iTunes播放 58 | self.path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"audio.aac"]; 59 | NSFileManager *manager = [NSFileManager defaultManager]; 60 | BOOL a = [manager createFileAtPath:_path contents:nil attributes:nil]; 61 | if (a) { 62 | NSLog(@"creat file success"); 63 | }else{ 64 | NSLog(@"creat file fail"); 65 | } 66 | NSFileHandle *handle = [NSFileHandle fileHandleForWritingAtPath:_path]; 67 | self.handle = handle; 68 | 69 | } 70 | return self; 71 | } 72 | 73 | - (void)setUpConverter:(CMSampleBufferRef)sampleBuffer{ 74 | // 获取audioformat的描述信息 75 | CMAudioFormatDescriptionRef audioFormatDes = (CMAudioFormatDescriptionRef)CMSampleBufferGetFormatDescription(sampleBuffer); 76 | // 获取输入的asbd的信息 77 | AudioStreamBasicDescription inAudioStreamBasicDescription = *(CMAudioFormatDescriptionGetStreamBasicDescription(audioFormatDes)); 78 | // 开始构造输出的asbd 79 | AudioStreamBasicDescription outAudioStreamBasicDescription = {0}; 80 | // 对于压缩格式必须设置为0 81 | outAudioStreamBasicDescription.mBitsPerChannel = 0; 82 | outAudioStreamBasicDescription.mBytesPerFrame = 0; 83 | // 设定声道数为1 84 | outAudioStreamBasicDescription.mChannelsPerFrame = 1; 85 | // 设定输出音频的格式 86 | outAudioStreamBasicDescription.mFormatID = kAudioFormatMPEG4AAC; 87 | outAudioStreamBasicDescription.mFormatFlags = kMPEG4Object_AAC_LC; 88 | // 填充输出的音频格式 89 | UInt32 size = sizeof(outAudioStreamBasicDescription); 90 | AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &size, &outAudioStreamBasicDescription); 91 | // 选择aac的编码器(用来描述一个已经安装的编解码器) 92 | AudioClassDescription audioClassDes; 93 | // 初始化为0 94 | memset(&audioClassDes, 0, sizeof(audioClassDes)); 95 | // 获取满足要求的aac编码起的总大小 96 | UInt32 countSize = 0; 97 | AudioFormatGetPropertyInfo(kAudioFormatProperty_Encoders, sizeof(outAudioStreamBasicDescription.mFormatID), &outAudioStreamBasicDescription.mFormatID, &countSize); 98 | // 用来计算aac的编解码器的个数 99 | int cout = countSize / sizeof(audioClassDes); 100 | // 创建一个包含有cout个数的编码器数组 101 | AudioClassDescription descriptions[cout]; 102 | // 将编码起数组信息写入到descriptions中。 103 | AudioFormatGetProperty(kAudioFormatProperty_Encoders, sizeof(outAudioStreamBasicDescription.mFormatID), &outAudioStreamBasicDescription.mFormatID, &countSize, descriptions); 104 | for (int i = 0; i < cout; cout++) { 105 | AudioClassDescription temp = descriptions[i]; 106 | if (temp.mManufacturer == kAppleSoftwareAudioCodecManufacturer && temp.mSubType ==outAudioStreamBasicDescription.mFormatID) { 107 | audioClassDes = temp; 108 | break; 109 | } 110 | } 111 | // 创建convertcontext用来保存converter的信息 112 | ConverterContext *context = malloc(sizeof(ConverterContext)); 113 | self->convertContext = context; 114 | OSStatus result = AudioConverterNewSpecific(&inAudioStreamBasicDescription, &outAudioStreamBasicDescription, 1, &audioClassDes, &(context->converter)); 115 | if (result == noErr) { 116 | // 创建编解码器成功 117 | AudioConverterRef converter = context->converter; 118 | 119 | // 设置编码起属性 120 | UInt32 temp = kAudioConverterQuality_High; 121 | AudioConverterSetProperty(converter, kAudioConverterCodecQuality, sizeof(temp), &temp); 122 | 123 | // 设置比特率 124 | UInt32 bitRate = 96000; 125 | result = AudioConverterSetProperty(converter, kAudioConverterEncodeBitRate, sizeof(bitRate), &bitRate); 126 | if (result != noErr) { 127 | NSLog(@"设置比特率失败"); 128 | } 129 | }else{ 130 | // 创建编解码器失败 131 | free(context); 132 | context = NULL; 133 | NSLog(@"创建编解码器失败"); 134 | } 135 | } 136 | 137 | 138 | // 编码samplebuffer数据 139 | -(void)encodeSmapleBuffer:(CMSampleBufferRef)sampleBuffer{ 140 | 141 | if (!self->convertContext) { 142 | [self setUpConverter:sampleBuffer]; 143 | } 144 | ConverterContext *cxt = self->convertContext; 145 | if (cxt && cxt->converter) { 146 | // 从samplebuffer中提取数据 147 | CFRetain(sampleBuffer); 148 | dispatch_async(encodeQueue, ^{ 149 | // 从samplebuffer众获取blockbuffer 150 | CMBlockBufferRef blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer); 151 | size_t pcmLength = 0; 152 | char * pcmData = NULL; 153 | // 获取blockbuffer中的pcm数据的指针和长度 154 | OSStatus status = CMBlockBufferGetDataPointer(blockBuffer, 0, NULL, &pcmLength, &pcmData); 155 | if (status != noErr) { 156 | NSLog(@"从block众获取pcm数据失败"); 157 | CFRelease(sampleBuffer); 158 | return ; 159 | }else{ 160 | // 在堆区分配内存用来保存编码后的aac数据 161 | char *outputBuffer = malloc(pcmLength); 162 | memset(outputBuffer, 0, pcmLength); 163 | 164 | UInt32 packetSize = 1; 165 | AudioStreamPacketDescription *outputPacketDes = (AudioStreamPacketDescription *)malloc(sizeof(AudioStreamPacketDescription) * packetSize); 166 | // 使用fillcomplexinputparm来保存pcm数据 167 | FillComplexInputParm userParam; 168 | userParam.source = pcmData; 169 | userParam.sourceSize = (UInt32)pcmLength; 170 | userParam.channelCount = 1; 171 | userParam.packetDescription = NULL; 172 | 173 | // 在堆区创建audiobufferlist 174 | // AudioBufferList *bufferList = malloc(sizeof(AudioBufferList)); 175 | AudioBufferList outputBufferList; 176 | outputBufferList.mNumberBuffers = 1; 177 | outputBufferList.mBuffers[0].mData = outputBuffer; 178 | outputBufferList.mBuffers[0].mDataByteSize = pcmLength; 179 | outputBufferList.mBuffers[0].mNumberChannels = 1; 180 | 181 | status = AudioConverterFillComplexBuffer(convertContext->converter, audioConverterComplexInputDataProc, &userParam, &packetSize, &outputBufferList, outputPacketDes); 182 | free(outputPacketDes); 183 | outputPacketDes = NULL; 184 | if (status == noErr) { 185 | static int64_t totoalLength = 0; 186 | if (totoalLength >= 1024 * 1024 * 1) { 187 | return; 188 | } 189 | NSLog(@"编码成功"); 190 | // 获取原始的aac数据 191 | NSData *rawAAC = [NSData dataWithBytes:outputBufferList.mBuffers[0].mData length:outputBufferList.mBuffers[0].mDataByteSize]; 192 | free(outputBuffer); 193 | outputBuffer = NULL; 194 | 195 | // 设置adts头 196 | int headerLength = 0; 197 | char *packetHeader = newAdtsDataForPacketLength(rawAAC.length, 44100, 1, &headerLength); 198 | NSData *adtsHeader = [NSData dataWithBytes:packetHeader length:headerLength]; 199 | free(packetHeader); 200 | packetHeader = NULL; 201 | NSMutableData *fullData = [NSMutableData dataWithData:adtsHeader]; 202 | [fullData appendData:rawAAC]; 203 | [_handle seekToEndOfFile]; 204 | [_handle writeData:fullData]; 205 | fullData = nil; 206 | rawAAC = nil; 207 | totoalLength+=fullData.length; 208 | if (totoalLength >= 1024 * 1024 *1) { 209 | [_handle closeFile]; 210 | } 211 | } 212 | CFRelease(sampleBuffer); 213 | 214 | } 215 | }); 216 | } 217 | } 218 | // 給aac加上adts头, packetLength 为rewaac的长度, 219 | char *newAdtsDataForPacketLength(int packetLength,int sampleRate,int channelCout, int *ioHeaderLen){ 220 | // adts头的长度为固定的7个字节 221 | int adtsLen = 7; 222 | // 在堆区分配7个字节的内存 223 | char *packet = malloc(sizeof(char) * adtsLen); 224 | // 选择AAC LC 225 | int profile = 2; 226 | // 选择采样率对应的下标 227 | int freqIdx = 4; 228 | // 选择声道数所对应的下标 229 | int chanCfg = 1; 230 | // 获取adts头和raw aac的总长度 231 | NSUInteger fullLength = adtsLen + packetLength; 232 | // 设置syncword 233 | packet[0] = 0xFF; 234 | packet[1] = 0xF9; 235 | packet[2] = (char)(((profile - 1)<<6) + (freqIdx<<2)+(chanCfg>>2)); 236 | packet[3] = (char)(((chanCfg&3)<<6)+(fullLength>>11)); 237 | packet[4] = (char)((fullLength&0x7FF)>>3); 238 | packet[5] = (char)(((fullLength&7)<<5)+0x1F); 239 | packet[6] = (char)0xFC; 240 | *ioHeaderLen =adtsLen; 241 | return packet; 242 | } 243 | @end 244 | -------------------------------------------------------------------------------- /AVColletion/AVColletion/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 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | NSPhotoLibraryUsageDescription 45 | App需要您的同意,才能访问相册 46 | NSCameraUsageDescription 47 | App需要您的同意,才能访问相机 48 | NSMicrophoneUsageDescription 49 | App需要您的同意,才能访问麦克风 50 | NSLocationUsageDescription 51 | App需要您的同意,才能访问位置 52 | NSLocationWhenInUseUsageDescription 53 | App需要您的同意,才能在使用期间访问位置 54 | NSLocationAlwaysUsageDescription 55 | App需要您的同意,才能始终访问位置 56 | NSCalendarsUsageDescription 57 | App需要您的同意,才能访问日历 58 | NSRemindersUsageDescription 59 | App需要您的同意,才能访问提醒事项 60 | NSMotionUsageDescription 61 | App需要您的同意,才能访问运动与健身 62 | NSHealthUpdateUsageDescription 63 | App需要您的同意,才能访问健康更新 64 | NSHealthShareUsageDescription 65 | App需要您的同意,才能访问健康分享 66 | NSBluetoothPeripheralUsageDescription 67 | App需要您的同意,才能访问蓝牙 68 | NSAppleMusicUsageDescription 69 | App需要您的同意,才能访问媒体资料库 70 | UIFileSharingEnabled 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /AVColletion/AVColletion/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // AVColletion 4 | // 5 | // Created by Tg W on 2017/3/1. 6 | // Copyright © 2017年 oppsr. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | @property (weak, nonatomic) IBOutlet UIButton *startBtn; 14 | 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /AVColletion/AVColletion/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // AVColletion 4 | // 5 | // Created by Tg W on 2017/3/1. 6 | // Copyright © 2017年 oppsr. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "MyCaptureSession.h" 11 | #import "EncoderAAC.h" 12 | #import "EncodeH264.h" 13 | @interface ViewController () { 14 | 15 | EncoderAAC *_aac; 16 | EncodeH264 *_h264; 17 | } 18 | @property (nonatomic, strong) MyCaptureSession *captureSession; 19 | @end 20 | 21 | @implementation ViewController 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | //初始化音频编码 26 | _aac = [[EncoderAAC alloc] init]; 27 | //初始化视频编码 28 | _h264 = [[EncodeH264 alloc] init]; 29 | //创建视频解码会话 30 | [_h264 createEncodeSession:480 height:640 fps:25 bite:640*1000]; 31 | //创建音视频采集会话 32 | _captureSession = [[MyCaptureSession alloc]initCaptureWithSessionPreset:CaptureSessionPreset640x480]; 33 | //采集代理 34 | _captureSession.delegate = self; 35 | 36 | AVCaptureVideoPreviewLayer *preViewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession.session]; 37 | //创建视频展示layer 38 | preViewLayer.frame = CGRectMake(0.f, 0.f, self.view.bounds.size.width, self.view.bounds.size.height); 39 | // 设置layer展示视频的方向 40 | preViewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; 41 | [self.view.layer addSublayer:preViewLayer]; 42 | [self.view bringSubviewToFront:self.startBtn]; 43 | 44 | } 45 | 46 | - (IBAction)startCode:(UIButton *)sender { 47 | 48 | sender.selected = !sender.selected; 49 | if (sender.selected) { 50 | //存储操作其实可以提取出来 51 | [_h264 openfile]; 52 | [_captureSession start]; 53 | [sender setTitle:@"停止编码" forState:UIControlStateNormal]; 54 | 55 | }else { 56 | [_h264 closefile]; 57 | [_captureSession stop]; 58 | [sender setTitle:@"开始编码" forState:UIControlStateNormal]; 59 | } 60 | 61 | } 62 | 63 | - (void)audioWithSampleBuffer:(CMSampleBufferRef)sampleBuffer { 64 | 65 | [_aac encodeSmapleBuffer:sampleBuffer]; 66 | } 67 | 68 | - (void)videoWithSampleBuffer:(CMSampleBufferRef)sampleBuffer { 69 | 70 | [_h264 encodeSmapleBuffer:sampleBuffer]; 71 | } 72 | 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /AVColletion/AVColletion/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // AVColletion 4 | // 5 | // Created by Tg W on 2017/3/1. 6 | // Copyright © 2017年 oppsr. 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 | -------------------------------------------------------------------------------- /AVColletion/AVColletionTests/AVColletionTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // AVColletionTests.m 3 | // AVColletionTests 4 | // 5 | // Created by Tg W on 2017/3/1. 6 | // Copyright © 2017年 oppsr. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AVColletionTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation AVColletionTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /AVColletion/AVColletionTests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /AVColletion/AVColletionUITests/AVColletionUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // AVColletionUITests.m 3 | // AVColletionUITests 4 | // 5 | // Created by Tg W on 2017/3/1. 6 | // Copyright © 2017年 oppsr. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AVColletionUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation AVColletionUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /AVColletion/AVColletionUITests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /AVColletion/MyCaptureSession.h: -------------------------------------------------------------------------------- 1 | // 2 | // MyCaptureSession.h 3 | // AVColletion 4 | // 5 | // Created by Tg W on 2017/3/1. 6 | // Copyright © 2017年 oppsr. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | typedef NS_ENUM(NSUInteger,CaptureSessionPreset){ 13 | CaptureSessionPreset640x480, 14 | CaptureSessionPresetiFrame960x540, 15 | CaptureSessionPreset1280x720, 16 | }; 17 | @protocol MycaptureSessionDelegate 18 | 19 | - (void)videoWithSampleBuffer:(CMSampleBufferRef)sampleBuffer; 20 | 21 | - (void)audioWithSampleBuffer:(CMSampleBufferRef)sampleBuffer; 22 | 23 | 24 | @end 25 | @interface MyCaptureSession : NSObject 26 | @property (nonatomic ,strong) iddelegate; 27 | @property (nonatomic ,strong) AVCaptureSession *session; //管理对象 28 | 29 | - (instancetype)initCaptureWithSessionPreset:(CaptureSessionPreset)preset; 30 | 31 | - (void)start; 32 | 33 | - (void)stop; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /AVColletion/MyCaptureSession.m: -------------------------------------------------------------------------------- 1 | // 2 | // MyCaptureSession.m 3 | // AVColletion 4 | // 5 | // Created by Tg W on 2017/3/1. 6 | // Copyright © 2017年 oppsr. All rights reserved. 7 | // 8 | 9 | #import "MyCaptureSession.h" 10 | 11 | @interface MyCaptureSession() 12 | 13 | @property (nonatomic ,strong) AVCaptureDevice *videoDevice; //设备 14 | @property (nonatomic ,strong) AVCaptureDevice *audioDevice; 15 | 16 | @property (nonatomic ,strong) AVCaptureDeviceInput *videoInput;//输入对象 17 | @property (nonatomic ,strong) AVCaptureDeviceInput *audioInput; 18 | 19 | @property (nonatomic, strong) AVCaptureVideoDataOutput *videoOutput;//输出对象 20 | @property (nonatomic, strong) AVCaptureAudioDataOutput *audioOutput; 21 | 22 | @property (nonatomic, assign) CaptureSessionPreset definePreset; 23 | @property (nonatomic, strong) NSString *realPreset; 24 | @end 25 | @implementation MyCaptureSession 26 | 27 | - (instancetype)initCaptureWithSessionPreset:(CaptureSessionPreset)preset { 28 | 29 | if ([super init]) { 30 | 31 | [self initAVcaptureSession]; 32 | _definePreset = preset; 33 | } 34 | return self; 35 | } 36 | 37 | - (void)initAVcaptureSession { 38 | 39 | //初始化AVCaptureSession 40 | _session = [[AVCaptureSession alloc] init]; 41 | // 设置录像分辨率 42 | if (![self.session canSetSessionPreset:self.realPreset]) { 43 | if (![self.session canSetSessionPreset:AVCaptureSessionPresetiFrame960x540]) { 44 | if (![self.session canSetSessionPreset:AVCaptureSessionPreset640x480]) { 45 | } 46 | } 47 | } 48 | 49 | //开始配置 50 | [_session beginConfiguration]; 51 | 52 | NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; 53 | //获取视频设备对象 54 | for(AVCaptureDevice *device in devices) { 55 | if (device.position == AVCaptureDevicePositionFront) { 56 | self.videoDevice = device;//前置摄像头 57 | 58 | } 59 | } 60 | //初始化视频捕获输入对象 61 | NSError *error; 62 | self.videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:self.videoDevice error:&error]; 63 | if (error) { 64 | NSLog(@"摄像头错误"); 65 | return; 66 | } 67 | //输入对象添加到Session 68 | if ([self.session canAddInput:self.videoInput]) { 69 | [self.session addInput:self.videoInput]; 70 | } 71 | //输出对象 72 | self.videoOutput = [[AVCaptureVideoDataOutput alloc] init]; 73 | //是否卡顿时丢帧 74 | self.videoOutput.alwaysDiscardsLateVideoFrames = NO; 75 | // 设置像素格式 76 | [self.videoOutput setVideoSettings:@{ 77 | (__bridge NSString *)kCVPixelBufferPixelFormatTypeKey:@(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange) 78 | }]; 79 | //将输出对象添加到队列、并设置代理 80 | dispatch_queue_t captureQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 81 | [self.videoOutput setSampleBufferDelegate:self queue:captureQueue]; 82 | 83 | // 判断session 是否可添加视频输出对象 84 | if ([self.session canAddOutput:self.videoOutput]) { 85 | [self.session addOutput:self.videoOutput]; 86 | // 链接视频 I/O 对象 87 | } 88 | //创建连接 AVCaptureConnection输入对像和捕获输出对象之间建立连接。 89 | AVCaptureConnection *connection = [self.videoOutput connectionWithMediaType:AVMediaTypeVideo]; 90 | //视频的方向 91 | connection.videoOrientation = AVCaptureVideoOrientationPortrait; 92 | //设置稳定性,判断connection连接对象是否支持视频稳定 93 | if ([connection isVideoStabilizationSupported]) { 94 | //这个稳定模式最适合连接 95 | connection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto; 96 | } 97 | //缩放裁剪系数 98 | connection.videoScaleAndCropFactor = connection.videoMaxScaleAndCropFactor; 99 | 100 | //***************音频设置*********** 101 | 102 | NSError *error1; 103 | //获取音频设备对象 104 | self.audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio]; 105 | //初始化捕获输入对象 106 | self.audioInput = [[AVCaptureDeviceInput alloc] initWithDevice:self.audioDevice error:&error]; 107 | if (error1) { 108 | NSLog(@"== 录音设备出错"); 109 | } 110 | // 添加音频输入对象到session 111 | if ([self.session canAddInput:self.audioInput]) { 112 | [self.session addInput:self.audioInput]; 113 | } 114 | //初始化输出捕获对象 115 | self.audioOutput = [[AVCaptureAudioDataOutput alloc] init]; 116 | 117 | // 添加音频输出对象到session 118 | if ([self.session canAddOutput:self.audioOutput]) { 119 | [self.session addOutput:self.audioOutput]; 120 | } 121 | 122 | // 创建设置音频输出代理所需要的线程队列 123 | dispatch_queue_t audioQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0); 124 | [self.audioOutput setSampleBufferDelegate:self queue:audioQueue]; // 提交配置 125 | [self.session commitConfiguration]; 126 | 127 | } 128 | 129 | - (NSString*)realPreset { 130 | switch (_definePreset) { 131 | case CaptureSessionPreset640x480: 132 | _realPreset = AVCaptureSessionPreset640x480; 133 | break; 134 | case CaptureSessionPresetiFrame960x540: 135 | _realPreset = AVCaptureSessionPresetiFrame960x540; 136 | 137 | break; 138 | case CaptureSessionPreset1280x720: 139 | _realPreset = AVCaptureSessionPreset1280x720; 140 | 141 | break; 142 | default: 143 | _realPreset = AVCaptureSessionPreset640x480; 144 | 145 | break; 146 | } 147 | 148 | return _realPreset; 149 | } 150 | 151 | - (void)start { 152 | 153 | [self.session startRunning]; 154 | 155 | } 156 | - (void)stop { 157 | 158 | [self.session stopRunning]; 159 | } 160 | - (void)captureOutput:(AVCaptureOutput *)captureOutput 161 | didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { 162 | 163 | if (captureOutput == self.audioOutput) { 164 | if (self.delegate && [self.delegate respondsToSelector:@selector(audioWithSampleBuffer:)]) { 165 | [self.delegate audioWithSampleBuffer:sampleBuffer]; 166 | } 167 | }else { 168 | if (self.delegate && [self.delegate respondsToSelector:@selector(videoWithSampleBuffer:)]) { 169 | [self.delegate videoWithSampleBuffer:sampleBuffer]; 170 | } 171 | } 172 | 173 | } 174 | @end 175 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AVDecode 2 | iOS中音视频采集,硬编码(AudioToolbox、VideoToolbox) 3 | 4 | 用到AVCaptureSession来进行音视频数据采集、采集得到pcm和yuv420原始数据。 5 | 6 | 采用AudioToolbox将数据pcm硬编码为aac 7 | 8 | 用VideoToolbox将数据yuv420硬编码为h.264 9 | 10 | ![image](http://wx1.sinaimg.cn/mw690/c320c33egy1fdc53zsh92j20ku112tf3.jpg) --------------------------------------------------------------------------------