这是来自文档的引用(讨论canAddOutput:
)
您不能添加从用于初始化接收器的资产以外的资产轨道读取的输出。
对您有帮助的说明(请检查您的代码是否与本指南匹配,如果您做得很好,它不应该触发错误,因为基本上canAddOuput:
检查了兼容性)。
AVCaptureSession
用于组织 Device Input 和 output 之间的连接,类似于 DShow 过滤器的连接。如果可以连接输入和输出,启动后,数据将从输入读取到输出。几个要点:
a) AVCaptureDevice,定义设备,既是摄像头Device。
b) AVCaptureInput
c) AVCaptureOutput
输入和输出不是一对一的,比如视频输出而视频+音频输入。切换相机前后:
AVCaptureSession * session = <# A capture session #>;
[session beginConfiguration];
[session removeInput: frontFacingCameraDeviceInput];
[session addInput: backFacingCameraDeviceInput];
[session commitConfiguration];
添加捕获输入:
要将捕获设备添加到捕获会话,请使用 AVCaptureDeviceInput 的实例(抽象 AVCaptureInput 类的具体子类)。捕获设备输入管理设备的端口。
NSError * error = nil;
AVCaptureDeviceInput * input =
[AVCaptureDeviceInput deviceInputWithDevice: device error: & error];
if (input) {
// Handle the error appropriately.
}
添加输出,输出分类:
要从捕获会话中获取输出,请添加一个或多个输出。输出是 AVCaptureOutput 的具体子类的实例;您
使用:
AVCaptureMovieFileOutput输出到电影文件
_会话使用 addOutput:。
您使用 . 检查捕获输出是否与现有会话兼容。
您可以在会话运行时根据需要添加和删除输出。
canAddOutput:
AVCaptureSession * captureSession = <# Get a capture session #>;
AVCaptureMovieFileOutput * movieInput = <# Create and configure a movie output #>;
if ([captureSession canAddOutput: movieInput]) {
[captureSession addOutput: movieInput];
}
else {
// Handle the failure.
}
保存视频文件,添加视频文件输出:
您可以使用 AVCaptureMovieFileOutput 对象将电影数据保存到文件中。(AVCaptureMovieFileOutput 是 AVCaptureFileOutput 的具体子类,它定义了许多基本行为。)您可以配置电影文件输出的各个方面,例如录制的最长持续时间或最大文件大小。如果剩余的磁盘空间少于给定数量,您也可以禁止记录。
AVCaptureMovieFileOutput * aMovieFileOutput = [[AVCaptureMovieFileOutput alloc]
init];
CMTime maxDuration = <# Create a CMTime to represent the maximum duration #>;
aMovieFileOutput.maxRecordedDuration = maxDuration;
aMovieFileOutput.minFreeDiskSpaceLimit = <# An appropriate minimum given the quality
of the movie format and the duration #>;
处理预览视频帧数据,每一帧取景器数据可用于后续高级处理,如人脸检测等。
AVCaptureVideoDataOutput 对象使用委托来出售视频帧。您使用
setSampleBufferDelegate: queue:
.
除了委托之外,您还可以指定一个串行队列,在该队列上调用委托方法。您必须使用串行队列来确保帧以正确的顺序传递给委托人。
你不应该通过返回的队列dispatch_get_current_queue
因为不能保证当前队列在哪个线程上运行。您可以使用队列来修改传递和处理视频帧的优先级。对帧的数据处理,必须有大小(图像大小)和处理时间限制,如果处理时间过长,底层传感器将不会向布局器和回调发送数据。
您应该将会话输出设置为应用程序的最低实际分辨率。
将输出设置为比所需分辨率更高的分辨率会浪费处理周期并不必要地消耗功率。您必须确保您的 captureOutput: didOutputSampleBuffer: fromConnection: 实现能够在分配给帧的时间内处理样本缓冲区。如果花费的时间过长,并且您持有视频帧,则 AVFoundation 将停止传送帧,不仅是您的代理,还有其他输出,例如预览层。
处理抓包过程:
AVCaptureStillImageOutput * stillImageOutput = [[AVCaptureStillImageOutput alloc]
init];
NSDictionary * outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG,
AVVideoCodecKey, nil];
[StillImageOutput setOutputSettings: outputSettings];
能够支持不同的格式也支持直接生成jpg流。如果要捕获 JPEG 图像,通常不应指定自己的压缩格式。相反,您应该让静止图像输出为您进行压缩,因为它的压缩是硬件加速的。如果您需要图像的数据表示,可以使用 jpegStillImageNSDataRepresentation: 来获取 NSData 对象,而无需重新压缩数据,即使您修改了图像的元数据。
相机预览显示:
您可以使用 AVCaptureVideoPreviewLayer 对象为用户提供正在录制的内容的预览。AVCaptureVideoPreviewLayer 是 CALayer 的子类(请参阅核心动画编程指南。您不需要任何输出来显示预览。
AVCaptureSession * captureSession = <# Get a capture session #>;
CALayer * viewLayer = <# Get a layer from the view in which you want to present the
The preview #>;
AVCaptureVideoPreviewLayer * captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer
alloc] initWithSession: captureSession];
[viewLayer addSublayer: captureVideoPreviewLayer];
通常,预览层的行为类似于渲染树中的任何其他 CALayer 对象(请参阅核心动画编程指南)。您可以像处理任何图层一样缩放图像并执行变换、旋转等。一个区别是您可能需要设置图层的方向属性来指定它应该如何旋转来自相机的图像。此外,在 iPhone 4 上,预览层支持镜像(这是预览前置摄像头时的默认设置)。