├── 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 | 
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 |
--------------------------------------------------------------------------------