14

canAddOutput:用来确定是否可以将 a 添加AVCaptureMovieFileOutput到 a 中AVCaptureSession,但我发现它canAddOutput:有时会返回 NO,并且大多返回 YES。有没有办法找出返回 NO 的原因?或者一种消除导致 NO 被退回的情况的方法?或者我能做的任何其他事情都会阻止用户看到间歇性故障?

一些进一步的说明:这大约在 30 次通话中发生一次。由于我的应用程序没有启动,它只在一台设备上进行了测试:运行 7.1.2 的 iPhone 5

4

5 回答 5

15

这是来自文档的引用(讨论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 上,预览层支持镜像(这是预览前置摄像头时的默认设置)。

于 2014-07-10T11:40:01.757 回答
2

参考这个答案这个委托方法可能会在后台运行,这可能会导致以前没有正确断开连接,有时会AVCaptureSession导致有时。canAddOutput:NO

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection

解决方案可能是stopRunning在上述委托中使用(当然,在进行必要的操作和条件检查之后,您需要正确完成之前的会话,对吧?)。

除此之外,如果您提供一些您正在尝试做的事情的代码会更好。

于 2014-07-07T05:53:12.673 回答
1

它可以是这 2 种情况中的一种
1)会话正在运行
2)您已经添加了输出
您不能添加 2 个输出或 2 个输入,也不能创建 2 个不同的会话

于 2014-07-10T16:26:20.927 回答
0

它可能是以下组合:

  • 相机忙时调用此方法。
  • 未正确删除您以前连接的AVCaptureSession.

您应该尝试只添加一次(我猜canAddOutput:将永远是YES)并根据需要暂停/恢复您的会话:

// Stop session if possible
if (_captureSession.running && !_captureInProgress)
{
    [_captureSession stopRunning];
    NBULogVerbose(@"Capture session: {\n%@} stopped running", _captureSession);
}

你可以看看这里

于 2014-07-07T02:17:16.780 回答
0

我认为这将帮助您 canAddOutput:返回一个布尔值,指示是否可以将给定的输出添加到会话中。

- (BOOL)canAddOutput:(AVCaptureOutput *)output

参数 output 要添加到会话的输出。返回值 如果可以将输出添加到会话中,则返回 YES,否则返回 NO。

可用性 适用于 OS X v10.7 及更高版本。

这是苹果文档的链接点击这里

于 2014-07-10T11:05:33.440 回答