美文网首页AVCaptureDevice
iOS音视频三: AVCaptureSession视频捕捉会话

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

作者: 司空123 | 来源:发表于2019-05-15 22:19 被阅读0次

    一 、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;
    }
    

    相关文章

      网友评论

        本文标题:iOS音视频三: AVCaptureSession视频捕捉会话

        本文链接:https://www.haomeiwen.com/subject/bkrraqtx.html