AVFoundation 初步探索

1,561 阅读3分钟

AVFoundation 学习之初始

在目前iOS的技术栈里面,视频流一直是比较主流的一个学习方向,今天,在这写上一些上周在AVFoundation框架下,所学所讲的。

我们在理解AVFoundation 这个框架的时候,要学会 Apple 对这个框架有什么作用:

照片/视频的捕捉 小视频/直播

捕捉会话

  • AVCaptureSession 设备捕捉会话

  • AVCaptureDevice 捕捉设备

  • AVCaptureDeviceInput 捕捉设备输入

  • AVCaptureFileOutput (一个抽象类) 多类型音频文件

    • AVCaptureStillImageOutput 静态图片输出
    • AVCaptureFileOutput 文件输出
    • AVCaptureMovieFileOutput 静态视频文件输出
    • AVCaptureAudioFileOutput 音频文件输出
    • AVCaptureVideoDataOutput 视频文件输出
  • 捕捉连接 AVCaptureConnection 建立输入输出的连接

  • AVCaptureVideoPreviewLayer 渲染捕捉涂层 预览内容

摄像头坐标 && 手机坐标 相互转换

  • captureDevicePointOfInterestForPoint 获取到屏幕的坐标系的point 转换成物理设备的坐标数据
  • PointForCaptureDevicePointOfInterest 获取到物理设备坐标系 转化为手机屏幕的坐标

##干货 直接上代码 写注释

   //初始化 AVCaptureSession 对象
    self.captureSession = [[AVCaptureSession alloc] init];
    //设置高分辨率  其他参数 请查看 sessionPreset 内的设置
    self.captureSession.sessionPreset = AVCaptureSessionPresetHigh;
    
    // 获取到设备    MediaType 代表的是获取设备的哪种类型
    AVCaptureDevice * videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    
    //输入设备 将设备转化为   AVCaptureDeviceInput
    AVCaptureDeviceInput * videoDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:nil];
    
    if (videoDevice) {
        //判断是否有效
        if ([self.captureSession canAddInput:videoDeviceInput]) {
            [self.captureSession addInput:videoDeviceInput];
        }
    }
    
    
    // 获取设备的音频输出处理装置
    AVCaptureDevice * audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
    AVCaptureDeviceInput * audiodeViceInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:nil];
    
    if (audiodeViceInput) {
        if ([self.captureSession canAddInput:audiodeViceInput]) {
            [self.captureSession addInput:audiodeViceInput];
        }
    }
    
    //静态图片输出对象的初始化
    self.imageOutput = [[AVCaptureStillImageOutput alloc]init];
    //设置 视屏的格式 JPEG
    self.imageOutput.outputSettings = @{AVVideoCodecKey:AVVideoCodecTypeJPEG};
    if ([self.captureSession canAddOutput:self.imageOutput]) {
        [self.captureSession canAddOutput:self.imageOutput];
    }
    
    //创建一个文件
    self.movieOutPut = [[AVCaptureMovieFileOutput alloc] init];
    if ([self.captureSession canAddOutput:self.movieOutPut]) {
        [self.captureSession addOutput:self.movieOutPut];
    }
    
    self.videoQuect = dispatch_queue_create("jz.videoqueue", NULL);
    

session

作为捕捉音视频的连接者,我们能对视频的状态做出处理 以及切换

例如:


self.captureSession isRunning  //  判断的就是当前的session 是否是在运行中

个人建议同步调用会损耗一定的时间,则用异步的方式处理

   dispatch_async(self.videoQueue, ^{
            [self.captureSession stopRunning];
        });
 // 同道理  开始的时候 可检测
 
  if (![self.captureSession isRunning])
    {
        dispatch_async(self.videoQueue, ^{
            [self.captureSession startRunning];
        });
        
    }       

前后摄像头的切换

// 判断设备 是否拥有物理设备
<!--    NSArray * devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    获取当前设备的数组设备 然后进行判断
      for (AVCaptureDevice *device in devices)
    {
        if (device.position == position) {
            return device;  //获取到我当前的 position  然后返回设备
        }
    }
-->

// 判断设备 当前的物理设备数
//获取当前视频捕捉设备的数量
NSInteger deviceCount =  [[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo] count];

// 获取当前的活跃设备 
self.videoDeviceInput.device  
  
// 获取当前前后置摄像头的处理
       AVCaptureDevice *device = nil;
       if(deviceCount > 1)
       {
          //返回获取到逆向切换的物理设备
           if (self.videoDeviceInput.device.position == AVCaptureDevicePositionBack)
           {
              //AVCaptureDevicePositionFront 后置摄像头
           }
           else
           {
             //AVCaptureDevicePositionBack  前置摄像头
           }
       }

// 生成当前的输入源   videoDevice 是你当前的切换的设备信息
  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
    {
        //创建input设备出错 的处理机制
    }