├── EasyCamera_iOS ├── EasyCamera │ ├── G711 │ │ ├── .svn │ │ │ ├── entries │ │ │ ├── format │ │ │ ├── wc.db │ │ │ └── pristine │ │ │ │ ├── 22 │ │ │ │ └── 2234e5cf25004bedadd35d9aa4eb4544ab862db9.svn-base │ │ │ │ ├── f3 │ │ │ │ └── f3df9e67f84a87914d0c26506b3dc742ed60b844.svn-base │ │ │ │ └── 9b │ │ │ │ └── 9bcc65a54b8c5cd1508688da1d9605f9ba0b01f4.svn-base │ │ ├── g711codec.h │ │ ├── g711.c │ │ └── g711codec.c │ ├── .DS_Store │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── .DS_Store │ │ ├── AppIcon.appiconset │ │ │ ├── EasyCamera.png │ │ │ ├── EasyCamera-1.png │ │ │ ├── EasyCamera-2.png │ │ │ ├── EasyCamera-3.png │ │ │ ├── EasyCamera-4.png │ │ │ ├── EasyCamera-5.png │ │ │ ├── EasyCamera-6.png │ │ │ ├── EasyCamera-7.png │ │ │ └── Contents.json │ │ ├── EasyPusher.imageset │ │ │ ├── EasyCamera1.png │ │ │ └── Contents.json │ │ ├── EasyClient_iOS_appStore.imageset │ │ │ ├── EasyClient_iOS_appStore.png │ │ │ └── Contents.json │ │ ├── ic_action_about.imageset │ │ │ ├── Info_96px_1180699_easyicon.net.png │ │ │ └── Contents.json │ │ ├── icn_change_view_pressed.imageset │ │ │ ├── icn_change_view_pressed.png │ │ │ └── Contents.json │ │ └── video_record_set_off_press.imageset │ │ │ ├── video_record_set_off_press.png │ │ │ └── Contents.json │ ├── EasySocket.m │ ├── EasyDarwinInfoViewController.h │ ├── ServerInfoViewController.h │ ├── AppDelegate.h │ ├── ViewController.h │ ├── EasySocket.h │ ├── main.m │ ├── EasySetingViewController.h │ ├── ServerInfoViewController.m │ ├── EasyDarwinInfoViewController.m │ ├── Base.lproj │ │ ├── Main.storyboard │ │ └── LaunchScreen.storyboard │ ├── Info.plist │ ├── PureLayout │ │ ├── PureLayout.h │ │ ├── NSLayoutConstraint+PureLayout.h │ │ ├── PureLayout+Internal.h │ │ ├── NSArray+PureLayout.h │ │ ├── ALView+PureLayout.h │ │ └── PureLayoutDefines.h │ ├── AppDelegate.m │ ├── EasySetingViewController.m │ ├── ServerInfoViewController.xib │ └── EasyDarwinInfoViewController.xib ├── .DS_Store ├── Encoder │ ├── .DS_Store │ ├── Codec │ │ ├── H264Packet.h │ │ ├── H264HWDecoder.h │ │ ├── AACEncoder.h │ │ ├── H264HWEncoder.h │ │ ├── H264Packet.m │ │ ├── H264HWEncoder.m │ │ ├── AACEncoder.m │ │ └── H264HWDecoder.m │ ├── EasyResolutionViewController.h │ ├── CameraEncoder.h │ ├── EasyResolutionViewController.m │ ├── EasyResolutionViewController.xib │ └── CameraEncoder.m ├── EasyPusherLib │ ├── .DS_Store │ ├── EasyTypes.h │ ├── EasyTypes的副本.h │ ├── libEasyPusher.a │ ├── libEasyPusher.a的副本 │ ├── EasyPusherAPI.h │ └── EasyPusherAPI的副本.h └── EasyCamera.xcodeproj │ ├── project.xcworkspace │ ├── xcuserdata │ │ └── yingengyue.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── contents.xcworkspacedata │ └── xcuserdata │ ├── yingengyue.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── EasyCamera.xcscheme │ └── tsinglink.xcuserdatad │ └── xcschemes │ ├── xcschememanagement.plist │ └── EasyPush.xcscheme ├── .DS_Store └── README.md /EasyCamera_iOS/EasyCamera/G711/.svn/entries: -------------------------------------------------------------------------------- 1 | 12 2 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/G711/.svn/format: -------------------------------------------------------------------------------- 1 | 12 2 | -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/.DS_Store -------------------------------------------------------------------------------- /EasyCamera_iOS/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/.DS_Store -------------------------------------------------------------------------------- /EasyCamera_iOS/Encoder/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/Encoder/.DS_Store -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/EasyCamera/.DS_Store -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyPusherLib/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/EasyPusherLib/.DS_Store -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyPusherLib/EasyTypes.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/EasyPusherLib/EasyTypes.h -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/G711/.svn/wc.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/EasyCamera/G711/.svn/wc.db -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyPusherLib/EasyTypes的副本.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/EasyPusherLib/EasyTypes的副本.h -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyPusherLib/libEasyPusher.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/EasyPusherLib/libEasyPusher.a -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyPusherLib/libEasyPusher.a的副本: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/EasyPusherLib/libEasyPusher.a的副本 -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/Assets.xcassets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/EasyCamera/Assets.xcassets/.DS_Store -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/Assets.xcassets/AppIcon.appiconset/EasyCamera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/EasyCamera/Assets.xcassets/AppIcon.appiconset/EasyCamera.png -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/Assets.xcassets/AppIcon.appiconset/EasyCamera-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/EasyCamera/Assets.xcassets/AppIcon.appiconset/EasyCamera-1.png -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/Assets.xcassets/AppIcon.appiconset/EasyCamera-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/EasyCamera/Assets.xcassets/AppIcon.appiconset/EasyCamera-2.png -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/Assets.xcassets/AppIcon.appiconset/EasyCamera-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/EasyCamera/Assets.xcassets/AppIcon.appiconset/EasyCamera-3.png -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/Assets.xcassets/AppIcon.appiconset/EasyCamera-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/EasyCamera/Assets.xcassets/AppIcon.appiconset/EasyCamera-4.png -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/Assets.xcassets/AppIcon.appiconset/EasyCamera-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/EasyCamera/Assets.xcassets/AppIcon.appiconset/EasyCamera-5.png -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/Assets.xcassets/AppIcon.appiconset/EasyCamera-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/EasyCamera/Assets.xcassets/AppIcon.appiconset/EasyCamera-6.png -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/Assets.xcassets/AppIcon.appiconset/EasyCamera-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/EasyCamera/Assets.xcassets/AppIcon.appiconset/EasyCamera-7.png -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/Assets.xcassets/EasyPusher.imageset/EasyCamera1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/EasyCamera/Assets.xcassets/EasyPusher.imageset/EasyCamera1.png -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/Assets.xcassets/EasyClient_iOS_appStore.imageset/EasyClient_iOS_appStore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/EasyCamera/Assets.xcassets/EasyClient_iOS_appStore.imageset/EasyClient_iOS_appStore.png -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/Assets.xcassets/ic_action_about.imageset/Info_96px_1180699_easyicon.net.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/EasyCamera/Assets.xcassets/ic_action_about.imageset/Info_96px_1180699_easyicon.net.png -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/Assets.xcassets/icn_change_view_pressed.imageset/icn_change_view_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/EasyCamera/Assets.xcassets/icn_change_view_pressed.imageset/icn_change_view_pressed.png -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/Assets.xcassets/video_record_set_off_press.imageset/video_record_set_off_press.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/EasyCamera/Assets.xcassets/video_record_set_off_press.imageset/video_record_set_off_press.png -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera.xcodeproj/project.xcworkspace/xcuserdata/yingengyue.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/babosa/EasyCamera_iOS/HEAD/EasyCamera_iOS/EasyCamera.xcodeproj/project.xcworkspace/xcuserdata/yingengyue.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/EasySocket.m: -------------------------------------------------------------------------------- 1 | // 2 | // EasySocket.m 3 | // EasyCamera 4 | // 5 | // Created by yingengyue on 2017/3/18. 6 | // Copyright © 2017年 phylony. All rights reserved. 7 | // 8 | 9 | #import "EasySocket.h" 10 | 11 | @implementation EasySocket 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/EasyDarwinInfoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // EasyDarwinInfoViewController.h 3 | // EasyPusher 4 | // 5 | // Created by yingengyue on 2017/3/4. 6 | // Copyright © 2017年 phylony. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface EasyDarwinInfoViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/ServerInfoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ServerInfoViewController.h 3 | // EasyCapture 4 | // 5 | // Created by ChenShun on 2016/11/21. 6 | // Copyright © 2016年 phylony. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ServerInfoViewController : UIViewController 12 | { 13 | 14 | } 15 | @end 16 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // EasyCapture 4 | // 5 | // Created by phylony on 9/11/16. 6 | // Copyright © 2016 phylony. 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 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // EasyCapture 4 | // 5 | // Created by phylony on 9/11/16. 6 | // Copyright © 2016 phylony. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CameraEncoder.h" 11 | 12 | @interface ViewController : UIViewController{ 13 | CameraEncoder *encoder; 14 | 15 | } 16 | 17 | 18 | @end 19 | 20 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/EasySocket.h: -------------------------------------------------------------------------------- 1 | // 2 | // EasySocket.h 3 | // EasyCamera 4 | // 5 | // Created by yingengyue on 2017/3/18. 6 | // Copyright © 2017年 phylony. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface EasySocket : NSObject 12 | 13 | 14 | /** 15 | * 获取单例 16 | * 17 | * @return 单例对象 18 | */ 19 | + (nullable EasySocket *)sharedInstance; 20 | @end 21 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // EasyCapture 4 | // 5 | // Created by phylony on 9/11/16. 6 | // Copyright © 2016 phylony. 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 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/EasySetingViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // EasySetingViewController.h 3 | // EasyPusher 4 | // 5 | // Created by yingengyue on 2017/1/10. 6 | // Copyright © 2017年 phylony. All rights reserved. 7 | // 8 | 9 | #import 10 | @protocol SetDelegate 11 | 12 | - (void)setFinish; 13 | @end 14 | @interface EasySetingViewController : UIViewController 15 | 16 | @property(assign)iddelegate; 17 | @end 18 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/Assets.xcassets/EasyPusher.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "EasyCamera1.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/Assets.xcassets/ic_action_about.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Info_96px_1180699_easyicon.net.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/Assets.xcassets/EasyClient_iOS_appStore.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "EasyClient_iOS_appStore.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/Assets.xcassets/icn_change_view_pressed.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icn_change_view_pressed.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/Assets.xcassets/video_record_set_off_press.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "video_record_set_off_press.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /EasyCamera_iOS/Encoder/Codec/H264Packet.h: -------------------------------------------------------------------------------- 1 | // 2 | // H264Packet.h 3 | // EasyCapture 4 | // 5 | // Created by phylony on 9/11/16. 6 | // Copyright © 2016 phylony. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface H264Packet : NSObject 13 | 14 | @property (strong, nonatomic) NSMutableData *packet; 15 | @property (assign, nonatomic) BOOL keyFrame; 16 | - (id)initWithCMSampleBuffer:(CMSampleBufferRef)sample; 17 | 18 | - (void)packetizeAVC:(CMSampleBufferRef)sample; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /EasyCamera_iOS/Encoder/EasyResolutionViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // EasyResolutionViewController.h 3 | // EasyPusher 4 | // 5 | // Created by yingengyue on 2017/3/3. 6 | // Copyright © 2017年 phylony. All rights reserved. 7 | // 8 | 9 | #import 10 | @protocol EasyResolutionDelegate 11 | 12 | -(void)onSelecedesolution:(NSInteger)resolutionNo; 13 | 14 | @end 15 | 16 | @interface EasyResolutionViewController : UIViewController 17 | 18 | @property(nonatomic , weak)IBOutlet UITableView *myTabel; 19 | @property(nonatomic , weak)iddelegate; 20 | @end 21 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera.xcodeproj/xcuserdata/yingengyue.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /EasyCamera_iOS/Encoder/Codec/H264HWDecoder.h: -------------------------------------------------------------------------------- 1 | // 2 | // H264HWDecoder.h 3 | // EasyCapture 4 | // 5 | // Created by phylony on 9/11/16. 6 | // Copyright © 2016 phylony. All rights reserved. 7 | // 8 | #import 9 | #import 10 | 11 | @protocol H264HWDecoderDelegate 12 | 13 | - (void)displayDecodedFrame:(CVImageBufferRef)imageBuffer; 14 | 15 | @end 16 | 17 | @interface H264HWDecoder : NSObject 18 | 19 | @property (weak, nonatomic) id delegate; 20 | 21 | -(void) receivedRawVideoFrame:(uint8_t *)frame withSize:(uint32_t)frameSize isIFrame:(int)isIFrame; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera.xcodeproj/xcuserdata/tsinglink.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | EasyPush.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | F6C510291D858306001EB536 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera.xcodeproj/xcuserdata/yingengyue.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | EasyCamera.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | F6C510291D858306001EB536 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EasyCamera # 2 | 3 | ### !!!EasyCamera是配套EasyDarwin云平台使用的,是平台整体的设备部分,类似于萤石、360水滴、小米、i耳目、Dropcam这种云摄像机方案的模式和流程! ### 4 | 5 | 6 | **EasyCamera** 并不是做摄像机硬件方案,或者说EasyCamera是硬件芯片无关的云平台对接方案,我们是在摄像机方案商方案的基础上,通过摄像机方案商提供的SDK在摄像机ARM系统内部与摄像机主服务进行交互,包括实时音视频、云台控制、联动报警等功能,我们在摄像机内部植入EasyCamera程序,一边通过SDK与摄像机主服务交互(获取音视频数据、控制云台、联动报警等交互),一边与EasyDarwin流媒体云平台(EasyCMS、EasyDarwin、EasyRMS等云服务器)对接,上传数据、接受指令控制,形成一套云摄像机方案. 7 | 8 | 9 | ## 获取更多信息 ## 10 | 11 | 邮件:[support@easydarwin.org](mailto:support@easydarwin.org) 12 | 13 | WEB:[www.EasyDarwin.org](http://www.easydarwin.org) 14 | 15 | Copyright © EasyDarwin.org 2012-2017 16 | 17 | ![EasyDarwin](http://www.easydarwin.org/skin/easydarwin/images/wx_qrcode.jpg) 18 | -------------------------------------------------------------------------------- /EasyCamera_iOS/Encoder/Codec/AACEncoder.h: -------------------------------------------------------------------------------- 1 | // 2 | // AACEncoder.h 3 | // EasyCapture 4 | // 5 | // Created by phylony on 9/11/16. 6 | // Copyright © 2016 phylony. All rights reserved. 7 | // 8 | #import 9 | #import 10 | 11 | @protocol AACEncoderDelegate 12 | 13 | @required 14 | - (void)gotAACEncodedData:(NSData *)data timestamp:(CMTime)timestamp error:(NSError*)error; 15 | 16 | @end 17 | 18 | @interface AACEncoder : NSObject 19 | 20 | @property (weak, nonatomic) id delegate; 21 | 22 | @property (nonatomic) dispatch_queue_t encoderQueue; 23 | @property (nonatomic) dispatch_queue_t callbackQueue; 24 | 25 | - (void) encode:(CMSampleBufferRef)sampleBuffer; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /EasyCamera_iOS/Encoder/Codec/H264HWEncoder.h: -------------------------------------------------------------------------------- 1 | // 2 | // H264HWEncoder.h 3 | // EasyCapture 4 | // 5 | // Created by phylony on 9/11/16. 6 | // Copyright © 2016 phylony. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "H264Packet.h" 12 | 13 | @protocol H264HWEncoderDelegate 14 | 15 | @required 16 | - (void)gotH264EncodedData:(NSData *)packet keyFrame:(BOOL)keyFrame timestamp:(CMTime)timestamp error:(NSError*)error; 17 | 18 | @end 19 | 20 | @interface H264HWEncoder : NSObject 21 | { 22 | int _spsppsFound; 23 | unsigned char *_EncoderBuffer; 24 | } 25 | - (void) invalidate; 26 | - (void) setOutputSize:(CGSize)size; 27 | - (void) encode:(CMSampleBufferRef )sampleBuffer; 28 | 29 | @property (weak, nonatomic) id delegate; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/ServerInfoViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ServerInfoViewController.m 3 | // EasyCapture 4 | // 5 | // Created by ChenShun on 2016/11/21. 6 | // Copyright © 2016年 phylony. All rights reserved. 7 | // 8 | 9 | #import "ServerInfoViewController.h" 10 | 11 | @interface ServerInfoViewController () 12 | 13 | @end 14 | 15 | @implementation ServerInfoViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view from its nib. 20 | } 21 | 22 | - (void)didReceiveMemoryWarning { 23 | [super didReceiveMemoryWarning]; 24 | // Dispose of any resources that can be recreated. 25 | } 26 | 27 | /* 28 | #pragma mark - Navigation 29 | 30 | // In a storyboard-based application, you will often want to do a little preparation before navigation 31 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 32 | // Get the new view controller using [segue destinationViewController]. 33 | // Pass the selected object to the new view controller. 34 | } 35 | */ 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/G711/g711codec.h: -------------------------------------------------------------------------------- 1 | /* 2 | * G711 encode decode HEADER. 3 | */ 4 | 5 | #ifndef __G711CODEC_H__ 6 | #define __G711CODEC_H__ 7 | 8 | /* 9 | * u-law, A-law and linear PCM conversions. 10 | */ 11 | #define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */ 12 | #define QUANT_MASK (0xf) /* Quantization field mask. */ 13 | #define NSEGS (8) /* Number of A-law segments. */ 14 | #define SEG_SHIFT (4) /* Left shift for segment number. */ 15 | #define SEG_MASK (0x70) /* Segment field mask. */ 16 | #define BIAS (0x84) /* Bias for linear code. */ 17 | 18 | int PCM2G711a( char *InAudioData, char *OutAudioData, int DataLen, int reserve ); 19 | int PCM2G711u( char *InAudioData, char *OutAudioData, int DataLen, int reserve ); 20 | 21 | int G711a2PCM( char *InAudioData, char *OutAudioData, int DataLen, int reserve ); 22 | int G711u2PCM( char *InAudioData, char *OutAudioData, int DataLen, int reserve ); 23 | 24 | int g711a_decode(short amp[], const unsigned char g711a_data[], int g711a_bytes); 25 | 26 | int g711u_decode(short amp[], const unsigned char g711u_data[], int g711u_bytes); 27 | 28 | int g711a_encode(unsigned char g711_data[], const short amp[], int len); 29 | 30 | int g711u_encode(unsigned char g711_data[], const short amp[], int len); 31 | 32 | #endif /* g711codec.h */ 33 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/G711/.svn/pristine/22/2234e5cf25004bedadd35d9aa4eb4544ab862db9.svn-base: -------------------------------------------------------------------------------- 1 | /* 2 | * G711 encode decode HEADER. 3 | */ 4 | 5 | #ifndef __G711CODEC_H__ 6 | #define __G711CODEC_H__ 7 | 8 | /* 9 | * u-law, A-law and linear PCM conversions. 10 | */ 11 | #define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */ 12 | #define QUANT_MASK (0xf) /* Quantization field mask. */ 13 | #define NSEGS (8) /* Number of A-law segments. */ 14 | #define SEG_SHIFT (4) /* Left shift for segment number. */ 15 | #define SEG_MASK (0x70) /* Segment field mask. */ 16 | #define BIAS (0x84) /* Bias for linear code. */ 17 | 18 | int PCM2G711a( char *InAudioData, char *OutAudioData, int DataLen, int reserve ); 19 | int PCM2G711u( char *InAudioData, char *OutAudioData, int DataLen, int reserve ); 20 | 21 | int G711a2PCM( char *InAudioData, char *OutAudioData, int DataLen, int reserve ); 22 | int G711u2PCM( char *InAudioData, char *OutAudioData, int DataLen, int reserve ); 23 | 24 | int g711a_decode(short amp[], const unsigned char g711a_data[], int g711a_bytes); 25 | 26 | int g711u_decode(short amp[], const unsigned char g711u_data[], int g711u_bytes); 27 | 28 | int g711a_encode(unsigned char g711_data[], const short amp[], int len); 29 | 30 | int g711u_encode(unsigned char g711_data[], const short amp[], int len); 31 | 32 | #endif /* g711codec.h */ 33 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/EasyDarwinInfoViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // EasyDarwinInfoViewController.m 3 | // EasyPusher 4 | // 5 | // Created by yingengyue on 2017/3/4. 6 | // Copyright © 2017年 phylony. All rights reserved. 7 | // 8 | 9 | #import "EasyDarwinInfoViewController.h" 10 | 11 | @interface EasyDarwinInfoViewController () 12 | 13 | @end 14 | 15 | @implementation EasyDarwinInfoViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view from its nib. 20 | } 21 | 22 | - (IBAction)gotoShop:(id)sender{ 23 | [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"itms-apps://itunes.apple.com/us/app/easyclient/id1141850816?l=zh&ls=1&mt=8"]]; 24 | } 25 | 26 | - (IBAction)close:(id)sender{ 27 | [self dismissViewControllerAnimated:YES completion:nil]; 28 | } 29 | 30 | - (void)didReceiveMemoryWarning { 31 | [super didReceiveMemoryWarning]; 32 | // Dispose of any resources that can be recreated. 33 | } 34 | 35 | /* 36 | #pragma mark - Navigation 37 | 38 | // In a storyboard-based application, you will often want to do a little preparation before navigation 39 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 40 | // Get the new view controller using [segue destinationViewController]. 41 | // Pass the selected object to the new view controller. 42 | } 43 | */ 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/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 | 25 | 26 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | EasyCamera 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 4 25 | LSRequiresIPhoneOS 26 | 27 | NSCameraUsageDescription 28 | $(EXECUTABLE_NAME) 29 | NSMicrophoneUsageDescription 30 | $(EXECUTABLE_NAME) 31 | UILaunchStoryboardName 32 | LaunchScreen 33 | UIMainStoryboardFile 34 | Main 35 | UIRequiredDeviceCapabilities 36 | 37 | armv7 38 | 39 | UISupportedInterfaceOrientations 40 | 41 | UIInterfaceOrientationPortrait 42 | 43 | UISupportedInterfaceOrientations~ipad 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationPortraitUpsideDown 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/PureLayout/PureLayout.h: -------------------------------------------------------------------------------- 1 | // 2 | // PureLayout.h 3 | // https://github.com/PureLayout/PureLayout 4 | // 5 | // Copyright (c) 2014-2015 Tyler Fox 6 | // 7 | // This code is distributed under the terms and conditions of the MIT license. 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to 11 | // deal in the Software without restriction, including without limitation the 12 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 13 | // sell copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 25 | // IN THE SOFTWARE. 26 | // 27 | 28 | #ifndef PureLayout_h 29 | #define PureLayout_h 30 | 31 | #import 32 | 33 | //! Project version number for PureLayout. 34 | FOUNDATION_EXPORT double PureLayoutVersionNumber; 35 | 36 | //! Project version string for PureLayout. 37 | FOUNDATION_EXPORT const unsigned char PureLayoutVersionString[]; 38 | 39 | #import "ALView+PureLayout.h" 40 | #import "NSArray+PureLayout.h" 41 | #import "NSLayoutConstraint+PureLayout.h" 42 | 43 | #endif /* PureLayout_h */ 44 | -------------------------------------------------------------------------------- /EasyCamera_iOS/Encoder/CameraEncoder.h: -------------------------------------------------------------------------------- 1 | // 2 | // CameraEncoder.h 3 | // EasyCapture 4 | // 5 | // Created by phylony on 9/11/16. 6 | // Copyright © 2016 phylony. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | 13 | #import "H264HWEncoder.h" 14 | 15 | #import 16 | #import "AACEncoder.h" 17 | #import "EasyPusherAPI.h" 18 | @protocol ConnectDelegate 19 | - (void)getConnectStatus:(NSString *)status isFist:(int)tag; 20 | @end 21 | @interface CameraEncoder : NSObject 22 | { 23 | dispatch_queue_t _encodeVideoQueue; 24 | dispatch_queue_t _encodeAudioQueue; 25 | 26 | CMSimpleQueueRef vbuffQueue; 27 | CMSimpleQueueRef abuffQueue; 28 | BOOL running; 29 | } 30 | @property(nonatomic, assign)BOOL running; 31 | 32 | @property (strong, nonatomic) AVCaptureVideoPreviewLayer *previewLayer; 33 | @property (nonatomic, strong) dispatch_queue_t videoQueue; 34 | @property (nonatomic, strong) dispatch_queue_t AudioQueue; 35 | // 负责从 AVCaptureDevice 获得输入数据 36 | @property (nonatomic, strong) AVCaptureDeviceInput *captureDeviceInput; 37 | @property (nonatomic, strong) AVCaptureVideoDataOutput *videoOutput; 38 | @property (nonatomic, strong) AVCaptureConnection *videoConnection; 39 | @property (nonatomic, strong) AVCaptureConnection *audioConnection; 40 | @property (nonatomic, strong) AVCaptureSession *videoCaptureSession; 41 | @property (nonatomic, strong) UIImage *screenShotImage; 42 | @property(nonatomic , weak)iddelegate; 43 | 44 | - (void) initCameraWithOutputSize:(CGSize)size; 45 | - (void)startCapture; 46 | - (void) startCamera:(NSString *)hostUrl; 47 | - (void) stopCamera; 48 | - (void)swapFrontAndBackCameras; 49 | - (void)swapResolution; 50 | @end 51 | 52 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "EasyCamera-7.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "EasyCamera-5.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "EasyCamera-6.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "EasyCamera-3.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "EasyCamera-4.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "EasyCamera-2.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "EasyCamera-1.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "EasyCamera.png", 49 | "scale" : "3x" 50 | }, 51 | { 52 | "idiom" : "ipad", 53 | "size" : "20x20", 54 | "scale" : "1x" 55 | }, 56 | { 57 | "idiom" : "ipad", 58 | "size" : "20x20", 59 | "scale" : "2x" 60 | }, 61 | { 62 | "idiom" : "ipad", 63 | "size" : "29x29", 64 | "scale" : "1x" 65 | }, 66 | { 67 | "idiom" : "ipad", 68 | "size" : "29x29", 69 | "scale" : "2x" 70 | }, 71 | { 72 | "idiom" : "ipad", 73 | "size" : "40x40", 74 | "scale" : "1x" 75 | }, 76 | { 77 | "idiom" : "ipad", 78 | "size" : "40x40", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "idiom" : "ipad", 83 | "size" : "76x76", 84 | "scale" : "1x" 85 | }, 86 | { 87 | "idiom" : "ipad", 88 | "size" : "76x76", 89 | "scale" : "2x" 90 | }, 91 | { 92 | "idiom" : "ipad", 93 | "size" : "83.5x83.5", 94 | "scale" : "2x" 95 | } 96 | ], 97 | "info" : { 98 | "version" : 1, 99 | "author" : "xcode" 100 | } 101 | } -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyPusherLib/EasyPusherAPI.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013-2015 EasyDarwin.ORG. All rights reserved. 3 | Github: https://github.com/EasyDarwin 4 | WEChat: EasyDarwin 5 | Website: http://www.easydarwin.org 6 | */ 7 | #ifndef __EasyPusher_H__ 8 | #define __EasyPusher_H__ 9 | 10 | #include "EasyTypes.h" 11 | 12 | #define RTSP_CLIENT_NAME "EasyPusher v1.16.0325" 13 | 14 | 15 | typedef struct __EASY_AV_Frame 16 | { 17 | Easy_U32 u32AVFrameFlag; /* 帧标志 视频 or 音频 */ 18 | Easy_U32 u32AVFrameLen; /* 帧的长度 */ 19 | Easy_U32 u32VFrameType; /* 视频的类型,I帧或P帧 */ 20 | Easy_U8 *pBuffer; /* 数据 */ 21 | Easy_U32 u32TimestampSec; /* 时间戳(秒)*/ 22 | Easy_U32 u32TimestampUsec; /* 时间戳(微秒) */ 23 | }EASY_AV_Frame; 24 | 25 | /* 推送事件类型定义 */ 26 | typedef enum __EASY_PUSH_STATE_T 27 | { 28 | EASY_PUSH_STATE_CONNECTING = 1, /* 连接中 */ 29 | EASY_PUSH_STATE_CONNECTED, /* 连接成功 */ 30 | EASY_PUSH_STATE_CONNECT_FAILED, /* 连接失败 */ 31 | EASY_PUSH_STATE_CONNECT_ABORT, /* 连接异常中断 */ 32 | EASY_PUSH_STATE_PUSHING, /* 推流中 */ 33 | EASY_PUSH_STATE_DISCONNECTED, /* 断开连接 */ 34 | EASY_PUSH_STATE_ERROR 35 | }EASY_PUSH_STATE_T; 36 | 37 | /* 推送回调函数定义 _userptr表示用户自定义数据 */ 38 | typedef int (*EasyPusher_Callback)(int _id, EASY_PUSH_STATE_T _state, EASY_AV_Frame *_frame, void *_userptr); 39 | 40 | #ifdef __cplusplus 41 | extern "C" 42 | { 43 | #endif 44 | 45 | Easy_API Easy_I32 Easy_APICALL EasyPusher_Activate(char *license); 46 | 47 | /* 创建推送句柄 返回为句柄值 */ 48 | Easy_API Easy_Pusher_Handle Easy_APICALL EasyPusher_Create(); 49 | 50 | /* 释放推送句柄 */ 51 | Easy_API Easy_U32 Easy_APICALL EasyPusher_Release(Easy_Pusher_Handle handle); 52 | 53 | /* 设置流传输事件回调 userptr传输自定义对象指针*/ 54 | Easy_API Easy_U32 Easy_APICALL EasyPusher_SetEventCallback(Easy_Pusher_Handle handle, EasyPusher_Callback callback, int id, void *userptr); 55 | 56 | /* 开始流传输 serverAddr:流媒体服务器地址、port:流媒体端口、streamName:流名称、username/password:推送携带的用户名密码、pstruStreamInfo:推送的媒体定义、bufferKSize:以k为单位的缓冲区大小<512~2048之间,默认512> bool createlogfile:创建日志文件*/ 57 | Easy_API Easy_U32 Easy_APICALL EasyPusher_StartStream(Easy_Pusher_Handle handle, char* serverAddr, Easy_U16 port, char* streamName, char *username, char *password, EASY_MEDIA_INFO_T* pstruStreamInfo, Easy_U32 bufferKSize, Easy_Bool createlogfile ); 58 | 59 | /* 停止流传输 */ 60 | Easy_API Easy_U32 Easy_APICALL EasyPusher_StopStream(Easy_Pusher_Handle handle); 61 | 62 | /* 推流 frame:具体推送的流媒体帧 */ 63 | Easy_API Easy_U32 Easy_APICALL EasyPusher_PushFrame(Easy_Pusher_Handle handle, EASY_AV_Frame* frame ); 64 | 65 | #ifdef __cplusplus 66 | } 67 | #endif 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyPusherLib/EasyPusherAPI的副本.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013-2015 EasyDarwin.ORG. All rights reserved. 3 | Github: https://github.com/EasyDarwin 4 | WEChat: EasyDarwin 5 | Website: http://www.easydarwin.org 6 | */ 7 | #ifndef __EasyPusher_H__ 8 | #define __EasyPusher_H__ 9 | 10 | #include "EasyTypes.h" 11 | 12 | #define RTSP_CLIENT_NAME "EasyPusher v1.16.0325" 13 | 14 | 15 | typedef struct __EASY_AV_Frame 16 | { 17 | Easy_U32 u32AVFrameFlag; /* 帧标志 视频 or 音频 */ 18 | Easy_U32 u32AVFrameLen; /* 帧的长度 */ 19 | Easy_U32 u32VFrameType; /* 视频的类型,I帧或P帧 */ 20 | Easy_U8 *pBuffer; /* 数据 */ 21 | Easy_U32 u32TimestampSec; /* 时间戳(秒)*/ 22 | Easy_U32 u32TimestampUsec; /* 时间戳(微秒) */ 23 | }EASY_AV_Frame; 24 | 25 | /* 推送事件类型定义 */ 26 | typedef enum __EASY_PUSH_STATE_T 27 | { 28 | EASY_PUSH_STATE_CONNECTING = 1, /* 连接中 */ 29 | EASY_PUSH_STATE_CONNECTED, /* 连接成功 */ 30 | EASY_PUSH_STATE_CONNECT_FAILED, /* 连接失败 */ 31 | EASY_PUSH_STATE_CONNECT_ABORT, /* 连接异常中断 */ 32 | EASY_PUSH_STATE_PUSHING, /* 推流中 */ 33 | EASY_PUSH_STATE_DISCONNECTED, /* 断开连接 */ 34 | EASY_PUSH_STATE_ERROR 35 | }EASY_PUSH_STATE_T; 36 | 37 | /* 推送回调函数定义 _userptr表示用户自定义数据 */ 38 | typedef int (*EasyPusher_Callback)(int _id, EASY_PUSH_STATE_T _state, EASY_AV_Frame *_frame, void *_userptr); 39 | 40 | #ifdef __cplusplus 41 | extern "C" 42 | { 43 | #endif 44 | 45 | Easy_API Easy_I32 Easy_APICALL EasyPusher_Activate(char *license); 46 | 47 | /* 创建推送句柄 返回为句柄值 */ 48 | Easy_API Easy_Pusher_Handle Easy_APICALL EasyPusher_Create(); 49 | 50 | /* 释放推送句柄 */ 51 | Easy_API Easy_U32 Easy_APICALL EasyPusher_Release(Easy_Pusher_Handle handle); 52 | 53 | /* 设置流传输事件回调 userptr传输自定义对象指针*/ 54 | Easy_API Easy_U32 Easy_APICALL EasyPusher_SetEventCallback(Easy_Pusher_Handle handle, EasyPusher_Callback callback, int id, void *userptr); 55 | 56 | /* 开始流传输 serverAddr:流媒体服务器地址、port:流媒体端口、streamName:流名称、username/password:推送携带的用户名密码、pstruStreamInfo:推送的媒体定义、bufferKSize:以k为单位的缓冲区大小<512~2048之间,默认512> bool createlogfile:创建日志文件*/ 57 | Easy_API Easy_U32 Easy_APICALL EasyPusher_StartStream(Easy_Pusher_Handle handle, char* serverAddr, Easy_U16 port, char* streamName, char *username, char *password, EASY_MEDIA_INFO_T* pstruStreamInfo, Easy_U32 bufferKSize, Easy_Bool createlogfile ); 58 | 59 | /* 停止流传输 */ 60 | Easy_API Easy_U32 Easy_APICALL EasyPusher_StopStream(Easy_Pusher_Handle handle); 61 | 62 | /* 推流 frame:具体推送的流媒体帧 */ 63 | Easy_API Easy_U32 Easy_APICALL EasyPusher_PushFrame(Easy_Pusher_Handle handle, EASY_AV_Frame* frame ); 64 | 65 | #ifdef __cplusplus 66 | } 67 | #endif 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /EasyCamera_iOS/Encoder/EasyResolutionViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // EasyResolutionViewController.m 3 | // EasyPusher 4 | // 5 | // Created by yingengyue on 2017/3/3. 6 | // Copyright © 2017年 phylony. All rights reserved. 7 | // 8 | 9 | #import "EasyResolutionViewController.h" 10 | 11 | @interface EasyResolutionViewController () 12 | 13 | @property (nonatomic, strong) NSArray *resolutionArray; 14 | @end 15 | 16 | @implementation EasyResolutionViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | // Do any additional setup after loading the view from its nib. 21 | _myTabel.rowHeight = 44.0; 22 | } 23 | 24 | - (NSArray *)resolutionArray{ 25 | if (!_resolutionArray) { 26 | _resolutionArray = @[@"288*352",@"480*640",@"720*1280",@"1080*1920"]; 27 | } 28 | return _resolutionArray; 29 | } 30 | 31 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 32 | return self.resolutionArray.count; 33 | } 34 | 35 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 36 | static NSString *cellIden = @"cell"; 37 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIden]; 38 | if (!cell) { 39 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIden]; 40 | UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, 43.0, 150.0, 1.0)]; 41 | lineView.backgroundColor = [UIColor lightGrayColor]; 42 | [cell.contentView addSubview:lineView]; 43 | } 44 | cell.textLabel.textAlignment = NSTextAlignmentCenter; 45 | cell.textLabel.text = self.resolutionArray[indexPath.row]; 46 | return cell; 47 | } 48 | 49 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 50 | [[NSUserDefaults standardUserDefaults] setObject:self.resolutionArray[indexPath.row] forKey:@"resolition"]; 51 | [[NSUserDefaults standardUserDefaults] synchronize]; 52 | if (_delegate) { 53 | [_delegate onSelecedesolution:indexPath.row]; 54 | } 55 | [self dismissViewControllerAnimated:YES completion:nil]; 56 | } 57 | 58 | - (IBAction)closeView:(id)sender{ 59 | [self dismissViewControllerAnimated:YES completion:nil]; 60 | } 61 | 62 | - (void)didReceiveMemoryWarning { 63 | [super didReceiveMemoryWarning]; 64 | // Dispose of any resources that can be recreated. 65 | } 66 | 67 | /* 68 | #pragma mark - Navigation 69 | 70 | // In a storyboard-based application, you will often want to do a little preparation before navigation 71 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 72 | // Get the new view controller using [segue destinationViewController]. 73 | // Pass the selected object to the new view controller. 74 | } 75 | */ 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/G711/g711.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "g711codec.h" 3 | 4 | /* 5 | * function: convert PCM audio format to g711 alaw/ulaw.(zqj) 6 | * InAudioData: PCM data prepared for encoding to g711 alaw/ulaw. 7 | * OutAudioData: encoded g711 alaw/ulaw. 8 | * DataLen: PCM data size. 9 | * reserve: reserved param, no use. 10 | */ 11 | 12 | /*alaw*/ 13 | int PCM2G711a( char *InAudioData, char *OutAudioData, int DataLen, int reserve ) 14 | { 15 | //check params. 16 | if( (NULL == InAudioData) && (NULL == OutAudioData) && (0 == DataLen) ) 17 | { 18 | // printf("Error, empty data or transmit failed, exit !\n"); 19 | return -1; 20 | } 21 | // printf("DataLen = %d, %s, %d\n", DataLen, __func__, __LINE__); 22 | 23 | int Retaen = 0; 24 | // printf("G711a encode start......\n"); 25 | Retaen = g711a_encode( (unsigned char *)OutAudioData, (short*)InAudioData, DataLen/2 ); 26 | // printf("Retaen = %d, %s, %d\n", Retaen, __func__, __LINE__); 27 | 28 | return Retaen; //index successfully encoded data len. 29 | } 30 | 31 | /*ulaw*/ 32 | int PCM2G711u( char *InAudioData, char *OutAudioData, int DataLen, int reserve ) 33 | { 34 | //check params. 35 | if( (NULL == InAudioData) && (NULL == OutAudioData) && (0 == DataLen) ) 36 | { 37 | // printf("Error, empty data or transmit failed, exit !\n"); 38 | return -1; 39 | } 40 | // printf("DataLen = %d, %s, %d\n", DataLen, __func__, __LINE__); 41 | 42 | int Retuen = 0; 43 | // printf("G711u encode start......\n"); 44 | Retuen = g711u_encode( (unsigned char *)OutAudioData, (short*)InAudioData, DataLen/2 ); 45 | // printf("Retuen = %d, %s, %d\n", Retuen, __func__, __LINE__); 46 | 47 | return Retuen; 48 | } 49 | 50 | /* 51 | * function: convert g711 alaw audio format to PCM.(zqj) 52 | * InAudioData: g711 alaw data prepared for encoding to PCM. 53 | * OutAudioData: encoded PCM audio data. 54 | * DataLen: g711a data size. 55 | * reserve: reserved param, no use. 56 | */ 57 | 58 | /*alaw*/ 59 | int G711a2PCM( char *InAudioData, char *OutAudioData, int DataLen, int reserve ) 60 | { 61 | //check param. 62 | if( (NULL == InAudioData) && (NULL == OutAudioData) && (0 == DataLen) ) 63 | { 64 | // printf("Error, empty data or transmit failed, exit !\n"); 65 | return -1; 66 | } 67 | // printf("DataLen = %d, %s, %d\n", DataLen, __func__, __LINE__); 68 | 69 | int Retade = 0; 70 | // printf("G711a decode start......\n"); 71 | Retade = g711a_decode( (short*)OutAudioData, (unsigned char *)InAudioData, DataLen ); 72 | // printf("Retade = %d, %s, %d\n", Retade, __func__, __LINE__); 73 | 74 | return Retade; //index successfully decoded data len. 75 | } 76 | 77 | /*ulaw*/ 78 | int G711u2PCM( char *InAudioData, char *OutAudioData, int DataLen, int reserve ) 79 | { 80 | //check param. 81 | if( (NULL == InAudioData) && (NULL == OutAudioData) && (0 == DataLen) ) 82 | { 83 | // printf("Error, empty data or transmit failed, exit !\n"); 84 | return -1; 85 | } 86 | // printf("DataLen = %d, %s, %d\n", DataLen, __func__, __LINE__); 87 | 88 | int Retude = 0; 89 | // printf("G711u decode start......\n"); 90 | Retude = g711u_decode( (short*)OutAudioData, (unsigned char *)InAudioData, DataLen ); 91 | // printf("Retude = %d, %s, %d\n", Retude, __func__, __LINE__); 92 | 93 | return Retude; 94 | } 95 | 96 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/G711/.svn/pristine/f3/f3df9e67f84a87914d0c26506b3dc742ed60b844.svn-base: -------------------------------------------------------------------------------- 1 | #include 2 | #include "g711codec.h" 3 | 4 | /* 5 | * function: convert PCM audio format to g711 alaw/ulaw.(zqj) 6 | * InAudioData: PCM data prepared for encoding to g711 alaw/ulaw. 7 | * OutAudioData: encoded g711 alaw/ulaw. 8 | * DataLen: PCM data size. 9 | * reserve: reserved param, no use. 10 | */ 11 | 12 | /*alaw*/ 13 | int PCM2G711a( char *InAudioData, char *OutAudioData, int DataLen, int reserve ) 14 | { 15 | //check params. 16 | if( (NULL == InAudioData) && (NULL == OutAudioData) && (0 == DataLen) ) 17 | { 18 | // printf("Error, empty data or transmit failed, exit !\n"); 19 | return -1; 20 | } 21 | // printf("DataLen = %d, %s, %d\n", DataLen, __func__, __LINE__); 22 | 23 | int Retaen = 0; 24 | // printf("G711a encode start......\n"); 25 | Retaen = g711a_encode( (unsigned char *)OutAudioData, (short*)InAudioData, DataLen/2 ); 26 | // printf("Retaen = %d, %s, %d\n", Retaen, __func__, __LINE__); 27 | 28 | return Retaen; //index successfully encoded data len. 29 | } 30 | 31 | /*ulaw*/ 32 | int PCM2G711u( char *InAudioData, char *OutAudioData, int DataLen, int reserve ) 33 | { 34 | //check params. 35 | if( (NULL == InAudioData) && (NULL == OutAudioData) && (0 == DataLen) ) 36 | { 37 | // printf("Error, empty data or transmit failed, exit !\n"); 38 | return -1; 39 | } 40 | // printf("DataLen = %d, %s, %d\n", DataLen, __func__, __LINE__); 41 | 42 | int Retuen = 0; 43 | // printf("G711u encode start......\n"); 44 | Retuen = g711u_encode( (unsigned char *)OutAudioData, (short*)InAudioData, DataLen/2 ); 45 | // printf("Retuen = %d, %s, %d\n", Retuen, __func__, __LINE__); 46 | 47 | return Retuen; 48 | } 49 | 50 | /* 51 | * function: convert g711 alaw audio format to PCM.(zqj) 52 | * InAudioData: g711 alaw data prepared for encoding to PCM. 53 | * OutAudioData: encoded PCM audio data. 54 | * DataLen: g711a data size. 55 | * reserve: reserved param, no use. 56 | */ 57 | 58 | /*alaw*/ 59 | int G711a2PCM( char *InAudioData, char *OutAudioData, int DataLen, int reserve ) 60 | { 61 | //check param. 62 | if( (NULL == InAudioData) && (NULL == OutAudioData) && (0 == DataLen) ) 63 | { 64 | // printf("Error, empty data or transmit failed, exit !\n"); 65 | return -1; 66 | } 67 | // printf("DataLen = %d, %s, %d\n", DataLen, __func__, __LINE__); 68 | 69 | int Retade = 0; 70 | // printf("G711a decode start......\n"); 71 | Retade = g711a_decode( (short*)OutAudioData, (unsigned char *)InAudioData, DataLen ); 72 | // printf("Retade = %d, %s, %d\n", Retade, __func__, __LINE__); 73 | 74 | return Retade; //index successfully decoded data len. 75 | } 76 | 77 | /*ulaw*/ 78 | int G711u2PCM( char *InAudioData, char *OutAudioData, int DataLen, int reserve ) 79 | { 80 | //check param. 81 | if( (NULL == InAudioData) && (NULL == OutAudioData) && (0 == DataLen) ) 82 | { 83 | // printf("Error, empty data or transmit failed, exit !\n"); 84 | return -1; 85 | } 86 | // printf("DataLen = %d, %s, %d\n", DataLen, __func__, __LINE__); 87 | 88 | int Retude = 0; 89 | // printf("G711u decode start......\n"); 90 | Retude = g711u_decode( (short*)OutAudioData, (unsigned char *)InAudioData, DataLen ); 91 | // printf("Retude = %d, %s, %d\n", Retude, __func__, __LINE__); 92 | 93 | return Retude; 94 | } 95 | 96 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // EasyCapture 4 | // 5 | // Created by phylony on 9/11/16. 6 | // Copyright © 2016 phylony. 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 | [application setIdleTimerDisabled:YES]; 21 | [[NSUserDefaults standardUserDefaults] setObject:@"cloud.easydarwin.org" forKey:@"ConfigIP"]; 22 | [[NSUserDefaults standardUserDefaults] setObject:@"10000" forKey:@"ConfigPORT"]; 23 | [[NSUserDefaults standardUserDefaults] setObject:@"480*640" forKey:@"resolition"]; 24 | [[NSUserDefaults standardUserDefaults] synchronize]; 25 | 26 | NSArray *array = [[NSUserDefaults standardUserDefaults] objectForKey:@"defaultConfig"]; 27 | if (!array) { 28 | NSMutableString *randomNum = [[NSMutableString alloc] init]; 29 | for(int i = 0; i < 13;i++){ 30 | int num = arc4random() % 10; 31 | [randomNum appendString:[NSString stringWithFormat:@"%d",num]]; 32 | } 33 | NSString* userPhoneName = [[UIDevice currentDevice] name]; 34 | NSArray *configArray = @[@"cloud.easydarwin.org",@"10000",randomNum,userPhoneName,@"000000",@"iOS",@"30"]; 35 | [[NSUserDefaults standardUserDefaults] setObject:configArray forKey:@"defaultConfig"]; 36 | // [[NSUserDefaults standardUserDefaults] setObject:@"192.168.66.108" forKey:@"ConfigIP"]; 37 | // [[NSUserDefaults standardUserDefaults] setObject:@"554" forKey:@"ConfigPORT"]; 38 | [[NSUserDefaults standardUserDefaults] synchronize]; 39 | } 40 | 41 | return YES; 42 | } 43 | 44 | - (void)applicationWillResignActive:(UIApplication *)application { 45 | // 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. 46 | // 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. 47 | } 48 | 49 | - (void)applicationDidEnterBackground:(UIApplication *)application { 50 | // 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. 51 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 52 | } 53 | 54 | - (void)applicationWillEnterForeground:(UIApplication *)application { 55 | // 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. 56 | } 57 | 58 | - (void)applicationDidBecomeActive:(UIApplication *)application { 59 | // 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. 60 | } 61 | 62 | - (void)applicationWillTerminate:(UIApplication *)application { 63 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera.xcodeproj/xcuserdata/tsinglink.xcuserdatad/xcschemes/EasyPush.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 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera.xcodeproj/xcuserdata/yingengyue.xcuserdatad/xcschemes/EasyCamera.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 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/PureLayout/NSLayoutConstraint+PureLayout.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSLayoutConstraint+PureLayout.h 3 | // https://github.com/PureLayout/PureLayout 4 | // 5 | // Copyright (c) 2013-2015 Tyler Fox 6 | // 7 | // This code is distributed under the terms and conditions of the MIT license. 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to 11 | // deal in the Software without restriction, including without limitation the 12 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 13 | // sell copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 25 | // IN THE SOFTWARE. 26 | // 27 | 28 | #import "PureLayoutDefines.h" 29 | 30 | 31 | PL__ASSUME_NONNULL_BEGIN 32 | 33 | #pragma mark NSLayoutConstraint+PureLayout 34 | 35 | /** 36 | A category on NSLayoutConstraint that allows constraints to be easily installed & removed. 37 | */ 38 | @interface NSLayoutConstraint (PureLayout) 39 | 40 | 41 | #pragma mark Batch Constraint Creation 42 | 43 | /** Creates all of the constraints in the block, then installs (activates) them all at once. 44 | All constraints created from calls to the PureLayout API in the block are returned in a single array. 45 | This may be more efficient than installing (activating) each constraint one-by-one. */ 46 | + (PL__NSArray_of(NSLayoutConstraint *) *)autoCreateAndInstallConstraints:(ALConstraintsBlock)block; 47 | 48 | /** Creates all of the constraints in the block but prevents them from being automatically installed (activated). 49 | All constraints created from calls to the PureLayout API in the block are returned in a single array. */ 50 | + (PL__NSArray_of(NSLayoutConstraint *) *)autoCreateConstraintsWithoutInstalling:(ALConstraintsBlock)block; 51 | 52 | 53 | #pragma mark Set Priority For Constraints 54 | 55 | /** Sets the constraint priority to the given value for all constraints created using the PureLayout API within the given constraints block. 56 | NOTE: This method will have no effect (and will NOT set the priority) on constraints created or added without using the PureLayout API! */ 57 | + (void)autoSetPriority:(ALLayoutPriority)priority forConstraints:(ALConstraintsBlock)block; 58 | 59 | 60 | #pragma mark Identify Constraints 61 | 62 | #if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 63 | 64 | /** Sets the identifier for all constraints created using the PureLayout API within the given constraints block. 65 | NOTE: This method will have no effect (and will NOT set the identifier) on constraints created or added without using the PureLayout API! */ 66 | + (void)autoSetIdentifier:(NSString *)identifier forConstraints:(ALConstraintsBlock)block; 67 | 68 | /** Sets the string as the identifier for this constraint. Available in iOS 7.0 and OS X 10.9 and later. */ 69 | - (instancetype)autoIdentify:(NSString *)identifier; 70 | 71 | #endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */ 72 | 73 | 74 | #pragma mark Install & Remove Constraints 75 | 76 | /** Activates the the constraint. */ 77 | - (void)autoInstall; 78 | 79 | /** Deactivates the constraint. */ 80 | - (void)autoRemove; 81 | 82 | @end 83 | 84 | PL__ASSUME_NONNULL_END 85 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/PureLayout/PureLayout+Internal.h: -------------------------------------------------------------------------------- 1 | // 2 | // PureLayout+Internal.h 3 | // https://github.com/PureLayout/PureLayout 4 | // 5 | // Copyright (c) 2014-2015 Tyler Fox 6 | // 7 | // This code is distributed under the terms and conditions of the MIT license. 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to 11 | // deal in the Software without restriction, including without limitation the 12 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 13 | // sell copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 25 | // IN THE SOFTWARE. 26 | // 27 | 28 | #import "PureLayoutDefines.h" 29 | 30 | 31 | // Using generics with NSMutableArray is so common in the internal implementation of PureLayout that it gets a dedicated preprocessor macro for better readability. 32 | #define __NSMutableArray_of(type) PL__GENERICS(NSMutableArray, type) 33 | 34 | PL__ASSUME_NONNULL_BEGIN 35 | 36 | /** A constant that represents the smallest valid positive value for the multiplier of a constraint, 37 | since a value of 0 will cause the second item to be lost in the internal auto layout engine. */ 38 | static const CGFloat kMULTIPLIER_MIN_VALUE = (CGFloat)0.00001; // very small floating point numbers (e.g. CGFLOAT_MIN) can cause problems 39 | 40 | 41 | /** 42 | A category that exposes the internal (private) helper methods of the ALView+PureLayout category. 43 | */ 44 | @interface ALView (PureLayoutInternal) 45 | 46 | - (void)al_addConstraint:(NSLayoutConstraint *)constraint; 47 | - (ALView *)al_commonSuperviewWithView:(ALView *)otherView; 48 | - (NSLayoutConstraint *)al_alignAttribute:(ALAttribute)attribute toView:(ALView *)otherView forAxis:(ALAxis)axis; 49 | 50 | @end 51 | 52 | 53 | /** 54 | A category that exposes the internal (private) helper methods of the NSArray+PureLayout category. 55 | */ 56 | @interface NSArray (PureLayoutInternal) 57 | 58 | - (ALView *)al_commonSuperviewOfViews; 59 | - (BOOL)al_containsMinimumNumberOfViews:(NSUInteger)minimumNumberOfViews; 60 | - (PL__NSArray_of(ALView *) *)al_copyViewsOnly; 61 | 62 | @end 63 | 64 | 65 | /** 66 | A category that exposes the internal (private) helper methods of the NSLayoutConstraint+PureLayout category. 67 | */ 68 | @interface NSLayoutConstraint (PureLayoutInternal) 69 | 70 | + (BOOL)al_preventAutomaticConstraintInstallation; 71 | + (__NSMutableArray_of(NSLayoutConstraint *) *)al_currentArrayOfCreatedConstraints; 72 | + (BOOL)al_isExecutingPriorityConstraintsBlock; 73 | + (ALLayoutPriority)al_currentGlobalConstraintPriority; 74 | #if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 75 | + (NSString *)al_currentGlobalConstraintIdentifier; 76 | #endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */ 77 | + (void)al_applyGlobalStateToConstraint:(NSLayoutConstraint *)constraint; 78 | + (NSLayoutAttribute)al_layoutAttributeForAttribute:(ALAttribute)attribute; 79 | + (ALLayoutConstraintAxis)al_constraintAxisForAxis:(ALAxis)axis; 80 | #if PL__PureLayout_MinBaseSDK_iOS_8_0 81 | + (ALMargin)al_marginForEdge:(ALEdge)edge; 82 | + (ALMarginAxis)al_marginAxisForAxis:(ALAxis)axis; 83 | #endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ 84 | 85 | @end 86 | 87 | PL__ASSUME_NONNULL_END 88 | -------------------------------------------------------------------------------- /EasyCamera_iOS/Encoder/EasyResolutionViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /EasyCamera_iOS/Encoder/Codec/H264Packet.m: -------------------------------------------------------------------------------- 1 | // 2 | // H264Packet.m 3 | // EasyCapture 4 | // 5 | // Created by phylony on 9/11/16. 6 | // Copyright © 2016 phylony. All rights reserved. 7 | // 8 | 9 | #import "H264Packet.h" 10 | 11 | @interface H264Packet () 12 | { 13 | } 14 | 15 | @end 16 | 17 | @implementation H264Packet 18 | 19 | - (id)initWithCMSampleBuffer:(CMSampleBufferRef)sample 20 | { 21 | self = [super init]; 22 | if(self) 23 | { 24 | [self packetizeAVC:sample]; 25 | } 26 | return self; 27 | } 28 | 29 | - (void)packetizeAVC:(CMSampleBufferRef)sample 30 | { 31 | self.packet = [NSMutableData data]; 32 | 33 | NSData *sps, *pps; 34 | 35 | CFDictionaryRef ref = (CFDictionaryRef)CFArrayGetValueAtIndex(CMSampleBufferGetSampleAttachmentsArray(sample, true), 0); 36 | // 判断当前帧是否为关键帧 37 | bool keyframe = !CFDictionaryContainsKey(ref , kCMSampleAttachmentKey_NotSync); 38 | 39 | int resultLen = 0; 40 | if (keyframe) 41 | { 42 | CMFormatDescriptionRef format = CMSampleBufferGetFormatDescription(sample); 43 | 44 | size_t sparameterSetSize, sparameterSetCount; 45 | const uint8_t *sparameterSet; 46 | OSStatus statusCode = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(format, 0, &sparameterSet, &sparameterSetSize, &sparameterSetCount, 0 ); 47 | if (statusCode == noErr) 48 | { 49 | // Found sps and now check for pps 50 | size_t pparameterSetSize, pparameterSetCount; 51 | const uint8_t *pparameterSet; 52 | OSStatus statusCode = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(format, 1, &pparameterSet, &pparameterSetSize, &pparameterSetCount, 0 ); 53 | if (statusCode == noErr) 54 | { 55 | // Found pps 56 | sps = [NSData dataWithBytes:sparameterSet length:sparameterSetSize]; 57 | pps = [NSData dataWithBytes:pparameterSet length:pparameterSetSize]; 58 | 59 | const char bytes[] = {0, 0, 0, 1}; // SPS PPS Header 60 | NSData *byteHeader = [NSData dataWithBytes:bytes length:4]; 61 | NSMutableData *fullSPSData = [NSMutableData dataWithData:byteHeader]; 62 | NSMutableData *fullPPSData = [NSMutableData dataWithData:byteHeader]; 63 | 64 | [fullSPSData appendData:sps]; 65 | [fullPPSData appendData:pps]; 66 | 67 | sps = fullSPSData; 68 | pps = fullPPSData; 69 | 70 | [self.packet appendData:sps]; 71 | [self.packet appendData:pps]; 72 | 73 | resultLen += 8 + sparameterSetSize + pparameterSetSize; 74 | } 75 | } 76 | } 77 | 78 | CMBlockBufferRef dataBuffer = CMSampleBufferGetDataBuffer(sample); 79 | size_t totalLength; 80 | char *dataPointer; 81 | OSStatus statusCodeRet = CMBlockBufferGetDataPointer(dataBuffer, 0, NULL, &totalLength, &dataPointer); 82 | if (statusCodeRet == noErr) { 83 | 84 | size_t bufferOffset = 0; 85 | static const int AVCCHeaderLength = 4; 86 | while (bufferOffset < totalLength - AVCCHeaderLength) { 87 | // Read the NAL unit length 88 | uint32_t NALUnitLength = 0; 89 | memcpy(&NALUnitLength, dataPointer + bufferOffset, AVCCHeaderLength); 90 | 91 | // Convert the length value from Big-endian to Little-endian 92 | NALUnitLength = CFSwapInt32BigToHost(NALUnitLength); 93 | 94 | NSData* data = [[NSData alloc] initWithBytes:(dataPointer + bufferOffset + AVCCHeaderLength) length:NALUnitLength]; 95 | 96 | const char bytes[] = {0, 0, 0, 1}; // SPS PPS Header 97 | NSData *byteHeader = [NSData dataWithBytes:bytes length:4]; 98 | NSMutableData *fullAVCData = [NSMutableData dataWithData:byteHeader]; 99 | [fullAVCData appendData:data]; 100 | 101 | [self.packet appendData:fullAVCData]; 102 | 103 | // Move to the next NAL unit in the block buffer 104 | bufferOffset += AVCCHeaderLength + NALUnitLength; 105 | resultLen += AVCCHeaderLength + NALUnitLength; 106 | } 107 | } 108 | self.keyFrame = keyframe; 109 | } 110 | 111 | @end 112 | -------------------------------------------------------------------------------- /EasyCamera_iOS/Encoder/Codec/H264HWEncoder.m: -------------------------------------------------------------------------------- 1 | // 2 | // H264HWEncoder.m 3 | // EasyCapture 4 | // 5 | // Created by phylony on 9/11/16. 6 | // Copyright © 2016 phylony. All rights reserved. 7 | // 8 | 9 | #import "H264HWEncoder.h" 10 | 11 | @import VideoToolbox; 12 | @import AVFoundation; 13 | 14 | @implementation H264HWEncoder 15 | { 16 | VTCompressionSessionRef session; 17 | CGSize outputSize; 18 | } 19 | 20 | - (void) dealloc { 21 | [self invalidate]; 22 | } 23 | 24 | - (id) init { 25 | if (self = [super init]) { 26 | session = NULL; 27 | outputSize = CGSizeMake(1920, 1080); 28 | } 29 | return self; 30 | } 31 | 32 | void didCompressH264(void *outputCallbackRefCon, void *sourceFrameRefCon, OSStatus status, VTEncodeInfoFlags infoFlags, 33 | CMSampleBufferRef sampleBuffer ) 34 | { 35 | H264HWEncoder* encoder = (__bridge H264HWEncoder*)outputCallbackRefCon; 36 | 37 | if (status == noErr) { 38 | return [encoder didReceiveSampleBuffer:sampleBuffer]; 39 | } 40 | 41 | NSLog(@"Error %d : %@", infoFlags, [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]); 42 | } 43 | 44 | - (void)didReceiveSampleBuffer:(CMSampleBufferRef)sampleBuffer { 45 | if (!sampleBuffer) { 46 | return; 47 | } 48 | 49 | CMTime timestamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer); 50 | H264Packet *packet = [[H264Packet alloc] initWithCMSampleBuffer:sampleBuffer]; 51 | 52 | if (self.delegate != nil) { 53 | [self.delegate gotH264EncodedData:packet.packet keyFrame:packet.keyFrame timestamp:timestamp error:nil]; 54 | } 55 | } 56 | 57 | - (void) setOutputSize:(CGSize)size 58 | { 59 | outputSize = size; 60 | } 61 | 62 | - (void) initSession 63 | { 64 | CFMutableDictionaryRef encoderSpecifications = NULL; 65 | 66 | NSString *resolution = [[NSUserDefaults standardUserDefaults] objectForKey:@"resolition"]; 67 | NSArray *resolutionArray = [resolution componentsSeparatedByString:@"*"]; 68 | int width = [resolutionArray[0] intValue]; 69 | int height = [resolutionArray[1] intValue]; 70 | OSStatus status = VTCompressionSessionCreate(kCFAllocatorDefault, width , height, kCMVideoCodecType_H264, NULL, NULL, NULL, didCompressH264, (__bridge void *)(self), &session); 71 | if (status == noErr) 72 | { 73 | int fps = 25; 74 | int bt = 640 * 1000; 75 | 76 | // 设置编码码率(比特率),如果不设置,默认将会以很低的码率编码,导致编码出来的视频很模糊 77 | status = VTSessionSetProperty(session, kVTCompressionPropertyKey_AverageBitRate, (__bridge CFTypeRef)@(bt)); // bps 78 | status += VTSessionSetProperty(session, kVTCompressionPropertyKey_DataRateLimits, (__bridge CFArrayRef)@[@(bt*2/8), @1]); // Bps 79 | NSLog(@"set bitrate return: %d", (int)status); 80 | 81 | const int32_t v = fps * 2; // 2-second kfi 82 | CFNumberRef ref = CFNumberCreate(NULL, kCFNumberSInt32Type, &v); 83 | VTSessionSetProperty(session, kVTCompressionPropertyKey_MaxKeyFrameInterval, ref); 84 | CFRelease(ref); 85 | 86 | ref = CFNumberCreate(NULL, kCFNumberSInt32Type, &fps); 87 | OSStatus ret = VTSessionSetProperty(session, kVTCompressionPropertyKey_ExpectedFrameRate, ref); 88 | CFRelease(ref); 89 | 90 | VTSessionSetProperty(session, kVTCompressionPropertyKey_RealTime, kCFBooleanTrue); 91 | VTSessionSetProperty(session, kVTCompressionPropertyKey_ProfileLevel, kVTProfileLevel_H264_Baseline_AutoLevel); 92 | 93 | // 开始编码 94 | status = VTCompressionSessionPrepareToEncodeFrames(session); 95 | NSLog(@"start encode return: %d", (int)status); 96 | 97 | } 98 | } 99 | 100 | - (void) invalidate 101 | { 102 | if(session) 103 | { 104 | VTCompressionSessionCompleteFrames(session, kCMTimeInvalid); 105 | VTCompressionSessionInvalidate(session); 106 | CFRelease(session); 107 | session = NULL; 108 | } 109 | } 110 | 111 | - (void) encode:(CMSampleBufferRef )sampleBuffer 112 | { 113 | CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 114 | 115 | if(session == NULL) 116 | { 117 | [self initSession]; 118 | } 119 | 120 | if( session != NULL && sampleBuffer != NULL ) 121 | { 122 | // Create properties 123 | 124 | CMTime timestamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer); 125 | // CMTime pts = CMTimeMake(CMTimeGetSeconds(timestamp), 1000.0); 126 | 127 | VTEncodeInfoFlags flags; 128 | 129 | VTCompressionSessionEncodeFrame(session, imageBuffer, timestamp, kCMTimeInvalid, NULL, NULL, &flags); 130 | } 131 | } 132 | 133 | @end 134 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/G711/g711codec.c: -------------------------------------------------------------------------------- 1 | #include "g711codec.h" 2 | 3 | static short seg_end[8] = {0xFF, 0x1FF, 0x3FF, 0x7FF, 4 | 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF}; 5 | 6 | static int search(int val, short *table, int size) 7 | { 8 | int i; 9 | 10 | for (i = 0; i < size; i++) { 11 | if (val <= *table++) 12 | return (i); 13 | } 14 | return (size); 15 | } 16 | 17 | /* 18 | * alaw2linear() - Convert an A-law value to 16-bit linear PCM 19 | * 20 | */ 21 | static int alaw2linear( unsigned char a_val ) 22 | { 23 | int t; 24 | int seg; 25 | 26 | a_val ^= 0x55; 27 | 28 | t = (a_val & QUANT_MASK) << 4; 29 | seg = ( (unsigned)a_val & SEG_MASK ) >> SEG_SHIFT; 30 | switch (seg) 31 | { 32 | case 0: 33 | t += 8; 34 | break; 35 | case 1: 36 | t += 0x108; 37 | break; 38 | default: 39 | t += 0x108; 40 | t <<= seg - 1; 41 | } 42 | return ((a_val & SIGN_BIT) ? t : -t); 43 | } 44 | 45 | 46 | /* 47 | * ulaw2linear() - Convert a u-law value to 16-bit linear PCM 48 | * 49 | * First, a biased linear code is derived from the code word. An unbiased 50 | * output can then be obtained by subtracting 33 from the biased code. 51 | * 52 | * Note that this function expects to be passed the complement of the 53 | * original code word. This is in keeping with ISDN conventions. 54 | */ 55 | static int ulaw2linear(unsigned char u_val) 56 | { 57 | int t; 58 | 59 | /* Complement to obtain normal u-law value. */ 60 | u_val = ~u_val; 61 | 62 | /* 63 | * Extract and bias the quantization bits. Then 64 | * shift up by the segment number and subtract out the bias. 65 | */ 66 | t = ((u_val & QUANT_MASK) << 3) + BIAS; 67 | t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT; 68 | 69 | return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS)); 70 | } 71 | 72 | 73 | /* 74 | * linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law 75 | * 76 | */ 77 | unsigned char linear2alaw(int pcm_val) /* 2's complement (16-bit range) */ 78 | { 79 | int mask; 80 | int seg; 81 | unsigned char aval; 82 | 83 | if (pcm_val >= 0) { 84 | mask = 0xD5; /* sign (7th) bit = 1 */ 85 | } else { 86 | mask = 0x55; /* sign bit = 0 */ 87 | pcm_val = -pcm_val - 8; 88 | } 89 | 90 | /* Convert the scaled magnitude to segment number. */ 91 | seg = search(pcm_val, seg_end, 8); 92 | 93 | /* Combine the sign, segment, and quantization bits. */ 94 | 95 | if (seg >= 8) /* out of range, return maximum value. */ 96 | return (0x7F ^ mask); 97 | else { 98 | aval = seg << SEG_SHIFT; 99 | if (seg < 2) 100 | aval |= (pcm_val >> 4) & QUANT_MASK; 101 | else 102 | aval |= (pcm_val >> (seg + 3)) & QUANT_MASK; 103 | return (aval ^ mask); 104 | } 105 | } 106 | 107 | 108 | /* 109 | * linear2ulaw() - Convert a linear PCM value to u-law 110 | * 111 | */ 112 | unsigned char linear2ulaw(int pcm_val) /* 2's complement (16-bit range) */ 113 | { 114 | int mask; 115 | int seg; 116 | unsigned char uval; 117 | 118 | /* Get the sign and the magnitude of the value. */ 119 | if (pcm_val < 0) { 120 | pcm_val = BIAS - pcm_val; 121 | mask = 0x7F; 122 | } else { 123 | pcm_val += BIAS; 124 | mask = 0xFF; 125 | } 126 | 127 | /* Convert the scaled magnitude to segment number. */ 128 | seg = search(pcm_val, seg_end, 8); 129 | 130 | /* 131 | * Combine the sign, segment, quantization bits; 132 | * and complement the code word. 133 | */ 134 | if (seg >= 8) /* out of range, return maximum value. */ 135 | return (0x7F ^ mask); 136 | else { 137 | uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0xF); 138 | return (uval ^ mask); 139 | } 140 | } 141 | 142 | 143 | int g711a_decode( short amp[], const unsigned char g711a_data[], int g711a_bytes ) 144 | { 145 | int i; 146 | int samples; 147 | unsigned char code; 148 | int sl; 149 | 150 | for ( samples = i = 0; ; ) 151 | { 152 | if (i >= g711a_bytes) 153 | break; 154 | code = g711a_data[i++]; 155 | 156 | sl = alaw2linear( code ); 157 | 158 | amp[samples++] = (short) sl; 159 | } 160 | return samples*2; 161 | } 162 | 163 | int g711u_decode(short amp[], const unsigned char g711u_data[], int g711u_bytes) 164 | { 165 | int i; 166 | int samples; 167 | unsigned char code; 168 | int sl; 169 | 170 | for (samples = i = 0;;) 171 | { 172 | if (i >= g711u_bytes) 173 | break; 174 | code = g711u_data[i++]; 175 | 176 | sl = ulaw2linear(code); 177 | 178 | amp[samples++] = (short) sl; 179 | } 180 | return samples*2; 181 | } 182 | 183 | int g711a_encode(unsigned char g711_data[], const short amp[], int len) 184 | { 185 | int i; 186 | 187 | for (i = 0; i < len; i++) 188 | { 189 | g711_data[i] = linear2alaw(amp[i]); 190 | } 191 | 192 | return len; 193 | } 194 | 195 | int g711u_encode(unsigned char g711_data[], const short amp[], int len) 196 | { 197 | int i; 198 | 199 | for (i = 0; i < len; i++) 200 | { 201 | g711_data[i] = linear2ulaw(amp[i]); 202 | } 203 | 204 | return len; 205 | } 206 | 207 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/G711/.svn/pristine/9b/9bcc65a54b8c5cd1508688da1d9605f9ba0b01f4.svn-base: -------------------------------------------------------------------------------- 1 | #include "g711codec.h" 2 | 3 | static short seg_end[8] = {0xFF, 0x1FF, 0x3FF, 0x7FF, 4 | 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF}; 5 | 6 | static int search(int val, short *table, int size) 7 | { 8 | int i; 9 | 10 | for (i = 0; i < size; i++) { 11 | if (val <= *table++) 12 | return (i); 13 | } 14 | return (size); 15 | } 16 | 17 | /* 18 | * alaw2linear() - Convert an A-law value to 16-bit linear PCM 19 | * 20 | */ 21 | static int alaw2linear( unsigned char a_val ) 22 | { 23 | int t; 24 | int seg; 25 | 26 | a_val ^= 0x55; 27 | 28 | t = (a_val & QUANT_MASK) << 4; 29 | seg = ( (unsigned)a_val & SEG_MASK ) >> SEG_SHIFT; 30 | switch (seg) 31 | { 32 | case 0: 33 | t += 8; 34 | break; 35 | case 1: 36 | t += 0x108; 37 | break; 38 | default: 39 | t += 0x108; 40 | t <<= seg - 1; 41 | } 42 | return ((a_val & SIGN_BIT) ? t : -t); 43 | } 44 | 45 | 46 | /* 47 | * ulaw2linear() - Convert a u-law value to 16-bit linear PCM 48 | * 49 | * First, a biased linear code is derived from the code word. An unbiased 50 | * output can then be obtained by subtracting 33 from the biased code. 51 | * 52 | * Note that this function expects to be passed the complement of the 53 | * original code word. This is in keeping with ISDN conventions. 54 | */ 55 | static int ulaw2linear(unsigned char u_val) 56 | { 57 | int t; 58 | 59 | /* Complement to obtain normal u-law value. */ 60 | u_val = ~u_val; 61 | 62 | /* 63 | * Extract and bias the quantization bits. Then 64 | * shift up by the segment number and subtract out the bias. 65 | */ 66 | t = ((u_val & QUANT_MASK) << 3) + BIAS; 67 | t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT; 68 | 69 | return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS)); 70 | } 71 | 72 | 73 | /* 74 | * linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law 75 | * 76 | */ 77 | unsigned char linear2alaw(int pcm_val) /* 2's complement (16-bit range) */ 78 | { 79 | int mask; 80 | int seg; 81 | unsigned char aval; 82 | 83 | if (pcm_val >= 0) { 84 | mask = 0xD5; /* sign (7th) bit = 1 */ 85 | } else { 86 | mask = 0x55; /* sign bit = 0 */ 87 | pcm_val = -pcm_val - 8; 88 | } 89 | 90 | /* Convert the scaled magnitude to segment number. */ 91 | seg = search(pcm_val, seg_end, 8); 92 | 93 | /* Combine the sign, segment, and quantization bits. */ 94 | 95 | if (seg >= 8) /* out of range, return maximum value. */ 96 | return (0x7F ^ mask); 97 | else { 98 | aval = seg << SEG_SHIFT; 99 | if (seg < 2) 100 | aval |= (pcm_val >> 4) & QUANT_MASK; 101 | else 102 | aval |= (pcm_val >> (seg + 3)) & QUANT_MASK; 103 | return (aval ^ mask); 104 | } 105 | } 106 | 107 | 108 | /* 109 | * linear2ulaw() - Convert a linear PCM value to u-law 110 | * 111 | */ 112 | unsigned char linear2ulaw(int pcm_val) /* 2's complement (16-bit range) */ 113 | { 114 | int mask; 115 | int seg; 116 | unsigned char uval; 117 | 118 | /* Get the sign and the magnitude of the value. */ 119 | if (pcm_val < 0) { 120 | pcm_val = BIAS - pcm_val; 121 | mask = 0x7F; 122 | } else { 123 | pcm_val += BIAS; 124 | mask = 0xFF; 125 | } 126 | 127 | /* Convert the scaled magnitude to segment number. */ 128 | seg = search(pcm_val, seg_end, 8); 129 | 130 | /* 131 | * Combine the sign, segment, quantization bits; 132 | * and complement the code word. 133 | */ 134 | if (seg >= 8) /* out of range, return maximum value. */ 135 | return (0x7F ^ mask); 136 | else { 137 | uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0xF); 138 | return (uval ^ mask); 139 | } 140 | } 141 | 142 | 143 | int g711a_decode( short amp[], const unsigned char g711a_data[], int g711a_bytes ) 144 | { 145 | int i; 146 | int samples; 147 | unsigned char code; 148 | int sl; 149 | 150 | for ( samples = i = 0; ; ) 151 | { 152 | if (i >= g711a_bytes) 153 | break; 154 | code = g711a_data[i++]; 155 | 156 | sl = alaw2linear( code ); 157 | 158 | amp[samples++] = (short) sl; 159 | } 160 | return samples*2; 161 | } 162 | 163 | int g711u_decode(short amp[], const unsigned char g711u_data[], int g711u_bytes) 164 | { 165 | int i; 166 | int samples; 167 | unsigned char code; 168 | int sl; 169 | 170 | for (samples = i = 0;;) 171 | { 172 | if (i >= g711u_bytes) 173 | break; 174 | code = g711u_data[i++]; 175 | 176 | sl = ulaw2linear(code); 177 | 178 | amp[samples++] = (short) sl; 179 | } 180 | return samples*2; 181 | } 182 | 183 | int g711a_encode(unsigned char g711_data[], const short amp[], int len) 184 | { 185 | int i; 186 | 187 | for (i = 0; i < len; i++) 188 | { 189 | g711_data[i] = linear2alaw(amp[i]); 190 | } 191 | 192 | return len; 193 | } 194 | 195 | int g711u_encode(unsigned char g711_data[], const short amp[], int len) 196 | { 197 | int i; 198 | 199 | for (i = 0; i < len; i++) 200 | { 201 | g711_data[i] = linear2ulaw(amp[i]); 202 | } 203 | 204 | return len; 205 | } 206 | 207 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/EasySetingViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // EasySetingViewController.m 3 | // EasyPusher 4 | // 5 | // Created by yingengyue on 2017/1/10. 6 | // Copyright © 2017年 phylony. All rights reserved. 7 | // 8 | 9 | #import "EasySetingViewController.h" 10 | 11 | @interface EasySetingViewController () 12 | 13 | @end 14 | 15 | @implementation EasySetingViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view. 20 | self.view.backgroundColor = [UIColor whiteColor]; 21 | // UITextField *ipTextField = [[UITextField alloc] initWithFrame:CGRectMake(80, 64, 200.0, 30.0)]; 22 | // ipTextField.tag = 1000; 23 | // ipTextField.delegate = self; 24 | // ipTextField.placeholder = @"EasyCMS IP"; 25 | // ipTextField.text = [[NSUserDefaults standardUserDefaults] objectForKey:@"ConfigIP"]; 26 | // [self.view addSubview:ipTextField]; 27 | // 28 | // UITextField *portTextField = [[UITextField alloc] initWithFrame:CGRectMake(80, 104, 200.0, 30.0)]; 29 | // portTextField.tag = 1001; 30 | // portTextField.text = [[NSUserDefaults standardUserDefaults] objectForKey:@"ConfigPORT"]; 31 | // portTextField.delegate = self; 32 | // portTextField.placeholder = @"EasyCMS Port"; 33 | // [self.view addSubview:portTextField]; 34 | 35 | NSArray *placeArray = @[@"EasyCMS IP",@"EasyCMS Port",@"Device Serial",@"Device Name",@"Device Token",@"Device Tag",@"Keep Alive Interval"]; 36 | NSArray *defaultArray = [[NSUserDefaults standardUserDefaults] objectForKey:@"defaultConfig"]; 37 | for (int i = 0; i < placeArray.count; i ++) { 38 | UITextField *text = [[UITextField alloc] initWithFrame:CGRectMake(20, 64 + 40*i, [UIScreen mainScreen].bounds.size.width - 40, 30.0)]; 39 | text.placeholder = placeArray[i]; 40 | text.text = defaultArray[i]; 41 | text.delegate = self; 42 | text.tag = 10000 + i; 43 | [self.view addSubview:text]; 44 | } 45 | 46 | UIButton *saveBtn = [[UIButton alloc] initWithFrame:CGRectMake(20, 64 + 40 * placeArray.count, [UIScreen mainScreen].bounds.size.width - 40, 40.0)]; 47 | saveBtn.backgroundColor = [UIColor lightGrayColor]; 48 | [saveBtn setTitle:@"保存" forState:UIControlStateNormal]; 49 | [saveBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 50 | [saveBtn addTarget:self action:@selector(saveIpAndPort) forControlEvents:UIControlEventTouchUpInside]; 51 | [self.view addSubview:saveBtn]; 52 | 53 | 54 | UIButton *closeBtn = [[UIButton alloc] initWithFrame:CGRectMake([UIScreen mainScreen].bounds.size.width - 50, 25, 40, 40)]; 55 | [closeBtn setTitle:@"关闭" forState:UIControlStateNormal]; 56 | [closeBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 57 | [closeBtn addTarget:self action:@selector(close:) forControlEvents:UIControlEventTouchUpInside]; 58 | [self.view addSubview:closeBtn]; 59 | } 60 | 61 | - (void)close:(UIButton *)sender{ 62 | __weak typeof(self) weakSelf = self; 63 | UIAlertController *alt = [UIAlertController alertControllerWithTitle:nil message:@"未保存修改,是否退出设置" preferredStyle:UIAlertControllerStyleAlert]; 64 | [alt addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { 65 | [weakSelf.delegate setFinish]; 66 | [weakSelf dismissViewControllerAnimated:YES completion:nil]; 67 | }]]; 68 | [alt addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { 69 | }]]; 70 | [self presentViewController:alt animated:YES completion:nil]; 71 | } 72 | 73 | - (BOOL)textFieldShouldReturn:(UITextField *)textField{ 74 | [textField resignFirstResponder]; 75 | return YES; 76 | } 77 | 78 | - (void)saveIpAndPort{ 79 | [self.view endEditing:YES]; 80 | // UITextField *ipConfig = (UITextField *)[self.view viewWithTag:1000]; 81 | // UITextField *portConfig = (UITextField *)[self.view viewWithTag:1001]; 82 | __weak typeof(self) weakSelf = self; 83 | NSArray *defaultArray = [[NSUserDefaults standardUserDefaults] objectForKey:@"defaultConfig"]; 84 | NSMutableArray *defaultArrayMu = [[NSMutableArray alloc] initWithArray:defaultArray]; 85 | for (int i = 0; i < 7; i++) { 86 | UITextField *text = (UITextField *)[self.view viewWithTag:10000 + i]; 87 | if (![text.text isEqualToString:@""]) { 88 | [defaultArrayMu replaceObjectAtIndex:i withObject:text.text]; 89 | } 90 | } 91 | [[NSUserDefaults standardUserDefaults] setObject:defaultArrayMu forKey:@"defaultConfig"]; 92 | [[NSUserDefaults standardUserDefaults] synchronize]; 93 | [self dismissViewControllerAnimated:YES completion:^{ 94 | [weakSelf.delegate setFinish]; 95 | }]; 96 | } 97 | 98 | - (void)didReceiveMemoryWarning { 99 | [super didReceiveMemoryWarning]; 100 | // Dispose of any resources that can be recreated. 101 | } 102 | 103 | /* 104 | #pragma mark - Navigation 105 | 106 | // In a storyboard-based application, you will often want to do a little preparation before navigation 107 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 108 | // Get the new view controller using [segue destinationViewController]. 109 | // Pass the selected object to the new view controller. 110 | } 111 | */ 112 | 113 | @end 114 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/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 | 29 | 30 | 31 | 37 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/PureLayout/NSArray+PureLayout.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSArray+PureLayout.h 3 | // https://github.com/PureLayout/PureLayout 4 | // 5 | // Copyright (c) 2012 Richard Turton 6 | // Copyright (c) 2013-2015 Tyler Fox 7 | // 8 | // This code is distributed under the terms and conditions of the MIT license. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a copy 11 | // of this software and associated documentation files (the "Software"), to 12 | // deal in the Software without restriction, including without limitation the 13 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 14 | // sell copies of the Software, and to permit persons to whom the Software is 15 | // furnished to do so, subject to the following conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be included in 18 | // all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 26 | // IN THE SOFTWARE. 27 | // 28 | 29 | #import "PureLayoutDefines.h" 30 | 31 | 32 | PL__ASSUME_NONNULL_BEGIN 33 | 34 | #pragma mark NSArray+PureLayout 35 | 36 | /** 37 | A category on NSArray that provides a simple yet powerful interface to: 38 | - Manage an array of Auto Layout constraints 39 | - Apply constraints to an array of views 40 | */ 41 | @interface NSArray (PureLayout) 42 | 43 | 44 | #pragma mark Array of Constraints 45 | 46 | /** Activates the constraints in this array. */ 47 | - (void)autoInstallConstraints; 48 | 49 | /** Deactivates the constraints in this array. */ 50 | - (void)autoRemoveConstraints; 51 | 52 | #if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 53 | 54 | /** Sets the string as the identifier for the constraints in this array. Available in iOS 7.0 and OS X 10.9 and later. */ 55 | - (instancetype)autoIdentifyConstraints:(NSString *)identifier; 56 | 57 | #endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */ 58 | 59 | 60 | #pragma mark Array of Views 61 | 62 | /** Aligns views in this array to one another along a given edge. */ 63 | - (PL__NSArray_of(NSLayoutConstraint *) *)autoAlignViewsToEdge:(ALEdge)edge; 64 | 65 | /** Aligns views in this array to one another along a given axis. */ 66 | - (PL__NSArray_of(NSLayoutConstraint *) *)autoAlignViewsToAxis:(ALAxis)axis; 67 | 68 | /** Matches a given dimension of all the views in this array. */ 69 | - (PL__NSArray_of(NSLayoutConstraint *) *)autoMatchViewsDimension:(ALDimension)dimension; 70 | 71 | /** Sets the given dimension of all the views in this array to a given size. */ 72 | - (PL__NSArray_of(NSLayoutConstraint *) *)autoSetViewsDimension:(ALDimension)dimension toSize:(CGFloat)size; 73 | 74 | /** Sets all of the views in this array to a given size. */ 75 | - (PL__NSArray_of(NSLayoutConstraint *) *)autoSetViewsDimensionsToSize:(CGSize)size; 76 | 77 | 78 | /** Distributes the views in this array equally along the selected axis in their superview. 79 | Views will be the same size (variable) in the dimension along the axis and will have spacing (fixed) between them. */ 80 | - (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis 81 | alignedTo:(ALAttribute)alignment 82 | withFixedSpacing:(CGFloat)spacing; 83 | 84 | /** Distributes the views in this array equally along the selected axis in their superview. 85 | Views will be the same size (variable) in the dimension along the axis and will have spacing (fixed) between them, with optional insets from the first and last views to their superview. */ 86 | - (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis 87 | alignedTo:(ALAttribute)alignment 88 | withFixedSpacing:(CGFloat)spacing 89 | insetSpacing:(BOOL)shouldSpaceInsets; 90 | 91 | /** Distributes the views in this array equally along the selected axis in their superview. 92 | Views will have spacing (fixed) between them, with optional insets from the first and last views to their superview, and optionally constrained to the same size in the dimension along the axis. */ 93 | - (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis 94 | alignedTo:(ALAttribute)alignment 95 | withFixedSpacing:(CGFloat)spacing 96 | insetSpacing:(BOOL)shouldSpaceInsets 97 | matchedSizes:(BOOL)shouldMatchSizes; 98 | 99 | 100 | /** Distributes the views in this array equally along the selected axis in their superview. 101 | Views will be the same size (fixed) in the dimension along the axis and will have spacing (variable) between them. */ 102 | - (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis 103 | alignedTo:(ALAttribute)alignment 104 | withFixedSize:(CGFloat)size; 105 | 106 | /** Distributes the views in this array equally along the selected axis in their superview. 107 | Views will be the same size (fixed) in the dimension along the axis and will have spacing (variable) between them, with optional insets from the first and last views to their superview. */ 108 | - (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis 109 | alignedTo:(ALAttribute)alignment 110 | withFixedSize:(CGFloat)size 111 | insetSpacing:(BOOL)shouldSpaceInsets; 112 | 113 | @end 114 | 115 | PL__ASSUME_NONNULL_END 116 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/ServerInfoViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 42 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 77 | 84 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/PureLayout/ALView+PureLayout.h: -------------------------------------------------------------------------------- 1 | // 2 | // ALView+PureLayout.h 3 | // https://github.com/PureLayout/PureLayout 4 | // 5 | // Copyright (c) 2012 Richard Turton 6 | // Copyright (c) 2013-2015 Tyler Fox 7 | // 8 | // This code is distributed under the terms and conditions of the MIT license. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a copy 11 | // of this software and associated documentation files (the "Software"), to 12 | // deal in the Software without restriction, including without limitation the 13 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 14 | // sell copies of the Software, and to permit persons to whom the Software is 15 | // furnished to do so, subject to the following conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be included in 18 | // all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 26 | // IN THE SOFTWARE. 27 | // 28 | 29 | #import "PureLayoutDefines.h" 30 | 31 | 32 | PL__ASSUME_NONNULL_BEGIN 33 | 34 | #pragma mark ALView+PureLayout 35 | 36 | /** 37 | A category on UIView/NSView that provides a simple yet powerful interface for creating Auto Layout constraints. 38 | */ 39 | @interface ALView (PureLayout) 40 | 41 | 42 | #pragma mark Factory & Initializer Methods 43 | 44 | /** Creates and returns a new view that does not convert the autoresizing mask into constraints. */ 45 | + (instancetype)newAutoLayoutView; 46 | 47 | /** Initializes and returns a new view that does not convert the autoresizing mask into constraints. */ 48 | - (instancetype)initForAutoLayout; 49 | 50 | /** Configures an existing view to not convert the autoresizing mask into constraints and returns the view. */ 51 | - (instancetype)configureForAutoLayout; 52 | 53 | 54 | #pragma mark Center & Align in Superview 55 | 56 | /** Centers the view in its superview. */ 57 | - (PL__NSArray_of(NSLayoutConstraint *) *)autoCenterInSuperview; 58 | 59 | /** Aligns the view to the same axis of its superview. */ 60 | - (NSLayoutConstraint *)autoAlignAxisToSuperviewAxis:(ALAxis)axis; 61 | 62 | #if PL__PureLayout_MinBaseSDK_iOS_8_0 63 | 64 | /** Centers the view in its superview's margins. Available in iOS 8.0 and later. */ 65 | - (PL__NSArray_of(NSLayoutConstraint *) *)autoCenterInSuperviewMargins; 66 | 67 | /** Aligns the view to the corresponding margin axis of its superview. Available in iOS 8.0 and later. */ 68 | - (NSLayoutConstraint *)autoAlignAxisToSuperviewMarginAxis:(ALAxis)axis; 69 | 70 | #endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ 71 | 72 | 73 | #pragma mark Pin Edges to Superview 74 | 75 | /** Pins the given edge of the view to the same edge of its superview. */ 76 | - (NSLayoutConstraint *)autoPinEdgeToSuperviewEdge:(ALEdge)edge; 77 | 78 | /** Pins the given edge of the view to the same edge of its superview with an inset. */ 79 | - (NSLayoutConstraint *)autoPinEdgeToSuperviewEdge:(ALEdge)edge withInset:(CGFloat)inset; 80 | 81 | /** Pins the given edge of the view to the same edge of its superview with an inset as a maximum or minimum. */ 82 | - (NSLayoutConstraint *)autoPinEdgeToSuperviewEdge:(ALEdge)edge withInset:(CGFloat)inset relation:(NSLayoutRelation)relation; 83 | 84 | /** Pins the edges of the view to the edges of its superview. */ 85 | - (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewEdges; 86 | 87 | /** Pins the edges of the view to the edges of its superview with the given edge insets. */ 88 | - (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewEdgesWithInsets:(ALEdgeInsets)insets; 89 | 90 | /** Pins 3 of the 4 edges of the view to the edges of its superview with the given edge insets, excluding one edge. */ 91 | - (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewEdgesWithInsets:(ALEdgeInsets)insets excludingEdge:(ALEdge)edge; 92 | 93 | #if PL__PureLayout_MinBaseSDK_iOS_8_0 94 | 95 | /** Pins the given edge of the view to the corresponding margin of its superview. Available in iOS 8.0 and later. */ 96 | - (NSLayoutConstraint *)autoPinEdgeToSuperviewMargin:(ALEdge)edge; 97 | 98 | /** Pins the given edge of the view to the corresponding margin of its superview as a maximum or minimum. Available in iOS 8.0 and later. */ 99 | - (NSLayoutConstraint *)autoPinEdgeToSuperviewMargin:(ALEdge)edge relation:(NSLayoutRelation)relation; 100 | 101 | /** Pins the edges of the view to the margins of its superview. Available in iOS 8.0 and later. */ 102 | - (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewMargins; 103 | 104 | /** Pins 3 of the 4 edges of the view to the margins of its superview excluding one edge. Available in iOS 8.0 and later. */ 105 | - (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewMarginsExcludingEdge:(ALEdge)edge; 106 | 107 | #endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ 108 | 109 | 110 | #pragma mark Pin Edges 111 | 112 | /** Pins an edge of the view to a given edge of another view. */ 113 | - (NSLayoutConstraint *)autoPinEdge:(ALEdge)edge toEdge:(ALEdge)toEdge ofView:(ALView *)otherView; 114 | 115 | /** Pins an edge of the view to a given edge of another view with an offset. */ 116 | - (NSLayoutConstraint *)autoPinEdge:(ALEdge)edge toEdge:(ALEdge)toEdge ofView:(ALView *)otherView withOffset:(CGFloat)offset; 117 | 118 | /** Pins an edge of the view to a given edge of another view with an offset as a maximum or minimum. */ 119 | - (NSLayoutConstraint *)autoPinEdge:(ALEdge)edge toEdge:(ALEdge)toEdge ofView:(ALView *)otherView withOffset:(CGFloat)offset relation:(NSLayoutRelation)relation; 120 | 121 | 122 | #pragma mark Align Axes 123 | 124 | /** Aligns an axis of the view to the same axis of another view. */ 125 | - (NSLayoutConstraint *)autoAlignAxis:(ALAxis)axis toSameAxisOfView:(ALView *)otherView; 126 | 127 | /** Aligns an axis of the view to the same axis of another view with an offset. */ 128 | - (NSLayoutConstraint *)autoAlignAxis:(ALAxis)axis toSameAxisOfView:(ALView *)otherView withOffset:(CGFloat)offset; 129 | 130 | /** Aligns an axis of the view to the same axis of another view with a multiplier. */ 131 | - (NSLayoutConstraint *)autoAlignAxis:(ALAxis)axis toSameAxisOfView:(ALView *)otherView withMultiplier:(CGFloat)multiplier; 132 | 133 | 134 | #pragma mark Match Dimensions 135 | 136 | /** Matches a dimension of the view to a given dimension of another view. */ 137 | - (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(ALView *)otherView; 138 | 139 | /** Matches a dimension of the view to a given dimension of another view with an offset. */ 140 | - (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(ALView *)otherView withOffset:(CGFloat)offset; 141 | 142 | /** Matches a dimension of the view to a given dimension of another view with an offset as a maximum or minimum. */ 143 | - (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(ALView *)otherView withOffset:(CGFloat)offset relation:(NSLayoutRelation)relation; 144 | 145 | /** Matches a dimension of the view to a multiple of a given dimension of another view. */ 146 | - (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(ALView *)otherView withMultiplier:(CGFloat)multiplier; 147 | 148 | /** Matches a dimension of the view to a multiple of a given dimension of another view as a maximum or minimum. */ 149 | - (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(ALView *)otherView withMultiplier:(CGFloat)multiplier relation:(NSLayoutRelation)relation; 150 | 151 | 152 | #pragma mark Set Dimensions 153 | 154 | /** Sets the view to a specific size. */ 155 | - (PL__NSArray_of(NSLayoutConstraint *) *)autoSetDimensionsToSize:(CGSize)size; 156 | 157 | /** Sets the given dimension of the view to a specific size. */ 158 | - (NSLayoutConstraint *)autoSetDimension:(ALDimension)dimension toSize:(CGFloat)size; 159 | 160 | /** Sets the given dimension of the view to a specific size as a maximum or minimum. */ 161 | - (NSLayoutConstraint *)autoSetDimension:(ALDimension)dimension toSize:(CGFloat)size relation:(NSLayoutRelation)relation; 162 | 163 | 164 | #pragma mark Set Content Compression Resistance & Hugging 165 | 166 | /** Sets the priority of content compression resistance for an axis. 167 | NOTE: This method must be called from within the block passed into the method +[NSLayoutConstraint autoSetPriority:forConstraints:] */ 168 | - (void)autoSetContentCompressionResistancePriorityForAxis:(ALAxis)axis; 169 | 170 | /** Sets the priority of content hugging for an axis. 171 | NOTE: This method must be called from within the block passed into the method +[NSLayoutConstraint autoSetPriority:forConstraints:] */ 172 | - (void)autoSetContentHuggingPriorityForAxis:(ALAxis)axis; 173 | 174 | 175 | #pragma mark Constrain Any Attributes 176 | 177 | /** Constrains an attribute of the view to a given attribute of another view. */ 178 | - (NSLayoutConstraint *)autoConstrainAttribute:(ALAttribute)attribute toAttribute:(ALAttribute)toAttribute ofView:(ALView *)otherView; 179 | 180 | /** Constrains an attribute of the view to a given attribute of another view with an offset. */ 181 | - (NSLayoutConstraint *)autoConstrainAttribute:(ALAttribute)attribute toAttribute:(ALAttribute)toAttribute ofView:(ALView *)otherView withOffset:(CGFloat)offset; 182 | 183 | /** Constrains an attribute of the view to a given attribute of another view with an offset as a maximum or minimum. */ 184 | - (NSLayoutConstraint *)autoConstrainAttribute:(ALAttribute)attribute toAttribute:(ALAttribute)toAttribute ofView:(ALView *)otherView withOffset:(CGFloat)offset relation:(NSLayoutRelation)relation; 185 | 186 | /** Constrains an attribute of the view to a given attribute of another view with a multiplier. */ 187 | - (NSLayoutConstraint *)autoConstrainAttribute:(ALAttribute)attribute toAttribute:(ALAttribute)toAttribute ofView:(ALView *)otherView withMultiplier:(CGFloat)multiplier; 188 | 189 | /** Constrains an attribute of the view to a given attribute of another view with a multiplier as a maximum or minimum. */ 190 | - (NSLayoutConstraint *)autoConstrainAttribute:(ALAttribute)attribute toAttribute:(ALAttribute)toAttribute ofView:(ALView *)otherView withMultiplier:(CGFloat)multiplier relation:(NSLayoutRelation)relation; 191 | 192 | 193 | #pragma mark Pin to Layout Guides (iOS only) 194 | 195 | #if TARGET_OS_IPHONE 196 | 197 | /** Pins the top edge of the view to the top layout guide of the given view controller with an inset. Available on iOS only. */ 198 | - (NSLayoutConstraint *)autoPinToTopLayoutGuideOfViewController:(UIViewController *)viewController withInset:(CGFloat)inset; 199 | 200 | /** Pins the top edge of the view to the top layout guide of the given view controller with an inset as a maximum or minimum. Available on iOS only. */ 201 | - (NSLayoutConstraint *)autoPinToTopLayoutGuideOfViewController:(UIViewController *)viewController withInset:(CGFloat)inset relation:(NSLayoutRelation)relation; 202 | 203 | /** Pins the bottom edge of the view to the bottom layout guide of the given view controller with an inset. Available on iOS only. */ 204 | - (NSLayoutConstraint *)autoPinToBottomLayoutGuideOfViewController:(UIViewController *)viewController withInset:(CGFloat)inset; 205 | 206 | /** Pins the bottom edge of the view to the bottom layout guide of the given view controller with an inset as a maximum or minimum. Available on iOS only. */ 207 | - (NSLayoutConstraint *)autoPinToBottomLayoutGuideOfViewController:(UIViewController *)viewController withInset:(CGFloat)inset relation:(NSLayoutRelation)relation; 208 | 209 | #endif /* TARGET_OS_IPHONE */ 210 | 211 | @end 212 | 213 | PL__ASSUME_NONNULL_END 214 | -------------------------------------------------------------------------------- /EasyCamera_iOS/Encoder/Codec/AACEncoder.m: -------------------------------------------------------------------------------- 1 | // 2 | // AACEncoder.m 3 | // EasyCapture 4 | // 5 | // Created by phylony on 9/11/16. 6 | // Copyright © 2016 phylony. All rights reserved. 7 | // 8 | 9 | #import "AACEncoder.h" 10 | #import 11 | #import 12 | 13 | @interface AACEncoder() 14 | { 15 | } 16 | @property (nonatomic) AudioConverterRef audioConverter; 17 | @property (nonatomic) uint8_t *aacBuffer; 18 | @property (nonatomic) NSUInteger aacBufferSize; 19 | @property (nonatomic) char *pcmBuffer; 20 | @property (nonatomic) size_t pcmBufferSize; 21 | 22 | @end 23 | 24 | @implementation AACEncoder 25 | 26 | - (void) dealloc { 27 | AudioConverterDispose(_audioConverter); 28 | free(_aacBuffer); 29 | } 30 | 31 | - (id) init { 32 | if (self = [super init]) { 33 | _encoderQueue = dispatch_queue_create("AAC Encoder Queue", DISPATCH_QUEUE_SERIAL); 34 | _callbackQueue = dispatch_queue_create("AAC Encoder Callback Queue", DISPATCH_QUEUE_SERIAL); 35 | _audioConverter = NULL; 36 | _pcmBufferSize = 0; 37 | _pcmBuffer = NULL; 38 | _aacBufferSize = 1024; 39 | _aacBuffer = malloc(_aacBufferSize * sizeof(uint8_t)); 40 | memset(_aacBuffer, 0, _aacBufferSize); 41 | self.delegate = nil; 42 | } 43 | return self; 44 | } 45 | 46 | //- (void)createEncoder 47 | //{ 48 | // // 打开faac编码器引擎 49 | // int nMaxOutputBytes = 0; 50 | // hEncoder = faacEncOpen(nSampleRate, nChannels, &nInputSamples, &nMaxOutputBytes); 51 | // if(hEncoder == NULL) 52 | // { 53 | // printf("打开faac编码器引擎失败!\n"); 54 | // return; 55 | // } 56 | // 57 | // // 分配内存信息 58 | // unsigned int nPCMBitSize = 16; 59 | // int nPCMBufferSize = nInputSamples * nPCMBitSize / 8; 60 | // char* pbPCMBuffer = (char *)malloc(nPCMBufferSize); 61 | // char* pbAACBuffer = (char *)malloc(nPCMBufferSize); 62 | // 63 | // // 获取当前编码器信息 64 | // faacEncConfigurationPtr pConfiguration = {0}; 65 | // pConfiguration = faacEncGetCurrentConfiguration(hEncoder); 66 | // 67 | // pConfiguration->inputFormat = FAAC_INPUT_16BIT; 68 | // pConfiguration->outputFormat = 1; 69 | // 70 | // pConfiguration->aacObjectType = LOW; 71 | //// pConfiguration->allowMidside = 0; 72 | //// pConfiguration->useLfe = 0; 73 | //// pConfiguration->bitRate = 48000; 74 | //// pConfiguration->bandWidth = 32000; 75 | //} 76 | 77 | - (void) setupEncoderFromSampleBuffer:(CMSampleBufferRef)sampleBuffer { 78 | AudioStreamBasicDescription inAudioStreamBasicDescription = *CMAudioFormatDescriptionGetStreamBasicDescription((CMAudioFormatDescriptionRef)CMSampleBufferGetFormatDescription(sampleBuffer)); 79 | // inAudioStreamBasicDescription.mFormatID = kAudioFormatLinearPCM; 80 | // inAudioStreamBasicDescription.mSampleRate = 8000; 81 | // inAudioStreamBasicDescription.mChannelsPerFrame = 1; 82 | //// inAudioStreamBasicDescription.mBitsPerChannel = 16; 83 | //// inAudioStreamBasicDescription.mBytesPerFrame = 2; 84 | // inAudioStreamBasicDescription.mBytesPerPacket = inAudioStreamBasicDescription.mBytesPerFrame * inAudioStreamBasicDescription.mFramesPerPacket; 85 | // inAudioStreamBasicDescription.mFormatFlags = kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsNonInterleaved; 86 | // inAudioStreamBasicDescription.mReserved = 0; 87 | AudioStreamBasicDescription outAudioStreamBasicDescription = {0}; // Always initialize the fields of a new audio stream basic description structure to zero, as shown here: ... 88 | outAudioStreamBasicDescription.mSampleRate = inAudioStreamBasicDescription.mSampleRate; // The number of frames per second of the data in the stream, when the stream is played at normal speed. For compressed formats, this field indicates the number of frames per second of equivalent decompressed data. The mSampleRate field must be nonzero, except when this structure is used in a listing of supported formats (see “kAudioStreamAnyRate”). 89 | outAudioStreamBasicDescription.mFormatID = kAudioFormatMPEG4AAC; // kAudioFormatMPEG4AAC_HE does not work. Can't find `AudioClassDescription`. `mFormatFlags` is set to 0. 90 | outAudioStreamBasicDescription.mFormatFlags = kMPEG4Object_AAC_LC; // Format-specific flags to specify details of the format. Set to 0 to indicate no format flags. See “Audio Data Format Identifiers” for the flags that apply to each format. 91 | outAudioStreamBasicDescription.mBytesPerPacket = 0; // The number of bytes in a packet of audio data. To indicate variable packet size, set this field to 0. For a format that uses variable packet size, specify the size of each packet using an AudioStreamPacketDescription structure. 92 | outAudioStreamBasicDescription.mFramesPerPacket = 1024; // The number of frames in a packet of audio data. For uncompressed audio, the value is 1. For variable bit-rate formats, the value is a larger fixed number, such as 1024 for AAC. For formats with a variable number of frames per packet, such as Ogg Vorbis, set this field to 0. 93 | outAudioStreamBasicDescription.mBytesPerFrame = 0; // The number of bytes from the start of one frame to the start of the next frame in an audio buffer. Set this field to 0 for compressed formats. ... 94 | outAudioStreamBasicDescription.mChannelsPerFrame = 2; // The number of channels in each frame of audio data. This value must be nonzero. 95 | outAudioStreamBasicDescription.mBitsPerChannel = 0; // ... Set this field to 0 for compressed formats. 96 | outAudioStreamBasicDescription.mReserved = 0; // Pads the structure out to force an even 8-byte alignment. Must be set to 0. 97 | AudioClassDescription *description = [self 98 | getAudioClassDescriptionWithType:kAudioFormatMPEG4AAC 99 | fromManufacturer:kAppleHardwareAudioCodecManufacturer]; 100 | 101 | OSStatus status = AudioConverterNewSpecific(&inAudioStreamBasicDescription, &outAudioStreamBasicDescription, 1, description, &_audioConverter); 102 | if (status != 0) { 103 | NSLog(@"setup converter: %d", (int)status); 104 | } 105 | 106 | // UInt32 bitRate = 64000; 107 | // UInt32 uiSize = sizeof(bitRate); 108 | // status = AudioConverterSetProperty(_audioConverter, kAudioConverterEncodeBitRate, uiSize, &bitRate); 109 | // 110 | // UInt32 value = 0; 111 | // uiSize = sizeof(value); 112 | // AudioConverterGetProperty(_audioConverter, kAudioConverterPropertyMaximumOutputPacketSize, &uiSize, &value); 113 | // NSLog(@"packet size = %d", value); 114 | } 115 | 116 | - (AudioClassDescription *)getAudioClassDescriptionWithType:(UInt32)type 117 | fromManufacturer:(UInt32)manufacturer 118 | { 119 | static AudioClassDescription desc; 120 | 121 | UInt32 encoderSpecifier = type; 122 | OSStatus st; 123 | 124 | UInt32 size; 125 | st = AudioFormatGetPropertyInfo(kAudioFormatProperty_Encoders, 126 | sizeof(encoderSpecifier), 127 | &encoderSpecifier, 128 | &size); 129 | if (st) { 130 | NSLog(@"error getting audio format propery info: %d", (int)(st)); 131 | return nil; 132 | } 133 | 134 | unsigned int count = size / sizeof(AudioClassDescription); 135 | AudioClassDescription descriptions[count]; 136 | st = AudioFormatGetProperty(kAudioFormatProperty_Encoders, 137 | sizeof(encoderSpecifier), 138 | &encoderSpecifier, 139 | &size, 140 | descriptions); 141 | if (st) { 142 | // NSLog(@"error getting audio format propery: %d", (int)(st)); 143 | return nil; 144 | } 145 | 146 | for (unsigned int i = 0; i < count; i++) { 147 | if ((type == descriptions[i].mSubType) && 148 | (manufacturer == descriptions[i].mManufacturer)) { 149 | memcpy(&desc, &(descriptions[i]), sizeof(desc)); 150 | return &desc; 151 | } 152 | } 153 | 154 | return nil; 155 | } 156 | 157 | static OSStatus inInputDataProc(AudioConverterRef inAudioConverter, UInt32 *ioNumberDataPackets, AudioBufferList *ioData, AudioStreamPacketDescription **outDataPacketDescription, void *inUserData) 158 | { 159 | AACEncoder *encoder = (__bridge AACEncoder *)(inUserData); 160 | UInt32 requestedPackets = *ioNumberDataPackets; 161 | // NSLog(@"Number of packets requested: %d", (unsigned int)requestedPackets); 162 | size_t copiedSize = [encoder copyPCMBuffer:ioData]; 163 | if (copiedSize < requestedPackets * 2) { 164 | NSLog(@"PCM buffer isn't full enough!"); 165 | *ioNumberDataPackets = 0; 166 | return -1; 167 | } 168 | *ioNumberDataPackets = requestedPackets; 169 | 170 | 171 | //NSLog(@"Copied %zu samples into ioData", copiedSamples); 172 | return noErr; 173 | } 174 | 175 | - (size_t) copyPCMBuffer:(AudioBufferList*)ioData { 176 | size_t originalBufferSize = _pcmBufferSize; 177 | if (!originalBufferSize) { 178 | return 0; 179 | } 180 | ioData->mBuffers[0].mData = _pcmBuffer; 181 | ioData->mBuffers[0].mDataByteSize = (UInt32)_pcmBufferSize; 182 | _pcmBuffer = NULL; 183 | _pcmBufferSize = 0; 184 | return originalBufferSize; 185 | } 186 | 187 | - (void) encode:(CMSampleBufferRef)sampleBuffer { 188 | // CFRetain(sampleBuffer); 189 | CMTime timestamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer); 190 | // dispatch_async(_encoderQueue, ^{ 191 | if (!_audioConverter) { 192 | [self setupEncoderFromSampleBuffer:sampleBuffer]; 193 | } 194 | CMBlockBufferRef blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer); 195 | CFRetain(blockBuffer); 196 | OSStatus status = CMBlockBufferGetDataPointer(blockBuffer, 0, NULL, &_pcmBufferSize, &_pcmBuffer); 197 | NSError *error = nil; 198 | if (status != kCMBlockBufferNoErr) { 199 | error = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; 200 | NSLog(@"err:%@",error); 201 | } 202 | 203 | memset(_aacBuffer, 0, _aacBufferSize); 204 | AudioBufferList outAudioBufferList = {0}; 205 | outAudioBufferList.mNumberBuffers = 1; 206 | outAudioBufferList.mBuffers[0].mNumberChannels = 1; 207 | outAudioBufferList.mBuffers[0].mDataByteSize = (UInt32)_aacBufferSize; 208 | outAudioBufferList.mBuffers[0].mData = _aacBuffer; 209 | AudioStreamPacketDescription *outPacketDescription = NULL; 210 | UInt32 ioOutputDataPacketSize = 1; 211 | status = AudioConverterFillComplexBuffer(_audioConverter, inInputDataProc, (__bridge void *)(self), &ioOutputDataPacketSize, &outAudioBufferList, outPacketDescription); 212 | NSData *data = nil; 213 | if ( status == 0) { 214 | NSData *rawAAC = [NSData dataWithBytes:outAudioBufferList.mBuffers[0].mData length:outAudioBufferList.mBuffers[0].mDataByteSize]; 215 | 216 | NSData *adtsHeader = [self adtsDataForPacketLength:rawAAC.length]; 217 | NSMutableData *fullData = [NSMutableData dataWithData:adtsHeader]; 218 | [fullData appendData:rawAAC]; 219 | data = fullData; 220 | } else { 221 | error = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; 222 | NSLog(@"%@",error); 223 | } 224 | if (self.delegate != nil) { 225 | dispatch_async(_callbackQueue, ^{ 226 | [self.delegate gotAACEncodedData:data timestamp:timestamp error:error]; 227 | }); 228 | } 229 | // CFRelease(sampleBuffer); 230 | CFRelease(blockBuffer); 231 | // }); 232 | } 233 | 234 | 235 | 236 | /** 237 | * Add ADTS header at the beginning of each and every AAC packet. 238 | * This is needed as MediaCodec encoder generates a packet of raw 239 | * AAC data. 240 | * 241 | * Note the packetLen must count in the ADTS header itself. 242 | * See: http://wiki.multimedia.cx/index.php?title=ADTS 243 | * Also: http://wiki.multimedia.cx/index.php?title=MPEG-4_Audio#Channel_Configurations 244 | **/ 245 | - (NSData*) adtsDataForPacketLength:(NSUInteger)packetLength { 246 | int adtsLength = 7; 247 | char *packet = malloc(sizeof(char) * adtsLength); 248 | // Variables Recycled by addADTStoPacket 249 | int profile = 2; //AAC LC 250 | //39=MediaCodecInfo.CodecProfileLevel.AACObjectELD; 251 | // int freqIdx = 11; //8KHz 252 | int freqIdx = 4; 253 | int chanCfg = 2; //MPEG-4 Audio Channel Configuration. 1 Channel front-center 254 | NSUInteger fullLength = adtsLength + packetLength; 255 | // fill in ADTS data 256 | packet[0] = (char)0xFF; // 11111111 = syncword 257 | packet[1] = (char)0xF9; // 1111 1 00 1 = syncword MPEG-2 Layer CRC 258 | packet[2] = (char)(((profile-1)<<6) + (freqIdx<<2) +(chanCfg>>2)); 259 | packet[3] = (char)(((chanCfg&3)<<6) + (fullLength>>11)); 260 | packet[4] = (char)((fullLength&0x7FF) >> 3); 261 | packet[5] = (char)(((fullLength&7)<<5) + 0x1F); 262 | packet[6] = (char)0xFC; 263 | NSData *data = [NSData dataWithBytesNoCopy:packet length:adtsLength freeWhenDone:YES]; 264 | return data; 265 | } 266 | 267 | @end 268 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/PureLayout/PureLayoutDefines.h: -------------------------------------------------------------------------------- 1 | // 2 | // PureLayoutDefines.h 3 | // https://github.com/PureLayout/PureLayout 4 | // 5 | // Copyright (c) 2014-2015 Tyler Fox 6 | // 7 | // This code is distributed under the terms and conditions of the MIT license. 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to 11 | // deal in the Software without restriction, including without limitation the 12 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 13 | // sell copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 25 | // IN THE SOFTWARE. 26 | // 27 | 28 | #ifndef PureLayoutDefines_h 29 | #define PureLayoutDefines_h 30 | 31 | #import 32 | 33 | // Define some preprocessor macros to check for a minimum Base SDK. These are used to prevent compile-time errors in older versions of Xcode. 34 | #define PL__PureLayout_MinBaseSDK_iOS_8_0 (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_7_1) 35 | #define PL__PureLayout_MinBaseSDK_OSX_10_10 (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MAX_ALLOWED > __MAC_10_9) 36 | 37 | // Define some preprocessor macros to check for a minimum System Version. These are used to prevent runtime crashes on older versions of iOS/OS X. 38 | #define PL__PureLayout_MinSysVer_iOS_7_0 (TARGET_OS_IPHONE && floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) 39 | #define PL__PureLayout_MinSysVer_iOS_8_0 (TARGET_OS_IPHONE && floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_7_1) 40 | #define PL__PureLayout_MinSysVer_OSX_10_9 (!TARGET_OS_IPHONE && floor(NSFoundationVersionNumber) > NSFoundationVersionNumber10_8_4) 41 | 42 | // Define some preprocessor macros that allow nullability annotations to be adopted in a backwards-compatible manner. 43 | #if __has_feature(nullability) 44 | # define PL__ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN 45 | # define PL__ASSUME_NONNULL_END NS_ASSUME_NONNULL_END 46 | #else 47 | # define PL__ASSUME_NONNULL_BEGIN 48 | # define PL__ASSUME_NONNULL_END 49 | #endif 50 | 51 | // Define some preprocessor macros that allow generics to be adopted in a backwards-compatible manner. 52 | #if __has_feature(objc_generics) 53 | # define PL__GENERICS(class, ...) class<__VA_ARGS__> 54 | #else 55 | # define PL__GENERICS(class, ...) class 56 | #endif 57 | 58 | // Using generics with NSArray is so common in PureLayout that it gets a dedicated preprocessor macro for better readability. 59 | #define PL__NSArray_of(type) PL__GENERICS(NSArray, type) 60 | 61 | // Define generic AL-prefixed macros for the types/constants/etc that have slight naming variations across iOS and OS X, which allows the same code to be platform-independent. 62 | #if TARGET_OS_IPHONE || TARGET_OS_TV 63 | # import 64 | # define ALView UIView 65 | # define ALEdgeInsets UIEdgeInsets 66 | # define ALEdgeInsetsZero UIEdgeInsetsZero 67 | # define ALEdgeInsetsMake UIEdgeInsetsMake 68 | # define ALLayoutConstraintAxis UILayoutConstraintAxis 69 | # define ALLayoutConstraintOrientation ALLayoutConstraintAxis 70 | # define ALLayoutConstraintAxisHorizontal UILayoutConstraintAxisHorizontal 71 | # define ALLayoutConstraintAxisVertical UILayoutConstraintAxisVertical 72 | # define ALLayoutConstraintOrientationHorizontal ALLayoutConstraintAxisHorizontal 73 | # define ALLayoutConstraintOrientationVertical ALLayoutConstraintAxisVertical 74 | # define ALLayoutPriority UILayoutPriority 75 | # define ALLayoutPriorityRequired UILayoutPriorityRequired 76 | # define ALLayoutPriorityDefaultHigh UILayoutPriorityDefaultHigh 77 | # define ALLayoutPriorityDefaultLow UILayoutPriorityDefaultLow 78 | # define ALLayoutPriorityFittingSizeLevel UILayoutPriorityFittingSizeLevel 79 | # define ALLayoutPriorityFittingSizeCompression ALLayoutPriorityFittingSizeLevel 80 | #else 81 | # import 82 | # define ALView NSView 83 | # define ALEdgeInsets NSEdgeInsets 84 | # define ALEdgeInsetsZero NSEdgeInsetsMake(0, 0, 0, 0) 85 | # define ALEdgeInsetsMake NSEdgeInsetsMake 86 | # define ALLayoutConstraintOrientation NSLayoutConstraintOrientation 87 | # define ALLayoutConstraintAxis ALLayoutConstraintOrientation 88 | # define ALLayoutConstraintOrientationHorizontal NSLayoutConstraintOrientationHorizontal 89 | # define ALLayoutConstraintOrientationVertical NSLayoutConstraintOrientationVertical 90 | # define ALLayoutConstraintAxisHorizontal ALLayoutConstraintOrientationHorizontal 91 | # define ALLayoutConstraintAxisVertical ALLayoutConstraintOrientationVertical 92 | # define ALLayoutPriority NSLayoutPriority 93 | # define ALLayoutPriorityRequired NSLayoutPriorityRequired 94 | # define ALLayoutPriorityDefaultHigh NSLayoutPriorityDefaultHigh 95 | # define ALLayoutPriorityDefaultLow NSLayoutPriorityDefaultLow 96 | # define ALLayoutPriorityFittingSizeCompression NSLayoutPriorityFittingSizeCompression 97 | # define ALLayoutPriorityFittingSizeLevel ALLayoutPriorityFittingSizeCompression 98 | #endif /* TARGET_OS_IPHONE */ 99 | 100 | 101 | #pragma mark PureLayout Attributes 102 | 103 | /** Constants that represent edges of a view. */ 104 | typedef NS_ENUM(NSInteger, ALEdge) { 105 | /** The left edge of the view. */ 106 | ALEdgeLeft = NSLayoutAttributeLeft, 107 | /** The right edge of the view. */ 108 | ALEdgeRight = NSLayoutAttributeRight, 109 | /** The top edge of the view. */ 110 | ALEdgeTop = NSLayoutAttributeTop, 111 | /** The bottom edge of the view. */ 112 | ALEdgeBottom = NSLayoutAttributeBottom, 113 | /** The leading edge of the view (left edge for left-to-right languages like English, right edge for right-to-left languages like Arabic). */ 114 | ALEdgeLeading = NSLayoutAttributeLeading, 115 | /** The trailing edge of the view (right edge for left-to-right languages like English, left edge for right-to-left languages like Arabic). */ 116 | ALEdgeTrailing = NSLayoutAttributeTrailing 117 | }; 118 | 119 | /** Constants that represent dimensions of a view. */ 120 | typedef NS_ENUM(NSInteger, ALDimension) { 121 | /** The width of the view. */ 122 | ALDimensionWidth = NSLayoutAttributeWidth, 123 | /** The height of the view. */ 124 | ALDimensionHeight = NSLayoutAttributeHeight 125 | }; 126 | 127 | /** Constants that represent axes of a view. */ 128 | typedef NS_ENUM(NSInteger, ALAxis) { 129 | /** A vertical line equidistant from the view's left and right edges. */ 130 | ALAxisVertical = NSLayoutAttributeCenterX, 131 | /** A horizontal line equidistant from the view's top and bottom edges. */ 132 | ALAxisHorizontal = NSLayoutAttributeCenterY, 133 | 134 | /** A horizontal line at the baseline of the last line of text in the view. (For views that do not draw text, will be equivalent to ALEdgeBottom.) Same as ALAxisLastBaseline. */ 135 | ALAxisBaseline = NSLayoutAttributeBaseline, 136 | /** A horizontal line at the baseline of the last line of text in the view. (For views that do not draw text, will be equivalent to ALEdgeBottom.) */ 137 | ALAxisLastBaseline = ALAxisBaseline, 138 | #if PL__PureLayout_MinBaseSDK_iOS_8_0 139 | /** A horizontal line at the baseline of the first line of text in a view. (For views that do not draw text, will be equivalent to ALEdgeTop.) Available in iOS 8.0 and later. */ 140 | ALAxisFirstBaseline = NSLayoutAttributeFirstBaseline 141 | #endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ 142 | }; 143 | 144 | #if PL__PureLayout_MinBaseSDK_iOS_8_0 145 | 146 | /** Constants that represent layout margins of a view. Available in iOS 8.0 and later. */ 147 | typedef NS_ENUM(NSInteger, ALMargin) { 148 | /** The left margin of the view, based on the view's layoutMargins left inset. */ 149 | ALMarginLeft = NSLayoutAttributeLeftMargin, 150 | /** The right margin of the view, based on the view's layoutMargins right inset. */ 151 | ALMarginRight = NSLayoutAttributeRightMargin, 152 | /** The top margin of the view, based on the view's layoutMargins top inset. */ 153 | ALMarginTop = NSLayoutAttributeTopMargin, 154 | /** The bottom margin of the view, based on the view's layoutMargins bottom inset. */ 155 | ALMarginBottom = NSLayoutAttributeBottomMargin, 156 | /** The leading margin of the view, based on the view's layoutMargins left/right (depending on language direction) inset. */ 157 | ALMarginLeading = NSLayoutAttributeLeadingMargin, 158 | /** The trailing margin of the view, based on the view's layoutMargins left/right (depending on language direction) inset. */ 159 | ALMarginTrailing = NSLayoutAttributeTrailingMargin 160 | }; 161 | 162 | /** Constants that represent axes of the layout margins of a view. Available in iOS 8.0 and later. */ 163 | typedef NS_ENUM(NSInteger, ALMarginAxis) { 164 | /** A vertical line equidistant from the view's left and right margins. */ 165 | ALMarginAxisVertical = NSLayoutAttributeCenterXWithinMargins, 166 | /** A horizontal line equidistant from the view's top and bottom margins. */ 167 | ALMarginAxisHorizontal = NSLayoutAttributeCenterYWithinMargins 168 | }; 169 | 170 | #endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ 171 | 172 | /** An attribute of a view that can be used in auto layout constraints. These constants are identical to the more specific enum types: 173 | ALEdge, ALAxis, ALDimension, ALMargin, ALMarginAxis. It is safe to cast a more specific enum type to the ALAttribute type. */ 174 | typedef NS_ENUM(NSInteger, ALAttribute) { 175 | /** The left edge of the view. */ 176 | ALAttributeLeft = ALEdgeLeft, 177 | /** The right edge of the view. */ 178 | ALAttributeRight = ALEdgeRight, 179 | /** The top edge of the view. */ 180 | ALAttributeTop = ALEdgeTop, 181 | /** The bottom edge of the view. */ 182 | ALAttributeBottom = ALEdgeBottom, 183 | /** The leading edge of the view (left edge for left-to-right languages like English, right edge for right-to-left languages like Arabic). */ 184 | ALAttributeLeading = ALEdgeLeading, 185 | /** The trailing edge of the view (right edge for left-to-right languages like English, left edge for right-to-left languages like Arabic). */ 186 | ALAttributeTrailing = ALEdgeTrailing, 187 | /** The width of the view. */ 188 | ALAttributeWidth = ALDimensionWidth, 189 | /** The height of the view. */ 190 | ALAttributeHeight = ALDimensionHeight, 191 | /** A vertical line equidistant from the view's left and right edges. */ 192 | ALAttributeVertical = ALAxisVertical, 193 | /** A horizontal line equidistant from the view's top and bottom edges. */ 194 | ALAttributeHorizontal = ALAxisHorizontal, 195 | /** A horizontal line at the baseline of the last line of text in the view. (For views that do not draw text, will be equivalent to ALEdgeBottom.) Same as ALAxisLastBaseline. */ 196 | ALAttributeBaseline = ALAxisBaseline, 197 | /** A horizontal line at the baseline of the last line of text in the view. (For views that do not draw text, will be equivalent to ALEdgeBottom.) */ 198 | ALAttributeLastBaseline = ALAxisLastBaseline, 199 | #if PL__PureLayout_MinBaseSDK_iOS_8_0 200 | /** A horizontal line at the baseline of the first line of text in a view. (For views that do not draw text, will be equivalent to ALEdgeTop.) Available in iOS 8.0 and later. */ 201 | ALAttributeFirstBaseline = ALAxisFirstBaseline, 202 | /** The left margin of the view, based on the view's layoutMargins left inset. */ 203 | ALAttributeMarginLeft = ALMarginLeft, 204 | /** The right margin of the view, based on the view's layoutMargins right inset. */ 205 | ALAttributeMarginRight = ALMarginRight, 206 | /** The top margin of the view, based on the view's layoutMargins top inset. */ 207 | ALAttributeMarginTop = ALMarginTop, 208 | /** The bottom margin of the view, based on the view's layoutMargins bottom inset. */ 209 | ALAttributeMarginBottom = ALMarginBottom, 210 | /** The leading margin of the view, based on the view's layoutMargins left/right (depending on language direction) inset. */ 211 | ALAttributeMarginLeading = ALMarginLeading, 212 | /** The trailing margin of the view, based on the view's layoutMargins left/right (depending on language direction) inset. */ 213 | ALAttributeMarginTrailing = ALMarginTrailing, 214 | /** A vertical line equidistant from the view's left and right margins. */ 215 | ALAttributeMarginAxisVertical = ALMarginAxisVertical, 216 | /** A horizontal line equidistant from the view's top and bottom margins. */ 217 | ALAttributeMarginAxisHorizontal = ALMarginAxisHorizontal 218 | #endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ 219 | }; 220 | 221 | /** A block containing method calls to the PureLayout API. Takes no arguments and has no return value. */ 222 | typedef void(^ALConstraintsBlock)(void); 223 | 224 | #endif /* PureLayoutDefines_h */ 225 | -------------------------------------------------------------------------------- /EasyCamera_iOS/Encoder/Codec/H264HWDecoder.m: -------------------------------------------------------------------------------- 1 | // 2 | // H264HWDecoder.m 3 | // EasyCapture 4 | // 5 | // Created by phylony on 9/11/16. 6 | // Copyright © 2016 phylony. All rights reserved. 7 | // 8 | #import "H264HWDecoder.h" 9 | 10 | @interface H264HWDecoder () 11 | 12 | @property (nonatomic, assign) CMVideoFormatDescriptionRef formatDesc; 13 | @property (nonatomic, assign) VTDecompressionSessionRef decompressionSession; 14 | @property (nonatomic, assign) int spsSize; 15 | @property (nonatomic, assign) int ppsSize; 16 | 17 | @end 18 | 19 | NSString * const naluTypesStrings[] = 20 | { 21 | @"0: Unspecified (non-VCL)", 22 | @"1: Coded slice of a non-IDR picture (VCL)", // P frame 23 | @"2: Coded slice data partition A (VCL)", 24 | @"3: Coded slice data partition B (VCL)", 25 | @"4: Coded slice data partition C (VCL)", 26 | @"5: Coded slice of an IDR picture (VCL)", // I frame 27 | @"6: Supplemental enhancement information (SEI) (non-VCL)", 28 | @"7: Sequence parameter set (non-VCL)", // SPS parameter 29 | @"8: Picture parameter set (non-VCL)", // PPS parameter 30 | @"9: Access unit delimiter (non-VCL)", 31 | @"10: End of sequence (non-VCL)", 32 | @"11: End of stream (non-VCL)", 33 | @"12: Filler data (non-VCL)", 34 | @"13: Sequence parameter set extension (non-VCL)", 35 | @"14: Prefix NAL unit (non-VCL)", 36 | @"15: Subset sequence parameter set (non-VCL)", 37 | @"16: Reserved (non-VCL)", 38 | @"17: Reserved (non-VCL)", 39 | @"18: Reserved (non-VCL)", 40 | @"19: Coded slice of an auxiliary coded picture without partitioning (non-VCL)", 41 | @"20: Coded slice extension (non-VCL)", 42 | @"21: Coded slice extension for depth view components (non-VCL)", 43 | @"22: Reserved (non-VCL)", 44 | @"23: Reserved (non-VCL)", 45 | @"24: STAP-A Single-time aggregation packet (non-VCL)", 46 | @"25: STAP-B Single-time aggregation packet (non-VCL)", 47 | @"26: MTAP16 Multi-time aggregation packet (non-VCL)", 48 | @"27: MTAP24 Multi-time aggregation packet (non-VCL)", 49 | @"28: FU-A Fragmentation unit (non-VCL)", 50 | @"29: FU-B Fragmentation unit (non-VCL)", 51 | @"30: Unspecified (non-VCL)", 52 | @"31: Unspecified (non-VCL)", 53 | }; 54 | 55 | @implementation H264HWDecoder 56 | 57 | - (id)init 58 | { 59 | self = [super init]; 60 | if(self != nil) 61 | { 62 | self.delegate = nil; 63 | } 64 | return self; 65 | } 66 | 67 | - (void) receivedRawVideoFrame:(uint8_t *)frame withSize:(uint32_t)frameSize isIFrame:(int)isIFrame 68 | { 69 | OSStatus status; 70 | 71 | uint8_t *data = NULL; 72 | uint8_t *pps = NULL; 73 | uint8_t *sps = NULL; 74 | 75 | // I know what my H.264 data source's NALUs look like so I know start code index is always 0. 76 | // if you don't know where it starts, you can use a for loop similar to how i find the 2nd and 3rd start codes 77 | int startCodeIndex = 0; 78 | int secondStartCodeIndex = 0; 79 | int thirdStartCodeIndex = 0; 80 | 81 | long blockLength = 0; 82 | 83 | CMSampleBufferRef sampleBuffer = NULL; 84 | CMBlockBufferRef blockBuffer = NULL; 85 | 86 | int nalu_type = (frame[startCodeIndex + 4] & 0x1F); 87 | // NSLog(@"~~~~~~~ Received NALU Type \"%@\" ~~~~~~~~", naluTypesStrings[nalu_type]); 88 | 89 | // if we havent already set up our format description with our SPS PPS parameters, we 90 | // can't process any frames except type 7 that has our parameters 91 | if (nalu_type != 7 && _formatDesc == NULL) 92 | { 93 | // NSLog(@"Video error: Frame is not an I Frame and format description is null"); 94 | return; 95 | } 96 | 97 | // NALU type 7 is the SPS parameter NALU 98 | if (nalu_type == 7) 99 | { 100 | // find where the second PPS start code begins, (the 0x00 00 00 01 code) 101 | // from which we also get the length of the first SPS code 102 | for (int i = startCodeIndex + 4; i < startCodeIndex + 40; i++) 103 | { 104 | if (frame[i] == 0x00 && frame[i+1] == 0x00 && frame[i+2] == 0x00 && frame[i+3] == 0x01) 105 | { 106 | secondStartCodeIndex = i; 107 | _spsSize = secondStartCodeIndex; // includes the header in the size 108 | break; 109 | } 110 | } 111 | 112 | // find what the second NALU type is 113 | nalu_type = (frame[secondStartCodeIndex + 4] & 0x1F); 114 | // NSLog(@"~~~~~~~ Received NALU Type \"%@\" ~~~~~~~~", naluTypesStrings[nalu_type]); 115 | } 116 | 117 | // type 8 is the PPS parameter NALU 118 | if(nalu_type == 8) 119 | { 120 | // find where the NALU after this one starts so we know how long the PPS parameter is 121 | for (int i = _spsSize + 4; i < _spsSize + 30; i++) 122 | { 123 | if (frame[i] == 0x00 && frame[i+1] == 0x00 && frame[i+2] == 0x00 && frame[i+3] == 0x01) 124 | { 125 | thirdStartCodeIndex = i; 126 | _ppsSize = thirdStartCodeIndex - _spsSize; 127 | break; 128 | } 129 | } 130 | 131 | // allocate enough data to fit the SPS and PPS parameters into our data objects. 132 | // VTD doesn't want you to include the start code header (4 bytes long) so we add the - 4 here 133 | sps = malloc(_spsSize - 4); 134 | pps = malloc(_ppsSize - 4); 135 | 136 | // copy in the actual sps and pps values, again ignoring the 4 byte header 137 | memcpy (sps, &frame[4], _spsSize-4); 138 | memcpy (pps, &frame[_spsSize+4], _ppsSize-4); 139 | 140 | // now we set our H264 parameters 141 | uint8_t* parameterSetPointers[2] = {sps, pps}; 142 | size_t parameterSetSizes[2] = {_spsSize-4, _ppsSize-4}; 143 | 144 | status = CMVideoFormatDescriptionCreateFromH264ParameterSets(kCFAllocatorDefault, 2, 145 | (const uint8_t *const*)parameterSetPointers, 146 | parameterSetSizes, 4, 147 | &_formatDesc); 148 | 149 | // NSLog(@"\t\t Creation of CMVideoFormatDescription: %@", (status == noErr) ? @"successful!" : @"failed..."); 150 | // if(status != noErr) NSLog(@"\t\t Format Description ERROR type: %d", (int)status); 151 | 152 | // See if decomp session can convert from previous format description 153 | // to the new one, if not we need to remake the decomp session. 154 | // This snippet was not necessary for my applications but it could be for yours 155 | /*BOOL needNewDecompSession = (VTDecompressionSessionCanAcceptFormatDescription(_decompressionSession, _formatDesc) == NO); 156 | if(needNewDecompSession) 157 | { 158 | [self createDecompSession]; 159 | }*/ 160 | 161 | // now lets handle the IDR frame that (should) come after the parameter sets 162 | // I say "should" because that's how I expect my H264 stream to work, YMMV 163 | nalu_type = (frame[thirdStartCodeIndex + 4] & 0x1F); 164 | // NSLog(@"~~~~~~~ Received NALU Type \"%@\" ~~~~~~~~", naluTypesStrings[nalu_type]); 165 | } 166 | 167 | // create our VTDecompressionSession. This isnt neccessary if you choose to use AVSampleBufferDisplayLayer 168 | if((status == noErr) && (_decompressionSession == NULL)) 169 | { 170 | [self createDecompSession]; 171 | } 172 | 173 | // type 5 is an IDR frame NALU. The SPS and PPS NALUs should always be followed by an IDR (or IFrame) NALU, as far as I know 174 | if(nalu_type == 5) 175 | { 176 | // find the offset, or where the SPS and PPS NALUs end and the IDR frame NALU begins 177 | int offset = _spsSize + _ppsSize; 178 | blockLength = frameSize - offset; 179 | data = malloc(blockLength); 180 | data = memcpy(data, &frame[offset], blockLength); 181 | 182 | // replace the start code header on this NALU with its size. 183 | // AVCC format requires that you do this. 184 | // htonl converts the unsigned int from host to network byte order 185 | uint32_t dataLength32 = htonl (blockLength - 4); 186 | memcpy (data, &dataLength32, sizeof (uint32_t)); 187 | 188 | // create a block buffer from the IDR NALU 189 | status = CMBlockBufferCreateWithMemoryBlock(NULL, data, // memoryBlock to hold buffered data 190 | blockLength, // block length of the mem block in bytes. 191 | kCFAllocatorNull, NULL, 192 | 0, // offsetToData 193 | blockLength, // dataLength of relevant bytes, starting at offsetToData 194 | 0, &blockBuffer); 195 | 196 | // NSLog(@"\t\t BlockBufferCreation: \t %@", (status == kCMBlockBufferNoErr) ? @"successful!" : @"failed..."); 197 | } 198 | 199 | // NALU type 1 is non-IDR (or PFrame) picture 200 | if (nalu_type == 1) 201 | { 202 | // non-IDR frames do not have an offset due to SPS and PSS, so the approach 203 | // is similar to the IDR frames just without the offset 204 | blockLength = frameSize; 205 | data = malloc(blockLength); 206 | data = memcpy(data, &frame[0], blockLength); 207 | 208 | // again, replace the start header with the size of the NALU 209 | uint32_t dataLength32 = htonl (blockLength - 4); 210 | memcpy (data, &dataLength32, sizeof (uint32_t)); 211 | 212 | status = CMBlockBufferCreateWithMemoryBlock(NULL, data, // memoryBlock to hold data. If NULL, block will be alloc when needed 213 | blockLength, // overall length of the mem block in bytes 214 | kCFAllocatorNull, NULL, 215 | 0, // offsetToData 216 | blockLength, // dataLength of relevant data bytes, starting at offsetToData 217 | 0, &blockBuffer); 218 | 219 | // NSLog(@"\t\t BlockBufferCreation: \t %@", (status == kCMBlockBufferNoErr) ? @"successful!" : @"failed..."); 220 | } 221 | 222 | // now create our sample buffer from the block buffer, 223 | if(status == noErr) 224 | { 225 | // here I'm not bothering with any timing specifics since in my case we displayed all frames immediately 226 | const size_t sampleSize = blockLength; 227 | status = CMSampleBufferCreate(kCFAllocatorDefault, 228 | blockBuffer, true, NULL, NULL, 229 | _formatDesc, 1, 0, NULL, 1, 230 | &sampleSize, &sampleBuffer); 231 | 232 | // NSLog(@"\t\t SampleBufferCreate: \t %@", (status == noErr) ? @"successful!" : @"failed..."); 233 | } 234 | 235 | if(status == noErr) 236 | { 237 | // set some values of the sample buffer's attachments 238 | CFArrayRef attachments = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, YES); 239 | CFMutableDictionaryRef dict = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachments, 0); 240 | CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue); 241 | 242 | // either send the samplebuffer to a VTDecompressionSession or to an AVSampleBufferDisplayLayer 243 | [self render:sampleBuffer]; 244 | } 245 | 246 | // free memory to avoid a memory leak, do the same for sps, pps and blockbuffer 247 | if (NULL != data) 248 | { 249 | free (data); 250 | data = NULL; 251 | } 252 | } 253 | 254 | -(void) createDecompSession 255 | { 256 | // make sure to destroy the old VTD session 257 | _decompressionSession = NULL; 258 | VTDecompressionOutputCallbackRecord callBackRecord; 259 | callBackRecord.decompressionOutputCallback = decompressionSessionDecodeFrameCallback; 260 | 261 | // this is necessary if you need to make calls to Objective C "self" from within in the callback method. 262 | callBackRecord.decompressionOutputRefCon = (__bridge void *)self; 263 | 264 | // you can set some desired attributes for the destination pixel buffer. I didn't use this but you may 265 | // if you need to set some attributes, be sure to uncomment the dictionary in VTDecompressionSessionCreate 266 | // NSDictionary *destinationImageBufferAttributes = [NSDictionary dictionaryWithObjectsAndKeys: 267 | // [NSNumber numberWithBool:YES], 268 | // (id)kCVPixelBufferOpenGLESCompatibilityKey, 269 | // nil]; 270 | 271 | OSStatus status = VTDecompressionSessionCreate(NULL, _formatDesc, NULL, 272 | NULL, // (__bridge CFDictionaryRef)(destinationImageBufferAttributes) 273 | &callBackRecord, &_decompressionSession); 274 | // NSLog(@"Video Decompression Session Create: \t %@", (status == noErr) ? @"successful!" : @"failed..."); 275 | if(status != noErr) NSLog(@"\t\t VTD ERROR type: %d", (int)status); 276 | } 277 | 278 | void decompressionSessionDecodeFrameCallback(void *decompressionOutputRefCon, 279 | void *sourceFrameRefCon, 280 | OSStatus status, 281 | VTDecodeInfoFlags infoFlags, 282 | CVImageBufferRef imageBuffer, 283 | CMTime presentationTimeStamp, 284 | CMTime presentationDuration) 285 | { 286 | H264HWDecoder *streamManager = (__bridge H264HWDecoder *)decompressionOutputRefCon; 287 | 288 | if (status != noErr) 289 | { 290 | NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; 291 | // NSLog(@"Decompressed error: %@", error); 292 | } 293 | else 294 | { 295 | // NSLog(@"Decompressed sucessfully"); 296 | 297 | // do something with your resulting CVImageBufferRef that is your decompressed frame 298 | if(streamManager.delegate != nil) 299 | { 300 | [streamManager.delegate displayDecodedFrame:imageBuffer]; 301 | } 302 | } 303 | } 304 | 305 | - (void) render:(CMSampleBufferRef)sampleBuffer 306 | { 307 | VTDecodeFrameFlags flags = kVTDecodeFrame_EnableAsynchronousDecompression; 308 | VTDecodeInfoFlags flagOut; 309 | NSDate* currentTime = [NSDate date]; 310 | VTDecompressionSessionDecodeFrame(_decompressionSession, sampleBuffer, flags, 311 | (void*)CFBridgingRetain(currentTime), &flagOut); 312 | CFBridgingRelease((void*)CFBridgingRetain(currentTime)); 313 | CFRelease(sampleBuffer); 314 | 315 | //if you're using AVSampleBufferDisplayLayer, you only need to use this line of code 316 | // [videoLayer enqueueSampleBuffer:sampleBuffer]; 317 | } 318 | 319 | @end 320 | -------------------------------------------------------------------------------- /EasyCamera_iOS/EasyCamera/EasyDarwinInfoViewController.xib: -------------------------------------------------------------------------------- 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 | 32 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 177 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | -------------------------------------------------------------------------------- /EasyCamera_iOS/Encoder/CameraEncoder.m: -------------------------------------------------------------------------------- 1 | // 2 | // CameraEncoder.m 3 | // EasyCapture 4 | // 5 | // Created by phylony on 9/11/16. 6 | // Copyright © 2016 phylony. All rights reserved. 7 | // 8 | #import "CameraEncoder.h" 9 | 10 | 11 | //char* ConfigIP = "121.40.50.44"; //Default EasyDarwin Address 12 | //char* ConfigIP = "114.55.107.180"; 13 | ////char* ConfigPort = "554"; //Default EasyDarwin Port 14 | //char* ConfigPort = "10554"; 15 | char* ConfigName = "ios11.sdp";//Default Push StreamName 16 | char* ConfigUName = "admin"; //SDK UserName 17 | char* ConfigPWD = "admin"; //SDK Password 18 | char* ConfigDHost = "192.168.66.189"; //SDK Host 19 | char* ConfigDPort = "80"; //SDK Port 20 | char *ProgName; //Program Name 21 | static CameraEncoder *selfClass =nil; 22 | @interface CameraEncoder () 23 | { 24 | H264HWEncoder *h264Encoder; 25 | 26 | AACEncoder *aacEncoder; 27 | Easy_I32 isActivated; 28 | Easy_Pusher_Handle handle; 29 | 30 | dispatch_queue_t encodeQueue; 31 | 32 | // NSString *h264File; 33 | // NSString *aacFile; 34 | // NSFileHandle *fileH264Handle; 35 | // NSFileHandle *fileAACHandle; 36 | } 37 | 38 | @end 39 | 40 | @implementation CameraEncoder 41 | @synthesize running; 42 | 43 | - (void)initCameraWithOutputSize:(CGSize)size 44 | { 45 | h264Encoder = [[H264HWEncoder alloc] init]; 46 | [h264Encoder setOutputSize:size]; 47 | h264Encoder.delegate = self; 48 | 49 | #if TARGET_OS_IPHONE 50 | aacEncoder = [[AACEncoder alloc] init]; 51 | aacEncoder.delegate = self; 52 | #endif 53 | 54 | running = NO; 55 | /* 56 | 激活授权码, 57 | */ 58 | if (EasyPusher_Activate("6A36334A742F2B32734B79416B68745A707552476350564659584E355548567A614756794931634D56714459384F424859585A7062695A4359574A76633246414D6A41784E6B566863336C4559584A33615735555A5746745A57467A65513D3D") == 0) { 59 | if (_delegate) { 60 | [_delegate getConnectStatus:@"激活成功" isFist:1]; 61 | } 62 | 63 | }else{ 64 | [_delegate getConnectStatus:@"激活失败" isFist:1]; 65 | // NSLog(@"激活失败"); 66 | } 67 | 68 | handle = EasyPusher_Create(); 69 | EasyPusher_SetEventCallback(handle,easyPusher_Callback, 1, "123"); 70 | 71 | _encodeVideoQueue = dispatch_queue_create( "encodeVideoQueue", DISPATCH_QUEUE_SERIAL ); 72 | _encodeAudioQueue = dispatch_queue_create( "encodeAudioQueue", DISPATCH_QUEUE_SERIAL ); 73 | CMSimpleQueueCreate(kCFAllocatorDefault, 2, &vbuffQueue); 74 | CMSimpleQueueCreate(kCFAllocatorDefault, 2, &abuffQueue); 75 | _videoCaptureSession = [[AVCaptureSession alloc] init]; 76 | [self setupAudioCapture]; 77 | [self setupVideoCapture]; 78 | 79 | encodeQueue = dispatch_queue_create("encodeQueue", NULL); 80 | selfClass =self; 81 | } 82 | 83 | - (void)dealloc { 84 | #if TARGET_OS_IPHONE 85 | [h264Encoder invalidate]; 86 | #endif 87 | running = NO; 88 | } 89 | 90 | #pragma mark - Camera Control 91 | 92 | 93 | - (void)setupAudioCapture 94 | { 95 | AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio]; 96 | NSError *error = nil; 97 | AVCaptureDeviceInput *audioInput = [[AVCaptureDeviceInput alloc]initWithDevice:audioDevice error:&error]; 98 | 99 | if (error) { 100 | NSLog(@"Error getting audio input device:%@",error.description); 101 | } 102 | if ([self.videoCaptureSession canAddInput:audioInput]) { 103 | [self.videoCaptureSession addInput:audioInput]; 104 | } 105 | 106 | self.AudioQueue = dispatch_queue_create("Audio Capture Queue", DISPATCH_QUEUE_SERIAL); 107 | AVCaptureAudioDataOutput *audioOutput = [AVCaptureAudioDataOutput new]; 108 | 109 | [audioOutput setSampleBufferDelegate:self queue:self.AudioQueue]; 110 | 111 | if ([self.videoCaptureSession canAddOutput:audioOutput]) { 112 | 113 | [self.videoCaptureSession addOutput:audioOutput]; 114 | } 115 | self.audioConnection = [audioOutput connectionWithMediaType:AVMediaTypeAudio]; 116 | } 117 | 118 | - (void)swapResolution{ 119 | [self.videoCaptureSession beginConfiguration]; 120 | NSString *resolution = [[NSUserDefaults standardUserDefaults] objectForKey:@"resolition"]; 121 | if ([resolution isEqualToString:@"480*640"]){ 122 | if ([self.videoCaptureSession canSetSessionPreset:AVCaptureSessionPreset640x480]) { 123 | self.videoCaptureSession.sessionPreset = AVCaptureSessionPreset640x480; 124 | } 125 | }else if ([resolution isEqualToString:@"720*1280"]){ 126 | if ([self.videoCaptureSession canSetSessionPreset:AVCaptureSessionPreset1280x720]) { 127 | self.videoCaptureSession.sessionPreset = AVCaptureSessionPreset1280x720; 128 | } 129 | }else if ([resolution isEqualToString:@"1080*1920"]){ 130 | if ([self.videoCaptureSession canSetSessionPreset:AVCaptureSessionPreset1920x1080]) { 131 | self.videoCaptureSession.sessionPreset = AVCaptureSessionPreset1920x1080; 132 | } 133 | }else if ([resolution isEqualToString:@"288*352"]){ 134 | if ([self.videoCaptureSession canSetSessionPreset:AVCaptureSessionPreset352x288]) { 135 | self.videoCaptureSession.sessionPreset = AVCaptureSessionPreset352x288; 136 | } 137 | } 138 | [self.videoCaptureSession commitConfiguration]; 139 | } 140 | 141 | #pragma mark - 设置视频 capture 3 142 | - (void)setupVideoCapture { 143 | // if ([self.videoCaptureSession canSetSessionPreset:AVCaptureSessionPreset1280x720]) { 144 | // // 设置分辨率 145 | // self.videoCaptureSession.sessionPreset = AVCaptureSessionPreset1280x720; 146 | // } 147 | 148 | NSString *resolution = [[NSUserDefaults standardUserDefaults] objectForKey:@"resolition"]; 149 | if ([resolution isEqualToString:@"480*640"]){ 150 | if ([self.videoCaptureSession canSetSessionPreset:AVCaptureSessionPreset640x480]) { 151 | self.videoCaptureSession.sessionPreset = AVCaptureSessionPreset640x480; 152 | } 153 | }else if ([resolution isEqualToString:@"720*1280"]){ 154 | if ([self.videoCaptureSession canSetSessionPreset:AVCaptureSessionPreset1280x720]) { 155 | self.videoCaptureSession.sessionPreset = AVCaptureSessionPreset1280x720; 156 | } 157 | }else if ([resolution isEqualToString:@"1080*1920"]){ 158 | if ([self.videoCaptureSession canSetSessionPreset:AVCaptureSessionPreset1920x1080]) { 159 | self.videoCaptureSession.sessionPreset = AVCaptureSessionPreset1920x1080; 160 | } 161 | }else if ([resolution isEqualToString:@"288*352"]){ 162 | if ([self.videoCaptureSession canSetSessionPreset:AVCaptureSessionPreset352x288]) { 163 | self.videoCaptureSession.sessionPreset = AVCaptureSessionPreset352x288; 164 | } 165 | } 166 | // 167 | //设置采集的 Video 和 Audio 格式,这两个是分开设置的,也就是说,你可以只采集视频。 168 | //配置采集输入源(摄像头) 169 | 170 | NSError *error = nil; 171 | //获得一个采集设备, 例如前置/后置摄像头 172 | AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 173 | 174 | // videoDevice = [self cameraWithPosition:AVCaptureDevicePositionBack]; 175 | // videoDevice.position = AVCaptureDevicePositionBack; 176 | //用设备初始化一个采集的输入对象 177 | AVCaptureDeviceInput *videoInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error]; 178 | if (error) { 179 | NSLog(@"Error getting video input device:%@",error.description); 180 | } 181 | if ([self.videoCaptureSession canAddInput:videoInput]) { 182 | [self.videoCaptureSession addInput:videoInput]; 183 | } 184 | //配置采集输出,即我们取得视频图像的接口 185 | _videoQueue = dispatch_queue_create("Video Capture Queue", DISPATCH_QUEUE_SERIAL); 186 | _videoOutput = [AVCaptureVideoDataOutput new]; 187 | [_videoOutput setSampleBufferDelegate:self queue:_videoQueue]; 188 | // 配置输出视频图像格式 189 | NSDictionary *captureSettings = @{(NSString*)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA)}; 190 | _videoOutput.videoSettings = captureSettings; 191 | _videoOutput.alwaysDiscardsLateVideoFrames = YES; 192 | if ([self.videoCaptureSession canAddOutput:_videoOutput]) { 193 | [self.videoCaptureSession addOutput:_videoOutput]; 194 | } 195 | // 设置采集图像的方向,如果不设置,采集回来的图形会是旋转90度的 196 | _videoConnection = [_videoOutput connectionWithMediaType:AVMediaTypeVideo]; 197 | _videoConnection.videoOrientation = AVCaptureVideoOrientationPortrait; 198 | // 保存Connection,用于SampleBufferDelegate中判断数据来源(video or audio?) 199 | _videoConnection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto; 200 | _videoConnection = [_videoOutput connectionWithMediaType:AVMediaTypeVideo]; 201 | //将当前硬件采集视频图像显示到屏幕 202 | // 添加预览 203 | self.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.videoCaptureSession]; 204 | [self.previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill]; 205 | } 206 | 207 | - (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition)position{ 208 | NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; 209 | for (AVCaptureDevice *device in devices ) 210 | if ( device.position == position ) 211 | return device; 212 | return nil; 213 | } 214 | 215 | - (void)swapFrontAndBackCameras { 216 | // Assume the session is already running 217 | NSArray *inputs =self.videoCaptureSession.inputs; 218 | for (AVCaptureDeviceInput *input in inputs ) { 219 | AVCaptureDevice *device = input.device; 220 | if ( [device hasMediaType:AVMediaTypeVideo] ) { 221 | AVCaptureDevicePosition position = device.position; 222 | AVCaptureDevice *newCamera =nil; 223 | AVCaptureDeviceInput *newInput =nil; 224 | CATransition *animation = [CATransition animation]; 225 | animation.duration = .5f; 226 | animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 227 | animation.type = @"oglFlip"; 228 | 229 | if (position ==AVCaptureDevicePositionFront){ 230 | newCamera = [self cameraWithPosition:AVCaptureDevicePositionBack]; 231 | animation.subtype = kCATransitionFromLeft;//动画翻转方向 232 | } 233 | else{ 234 | newCamera = [self cameraWithPosition:AVCaptureDevicePositionFront]; 235 | animation.subtype = kCATransitionFromRight;//动画翻转方向 236 | } 237 | 238 | newInput = [AVCaptureDeviceInput deviceInputWithDevice:newCamera error:nil]; 239 | [self.previewLayer addAnimation:animation forKey:nil]; 240 | // beginConfiguration ensures that pending changes are not applied immediately 241 | 242 | [self.videoCaptureSession beginConfiguration]; 243 | [self.videoCaptureSession removeInput:input]; 244 | if ([self.videoCaptureSession canAddInput:newInput]) { 245 | [self.videoCaptureSession addInput:newInput]; 246 | 247 | } else { 248 | [self.videoCaptureSession addInput:input]; 249 | } 250 | [self.videoCaptureSession removeOutput:_videoOutput]; 251 | 252 | AVCaptureVideoDataOutput * new_videoOutput = [AVCaptureVideoDataOutput new]; 253 | _videoOutput = new_videoOutput; 254 | [new_videoOutput setSampleBufferDelegate:self queue:_videoQueue]; 255 | // 配置输出视频图像格式 256 | NSDictionary *captureSettings = @{(NSString*)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA)}; 257 | new_videoOutput.videoSettings = captureSettings; 258 | new_videoOutput.alwaysDiscardsLateVideoFrames = YES; 259 | if ([self.videoCaptureSession canAddOutput:new_videoOutput]) { 260 | [self.videoCaptureSession addOutput:new_videoOutput]; 261 | } 262 | // 设置采集图像的方向,如果不设置,采集回来的图形会是旋转90度的 263 | _videoConnection = [new_videoOutput connectionWithMediaType:AVMediaTypeVideo]; 264 | _videoConnection.videoOrientation = AVCaptureVideoOrientationPortrait; 265 | // 保存Connection,用于SampleBufferDelegate中判断数据来源(video or audio?) 266 | _videoConnection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto; 267 | _videoConnection = [new_videoOutput connectionWithMediaType:AVMediaTypeVideo]; 268 | 269 | // Changes take effect once the outermost commitConfiguration is invoked. 270 | [self.videoCaptureSession commitConfiguration]; 271 | break; 272 | } 273 | } 274 | } 275 | 276 | - (void)startCapture 277 | { 278 | [self.videoCaptureSession startRunning]; 279 | } 280 | 281 | #pragma mark --开始推流 282 | - (void) startCamera:(NSString *)hostUrl 283 | { 284 | EASY_MEDIA_INFO_T mediainfo; 285 | memset(&mediainfo, 0, sizeof(EASY_MEDIA_INFO_T)); 286 | mediainfo.u32VideoCodec = EASY_SDK_VIDEO_CODEC_H264; 287 | mediainfo.u32VideoFps = 25; 288 | mediainfo.u32AudioCodec = EASY_SDK_AUDIO_CODEC_AAC;//SDK output Audio PCMA 289 | mediainfo.u32AudioSamplerate = 44100; 290 | mediainfo.u32AudioChannel = 2; 291 | // mediainfo.u32AudioSamplerate = 8000; 292 | // mediainfo.u32AudioChannel = 1; 293 | mediainfo.u32AudioBitsPerSample = 16; 294 | const char *expr = [[[NSUserDefaults standardUserDefaults] objectForKey:@"ConfigIP"] UTF8String]; 295 | char *ConfigIP = malloc(strlen(expr)+1); 296 | strcpy(ConfigIP, expr); 297 | const char *exIp = [[[NSUserDefaults standardUserDefaults] objectForKey:@"ConfigPORT"] cStringUsingEncoding:NSUTF8StringEncoding]; 298 | char *ConfigPort = malloc(strlen(exIp) + 1); 299 | strcpy(ConfigPort, exIp); 300 | 301 | NSString *nameString = [hostUrl copy]; 302 | const char *exName = [nameString cStringUsingEncoding:NSUTF8StringEncoding]; 303 | char *name = malloc(strlen(exName)+1); 304 | strcpy(name, exName); 305 | 306 | 307 | EasyPusher_StartStream(handle, ConfigIP, atoi(ConfigPort), name, "admin", "admin", &mediainfo, 1024, false);//1M缓冲区 308 | running = YES; 309 | free(name); 310 | free(ConfigIP); 311 | free(ConfigPort); 312 | } 313 | 314 | int easyPusher_Callback(int _id, EASY_PUSH_STATE_T _state, EASY_AV_Frame *_frame, void *_userptr) 315 | { 316 | // const char *expr = [[[NSUserDefaults standardUserDefaults] objectForKey:@"ConfigIP"] UTF8String]; 317 | // char *ConfigIP = malloc(strlen(expr)+1); 318 | // strcpy(ConfigIP, expr); 319 | // const char *exIp = [[[NSUserDefaults standardUserDefaults] objectForKey:@"ConfigPORT"] cStringUsingEncoding:NSUTF8StringEncoding]; 320 | // char *ConfigPort = malloc(strlen(exIp) + 1); 321 | // strcpy(ConfigPort, exIp); 322 | if (_state == EASY_PUSH_STATE_CONNECTING) { 323 | if (selfClass.delegate) { 324 | [selfClass.delegate getConnectStatus:@"连接中" isFist:0]; 325 | } 326 | } 327 | else if (_state == EASY_PUSH_STATE_CONNECTED) { 328 | if (selfClass.delegate) { 329 | [selfClass.delegate getConnectStatus:@"连接成功" isFist:0]; 330 | } 331 | } 332 | 333 | else if (_state == EASY_PUSH_STATE_CONNECT_FAILED) { 334 | if (selfClass.delegate) { 335 | [selfClass.delegate getConnectStatus:@"连接失败" isFist:0]; 336 | } 337 | } 338 | 339 | else if (_state == EASY_PUSH_STATE_CONNECT_ABORT) { 340 | if (selfClass.delegate) { 341 | [selfClass.delegate getConnectStatus:@"连接异常中断" isFist:0]; 342 | } 343 | } 344 | 345 | else if (_state == EASY_PUSH_STATE_PUSHING) { 346 | if (selfClass.delegate) { 347 | [selfClass.delegate getConnectStatus:@"推流中" isFist:0]; 348 | } 349 | } 350 | else if (_state == EASY_PUSH_STATE_DISCONNECTED) { 351 | if (selfClass.delegate) { 352 | [selfClass.delegate getConnectStatus:@"断开连接" isFist:0]; 353 | } 354 | } 355 | 356 | 357 | return 0; 358 | } 359 | 360 | - (void) stopCamera 361 | { 362 | running = NO; 363 | [h264Encoder invalidate]; 364 | EasyPusher_StopStream(handle); 365 | } 366 | 367 | 368 | -(void) captureOutput:(AVCaptureOutput*)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection*)connection 369 | { 370 | CFRetain(sampleBuffer); 371 | if(connection == self.videoConnection) 372 | { 373 | 374 | CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 375 | CVPixelBufferLockBaseAddress(imageBuffer,0); 376 | uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer); 377 | size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 378 | size_t width = CVPixelBufferGetWidth(imageBuffer); 379 | size_t height = CVPixelBufferGetHeight(imageBuffer); 380 | 381 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 382 | CGContextRef newContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); 383 | 384 | CGImageRef newImage = CGBitmapContextCreateImage(newContext); 385 | _screenShotImage = [UIImage imageWithCGImage:newImage scale:1.0 orientation:UIImageOrientationUp]; 386 | 387 | CGContextRelease(newContext); 388 | CGColorSpaceRelease(colorSpace); 389 | // NSData* imageData = UIImageJPEGRepresentation(image, 1.0); 390 | // _screenShotImage = [UIImage imageWithData:imageData];; 391 | // id object = (__bridge id)newImage; 392 | // // http://www.cnblogs.com/zzltjnh/p/3885012.html 393 | // [self.customLayer performSelectorOnMainThread:@selector(setContents:) withObject: object waitUntilDone:YES]; 394 | 395 | 396 | 397 | // release 398 | CGImageRelease(newImage); 399 | 400 | 401 | CVPixelBufferUnlockBaseAddress(imageBuffer, 0); 402 | // CFRelease(imageBuffer); 403 | if (running) 404 | { 405 | dispatch_async(encodeQueue, ^{ 406 | 407 | [h264Encoder encode:sampleBuffer]; 408 | CFRelease(sampleBuffer); 409 | }); 410 | } 411 | 412 | } 413 | else if(connection == self.audioConnection) 414 | { 415 | if (running) 416 | { 417 | dispatch_async(encodeQueue, ^{ 418 | 419 | [aacEncoder encode:sampleBuffer]; 420 | CFRelease(sampleBuffer); 421 | }); 422 | } 423 | 424 | } 425 | 426 | if (!running) 427 | { 428 | CFRelease(sampleBuffer); 429 | } 430 | } 431 | 432 | - (void)captureOutput:(AVCaptureOutput *)captureOutput didDropSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection 433 | { 434 | NSLog(@"drop frame"); 435 | } 436 | 437 | #pragma mark - H264HWEncoderDelegate declare 438 | 439 | - (void)gotH264EncodedData:(NSData *)packet keyFrame:(BOOL)keyFrame timestamp:(CMTime)timestamp error:(NSError*)error 440 | { 441 | // NSLog(@"gotH264EncodedData %d", (int)[packet length]); 442 | // 443 | // [fileH264Handle writeData:packet]; 444 | 445 | // if(isReadyVideo && isReadyAudio) [rtp_h264 publish:packet timestamp:timestamp payloadType:98]; 446 | 447 | // CGFloat secs = CMTimeGetSeconds(timestamp); 448 | // UInt32 uSecs = (secs - (int)secs) * 1000 * 1000; 449 | 450 | EASY_AV_Frame frame; 451 | frame.pBuffer=(void*)packet.bytes; 452 | frame.u32AVFrameFlag=EASY_SDK_VIDEO_FRAME_FLAG; 453 | frame.u32AVFrameLen=(Easy_U32)packet.length; 454 | // frame.u32TimestampSec = secs; //(Easy_U32)timestamp.value/timestamp.timescale; 455 | // frame.u32TimestampUsec = uSecs;//timestamp.value%timestamp.timescale/1000;å 456 | frame.u32TimestampSec = 0; 457 | frame.u32TimestampUsec = 0; 458 | frame.u32VFrameType= keyFrame ? EASY_SDK_VIDEO_FRAME_I : EASY_SDK_VIDEO_FRAME_P; 459 | 460 | if(running) 461 | { 462 | EasyPusher_PushFrame(handle, &frame); 463 | }//[publish:packet timestamp:timestamp payloadType:98]; 464 | } 465 | 466 | #if TARGET_OS_IPHONE 467 | #pragma mark - AACEncoderDelegate declare 468 | 469 | - (void)gotAACEncodedData:(NSData *)data timestamp:(CMTime)timestamp error:(NSError*)error 470 | { 471 | // NSLog(@"gotAACEncodedData %d", (int)[data length]); 472 | // 473 | // if (fileAACHandle != NULL) 474 | // { 475 | // [fileAACHandle writeData:data]; 476 | // } 477 | 478 | // if(isReadyVideo && isReadyAudio) [rtp_aac publish:data timestamp:timestamp payloadType:97]; 479 | CGFloat secs = CMTimeGetSeconds(timestamp); 480 | UInt32 uSecs = (secs - (int)secs) * 1000 * 1000; 481 | 482 | EASY_AV_Frame frame; 483 | frame.pBuffer=(void*)[data bytes]; 484 | frame.u32AVFrameLen = (Easy_U32)[data length]; 485 | frame.u32VFrameType = EASY_SDK_AUDIO_CODEC_AAC; 486 | frame.u32AVFrameFlag=EASY_SDK_AUDIO_FRAME_FLAG; 487 | 488 | frame.u32TimestampSec= secs;//(Easy_U32)timestamp.value/timestamp.timescale; 489 | frame.u32TimestampUsec = uSecs;//timestamp.value%timestamp.timescale; 490 | if(running) 491 | { 492 | EasyPusher_PushFrame(handle,&frame); 493 | }//[rtp_aac publish:data timestamp:timestamp payloadType:97]; 494 | 495 | } 496 | #endif 497 | 498 | 499 | @end 500 | --------------------------------------------------------------------------------