摘要:本文将带你了解IOS开发入门最简单的iOS直播推流(三)使用系统接口捕获音视频数据,希望本文对大家学IOS有所帮助。
本文将带你了解IOS开发入门最简单的iOS直播推流(三)使用系统接口捕获音视频数据,希望本文对大家学IOS有所帮助。
最简单的iOS
推流代码,视频捕获,软编码(faac,x264),硬编码(aac,h264),美颜,flv编码,rtmp协议,陆续更新代码解析,你想学的知识这里都有,愿意懂直播技术的同学快来看!!
源代码:https://github.com/hardman/AWLive
通过系统相机录制视频获取音视频数据,是推流的第一步。
源码中提供2种获取音视频数据的方法:一是使用系统自带接口;二是使用GPUImage。
本篇首先介绍第一种。
网络上关于获取视频数据的代码有不少,但是为了方便代码阅读,这里简要介绍一下。
[注意]请仔细阅读代码注释
相关代码入口
整套推流代码的入口:AWAVCaptureManager,它是根据参数创建上述2种获取数据方法的一个工厂类。
可以通过设置 captureType 来决定使用哪种数据获取方式。
AWAVCaptureManager部分代码如下:
typedef enum : NSUInteger
{ AWAVCaptureTypeNone, AWAVCaptureTypeSystem, AWAVCaptureTypeGPUImage,}
AWAVCaptureType; @interface AWAVCaptureManager :
NSObject//视频捕获类型@property (nonatomic, unsafe_unretained) AWAVCaptureType
captureType;@property (nonatomic, weak) AWAVCapture
*avCapture; //省略其他代码......@end
设置了captureType之后,直接可以通过avCapture获取到正确的捕获视频数据的对象了。
AWAVCapture 是一个虚基类(c++中的说法,不会直接产生对象,只用来继承的类,java中叫做抽象类)。
它的两个子类分别是 AWSystemAVCapture 和 AWGPUImageAVCapture。
这里使用了多态。
如果 captureType设置的是 AWAVCaptureTypeSystem,avCapture获取到的真实对象就是
AWSystemAVCapture类型;
如果 captureType设置的是 AWAVCaptureTypeGPUImage,avCapture获取到的真实对象就是
AWGPUImageAVCapture类型。
AWSystemAVCapture类的功能只有一个:调用系统相机,获取音视频数据。
相机数据获取的方法
分为3步骤:
1. 初始化输入输出设备。
2. 创建AVCaptureSession,用来管理视频与数据的捕获。
3. 创建预览UI。
还包括一些其他功能:
1. 切换摄像头
2. 更改fps
在代码中对应的是 AWSystemAVCapture中的 onInit方法。只要初始化就会调用。
【注意】请仔细阅读下文代码中的注释
初始化输入设备
-(void)
createCaptureDevice{ //
初始化前后摄像头 //
执行这几句代码后,系统会弹框提示:应用想要访问您的相机。请点击同意 // 另外iOS10
需要在info.plist中添加字段NSCameraUsageDescription。否则会闪退,具体请自行baidu。 NSArray
*videoDevices = [AVCaptureDevice
devicesWithMediaType:AVMediaTypeVideo]; self.frontCamera
= [AVCaptureDeviceInput deviceInputWithDevice:videoDevices.firstObject
error:nil]; self.backCamera =[AVCaptureDeviceInput
deviceInputWithDevice:videoDevices.lastObject
error:nil]; // 初始化麦克风 //
执行这几句代码后,系统会弹框提示:应用想要访问您的麦克风。请点击同意 // 另外iOS10
需要在info.plist中添加字段NSMicrophoneUsageDescription。否则会闪退,具体请自行baidu。 AVCaptureDevice
*audioDevice = [AVCaptureDevice
defaultDeviceWithMediaType:AVMediaTypeAudio]; self.audioInputDevice
= [AVCaptureDeviceInput deviceInputWithDevice:audioDevice
error:nil]; //省略其他代码 ...}
初始化输出设备
-(void) createOutput{
//创建数据获取线程 dispatch_queue_t
captureQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
0); //视频数据输出 self.videoDataOutput
= [[AVCaptureVideoDataOutput alloc] init]; //设置代理,需要当前类实现protocol:AVCaptureVideoDataOutputSampleBufferDelegate [self.videoDataOutput
setSampleBufferDelegate:self
queue:captureQueue]; //抛弃过期帧,保证实时性 [self.videoDataOutput
setAlwaysDiscardsLateVideoFrames:YES]; //设置输出格式为
yuv420 [self.videoDataOutput
setVideoSettings:@{ (__bridge
NSString
*)kCVPixelBufferPixelFormatTypeKey:@(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange) }]; //音频数据输出 self.audioDataOutput
= [[AVCaptureAudioDataOutput alloc]
init]; //设置代理,需要当前类实现protocol:AVCaptureAudioDataOutputSampleBufferDelegate [self.audioDataOutput
setSampleBufferDelegate:self
queue:captureQueue]; //
AVCaptureVideoDataOutputSampleBufferDelegate 和
AVCaptureAudioDataOutputSampleBufferDelegate
回调方法名相同都是: // captureOutput:(AVCaptureOutput
*)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
fromConnection:(AVCaptureConnection *)connection //
最终视频和音频数据都可以在此方法中获取。}
创建 captureSession
//
AVCaptureSession
创建逻辑很简单,它像是一个中介者,从音视频输入设备获取数据,处理后,传递给输出设备(数据代理/预览layer)。-(void)
createCaptureSession{ //初始化 self.captureSession
= [AVCaptureSession
new]; //修改配置 [self.captureSession
beginConfiguration]; //加入视频输入设备 if
([self.captureSession canAddInput:self.videoInputDevice]) { [self.captureSession
addInput:self.videoInputDevice]; } //加入音频输入设备 if
([self.captureSession canAddInput:self.audioInputDevice]) { [self.captureSession
addInput:self.audioInputDevice]; } //加入视频输出 if([self.captureSession
canAddOutput:self.videoDataOutput]){ [self.captureSession
addOutput:self.videoDataOutput]; [self
setVideoOutConfig]; } //加入音频输出 if([self.captureSession
canAddOutput:self.audioDataOutput]){ [self.captureSession
addOutput:self.audioDataOutput]; } //设置预览分辨率 //这个分辨率有一个值得注意的点: //iphone4录制视频时
前置摄像头只能支持 480*640 后置摄像头不支持 540*960 但是支持
720*1280 //诸如此类的限制,所以需要写一些对分辨率进行管理的代码。 //目前的处理是,对于不支持的分辨率会抛出一个异常 //但是这样做是不够、不完整的,最好的方案是,根据设备,提供不同的分辨率。 //如果必须要用一个不支持的分辨率,那么需要根据需求对数据和预览进行裁剪,缩放。 if
(![self.captureSession canSetSessionPreset:self.captureSessionPreset])
{ @throw [NSException
exceptionWithName:@"Not supported captureSessionPreset"
reason:[NSString stringWithFormat:@"captureSessionPreset is [%@]",
self.captureSessionPreset]
userInfo:nil]; } self.captureSession.sessionPreset
=
self.captureSessionPreset; //提交配置变更 [self.captureSession
commitConfiguration]; //开始运行,此时,CaptureSession将从输入设备获取数据,处理后,传递给输出设备。 [self.captureSession
startRunning];}
创建预览UI
?123456789// 其实只有一句代码:CALayer layer = [AVCaptureVideoPreviewLayer
layerWithSession:self.captureSession];// 它其实是 AVCaptureSession的一个输出方式而已。//
CaptureSession会将从input设备得到的数据,处理后,显示到此layer上。// 我们可以将此layer变换后加入到任意UIView中。-(void)
createPreviewLayer{ self.previewLayer =
[AVCaptureVideoPreviewLayer
layerWithSession:self.captureSession]; self.previewLayer.frame
= self.preview.bounds; [self.preview.layer addSublayer:self.previewLayer];}
切换摄像头
-(void)setVideoInputDevice:(AVCaptureDeviceInput
*)videoInputDevice{ if ([videoInputDevice
isEqual:_videoInputDevice]) { return; } //captureSession
修改配置 [self.captureSession
beginConfiguration]; //移除当前输入设备 if
(_videoInputDevice) { [self.captureSession
removeInput:_videoInputDevice]; } //增加新的输入设备 if
(videoInputDevice)
{ [self.captureSession
addInput:videoInputDevice]; } //提交配置,至此前后摄像头切换完毕 [self.captureSession
commitConfiguration]; _videoInputDevice =
videoInputDevice;}
设置fps
-(void) updateFps:(NSInteger)
fps{ //获取当前capture设备 NSArray
*videoDevices = [AVCaptureDevice
devicesWithMediaType:AVMediaTypeVideo]; //遍历所有设备(前后摄像头) for
(AVCaptureDevice *vDevice in videoDevices)
{ //获取当前支持的最大fps float
maxRate = [(AVFrameRateRange *)[vDevice.activeFormat.videoSupportedFrameRateRanges
objectAtIndex:0]
maxFrameRate]; //如果想要设置的fps小于或等于做大fps,就进行修改 if
(maxRate >= fps) { //实际修改fps的代码 if
([vDevice lockForConfiguration:NULL])
{ vDevice.activeVideoMinFrameDuration
= CMTimeMake(10, (int)(fps *
10)); vDevice.activeVideoMaxFrameDuration
= vDevice.activeVideoMinFrameDuration; [vDevice
unlockForConfiguration]; } } }}
至此,我们达到了所有目标:能够录制视频,预览,获取音视频数据,切换前后摄像头,修改捕获视频的fps。
本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之IOS频道!
您输入的评论内容中包含违禁敏感词
我知道了
请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号