美文网首页
AVFoundation音视频采集(一)

AVFoundation音视频采集(一)

作者: 枫紫_6174 | 来源:发表于2020-09-04 10:17 被阅读0次

    AVFoundation主要类介绍

    • 捕捉会话:AVCaptureSession

      • 是捕捉场景的中心枢纽
    • 捕捉设备:AVCaptureDevice

      1. 定义了很多方法,让开发者控制ios设备上的摄像头。可以独立调整和锁定摄像头的焦距、曝光、白平衡。对焦和曝光可以基于特定的兴趣点进行设置,使其在应用中实现点击对焦、点击曝光的功能。还可以让你控制设备的LED作为拍照的闪光灯或手电筒的使用
      2. 每当修改摄像头设备时,一定要先测试修改动作是否能被设备支持。并不是所有的摄像头都支持所有功能,例如牵制摄像头就不支持对焦操作,因为它和目标距离一般在一臂之长的距离。但大部分后置摄像头是可以支持全尺寸对焦。尝试应用一个不被支持的动作,会导致异常崩溃。所以修改摄像头设备前,需要判断是否支持
    • 捕捉设备输入:AVCaptureDeviceInput

      1. 包括前置摄像头/后置摄像头/麦克风等
    • 捕捉设备输出:AVCaptureOutput抽象类

      1. AVCaptureStillImageOutput 静态图片输出
      2. AVCaputureMovieFileOutput 录制文件输出
      3. AVCaputureAudioDataOutput音频输出
      4. AVCaputureVideoDataOutput视频输出
    • 捕捉链接: AVCaptureConnection

    • 捕捉预览: AVCaptureVideoPreviewLayer

    AVCaptureSession初始化

    • 简要文本说明
      1.初始化
      2.设置分辨率
      3. 配置输入设备(一定要转换为AVCaptureDeviceInput)
      4. 配置输入设备(音频视频)
      5. 配饰输出(静态图片输出,视频文件输出)

    在为session添加输入输出时,注意一定判断能否添加,因为摄像头并不属于任何一个APP,它属于公共设备,当另外一个APP占有该摄像头等输入输出设备时,直接添加会导致程序错误

    • 初始化流程
      AVCaptureSession初始化流程
    • 初始化代码
    - (BOOL)setupSession:(NSError **)error {
    
        
        //创建捕捉会话。AVCaptureSession 是捕捉场景的中心枢纽
        self.captureSession = [[AVCaptureSession alloc]init];
        
        /*
         AVCaptureSessionPresetHigh
         AVCaptureSessionPresetMedium
         AVCaptureSessionPresetLow
         AVCaptureSessionPreset640x480
         AVCaptureSessionPreset1280x720
         AVCaptureSessionPresetPhoto
         */
        //设置图像的分辨率
        self.captureSession.sessionPreset = AVCaptureSessionPresetHigh;
        
        //拿到默认视频捕捉设备 iOS系统返回后置摄像头
        AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        
        //将捕捉设备封装成AVCaptureDeviceInput
        //注意:为会话添加捕捉设备,必须将设备封装成AVCaptureDeviceInput对象
        AVCaptureDeviceInput *videoInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:error];
        
        //判断videoInput是否有效
        if (videoInput)
        {
            //canAddInput:测试是否能被添加到会话中
            if ([self.captureSession canAddInput:videoInput])
            {
                //将videoInput 添加到 captureSession中
                [self.captureSession addInput:videoInput];
                self.activeVideoInput = videoInput;
            }
        }else
        {
            return NO;
        }
        
        //选择默认音频捕捉设备 即返回一个内置麦克风
        AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
        
        //为这个设备创建一个捕捉设备输入
        AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:error];
       
        //判断audioInput是否有效
        if (audioInput) {
            
            //canAddInput:测试是否能被添加到会话中
            if ([self.captureSession canAddInput:audioInput])
            {
                //将audioInput 添加到 captureSession中
                [self.captureSession addInput:audioInput];
            }
        }else
        {
            return NO;
        }
    
        //AVCaptureStillImageOutput 实例 从摄像头捕捉静态图片
        self.imageOutput = [[AVCaptureStillImageOutput alloc]init];
        
        //配置字典:希望捕捉到JPEG格式的图片
        self.imageOutput.outputSettings = @{AVVideoCodecKey:AVVideoCodecJPEG};
        
        //输出连接 判断是否可用,可用则添加到输出连接中去
        if ([self.captureSession canAddOutput:self.imageOutput])
        {
            [self.captureSession addOutput:self.imageOutput];
            
        }
        
        
        //创建一个AVCaptureMovieFileOutput 实例,用于将Quick Time 电影录制到文件系统
        self.movieOutput = [[AVCaptureMovieFileOutput alloc]init];
        
        //输出连接 判断是否可用,可用则添加到输出连接中去
        if ([self.captureSession canAddOutput:self.movieOutput])
        {
            [self.captureSession addOutput:self.movieOutput];
        }
        
        
        self.videoQueue = dispatch_queue_create("cc.VideoQueue", NULL);
        
        return YES;
    }
    
    • 开始会话
    - (void)startSession {
    
        //检查是否处于运行状态
        if (![self.captureSession isRunning])
        {
            //使用同步调用会损耗一定的时间,则用异步的方式处理
            dispatch_async(self.videoQueue, ^{
                [self.captureSession startRunning];
            });
            
        }
    }
    
    • 结束会话
    - (void)stopSession {
        //检查是否处于运行状态
        if ([self.captureSession isRunning])
        {
            //使用异步方式,停止运行
            dispatch_async(self.videoQueue, ^{
                [self.captureSession stopRunning];
            });
        }
    }
    
    • 配置摄像头支持的方法
    - (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition)position {
        
        //获取可用视频设备
        NSArray *devicess = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
        
        //遍历可用的视频设备 并返回position 参数值
        for (AVCaptureDevice *device in devicess)
        {
            if (device.position == position) {
                return device;
            }
        }
        return nil;
        
    }
    
    - (AVCaptureDevice *)activeCamera {
    
        //返回当前捕捉会话对应的摄像头的device 属性
        return self.activeVideoInput.device;
    }
    
    //返回当前未激活的摄像头
    - (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;
        
    
    }
    
    //判断是否有超过1个摄像头可用
    - (BOOL)canSwitchCameras {
    
        
        return self.cameraCount > 1;
    }
    
    //可用视频捕捉设备的数量
    - (NSUInteger)cameraCount {
    
         return [[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo] count];
        
    }
    
    //切换摄像头
    - (BOOL)switchCameras {
    
        //判断是否有多个摄像头
        if (![self canSwitchCameras])
        {
            return NO;
        }
        
        //获取当前设备的反向设备
        NSError *error;
        AVCaptureDevice *videoDevice = [self inactiveCamera];
        
        
        //将输入设备封装成AVCaptureDeviceInput
        AVCaptureDeviceInput *videoInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error];
        
        //判断videoInput 是否为nil
        if (videoInput)
        {
            //标注原配置变化开始
            [self.captureSession beginConfiguration];
            
            //将捕捉会话中,原本的捕捉输入设备移除
            [self.captureSession removeInput:self.activeVideoInput];
            
            //判断新的设备是否能加入
            if ([self.captureSession canAddInput:videoInput])
            {
                //能加入成功,则将videoInput 作为新的视频捕捉设备
                [self.captureSession addInput:videoInput];
                
                //将获得设备 改为 videoInput
                self.activeVideoInput = videoInput;
            }else
            {
                //如果新设备,无法加入。则将原本的视频捕捉设备重新加入到捕捉会话中
                [self.captureSession addInput:self.activeVideoInput];
            }
            
            //配置完成后, AVCaptureSession commitConfiguration 会分批的将所有变更整合在一起。
            [self.captureSession commitConfiguration];
        }else
        {
            //创建AVCaptureDeviceInput 出现错误,则通知委托来处理该错误
            [self.delegate deviceConfigurationFailedWithError:error];
            return NO;
        }
        
        
        
        return YES;
    }
    
    /*
        AVCapture Device 定义了很多方法,让开发者控制ios设备上的摄像头。可以独立调整和锁定摄像头的焦距、曝光、白平衡。对焦和曝光可以基于特定的兴趣点进行设置,使其在应用中实现点击对焦、点击曝光的功能。
        还可以让你控制设备的LED作为拍照的闪光灯或手电筒的使用
        
        每当修改摄像头设备时,一定要先测试修改动作是否能被设备支持。并不是所有的摄像头都支持所有功能,例如牵制摄像头就不支持对焦操作,因为它和目标距离一般在一臂之长的距离。但大部分后置摄像头是可以支持全尺寸对焦。尝试应用一个不被支持的动作,会导致异常崩溃。所以修改摄像头设备前,需要判断是否支持
     
     
     */
    
    
    #pragma mark - Focus Methods 点击聚焦方法的实现
    
    - (BOOL)cameraSupportsTapToFocus {
        
        //询问激活中的摄像头是否支持兴趣点对焦
        return [[self activeCamera]isFocusPointOfInterestSupported];
    }
    
    - (void)focusAtPoint:(CGPoint)point {
        
        AVCaptureDevice *device = [self activeCamera];
        
        //是否支持兴趣点对焦 & 是否自动对焦模式
        if (device.isFocusPointOfInterestSupported && [device isFocusModeSupported:AVCaptureFocusModeAutoFocus]) {
            
            NSError *error;
            //锁定设备准备配置,如果获得了锁
            if ([device lockForConfiguration:&error]) {
                
                //将focusPointOfInterest属性设置CGPoint
                device.focusPointOfInterest = point;
                
                //focusMode 设置为AVCaptureFocusModeAutoFocus
                device.focusMode = AVCaptureFocusModeAutoFocus;
                
                //释放该锁定
                [device unlockForConfiguration];
            }else{
                //错误时,则返回给错误处理代理
                [self.delegate deviceConfigurationFailedWithError:error];
            }
            
        }
        
    }
    
    #pragma mark - Exposure Methods   点击曝光的方法实现
    
    - (BOOL)cameraSupportsTapToExpose {
        
        //询问设备是否支持对一个兴趣点进行曝光
        return [[self activeCamera] isExposurePointOfInterestSupported];
    }
    
    static const NSString *THCameraAdjustingExposureContext;
    
    - (void)exposeAtPoint:(CGPoint)point {
    
        
        AVCaptureDevice *device = [self activeCamera];
        
        AVCaptureExposureMode exposureMode =AVCaptureExposureModeContinuousAutoExposure;
        
        //判断是否支持 AVCaptureExposureModeContinuousAutoExposure 模式
        if (device.isExposurePointOfInterestSupported && [device isExposureModeSupported:exposureMode]) {
            
            [device isExposureModeSupported:exposureMode];
            
            NSError *error;
            
            //锁定设备准备配置
            if ([device lockForConfiguration:&error])
            {
                //配置期望值
                device.exposurePointOfInterest = point;
                device.exposureMode = exposureMode;
                
                //判断设备是否支持锁定曝光的模式。
                if ([device isExposureModeSupported:AVCaptureExposureModeLocked]) {
                    
                    //支持,则使用kvo确定设备的adjustingExposure属性的状态。
                    [device addObserver:self forKeyPath:@"adjustingExposure" options:NSKeyValueObservingOptionNew context:&THCameraAdjustingExposureContext];
                    
                }
                
                //释放该锁定
                [device unlockForConfiguration];
                
            }else
            {
                [self.delegate deviceConfigurationFailedWithError:error];
            }
            
            
        }
        
    }
    
    由于文章太长, 相关源代码会在接下来的文章中给出

    相关文章

      网友评论

          本文标题:AVFoundation音视频采集(一)

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