视频采集
主要是通过< AVFoundation >框架进行采集
demo下载地址
-
采集画面,这里必须使用真机,模拟器不支持
-
1.创建会话
AVCaptureSession *captureSession = [[AVCaptureSession alloc] init]; captureSession.sessionPreset = AVCaptureSessionPreset1280x720; self.captureSession = captureSession;
-
2.设置视频的输入
// 2.1获取输入设备,摄像头,默认为后置 AVCaptureDevice *videoDevice = [self getVideoDevice:AVCaptureDevicePositionBack]; //2.2创建对应视频输入对象 AVCaptureDeviceInput *videoDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:nil]; //2.3添加到会话中 // 注意:最好要判断是否能添加输入,会话不能添加空的 if ([captureSession canAddInput:videoDeviceInput]) { [captureSession addInput:videoDeviceInput]; }
3.设置视频的输出
// 3.1获取视频输出设备
AVCaptureVideoDataOutput *videoOutput = [[AVCaptureVideoDataOutput alloc] init];
//默认为YES,接收器会立即丢弃接收到的帧,在代理里面,NO的时候,将允许在丢弃之前有更多时间处理旧帧
// [videoOutput setAlwaysDiscardsLateVideoFrames:NO];
// 3.2 设置输出代理,捕获视频样品数据
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
[videoOutput setSampleBufferDelegate:self queue:queue];
if ([captureSession canAddOutput:videoOutput]) {
[captureSession addOutput:videoOutput];
}
//3.3 设置视频输出方向
// 注意:设置方向,必须在videoOutput添加到captureSession之后,否则出错
AVCaptureConnection *connection = [videoOutput connectionWithMediaType:AVMediaTypeVideo];
if (connection.isVideoOrientationSupported) {
[connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
}
4. 添加视频预览层
AVCaptureVideoPreviewLayer *layer = [AVCaptureVideoPreviewLayer layerWithSession:captureSession];
self.preViewlayer = layer;
[layer setVideoGravity:AVLayerVideoGravityResizeAspect];
layer.frame = preview.bounds;
[preview.layer insertSublayer:layer atIndex:0];
5.开始采集
[captureSession startRunning];
- 获取摄像头方向
//指定摄像头方向,获取摄像头
- (AVCaptureDevice *)getVideoDevice:(AVCaptureDevicePosition)position{
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *device in devices) {
if (device.position == position) {
return device;
}
}
return nil;
}
- 切换摄像头
// 切换采集摄像头
- (void)switchScene:(UIView *)preview{
// 1.添加动画
CATransition *rotaionAnim = [[CATransition alloc] init];
rotaionAnim.type = @"oglFlip";
rotaionAnim.subtype = @"fromLeft";
rotaionAnim.duration = 0.5;
[preview.layer addAnimation:rotaionAnim forKey:nil];
// 2.获取当前镜头
AVCaptureDevicePosition position = self.videoDeviceInput.device.position == AVCaptureDevicePositionBack ? AVCaptureDevicePositionFront : AVCaptureDevicePositionBack;
// 3.创建新的input对象
AVCaptureDevice *newDevice = [self getVideoDevice:position];
AVCaptureDeviceInput *newDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:newDevice error:nil];
// 4.移除旧输入,添加新输入
[self.captureSession beginConfiguration];
[self.captureSession removeInput:self.videoDeviceInput];
[self.captureSession addInput:newDeviceInput];
// 此处要重新设置视频输出方向,默认会旋转90度
self.connection = [_videoOutput connectionWithMediaType:AVMediaTypeVideo];
if (_connection.isVideoOrientationSupported) {
[_connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
}
[self.captureSession commitConfiguration];
// 5.保存新输入
self.videoDeviceInput = newDeviceInput;
}
- 实现代理 -- AVCaptureVideoDataOutputSampleBufferDelegat
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{
NSLog(@"获取到一帧数据");
// 对获取到的数据进行编码,编码部分在下一篇继续讲
dispatch_sync(mEncodeQueue, ^{
[self.encoder encodeFrame:sampleBuffer];
});
}
- 停止采集
- (void)stopCapturing{
// 停止扫描
[self.captureSession stopRunning];
// 移除预览图层
[self.preViewlayer removeFromSuperlayer];
// 将对象置为nil
self.captureSession = nil;
}