| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358 |
- //
- // MGVideoManager.m
- // MGLivenessDetection
- //
- // Created by 张英堂 on 16/3/31.
- // Copyright © 2016年 megvii. All rights reserved.
- //
- #import "MGVideoManager.h"
- //屏幕宽度 (区别于viewcontroller.view.fream)
- #define MG_WIN_WIDTH [UIScreen mainScreen].bounds.size.width
- //屏幕高度 (区别于viewcontroller.view.fream)
- #define MG_WIN_HEIGHT [UIScreen mainScreen].bounds.size.height
- @interface MGVideoManager ()<AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAudioDataOutputSampleBufferDelegate>
- {
- AVCaptureConnection *_audioConnection;
- AVCaptureConnection *_videoConnection;
- NSDictionary *_audioCompressionSettings;
- AVCaptureDevice *_videoDevice;
- dispatch_queue_t _videoQueue;
- }
- @property(nonatomic, assign) CMFormatDescriptionRef outputAudioFormatDescription;
- @property(nonatomic, assign) CMFormatDescriptionRef outputVideoFormatDescription;
- @property (nonatomic, strong) AVCaptureVideoPreviewLayer *videoPreviewLayer;
- @property(nonatomic, copy) NSString *sessionPreset;
- @property(nonatomic, copy) NSString *tempVideoPath;
- @property (nonatomic, assign) BOOL videoRecord;
- @property (nonatomic, assign) BOOL videoSound;
- @property (nonatomic, assign) BOOL startRecord;
- @end
- @implementation MGVideoManager
- -(void)dealloc{
- _audioConnection = nil;
- _videoConnection = nil;
- self.videoDelegate = nil;
- self.sessionPreset = nil;
- }
- -(instancetype)initWithPreset:(NSString *)sessionPreset
- devicePosition:(AVCaptureDevicePosition)devicePosition
- videoRecord:(BOOL)record
- videoSound:(BOOL)sound{
- self = [super init];
- if (self) {
- self.sessionPreset = sessionPreset;
- _devicePosition = devicePosition;
- self.videoRecord = record;
- self.videoSound = sound;
-
- _startRecord = NO;
- _videoQueue = dispatch_queue_create("com.megvii.face.video", NULL);
- }
- return self;
- }
- + (instancetype)videoPreset:(NSString *)sessionPreset
- devicePosition:(AVCaptureDevicePosition)devicePosition
- videoRecord:(BOOL)record
- videoSound:(BOOL)sound{
-
- MGVideoManager *manager = [[MGVideoManager alloc] initWithPreset:sessionPreset
- devicePosition:devicePosition
- videoRecord:record
- videoSound:sound];
- return manager;
- }
- #pragma mark - video 功能开关
- - (void)stopRunning{
- if (self.videoSession) {
- [self.videoSession stopRunning];
- }
- }
- - (void)startRunning{
- [self initialSession];
-
- if (self.videoSession) {
- [self.videoSession startRunning];
- }
- }
- - (void)startRecording{
- [self startRunning];
-
- if (!self.videoRecord) {
- return;
- }
- _startRecord = YES;
- }
- - (NSString *)stopRceording{
- _startRecord = NO;
-
-
- NSString *tempString = @"no video!";
- return tempString;
- }
- #pragma mark - 初始化video配置
- - (NSString *)sessionPreset{
- if (nil == _sessionPreset) {
- _sessionPreset = AVCaptureSessionPreset640x480;
- }
- return _sessionPreset;
- }
- -(AVCaptureVideoPreviewLayer *)videoPreviewLayer{
- if (nil == _videoPreviewLayer) {
- _videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.videoSession];
- [_videoPreviewLayer setFrame:CGRectMake(0, 0, MG_WIN_WIDTH, MG_WIN_HEIGHT)];
- [_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
- }
- return _videoPreviewLayer;
- }
- -(AVCaptureVideoPreviewLayer *)videoPreview{
- return self.videoPreviewLayer;
- }
- -(BOOL)videoSound{
- if (_videoRecord && _videoSound) {
- return YES;
- }
- return NO;
- }
- - (CMFormatDescriptionRef)formatDescription{
- return self.outputVideoFormatDescription;
- }
- - (dispatch_queue_t)getVideoQueue{
- return _videoQueue;
- }
- //初始化相机
- - (void) initialSession
- {
- if (self.videoSession == nil) {
-
- /* session */
- _videoSession = [[AVCaptureSession alloc] init];
-
- /* 摄像头 */
- _videoDevice = [self cameraWithPosition:self.devicePosition];
- [self setMaxVideoFrame:60 videoDevice:_videoDevice];
-
- /* input */
- NSError *DeviceError;
- _videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:_videoDevice error:&DeviceError];
- if (DeviceError) {
- [self videoError:DeviceError];
- return;
- }
- if ([self.videoSession canAddInput:self.videoInput]) {
- [self.videoSession addInput:self.videoInput];
- }
-
- /* output */
- AVCaptureVideoDataOutput *output = [[AVCaptureVideoDataOutput alloc] init];
- [output setSampleBufferDelegate:self queue:_videoQueue];
- output.videoSettings = @{(id)kCVPixelBufferPixelFormatTypeKey:@(kCVPixelFormatType_32BGRA)};
- output.alwaysDiscardsLateVideoFrames = NO;
-
- if ([self.videoSession canAddOutput:output]) {
- [self.videoSession addOutput:output];
- }
-
- /* sessionPreset */
- // 判断最佳分辨率
- if ([self.videoSession canSetSessionPreset:AVCaptureSessionPreset1920x1080]) {
- [self.videoSession setSessionPreset: AVCaptureSessionPreset1920x1080];
- NSLog(@"分辨率 1920*1080");
- }else if ([self.videoSession canSetSessionPreset:AVCaptureSessionPreset1280x720]) {
- [self.videoSession setSessionPreset: AVCaptureSessionPreset1280x720];
- NSLog(@"分辨率 1280*720");
- }else if ([self.videoSession canSetSessionPreset:AVCaptureSessionPresetiFrame960x540]) {
- [self.videoSession setSessionPreset: AVCaptureSessionPresetiFrame960x540];
- NSLog(@"分辨率 960*540");
- }else {
- [self.videoSession setSessionPreset: AVCaptureSessionPreset640x480];
- NSLog(@"分辨率 640*480");
- }
- // if ([self.videoSession canSetSessionPreset:self.sessionPreset]) {
- // [self.videoSession setSessionPreset: self.sessionPreset];
- // }else{
- // NSError *presetError = [NSError errorWithDomain:NSCocoaErrorDomain code:101 userInfo:@{@"sessionPreset":@"不支持的sessionPreset!"}];
- // [self videoError:presetError];
- // return;
- // }
-
- _videoConnection = [output connectionWithMediaType:AVMediaTypeVideo];
- // [_videoConnection setVideoOrientation:AVCaptureVideoOrientationPortrait];
- self.videoOrientation = _videoConnection.videoOrientation;
-
- /* 设置声音 */
- if (self.videoSound) {
- AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
- AVCaptureDeviceInput *audioIn = [[AVCaptureDeviceInput alloc] initWithDevice:audioDevice error:nil];
- if ( [self.videoSession canAddInput:audioIn] ) {
- [self.videoSession addInput:audioIn];
- }
-
- AVCaptureAudioDataOutput *audioOut = [[AVCaptureAudioDataOutput alloc] init];
- dispatch_queue_t audioCaptureQueue = dispatch_queue_create("com.megvii.audio", DISPATCH_QUEUE_SERIAL );
- [audioOut setSampleBufferDelegate:self queue:audioCaptureQueue];
-
- if ( [self.videoSession canAddOutput:audioOut] ) {
- [self.videoSession addOutput:audioOut];
- }
- _audioConnection = [audioOut connectionWithMediaType:AVMediaTypeAudio];
- output.alwaysDiscardsLateVideoFrames = YES;
-
- _audioCompressionSettings = [[audioOut recommendedAudioSettingsForAssetWriterWithOutputFileType:AVFileTypeQuickTimeMovie] copy];
- }
- }
- }
- - (void)initVideoRecord:(CMFormatDescriptionRef)formatDescription{
-
- }
- //前后摄像头
- - (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition) position {
- NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
- for (AVCaptureDevice *device in devices) {
- if ([device position] == position) {
- return device;
- }
- }
- return nil;
- }
- //前后摄像头的切换
- - (void)toggleCamera:(id)sender{
- NSUInteger cameraCount = [[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo] count];
- if (cameraCount > 1) {
- NSError *error;
- AVCaptureDeviceInput *newVideoInput;
- AVCaptureDevicePosition position = [[_videoInput device] position];
-
- if (position == AVCaptureDevicePositionBack)
- newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self cameraWithPosition:AVCaptureDevicePositionFront] error:&error];
- else if (position == AVCaptureDevicePositionFront)
- newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self cameraWithPosition:AVCaptureDevicePositionBack] error:&error];
- else
- return;
-
- if (newVideoInput != nil) {
- [self.videoSession beginConfiguration];
- [self.videoSession removeInput:self.videoInput];
- if ([self.videoSession canAddInput:newVideoInput]) {
- [self.videoSession addInput:newVideoInput];
- _videoInput = newVideoInput;
- } else {
- [self.videoSession addInput:self.videoInput];
- }
- [self.videoSession commitConfiguration];
- } else if (error) {
- [self videoError:error];
- }
- }
- }
- // 设置 视频最大帧率
- - (void)setMaxVideoFrame:(NSInteger)frame videoDevice:(AVCaptureDevice *)videoDevice{
- for(AVCaptureDeviceFormat *vFormat in [videoDevice formats])
- {
- CMFormatDescriptionRef description= vFormat.formatDescription;
- AVFrameRateRange *rateRange = (AVFrameRateRange*)[vFormat.videoSupportedFrameRateRanges objectAtIndex:0];
- float maxrate = rateRange.maxFrameRate;
-
- if(maxrate >= frame && CMFormatDescriptionGetMediaSubType(description)==kCVPixelFormatType_420YpCbCr8BiPlanarFullRange)
- {
- if (YES == [videoDevice lockForConfiguration:NULL])
- {
- videoDevice.activeFormat = vFormat;
- [videoDevice setActiveVideoMinFrameDuration:CMTimeMake(1,(int)(frame/3))];
- [videoDevice setActiveVideoMaxFrameDuration:CMTimeMake(1,(int)frame)];
- [videoDevice unlockForConfiguration];
- }
- }
- }
- }
- //录像功能
- - (void)appendVideoBuffer:(CMSampleBufferRef)pixelBuffer
- {
-
- }
- - (void)appendAudioBuffer:(CMSampleBufferRef)sampleBuffer{
-
- }
- - (CGAffineTransform)transformFromVideoBufferOrientationToOrientation:(AVCaptureVideoOrientation)orientation withAutoMirroring:(BOOL)mirror
- {
- CGAffineTransform transform = CGAffineTransformIdentity;
-
- CGFloat orientationAngleOffset = [MGImage angleOffsetFromPortraitOrientationToOrientation:orientation];
- CGFloat videoOrientationAngleOffset = [MGImage angleOffsetFromPortraitOrientationToOrientation:self.videoOrientation];
-
- CGFloat angleOffset = orientationAngleOffset - videoOrientationAngleOffset;
- transform = CGAffineTransformMakeRotation(angleOffset);
- // transform = CGAffineTransformRotate(transform, -M_PI);
-
- if ( _videoDevice.position == AVCaptureDevicePositionFront)
- {
- if (mirror) {
- transform = CGAffineTransformScale(transform, -1, 1);
- }else {
- transform = CGAffineTransformRotate(transform, M_PI );
- }
- }
-
- return transform;
- }
- #pragma mark - delegate
- - (void)captureOutput:(AVCaptureOutput *)captureOutput
- didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
- fromConnection:(AVCaptureConnection *)connection
- {
- @autoreleasepool {
- if (connection == _videoConnection)
- {
- CMFormatDescriptionRef formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer);
-
- if (self.outputVideoFormatDescription == nil) {
- self.outputVideoFormatDescription = formatDescription;
- }
- if (self.videoDelegate) {
- [self.videoDelegate MGCaptureOutput:captureOutput didOutputSampleBuffer:sampleBuffer fromConnection:connection];
- }
-
- if (self.videoRecord && _startRecord) {
- [self appendVideoBuffer:sampleBuffer];
- }
- }else if (connection == _audioConnection){
- [self appendAudioBuffer:sampleBuffer];
- }
- }
- }
- #pragma mark - 视频流出错,抛出异常
- - (void)videoError:(NSError *)error{
- if (self.videoDelegate && error) {
- [self.videoDelegate MGCaptureOutput:nil error:error];
- }
- }
- @end
|