`[AVCaptureSession canAddOutput:output]`间歇性地返回NO。我能找出原因吗?

时间:2014-07-01 02:14:47

标签: ios objective-c avcapturesession avcapturemoviefileoutput

我正在使用canAddOutput:确定我是否可以向AVCaptureMovieFileOutput添加AVCaptureSession,并且我发现canAddOutput:有时会返回NO,并且大部分都返回YES 。有没有办法找出NO被归还的原因?或者一种消除导致NO返回的情况的方法?或者我能做的任何事情都会阻止用户看到间歇性故障?

进一步说明:这种情况大约发生在30次通话中。由于我的应用程序尚未启动,因此仅在一台设备上进行了测试:运行7.1.2的iPhone 5

5 个答案:

答案 0 :(得分:13)

以下是文档引用(canAddOutput:)的讨论

You cannot add an output that reads from a track of an asset other than the asset used to initialize the receiver.

对您有帮助的说明(请检查您的代码是否与本指南匹配,如果您做得不好,则不应触发错误,因为基本上canAddOuput:会检查兼容性)。

<强> AVCaptureSession
用于组织设备输入和输出之间的连接,类似于DShow过滤器的连接。如果可以连接输入和输出,则在启动后,数据将从输入读取到输出。 几个要点:
a)AVCaptureDevice,设备的定义,两个摄像头设备 b)AVCaptureInput
c)AVCaptureOutput
输入和输出不是一对一的,例如视频+音频输入时的视频输出。 切换相机前后:

AVCaptureSession * session = <# A capture session #>; 
[session beginConfiguration]; 
[session removeInput: frontFacingCameraDeviceInput]; 
[session addInput: backFacingCameraDeviceInput]; 
[session commitConfiguration];

添加捕获INPUT:
要将捕获设备添加到捕获会话,请使用AVCaptureDeviceInput的实例(具体的 抽象AVCaptureInput类的子类)。捕获设备输入管理设备的端口。

NSError * error = nil; 
AVCaptureDeviceInput * input = 
[AVCaptureDeviceInput deviceInputWithDevice: device error: & error]; 
if (input) { 
   // Handle the error appropriately. 
}

添加输出,输出分类:

要从捕获会话获取输出,请添加一个或多个输出。输出是具体的实例 AVCaptureOutput的子类;
你用:
AVCaptureMovieFileOutput 输出到电影文件
AVCaptureVideoDataOutput 如果您想处理正在捕获的视频中的帧 AVCaptureAudioDataOutput 如果您想处理正在捕获的音频数据 AVCaptureStillImageOutput 如果您想捕获带有元数据的静止图像 您可以使用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:to 即使您修改了图像的元数据,也可以在不重新压缩数据的情况下获取NSData对象。

相机预览显示:

您可以使用AVCaptureVideoPreviewLayer为用户提供正在录制内容的预览 宾语。 AVCaptureVideoPreviewLayer是CALayer的子类(参见Core Animation Programming Guide。你不需要任何输出来显示预览。

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上,预览层支持镜像 (这是预览前置摄像头时的默认设置。)

答案 1 :(得分:2)

this answer引用,可能会在后台运行this delegate method,这会导致之前的AVCaptureSession未正确断开,有时会导致canAddOutput:有时是NO

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

解决方案可能是在上面的委托中使用stopRunning(当然,在做了必要的操作和条件检查之后,你需要正确完成以前的会话吗?)。

除此之外,如果你提供一些你想要做的代码会更好。

答案 2 :(得分:1)

这可能是这2例中的一个 1)会话正在运行中 2)您已添加输出
   您无法添加2个输出或2个输入,也无法创建2个不同的会话

答案 3 :(得分:0)

它可能是:

的组合
  • 相机占线时调用此方法。
  • 未正确删除之前连接的AVCaptureSession

您应该尝试只添加一次(我猜canAddOutput:始终为YES),然后根据需要暂停/恢复您的会话:

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

你可以看看here

答案 4 :(得分:0)

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

- (BOOL)canAddOutput:(AVCaptureOutput *)output

参数 产量 要添加到会话的输出。 回报价值 如果可以将输出添加到会话中,则为YES,否则为NO。

状况 适用于OS X v10.7及更高版本。

以下是apple doc Click here

的链接