Commit f2e2ed7862037df69b58e9d339987833d24fbaf9

Authored by 梁星国
1 parent fe1d43b1

提交

Showing 79 changed files with 4529 additions and 0 deletions
CNLiveAVCamera.podspec 0 → 100644
  1 +#
  2 +# Be sure to run `pod lib lint CNLiveAVCamera.podspec' to ensure this is a
  3 +# valid spec before submitting.
  4 +#
  5 +# Any lines starting with a # are optional, but their use is encouraged
  6 +# To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html
  7 +#
  8 +
  9 +Pod::Spec.new do |s|
  10 + s.name = 'CNLiveAVCamera'
  11 + s.version = '0.1.0'
  12 + s.summary = '常用相机'
  13 + s.description = <<-DESC
  14 +TODO: Add long description of the pod here.
  15 + DESC
  16 +
  17 + s.homepage = 'https://github.com/jyyjkt/CNLiveAVCamera'
  18 + # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
  19 + s.license = { :type => 'MIT', :file => 'LICENSE' }
  20 + s.author = { 'jyyjkt' => 'jyyjkt@qq.com' }
  21 + s.source = { :git => 'https://github.com/jyyjkt/CNLiveAVCamera.git', :tag => s.version.to_s }
  22 + # s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'
  23 + s.ios.deployment_target = '8.0'
  24 + s.source_files = 'CNLiveAVCamera/Classes/XFAVCamera/*.{h,m}'
  25 +
  26 +# s.resource_bundles = {
  27 +# 'CNLiveAVCamera' => ['CNLiveAVCamera/Assets/XFAVCamera/*']
  28 +# }
  29 + s.resources = 'CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle'
  30 +
  31 +
  32 + s.public_header_files = 'CNLiveAVCamera/Classes/XFAVCamera/*.h'
  33 + s.frameworks = 'UIKit', 'Photos'
  34 + s.dependency 'Masonry', '~> 1.0.2'
  35 +
  36 +end
CNLiveAVCamera/Assets/.gitkeep 0 → 100644
CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/Root.plist 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3 +<plist version="1.0">
  4 +<dict>
  5 + <key>StringsTable</key>
  6 + <string>Root</string>
  7 + <key>PreferenceSpecifiers</key>
  8 + <array>
  9 + <dict>
  10 + <key>Type</key>
  11 + <string>PSGroupSpecifier</string>
  12 + <key>Title</key>
  13 + <string>Group</string>
  14 + </dict>
  15 + <dict>
  16 + <key>Type</key>
  17 + <string>PSTextFieldSpecifier</string>
  18 + <key>Title</key>
  19 + <string>Name</string>
  20 + <key>Key</key>
  21 + <string>name_preference</string>
  22 + <key>DefaultValue</key>
  23 + <string></string>
  24 + <key>IsSecure</key>
  25 + <false/>
  26 + <key>KeyboardType</key>
  27 + <string>Alphabet</string>
  28 + <key>AutocapitalizationType</key>
  29 + <string>None</string>
  30 + <key>AutocorrectionType</key>
  31 + <string>No</string>
  32 + </dict>
  33 + <dict>
  34 + <key>Type</key>
  35 + <string>PSToggleSwitchSpecifier</string>
  36 + <key>Title</key>
  37 + <string>Enabled</string>
  38 + <key>Key</key>
  39 + <string>enabled_preference</string>
  40 + <key>DefaultValue</key>
  41 + <true/>
  42 + </dict>
  43 + <dict>
  44 + <key>Type</key>
  45 + <string>PSSliderSpecifier</string>
  46 + <key>Key</key>
  47 + <string>slider_preference</string>
  48 + <key>DefaultValue</key>
  49 + <real>0.5</real>
  50 + <key>MinimumValue</key>
  51 + <integer>0</integer>
  52 + <key>MaximumValue</key>
  53 + <integer>1</integer>
  54 + <key>MinimumValueImage</key>
  55 + <string></string>
  56 + <key>MaximumValueImage</key>
  57 + <string></string>
  58 + </dict>
  59 + </array>
  60 +</dict>
  61 +</plist>
CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/en.lproj/Root.strings 0 → 100644
1 Binary files /dev/null and b/CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/en.lproj/Root.strings differ 1 Binary files /dev/null and b/CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/en.lproj/Root.strings differ
CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/fb_chongpai.png 0 → 100644

1.98 KB

CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/fb_chongpai@2x.png 0 → 100644

3.38 KB

CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/fb_chongpai@3x.png 0 → 100644

4.87 KB

CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/fb_quxiaoxia.png 0 → 100644

1.26 KB

CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/fb_quxiaoxia@2x.png 0 → 100644

1.68 KB

CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/fb_quxiaoxia@3x.png 0 → 100644

1.96 KB

CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/fb_wancheng.png 0 → 100644

1.97 KB

CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/fb_wancheng@2x.png 0 → 100644

3.46 KB

CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/fb_wancheng@3x.png 0 → 100644

5.08 KB

CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/fb_xiangji.png 0 → 100644

1.32 KB

CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/fb_xiangji@2x.png 0 → 100644

1.68 KB

CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/fb_xiangji@3x.png 0 → 100644

2.27 KB

CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/gz_shoudian.png 0 → 100644

1.11 KB

CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/gz_shoudian2.png 0 → 100644

1.13 KB

CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/gz_shoudian2@2x.png 0 → 100644

1.34 KB

CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/gz_shoudian2@3x.png 0 → 100644

1.52 KB

CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/gz_shoudian@2x.png 0 → 100644

1.29 KB

CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/gz_shoudian@3x.png 0 → 100644

1.41 KB

CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/sight_video_focus@2x.png 0 → 100644

3.02 KB

CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/sight_video_focus@3x.png 0 → 100644

3.36 KB

CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/zhuangtai_kong.png 0 → 100644

7.43 KB

CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/zhuangtai_kong@2x.png 0 → 100644

20.7 KB

CNLiveAVCamera/Assets/XFAVCamera/XFAVCamera.bundle/zhuangtai_kong@3x.png 0 → 100644

41.3 KB

CNLiveAVCamera/Assets/image/fb_chongpai.png 0 → 100644

1.98 KB

CNLiveAVCamera/Assets/image/fb_chongpai@2x.png 0 → 100644

3.38 KB

CNLiveAVCamera/Assets/image/fb_chongpai@3x.png 0 → 100644

4.87 KB

CNLiveAVCamera/Assets/image/fb_quxiaoxia.png 0 → 100644

1.26 KB

CNLiveAVCamera/Assets/image/fb_quxiaoxia@2x.png 0 → 100644

1.68 KB

CNLiveAVCamera/Assets/image/fb_quxiaoxia@3x.png 0 → 100644

1.96 KB

CNLiveAVCamera/Assets/image/fb_wancheng.png 0 → 100644

1.97 KB

CNLiveAVCamera/Assets/image/fb_wancheng@2x.png 0 → 100644

3.46 KB

CNLiveAVCamera/Assets/image/fb_wancheng@3x.png 0 → 100644

5.08 KB

CNLiveAVCamera/Assets/image/fb_xiangji.png 0 → 100644

1.32 KB

CNLiveAVCamera/Assets/image/fb_xiangji@2x.png 0 → 100644

1.68 KB

CNLiveAVCamera/Assets/image/fb_xiangji@3x.png 0 → 100644

2.27 KB

CNLiveAVCamera/Assets/image/gz_shoudian.png 0 → 100644

1.11 KB

CNLiveAVCamera/Assets/image/gz_shoudian2.png 0 → 100644

1.13 KB

CNLiveAVCamera/Assets/image/gz_shoudian2@2x.png 0 → 100644

1.34 KB

CNLiveAVCamera/Assets/image/gz_shoudian2@3x.png 0 → 100644

1.52 KB

CNLiveAVCamera/Assets/image/gz_shoudian@2x.png 0 → 100644

1.29 KB

CNLiveAVCamera/Assets/image/gz_shoudian@3x.png 0 → 100644

1.41 KB

CNLiveAVCamera/Assets/image/sight_video_focus@2x.png 0 → 100644

3.02 KB

CNLiveAVCamera/Assets/image/sight_video_focus@3x.png 0 → 100644

3.36 KB

CNLiveAVCamera/Classes/.gitkeep 0 → 100644
CNLiveAVCamera/Classes/XFAVCamera/NSBundle+CNLiveXFCamera.h 0 → 100644
  1 +//
  2 +// NSBundle+CNLiveXFCamera.h
  3 +// CNLiveAVCamera
  4 +//
  5 +// Created by 梁星国 on 2018/12/8.
  6 +//
  7 +
  8 +#import <Foundation/Foundation.h>
  9 +
  10 +NS_ASSUME_NONNULL_BEGIN
  11 +
  12 +@interface NSBundle (CNLiveXFCamera)
  13 +
  14 +
  15 +/**
  16 + 取得相机包bundle
  17 +
  18 + @return 返回bundle
  19 + */
  20 ++ (NSBundle *)xf_imageBundle;
  21 +
  22 +/**
  23 + 取得Bundle
  24 +
  25 + @param cls 包中类名
  26 + @param package 包
  27 + @param bundleName bundle名
  28 + @return 返回bundle
  29 + */
  30 ++ (NSBundle *)xf_imageBundleWithCls:(id)cls package:(NSString *)package bundleName:(NSString *)bundleName;
  31 +
  32 +@end
  33 +
  34 +NS_ASSUME_NONNULL_END
  35 +
  36 +NS_ASSUME_NONNULL_BEGIN
  37 +
  38 +@interface UIImage (CNLiveXFCamera)
  39 +
  40 +
  41 +/**
  42 + 从bundle中取图片
  43 +
  44 + @param imageName 图片名
  45 + @return 图片
  46 + */
  47 ++ (UIImage *)imageFromBundle:(NSString *)imageName;
  48 +
  49 +@end
  50 +
  51 +NS_ASSUME_NONNULL_END
CNLiveAVCamera/Classes/XFAVCamera/NSBundle+CNLiveXFCamera.m 0 → 100644
  1 +//
  2 +// NSBundle+CNLiveXFCamera.m
  3 +// CNLiveAVCamera
  4 +//
  5 +// Created by 梁星国 on 2018/12/8.
  6 +//
  7 +
  8 +#import "NSBundle+CNLiveXFCamera.h"
  9 +#import "XFCameraController.h"
  10 +
  11 +@implementation NSBundle (CNLiveXFCamera)
  12 +
  13 +/**
  14 + 取得相机包bundle
  15 +
  16 + @return 返回bundle
  17 + */
  18 ++ (NSBundle *)xf_imageBundle {
  19 +
  20 + return [NSBundle xf_imageBundleWithCls:[XFCameraController class] package:@"CNLiveAVCamera.framework" bundleName:@"XFAVCamera"];
  21 +}
  22 +
  23 +
  24 +/**
  25 + 取得Bundle
  26 +
  27 + @param cls 包中类名
  28 + @param package 包
  29 + @param bundleName bundle名
  30 + @return 返回bundle
  31 + */
  32 ++ (NSBundle *)xf_imageBundleWithCls:(id)cls package:(NSString *)package bundleName:(NSString *)bundleName {
  33 +
  34 + NSBundle *bundle = [NSBundle bundleForClass:[cls class]];
  35 + NSURL *url = [bundle URLForResource:bundleName withExtension:@"bundle"];
  36 + if (!url) {
  37 + NSString *resource = [NSString stringWithFormat:@"%@/%@",package,bundleName];
  38 + NSString *path = [[NSBundle mainBundle] pathForResource:resource ofType:@"bundle"];
  39 + if (path) {
  40 + resource = [NSString stringWithFormat:@"%@",package];
  41 + path = [[NSBundle mainBundle] pathForResource:resource ofType:@"bundle"];
  42 + if (path) {
  43 + url = [NSURL fileURLWithPath:path];
  44 + }else {
  45 + url = nil;
  46 + }
  47 + }else{
  48 + url = [NSURL fileURLWithPath:path];
  49 + }
  50 + }
  51 +
  52 + if (url) {
  53 + return [NSBundle bundleWithURL:url];
  54 + }else {
  55 + return [NSBundle mainBundle];
  56 + }
  57 +
  58 +}
  59 +
  60 +
  61 +
  62 +@end
  63 +
  64 +
  65 +@implementation UIImage (CNLiveXFCamera)
  66 +
  67 +
  68 +/**
  69 + 从bundle中取图片
  70 +
  71 + @param imageName 图片名
  72 + @return 图片
  73 + */
  74 ++ (UIImage *)imageFromBundle:(NSString *)imageName{
  75 + NSBundle *bundle = [NSBundle xf_imageBundle];
  76 + NSString *name = [NSString stringWithFormat:@"%@",imageName];
  77 + name = [name stringByAppendingString:@"@2x"];
  78 + NSString *imagePath = [bundle pathForResource:name ofType:@"png"];
  79 + if (!imagePath) {
  80 + name = [name stringByReplacingOccurrencesOfString:@"@2x" withString:@"@3x"];
  81 + imagePath = [bundle pathForResource:name ofType:@"png"];
  82 + }
  83 + UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
  84 + return image;
  85 +}
  86 +
  87 +
  88 +@end
CNLiveAVCamera/Classes/XFAVCamera/XFCameraButton.h 0 → 100644
  1 +//
  2 +// XFCameraButton.h
  3 +//
  4 +//
  5 +// Created by xf-ling on 2017/6/1.
  6 +// Copyright © 2017年 LXF. All rights reserved.
  7 +//
  8 +
  9 +#import <UIKit/UIKit.h>
  10 +
  11 +typedef void(^TapEventBlock)(UITapGestureRecognizer *tapGestureRecognizer);
  12 +typedef void(^LongPressEventBlock)(UILongPressGestureRecognizer *longPressGestureRecognizer);
  13 +
  14 +@interface XFCameraButton : UIView
  15 +
  16 +/**
  17 + * 设置进度条的录制视频时长百分比 = 当前录制时间 / 最大录制时间
  18 + */
  19 +@property (nonatomic, assign) CGFloat progressPercentage;
  20 +
  21 ++ (instancetype)defaultCameraButton;
  22 +
  23 +/**
  24 + * 配置点击事件
  25 + */
  26 +- (void)configureTapCameraButtonEventWithBlock:(TapEventBlock)tapEventBlock;
  27 +
  28 +/**
  29 + * 配置按压事件
  30 + */
  31 +- (void)configureLongPressCameraButtonEventWithBlock:(LongPressEventBlock)longPressEventBlock;
  32 +
  33 +/**
  34 + * 开始录制前的准备动画
  35 + */
  36 +- (void)startShootAnimationWithDuration:(NSTimeInterval)duration;
  37 +
  38 +/**
  39 + * 结束摄影动画
  40 + */
  41 +- (void)stopShootAnimation;
  42 +
  43 +@end
CNLiveAVCamera/Classes/XFAVCamera/XFCameraButton.m 0 → 100644
  1 +//
  2 +// XFCameraButton.m
  3 +//
  4 +//
  5 +// Created by xf-ling on 2017/6/1.
  6 +// Copyright © 2017年 LXF. All rights reserved.
  7 +//
  8 +
  9 +#import "XFCameraButton.h"
  10 +
  11 +// 默认按钮大小
  12 +#define CAMERABUTTONWIDTH 75
  13 +#define TOUCHVIEWWIDTH 55
  14 +
  15 +// 录制时按钮的缩放比
  16 +#define SHOOTCAMERABUTTONSCALE 1.6f
  17 +#define SHOOTTOUCHVIEWSCALE 0.5f
  18 +
  19 +// 录制按钮动画轨道宽度
  20 +#define PROGRESSLINEWIDTH 3
  21 +
  22 +#ifndef CAMERA_RGB
  23 +#define CAMERA_RGB(r, g, b, a) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:a]
  24 +#endif
  25 +
  26 +@interface XFCameraButton ()
  27 +
  28 +@property (weak, nonatomic) UIView *touchView;
  29 +@property (strong, nonatomic) CAShapeLayer *trackLayer;
  30 +@property (strong, nonatomic) CAShapeLayer *progressLayer;
  31 +
  32 +@property (copy, nonatomic) TapEventBlock tapEventBlock;
  33 +@property (copy, nonatomic) LongPressEventBlock longPressEventBlock;
  34 +
  35 +@end
  36 +
  37 +@implementation XFCameraButton
  38 +
  39 +#pragma mark - 工厂方法
  40 +
  41 ++ (instancetype)defaultCameraButton
  42 +{
  43 + // 设置camera view
  44 + XFCameraButton *cameraButton = [[XFCameraButton alloc] initWithFrame:CGRectMake(0, 0, CAMERABUTTONWIDTH, CAMERABUTTONWIDTH)];
  45 + [cameraButton.layer setCornerRadius:(CAMERABUTTONWIDTH / 2)];
  46 + cameraButton.backgroundColor = [UIColor whiteColor];//[UIColor colorWithRed:225/255.0f green:225/255.0f blue:230/255.0f alpha:1.0f];
  47 +
  48 + // 设置camera view的点击按钮
  49 + CGFloat touchViewX = (CAMERABUTTONWIDTH - TOUCHVIEWWIDTH) / 2;
  50 + CGFloat touchViewY = (CAMERABUTTONWIDTH - TOUCHVIEWWIDTH) / 2;
  51 + UIView *touchView = [[UIView alloc] initWithFrame:CGRectMake(touchViewX, touchViewY, TOUCHVIEWWIDTH, TOUCHVIEWWIDTH)];
  52 + cameraButton.touchView = touchView;
  53 + [cameraButton addSubview:touchView];
  54 + [cameraButton.touchView.layer setCornerRadius:(cameraButton.touchView.bounds.size.width / 2)];
  55 + touchView.backgroundColor = CAMERA_RGB(255, 163, 0, 1);
  56 +
  57 + [cameraButton initCircleAnimationLayer];
  58 +
  59 + return cameraButton;
  60 +}
  61 +
  62 +
  63 +#pragma mark - 点击事件与长按事件
  64 +
  65 +/**
  66 + * 配置点击事件
  67 + */
  68 +- (void)configureTapCameraButtonEventWithBlock:(TapEventBlock)tapEventBlock
  69 +{
  70 + self.tapEventBlock = tapEventBlock;
  71 +
  72 + UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapCameraButtonEvent:)];
  73 +
  74 + [self.touchView addGestureRecognizer:tapGestureRecognizer];
  75 +}
  76 +
  77 +- (void)tapCameraButtonEvent:(UITapGestureRecognizer *)tapGestureRecognizer
  78 +{
  79 + if (self.tapEventBlock)
  80 + {
  81 + self.tapEventBlock(tapGestureRecognizer);
  82 + }
  83 +}
  84 +
  85 +/**
  86 + * 配置按压事件
  87 + */
  88 +- (void)configureLongPressCameraButtonEventWithBlock:(LongPressEventBlock)longPressEventBlock
  89 +{
  90 + self.longPressEventBlock = longPressEventBlock;
  91 +
  92 + UILongPressGestureRecognizer *longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressCameraButtonEvent:)];
  93 +
  94 + [self.touchView addGestureRecognizer:longPressGestureRecognizer];
  95 +}
  96 +
  97 +- (void)longPressCameraButtonEvent:(UILongPressGestureRecognizer *)longPressGestureRecognizer
  98 +{
  99 + if (self.longPressEventBlock)
  100 + {
  101 + self.longPressEventBlock(longPressGestureRecognizer);
  102 + }
  103 +}
  104 +
  105 +#pragma mark - 录制视频按钮动画
  106 +
  107 +// 初始化按钮路径
  108 +- (void)initCircleAnimationLayer
  109 +{
  110 + float centerX = self.bounds.size.width / 2.0;
  111 + float centerY = self.bounds.size.height / 2.0;
  112 + //半径
  113 + float radius = (self.bounds.size.width - PROGRESSLINEWIDTH) / 2.0;
  114 +
  115 + //创建贝塞尔路径
  116 + UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(centerX, centerY) radius:radius startAngle:(-0.5f * M_PI) endAngle:(1.5f * M_PI) clockwise:YES];
  117 +
  118 + //添加背景圆环
  119 + CAShapeLayer *backLayer = [CAShapeLayer layer];
  120 + backLayer.frame = self.bounds;
  121 + backLayer.fillColor = [[UIColor clearColor] CGColor];
  122 + backLayer.strokeColor = CAMERA_RGB(242, 242, 242,1).CGColor;//[RGB(225, 225, 230, 1.0f) CGColor];
  123 + backLayer.lineWidth = PROGRESSLINEWIDTH;
  124 + backLayer.path = [path CGPath];
  125 + backLayer.strokeEnd = 1;
  126 + [self.layer addSublayer:backLayer];
  127 +
  128 + //创建进度layer
  129 + _progressLayer = [CAShapeLayer layer];
  130 + _progressLayer.frame = self.bounds;
  131 + _progressLayer.fillColor = [[UIColor clearColor] CGColor];
  132 + //指定path的渲染颜色
  133 + _progressLayer.strokeColor = [[UIColor blackColor] CGColor];
  134 + _progressLayer.lineCap = kCALineCapSquare;//kCALineCapRound;
  135 + _progressLayer.lineWidth = PROGRESSLINEWIDTH;
  136 + _progressLayer.path = [path CGPath];
  137 + _progressLayer.strokeEnd = 0;
  138 +
  139 + //设置渐变颜色
  140 + CAGradientLayer *gradientLayer = [CAGradientLayer layer];
  141 + gradientLayer.frame = self.bounds;
  142 +
  143 + // 渐变颜色
  144 + [gradientLayer setColors:[NSArray arrayWithObjects:(id)[CAMERA_RGB(255, 163, 0,1) CGColor], (id)[CAMERA_RGB(255, 163, 0, 1) CGColor], nil]];//RGB(76, 192, 29, 1.0f) [RGB(76, 192, 29, 1.0f) CGColor]
  145 +// [gradientLayer setColors:[NSArray arrayWithObjects:(id)[RGB(28, 178, 29, 1.0f) CGColor], (id)[RGB(255, 203, 0, 1.0f) CGColor], nil]];
  146 +
  147 + gradientLayer.startPoint = CGPointMake(0, 0);
  148 + gradientLayer.endPoint = CGPointMake(0, 1);
  149 + [gradientLayer setMask:_progressLayer]; //用progressLayer来截取渐变层
  150 + [self.layer addSublayer:gradientLayer];
  151 +
  152 +}
  153 +
  154 +// 设置按钮百分比
  155 +- (void)setProgressPercentage:(CGFloat)progressPercentage
  156 +{
  157 + _progressPercentage = progressPercentage;
  158 + _progressLayer.strokeEnd = progressPercentage;
  159 + [_progressLayer removeAllAnimations];
  160 +}
  161 +
  162 +/**
  163 + * 开始录制前的准备动画
  164 + */
  165 +- (void)startShootAnimationWithDuration:(NSTimeInterval)duration
  166 +{
  167 + __weak typeof(self) weakSelf = self;
  168 +
  169 + [UIView animateWithDuration:duration animations:^{
  170 +
  171 + weakSelf.transform = CGAffineTransformMakeScale(SHOOTCAMERABUTTONSCALE, SHOOTCAMERABUTTONSCALE);
  172 + weakSelf.touchView.transform = CGAffineTransformMakeScale(SHOOTTOUCHVIEWSCALE, SHOOTTOUCHVIEWSCALE);
  173 +
  174 + } completion:^(BOOL finished) {
  175 + // nothing
  176 + }];
  177 +}
  178 +
  179 +/**
  180 + * 结束摄影动画
  181 + */
  182 +- (void)stopShootAnimation
  183 +{
  184 + self.transform = CGAffineTransformIdentity;
  185 + self.touchView.transform = CGAffineTransformIdentity;
  186 +}
  187 +
  188 +
  189 +@end
  190 +
  191 +
  192 +
  193 +
  194 +
  195 +
  196 +
  197 +
  198 +
  199 +
CNLiveAVCamera/Classes/XFAVCamera/XFCameraController.h 0 → 100644
  1 +//
  2 +// QXCameraController.h
  3 +//
  4 +//
  5 +// Created by xf-ling on 2017/6/1.
  6 +// Copyright © 2017年 LXF. All rights reserved.
  7 +//
  8 +
  9 +#import <UIKit/UIKit.h>
  10 +#import <Photos/Photos.h>
  11 +
  12 +@interface UIControl (CameraEventInterval)
  13 +
  14 +@property (nonatomic, assign) NSTimeInterval camera_cs_acceptEventInterval; // 重复点击的间隔
  15 +
  16 +@property (nonatomic, assign) NSTimeInterval camera_cs_acceptEventTime;
  17 +
  18 +@end
  19 +
  20 +
  21 +typedef void(^TakePhotosCompletionBlock)(UIImage *image, NSError *error);
  22 +typedef void(^ShootCompletionBlock)(NSURL *videoUrl, CGFloat videoTimeLength, UIImage *thumbnailImage, NSError *error);
  23 +
  24 +//zx
  25 +typedef void(^ZXShootCompletionBlock)(PHAsset *asset,NSURL *videoUrl, CGFloat videoTimeLength, UIImage *thumbnailImage, NSError *error);
  26 +
  27 +@interface XFCameraController : UIViewController
  28 +
  29 +/**
  30 + * 拍照完成后的Block回调
  31 + */
  32 +@property (copy, nonatomic) TakePhotosCompletionBlock takePhotosCompletionBlock;
  33 +
  34 +/**
  35 + * 拍摄完成后的Block回调
  36 + */
  37 +@property (copy, nonatomic) ShootCompletionBlock shootCompletionBlock;
  38 +
  39 +/**
  40 + * zx拍摄完成后的Block回调
  41 + */
  42 +@property (copy, nonatomic) ZXShootCompletionBlock zxshootCompletionBlock;
  43 +
  44 +/**
  45 + * 自定义APP相册名字,如果为空则默认为APP的名字
  46 + */
  47 +@property (strong, nonatomic) NSString *assetCollectionName;
  48 +
  49 +/**
  50 + * 视频文件保存文件夹,如果没有定义,默认在document/video文件夹下面
  51 + */
  52 +@property (strong, nonatomic) NSString *videoFilePath;
  53 +
  54 +
  55 +//zx 当前是否可以拍摄视频 BOOL
  56 +@property (nonatomic ,assign) BOOL isCanShootVideo;
  57 +
  58 +//zl__会话ID,用于存储拍摄的视频
  59 +@property (nonatomic ,strong) NSString *conversationId;
  60 +
  61 +@end
CNLiveAVCamera/Classes/XFAVCamera/XFCameraController.m 0 → 100644
  1 +//
  2 +// QXCameraController.m
  3 +//
  4 +//
  5 +// Created by xf-ling on 2017/6/1.
  6 +// Copyright © 2017年 LXF. All rights reserved.
  7 +//
  8 +
  9 +#import "XFCameraController.h"
  10 +#import <AVFoundation/AVFoundation.h>
  11 +#import <AssetsLibrary/AssetsLibrary.h>
  12 +#import "XFCameraButton.h"
  13 +#import "XFPhotoLibraryManager.h"
  14 +#import <Photos/Photos.h>
  15 +#import <CoreMotion/CoreMotion.h>
  16 +#import <Masonry/Masonry.h>
  17 +#import <objc/runtime.h>
  18 +#import <UIKit/UIKit.h>
  19 +#import "NSBundle+CNLiveXFCamera.h"
  20 +
  21 +
  22 +#ifndef kCameraScreenWidth
  23 +#define kCameraScreenWidth [UIScreen mainScreen].bounds.size.width
  24 +#endif
  25 +#ifndef kCameraScreenHeight
  26 +#define kCameraScreenHeight [UIScreen mainScreen].bounds.size.height
  27 +#endif
  28 +
  29 +#define SafeViewBottomHeight (kCameraScreenHeight == 812.0 ? 34.0 : 0.0)
  30 +#define VIDEO_FILEPATH @"video"
  31 +#define TIMER_INTERVAL 0.01f //定时器记录视频间隔
  32 +#define VIDEO_RECORDER_MAX_TIME 15.0f //视频最大时长 (单位/秒)
  33 +#define VIDEO_RECORDER_MIN_TIME 2.0f //最短视频时长 (单位/秒)
  34 +#define START_VIDEO_ANIMATION_DURATION 0.3f //录制视频前的动画时间
  35 +
  36 +#define CAMERA_IS_IPhoneX_All (CGSizeEqualToSize([UIScreen mainScreen].bounds.size, CGSizeMake(375, 812)) ||CGSizeEqualToSize([UIScreen mainScreen].bounds.size, CGSizeMake(812, 375)) ||CGSizeEqualToSize([UIScreen mainScreen].bounds.size, CGSizeMake(414, 896)) ||CGSizeEqualToSize([UIScreen mainScreen].bounds.size, CGSizeMake(896, 414)))
  37 +
  38 +#define kCameraStatusHeight (int)[UIApplication sharedApplication].statusBarFrame.size.height //x44 非x20
  39 +#define kCameraNavigationBarHeight ((int)[UIApplication sharedApplication].statusBarFrame.size.height+44) //x88 非x64
  40 +#define kCameraVerticalNaviBarHeight ((CAMERA_IS_IPhoneX_All > 0) ? 88 : 44)
  41 +#define kCameraVerticalTabBarTotalHeight ((CAMERA_IS_IPhoneX_All > 0) ? 83 : 49)
  42 +#define kCameraVerticalBottomSafeHeight ((CAMERA_IS_IPhoneX_All > 0) ? 34 : 0)
  43 +#define kCameraVerticalStatusHeight ((CAMERA_IS_IPhoneX_All > 0) ? 44 : 20)
  44 +#define kCameraVerticalTopHeight ((CAMERA_IS_IPhoneX_All > 0) ? 24 : 0)
  45 +#define kCameraHorizontalTopNaviBarHeight 32
  46 +#define kCameraHorizontalBottomHeight ((CAMERA_IS_IPhoneX_All > 0) ? 21 : 0)
  47 +#define kCameraHorizontalLeftHeight ((CAMERA_IS_IPhoneX_All > 0) ? 44 : 0)
  48 +#define kCameraHorizontalRightHeight ((CAMERA_IS_IPhoneX_All > 0) ? 44 : 0)
  49 +#define kCameraHorizontalTopHeight ((CAMERA_IS_IPhoneX_All > 0) ? 24 : 0)
  50 +
  51 +#define CameraImageMake(img) [UIImage imageNamed:img inBundle:nil compatibleWithTraitCollection:nil]
  52 +
  53 +@implementation UIControl (CNEventInterval)
  54 +
  55 +static const char *UIControl_acceptEventInterval = "UIControl_acceptEventInterval";
  56 +- (NSTimeInterval)camera_cs_acceptEventInterval {
  57 + return [objc_getAssociatedObject(self, UIControl_acceptEventInterval) doubleValue];
  58 +}
  59 +
  60 +- (void)setCamera_cs_acceptEventInterval:(NSTimeInterval)camera_cs_acceptEventInterval {
  61 + objc_setAssociatedObject(self, UIControl_acceptEventInterval, @(camera_cs_acceptEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  62 +}
  63 +
  64 +static const char *UIControl_acceptEventTime = "UIControl_acceptEventTime";
  65 +
  66 +- (NSTimeInterval)camera_cs_acceptEventTime {
  67 + return [objc_getAssociatedObject(self, UIControl_acceptEventTime) doubleValue];
  68 +}
  69 +
  70 +- (void)setCamera_cs_acceptEventTime:(NSTimeInterval)camera_cs_acceptEventTime {
  71 + objc_setAssociatedObject(self, UIControl_acceptEventTime, @(camera_cs_acceptEventTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  72 +}
  73 +
  74 +
  75 +// 在load时执行hook
  76 ++ (void)load {
  77 + Method before = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));
  78 + Method after = class_getInstanceMethod(self, @selector(cs_sendAction:to:forEvent:));
  79 + method_exchangeImplementations(before, after);
  80 +}
  81 +
  82 +- (void)cs_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
  83 + if ([NSDate date].timeIntervalSince1970 - self.camera_cs_acceptEventTime < self.camera_cs_acceptEventInterval) {
  84 + return;
  85 + }
  86 + if (self.camera_cs_acceptEventInterval > 0) {
  87 + self.camera_cs_acceptEventTime = [NSDate date].timeIntervalSince1970;
  88 + }
  89 +
  90 + [self cs_sendAction:action to:target forEvent:event];
  91 +}
  92 +
  93 +@end
  94 +
  95 +
  96 +typedef void(^PropertyChangeBlock)(AVCaptureDevice *captureDevice);
  97 +
  98 +@interface XFCameraController() <AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAudioDataOutputSampleBufferDelegate, UIGestureRecognizerDelegate>
  99 +{
  100 + BOOL _isPicOrVideo;//已经拍照或者录制视频标识,进入后台时不dismiss
  101 +}
  102 +@property (nonatomic ,assign) BOOL isAlertShow;
  103 +@property (nonatomic, strong) dispatch_queue_t videoQueue;
  104 +
  105 +@property (strong, nonatomic) AVCaptureSession *captureSession; //负责输入和输出设备之间的数据传递
  106 +
  107 +@property (nonatomic, strong) AVCaptureDeviceInput *videoInput; //视频输入
  108 +@property (nonatomic, strong) AVCaptureDeviceInput *audioInput; //声音输入
  109 +@property (nonatomic, strong) AVCaptureVideoDataOutput *videoOutput;
  110 +@property (nonatomic, strong) AVCaptureAudioDataOutput *audioOutput;
  111 +
  112 +@property (strong, nonatomic) AVCaptureStillImageOutput *captureStillImageOutput; //照片输出流
  113 +
  114 +@property (nonatomic, strong) AVAssetWriter *assetWriter;
  115 +@property (nonatomic, strong) AVAssetWriterInput *assetWriterVideoInput;
  116 +@property (nonatomic, strong) AVAssetWriterInput *assetWriterAudioInput;
  117 +@property (nonatomic, strong) NSDictionary *videoCompressionSettings;
  118 +@property (nonatomic, strong) NSDictionary *audioCompressionSettings;
  119 +@property (nonatomic, assign) BOOL canWrite;
  120 +
  121 +@property (strong, nonatomic) AVCaptureVideoPreviewLayer *captureVideoPreviewLayer; //预览图层
  122 +
  123 +@property (nonatomic, strong) NSTimer *timer; //记录录制时间
  124 +
  125 +@property (nonatomic, strong) UIButton *rotateCameraButton;
  126 +@property (nonatomic, strong) UIButton *flashButton;
  127 +@property (nonatomic, strong) UIButton *takeButton; //拍摄按钮
  128 +@property (nonatomic, strong) UIButton *closeButton;
  129 +@property (nonatomic, strong) UILabel *tipLabel;
  130 +@property (strong, nonatomic) XFCameraButton *cameraButton; //拍摄按钮
  131 +
  132 +@property (nonatomic, strong) UIImageView *focusImageView; //聚焦视图
  133 +@property (assign, nonatomic) Boolean isFocusing; //镜头正在聚焦
  134 +@property (assign, nonatomic) Boolean isTakingPhoto; //正在拍摄照片 lxg
  135 +@property (assign, nonatomic) Boolean isShooting; //正在拍摄
  136 +@property (assign, nonatomic) Boolean isRotatingCamera; //正在旋转摄像头
  137 +
  138 +//捏合缩放摄像头
  139 +@property (nonatomic,assign) CGFloat beginGestureScale; //记录开始的缩放比例
  140 +@property (nonatomic,assign) CGFloat effectiveScale; //最后的缩放比例
  141 +
  142 +// 拍照摄像后的预览模块
  143 +@property (nonatomic, strong) UIButton *cancelButton;
  144 +@property (nonatomic, strong) UIButton *confirmButton;
  145 +@property (strong, nonatomic) UIView *photoPreviewContainerView; //相片预览ContainerView
  146 +@property (strong, nonatomic) UIImageView *photoPreviewImageView; //相片预览ImageView
  147 +@property (strong, nonatomic) UIView *videoPreviewContainerView; //视频预览View
  148 +@property (strong, nonatomic) NSURL *videoURL; //视频文件地址
  149 +@property (strong, nonatomic) AVPlayerLayer *playerLayer;
  150 +@property (strong, nonatomic) AVPlayer *player;
  151 +@property (strong, nonatomic) AVPlayerItem *playerItem;
  152 +@property (assign, nonatomic) CGFloat currentVideoTimeLength; //当前小视频总时长
  153 +
  154 +@property (assign, nonatomic) UIDeviceOrientation shootingOrientation; //拍摄中的手机方向
  155 +@property (strong, nonatomic) CMMotionManager *motionManager;
  156 +
  157 +@end
  158 +
  159 +@implementation XFCameraController{
  160 +
  161 + CGFloat timeLength; //时间长度
  162 +
  163 +}
  164 +
  165 +#pragma mark - 控制器方法
  166 +
  167 +- (void)viewDidLoad
  168 +{
  169 + [super viewDidLoad];
  170 + self.view.backgroundColor = [UIColor blackColor];
  171 +
  172 + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(enterBackgroundNotification) name:UIApplicationDidEnterBackgroundNotification object:nil];
  173 +
  174 + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
  175 +
  176 + // 隐藏状态栏
  177 + // [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
  178 + [UIApplication sharedApplication].statusBarHidden = YES;
  179 +
  180 + _isFocusing = NO;
  181 + _isTakingPhoto = NO;
  182 + _isShooting = NO;
  183 + _isRotatingCamera = NO;
  184 + _canWrite = NO;
  185 + _beginGestureScale = 1.0f;
  186 + _effectiveScale = 1.0f;
  187 +
  188 + [self.view addSubview:self.rotateCameraButton];
  189 + [self.view addSubview:self.flashButton];
  190 + [self.view addSubview:self.takeButton];
  191 + [self.view addSubview:self.closeButton];
  192 + [self.view addSubview:self.tipLabel];
  193 + [self.view addSubview:self.focusImageView];
  194 + [self.view addSubview:self.cancelButton];
  195 + [self.view addSubview:self.confirmButton];
  196 +
  197 + CGFloat rotateOffest = CAMERA_IS_IPhoneX_All ? kCameraNavigationBarHeight : 20 ;
  198 + [self.rotateCameraButton mas_makeConstraints:^(MASConstraintMaker *make) {
  199 + make.width.mas_equalTo(50);
  200 + make.height.mas_equalTo(30);
  201 + make.top.mas_equalTo(self.view.mas_top).mas_offset(rotateOffest);
  202 + make.right.mas_equalTo(self.view.mas_right).mas_offset(-15);
  203 + }];
  204 +
  205 + [self.flashButton mas_makeConstraints:^(MASConstraintMaker *make) {
  206 + make.width.mas_equalTo(50);
  207 + make.height.mas_equalTo(30);
  208 + make.top.mas_equalTo(self.view.mas_top).mas_offset(rotateOffest);
  209 + make.right.mas_equalTo(self.rotateCameraButton.mas_left);
  210 + }];
  211 +
  212 + //拍摄按钮
  213 + CGFloat bottom = CAMERA_IS_IPhoneX_All ? -55-kCameraVerticalBottomSafeHeight : -20;
  214 + [self.takeButton mas_makeConstraints:^(MASConstraintMaker *make) {
  215 + make.width.mas_equalTo(120);
  216 + make.height.mas_equalTo(120);
  217 + make.centerX.mas_equalTo(self.view.mas_centerX);
  218 + make.bottom.mas_equalTo(self.view.mas_bottom).mas_offset(bottom);
  219 + }];
  220 +
  221 + [self.closeButton mas_makeConstraints:^(MASConstraintMaker *make) {
  222 + make.width.mas_equalTo(60);
  223 + make.height.mas_equalTo(30);
  224 + make.centerY.mas_equalTo(self.takeButton.mas_centerY);
  225 + make.right.mas_equalTo(self.takeButton.mas_left).mas_offset(-20);
  226 + }];
  227 +
  228 + [self.tipLabel mas_makeConstraints:^(MASConstraintMaker *make) {
  229 + make.centerX.mas_equalTo(self.view.mas_centerX);
  230 + make.bottom.mas_equalTo(self.takeButton.mas_top).mas_offset(-20);
  231 + }];
  232 +
  233 + [self.focusImageView mas_makeConstraints:^(MASConstraintMaker *make) {
  234 + make.width.mas_equalTo(60);
  235 + make.height.mas_equalTo(60);
  236 + make.centerX.mas_equalTo(self.view.mas_centerX);
  237 + make.centerY.mas_equalTo(self.view.mas_centerY);
  238 + }];
  239 +
  240 + [self.cancelButton mas_makeConstraints:^(MASConstraintMaker *make) {
  241 + make.width.mas_equalTo(60);
  242 + make.height.mas_equalTo(60);
  243 + make.left.mas_equalTo(self.view.mas_left).mas_offset(40);
  244 + make.bottom.mas_equalTo(self.view.mas_bottom).mas_offset(-60-kCameraVerticalBottomSafeHeight);
  245 + }];
  246 +
  247 + [self.confirmButton mas_makeConstraints:^(MASConstraintMaker *make) {
  248 + make.width.mas_equalTo(60);
  249 + make.height.mas_equalTo(60);
  250 + make.right.mas_equalTo(self.view.mas_right).mas_offset(-40);
  251 + make.bottom.mas_equalTo(self.cancelButton.mas_bottom);
  252 + }];
  253 +
  254 +}
  255 +
  256 +- (void)viewWillAppear:(BOOL)animated
  257 +{
  258 + [super viewWillAppear:animated];
  259 +
  260 + AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
  261 + if (authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied)
  262 + {
  263 + [self requestAuthorizationForVideo];
  264 + }
  265 +
  266 + //判断用户是否允许访问麦克风权限
  267 + authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
  268 + if (authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied)
  269 + {
  270 + [self requestAuthorizationForVideo];
  271 + }
  272 + [self requestAuthorizationForPhotoLibrary];
  273 +
  274 + [self initAVCaptureSession];
  275 +
  276 + [self configDefaultUIDisplay];
  277 +
  278 + [self addTapGenstureRecognizerForCamera];
  279 +
  280 +}
  281 +
  282 +- (void)viewDidAppear:(BOOL)animated
  283 +{
  284 + [super viewDidAppear:animated];
  285 +
  286 + [self startSession];
  287 +
  288 + [self setFocusCursorWithPoint:self.view.center];
  289 +
  290 + if (self.isCanShootVideo)
  291 + {
  292 + self.tipLabel.text = @"点击拍照,长按摄像";
  293 + }else
  294 + {
  295 + self.tipLabel.text = @"点击拍照,不可摄像";
  296 + }
  297 +
  298 + [self tipLabelAnimation];
  299 +
  300 +}
  301 +
  302 +- (void)viewWillDisappear:(BOOL)animated
  303 +{
  304 + [super viewWillDisappear:animated];
  305 +
  306 + [self setCaptureVideoPreviewLayerTransformWithScale:1.0f];
  307 +
  308 + // 显示状态栏
  309 + // [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];
  310 + [UIApplication sharedApplication].statusBarHidden = YES;
  311 +}
  312 +
  313 +- (BOOL)prefersStatusBarHidden
  314 +{
  315 + return YES;
  316 +}
  317 +
  318 +- (void)viewDidDisappear:(BOOL)animated
  319 +{
  320 + [super viewDidDisappear:animated];
  321 +
  322 + [self stopSession];
  323 +
  324 + [self stopUpdateAccelerometer];
  325 +}
  326 +
  327 +#pragma mark - 释放
  328 +- (void)dealloc
  329 +{
  330 + NSLog(@"XFCameraController 释放了");
  331 + [[NSNotificationCenter defaultCenter] removeObserver:self];
  332 +}
  333 +
  334 +- (void)didReceiveMemoryWarning
  335 +{
  336 + [super didReceiveMemoryWarning];
  337 +}
  338 +
  339 +#pragma mark - 控件方法
  340 +
  341 +/**
  342 + * 关闭当前界面
  343 + */
  344 +- (void)closeBtnFunc
  345 +{
  346 + [self dismissViewControllerAnimated:YES completion:nil];
  347 +}
  348 +
  349 +/**
  350 + * 切换前后摄像头
  351 + */
  352 +- (void)rotateCameraBtnFunc:(UIButton *)btn
  353 +{
  354 + btn.selected = !btn.selected;
  355 + if (btn.selected) {
  356 + self.flashButton.hidden = YES;
  357 + } else {
  358 + self.flashButton.hidden = NO;
  359 + }
  360 + _isRotatingCamera = YES;
  361 +
  362 + AVCaptureDevice *currentDevice = [self.videoInput device];
  363 + AVCaptureDevicePosition currentPosition = [currentDevice position];
  364 +
  365 + AVCaptureDevice *toChangeDevice;
  366 + AVCaptureDevicePosition toChangePosition = AVCaptureDevicePositionFront;
  367 + if (currentPosition == AVCaptureDevicePositionUnspecified || currentPosition == AVCaptureDevicePositionFront)
  368 + {
  369 + toChangePosition = AVCaptureDevicePositionBack;
  370 + }
  371 + toChangeDevice = [self getCameraDeviceWithPosition:toChangePosition];
  372 +
  373 + //获得要调整的设备输入对象
  374 + AVCaptureDeviceInput *toChangeDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:toChangeDevice error:nil];
  375 +
  376 + //改变会话的配置前一定要先开启配置,配置完成后提交配置改变
  377 + [self.captureSession beginConfiguration];
  378 + //移除原有输入对象
  379 + [self.captureSession removeInput:self.videoInput];
  380 + //添加新的输入对象
  381 + if ([self.captureSession canAddInput:toChangeDeviceInput])
  382 + {
  383 + [self.captureSession addInput:toChangeDeviceInput];
  384 + self.videoInput = toChangeDeviceInput;
  385 + }
  386 +
  387 + //提交会话配置
  388 + [self.captureSession commitConfiguration];
  389 +
  390 + _isRotatingCamera = NO;
  391 +}
  392 +
  393 +- (void)flashBtnFunc:(UIButton *)btn
  394 +{
  395 + btn.selected = !btn.selected;
  396 +#pragma mark - TODO: 更改是否打开手电筒
  397 + if (btn.selected)
  398 + {
  399 +// [SGQRCodeHelperTool SG_openFlashlight];
  400 + }else
  401 + {
  402 +// [SGQRCodeHelperTool SG_CloseFlashlight];
  403 + }
  404 +}
  405 +
  406 +- (void)cancelBtnfunc
  407 +{
  408 + _isTakingPhoto = NO;
  409 + [self removePlayerItemNotification];
  410 +
  411 + [self startAnimationGroup];
  412 +}
  413 +
  414 +/**
  415 + * 确认按钮并返回代理
  416 + */
  417 +- (void)confirmBtnFunc
  418 +{
  419 +
  420 + if (self.playerLayer) {
  421 + self.playerLayer.hidden = YES;
  422 + }
  423 +
  424 + if (self.captureVideoPreviewLayer) {
  425 + self.captureVideoPreviewLayer.hidden = NO;
  426 + }
  427 +
  428 + __weak typeof(self) weakSelf = self;
  429 + if (self.photoPreviewImageView)
  430 + {
  431 + UIImage *finalImage = [self cutImageWithView:self.photoPreviewImageView];
  432 +
  433 + // [XFPhotoLibraryManager savePhotoWithImage:finalImage andAssetCollectionName:self.assetCollectionName withCompletion:^(UIImage *image, NSError *error) {
  434 + //
  435 + if (self.takePhotosCompletionBlock)
  436 + {
  437 + // if (error)
  438 + // {
  439 + // NSLog(@"保存照片失败!");
  440 + // weakSelf.takePhotosCompletionBlock(nil, error);
  441 + // }
  442 + // else
  443 + // {
  444 + // NSLog(@"保存照片成功!");
  445 + weakSelf.takePhotosCompletionBlock(finalImage, nil);
  446 + // }
  447 + }
  448 +
  449 + // }];
  450 +
  451 + self.confirmButton.userInteractionEnabled = NO;
  452 +
  453 + }
  454 + else
  455 + {
  456 + [self.player.currentItem cancelPendingSeeks];
  457 + [self.player.currentItem.asset cancelLoading];
  458 + [self.player pause];
  459 +
  460 + _playerItem = nil;
  461 + [self.player replaceCurrentItemWithPlayerItem:nil];
  462 + self.player = nil;
  463 +
  464 + [_playerLayer removeFromSuperlayer];
  465 + _playerLayer = nil;
  466 +
  467 + [weakSelf cropWithVideoUrlStr:weakSelf.videoURL start:0 end:weakSelf.currentVideoTimeLength completion:^(NSURL *outputURL, Float64 videoDuration, BOOL isSuccess) {
  468 +
  469 + if (isSuccess)
  470 + {
  471 +
  472 + [XFPhotoLibraryManager zx_saveVideoWithVideoUrl:outputURL andAssetCollectionName:nil withCompletion:^(PHAsset *asset, NSURL *videoUrl, NSError *error) {
  473 + if (weakSelf.zxshootCompletionBlock)
  474 + {
  475 + if (error)
  476 + {
  477 + NSLog(@"保存视频失败!");
  478 + weakSelf.zxshootCompletionBlock(asset,nil, 0, nil, error);
  479 + }
  480 + else
  481 + {
  482 + NSLog(@"保存视频成功!");
  483 +
  484 + // 获取视频的第一帧图片
  485 + UIImage *image = [weakSelf thumbnailImageRequestWithVideoUrl:videoUrl andTime:0.01f];
  486 +
  487 +
  488 + weakSelf.zxshootCompletionBlock(asset,videoUrl, videoDuration, image, nil);
  489 +
  490 + [[NSFileManager defaultManager] removeItemAtURL:weakSelf.videoURL error:nil];
  491 + weakSelf.videoURL = nil;
  492 + }
  493 + }
  494 +
  495 + weakSelf.confirmButton.userInteractionEnabled = NO;
  496 + }];
  497 +
  498 + // [XFPhotoLibraryManager saveVideoWithVideoUrl:outputURL andAssetCollectionName:nil withCompletion:^(NSURL *videoUrl, NSError *error) {
  499 + //
  500 + // if (self.shootCompletionBlock)
  501 + // {
  502 + // if (error)
  503 + // {
  504 + // NSLog(@"保存视频失败!");
  505 + // weakSelf.shootCompletionBlock(nil, 0, nil, error);
  506 + // }
  507 + // else
  508 + // {
  509 + // NSLog(@"保存视频成功!");
  510 + //
  511 + // // 获取视频的第一帧图片
  512 + // UIImage *image = [weakSelf thumbnailImageRequestWithVideoUrl:videoUrl andTime:0.01f];
  513 + //
  514 + // weakSelf.shootCompletionBlock(videoUrl, videoDuration, image, nil);
  515 + //
  516 + // [[NSFileManager defaultManager] removeItemAtURL:weakSelf.videoURL error:nil];
  517 + // weakSelf.videoURL = nil;
  518 + // }
  519 + // }
  520 + //
  521 + // weakSelf.confirmButton.userInteractionEnabled = NO;
  522 + //
  523 + // }];
  524 + }
  525 + else
  526 + {
  527 + NSLog(@"保存视频失败!");
  528 + [[NSFileManager defaultManager] removeItemAtURL:weakSelf.videoURL error:nil];
  529 + weakSelf.videoURL = nil;
  530 + [[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil];
  531 + }
  532 + }];
  533 + }
  534 +}
  535 +
  536 +#pragma mark - 懒加载
  537 +- (AVCaptureSession *)captureSession
  538 +{
  539 + if (_captureSession == nil)
  540 + {
  541 + _captureSession = [[AVCaptureSession alloc] init];
  542 +
  543 + if ([_captureSession canSetSessionPreset:AVCaptureSessionPresetHigh])
  544 + {
  545 + _captureSession.sessionPreset = AVCaptureSessionPresetHigh;
  546 + }
  547 + }
  548 +
  549 + return _captureSession;
  550 +}
  551 +
  552 +- (dispatch_queue_t)videoQueue
  553 +{
  554 + if (!_videoQueue)
  555 + {
  556 + _videoQueue = dispatch_get_main_queue();
  557 + }
  558 +
  559 + return _videoQueue;
  560 +}
  561 +
  562 +- (CMMotionManager *)motionManager
  563 +{
  564 + if (!_motionManager)
  565 + {
  566 + _motionManager = [[CMMotionManager alloc] init];
  567 + }
  568 + return _motionManager;
  569 +}
  570 +
  571 +- (UIButton *)rotateCameraButton
  572 +{
  573 + if (!_rotateCameraButton)
  574 + {
  575 + _rotateCameraButton = [[UIButton alloc] init];
  576 + [_rotateCameraButton setImage:[UIImage imageFromBundle:@"fb_xiangji"] forState:UIControlStateNormal];
  577 + [_rotateCameraButton addTarget:self action:@selector(rotateCameraBtnFunc:) forControlEvents:UIControlEventTouchUpInside];
  578 + }
  579 + return _rotateCameraButton;
  580 +}
  581 +
  582 +- (UIButton *)flashButton
  583 +{
  584 + if (!_flashButton)
  585 + {
  586 + _flashButton = [[UIButton alloc] init];
  587 + [_flashButton setImage:[UIImage imageFromBundle:@"gz_shoudian"] forState:UIControlStateNormal];
  588 + [_flashButton setImage:[UIImage imageFromBundle:@"gz_shoudian2"] forState:UIControlStateSelected];
  589 + [_flashButton addTarget:self action:@selector(flashBtnFunc:) forControlEvents:UIControlEventTouchUpInside];
  590 + }
  591 + return _flashButton;
  592 +}
  593 +
  594 +//拍摄按钮
  595 +- (UIButton *)takeButton
  596 +{
  597 + if (!_takeButton)
  598 + {
  599 + _takeButton = [[UIButton alloc] init];
  600 + }
  601 +
  602 + return _takeButton;
  603 +}
  604 +
  605 +- (UIButton *)closeButton
  606 +{
  607 + if (!_closeButton)
  608 + {
  609 + _closeButton = [[UIButton alloc] init];
  610 + [_closeButton setImage:[UIImage imageFromBundle:@"fb_quxiaoxia"] forState:UIControlStateNormal];
  611 + [_closeButton addTarget:self action:@selector(closeBtnFunc) forControlEvents:UIControlEventTouchUpInside];
  612 + }
  613 + return _closeButton;
  614 +}
  615 +
  616 +- (UILabel *)tipLabel
  617 +{
  618 + if (!_tipLabel)
  619 + {
  620 + _tipLabel = [[UILabel alloc] init];
  621 + _tipLabel.font = [UIFont systemFontOfSize:14];
  622 + _tipLabel.textColor = [UIColor whiteColor];
  623 + }
  624 + return _tipLabel;
  625 +}
  626 +
  627 +- (UIImageView *)focusImageView
  628 +{
  629 + if (!_focusImageView)
  630 + {
  631 + _focusImageView = [[UIImageView alloc] init];
  632 + _focusImageView.image = [UIImage imageFromBundle:@"sight_video_focus"];
  633 + }
  634 + return _focusImageView;
  635 +}
  636 +
  637 +// 拍照摄像后的预览模块
  638 +- (UIButton *)cancelButton
  639 +{
  640 + if (!_cancelButton)
  641 + {
  642 + _cancelButton = [[UIButton alloc] init];
  643 + [_cancelButton setImage:[UIImage imageFromBundle:@"fb_chongpai"] forState:UIControlStateNormal];
  644 + [_cancelButton addTarget:self action:@selector(cancelBtnfunc) forControlEvents:UIControlEventTouchUpInside];
  645 + }
  646 + return _cancelButton;
  647 +}
  648 +
  649 +// 拍照摄像后的预览模块
  650 +- (UIButton *)confirmButton
  651 +{
  652 + if (!_confirmButton)
  653 + {
  654 + _confirmButton = [[UIButton alloc] init];
  655 + [_confirmButton setImage:[UIImage imageFromBundle:@"fb_wancheng"] forState:UIControlStateNormal];
  656 + [_confirmButton addTarget:self action:@selector(confirmBtnFunc) forControlEvents:UIControlEventTouchUpInside];
  657 + _confirmButton.camera_cs_acceptEventInterval = 2.0f;
  658 +
  659 + }
  660 + return _confirmButton;
  661 +}
  662 +
  663 +#pragma mark - 私有方法
  664 +
  665 +/**
  666 + * 初始化AVCapture会话
  667 + */
  668 +- (void)initAVCaptureSession
  669 +{
  670 + //1、添加 "视频" 与 "音频" 输入流到session
  671 + [self setupVideo];
  672 +
  673 + [self setupAudio];
  674 +
  675 + //2、添加图片,movie输出流到session
  676 + [self setupCaptureStillImageOutput];
  677 +
  678 + //3、创建视频预览层,用于实时展示摄像头状态
  679 + [self setupCaptureVideoPreviewLayer];
  680 +
  681 + //设置静音状态也可播放声音
  682 + AVAudioSession *audioSession = [AVAudioSession sharedInstance];
  683 + [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
  684 +}
  685 +
  686 +/**
  687 + * 设置视频输入
  688 + */
  689 +- (void)setupVideo
  690 +{
  691 + AVCaptureDevice *captureDevice = [self getCameraDeviceWithPosition:AVCaptureDevicePositionBack];
  692 + if (!captureDevice)
  693 + {
  694 + NSLog(@"取得后置摄像头时出现问题.");
  695 +
  696 + return;
  697 + }
  698 +
  699 + NSError *error = nil;
  700 + self.videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:captureDevice error:&error];
  701 + if (error)
  702 + {
  703 + NSLog(@"取得设备输入videoInput对象时出错,错误原因:%@", error);
  704 +
  705 + return;
  706 + }
  707 +
  708 + //3、将设备输出添加到会话中
  709 + if ([self.captureSession canAddInput:self.videoInput])
  710 + {
  711 + [self.captureSession addInput:self.videoInput];
  712 + }
  713 +
  714 + self.videoOutput = [[AVCaptureVideoDataOutput alloc] init];
  715 + self.videoOutput.alwaysDiscardsLateVideoFrames = YES; //立即丢弃旧帧,节省内存,默认YES
  716 + [self.videoOutput setSampleBufferDelegate:self queue:self.videoQueue];
  717 + if ([self.captureSession canAddOutput:self.videoOutput])
  718 + {
  719 + [self.captureSession addOutput:self.videoOutput];
  720 + }
  721 +}
  722 +
  723 +/**
  724 + * 设置音频录入
  725 + */
  726 +- (void)setupAudio
  727 +{
  728 + NSError *error = nil;
  729 + self.audioInput = [[AVCaptureDeviceInput alloc] initWithDevice:[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio] error:&error];
  730 + if (error)
  731 + {
  732 + NSLog(@"取得设备输入audioInput对象时出错,错误原因:%@", error);
  733 +
  734 + return;
  735 + }
  736 + if ([self.captureSession canAddInput:self.audioInput])
  737 + {
  738 + [self.captureSession addInput:self.audioInput];
  739 + }
  740 +
  741 + self.audioOutput = [[AVCaptureAudioDataOutput alloc] init];
  742 + [self.audioOutput setSampleBufferDelegate:self queue:self.videoQueue];
  743 + if([self.captureSession canAddOutput:self.audioOutput])
  744 + {
  745 + [self.captureSession addOutput:self.audioOutput];
  746 + }
  747 +}
  748 +
  749 +/**
  750 + * 设置图片输出
  751 + */
  752 +- (void)setupCaptureStillImageOutput
  753 +{
  754 + self.captureStillImageOutput = [[AVCaptureStillImageOutput alloc] init];
  755 + NSDictionary *outputSettings = @{
  756 + AVVideoCodecKey:AVVideoCodecJPEG
  757 + };
  758 + [_captureStillImageOutput setOutputSettings:outputSettings];
  759 +
  760 + if ([self.captureSession canAddOutput:_captureStillImageOutput])
  761 + {
  762 + [self.captureSession addOutput:_captureStillImageOutput];
  763 + }
  764 +}
  765 +
  766 +/**
  767 + * 设置预览layer
  768 + */
  769 +- (void)setupCaptureVideoPreviewLayer
  770 +{
  771 + _captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];
  772 +
  773 + CALayer *layer = self.view.layer;
  774 +
  775 + _captureVideoPreviewLayer.frame = CGRectMake(0, 0, kCameraScreenWidth, kCameraScreenHeight);
  776 +
  777 + CGFloat centerY = self.view.frame.origin.y + self.view.frame.size.height * 0.5;
  778 + CGRect frame = _captureVideoPreviewLayer.frame;
  779 + frame.origin.y = centerY - frame.size.height * 0.5;
  780 + _captureVideoPreviewLayer.frame = frame;
  781 +
  782 + _captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspect; //填充模式
  783 +
  784 + [layer addSublayer:_captureVideoPreviewLayer];
  785 +}
  786 +
  787 +/**
  788 + * 开启会话
  789 + */
  790 +- (void)startSession
  791 +{
  792 + if (![self.captureSession isRunning])
  793 + {
  794 + [self.captureSession startRunning];
  795 + }
  796 +}
  797 +
  798 +/**
  799 + * 停止会话
  800 + */
  801 +- (void)stopSession
  802 +{
  803 + if ([self.captureSession isRunning])
  804 + {
  805 + [self.captureSession stopRunning];
  806 + }
  807 +}
  808 +
  809 +/**
  810 + * 开始拍照录像动画组合
  811 + */
  812 +- (void)startAnimationGroup
  813 +{
  814 + [self configDefaultUIDisplay];
  815 +
  816 + [self setFocusCursorWithPoint:self.view.center];
  817 +
  818 +
  819 +
  820 + [self tipLabelAnimation];
  821 +}
  822 +
  823 +/**
  824 + * 配置默认UI信息
  825 + */
  826 +- (void)configDefaultUIDisplay
  827 +{
  828 + _isPicOrVideo = NO;
  829 + if (self.photoPreviewImageView)//图片设置置空
  830 + {
  831 + [self.photoPreviewImageView removeFromSuperview];
  832 + [self.photoPreviewContainerView removeFromSuperview];
  833 + self.photoPreviewImageView = nil;
  834 + self.photoPreviewContainerView = nil;
  835 + }
  836 + if (self.playerLayer)//视频设置置空
  837 + {
  838 + [self.player pause];
  839 + self.player = nil;
  840 + self.playerItem = nil;
  841 + self.playerLayer.hidden = YES;
  842 + [self.playerLayer removeFromSuperlayer];
  843 + self.playerLayer = nil;
  844 + self.cameraButton.progressPercentage = 0.0f;
  845 + self.videoPreviewContainerView = nil;
  846 + [[NSFileManager defaultManager] removeItemAtURL:self.videoURL error:nil];
  847 + self.videoURL = nil;
  848 + }
  849 + if (self.captureVideoPreviewLayer) {
  850 + self.captureVideoPreviewLayer.hidden = NO;
  851 + }
  852 +
  853 + //更改
  854 + if (_captureVideoPreviewLayer.superlayer == self.view.layer) {
  855 + [_captureVideoPreviewLayer removeFromSuperlayer];
  856 + [self.view.layer insertSublayer:_captureVideoPreviewLayer atIndex:(unsigned)self.view.layer.sublayers.count];
  857 + }
  858 +
  859 + [self.view bringSubviewToFront:self.rotateCameraButton];
  860 + [self.view bringSubviewToFront:self.flashButton];
  861 + [self.view bringSubviewToFront:self.closeButton];
  862 + [self.rotateCameraButton setHidden:NO];
  863 + [self.flashButton setHidden:NO];
  864 + [self.closeButton setHidden:NO];
  865 +
  866 +
  867 + [self.view bringSubviewToFront:self.tipLabel];
  868 + [self.tipLabel setAlpha:0];
  869 +
  870 + [self.cancelButton setHidden:YES];
  871 + [self.confirmButton setHidden:YES];
  872 +
  873 + // 设置拍照按钮
  874 + if (_cameraButton == nil)
  875 + {
  876 + XFCameraButton *cameraButton = [XFCameraButton defaultCameraButton];
  877 + _cameraButton = cameraButton;
  878 +
  879 + [self.view addSubview:cameraButton];
  880 + CGFloat cameraBtnX = (kCameraScreenWidth - cameraButton.bounds.size.width) / 2;
  881 +
  882 + CGFloat bottom = CAMERA_IS_IPhoneX_All ? 90 + SafeViewBottomHeight : 20+30;
  883 +
  884 + CGFloat cameraBtnY = kCameraScreenHeight - cameraButton.bounds.size.height - bottom; //距离底部60
  885 + cameraButton.frame = CGRectMake(cameraBtnX, cameraBtnY, cameraButton.bounds.size.width, cameraButton.bounds.size.height);
  886 + [self.view bringSubviewToFront:cameraButton];
  887 +
  888 + // 设置拍照按钮点击事件
  889 + __weak typeof(self) weakSelf = self;
  890 + // 配置拍照方法
  891 + [cameraButton configureTapCameraButtonEventWithBlock:^(UITapGestureRecognizer *tapGestureRecognizer) {
  892 + if (self->_isTakingPhoto) {
  893 + return;
  894 + }
  895 + [weakSelf requestAuthCamera];
  896 + [weakSelf takePhotos:tapGestureRecognizer];
  897 +
  898 + }];
  899 + if (self.isCanShootVideo) {
  900 + // 配置拍摄方法
  901 + [cameraButton configureLongPressCameraButtonEventWithBlock:^(UILongPressGestureRecognizer *longPressGestureRecognizer) {
  902 + [weakSelf requestAuthorizationForVideo];
  903 + [weakSelf longPressCameraButtonFunc:longPressGestureRecognizer];
  904 + }];
  905 + }
  906 + }
  907 + [self.cameraButton setHidden:NO];
  908 + [self.view bringSubviewToFront:self.cameraButton];
  909 +
  910 + [self setCaptureVideoPreviewLayerTransformWithScale:1.0f];
  911 +
  912 + // 对焦imageView
  913 + [self.view bringSubviewToFront:self.focusImageView];
  914 + [self.focusImageView setAlpha:0];
  915 +
  916 + // 监听屏幕方向
  917 + [self startUpdateAccelerometer];
  918 +}
  919 +
  920 +/**
  921 + * 提示语动画
  922 + */
  923 +- (void)tipLabelAnimation
  924 +{
  925 + [self.view bringSubviewToFront:self.tipLabel];
  926 +
  927 + __weak typeof(self) weakSelf = self;
  928 + [UIView animateWithDuration:1.0f delay:0.5f options:UIViewAnimationOptionCurveEaseInOut animations:^{
  929 +
  930 + [weakSelf.tipLabel setAlpha:1];
  931 +
  932 + } completion:^(BOOL finished) {
  933 +
  934 + [UIView animateWithDuration:1.0f delay:3.0f options:UIViewAnimationOptionCurveEaseInOut animations:^{
  935 +
  936 + [weakSelf.tipLabel setAlpha:0];
  937 +
  938 + } completion:nil];
  939 +
  940 + }];
  941 +}
  942 +
  943 +/**
  944 + * 取得指定位置的摄像头
  945 + *
  946 + * @param position 摄像头位置
  947 + *
  948 + * @return 摄像头设备
  949 + */
  950 +- (AVCaptureDevice *)getCameraDeviceWithPosition:(AVCaptureDevicePosition )position
  951 +{
  952 + NSArray *cameras = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
  953 + for (AVCaptureDevice *camera in cameras)
  954 + {
  955 + if ([camera position] == position)
  956 + {
  957 + return camera;
  958 + }
  959 + }
  960 + return nil;
  961 +}
  962 +
  963 +/**
  964 + * 改变设备属性的统一操作方法
  965 + *
  966 + * @param propertyChange 属性改变操作
  967 + */
  968 +- (void)changeDeviceProperty:(PropertyChangeBlock)propertyChange
  969 +{
  970 + AVCaptureDevice *captureDevice = [self.videoInput device];
  971 + NSError *error;
  972 +
  973 + //注意改变设备属性前一定要首先调用lockForConfiguration:调用完之后使用unlockForConfiguration方法解锁
  974 + if ([captureDevice lockForConfiguration:&error])
  975 + {
  976 + propertyChange(captureDevice);
  977 + [captureDevice unlockForConfiguration];
  978 + }
  979 + else
  980 + {
  981 + NSLog(@"设置设备属性过程发生错误,错误信息:%@",error.localizedDescription);
  982 + }
  983 +}
  984 +
  985 +#pragma mark - 拍照功能
  986 +
  987 +/**
  988 + * 拍照方法
  989 + */
  990 +- (void)takePhotos:(UITapGestureRecognizer *)tapGestureRecognizer
  991 +{
  992 +
  993 + __weak typeof(self) weakSelf = self;
  994 + // 请求相机权限
  995 + AVAuthorizationStatus videoAuthStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
  996 + if (videoAuthStatus != AVAuthorizationStatusAuthorized)
  997 + {
  998 + NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
  999 +
  1000 + NSString *appName = [infoDictionary objectForKey:@"CFBundleDisplayName"];
  1001 + if (appName == nil)
  1002 + {
  1003 + appName = @"APP";
  1004 + }
  1005 + NSString *message = [NSString stringWithFormat:@"请在iPhone的“设置-隐私”选项中,允许%@访问你的相册,相机和麦克风。", appName];
  1006 +
  1007 + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"" message:message preferredStyle:UIAlertControllerStyleAlert];//无法拍摄
  1008 +
  1009 + UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  1010 + [weakSelf dismissViewControllerAnimated:YES completion:nil];
  1011 + }];
  1012 +
  1013 + [alertController addAction:okAction];
  1014 + [self presentViewController:alertController animated:YES completion:nil];
  1015 +
  1016 + return;
  1017 + }
  1018 +
  1019 + // 请求麦克风权限
  1020 + AVAuthorizationStatus audioAuthStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
  1021 + if (audioAuthStatus != AVAuthorizationStatusAuthorized)
  1022 + {
  1023 + NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
  1024 +
  1025 + NSString *appName = [infoDictionary objectForKey:@"CFBundleDisplayName"];
  1026 + if (appName == nil)
  1027 + {
  1028 + appName = @"APP";
  1029 + }
  1030 + NSString *message = [NSString stringWithFormat:@"请在iPhone的“设置-隐私“选项中,允许%@访问你的相册,相机和麦克风。", appName];//[NSString stringWithFormat:@"请在iPhone的““设置-隐私””选项中, 允许%@访问你的麦克风?", appName];
  1031 +
  1032 + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"" message:message preferredStyle:UIAlertControllerStyleAlert];
  1033 +
  1034 + UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  1035 + [weakSelf dismissViewControllerAnimated:YES completion:nil];
  1036 + }];
  1037 +
  1038 + [alertController addAction:okAction];
  1039 +
  1040 + [self presentViewController:alertController animated:YES completion:nil];
  1041 +
  1042 + return;
  1043 + }
  1044 +
  1045 + _isTakingPhoto = YES;
  1046 + //根据设备输出获得连接
  1047 + AVCaptureConnection *captureConnection = [self.captureStillImageOutput connectionWithMediaType:AVMediaTypeVideo];
  1048 +
  1049 + [captureConnection setVideoScaleAndCropFactor:self.effectiveScale];
  1050 +
  1051 + //根据连接取得设备输出的数据
  1052 + [self.captureStillImageOutput captureStillImageAsynchronouslyFromConnection:captureConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
  1053 + if (imageDataSampleBuffer)
  1054 + {
  1055 + NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
  1056 + UIImage *image = [UIImage imageWithData:imageData];
  1057 +
  1058 + [self previewPhotoWithImage:image];
  1059 +
  1060 + self->_isTakingPhoto = YES;
  1061 + }else{
  1062 + self->_isTakingPhoto = NO;
  1063 + }
  1064 +
  1065 + }];
  1066 +}
  1067 +
  1068 +/**
  1069 + * 预览图片
  1070 + */
  1071 +- (void)previewPhotoWithImage:(UIImage *)image
  1072 +{
  1073 + [self stopUpdateAccelerometer];
  1074 +
  1075 + [self.cameraButton setHidden:YES];
  1076 + [self.closeButton setHidden:YES];
  1077 + [self.rotateCameraButton setHidden:YES];
  1078 + [self.flashButton setHidden:YES];
  1079 +
  1080 + UIImage *finalImage = nil;
  1081 + if (self.shootingOrientation == UIDeviceOrientationLandscapeRight)
  1082 + {
  1083 + finalImage = [self rotateImage:image withOrientation:UIImageOrientationDown];
  1084 + }
  1085 + else if (self.shootingOrientation == UIDeviceOrientationLandscapeLeft)
  1086 + {
  1087 + finalImage = [self rotateImage:image withOrientation:UIImageOrientationUp];
  1088 + }
  1089 + else if (self.shootingOrientation == UIDeviceOrientationPortraitUpsideDown)
  1090 + {
  1091 + finalImage = [self rotateImage:image withOrientation:UIImageOrientationLeft];
  1092 + }
  1093 + else
  1094 + {
  1095 + finalImage = [self rotateImage:image withOrientation:UIImageOrientationRight];
  1096 + }
  1097 +
  1098 + self.photoPreviewImageView = [[UIImageView alloc] init];
  1099 + float videoRatio = finalImage.size.width / finalImage.size.height;
  1100 + if (self.shootingOrientation == UIDeviceOrientationLandscapeRight || self.shootingOrientation == UIDeviceOrientationLandscapeLeft)
  1101 + {
  1102 + CGFloat height = kCameraScreenWidth * videoRatio;
  1103 + CGFloat y = (kCameraScreenHeight - height) / 2;
  1104 + [self.photoPreviewImageView setFrame:CGRectMake(0, y, kCameraScreenWidth, height)];
  1105 + }
  1106 + else
  1107 + {
  1108 + if (CAMERA_IS_IPhoneX_All) {
  1109 + [self.photoPreviewImageView setFrame:CGRectMake(0, 0, kCameraScreenWidth, 667)];
  1110 + CGFloat centerY = self.view.frame.origin.y + self.view.frame.size.height * 0.5;
  1111 + CGRect frame = _captureVideoPreviewLayer.frame;
  1112 + frame.origin.y = centerY - frame.size.height * 0.5;
  1113 + self.photoPreviewImageView.frame = frame;
  1114 + }else
  1115 + {
  1116 + [self.photoPreviewImageView setFrame:CGRectMake(0, 0, kCameraScreenWidth, kCameraScreenHeight)];
  1117 + }
  1118 + }
  1119 + self.photoPreviewImageView.image = finalImage;
  1120 +
  1121 + self.photoPreviewContainerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kCameraScreenWidth, kCameraScreenHeight)];
  1122 + self.photoPreviewContainerView.backgroundColor = [UIColor blackColor];
  1123 + [self.photoPreviewContainerView addSubview:self.photoPreviewImageView];
  1124 + [self.view addSubview:self.photoPreviewContainerView];
  1125 + [self.view bringSubviewToFront:self.photoPreviewImageView];
  1126 + [self.view bringSubviewToFront:self.cancelButton];
  1127 + [self.view bringSubviewToFront:self.confirmButton];
  1128 + [self.cancelButton setHidden:NO];
  1129 + [self.confirmButton setHidden:NO];
  1130 +
  1131 + _isPicOrVideo = YES;
  1132 +}
  1133 +
  1134 +- (UIImage *)cutImageWithView:(UIView *)view
  1135 +{
  1136 + UIGraphicsBeginImageContextWithOptions(view.frame.size, NO, 0);
  1137 + [view.layer renderInContext:UIGraphicsGetCurrentContext()];
  1138 + UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
  1139 + UIGraphicsEndImageContext();
  1140 +
  1141 + return image;
  1142 +}
  1143 +
  1144 +#pragma mark - 视频录制
  1145 +
  1146 +/**
  1147 + * 录制视频方法
  1148 + */
  1149 +- (void)longPressCameraButtonFunc:(UILongPressGestureRecognizer *)sender
  1150 +{
  1151 + AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
  1152 + if (authStatus == AVAuthorizationStatusRestricted || authStatus ==AVAuthorizationStatusDenied)
  1153 + {
  1154 + return;
  1155 + }
  1156 +
  1157 + //判断用户是否允许访问麦克风权限
  1158 + authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
  1159 + if (authStatus == AVAuthorizationStatusRestricted || authStatus ==AVAuthorizationStatusDenied)
  1160 + {
  1161 + return;
  1162 + }
  1163 +
  1164 + switch (sender.state) {
  1165 + case UIGestureRecognizerStateBegan:
  1166 + [self startVideoRecorder];
  1167 + break;
  1168 + case UIGestureRecognizerStateCancelled:
  1169 + [self stopVideoRecorder];
  1170 + break;
  1171 + case UIGestureRecognizerStateEnded:
  1172 + [self stopVideoRecorder];
  1173 + break;
  1174 + case UIGestureRecognizerStateFailed:
  1175 + [self stopVideoRecorder];
  1176 + break;
  1177 + default:
  1178 + break;
  1179 + }
  1180 +
  1181 +}
  1182 +
  1183 +/**
  1184 + * 开始录制视频
  1185 + */
  1186 +- (void)startVideoRecorder
  1187 +{
  1188 + _isShooting = YES;
  1189 +
  1190 + [self stopUpdateAccelerometer];
  1191 +
  1192 + [self setCaptureVideoPreviewLayerTransformWithScale:1.0f];
  1193 +
  1194 + [self.cameraButton startShootAnimationWithDuration:START_VIDEO_ANIMATION_DURATION];
  1195 +
  1196 + __weak typeof(self) weakSelf = self;
  1197 + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(START_VIDEO_ANIMATION_DURATION * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  1198 +
  1199 + NSURL *url = [NSURL fileURLWithPath:[weakSelf createVideoFilePath]];
  1200 + self.videoURL = url;
  1201 +
  1202 + [self setUpWriter];
  1203 +
  1204 + [weakSelf timerFired];
  1205 +
  1206 + });
  1207 +}
  1208 +
  1209 +/**
  1210 + * 结束录制视频
  1211 + */
  1212 +- (void)stopVideoRecorder
  1213 +{
  1214 + if (_isShooting)
  1215 + {
  1216 + _isShooting = NO;
  1217 + self.cameraButton.progressPercentage = 0.0f;
  1218 + [self.cameraButton stopShootAnimation];
  1219 + [self timerStop];
  1220 +
  1221 + __weak __typeof(self)weakSelf = self;
  1222 + if(_assetWriter && _assetWriter.status == AVAssetWriterStatusWriting)
  1223 + {
  1224 + // dispatch_async(self.videoQueue, ^{
  1225 + [_assetWriter finishWritingWithCompletionHandler:^{
  1226 + weakSelf.canWrite = NO;
  1227 + weakSelf.assetWriter = nil;
  1228 + weakSelf.assetWriterAudioInput = nil;
  1229 + weakSelf.assetWriterVideoInput = nil;
  1230 + }];
  1231 + // });
  1232 + }
  1233 +
  1234 + if (timeLength < VIDEO_RECORDER_MIN_TIME)
  1235 + {
  1236 + return;
  1237 + }
  1238 +
  1239 + [self.cameraButton setHidden:YES];
  1240 +
  1241 + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  1242 +
  1243 + [weakSelf previewVideoAfterShoot];
  1244 +
  1245 + });
  1246 + }
  1247 + else
  1248 + {
  1249 + // nothing
  1250 + }
  1251 +}
  1252 +
  1253 +/**
  1254 + * 设置写入视频属性
  1255 + */
  1256 +- (void)setUpWriter
  1257 +{
  1258 + if (self.videoURL == nil)
  1259 + {
  1260 + return;
  1261 + }
  1262 +
  1263 + self.assetWriter = [AVAssetWriter assetWriterWithURL:self.videoURL fileType:AVFileTypeMPEG4 error:nil];
  1264 + //写入视频大小
  1265 + NSInteger numPixels = kCameraScreenWidth * kCameraScreenHeight;
  1266 + //每像素比特
  1267 + CGFloat bitsPerPixel = 16.0;
  1268 + NSInteger bitsPerSecond = numPixels * bitsPerPixel;
  1269 +
  1270 + // 码率和帧率设置
  1271 + NSDictionary *compressionProperties = @{ AVVideoAverageBitRateKey : @(bitsPerSecond),
  1272 + AVVideoExpectedSourceFrameRateKey : @(30),
  1273 + AVVideoMaxKeyFrameIntervalKey : @(30),
  1274 + AVVideoProfileLevelKey : AVVideoProfileLevelH264BaselineAutoLevel };
  1275 +
  1276 + //视频属性
  1277 + CGFloat videoWidthKey = kCameraScreenHeight;
  1278 + if (CAMERA_IS_IPhoneX_All) {
  1279 + videoWidthKey = 667;
  1280 + }
  1281 + self.videoCompressionSettings = @{ AVVideoCodecKey : AVVideoCodecH264,
  1282 + AVVideoScalingModeKey : AVVideoScalingModeResizeAspectFill,
  1283 + AVVideoWidthKey : @(videoWidthKey * 2),
  1284 + AVVideoHeightKey : @(kCameraScreenWidth * 2),
  1285 + AVVideoCompressionPropertiesKey : compressionProperties };
  1286 + _assetWriterVideoInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:self.videoCompressionSettings];
  1287 + //expectsMediaDataInRealTime 必须设为yes,需要从capture session 实时获取数据
  1288 + _assetWriterVideoInput.expectsMediaDataInRealTime = YES;
  1289 +
  1290 + if (self.shootingOrientation == UIDeviceOrientationLandscapeRight)
  1291 + {
  1292 + _assetWriterVideoInput.transform = CGAffineTransformMakeRotation(M_PI);
  1293 + }
  1294 + else if (self.shootingOrientation == UIDeviceOrientationLandscapeLeft)
  1295 + {
  1296 + _assetWriterVideoInput.transform = CGAffineTransformMakeRotation(0);
  1297 + }
  1298 + else if (self.shootingOrientation == UIDeviceOrientationPortraitUpsideDown)
  1299 + {
  1300 + _assetWriterVideoInput.transform = CGAffineTransformMakeRotation(M_PI + (M_PI / 2.0));
  1301 + }
  1302 + else
  1303 + {
  1304 + _assetWriterVideoInput.transform = CGAffineTransformMakeRotation(M_PI / 2.0);
  1305 + }
  1306 +
  1307 + // 音频设置
  1308 + self.audioCompressionSettings = @{ AVEncoderBitRatePerChannelKey : @(28000),
  1309 + AVFormatIDKey : @(kAudioFormatMPEG4AAC),
  1310 + AVNumberOfChannelsKey : @(1),
  1311 + AVSampleRateKey : @(22050) };
  1312 +
  1313 + _assetWriterAudioInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:self.audioCompressionSettings];
  1314 + _assetWriterAudioInput.expectsMediaDataInRealTime = YES;
  1315 +
  1316 + if ([_assetWriter canAddInput:_assetWriterVideoInput])
  1317 + {
  1318 + [_assetWriter addInput:_assetWriterVideoInput];
  1319 + }
  1320 + else
  1321 + {
  1322 + NSLog(@"AssetWriter videoInput append Failed");
  1323 + }
  1324 +
  1325 + if ([_assetWriter canAddInput:_assetWriterAudioInput])
  1326 + {
  1327 + [_assetWriter addInput:_assetWriterAudioInput];
  1328 + }
  1329 + else
  1330 + {
  1331 + NSLog(@"AssetWriter audioInput Append Failed");
  1332 + }
  1333 +
  1334 + _canWrite = NO;
  1335 +}
  1336 +
  1337 +- (NSString *)createVideoFilePath
  1338 +{
  1339 + // 创建视频文件的存储路径
  1340 + NSString *filePath = [self createVideoFolderPath];
  1341 + if (filePath == nil)
  1342 + {
  1343 + return nil;
  1344 + }
  1345 +
  1346 + NSString *videoType = @".mp4";
  1347 + NSString *videoDestDateString = [self createFileNamePrefix];
  1348 + NSString *videoFileName = [videoDestDateString stringByAppendingString:videoType];
  1349 +
  1350 + NSUInteger idx = 1;
  1351 + /*We only allow 10000 same file name*/
  1352 + NSString *finalPath = [NSString stringWithFormat:@"%@/fileType=videoType_%@", filePath, videoFileName];
  1353 +
  1354 + while (idx % 10000 && [[NSFileManager defaultManager] fileExistsAtPath:finalPath])
  1355 + {
  1356 + finalPath = [NSString stringWithFormat:@"%@/%@_(%lu)%@", filePath, videoDestDateString, (unsigned long)idx++, videoType];
  1357 + }
  1358 +
  1359 + return finalPath;
  1360 +}
  1361 +
  1362 +- (NSString *)createVideoFolderPath
  1363 +{
  1364 +#pragma mark - TODO: 路径参数配置 写个新属性
  1365 +// if (self.conversationId) {
  1366 +// return [CNTools newChatFilePathByUserId:self.conversationId];
  1367 +// }
  1368 +// return [CNTools chatFilePathByUserId:[IMAPlatform sharedInstance].host.userId];
  1369 +//
  1370 + NSFileManager *fileManager = [NSFileManager defaultManager];
  1371 + NSString *homePath = NSHomeDirectory();
  1372 +
  1373 + NSString *tmpFilePath;
  1374 +
  1375 + if (homePath.length > 0)
  1376 + {
  1377 + NSString *documentPath = [homePath stringByAppendingString:@"/Documents"];
  1378 + if ([fileManager fileExistsAtPath:documentPath isDirectory:NULL] == YES)
  1379 + {
  1380 + BOOL success = NO;
  1381 +
  1382 + NSArray *paths = [fileManager contentsOfDirectoryAtPath:documentPath error:nil];
  1383 +
  1384 + //offline file folder
  1385 + tmpFilePath = [documentPath stringByAppendingString:[NSString stringWithFormat:@"/%@", VIDEO_FILEPATH]];
  1386 + if ([paths containsObject:VIDEO_FILEPATH] == NO)
  1387 + {
  1388 + success = [fileManager createDirectoryAtPath:tmpFilePath withIntermediateDirectories:YES attributes:nil error:nil];
  1389 + if (!success)
  1390 + {
  1391 + tmpFilePath = nil;
  1392 + }
  1393 + }
  1394 + return tmpFilePath;
  1395 + }
  1396 + }
  1397 +
  1398 + return false;
  1399 +}
  1400 +
  1401 +/**
  1402 + * 创建文件名
  1403 + *
  1404 + */
  1405 +- (NSString *)createFileNamePrefix
  1406 +{
  1407 + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
  1408 + [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss zzz"];
  1409 +
  1410 + NSString *destDateString = [dateFormatter stringFromDate:[NSDate date]];
  1411 + destDateString = [destDateString stringByReplacingOccurrencesOfString:@" " withString:@"-"];
  1412 + destDateString = [destDateString stringByReplacingOccurrencesOfString:@"+" withString:@"-"];
  1413 + destDateString = [destDateString stringByReplacingOccurrencesOfString:@":" withString:@"-"];
  1414 +
  1415 + return destDateString;
  1416 +}
  1417 +
  1418 +/**
  1419 + * 开启定时器
  1420 + */
  1421 +- (void)timerFired
  1422 +{
  1423 + timeLength = 0;
  1424 + self.timer = [NSTimer scheduledTimerWithTimeInterval:TIMER_INTERVAL target:self selector:@selector(timerRecord) userInfo:nil repeats:YES];
  1425 +}
  1426 +
  1427 +/**
  1428 + * 绿色转圈百分比计算
  1429 + */
  1430 +- (void)timerRecord
  1431 +{
  1432 + if (!_isShooting)
  1433 + {
  1434 + [self timerStop];
  1435 + return ;
  1436 + }
  1437 +
  1438 + // 时间大于VIDEO_RECORDER_MAX_TIME则停止录制
  1439 + if (timeLength > VIDEO_RECORDER_MAX_TIME)
  1440 + {
  1441 + [self stopVideoRecorder];
  1442 + }
  1443 +
  1444 + timeLength += TIMER_INTERVAL;
  1445 +
  1446 + // NSLog(@"%lf", timeLength / VIDEO_RECORDER_MAX_TIME);
  1447 +
  1448 + self.cameraButton.progressPercentage = timeLength / VIDEO_RECORDER_MAX_TIME;
  1449 +
  1450 +}
  1451 +
  1452 +/**
  1453 + * 停止定时器
  1454 + */
  1455 +- (void)timerStop
  1456 +{
  1457 + if ([self.timer isValid])
  1458 + {
  1459 + [self.timer invalidate];
  1460 + self.timer = nil;
  1461 + }
  1462 +}
  1463 +
  1464 +/**
  1465 + * 预览录制的视频
  1466 + */
  1467 +- (void)previewVideoAfterShoot
  1468 +{
  1469 + if (self.videoURL == nil || self.playerLayer != nil)
  1470 + {
  1471 + return;
  1472 + }
  1473 +
  1474 + _isPicOrVideo = YES;
  1475 +
  1476 + AVURLAsset *asset = [AVURLAsset assetWithURL:self.videoURL];
  1477 +
  1478 + //获取视频总时长
  1479 + Float64 duration = CMTimeGetSeconds(asset.duration);
  1480 +
  1481 + self.currentVideoTimeLength = duration;
  1482 +
  1483 +// // 初始化AVPlayer
  1484 +// self.videoPreviewContainerView = [[UIView alloc] init];
  1485 +//
  1486 +// self.videoPreviewContainerView.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight);
  1487 +// self.videoPreviewContainerView.backgroundColor = [UIColor blackColor];
  1488 +
  1489 + self.playerItem = [AVPlayerItem playerItemWithAsset:asset];
  1490 + self.player = [[AVPlayer alloc] initWithPlayerItem:_playerItem];
  1491 + self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
  1492 + self.playerLayer.frame = CGRectMake(0, 0, kCameraScreenWidth, kCameraScreenHeight);
  1493 + self.playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
  1494 + self.playerLayer.hidden = NO;
  1495 +
  1496 + [self.view.layer addSublayer:self.playerLayer];
  1497 +
  1498 + // 其余UI布局设置
  1499 +// [self.view addSubview:self.videoPreviewContainerView];
  1500 +// [self.view bringSubviewToFront:self.videoPreviewContainerView];
  1501 +
  1502 +// [self.view.layer qmui_bringSublayerToFront:self.playerLayer];
  1503 + //更改
  1504 + if (self.playerLayer.superlayer == self.view.layer) {
  1505 + [self.playerLayer removeFromSuperlayer];
  1506 + [self.view.layer insertSublayer:self.playerLayer atIndex:(unsigned)self.view.layer.sublayers.count];
  1507 + }
  1508 +
  1509 + self.captureVideoPreviewLayer.hidden = YES;
  1510 + [self.view bringSubviewToFront:self.cancelButton];
  1511 + [self.view bringSubviewToFront:self.confirmButton];
  1512 + [self.cameraButton setHidden:YES];
  1513 + [self.closeButton setHidden:YES];
  1514 + [self.rotateCameraButton setHidden:YES];
  1515 + [self.flashButton setHidden:YES];
  1516 + [self.cancelButton setHidden:NO];
  1517 + [self.confirmButton setHidden:NO];
  1518 + self.captureVideoPreviewLayer.hidden = YES;
  1519 +
  1520 + // 重复播放预览视频
  1521 + [self addNotificationWithPlayerItem];
  1522 +
  1523 + // 开始播放
  1524 + [self.player play];
  1525 +}
  1526 +
  1527 +/**
  1528 + * 截取指定时间的视频缩略图
  1529 + *
  1530 + * @param timeBySecond 时间点,单位:s
  1531 + */
  1532 +- (UIImage *)thumbnailImageRequestWithVideoUrl:(NSURL *)videoUrl andTime:(CGFloat)timeBySecond
  1533 +{
  1534 + if (self.videoURL == nil)
  1535 + {
  1536 + return nil;
  1537 + }
  1538 +
  1539 + AVURLAsset *urlAsset = [AVURLAsset assetWithURL:videoUrl];
  1540 +
  1541 + //根据AVURLAsset创建AVAssetImageGenerator
  1542 + AVAssetImageGenerator *imageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:urlAsset];
  1543 + /*截图
  1544 + * requestTime:缩略图创建时间
  1545 + * actualTime:缩略图实际生成的时间
  1546 + */
  1547 + NSError *error = nil;
  1548 + CMTime requestTime = CMTimeMakeWithSeconds(timeBySecond, 10); //CMTime是表示电影时间信息的结构体,第一个参数表示是视频第几秒,第二个参数表示每秒帧数.(如果要活的某一秒的第几帧可以使用CMTimeMake方法)
  1549 + CMTime actualTime;
  1550 + CGImageRef cgImage = [imageGenerator copyCGImageAtTime:requestTime actualTime:&actualTime error:&error];
  1551 + if(error)
  1552 + {
  1553 + NSLog(@"截取视频缩略图时发生错误,错误信息:%@", error.localizedDescription);
  1554 + return nil;
  1555 + }
  1556 +
  1557 + CMTimeShow(actualTime);
  1558 + UIImage *image = [UIImage imageWithCGImage:cgImage];
  1559 + CGImageRelease(cgImage);
  1560 +
  1561 + UIImage *finalImage = nil;
  1562 + if (self.shootingOrientation == UIDeviceOrientationLandscapeRight)
  1563 + {
  1564 + finalImage = [self rotateImage:image withOrientation:UIImageOrientationDown];
  1565 + }
  1566 + else if (self.shootingOrientation == UIDeviceOrientationLandscapeLeft)
  1567 + {
  1568 + finalImage = [self rotateImage:image withOrientation:UIImageOrientationUp];
  1569 + }
  1570 + else if (self.shootingOrientation == UIDeviceOrientationPortraitUpsideDown)
  1571 + {
  1572 + finalImage = [self rotateImage:image withOrientation:UIImageOrientationLeft];
  1573 + }
  1574 + else
  1575 + {
  1576 + finalImage = [self rotateImage:image withOrientation:UIImageOrientationRight];
  1577 + }
  1578 +
  1579 + return finalImage;
  1580 +}
  1581 +
  1582 +/**
  1583 + * 图片旋转
  1584 + */
  1585 +- (UIImage *)rotateImage:(UIImage *)image withOrientation:(UIImageOrientation)orientation
  1586 +{
  1587 + long double rotate = 0.0;
  1588 + CGRect rect;
  1589 + float translateX = 0;
  1590 + float translateY = 0;
  1591 + float scaleX = 1.0;
  1592 + float scaleY = 1.0;
  1593 +
  1594 + switch (orientation)
  1595 + {
  1596 + case UIImageOrientationLeft:
  1597 + rotate = M_PI_2;
  1598 + rect = CGRectMake(0, 0, image.size.height, image.size.width);
  1599 + translateX = 0;
  1600 + translateY = -rect.size.width;
  1601 + scaleY = rect.size.width/rect.size.height;
  1602 + scaleX = rect.size.height/rect.size.width;
  1603 + break;
  1604 + case UIImageOrientationRight:
  1605 + rotate = 3 * M_PI_2;
  1606 + rect = CGRectMake(0, 0, image.size.height, image.size.width);
  1607 + translateX = -rect.size.height;
  1608 + translateY = 0;
  1609 + scaleY = rect.size.width/rect.size.height;
  1610 + scaleX = rect.size.height/rect.size.width;
  1611 + break;
  1612 + case UIImageOrientationDown:
  1613 + rotate = M_PI;
  1614 + rect = CGRectMake(0, 0, image.size.width, image.size.height);
  1615 + translateX = -rect.size.width;
  1616 + translateY = -rect.size.height;
  1617 + break;
  1618 + default:
  1619 + rotate = 0.0;
  1620 + rect = CGRectMake(0, 0, image.size.width, image.size.height);
  1621 + translateX = 0;
  1622 + translateY = 0;
  1623 + break;
  1624 + }
  1625 +
  1626 + UIGraphicsBeginImageContext(rect.size);
  1627 + CGContextRef context = UIGraphicsGetCurrentContext();
  1628 + //做CTM变换
  1629 + CGContextTranslateCTM(context, 0.0, rect.size.height);
  1630 + CGContextScaleCTM(context, 1.0, -1.0);
  1631 + CGContextRotateCTM(context, rotate);
  1632 + CGContextTranslateCTM(context, translateX, translateY);
  1633 +
  1634 + CGContextScaleCTM(context, scaleX, scaleY);
  1635 + //绘制图片
  1636 + CGContextDrawImage(context, CGRectMake(0, 0, rect.size.width, rect.size.height), image.CGImage);
  1637 +
  1638 + UIImage *newPic = UIGraphicsGetImageFromCurrentImageContext();
  1639 +
  1640 + return newPic;
  1641 +}
  1642 +
  1643 +#pragma mark - 截取视频方法
  1644 +
  1645 +- (void)cropWithVideoUrlStr:(NSURL *)videoUrl start:(CGFloat)startTime end:(CGFloat)endTime completion:(void (^)(NSURL *outputURL, Float64 videoDuration, BOOL isSuccess))completionHandle
  1646 +{
  1647 + AVURLAsset *asset =[[AVURLAsset alloc] initWithURL:videoUrl options:nil];
  1648 +
  1649 + //获取视频总时长
  1650 + Float64 duration = CMTimeGetSeconds(asset.duration);
  1651 +
  1652 + if (duration > VIDEO_RECORDER_MAX_TIME)
  1653 + {
  1654 + duration = VIDEO_RECORDER_MAX_TIME;
  1655 + }
  1656 +
  1657 + startTime = 0;
  1658 + endTime = duration;
  1659 +
  1660 + NSString *outputFilePath = [self createVideoFilePath];
  1661 + NSURL *outputFileUrl = [NSURL fileURLWithPath:outputFilePath];
  1662 +
  1663 + NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:asset];
  1664 + if ([compatiblePresets containsObject:AVAssetExportPresetMediumQuality])
  1665 + {
  1666 +
  1667 + AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]
  1668 + initWithAsset:asset presetName:AVAssetExportPresetPassthrough];
  1669 +
  1670 + NSURL *outputURL = outputFileUrl;
  1671 +
  1672 + exportSession.outputURL = outputURL;
  1673 + exportSession.outputFileType = AVFileTypeMPEG4;
  1674 + exportSession.shouldOptimizeForNetworkUse = YES;
  1675 +
  1676 + CMTime start = CMTimeMakeWithSeconds(startTime, asset.duration.timescale);
  1677 + CMTime duration = CMTimeMakeWithSeconds(endTime - startTime,asset.duration.timescale);
  1678 + CMTimeRange range = CMTimeRangeMake(start, duration);
  1679 + exportSession.timeRange = range;
  1680 +
  1681 + [exportSession exportAsynchronouslyWithCompletionHandler:^{
  1682 + switch ([exportSession status]) {
  1683 + case AVAssetExportSessionStatusFailed:
  1684 + {
  1685 + NSLog(@"合成失败:%@", [[exportSession error] description]);
  1686 + completionHandle(outputURL, endTime, NO);
  1687 + }
  1688 + break;
  1689 + case AVAssetExportSessionStatusCancelled:
  1690 + {
  1691 + completionHandle(outputURL, endTime, NO);
  1692 + }
  1693 + break;
  1694 + case AVAssetExportSessionStatusCompleted:
  1695 + {
  1696 + completionHandle(outputURL, endTime, YES);
  1697 + }
  1698 + break;
  1699 + default:
  1700 + {
  1701 + completionHandle(outputURL, endTime, NO);
  1702 + } break;
  1703 + }
  1704 + }];
  1705 + }
  1706 +}
  1707 +
  1708 +#pragma mark - 预览视频通知
  1709 +/**
  1710 + * 添加播放器通知
  1711 + */
  1712 +-(void)addNotificationWithPlayerItem
  1713 +{
  1714 + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playVideoFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.playerItem];
  1715 +}
  1716 +
  1717 +-(void)removePlayerItemNotification
  1718 +{
  1719 + [[NSNotificationCenter defaultCenter] removeObserver:self];
  1720 +}
  1721 +
  1722 +/**
  1723 + * 播放完成通知
  1724 + *
  1725 + * @param notification 通知对象
  1726 + */
  1727 +-(void)playVideoFinished:(NSNotification *)notification
  1728 +{
  1729 + // NSLog(@"视频播放完成.");
  1730 +
  1731 + // 播放完成后重复播放
  1732 + // 跳到最新的时间点开始播放
  1733 + [self.player seekToTime:CMTimeMake(0, 1)];
  1734 + [self.player play];
  1735 +}
  1736 +
  1737 +#pragma mark - AVCaptureVideoDataOutputSampleBufferDelegate AVCaptureAudioDataOutputSampleBufferDelegate
  1738 +
  1739 +- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
  1740 +{
  1741 + if (_isRotatingCamera)
  1742 + {
  1743 + return;
  1744 + }
  1745 +
  1746 + @autoreleasepool
  1747 + {
  1748 + //视频
  1749 + if (connection == [self.videoOutput connectionWithMediaType:AVMediaTypeVideo])
  1750 + {
  1751 + @synchronized(self)
  1752 + {
  1753 + if (_isShooting)
  1754 + {
  1755 + [self appendSampleBuffer:sampleBuffer ofMediaType:AVMediaTypeVideo];
  1756 + }
  1757 + }
  1758 + }
  1759 +
  1760 + //音频
  1761 + if (connection == [self.audioOutput connectionWithMediaType:AVMediaTypeAudio])
  1762 + {
  1763 + @synchronized(self)
  1764 + {
  1765 + if (_isShooting)
  1766 + {
  1767 + [self appendSampleBuffer:sampleBuffer ofMediaType:AVMediaTypeAudio];
  1768 + }
  1769 + }
  1770 + }
  1771 + }
  1772 +}
  1773 +
  1774 +
  1775 +/**
  1776 + * 开始写入数据
  1777 + */
  1778 +- (void)appendSampleBuffer:(CMSampleBufferRef)sampleBuffer ofMediaType:(NSString *)mediaType
  1779 +{
  1780 + if (sampleBuffer == NULL)
  1781 + {
  1782 + NSLog(@"empty sampleBuffer");
  1783 + return;
  1784 + }
  1785 +
  1786 + // CFRetain(sampleBuffer);
  1787 + // dispatch_async(self.videoQueue, ^{
  1788 + @autoreleasepool
  1789 + {
  1790 + if (!self.canWrite && mediaType == AVMediaTypeVideo)
  1791 + {
  1792 + [self.assetWriter startWriting];
  1793 + [self.assetWriter startSessionAtSourceTime:CMSampleBufferGetPresentationTimeStamp(sampleBuffer)];
  1794 + self.canWrite = YES;
  1795 + }
  1796 +
  1797 + //写入视频数据
  1798 + if (mediaType == AVMediaTypeVideo)
  1799 + {
  1800 + if (self.assetWriterVideoInput.readyForMoreMediaData)
  1801 + {
  1802 + BOOL success = [self.assetWriterVideoInput appendSampleBuffer:sampleBuffer];
  1803 + if (!success)
  1804 + {
  1805 + @synchronized (self)
  1806 + {
  1807 + [self stopVideoRecorder];
  1808 + }
  1809 + }
  1810 + }
  1811 + }
  1812 +
  1813 + //写入音频数据
  1814 + if (mediaType == AVMediaTypeAudio)
  1815 + {
  1816 + if (self.assetWriterAudioInput.readyForMoreMediaData)
  1817 + {
  1818 + BOOL success = [self.assetWriterAudioInput appendSampleBuffer:sampleBuffer];
  1819 + if (!success)
  1820 + {
  1821 + @synchronized (self)
  1822 + {
  1823 + [self stopVideoRecorder];
  1824 + }
  1825 + }
  1826 + }
  1827 + }
  1828 +
  1829 + // CFRelease(sampleBuffer);
  1830 + }
  1831 + // });
  1832 +}
  1833 +
  1834 +#pragma mark - 摄像头聚焦,与缩放
  1835 +
  1836 +/**
  1837 + * 添加点按手势
  1838 + */
  1839 +- (void)addTapGenstureRecognizerForCamera
  1840 +{
  1841 + UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchGesture:)];
  1842 +
  1843 + pinchGesture.delegate = self;
  1844 +
  1845 + [self.view addGestureRecognizer:pinchGesture];
  1846 +}
  1847 +
  1848 +/**
  1849 + * 点击屏幕,聚焦事件
  1850 + */
  1851 +- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
  1852 +{
  1853 + // 不聚焦的情况:聚焦中,旋转摄像头中,查看录制的视频中,查看照片中
  1854 + if (_isFocusing || touches.count == 0 || _isRotatingCamera || _videoPreviewContainerView || _photoPreviewImageView)
  1855 + {
  1856 + return;
  1857 + }
  1858 +
  1859 + UITouch *touch = nil;
  1860 +
  1861 + for (UITouch *t in touches)
  1862 + {
  1863 + touch = t;
  1864 + break;
  1865 + }
  1866 +
  1867 + CGPoint point = [touch locationInView:self.view];;
  1868 +
  1869 + if (point.y > CGRectGetMaxY(self.tipLabel.frame))
  1870 + {
  1871 + return;
  1872 + }
  1873 +
  1874 + [self setFocusCursorWithPoint:point];
  1875 +}
  1876 +
  1877 +/**
  1878 + * 设置聚焦光标位置
  1879 + *
  1880 + * @param point 光标位置
  1881 + */
  1882 +- (void)setFocusCursorWithPoint:(CGPoint)point
  1883 +{
  1884 + self.isFocusing = YES;
  1885 +
  1886 + self.focusImageView.center = point;
  1887 + self.focusImageView.transform = CGAffineTransformMakeScale(1.5, 1.5);
  1888 + self.focusImageView.alpha = 1;
  1889 +
  1890 + //将UI坐标转化为摄像头坐标
  1891 + CGPoint cameraPoint = [self.captureVideoPreviewLayer captureDevicePointOfInterestForPoint:point];
  1892 + [self focusWithPoint:cameraPoint];
  1893 +
  1894 + __weak typeof(self) weakSelf = self;
  1895 + [UIView animateWithDuration:1.0 animations:^{
  1896 +
  1897 + weakSelf.focusImageView.transform = CGAffineTransformIdentity;
  1898 +
  1899 + } completion:^(BOOL finished) {
  1900 +
  1901 + weakSelf.focusImageView.alpha = 0;
  1902 + weakSelf.isFocusing = NO;
  1903 +
  1904 + }];
  1905 +}
  1906 +
  1907 +/**
  1908 + * 设置聚焦点
  1909 + *
  1910 + * @param point 聚焦点
  1911 + */
  1912 +-(void)focusWithPoint:(CGPoint)point
  1913 +{
  1914 + [self changeDeviceProperty:^(AVCaptureDevice *captureDevice)
  1915 + {
  1916 + // 聚焦
  1917 + if ([captureDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus])
  1918 + {
  1919 + [captureDevice setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
  1920 + }
  1921 + if ([captureDevice isFocusPointOfInterestSupported])
  1922 + {
  1923 + [captureDevice setFocusPointOfInterest:point];
  1924 + }
  1925 + // 曝光
  1926 + if ([captureDevice isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure])
  1927 + {
  1928 + [captureDevice setExposureMode:AVCaptureExposureModeContinuousAutoExposure];
  1929 + }
  1930 + if ([captureDevice isExposurePointOfInterestSupported])
  1931 + {
  1932 + [captureDevice setExposurePointOfInterest:point];
  1933 + }
  1934 + }];
  1935 +}
  1936 +
  1937 +- (void)handlePinchGesture:(UIPinchGestureRecognizer *)recognizer
  1938 +{
  1939 + if (_isShooting)
  1940 + {
  1941 + return;
  1942 + }
  1943 +
  1944 + BOOL allTouchesAreOnTheCaptureVideoPreviewLayer = YES;
  1945 +
  1946 + NSUInteger numTouches = [recognizer numberOfTouches], i;
  1947 + for ( i = 0; i < numTouches; ++i)
  1948 + {
  1949 + CGPoint location = [recognizer locationOfTouch:i inView:self.view];
  1950 + CGPoint convertedLocation = [self.captureVideoPreviewLayer convertPoint:location fromLayer:self.captureVideoPreviewLayer.superlayer];
  1951 + if (![self.captureVideoPreviewLayer containsPoint:convertedLocation])
  1952 + {
  1953 + allTouchesAreOnTheCaptureVideoPreviewLayer = NO;
  1954 + break;
  1955 + }
  1956 + }
  1957 +
  1958 + if (allTouchesAreOnTheCaptureVideoPreviewLayer)
  1959 + {
  1960 + self.effectiveScale = self.beginGestureScale * recognizer.scale;
  1961 + if (self.effectiveScale < 1.0f)
  1962 + {
  1963 + self.effectiveScale = 1.0f;
  1964 + }
  1965 +
  1966 + // NSLog(@"%f-------------->%f------------recognizerScale%f", self.effectiveScale, self.beginGestureScale, recognizer.scale);
  1967 +
  1968 + CGFloat imageMaxScaleAndCropFactor = [[self.captureStillImageOutput connectionWithMediaType:AVMediaTypeVideo] videoMaxScaleAndCropFactor];
  1969 +
  1970 + // NSLog(@"%f", imageMaxScaleAndCropFactor);
  1971 + if (self.effectiveScale > imageMaxScaleAndCropFactor)
  1972 + {
  1973 + self.effectiveScale = imageMaxScaleAndCropFactor;
  1974 + }
  1975 +
  1976 + [self setCaptureVideoPreviewLayerTransformWithScale:self.effectiveScale];
  1977 + }
  1978 +}
  1979 +
  1980 +- (void)setCaptureVideoPreviewLayerTransformWithScale:(CGFloat)scale
  1981 +{
  1982 + self.effectiveScale = scale;
  1983 + [CATransaction begin];
  1984 + [CATransaction setAnimationDuration:0.25f]; //时长最好低于 START_VIDEO_ANIMATION_DURATION
  1985 + [self.captureVideoPreviewLayer setAffineTransform:CGAffineTransformMakeScale(scale, scale)];
  1986 + [CATransaction commit];
  1987 +}
  1988 +
  1989 +#pragma mark - UIGestureRecognizerDelegate
  1990 +
  1991 +- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
  1992 +{
  1993 + if ([gestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]])
  1994 + {
  1995 + self.beginGestureScale = self.effectiveScale;
  1996 + }
  1997 +
  1998 + return YES;
  1999 +}
  2000 +
  2001 +#pragma mark - 重力感应相关
  2002 +
  2003 +/**
  2004 + * 开始监听屏幕方向
  2005 + */
  2006 +- (void)startUpdateAccelerometer
  2007 +{
  2008 + if ([self.motionManager isAccelerometerAvailable] == YES)
  2009 + {
  2010 + //回调会一直调用,建议获取到就调用下面的停止方法,需要再重新开始,当然如果需求是实时不间断的话可以等离开页面之后再stop
  2011 + [self.motionManager setAccelerometerUpdateInterval:1.0];
  2012 + [self.motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error)
  2013 + {
  2014 + double x = accelerometerData.acceleration.x;
  2015 + double y = accelerometerData.acceleration.y;
  2016 + if (fabs(y) >= fabs(x))
  2017 + {
  2018 + if (y >= 0)
  2019 + {
  2020 + // Down
  2021 + NSLog(@"Down");
  2022 + self->_shootingOrientation = UIDeviceOrientationPortraitUpsideDown;
  2023 + }
  2024 + else
  2025 + {
  2026 + // Portrait
  2027 + NSLog(@"Portrait");
  2028 + self->_shootingOrientation = UIDeviceOrientationPortrait;
  2029 + }
  2030 + }
  2031 + else
  2032 + {
  2033 + if (x >= 0)
  2034 + {
  2035 + // Right
  2036 + NSLog(@"Right");
  2037 + self->_shootingOrientation = UIDeviceOrientationLandscapeRight;
  2038 + }
  2039 + else
  2040 + {
  2041 + // Left
  2042 + NSLog(@"Left");
  2043 + self->_shootingOrientation = UIDeviceOrientationLandscapeLeft;
  2044 + }
  2045 + }
  2046 + }];
  2047 + }
  2048 +}
  2049 +
  2050 +/**
  2051 + * 停止监听屏幕方向
  2052 + */
  2053 +- (void)stopUpdateAccelerometer
  2054 +{
  2055 + if ([self.motionManager isAccelerometerActive] == YES)
  2056 + {
  2057 + [self.motionManager stopAccelerometerUpdates];
  2058 + _motionManager = nil;
  2059 + }
  2060 +}
  2061 +
  2062 +#pragma mark - 判断是否有权限
  2063 +
  2064 +/**
  2065 + * 请求权限
  2066 + */
  2067 +- (void)requestAuthorizationForVideo
  2068 +{
  2069 + __weak typeof(self) weakSelf = self;
  2070 +
  2071 + // 请求相机权限
  2072 + AVAuthorizationStatus videoAuthStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
  2073 + if (videoAuthStatus != AVAuthorizationStatusAuthorized)
  2074 + {
  2075 + NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
  2076 +
  2077 + NSString *appName = [infoDictionary objectForKey:@"CFBundleDisplayName"];
  2078 + if (appName == nil)
  2079 + {
  2080 + appName = @"APP";
  2081 + }
  2082 + NSString *message = [NSString stringWithFormat:@"请在iPhone的“设置-隐私”选项中,允许%@访问你的相册,相机和麦克风。", appName];
  2083 +
  2084 + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"" message:message preferredStyle:UIAlertControllerStyleAlert];//无法拍摄
  2085 +
  2086 + UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  2087 + [weakSelf dismissViewControllerAnimated:YES completion:nil];
  2088 + }];
  2089 +
  2090 + [alertController addAction:okAction];
  2091 + [self presentViewController:alertController animated:YES completion:nil];
  2092 + }
  2093 +
  2094 + // 请求麦克风权限
  2095 + AVAuthorizationStatus audioAuthStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
  2096 + if (audioAuthStatus != AVAuthorizationStatusAuthorized)
  2097 + {
  2098 + NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
  2099 +
  2100 + NSString *appName = [infoDictionary objectForKey:@"CFBundleDisplayName"];
  2101 + if (appName == nil)
  2102 + {
  2103 + appName = @"APP";
  2104 + }
  2105 + NSString *message = [NSString stringWithFormat:@"请在iPhone的“设置-隐私“选项中,允许%@访问你的相机,相册和麦克风。", appName];//[NSString stringWithFormat:@"请在iPhone的““设置-隐私””选项中, 允许%@访问你的麦克风?", appName];
  2106 +
  2107 + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"" message:message preferredStyle:UIAlertControllerStyleAlert];
  2108 +
  2109 + UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  2110 + [weakSelf dismissViewControllerAnimated:YES completion:nil];
  2111 + }];
  2112 +
  2113 + [alertController addAction:okAction];
  2114 +
  2115 + [self presentViewController:alertController animated:YES completion:nil];
  2116 + }
  2117 +
  2118 +
  2119 +}
  2120 +
  2121 +- (void)requestAuthorizationForPhotoLibrary
  2122 +{
  2123 + __weak typeof(self) weakSelf = self;
  2124 +
  2125 + // 请求照片权限
  2126 + [XFPhotoLibraryManager requestALAssetsLibraryAuthorizationWithCompletion:^(Boolean isAuth) {
  2127 +
  2128 + if (!isAuth)
  2129 + {
  2130 + NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
  2131 +
  2132 + NSString *appName = [infoDictionary objectForKey:@"CFBundleDisplayName"];
  2133 + if (appName == nil)
  2134 + {
  2135 + appName = @"APP";
  2136 + }
  2137 + NSString *message = [NSString stringWithFormat:@"请在iPhone的""设置-隐私-相册""中允许%@访问相册", appName];//@"允许%@访问你的相册?"
  2138 +
  2139 + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"" message:message preferredStyle:UIAlertControllerStyleAlert];
  2140 +
  2141 + UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  2142 + [weakSelf dismissViewControllerAnimated:YES completion:nil];
  2143 + weakSelf.isAlertShow = NO;
  2144 + }];
  2145 +
  2146 +// UIAlertAction *setAction = [UIAlertAction actionWithTitle:@"设置" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  2147 +// NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
  2148 +// if ([[UIApplication sharedApplication] canOpenURL:url])
  2149 +// {
  2150 +// [[UIApplication sharedApplication] openURL:url];
  2151 +// [weakSelf dismissViewControllerAnimated:YES completion:nil];
  2152 +// }
  2153 +// }];
  2154 +
  2155 + [alertController addAction:okAction];
  2156 +// [alertController addAction:setAction];
  2157 +
  2158 + [self presentViewController:alertController animated:YES completion:nil];
  2159 + self->_isAlertShow = YES;
  2160 +
  2161 + }
  2162 + }];
  2163 +}
  2164 +
  2165 +- (void)requestAuthCamera
  2166 +{
  2167 + __weak typeof(self) weakSelf = self;
  2168 +
  2169 + // 请求相机权限
  2170 + AVAuthorizationStatus videoAuthStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
  2171 + if (videoAuthStatus != AVAuthorizationStatusAuthorized)
  2172 + {
  2173 + NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
  2174 +
  2175 + NSString *appName = [infoDictionary objectForKey:@"CFBundleDisplayName"];
  2176 + if (appName == nil)
  2177 + {
  2178 + appName = @"APP";
  2179 + }
  2180 + NSString *message = [NSString stringWithFormat:@"请在iPhone的“设置-隐私”选项中,允许%@访问你的摄像头和麦克风。", appName];
  2181 +
  2182 + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"" message:message preferredStyle:UIAlertControllerStyleAlert];//无法拍摄
  2183 +
  2184 + UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  2185 + [weakSelf dismissViewControllerAnimated:YES completion:nil];
  2186 + }];
  2187 +
  2188 + [alertController addAction:okAction];
  2189 + [self presentViewController:alertController animated:YES completion:nil];
  2190 + }
  2191 +}
  2192 +
  2193 +#pragma mark - 进入前后台监听
  2194 +
  2195 +- (void)applicationBecomeActive
  2196 +{
  2197 + if (self.player) {
  2198 + [self.player play];
  2199 + }
  2200 +}
  2201 +
  2202 +- (void)enterBackgroundNotification
  2203 +{
  2204 + if (_isPicOrVideo) {
  2205 + //已经拍照或者录视频 不dismiss
  2206 + }else
  2207 + {//没有拍照或者录制视频 dismiss
  2208 + if (!_isAlertShow) {
  2209 + [self dismissViewControllerAnimated:YES completion:nil];
  2210 + }
  2211 + }
  2212 +}
  2213 +
  2214 +@end
CNLiveAVCamera/Classes/XFAVCamera/XFPhotoLibraryManager.h 0 → 100644
  1 +//
  2 +// XFPhotoLibraryManager.h
  3 +// WeChatVideoDemo
  4 +//
  5 +// Created by xf-ling on 2017/6/15.
  6 +// Copyright © 2017年 LXF. All rights reserved.
  7 +//
  8 +
  9 +#import <UIKit/UIKit.h>
  10 +#import <Photos/Photos.h>
  11 +
  12 +typedef void(^RequestAssetsLibraryAuthCompletion)(Boolean isAuth);
  13 +typedef void(^SavePhotoCompletionBlock)(UIImage *image, NSError *error);
  14 +typedef void(^SaveVideoCompletionBlock)(NSURL *vedioUrl, NSError *error);
  15 +
  16 +//zx
  17 +typedef void(^GetCameraVideoCompletionBlock)(PHAsset *asset,NSURL *vedioUrl, NSError *error);
  18 +
  19 +
  20 +@interface XFPhotoLibraryManager : NSObject
  21 +
  22 +/**
  23 + * 请求照片权限,注意,强烈要求用户获得照片权限,否则视频写入照片会有崩溃
  24 + */
  25 ++ (void)requestALAssetsLibraryAuthorizationWithCompletion:(RequestAssetsLibraryAuthCompletion) requestAssetsLibraryAuthCompletion;
  26 +
  27 +/**
  28 + * 保存照片
  29 + *
  30 + * @param image UImage
  31 + * @param assetCollectionName 相册名字,不填默认为app名字+相册
  32 + */
  33 ++ (void)savePhotoWithImage:(UIImage *)image andAssetCollectionName:(NSString *)assetCollectionName withCompletion:(SavePhotoCompletionBlock)savePhotoCompletionBlock;
  34 +
  35 +/**
  36 + * 保存视频
  37 + *
  38 + * @param videoUrl 视频地址
  39 + * @param assetCollectionName 相册名字,不填默认为app名字
  40 + */
  41 ++ (void)saveVideoWithVideoUrl:(NSURL *)videoUrl andAssetCollectionName:(NSString *)assetCollectionName withCompletion:(SaveVideoCompletionBlock)saveVideoCompletionBlock;
  42 +
  43 +
  44 +/**
  45 + * zx保存视频
  46 + *
  47 + * @param videoUrl 视频地址
  48 + * @param assetCollectionName 相册名字,不填默认为app名字
  49 + */
  50 ++ (void)zx_saveVideoWithVideoUrl:(NSURL *)videoUrl andAssetCollectionName:(NSString *)assetCollectionName withCompletion:(GetCameraVideoCompletionBlock)getCameraVideoCompletionBlock;
  51 +@end
CNLiveAVCamera/Classes/XFAVCamera/XFPhotoLibraryManager.m 0 → 100644
  1 +//
  2 +// XFPhotoLibraryManager.m
  3 +// WeChatVideoDemo
  4 +//
  5 +// Created by xf-ling on 2017/6/15.
  6 +// Copyright © 2017年 LXF. All rights reserved.
  7 +//
  8 +
  9 +#import "XFPhotoLibraryManager.h"
  10 +#import <Photos/Photos.h>
  11 +#import <AssetsLibrary/AssetsLibrary.h>
  12 +
  13 +@implementation XFPhotoLibraryManager
  14 +
  15 +/**
  16 + * 请求照片权限,注意,强烈要求用户获得照片权限,否则视频写入照片会有崩溃
  17 + */
  18 ++ (void)requestALAssetsLibraryAuthorizationWithCompletion:(RequestAssetsLibraryAuthCompletion)requestAssetsLibraryAuthCompletion
  19 +{
  20 + PHAuthorizationStatus authStatus = [PHPhotoLibrary authorizationStatus];
  21 + if (authStatus != PHAuthorizationStatusAuthorized) // 未授权
  22 + {
  23 + [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
  24 + if (status != PHAuthorizationStatusAuthorized) //已授权
  25 + {
  26 + NSLog(@"用户拒绝访问相册!");
  27 + if (requestAssetsLibraryAuthCompletion)
  28 + {
  29 + requestAssetsLibraryAuthCompletion(NO);
  30 + }
  31 + }
  32 + else
  33 + {
  34 + NSLog(@"用户允许访问相册!");
  35 + if (requestAssetsLibraryAuthCompletion)
  36 + {
  37 + requestAssetsLibraryAuthCompletion(YES);
  38 + }
  39 + }
  40 + }];
  41 + }
  42 + else
  43 + {
  44 + // nothing
  45 + }
  46 +}
  47 +
  48 +/**
  49 + * 保存照片
  50 + *
  51 + * @param image UImage
  52 + * @param assetCollectionName 相册名字,不填默认为app名字+相册
  53 + */
  54 ++ (void)savePhotoWithImage:(UIImage *)image andAssetCollectionName:(NSString *)assetCollectionName withCompletion:(SavePhotoCompletionBlock)savePhotoCompletionBlock
  55 +{
  56 + if (assetCollectionName == nil)
  57 + {
  58 + NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
  59 +
  60 + assetCollectionName = [infoDictionary objectForKey:@"CFBundleDisplayName"];
  61 +
  62 + if (assetCollectionName == nil)
  63 + {
  64 + assetCollectionName = @"视频相册";
  65 + }
  66 + }
  67 +
  68 + __block NSString *blockAssetCollectionName = assetCollectionName;
  69 + __block UIImage *blockImage = image;
  70 + __block NSString *assetId = nil;
  71 +
  72 + PHPhotoLibrary *library = [PHPhotoLibrary sharedPhotoLibrary];
  73 +
  74 + // 1. 存储图片到"相机胶卷"
  75 + [library performChanges:^{ // 这个block里保存一些"修改"性质的代码
  76 + // 新建一个PHAssetCreationRequest对象, 保存图片到"相机胶卷"
  77 + // 返回PHAsset(图片)的字符串标识
  78 + if (@available(iOS 9.0, *)) {
  79 + assetId = [PHAssetCreationRequest creationRequestForAssetFromImage:blockImage].placeholderForCreatedAsset.localIdentifier;
  80 + } else {
  81 + // Fallback on earlier versions
  82 + }
  83 + } completionHandler:^(BOOL success, NSError * _Nullable error) {
  84 + if (error) {
  85 + NSLog(@"error1%@", error);
  86 + return;
  87 + }
  88 +
  89 + NSLog(@"成功保存图片到相机胶卷中");
  90 +
  91 + // 2. 获得相册对象
  92 + // 获取曾经创建过的自定义视频相册名字
  93 + PHAssetCollection *createdAssetCollection = nil;
  94 + PHFetchResult <PHAssetCollection*> *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
  95 + for (PHAssetCollection *assetCollection in assetCollections)
  96 + {
  97 + if ([assetCollection.localizedTitle isEqualToString:blockAssetCollectionName])
  98 + {
  99 + createdAssetCollection = assetCollection;
  100 + break;
  101 + }
  102 + }
  103 +
  104 + //如果这个自定义框架没有创建过
  105 + if (createdAssetCollection == nil)
  106 + {
  107 + //创建新的[自定义的 Album](相簿\相册)
  108 + [library performChangesAndWait:^{
  109 +
  110 + assetId = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:blockAssetCollectionName].placeholderForCreatedAssetCollection.localIdentifier;
  111 +
  112 + } error:&error];
  113 +
  114 + NSLog(@"error2: %@", error);
  115 +
  116 + //抓取刚创建完的视频相册对象
  117 + createdAssetCollection = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[assetId] options:nil].firstObject;
  118 +
  119 + }
  120 +
  121 + // 3. 将“相机胶卷”中的图片添加到新的相册
  122 +// [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
  123 +// PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:createdAssetCollection];
  124 +//
  125 +// // 根据唯一标示获得相片对象
  126 +// PHAsset *asset = [PHAsset fetchAssetsWithLocalIdentifiers:@[assetId] options:nil].firstObject;
  127 +// // 添加图片到相册中
  128 +// [request addAssets:@[asset]];
  129 +// } completionHandler:^(BOOL success, NSError * _Nullable error) {
  130 +// if (error)
  131 +// {
  132 +// NSLog(@"添加图片到相册中失败");
  133 +// return;
  134 +// }
  135 +//
  136 +// NSLog(@"成功添加图片到相册中");
  137 +// }];
  138 +
  139 + // 将【Camera Roll】(相机胶卷)的视频 添加到【自定义Album】(相簿\相册)中
  140 + [library performChangesAndWait:^{
  141 + PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:createdAssetCollection];
  142 +
  143 + [request addAssets:[PHAsset fetchAssetsWithLocalIdentifiers:@[assetId] options:nil]];
  144 +
  145 + } error:&error];
  146 + NSLog(@"error3: %@", error);
  147 + // 提示信息
  148 + if (savePhotoCompletionBlock)
  149 + {
  150 + if (error)
  151 + {
  152 + NSLog(@"保存照片失败!");
  153 +
  154 + savePhotoCompletionBlock(nil, error);
  155 + }
  156 + else
  157 + {
  158 + NSLog(@"保存照片成功!");
  159 +
  160 + savePhotoCompletionBlock(blockImage, nil);
  161 + }
  162 + }
  163 +
  164 + }];
  165 +}
  166 +
  167 +/**
  168 + * 保存视频
  169 + *
  170 + * @param videoUrl 视频地址
  171 + * @param assetCollectionName 相册名字,不填默认为app名字+视频
  172 + */
  173 ++ (void)saveVideoWithVideoUrl:(NSURL *)videoUrl andAssetCollectionName:(NSString *)assetCollectionName withCompletion:(SaveVideoCompletionBlock)saveVideoCompletionBlock
  174 +{
  175 + if (assetCollectionName == nil)
  176 + {
  177 + NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
  178 +
  179 + assetCollectionName = [infoDictionary objectForKey:@"CFBundleDisplayName"];
  180 +
  181 + if (assetCollectionName == nil)
  182 + {
  183 + assetCollectionName = @"视频相册";
  184 + }
  185 + }
  186 +
  187 + __block NSString *blockAssetCollectionName = assetCollectionName;
  188 + __block NSURL *blockVideoUrl = videoUrl;
  189 + PHPhotoLibrary *library = [PHPhotoLibrary sharedPhotoLibrary];
  190 +
  191 + dispatch_async(dispatch_get_main_queue(), ^{
  192 +
  193 + NSError *error = nil;
  194 + __block NSString *assetId = nil;
  195 + __block NSString *assetCollectionId = nil;
  196 +
  197 + // 保存视频到【Camera Roll】(相机胶卷)
  198 + [library performChangesAndWait:^{
  199 +
  200 + assetId = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:blockVideoUrl].placeholderForCreatedAsset.localIdentifier;
  201 +
  202 + } error:&error];
  203 +
  204 + NSLog(@"error1: %@", error);
  205 +
  206 + // 获取曾经创建过的自定义视频相册名字
  207 + PHAssetCollection *createdAssetCollection = nil;
  208 + PHFetchResult <PHAssetCollection*> *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
  209 + for (PHAssetCollection *assetCollection in assetCollections)
  210 + {
  211 + if ([assetCollection.localizedTitle isEqualToString:blockAssetCollectionName])
  212 + {
  213 + createdAssetCollection = assetCollection;
  214 + break;
  215 + }
  216 + }
  217 +
  218 + //如果这个自定义框架没有创建过
  219 + if (createdAssetCollection == nil)
  220 + {
  221 + //创建新的[自定义的 Album](相簿\相册)
  222 + [library performChangesAndWait:^{
  223 +
  224 + assetCollectionId = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:blockAssetCollectionName].placeholderForCreatedAssetCollection.localIdentifier;
  225 +
  226 + } error:&error];
  227 +
  228 + NSLog(@"error2: %@", error);
  229 +
  230 + //抓取刚创建完的视频相册对象
  231 + createdAssetCollection = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[assetCollectionId] options:nil].firstObject;
  232 +
  233 + }
  234 +
  235 + // 将【Camera Roll】(相机胶卷)的视频 添加到【自定义Album】(相簿\相册)中
  236 + [library performChangesAndWait:^{
  237 + PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:createdAssetCollection];
  238 + [request addAssets:[PHAsset fetchAssetsWithLocalIdentifiers:@[assetId] options:nil]];
  239 +
  240 + } error:&error];
  241 + NSLog(@"error3: %@", error);
  242 +
  243 + // 提示信息
  244 + if (saveVideoCompletionBlock)
  245 + {
  246 + if (error)
  247 + {
  248 + NSLog(@"保存视频失败!");
  249 +
  250 + saveVideoCompletionBlock(nil, error);
  251 + }
  252 + else
  253 + {
  254 + NSLog(@"保存视频成功!");
  255 +
  256 + saveVideoCompletionBlock(blockVideoUrl, nil);
  257 + }
  258 + }
  259 +
  260 + });
  261 +}
  262 +
  263 ++ (void)zx_saveVideoWithVideoUrl:(NSURL *)videoUrl andAssetCollectionName:(NSString *)assetCollectionName withCompletion:(GetCameraVideoCompletionBlock)getCameraVideoCompletionBlock
  264 +{
  265 + if (assetCollectionName == nil)
  266 + {
  267 + NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
  268 +
  269 + assetCollectionName = [infoDictionary objectForKey:@"CFBundleDisplayName"];
  270 +
  271 + if (assetCollectionName == nil)
  272 + {
  273 + assetCollectionName = @"视频相册";
  274 + }
  275 + }
  276 +
  277 + __block NSString *blockAssetCollectionName = assetCollectionName;
  278 + __block NSURL *blockVideoUrl = videoUrl;
  279 + PHPhotoLibrary *library = [PHPhotoLibrary sharedPhotoLibrary];
  280 +
  281 + dispatch_async(dispatch_get_main_queue(), ^{
  282 +
  283 + NSError *error = nil;
  284 + __block NSString *assetId = nil;
  285 + __block NSString *assetCollectionId = nil;
  286 +
  287 + // 保存视频到【Camera Roll】(相机胶卷)
  288 + [library performChangesAndWait:^{
  289 +
  290 + assetId = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:blockVideoUrl].placeholderForCreatedAsset.localIdentifier;
  291 +
  292 + } error:&error];
  293 +
  294 + NSLog(@"error1: %@", error);
  295 +
  296 + // 获取曾经创建过的自定义视频相册名字
  297 + PHAssetCollection *createdAssetCollection = nil;
  298 + PHFetchResult <PHAssetCollection*> *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
  299 + for (PHAssetCollection *assetCollection in assetCollections)
  300 + {
  301 + if ([assetCollection.localizedTitle isEqualToString:blockAssetCollectionName])
  302 + {
  303 + createdAssetCollection = assetCollection;
  304 + break;
  305 + }
  306 + }
  307 +
  308 + //如果这个自定义框架没有创建过
  309 + if (createdAssetCollection == nil)
  310 + {
  311 + //创建新的[自定义的 Album](相簿\相册)
  312 + [library performChangesAndWait:^{
  313 +
  314 + assetCollectionId = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:blockAssetCollectionName].placeholderForCreatedAssetCollection.localIdentifier;
  315 +
  316 + } error:&error];
  317 +
  318 + NSLog(@"error2: %@", error);
  319 +
  320 + //抓取刚创建完的视频相册对象
  321 + createdAssetCollection = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[assetCollectionId] options:nil].firstObject;
  322 +
  323 + }
  324 +
  325 + // 将【Camera Roll】(相机胶卷)的视频 添加到【自定义Album】(相簿\相册)中
  326 + [library performChangesAndWait:^{
  327 + PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:createdAssetCollection];
  328 + [request addAssets:[PHAsset fetchAssetsWithLocalIdentifiers:@[assetId] options:nil]];
  329 +
  330 + } error:&error];
  331 + NSLog(@"error3: %@", error);
  332 +
  333 +
  334 + PHFetchResult<PHAsset *> *res = [PHAsset fetchAssetsWithLocalIdentifiers:@[assetId] options:nil];
  335 + PHAsset *asset = res[0];
  336 + NSLog(@"asset:\n%@",asset);
  337 +
  338 + if (getCameraVideoCompletionBlock) {
  339 + if (error)
  340 + {
  341 + getCameraVideoCompletionBlock(nil,nil,error);
  342 + }
  343 + else
  344 + {
  345 + getCameraVideoCompletionBlock(asset,blockVideoUrl,nil);
  346 + }
  347 + }
  348 +
  349 +//
  350 +// // 将【Camera Roll】(相机胶卷)的视频 添加到【自定义Album】(相簿\相册)中
  351 +// [library performChangesAndWait:^{
  352 +// PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:createdAssetCollection];
  353 +//
  354 +//// PHFetchResult<PHAsset *> *res = [PHAsset fetchAssetsWithLocalIdentifiers:@[assetId] options:nil];
  355 +//// PHAsset *asset1 = res[0];
  356 +//// NSLog(@"asset1:\n%@",asset1);
  357 +//
  358 +// [request addAssets:[PHAsset fetchAssetsWithLocalIdentifiers:@[assetId] options:nil]];
  359 +//
  360 +// } error:&error];
  361 +// NSLog(@"error3: %@", error);
  362 +//
  363 +// // 提示信息
  364 +// if (saveVideoCompletionBlock)
  365 +// {
  366 +// if (error)
  367 +// {
  368 +// NSLog(@"保存视频失败!");
  369 +//
  370 +// saveVideoCompletionBlock(nil, error);
  371 +// }
  372 +// else
  373 +// {
  374 +// NSLog(@"保存视频成功!");
  375 +//
  376 +// saveVideoCompletionBlock(blockVideoUrl, nil);
  377 +// }
  378 +// }
  379 +
  380 + });
  381 +}
  382 +@end
Example/CNLiveAVCamera.xcodeproj/project.pbxproj 0 → 100644
  1 +// !$*UTF8*$!
  2 +{
  3 + archiveVersion = 1;
  4 + classes = {
  5 + };
  6 + objectVersion = 46;
  7 + objects = {
  8 +
  9 +/* Begin PBXBuildFile section */
  10 + 528A8ADF0285C491B820F82E /* Pods_CNLiveAVCamera_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 774E0E4E88E7EA58FB0DBF0F /* Pods_CNLiveAVCamera_Example.framework */; };
  11 + 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; };
  12 + 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58F195388D20070C39A /* CoreGraphics.framework */; };
  13 + 6003F592195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; };
  14 + 6003F598195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F596195388D20070C39A /* InfoPlist.strings */; };
  15 + 6003F59A195388D20070C39A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F599195388D20070C39A /* main.m */; };
  16 + 6003F59E195388D20070C39A /* CNLiveAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F59D195388D20070C39A /* CNLiveAppDelegate.m */; };
  17 + 6003F5A7195388D20070C39A /* CNLiveViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F5A6195388D20070C39A /* CNLiveViewController.m */; };
  18 + 6003F5A9195388D20070C39A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5A8195388D20070C39A /* Images.xcassets */; };
  19 + 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F5AF195388D20070C39A /* XCTest.framework */; };
  20 + 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; };
  21 + 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; };
  22 + 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5B8195388D20070C39A /* InfoPlist.strings */; };
  23 + 6003F5BC195388D20070C39A /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F5BB195388D20070C39A /* Tests.m */; };
  24 + 71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */; };
  25 + 873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */; };
  26 + D6B4616FF3648DB1BE0A9900 /* Pods_CNLiveAVCamera_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7062A8FD28D9C146CB478315 /* Pods_CNLiveAVCamera_Tests.framework */; };
  27 +/* End PBXBuildFile section */
  28 +
  29 +/* Begin PBXContainerItemProxy section */
  30 + 6003F5B3195388D20070C39A /* PBXContainerItemProxy */ = {
  31 + isa = PBXContainerItemProxy;
  32 + containerPortal = 6003F582195388D10070C39A /* Project object */;
  33 + proxyType = 1;
  34 + remoteGlobalIDString = 6003F589195388D20070C39A;
  35 + remoteInfo = CNLiveAVCamera;
  36 + };
  37 +/* End PBXContainerItemProxy section */
  38 +
  39 +/* Begin PBXCopyFilesBuildPhase section */
  40 + 399A590F21BA760F0092926F /* Embed Frameworks */ = {
  41 + isa = PBXCopyFilesBuildPhase;
  42 + buildActionMask = 2147483647;
  43 + dstPath = "";
  44 + dstSubfolderSpec = 10;
  45 + files = (
  46 + );
  47 + name = "Embed Frameworks";
  48 + runOnlyForDeploymentPostprocessing = 0;
  49 + };
  50 +/* End PBXCopyFilesBuildPhase section */
  51 +
  52 +/* Begin PBXFileReference section */
  53 + 232FB65DACAACEB088650B26 /* Pods-CNLiveAVCamera_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CNLiveAVCamera_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-CNLiveAVCamera_Example/Pods-CNLiveAVCamera_Example.release.xcconfig"; sourceTree = "<group>"; };
  54 + 399A590521BA760F0092926F /* CNLiveAVCamera.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CNLiveAVCamera.h; sourceTree = "<group>"; };
  55 + 399A590621BA760F0092926F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
  56 + 4D1880C33D23BC4C4F02DDC2 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
  57 + 4F6BCE6DD63FA804E1500FF2 /* Pods-CNLiveAVCamera_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CNLiveAVCamera_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-CNLiveAVCamera_Tests/Pods-CNLiveAVCamera_Tests.debug.xcconfig"; sourceTree = "<group>"; };
  58 + 6003F58A195388D20070C39A /* CNLiveAVCamera_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CNLiveAVCamera_Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
  59 + 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
  60 + 6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
  61 + 6003F591195388D20070C39A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
  62 + 6003F595195388D20070C39A /* CNLiveAVCamera-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "CNLiveAVCamera-Info.plist"; sourceTree = "<group>"; };
  63 + 6003F597195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
  64 + 6003F599195388D20070C39A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
  65 + 6003F59B195388D20070C39A /* CNLiveAVCamera-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CNLiveAVCamera-Prefix.pch"; sourceTree = "<group>"; };
  66 + 6003F59C195388D20070C39A /* CNLiveAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CNLiveAppDelegate.h; sourceTree = "<group>"; };
  67 + 6003F59D195388D20070C39A /* CNLiveAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CNLiveAppDelegate.m; sourceTree = "<group>"; };
  68 + 6003F5A5195388D20070C39A /* CNLiveViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CNLiveViewController.h; sourceTree = "<group>"; };
  69 + 6003F5A6195388D20070C39A /* CNLiveViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CNLiveViewController.m; sourceTree = "<group>"; };
  70 + 6003F5A8195388D20070C39A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
  71 + 6003F5AE195388D20070C39A /* CNLiveAVCamera_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CNLiveAVCamera_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
  72 + 6003F5AF195388D20070C39A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
  73 + 6003F5B7195388D20070C39A /* Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Tests-Info.plist"; sourceTree = "<group>"; };
  74 + 6003F5B9195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
  75 + 6003F5BB195388D20070C39A /* Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = "<group>"; };
  76 + 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Tests-Prefix.pch"; sourceTree = "<group>"; };
  77 + 7062A8FD28D9C146CB478315 /* Pods_CNLiveAVCamera_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CNLiveAVCamera_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
  78 + 71719F9E1E33DC2100824A3D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
  79 + 774E0E4E88E7EA58FB0DBF0F /* Pods_CNLiveAVCamera_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CNLiveAVCamera_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
  80 + 774EA667BA71566BA72B8A5C /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = "<group>"; };
  81 + 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Main.storyboard; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
  82 + D34C72B66F62C1A82C1D9FA8 /* CNLiveAVCamera.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = CNLiveAVCamera.podspec; path = ../CNLiveAVCamera.podspec; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
  83 + D41556E2EE76E873ED9847B4 /* Pods-CNLiveAVCamera_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CNLiveAVCamera_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-CNLiveAVCamera_Tests/Pods-CNLiveAVCamera_Tests.release.xcconfig"; sourceTree = "<group>"; };
  84 + E61E5CDE06F66F688BB4ADF8 /* Pods-CNLiveAVCamera_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CNLiveAVCamera_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-CNLiveAVCamera_Example/Pods-CNLiveAVCamera_Example.debug.xcconfig"; sourceTree = "<group>"; };
  85 +/* End PBXFileReference section */
  86 +
  87 +/* Begin PBXFrameworksBuildPhase section */
  88 + 6003F587195388D20070C39A /* Frameworks */ = {
  89 + isa = PBXFrameworksBuildPhase;
  90 + buildActionMask = 2147483647;
  91 + files = (
  92 + 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */,
  93 + 6003F592195388D20070C39A /* UIKit.framework in Frameworks */,
  94 + 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */,
  95 + 528A8ADF0285C491B820F82E /* Pods_CNLiveAVCamera_Example.framework in Frameworks */,
  96 + );
  97 + runOnlyForDeploymentPostprocessing = 0;
  98 + };
  99 + 6003F5AB195388D20070C39A /* Frameworks */ = {
  100 + isa = PBXFrameworksBuildPhase;
  101 + buildActionMask = 2147483647;
  102 + files = (
  103 + 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */,
  104 + 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */,
  105 + 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */,
  106 + D6B4616FF3648DB1BE0A9900 /* Pods_CNLiveAVCamera_Tests.framework in Frameworks */,
  107 + );
  108 + runOnlyForDeploymentPostprocessing = 0;
  109 + };
  110 +/* End PBXFrameworksBuildPhase section */
  111 +
  112 +/* Begin PBXGroup section */
  113 + 0C13D0041B2063E549BF5B2A /* Pods */ = {
  114 + isa = PBXGroup;
  115 + children = (
  116 + E61E5CDE06F66F688BB4ADF8 /* Pods-CNLiveAVCamera_Example.debug.xcconfig */,
  117 + 232FB65DACAACEB088650B26 /* Pods-CNLiveAVCamera_Example.release.xcconfig */,
  118 + 4F6BCE6DD63FA804E1500FF2 /* Pods-CNLiveAVCamera_Tests.debug.xcconfig */,
  119 + D41556E2EE76E873ED9847B4 /* Pods-CNLiveAVCamera_Tests.release.xcconfig */,
  120 + );
  121 + name = Pods;
  122 + sourceTree = "<group>";
  123 + };
  124 + 399A590421BA760F0092926F /* CNLiveAVCamera */ = {
  125 + isa = PBXGroup;
  126 + children = (
  127 + 399A590521BA760F0092926F /* CNLiveAVCamera.h */,
  128 + 399A590621BA760F0092926F /* Info.plist */,
  129 + );
  130 + path = CNLiveAVCamera;
  131 + sourceTree = "<group>";
  132 + };
  133 + 6003F581195388D10070C39A = {
  134 + isa = PBXGroup;
  135 + children = (
  136 + 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */,
  137 + 6003F593195388D20070C39A /* Example for CNLiveAVCamera */,
  138 + 6003F5B5195388D20070C39A /* Tests */,
  139 + 399A590421BA760F0092926F /* CNLiveAVCamera */,
  140 + 6003F58C195388D20070C39A /* Frameworks */,
  141 + 6003F58B195388D20070C39A /* Products */,
  142 + 0C13D0041B2063E549BF5B2A /* Pods */,
  143 + );
  144 + sourceTree = "<group>";
  145 + };
  146 + 6003F58B195388D20070C39A /* Products */ = {
  147 + isa = PBXGroup;
  148 + children = (
  149 + 6003F58A195388D20070C39A /* CNLiveAVCamera_Example.app */,
  150 + 6003F5AE195388D20070C39A /* CNLiveAVCamera_Tests.xctest */,
  151 + );
  152 + name = Products;
  153 + sourceTree = "<group>";
  154 + };
  155 + 6003F58C195388D20070C39A /* Frameworks */ = {
  156 + isa = PBXGroup;
  157 + children = (
  158 + 6003F58D195388D20070C39A /* Foundation.framework */,
  159 + 6003F58F195388D20070C39A /* CoreGraphics.framework */,
  160 + 6003F591195388D20070C39A /* UIKit.framework */,
  161 + 6003F5AF195388D20070C39A /* XCTest.framework */,
  162 + 774E0E4E88E7EA58FB0DBF0F /* Pods_CNLiveAVCamera_Example.framework */,
  163 + 7062A8FD28D9C146CB478315 /* Pods_CNLiveAVCamera_Tests.framework */,
  164 + );
  165 + name = Frameworks;
  166 + sourceTree = "<group>";
  167 + };
  168 + 6003F593195388D20070C39A /* Example for CNLiveAVCamera */ = {
  169 + isa = PBXGroup;
  170 + children = (
  171 + 6003F59C195388D20070C39A /* CNLiveAppDelegate.h */,
  172 + 6003F59D195388D20070C39A /* CNLiveAppDelegate.m */,
  173 + 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */,
  174 + 6003F5A5195388D20070C39A /* CNLiveViewController.h */,
  175 + 6003F5A6195388D20070C39A /* CNLiveViewController.m */,
  176 + 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */,
  177 + 6003F5A8195388D20070C39A /* Images.xcassets */,
  178 + 6003F594195388D20070C39A /* Supporting Files */,
  179 + );
  180 + name = "Example for CNLiveAVCamera";
  181 + path = CNLiveAVCamera;
  182 + sourceTree = "<group>";
  183 + };
  184 + 6003F594195388D20070C39A /* Supporting Files */ = {
  185 + isa = PBXGroup;
  186 + children = (
  187 + 6003F595195388D20070C39A /* CNLiveAVCamera-Info.plist */,
  188 + 6003F596195388D20070C39A /* InfoPlist.strings */,
  189 + 6003F599195388D20070C39A /* main.m */,
  190 + 6003F59B195388D20070C39A /* CNLiveAVCamera-Prefix.pch */,
  191 + );
  192 + name = "Supporting Files";
  193 + sourceTree = "<group>";
  194 + };
  195 + 6003F5B5195388D20070C39A /* Tests */ = {
  196 + isa = PBXGroup;
  197 + children = (
  198 + 6003F5BB195388D20070C39A /* Tests.m */,
  199 + 6003F5B6195388D20070C39A /* Supporting Files */,
  200 + );
  201 + path = Tests;
  202 + sourceTree = "<group>";
  203 + };
  204 + 6003F5B6195388D20070C39A /* Supporting Files */ = {
  205 + isa = PBXGroup;
  206 + children = (
  207 + 6003F5B7195388D20070C39A /* Tests-Info.plist */,
  208 + 6003F5B8195388D20070C39A /* InfoPlist.strings */,
  209 + 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */,
  210 + );
  211 + name = "Supporting Files";
  212 + sourceTree = "<group>";
  213 + };
  214 + 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */ = {
  215 + isa = PBXGroup;
  216 + children = (
  217 + D34C72B66F62C1A82C1D9FA8 /* CNLiveAVCamera.podspec */,
  218 + 4D1880C33D23BC4C4F02DDC2 /* README.md */,
  219 + 774EA667BA71566BA72B8A5C /* LICENSE */,
  220 + );
  221 + name = "Podspec Metadata";
  222 + sourceTree = "<group>";
  223 + };
  224 +/* End PBXGroup section */
  225 +
  226 +/* Begin PBXNativeTarget section */
  227 + 6003F589195388D20070C39A /* CNLiveAVCamera_Example */ = {
  228 + isa = PBXNativeTarget;
  229 + buildConfigurationList = 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "CNLiveAVCamera_Example" */;
  230 + buildPhases = (
  231 + 8B8C0C69B53DCA1342E71BF1 /* [CP] Check Pods Manifest.lock */,
  232 + 6003F586195388D20070C39A /* Sources */,
  233 + 6003F587195388D20070C39A /* Frameworks */,
  234 + 6003F588195388D20070C39A /* Resources */,
  235 + A36B99FFC3152DBE818FC863 /* [CP] Embed Pods Frameworks */,
  236 + 399A590F21BA760F0092926F /* Embed Frameworks */,
  237 + );
  238 + buildRules = (
  239 + );
  240 + dependencies = (
  241 + );
  242 + name = CNLiveAVCamera_Example;
  243 + productName = CNLiveAVCamera;
  244 + productReference = 6003F58A195388D20070C39A /* CNLiveAVCamera_Example.app */;
  245 + productType = "com.apple.product-type.application";
  246 + };
  247 + 6003F5AD195388D20070C39A /* CNLiveAVCamera_Tests */ = {
  248 + isa = PBXNativeTarget;
  249 + buildConfigurationList = 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "CNLiveAVCamera_Tests" */;
  250 + buildPhases = (
  251 + FCD1D0667405CC357BEAB4F9 /* [CP] Check Pods Manifest.lock */,
  252 + 6003F5AA195388D20070C39A /* Sources */,
  253 + 6003F5AB195388D20070C39A /* Frameworks */,
  254 + 6003F5AC195388D20070C39A /* Resources */,
  255 + AD0B9B37F4F185810B0589E2 /* [CP] Embed Pods Frameworks */,
  256 + );
  257 + buildRules = (
  258 + );
  259 + dependencies = (
  260 + 6003F5B4195388D20070C39A /* PBXTargetDependency */,
  261 + );
  262 + name = CNLiveAVCamera_Tests;
  263 + productName = CNLiveAVCameraTests;
  264 + productReference = 6003F5AE195388D20070C39A /* CNLiveAVCamera_Tests.xctest */;
  265 + productType = "com.apple.product-type.bundle.unit-test";
  266 + };
  267 +/* End PBXNativeTarget section */
  268 +
  269 +/* Begin PBXProject section */
  270 + 6003F582195388D10070C39A /* Project object */ = {
  271 + isa = PBXProject;
  272 + attributes = {
  273 + CLASSPREFIX = CNLive;
  274 + LastUpgradeCheck = 0720;
  275 + ORGANIZATIONNAME = jyyjkt;
  276 + TargetAttributes = {
  277 + 6003F589195388D20070C39A = {
  278 + DevelopmentTeam = 94X49GG3ZW;
  279 + };
  280 + 6003F5AD195388D20070C39A = {
  281 + TestTargetID = 6003F589195388D20070C39A;
  282 + };
  283 + };
  284 + };
  285 + buildConfigurationList = 6003F585195388D10070C39A /* Build configuration list for PBXProject "CNLiveAVCamera" */;
  286 + compatibilityVersion = "Xcode 3.2";
  287 + developmentRegion = English;
  288 + hasScannedForEncodings = 0;
  289 + knownRegions = (
  290 + en,
  291 + Base,
  292 + );
  293 + mainGroup = 6003F581195388D10070C39A;
  294 + productRefGroup = 6003F58B195388D20070C39A /* Products */;
  295 + projectDirPath = "";
  296 + projectRoot = "";
  297 + targets = (
  298 + 6003F589195388D20070C39A /* CNLiveAVCamera_Example */,
  299 + 6003F5AD195388D20070C39A /* CNLiveAVCamera_Tests */,
  300 + );
  301 + };
  302 +/* End PBXProject section */
  303 +
  304 +/* Begin PBXResourcesBuildPhase section */
  305 + 6003F588195388D20070C39A /* Resources */ = {
  306 + isa = PBXResourcesBuildPhase;
  307 + buildActionMask = 2147483647;
  308 + files = (
  309 + 873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */,
  310 + 71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */,
  311 + 6003F5A9195388D20070C39A /* Images.xcassets in Resources */,
  312 + 6003F598195388D20070C39A /* InfoPlist.strings in Resources */,
  313 + );
  314 + runOnlyForDeploymentPostprocessing = 0;
  315 + };
  316 + 6003F5AC195388D20070C39A /* Resources */ = {
  317 + isa = PBXResourcesBuildPhase;
  318 + buildActionMask = 2147483647;
  319 + files = (
  320 + 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */,
  321 + );
  322 + runOnlyForDeploymentPostprocessing = 0;
  323 + };
  324 +/* End PBXResourcesBuildPhase section */
  325 +
  326 +/* Begin PBXShellScriptBuildPhase section */
  327 + 8B8C0C69B53DCA1342E71BF1 /* [CP] Check Pods Manifest.lock */ = {
  328 + isa = PBXShellScriptBuildPhase;
  329 + buildActionMask = 2147483647;
  330 + files = (
  331 + );
  332 + inputFileListPaths = (
  333 + );
  334 + inputPaths = (
  335 + "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
  336 + "${PODS_ROOT}/Manifest.lock",
  337 + );
  338 + name = "[CP] Check Pods Manifest.lock";
  339 + outputFileListPaths = (
  340 + );
  341 + outputPaths = (
  342 + "$(DERIVED_FILE_DIR)/Pods-CNLiveAVCamera_Example-checkManifestLockResult.txt",
  343 + );
  344 + runOnlyForDeploymentPostprocessing = 0;
  345 + shellPath = /bin/sh;
  346 + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
  347 + showEnvVarsInLog = 0;
  348 + };
  349 + A36B99FFC3152DBE818FC863 /* [CP] Embed Pods Frameworks */ = {
  350 + isa = PBXShellScriptBuildPhase;
  351 + buildActionMask = 2147483647;
  352 + files = (
  353 + );
  354 + inputFileListPaths = (
  355 + );
  356 + inputPaths = (
  357 + "${SRCROOT}/Pods/Target Support Files/Pods-CNLiveAVCamera_Example/Pods-CNLiveAVCamera_Example-frameworks.sh",
  358 + "${BUILT_PRODUCTS_DIR}/CNLiveAVCamera/CNLiveAVCamera.framework",
  359 + "${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework",
  360 + );
  361 + name = "[CP] Embed Pods Frameworks";
  362 + outputFileListPaths = (
  363 + );
  364 + outputPaths = (
  365 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CNLiveAVCamera.framework",
  366 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Masonry.framework",
  367 + );
  368 + runOnlyForDeploymentPostprocessing = 0;
  369 + shellPath = /bin/sh;
  370 + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-CNLiveAVCamera_Example/Pods-CNLiveAVCamera_Example-frameworks.sh\"\n";
  371 + showEnvVarsInLog = 0;
  372 + };
  373 + AD0B9B37F4F185810B0589E2 /* [CP] Embed Pods Frameworks */ = {
  374 + isa = PBXShellScriptBuildPhase;
  375 + buildActionMask = 2147483647;
  376 + files = (
  377 + );
  378 + inputFileListPaths = (
  379 + );
  380 + inputPaths = (
  381 + "${SRCROOT}/Pods/Target Support Files/Pods-CNLiveAVCamera_Tests/Pods-CNLiveAVCamera_Tests-frameworks.sh",
  382 + "${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework",
  383 + );
  384 + name = "[CP] Embed Pods Frameworks";
  385 + outputFileListPaths = (
  386 + );
  387 + outputPaths = (
  388 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Masonry.framework",
  389 + );
  390 + runOnlyForDeploymentPostprocessing = 0;
  391 + shellPath = /bin/sh;
  392 + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-CNLiveAVCamera_Tests/Pods-CNLiveAVCamera_Tests-frameworks.sh\"\n";
  393 + showEnvVarsInLog = 0;
  394 + };
  395 + FCD1D0667405CC357BEAB4F9 /* [CP] Check Pods Manifest.lock */ = {
  396 + isa = PBXShellScriptBuildPhase;
  397 + buildActionMask = 2147483647;
  398 + files = (
  399 + );
  400 + inputFileListPaths = (
  401 + );
  402 + inputPaths = (
  403 + "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
  404 + "${PODS_ROOT}/Manifest.lock",
  405 + );
  406 + name = "[CP] Check Pods Manifest.lock";
  407 + outputFileListPaths = (
  408 + );
  409 + outputPaths = (
  410 + "$(DERIVED_FILE_DIR)/Pods-CNLiveAVCamera_Tests-checkManifestLockResult.txt",
  411 + );
  412 + runOnlyForDeploymentPostprocessing = 0;
  413 + shellPath = /bin/sh;
  414 + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
  415 + showEnvVarsInLog = 0;
  416 + };
  417 +/* End PBXShellScriptBuildPhase section */
  418 +
  419 +/* Begin PBXSourcesBuildPhase section */
  420 + 6003F586195388D20070C39A /* Sources */ = {
  421 + isa = PBXSourcesBuildPhase;
  422 + buildActionMask = 2147483647;
  423 + files = (
  424 + 6003F59E195388D20070C39A /* CNLiveAppDelegate.m in Sources */,
  425 + 6003F5A7195388D20070C39A /* CNLiveViewController.m in Sources */,
  426 + 6003F59A195388D20070C39A /* main.m in Sources */,
  427 + );
  428 + runOnlyForDeploymentPostprocessing = 0;
  429 + };
  430 + 6003F5AA195388D20070C39A /* Sources */ = {
  431 + isa = PBXSourcesBuildPhase;
  432 + buildActionMask = 2147483647;
  433 + files = (
  434 + 6003F5BC195388D20070C39A /* Tests.m in Sources */,
  435 + );
  436 + runOnlyForDeploymentPostprocessing = 0;
  437 + };
  438 +/* End PBXSourcesBuildPhase section */
  439 +
  440 +/* Begin PBXTargetDependency section */
  441 + 6003F5B4195388D20070C39A /* PBXTargetDependency */ = {
  442 + isa = PBXTargetDependency;
  443 + target = 6003F589195388D20070C39A /* CNLiveAVCamera_Example */;
  444 + targetProxy = 6003F5B3195388D20070C39A /* PBXContainerItemProxy */;
  445 + };
  446 +/* End PBXTargetDependency section */
  447 +
  448 +/* Begin PBXVariantGroup section */
  449 + 6003F596195388D20070C39A /* InfoPlist.strings */ = {
  450 + isa = PBXVariantGroup;
  451 + children = (
  452 + 6003F597195388D20070C39A /* en */,
  453 + );
  454 + name = InfoPlist.strings;
  455 + sourceTree = "<group>";
  456 + };
  457 + 6003F5B8195388D20070C39A /* InfoPlist.strings */ = {
  458 + isa = PBXVariantGroup;
  459 + children = (
  460 + 6003F5B9195388D20070C39A /* en */,
  461 + );
  462 + name = InfoPlist.strings;
  463 + sourceTree = "<group>";
  464 + };
  465 + 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */ = {
  466 + isa = PBXVariantGroup;
  467 + children = (
  468 + 71719F9E1E33DC2100824A3D /* Base */,
  469 + );
  470 + name = LaunchScreen.storyboard;
  471 + sourceTree = "<group>";
  472 + };
  473 +/* End PBXVariantGroup section */
  474 +
  475 +/* Begin XCBuildConfiguration section */
  476 + 6003F5BD195388D20070C39A /* Debug */ = {
  477 + isa = XCBuildConfiguration;
  478 + buildSettings = {
  479 + ALWAYS_SEARCH_USER_PATHS = NO;
  480 + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
  481 + CLANG_CXX_LIBRARY = "libc++";
  482 + CLANG_ENABLE_MODULES = YES;
  483 + CLANG_ENABLE_OBJC_ARC = YES;
  484 + CLANG_WARN_BOOL_CONVERSION = YES;
  485 + CLANG_WARN_CONSTANT_CONVERSION = YES;
  486 + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
  487 + CLANG_WARN_EMPTY_BODY = YES;
  488 + CLANG_WARN_ENUM_CONVERSION = YES;
  489 + CLANG_WARN_INT_CONVERSION = YES;
  490 + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
  491 + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
  492 + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
  493 + COPY_PHASE_STRIP = NO;
  494 + ENABLE_TESTABILITY = YES;
  495 + GCC_C_LANGUAGE_STANDARD = gnu99;
  496 + GCC_DYNAMIC_NO_PIC = NO;
  497 + GCC_OPTIMIZATION_LEVEL = 0;
  498 + GCC_PREPROCESSOR_DEFINITIONS = (
  499 + "DEBUG=1",
  500 + "$(inherited)",
  501 + );
  502 + GCC_SYMBOLS_PRIVATE_EXTERN = NO;
  503 + GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
  504 + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
  505 + GCC_WARN_UNDECLARED_SELECTOR = YES;
  506 + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
  507 + GCC_WARN_UNUSED_FUNCTION = YES;
  508 + GCC_WARN_UNUSED_VARIABLE = YES;
  509 + IPHONEOS_DEPLOYMENT_TARGET = 9.3;
  510 + ONLY_ACTIVE_ARCH = YES;
  511 + SDKROOT = iphoneos;
  512 + TARGETED_DEVICE_FAMILY = "1,2";
  513 + };
  514 + name = Debug;
  515 + };
  516 + 6003F5BE195388D20070C39A /* Release */ = {
  517 + isa = XCBuildConfiguration;
  518 + buildSettings = {
  519 + ALWAYS_SEARCH_USER_PATHS = NO;
  520 + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
  521 + CLANG_CXX_LIBRARY = "libc++";
  522 + CLANG_ENABLE_MODULES = YES;
  523 + CLANG_ENABLE_OBJC_ARC = YES;
  524 + CLANG_WARN_BOOL_CONVERSION = YES;
  525 + CLANG_WARN_CONSTANT_CONVERSION = YES;
  526 + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
  527 + CLANG_WARN_EMPTY_BODY = YES;
  528 + CLANG_WARN_ENUM_CONVERSION = YES;
  529 + CLANG_WARN_INT_CONVERSION = YES;
  530 + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
  531 + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
  532 + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
  533 + COPY_PHASE_STRIP = YES;
  534 + ENABLE_NS_ASSERTIONS = NO;
  535 + GCC_C_LANGUAGE_STANDARD = gnu99;
  536 + GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
  537 + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
  538 + GCC_WARN_UNDECLARED_SELECTOR = YES;
  539 + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
  540 + GCC_WARN_UNUSED_FUNCTION = YES;
  541 + GCC_WARN_UNUSED_VARIABLE = YES;
  542 + IPHONEOS_DEPLOYMENT_TARGET = 9.3;
  543 + SDKROOT = iphoneos;
  544 + TARGETED_DEVICE_FAMILY = "1,2";
  545 + VALIDATE_PRODUCT = YES;
  546 + };
  547 + name = Release;
  548 + };
  549 + 6003F5C0195388D20070C39A /* Debug */ = {
  550 + isa = XCBuildConfiguration;
  551 + baseConfigurationReference = E61E5CDE06F66F688BB4ADF8 /* Pods-CNLiveAVCamera_Example.debug.xcconfig */;
  552 + buildSettings = {
  553 + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
  554 + CODE_SIGN_IDENTITY = "iPhone Developer";
  555 + DEVELOPMENT_TEAM = 94X49GG3ZW;
  556 + GCC_PRECOMPILE_PREFIX_HEADER = YES;
  557 + GCC_PREFIX_HEADER = "CNLiveAVCamera/CNLiveAVCamera-Prefix.pch";
  558 + INFOPLIST_FILE = "CNLiveAVCamera/CNLiveAVCamera-Info.plist";
  559 + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
  560 + MACH_O_TYPE = mh_execute;
  561 + MODULE_NAME = ExampleApp;
  562 + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}";
  563 + PRODUCT_NAME = "$(TARGET_NAME)";
  564 + WRAPPER_EXTENSION = app;
  565 + };
  566 + name = Debug;
  567 + };
  568 + 6003F5C1195388D20070C39A /* Release */ = {
  569 + isa = XCBuildConfiguration;
  570 + baseConfigurationReference = 232FB65DACAACEB088650B26 /* Pods-CNLiveAVCamera_Example.release.xcconfig */;
  571 + buildSettings = {
  572 + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
  573 + CODE_SIGN_IDENTITY = "iPhone Developer";
  574 + DEVELOPMENT_TEAM = 94X49GG3ZW;
  575 + GCC_PRECOMPILE_PREFIX_HEADER = YES;
  576 + GCC_PREFIX_HEADER = "CNLiveAVCamera/CNLiveAVCamera-Prefix.pch";
  577 + INFOPLIST_FILE = "CNLiveAVCamera/CNLiveAVCamera-Info.plist";
  578 + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
  579 + MACH_O_TYPE = mh_execute;
  580 + MODULE_NAME = ExampleApp;
  581 + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}";
  582 + PRODUCT_NAME = "$(TARGET_NAME)";
  583 + WRAPPER_EXTENSION = app;
  584 + };
  585 + name = Release;
  586 + };
  587 + 6003F5C3195388D20070C39A /* Debug */ = {
  588 + isa = XCBuildConfiguration;
  589 + baseConfigurationReference = 4F6BCE6DD63FA804E1500FF2 /* Pods-CNLiveAVCamera_Tests.debug.xcconfig */;
  590 + buildSettings = {
  591 + BUNDLE_LOADER = "$(TEST_HOST)";
  592 + FRAMEWORK_SEARCH_PATHS = (
  593 + "$(SDKROOT)/Developer/Library/Frameworks",
  594 + "$(inherited)",
  595 + "$(DEVELOPER_FRAMEWORKS_DIR)",
  596 + );
  597 + GCC_PRECOMPILE_PREFIX_HEADER = YES;
  598 + GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch";
  599 + GCC_PREPROCESSOR_DEFINITIONS = (
  600 + "DEBUG=1",
  601 + "$(inherited)",
  602 + );
  603 + INFOPLIST_FILE = "Tests/Tests-Info.plist";
  604 + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}";
  605 + PRODUCT_NAME = "$(TARGET_NAME)";
  606 + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CNLiveAVCamera_Example.app/CNLiveAVCamera_Example";
  607 + WRAPPER_EXTENSION = xctest;
  608 + };
  609 + name = Debug;
  610 + };
  611 + 6003F5C4195388D20070C39A /* Release */ = {
  612 + isa = XCBuildConfiguration;
  613 + baseConfigurationReference = D41556E2EE76E873ED9847B4 /* Pods-CNLiveAVCamera_Tests.release.xcconfig */;
  614 + buildSettings = {
  615 + BUNDLE_LOADER = "$(TEST_HOST)";
  616 + FRAMEWORK_SEARCH_PATHS = (
  617 + "$(SDKROOT)/Developer/Library/Frameworks",
  618 + "$(inherited)",
  619 + "$(DEVELOPER_FRAMEWORKS_DIR)",
  620 + );
  621 + GCC_PRECOMPILE_PREFIX_HEADER = YES;
  622 + GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch";
  623 + INFOPLIST_FILE = "Tests/Tests-Info.plist";
  624 + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}";
  625 + PRODUCT_NAME = "$(TARGET_NAME)";
  626 + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CNLiveAVCamera_Example.app/CNLiveAVCamera_Example";
  627 + WRAPPER_EXTENSION = xctest;
  628 + };
  629 + name = Release;
  630 + };
  631 +/* End XCBuildConfiguration section */
  632 +
  633 +/* Begin XCConfigurationList section */
  634 + 6003F585195388D10070C39A /* Build configuration list for PBXProject "CNLiveAVCamera" */ = {
  635 + isa = XCConfigurationList;
  636 + buildConfigurations = (
  637 + 6003F5BD195388D20070C39A /* Debug */,
  638 + 6003F5BE195388D20070C39A /* Release */,
  639 + );
  640 + defaultConfigurationIsVisible = 0;
  641 + defaultConfigurationName = Release;
  642 + };
  643 + 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "CNLiveAVCamera_Example" */ = {
  644 + isa = XCConfigurationList;
  645 + buildConfigurations = (
  646 + 6003F5C0195388D20070C39A /* Debug */,
  647 + 6003F5C1195388D20070C39A /* Release */,
  648 + );
  649 + defaultConfigurationIsVisible = 0;
  650 + defaultConfigurationName = Release;
  651 + };
  652 + 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "CNLiveAVCamera_Tests" */ = {
  653 + isa = XCConfigurationList;
  654 + buildConfigurations = (
  655 + 6003F5C3195388D20070C39A /* Debug */,
  656 + 6003F5C4195388D20070C39A /* Release */,
  657 + );
  658 + defaultConfigurationIsVisible = 0;
  659 + defaultConfigurationName = Release;
  660 + };
  661 +/* End XCConfigurationList section */
  662 + };
  663 + rootObject = 6003F582195388D10070C39A /* Project object */;
  664 +}
Example/CNLiveAVCamera.xcodeproj/xcshareddata/xcschemes/CNLiveAVCamera-Example.xcscheme 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<Scheme
  3 + LastUpgradeVersion = "0720"
  4 + version = "1.3">
  5 + <BuildAction
  6 + parallelizeBuildables = "YES"
  7 + buildImplicitDependencies = "YES">
  8 + <BuildActionEntries>
  9 + <BuildActionEntry
  10 + buildForTesting = "YES"
  11 + buildForRunning = "YES"
  12 + buildForProfiling = "YES"
  13 + buildForArchiving = "YES"
  14 + buildForAnalyzing = "YES">
  15 + <BuildableReference
  16 + BuildableIdentifier = "primary"
  17 + BlueprintIdentifier = "6003F589195388D20070C39A"
  18 + BuildableName = "CNLiveAVCamera_Example.app"
  19 + BlueprintName = "CNLiveAVCamera_Example"
  20 + ReferencedContainer = "container:CNLiveAVCamera.xcodeproj">
  21 + </BuildableReference>
  22 + </BuildActionEntry>
  23 + </BuildActionEntries>
  24 + </BuildAction>
  25 + <TestAction
  26 + buildConfiguration = "Debug"
  27 + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
  28 + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
  29 + shouldUseLaunchSchemeArgsEnv = "YES">
  30 + <Testables>
  31 + <TestableReference
  32 + skipped = "NO">
  33 + <BuildableReference
  34 + BuildableIdentifier = "primary"
  35 + BlueprintIdentifier = "6003F5AD195388D20070C39A"
  36 + BuildableName = "CNLiveAVCamera_Tests.xctest"
  37 + BlueprintName = "CNLiveAVCamera_Tests"
  38 + ReferencedContainer = "container:CNLiveAVCamera.xcodeproj">
  39 + </BuildableReference>
  40 + </TestableReference>
  41 + </Testables>
  42 + <MacroExpansion>
  43 + <BuildableReference
  44 + BuildableIdentifier = "primary"
  45 + BlueprintIdentifier = "6003F589195388D20070C39A"
  46 + BuildableName = "CNLiveAVCamera_Example.app"
  47 + BlueprintName = "CNLiveAVCamera_Example"
  48 + ReferencedContainer = "container:CNLiveAVCamera.xcodeproj">
  49 + </BuildableReference>
  50 + </MacroExpansion>
  51 + <AdditionalOptions>
  52 + </AdditionalOptions>
  53 + </TestAction>
  54 + <LaunchAction
  55 + buildConfiguration = "Debug"
  56 + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
  57 + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
  58 + launchStyle = "0"
  59 + useCustomWorkingDirectory = "NO"
  60 + ignoresPersistentStateOnLaunch = "NO"
  61 + debugDocumentVersioning = "YES"
  62 + debugServiceExtension = "internal"
  63 + allowLocationSimulation = "YES">
  64 + <BuildableProductRunnable
  65 + runnableDebuggingMode = "0">
  66 + <BuildableReference
  67 + BuildableIdentifier = "primary"
  68 + BlueprintIdentifier = "6003F589195388D20070C39A"
  69 + BuildableName = "CNLiveAVCamera_Example.app"
  70 + BlueprintName = "CNLiveAVCamera_Example"
  71 + ReferencedContainer = "container:CNLiveAVCamera.xcodeproj">
  72 + </BuildableReference>
  73 + </BuildableProductRunnable>
  74 + <AdditionalOptions>
  75 + </AdditionalOptions>
  76 + </LaunchAction>
  77 + <ProfileAction
  78 + buildConfiguration = "Release"
  79 + shouldUseLaunchSchemeArgsEnv = "YES"
  80 + savedToolIdentifier = ""
  81 + useCustomWorkingDirectory = "NO"
  82 + debugDocumentVersioning = "YES">
  83 + <BuildableProductRunnable
  84 + runnableDebuggingMode = "0">
  85 + <BuildableReference
  86 + BuildableIdentifier = "primary"
  87 + BlueprintIdentifier = "6003F589195388D20070C39A"
  88 + BuildableName = "CNLiveAVCamera_Example.app"
  89 + BlueprintName = "CNLiveAVCamera_Example"
  90 + ReferencedContainer = "container:CNLiveAVCamera.xcodeproj">
  91 + </BuildableReference>
  92 + </BuildableProductRunnable>
  93 + </ProfileAction>
  94 + <AnalyzeAction
  95 + buildConfiguration = "Debug">
  96 + </AnalyzeAction>
  97 + <ArchiveAction
  98 + buildConfiguration = "Release"
  99 + revealArchiveInOrganizer = "YES">
  100 + </ArchiveAction>
  101 +</Scheme>
Example/CNLiveAVCamera/Base.lproj/LaunchScreen.storyboard 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
  3 + <device id="retina4_7" orientation="portrait">
  4 + <adaptation id="fullscreen"/>
  5 + </device>
  6 + <dependencies>
  7 + <deployment identifier="iOS"/>
  8 + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
  9 + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
  10 + </dependencies>
  11 + <scenes>
  12 + <!--View Controller-->
  13 + <scene sceneID="EHf-IW-A2E">
  14 + <objects>
  15 + <viewController id="01J-lp-oVM" sceneMemberID="viewController">
  16 + <layoutGuides>
  17 + <viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
  18 + <viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
  19 + </layoutGuides>
  20 + <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
  21 + <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
  22 + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
  23 + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
  24 + </view>
  25 + </viewController>
  26 + <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
  27 + </objects>
  28 + <point key="canvasLocation" x="53" y="375"/>
  29 + </scene>
  30 + </scenes>
  31 +</document>
Example/CNLiveAVCamera/Base.lproj/Main.storyboard 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="whP-gf-Uak">
  3 + <device id="retina4_7" orientation="portrait">
  4 + <adaptation id="fullscreen"/>
  5 + </device>
  6 + <dependencies>
  7 + <deployment identifier="iOS"/>
  8 + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
  9 + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
  10 + </dependencies>
  11 + <scenes>
  12 + <!--View Controller-->
  13 + <scene sceneID="wQg-tq-qST">
  14 + <objects>
  15 + <viewController id="whP-gf-Uak" customClass="CNLiveViewController" sceneMemberID="viewController">
  16 + <layoutGuides>
  17 + <viewControllerLayoutGuide type="top" id="uEw-UM-LJ8"/>
  18 + <viewControllerLayoutGuide type="bottom" id="Mvr-aV-6Um"/>
  19 + </layoutGuides>
  20 + <view key="view" contentMode="scaleToFill" id="TpU-gO-2f1">
  21 + <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
  22 + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
  23 + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
  24 + </view>
  25 + </viewController>
  26 + <placeholder placeholderIdentifier="IBFirstResponder" id="tc2-Qw-aMS" userLabel="First Responder" sceneMemberID="firstResponder"/>
  27 + </objects>
  28 + <point key="canvasLocation" x="305" y="433"/>
  29 + </scene>
  30 + </scenes>
  31 +</document>
Example/CNLiveAVCamera/CNLiveAVCamera-Info.plist 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3 +<plist version="1.0">
  4 +<dict>
  5 + <key>CFBundleDevelopmentRegion</key>
  6 + <string>en</string>
  7 + <key>CFBundleDisplayName</key>
  8 + <string>${PRODUCT_NAME}</string>
  9 + <key>CFBundleExecutable</key>
  10 + <string>${EXECUTABLE_NAME}</string>
  11 + <key>CFBundleIdentifier</key>
  12 + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
  13 + <key>CFBundleInfoDictionaryVersion</key>
  14 + <string>6.0</string>
  15 + <key>CFBundleName</key>
  16 + <string>${PRODUCT_NAME}</string>
  17 + <key>CFBundlePackageType</key>
  18 + <string>APPL</string>
  19 + <key>CFBundleShortVersionString</key>
  20 + <string>1.0</string>
  21 + <key>CFBundleSignature</key>
  22 + <string>????</string>
  23 + <key>CFBundleVersion</key>
  24 + <string>1.0</string>
  25 + <key>LSRequiresIPhoneOS</key>
  26 + <true/>
  27 + <key>UILaunchStoryboardName</key>
  28 + <string>LaunchScreen</string>
  29 + <key>UIMainStoryboardFile</key>
  30 + <string>Main</string>
  31 + <key>UIRequiredDeviceCapabilities</key>
  32 + <array>
  33 + <string>armv7</string>
  34 + </array>
  35 + <key>UISupportedInterfaceOrientations</key>
  36 + <array>
  37 + <string>UIInterfaceOrientationPortrait</string>
  38 + <string>UIInterfaceOrientationLandscapeLeft</string>
  39 + <string>UIInterfaceOrientationLandscapeRight</string>
  40 + </array>
  41 + <key>UISupportedInterfaceOrientations~ipad</key>
  42 + <array>
  43 + <string>UIInterfaceOrientationPortrait</string>
  44 + <string>UIInterfaceOrientationPortraitUpsideDown</string>
  45 + <string>UIInterfaceOrientationLandscapeLeft</string>
  46 + <string>UIInterfaceOrientationLandscapeRight</string>
  47 + </array>
  48 +
  49 + <key>NSCameraUsageDescription</key>
  50 + <string>需要允许开启相机才能在发布生活圈或聊天时使用录制视频和拍照功能</string>
  51 + <key>NSContactsUsageDescription</key>
  52 + <string>需要允许访问通讯录才能获取手机联系人中的网++用户</string>
  53 + <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
  54 + <string>需要允许使用您的位置信息才能获取您所在的城市</string>
  55 + <key>NSLocationAlwaysUsageDescription</key>
  56 + <string>需要允许使用您的位置信息才能获取您所在的城市</string>
  57 + <key>NSLocationWhenInUseUsageDescription</key>
  58 + <string>需要允许使用您的位置信息才能获取您所在的城市</string>
  59 + <key>NSMicrophoneUsageDescription</key>
  60 + <string>需要允许开启麦克风才能使用录制视频和语音等服务</string>
  61 + <key>NSPhotoLibraryAddUsageDescription</key>
  62 + <string></string>
  63 + <key>NSPhotoLibraryUsageDescription</key>
  64 + <string>需要允许打开相册才能访问相册照片和保存照片</string>
  65 +
  66 +</dict>
  67 +</plist>
Example/CNLiveAVCamera/CNLiveAVCamera-Prefix.pch 0 → 100644
  1 +//
  2 +// Prefix header
  3 +//
  4 +// The contents of this file are implicitly included at the beginning of every source file.
  5 +//
  6 +
  7 +#import <Availability.h>
  8 +
  9 +#ifndef __IPHONE_5_0
  10 +#warning "This project uses features only available in iOS SDK 5.0 and later."
  11 +#endif
  12 +
  13 +#ifdef __OBJC__
  14 + @import UIKit;
  15 + @import Foundation;
  16 +#endif
Example/CNLiveAVCamera/CNLiveAVCamera.h 0 → 100644
  1 +//
  2 +// CNLiveAVCamera.h
  3 +// CNLiveAVCamera
  4 +//
  5 +// Created by 梁星国 on 2018/12/7.
  6 +// Copyright © 2018年 jyyjkt. All rights reserved.
  7 +//
  8 +
  9 +#import <UIKit/UIKit.h>
  10 +
  11 +//! Project version number for CNLiveAVCamera.
  12 +FOUNDATION_EXPORT double CNLiveAVCameraVersionNumber;
  13 +
  14 +//! Project version string for CNLiveAVCamera.
  15 +FOUNDATION_EXPORT const unsigned char CNLiveAVCameraVersionString[];
  16 +
  17 +// In this header, you should import all the public headers of your framework using statements like #import <CNLiveAVCamera/PublicHeader.h>
  18 +
  19 +
Example/CNLiveAVCamera/CNLiveAppDelegate.h 0 → 100644
  1 +//
  2 +// CNLiveAppDelegate.h
  3 +// CNLiveAVCamera
  4 +//
  5 +// Created by jyyjkt on 12/07/2018.
  6 +// Copyright (c) 2018 jyyjkt. All rights reserved.
  7 +//
  8 +
  9 +@import UIKit;
  10 +
  11 +@interface CNLiveAppDelegate : UIResponder <UIApplicationDelegate>
  12 +
  13 +@property (strong, nonatomic) UIWindow *window;
  14 +
  15 +@end
Example/CNLiveAVCamera/CNLiveAppDelegate.m 0 → 100644
  1 +//
  2 +// CNLiveAppDelegate.m
  3 +// CNLiveAVCamera
  4 +//
  5 +// Created by jyyjkt on 12/07/2018.
  6 +// Copyright (c) 2018 jyyjkt. All rights reserved.
  7 +//
  8 +
  9 +#import "CNLiveAppDelegate.h"
  10 +
  11 +@implementation CNLiveAppDelegate
  12 +
  13 +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  14 +{
  15 + // Override point for customization after application launch.
  16 + return YES;
  17 +}
  18 +
  19 +- (void)applicationWillResignActive:(UIApplication *)application
  20 +{
  21 + // 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.
  22 + // 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.
  23 +}
  24 +
  25 +- (void)applicationDidEnterBackground:(UIApplication *)application
  26 +{
  27 + // 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.
  28 + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
  29 +}
  30 +
  31 +- (void)applicationWillEnterForeground:(UIApplication *)application
  32 +{
  33 + // 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.
  34 +}
  35 +
  36 +- (void)applicationDidBecomeActive:(UIApplication *)application
  37 +{
  38 + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
  39 +}
  40 +
  41 +- (void)applicationWillTerminate:(UIApplication *)application
  42 +{
  43 + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
  44 +}
  45 +
  46 +@end
Example/CNLiveAVCamera/CNLiveViewController.h 0 → 100644
  1 +//
  2 +// CNLiveViewController.h
  3 +// CNLiveAVCamera
  4 +//
  5 +// Created by jyyjkt on 12/07/2018.
  6 +// Copyright (c) 2018 jyyjkt. All rights reserved.
  7 +//
  8 +
  9 +@import UIKit;
  10 +
  11 +@interface CNLiveViewController : UIViewController
  12 +
  13 +@end
Example/CNLiveAVCamera/CNLiveViewController.m 0 → 100644
  1 +//
  2 +// CNLiveViewController.m
  3 +// CNLiveAVCamera
  4 +//
  5 +// Created by jyyjkt on 12/07/2018.
  6 +// Copyright (c) 2018 jyyjkt. All rights reserved.
  7 +//
  8 +
  9 +#import "CNLiveViewController.h"
  10 +#import <CNLiveAVCamera/XFCameraController.h>
  11 +
  12 +@interface CNLiveViewController ()
  13 +
  14 +@end
  15 +
  16 +@implementation CNLiveViewController
  17 +
  18 +- (void)viewDidLoad
  19 +{
  20 + [super viewDidLoad];
  21 +
  22 + UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
  23 + button.frame = CGRectMake(100, 100, 100, 100);
  24 + [button setTitle:@"进入" forState:UIControlStateNormal];
  25 + [button setBackgroundColor:[UIColor yellowColor]];
  26 + [button addTarget: self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
  27 + [self.view addSubview:button];
  28 +}
  29 +
  30 +- (void)buttonAction:(id)sender {
  31 + [self takeToXFPhoto];
  32 +
  33 +}
  34 +
  35 +
  36 +#pragma mark - 私有方法
  37 +-(void)takeToXFPhoto {
  38 + XFCameraController *cameraController = [[XFCameraController alloc]init];
  39 + cameraController.isCanShootVideo = YES;
  40 + __weak XFCameraController *weakCameraController = cameraController;
  41 + cameraController.takePhotosCompletionBlock = ^(UIImage *image, NSError *error) {
  42 + if (!error) {
  43 + NSLog(@"------------输出图片=%@",image);
  44 + dispatch_async(dispatch_get_main_queue(), ^{
  45 + [weakCameraController dismissViewControllerAnimated:YES completion:nil];
  46 + });
  47 +
  48 + }
  49 +
  50 + };
  51 + //拍摄的是视频
  52 + cameraController.zxshootCompletionBlock = ^(PHAsset *asset, NSURL *videoUrl, CGFloat videoTimeLength, UIImage *thumbnailImage, NSError *error) {
  53 + if (!error) {
  54 + NSLog(@"------------输出视频路径=%@",videoUrl);
  55 + dispatch_async(dispatch_get_main_queue(), ^{
  56 + [weakCameraController dismissViewControllerAnimated:YES completion:nil];
  57 + });
  58 + }
  59 +
  60 + };
  61 + [self presentViewController:cameraController animated:YES completion:nil];
  62 +}
  63 +
  64 +
  65 +- (void)didReceiveMemoryWarning
  66 +{
  67 + [super didReceiveMemoryWarning];
  68 + // Dispose of any resources that can be recreated.
  69 +}
  70 +
  71 +@end
Example/CNLiveAVCamera/Images.xcassets/AppIcon.appiconset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "iphone",
  5 + "size" : "20x20",
  6 + "scale" : "2x"
  7 + },
  8 + {
  9 + "idiom" : "iphone",
  10 + "size" : "20x20",
  11 + "scale" : "3x"
  12 + },
  13 + {
  14 + "idiom" : "iphone",
  15 + "size" : "29x29",
  16 + "scale" : "2x"
  17 + },
  18 + {
  19 + "idiom" : "iphone",
  20 + "size" : "29x29",
  21 + "scale" : "3x"
  22 + },
  23 + {
  24 + "idiom" : "iphone",
  25 + "size" : "40x40",
  26 + "scale" : "2x"
  27 + },
  28 + {
  29 + "idiom" : "iphone",
  30 + "size" : "40x40",
  31 + "scale" : "3x"
  32 + },
  33 + {
  34 + "idiom" : "iphone",
  35 + "size" : "60x60",
  36 + "scale" : "2x"
  37 + },
  38 + {
  39 + "idiom" : "iphone",
  40 + "size" : "60x60",
  41 + "scale" : "3x"
  42 + },
  43 + {
  44 + "idiom" : "ipad",
  45 + "size" : "20x20",
  46 + "scale" : "1x"
  47 + },
  48 + {
  49 + "idiom" : "ipad",
  50 + "size" : "20x20",
  51 + "scale" : "2x"
  52 + },
  53 + {
  54 + "idiom" : "ipad",
  55 + "size" : "29x29",
  56 + "scale" : "1x"
  57 + },
  58 + {
  59 + "idiom" : "ipad",
  60 + "size" : "29x29",
  61 + "scale" : "2x"
  62 + },
  63 + {
  64 + "idiom" : "ipad",
  65 + "size" : "40x40",
  66 + "scale" : "1x"
  67 + },
  68 + {
  69 + "idiom" : "ipad",
  70 + "size" : "40x40",
  71 + "scale" : "2x"
  72 + },
  73 + {
  74 + "idiom" : "ipad",
  75 + "size" : "76x76",
  76 + "scale" : "1x"
  77 + },
  78 + {
  79 + "idiom" : "ipad",
  80 + "size" : "76x76",
  81 + "scale" : "2x"
  82 + },
  83 + {
  84 + "idiom" : "ipad",
  85 + "size" : "83.5x83.5",
  86 + "scale" : "2x"
  87 + },
  88 + {
  89 + "idiom" : "ios-marketing",
  90 + "size" : "1024x1024",
  91 + "scale" : "1x"
  92 + }
  93 + ],
  94 + "info" : {
  95 + "version" : 1,
  96 + "author" : "xcode"
  97 + }
  98 +}
Example/CNLiveAVCamera/Info.plist 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3 +<plist version="1.0">
  4 +<dict>
  5 + <key>CFBundleDevelopmentRegion</key>
  6 + <string>$(DEVELOPMENT_LANGUAGE)</string>
  7 + <key>CFBundleExecutable</key>
  8 + <string>$(EXECUTABLE_NAME)</string>
  9 + <key>CFBundleIdentifier</key>
  10 + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
  11 + <key>CFBundleInfoDictionaryVersion</key>
  12 + <string>6.0</string>
  13 + <key>CFBundleName</key>
  14 + <string>$(PRODUCT_NAME)</string>
  15 + <key>CFBundlePackageType</key>
  16 + <string>FMWK</string>
  17 + <key>CFBundleShortVersionString</key>
  18 + <string>1.0</string>
  19 + <key>CFBundleVersion</key>
  20 + <string>$(CURRENT_PROJECT_VERSION)</string>
  21 +</dict>
  22 +</plist>
Example/CNLiveAVCamera/en.lproj/InfoPlist.strings 0 → 100644
  1 +/* Localized versions of Info.plist keys */
  2 +
Example/CNLiveAVCamera/main.m 0 → 100644
  1 +//
  2 +// main.m
  3 +// CNLiveAVCamera
  4 +//
  5 +// Created by jyyjkt on 12/07/2018.
  6 +// Copyright (c) 2018 jyyjkt. All rights reserved.
  7 +//
  8 +
  9 +@import UIKit;
  10 +#import "CNLiveAppDelegate.h"
  11 +
  12 +int main(int argc, char * argv[])
  13 +{
  14 + @autoreleasepool {
  15 + return UIApplicationMain(argc, argv, nil, NSStringFromClass([CNLiveAppDelegate class]));
  16 + }
  17 +}
Example/Podfile 0 → 100644
  1 +use_frameworks!
  2 +
  3 +platform :ios, '8.0'
  4 +
  5 +target 'CNLiveAVCamera_Example' do
  6 + pod 'CNLiveAVCamera', :path => '../'
  7 +
  8 + pod 'Masonry', '~> 1.0.2'
  9 +
  10 + target 'CNLiveAVCamera_Tests' do
  11 + inherit! :search_paths
  12 + pod 'Masonry', '~> 1.0.2'
  13 +
  14 + end
  15 +end
Example/Tests/Tests-Info.plist 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3 +<plist version="1.0">
  4 +<dict>
  5 + <key>CFBundleDevelopmentRegion</key>
  6 + <string>en</string>
  7 + <key>CFBundleExecutable</key>
  8 + <string>${EXECUTABLE_NAME}</string>
  9 + <key>CFBundleIdentifier</key>
  10 + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
  11 + <key>CFBundleInfoDictionaryVersion</key>
  12 + <string>6.0</string>
  13 + <key>CFBundlePackageType</key>
  14 + <string>BNDL</string>
  15 + <key>CFBundleShortVersionString</key>
  16 + <string>1.0</string>
  17 + <key>CFBundleSignature</key>
  18 + <string>????</string>
  19 + <key>CFBundleVersion</key>
  20 + <string>1</string>
  21 +</dict>
  22 +</plist>
Example/Tests/Tests-Prefix.pch 0 → 100644
  1 +// The contents of this file are implicitly included at the beginning of every test case source file.
  2 +
  3 +#ifdef __OBJC__
  4 +
  5 +
  6 +
  7 +#endif
Example/Tests/Tests.m 0 → 100644
  1 +//
  2 +// CNLiveAVCameraTests.m
  3 +// CNLiveAVCameraTests
  4 +//
  5 +// Created by jyyjkt on 12/07/2018.
  6 +// Copyright (c) 2018 jyyjkt. All rights reserved.
  7 +//
  8 +
  9 +@import XCTest;
  10 +
  11 +@interface Tests : XCTestCase
  12 +
  13 +@end
  14 +
  15 +@implementation Tests
  16 +
  17 +- (void)setUp
  18 +{
  19 + [super setUp];
  20 + // Put setup code here. This method is called before the invocation of each test method in the class.
  21 +}
  22 +
  23 +- (void)tearDown
  24 +{
  25 + // Put teardown code here. This method is called after the invocation of each test method in the class.
  26 + [super tearDown];
  27 +}
  28 +
  29 +- (void)testExample
  30 +{
  31 + XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
  32 +}
  33 +
  34 +@end
  35 +
Example/Tests/en.lproj/InfoPlist.strings 0 → 100644
  1 +/* Localized versions of Info.plist keys */
  2 +
LICENSE 0 → 100644
  1 +Copyright (c) 2018 jyyjkt <jyyjkt@qq.com>
  2 +
  3 +Permission is hereby granted, free of charge, to any person obtaining a copy
  4 +of this software and associated documentation files (the "Software"), to deal
  5 +in the Software without restriction, including without limitation the rights
  6 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7 +copies of the Software, and to permit persons to whom the Software is
  8 +furnished to do so, subject to the following conditions:
  9 +
  10 +The above copyright notice and this permission notice shall be included in
  11 +all copies or substantial portions of the Software.
  12 +
  13 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19 +THE SOFTWARE.
README.md
  1 +# CNLiveAVCamera
  2 +
  3 +[![CI Status](https://img.shields.io/travis/jyyjkt/CNLiveAVCamera.svg?style=flat)](https://travis-ci.org/jyyjkt/CNLiveAVCamera)
  4 +[![Version](https://img.shields.io/cocoapods/v/CNLiveAVCamera.svg?style=flat)](https://cocoapods.org/pods/CNLiveAVCamera)
  5 +[![License](https://img.shields.io/cocoapods/l/CNLiveAVCamera.svg?style=flat)](https://cocoapods.org/pods/CNLiveAVCamera)
  6 +[![Platform](https://img.shields.io/cocoapods/p/CNLiveAVCamera.svg?style=flat)](https://cocoapods.org/pods/CNLiveAVCamera)
  7 +
  8 +## Example
  9 +
  10 +To run the example project, clone the repo, and run `pod install` from the Example directory first.
  11 +
  12 +## Requirements
  13 +
  14 +## Installation
  15 +
  16 +CNLiveAVCamera is available through [CocoaPods](https://cocoapods.org). To install
  17 +it, simply add the following line to your Podfile:
  18 +
  19 +```ruby
  20 +pod 'CNLiveAVCamera'
  21 +```
  22 +
  23 +## Author
  24 +
  25 +jyyjkt, jyyjkt@qq.com
  26 +
  27 +## License
  28 +
  29 +CNLiveAVCamera is available under the MIT license. See the LICENSE file for more info.
_Pods.xcodeproj 0 → 120000
  1 +Example/Pods/Pods.xcodeproj
0 \ No newline at end of file 2 \ No newline at end of file