当样本缓冲区为非null时,为什么jpegStillImageNSDataRepresentation会抛出异常?

时间:2012-09-10 16:28:10

标签: ios avcapture

在iOS中,我使用代码从AVCaptureStillImageOutput中捕获:

[_ captureStillOutput captureStillImageAsynchronouslyFromConnection:_captureConnection                                                              completionHandler:asyncCaptureCompletionHandler];

为简单起见我的代码,我的asyncCaptureCompletionHandler块看起来像这样:

void(^asyncCaptureCompletionHandler)(CMSampleBufferRef imageDataSampleBuffer, NSError *error) = 
^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
    if (CMSampleBufferIsValid(imageDataSampleBuffer)) {
        NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
        UIImage *image = [[UIImage alloc] initWithData:imageData];                                                                 
    }
}

我已经浏览了所有代码并使用堆栈溢出交叉引用,并且没有找到任何建议为什么在没有正确的JPEG的情况下捕获有效的样本缓冲区。

_captureStillOutput = [[AVCaptureStillImageOutput alloc] init];
_captureStillOutput.outputSettings = 
        [NSDictionary dictionaryWithObjectsAndKeys:
         AVVideoCodecJPEG, AVVideoCodecKey,
         nil];

if ([session canAddOutput:_captureStillOutput]) {
            [session addOutput:_captureStillOutput];
}

调试器中有补充信息: *由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:'* + [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:] - 不是jpeg样本缓冲区。'

搜索谷歌和堆栈溢出“Not a jpeg sample buffer”产生零结果。我被卡住了。呸。

2 个答案:

答案 0 :(得分:2)

这个问题很老但是黄金。我来自未来,可以确认这仍然发生在2015年。我试图通过相同的步骤来解决问题,但无济于事。但是,这个问题让我意识到CMSampleBufferRef imageDataSampleBuffercaptureStillImageAsynchronouslyFromConnection的完成处理程序之外被处理时表现得很奇怪。

简而言之:

[self.stillImageOutput captureStillImageAsynchronouslyFromConnection:connection
                                                       completionHandler:^( CMSampleBufferRef imageDataSampleBuffer, NSError *error )
    {
        //call another method to handle the sample buffer causes weird behaviour
        //maybe the buffer is not being safely referenced by AVFoundation?
        [self handleBufferSomewhereElse:imageDataSampleBuffer]; //will behave strangely
        //even more so if you move to another thread
    }];

更喜欢这样做

[self.stillImageOutput captureStillImageAsynchronouslyFromConnection:connection
                                                       completionHandler:^( CMSampleBufferRef imageDataSampleBuffer, NSError *error )
    {
        //handle the buffer right here
        NSData *data = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer]; 
        //works better
    }]; 

希望这有助于某人。

答案 1 :(得分:0)

此解决方案的下一步是使用以下命令记录调试器中报告的所有数据:

po imageDataSampleBuffer

这会在抛出异常时产生大量细节,样本缓冲区有很多信息。然后,自从发布到SO后,我注释掉了一些代码,然后取消注释,现在它正在运行。我的代码没有任何改变,但是,我确实关闭了在mac上运行的一些程序。也许这是一个开发机器的bug。在此之后,我关闭并重新打开了Xcode,并且没有抛出异常。