AVCaptureDevice

iOS音视频三: AVCaptureSession视频捕捉会话

2019-05-15  本文已影响0人  司空123

一 、AVCaptureSession 基础配置:

// 1. 创建捕捉会话。AVCaptureSession
    self.captureSession = [[AVCaptureSession alloc]init];
    // 2. 设置分辨率
    /*
     AVCaptureSessionPresetHigh
     AVCaptureSessionPresetMedium
     AVCaptureSessionPresetLow
     AVCaptureSessionPreset640x480
     AVCaptureSessionPreset1280x720
     AVCaptureSessionPresetPhoto
     */
    
    AVCaptureSessionPreset SessionPreset = AVCaptureSessionPresetPhoto;
    if ([self.captureSession canSetSessionPreset:SessionPreset]) {
        self.captureSession.sessionPreset = SessionPreset;
    }
    // 3. 输入源
    int frameRate;
    CMTime frameDuration = kCMTimeInvalid;
    AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
      NSError *error;
    if ([captureDevice lockForConfiguration:&error]) {
        
        frameRate = 30;
        frameDuration = CMTimeMake( 1, frameRate );
        
        captureDevice.activeVideoMaxFrameDuration = frameDuration;
        captureDevice.activeVideoMinFrameDuration = frameDuration;
        [captureDevice unlockForConfiguration];
    }
    
    AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
    // 4. 输出源
   AVCaptureStillImageOutput *imageOutput = [[AVCaptureStillImageOutput alloc]init];
    imageOutput.outputSettings = @{AVVideoCodecKey:AVVideoCodecJPEG};
    // 5. 开始添加输入输出
    [self.captureSession beginConfiguration];
    
    if (deviceInput && [self.captureSession canAddInput:deviceInput]) {
        [self.captureSession addInput:deviceInput];
        self.activeVideoInput = deviceInput;
    }
    if ([self.captureSession canAddOutput:self.imageOutput]) {
        [self.captureSession addOutput:self.imageOutput];
    }
    [self.captureSession commitConfiguration];

二 、AVCaptureSession 启动与停止:

// 启动session
- (void)startSession {
    
    if (![self.captureSession isRunning])
    {
        dispatch_async(self.videoQueue, ^{
            [self.captureSession startRunning];
        });
    }
}

// 停止session
- (void)stopSession {
    
    if ([self.captureSession isRunning])
    {
        dispatch_async(self.videoQueue, ^{
            [self.captureSession stopRunning];
        });
    }
}

三 、AVCaptureDevice(捕捉设备)相关操作:对焦 白平衡 曝光 HDR 镜头位置 感光度 等

// 当前活跃设备
- (AVCaptureDevice *)activeCamera { 
    return self.activeVideoInput.device;
}
// 聚焦
- (void)focusAtPoint:(CGPoint)point {
    
    AVCaptureDevice *device = [self activeCamera];
    if ([device isFocusPointOfInterestSupported] && [device isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) {
        NSError *error;
        if ([device lockForConfiguration:&error]) {
            device.focusPointOfInterest = point;
            device.focusMode = AVCaptureFocusModeContinuousAutoFocus;
            [device unlockForConfiguration];
        }
    }
}
//  对兴趣点进行曝光
- (void)exposeAtPoint:(CGPoint)point {

    AVCaptureDevice *device = [self activeCamera];
    AVCaptureExposureMode exposureMode =AVCaptureExposureModeContinuousAutoExposure;
    if ([device isFocusPointOfInterestSupported] && [device isExposureModeSupported:exposureMode]) {
        NSError *error;
        if ([device lockForConfiguration:&error]) {
            
            device.exposurePointOfInterest = point;
            device.exposureMode = exposureMode;
            [device unlockForConfiguration];
        }
    }
}
// 手动曝光调节
- (void)setExposureWithNewValue:(CGFloat)newExposureValue{

    NSError *error;
    AVCaptureDevice *device = [self activeCamera];
    if ([device lockForConfiguration:&error]) {
        [device setExposureTargetBias:newExposureValue completionHandler:nil];
        [device unlockForConfiguration];
    }
}

// 设置平滑对焦
- (void)setSmoothFocus:(BOOL)smoothFocusEnabled{

    NSError *error;
    AVCaptureDevice *captureDevice = [self activeCamera];
    if ([captureDevice lockForConfiguration:&error]) {
        [captureDevice setSmoothAutoFocusEnabled:smoothFocusEnabled];
        [captureDevice unlockForConfiguration];
    }
}
// 白平衡
- (void)setWhiteBalanceMode:(AVCaptureWhiteBalanceMode)whiteBalanceMode{

    AVCaptureDevice *device = [self activeCamera];
    if ([device isWhiteBalanceModeSupported:whiteBalanceMode]) {
        
        NSError *error;
        if ([device lockForConfiguration:&error]) {
            device.whiteBalanceMode = whiteBalanceMode;
            [device unlockForConfiguration];
        }
    }
}
/**
 自定义白平衡模式

 temperature: 通过华氏温度调节 (-150-~250)
 tint: 通过色调调节 (-150-~150)
 */
-(AVCaptureWhiteBalanceGains)clampGains:(AVCaptureWhiteBalanceGains)gains toMinVal:(CGFloat)minVal andMaxVal:(CGFloat)maxVal {
    
    AVCaptureWhiteBalanceGains tmpGains = gains;
    tmpGains.blueGain   = MAX(MIN(tmpGains.blueGain , maxVal), minVal);
    tmpGains.redGain    = MAX(MIN(tmpGains.redGain  , maxVal), minVal);
    tmpGains.greenGain  = MAX(MIN(tmpGains.greenGain, maxVal), minVal);
    
    return tmpGains;
}
-(void)setWhiteBlanceValueByTemperature:(CGFloat)temperature device:(AVCaptureDevice *)device {
    
    if ([device isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeLocked]) {
        
        [device lockForConfiguration:nil];
        
        // 白平衡增益
        AVCaptureWhiteBalanceGains currentGains = device.deviceWhiteBalanceGains;
        CGFloat currentTint = [device temperatureAndTintValuesForDeviceWhiteBalanceGains:currentGains].tint;
        AVCaptureWhiteBalanceTemperatureAndTintValues tempAndTintValues = {
            .temperature = temperature,
            .tint        = currentTint,
        };
        
        AVCaptureWhiteBalanceGains deviceGains = [device deviceWhiteBalanceGainsForTemperatureAndTintValues:tempAndTintValues];
        CGFloat maxWhiteBalanceGain = device.maxWhiteBalanceGain;
        deviceGains = [self clampGains:deviceGains toMinVal:1 andMaxVal:maxWhiteBalanceGain];
        
        [device setWhiteBalanceModeLockedWithDeviceWhiteBalanceGains:deviceGains completionHandler:nil];
        [device unlockForConfiguration];
    }
}

-(void)setWhiteBlanceValueByTint:(CGFloat)tint device:(AVCaptureDevice *)device {
    
    if ([device isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeLocked]) {
        [device lockForConfiguration:nil];
        CGFloat maxWhiteBalaceGain = device.maxWhiteBalanceGain;
        AVCaptureWhiteBalanceGains currentGains = device.deviceWhiteBalanceGains;
        currentGains = [self clampGains:currentGains toMinVal:1 andMaxVal:maxWhiteBalaceGain];
        CGFloat currentTemperature = [device temperatureAndTintValuesForDeviceWhiteBalanceGains:currentGains].temperature;
        AVCaptureWhiteBalanceTemperatureAndTintValues tempAndTintValues = {
            .temperature = currentTemperature,
            .tint        = tint,
        };
        
        AVCaptureWhiteBalanceGains deviceGains = [device deviceWhiteBalanceGainsForTemperatureAndTintValues:tempAndTintValues];
        deviceGains = [self clampGains:deviceGains toMinVal:1 andMaxVal:maxWhiteBalaceGain];
        
        [device setWhiteBalanceModeLockedWithDeviceWhiteBalanceGains:deviceGains completionHandler:nil];
        [device unlockForConfiguration];
    }
}
// 调节镜头的位置
- (void)setLensPosition:(float)lensPosition{

    AVCaptureDevice *captureDevice = [self activeCamera];
    NSError *error;
    if ([captureDevice lockForConfiguration:&error]) {
        [captureDevice setFocusModeLockedWithLensPosition:lensPosition completionHandler:^(CMTime syncTime) {
        }];
        [captureDevice unlockForConfiguration];
    }
}
/*
 调解自定义曝光时长 感光度
 */

- (void)setExposureModeWithDuration:(CMTime)duration ISO:(float)ISO completionHandler:(void(^)(CMTime syncTime))handler{
    
    AVCaptureDevice *captureDevice = [self activeCamera];
    NSError *error;
    if ([captureDevice lockForConfiguration:&error]) {
        [captureDevice setExposureModeCustomWithDuration:duration ISO:ISO completionHandler:^(CMTime syncTime) {
            
        }];
        [captureDevice unlockForConfiguration];
    }
}

四 、硬件相关操作:

// 获取指定位置摄像头 (前置摄像头 & 后置摄像头)
- (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition)position {
    
    NSArray *deviceArray = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    for (AVCaptureDevice *device in deviceArray)
    {
        if (device.position == position) {
            return device;
        }
    }
    return nil;
}
//设置手电筒模式
- (void)setTorchMode:(AVCaptureTorchMode)torchMode {
    /*
     AVCaptureTorchModeOff  = 0,
     AVCaptureTorchModeOn   = 1,
     AVCaptureTorchModeAuto = 2,
     */
    AVCaptureDevice *device = [self activeCamera];    
    if ([device isTorchModeSupported:torchMode]) {
        
        NSError *error;
        if ([device lockForConfiguration:&error]) {
            device.torchMode = torchMode;
            [device unlockForConfiguration];
        }
    }
}
//设置闪光灯
- (void)setFlashMode:(AVCaptureFlashMode)flashMode {
    
    //获取当前设备
    AVCaptureDevice *device = [self activeCamera];
    
    //判断是否支持闪光灯模式
    if ([device isFlashModeSupported:flashMode]) {
        
        //如果支持,则锁定设备
        NSError *error;
        if ([device lockForConfiguration:&error]) {
            
            /*
             AVCaptureFlashModeOff  = 0,
             AVCaptureFlashModeOn   = 1,
             AVCaptureFlashModeAuto = 2,
             */
            
            device.flashMode = flashMode;
            [device unlockForConfiguration];
            
        }
    }
}
// 切换摄像头,返回操作结果
- (BOOL)switchCameras{
    
    if (![self canSwitchCameras]) {
        return NO;
    }
    // 获取反向摄像头
    AVCaptureDevice *videoDevice = [self inactiveCamera];
    NSError *error;
    AVCaptureDeviceInput *videoInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error];
    if (videoInput)
    {
        [self.captureSession beginConfiguration];
        [self.captureSession removeInput:self.activeVideoInput];
        
        if ([self.captureSession canAddInput:videoInput])
        {
            [self.captureSession addInput:videoInput];
            self.activeVideoInput = videoInput;
            
        }else{
            [self.captureSession addInput:self.activeVideoInput];
            
        }
        [self.captureSession commitConfiguration];
    }else
    {
        return NO;
    }
    
    return YES;
}
//判断是否允许切换摄像头
- (BOOL)canSwitchCameras {
    
    return self.cameraCount > 1;
}
//获取反向摄像头
- (AVCaptureDevice *)inactiveCamera {
    
    //通过查找当前激活摄像头的反向摄像头获得,如果设备只有1个摄像头,则返回nil
    AVCaptureDevice *device = nil;
    if (self.cameraCount > 1)
    {
        if ([self activeCamera].position == AVCaptureDevicePositionBack) {
            device = [self cameraWithPosition:AVCaptureDevicePositionFront];
        }else
        {
            device = [self cameraWithPosition:AVCaptureDevicePositionBack];
        }
    }
    
    return device;
}
上一篇下一篇

猜你喜欢

热点阅读