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设备出错 的处理机制
}