使用 AVFoundation 显示来自 AVVideoCapture 会话的异步 stillImageOutput
DIsplaying Asynchronous stillImageOutput from AVVideoCapture Session using AVFoundation
我正在预览模式下拍摄视频,想显示相机拍摄的静止图像。
我目前将图像和捕获输出保存到接口中定义的ivars:
UIImage *snapshot
AVCaptureStillImageOutput* stillImageOutput;
视频显示正常。但是,当我尝试捕获和显示静止图像时,什么也没有出现,事实上,调试器显示 stillImageOutput 和图像为零。我认为这可能是异步捕获的时间问题,我需要使用完成处理程序,但我不擅长完成处理程序。
捕获静止图像后立即显示而不占用的正确方法是什么UI:
静态捕获代码:
- (void)takeSnapshot {
AVCaptureConnection *videoConnection = nil;
for (AVCaptureConnection *connection in stillImageOutput.connections) {
for (AVCaptureInputPort *port in [connection inputPorts]) {
if ([[port mediaType] isEqual:AVMediaTypeVideo]) {
videoConnection = connection;
break;
}
}
if (videoConnection) {
break;
}
}
[stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection
completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
if (imageDataSampleBuffer != NULL) {
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
snapshot = [UIImage imageWithData:imageData];
}
}];
}
静态显示代码。注意缺少完成处理程序,这可能是个问题,但是,我不确定如何写...
[self takeSnapshot];
self.imageView.image = snapshot;
我会更改 takeSnapshot 方法以接收完成块,然后在其他异步方法的完成块中调用该完成块:
captureStillImageAsynchronouslyFromConnection:completionHandler
这是一个方法示例,该方法采用完成块,然后在内部调用的方法的完成块中回调它:
// this correlates to your takeSnapshot method
// you want to add a completion portion to this method
- (void)doSomethingAsynchronouslyWithCompletion:(void (^)(NSData *completionData))completion {
// call your other async method
[self anotherAsyncMethodWithItsOwnCompletion:^(NSData *completionDataFromSecondMethod) {
if (completionDataFromSecondMethod.length > 0) {
// this is where you would receive the CMSampleBufferRef from the completion handler of captureStillImageAsynchronouslyFromConnection:completionHandler
// and convert it over to to data
// make sure the completion block isn't nil if it's nullable
if (completion) {
// you would want to pass back the NSData imageData in the completion block here
completion(completionDataFromSecondMethod);
}
}
}];
}
// this method would simulate the captureStillImageAsynchronouslyFromConnection:completionHandler: method
- (void)anotherAsyncMethodWithItsOwnCompletion:(void (^)(NSData * completionDataFromSecondMethod))anotherCompletion {
// this is just to simulate some time waiting for the asnyc task to complete
// never call sleep in your own code
sleep(3);
if (anotherCompletion) {
// this simulates the fake CFSampleBufferRef passed back by the captureStillImage...
NSData *fakeCompletionData = [@"FakeCompletionString" dataUsingEncoding:NSUTF8StringEncoding];
anotherCompletion(fakeCompletionData);
}
}
以及如何称呼它的示例:
[self doSomethingAsynchronouslyWithCompletion:^(NSData *completionData) {
if (completionData.length > 0) {
// come back on the main queue to modify any UI Elements
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// this is where you want want to set your self.imageView.image
// self.imageView.image = [UIImage imageWithData:{{dataFromCompletion}}]
NSLog(@"The completionString result = %@", [[NSString alloc] initWithData:completionData encoding:NSUTF8StringEncoding]);
}];
}
}];
这个 link 可能有助于您开始使用块语法:http://goshdarnblocksyntax.com
我正在预览模式下拍摄视频,想显示相机拍摄的静止图像。
我目前将图像和捕获输出保存到接口中定义的ivars:
UIImage *snapshot
AVCaptureStillImageOutput* stillImageOutput;
视频显示正常。但是,当我尝试捕获和显示静止图像时,什么也没有出现,事实上,调试器显示 stillImageOutput 和图像为零。我认为这可能是异步捕获的时间问题,我需要使用完成处理程序,但我不擅长完成处理程序。
捕获静止图像后立即显示而不占用的正确方法是什么UI:
静态捕获代码:
- (void)takeSnapshot {
AVCaptureConnection *videoConnection = nil;
for (AVCaptureConnection *connection in stillImageOutput.connections) {
for (AVCaptureInputPort *port in [connection inputPorts]) {
if ([[port mediaType] isEqual:AVMediaTypeVideo]) {
videoConnection = connection;
break;
}
}
if (videoConnection) {
break;
}
}
[stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection
completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
if (imageDataSampleBuffer != NULL) {
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
snapshot = [UIImage imageWithData:imageData];
}
}];
}
静态显示代码。注意缺少完成处理程序,这可能是个问题,但是,我不确定如何写...
[self takeSnapshot];
self.imageView.image = snapshot;
我会更改 takeSnapshot 方法以接收完成块,然后在其他异步方法的完成块中调用该完成块:
captureStillImageAsynchronouslyFromConnection:completionHandler
这是一个方法示例,该方法采用完成块,然后在内部调用的方法的完成块中回调它:
// this correlates to your takeSnapshot method
// you want to add a completion portion to this method
- (void)doSomethingAsynchronouslyWithCompletion:(void (^)(NSData *completionData))completion {
// call your other async method
[self anotherAsyncMethodWithItsOwnCompletion:^(NSData *completionDataFromSecondMethod) {
if (completionDataFromSecondMethod.length > 0) {
// this is where you would receive the CMSampleBufferRef from the completion handler of captureStillImageAsynchronouslyFromConnection:completionHandler
// and convert it over to to data
// make sure the completion block isn't nil if it's nullable
if (completion) {
// you would want to pass back the NSData imageData in the completion block here
completion(completionDataFromSecondMethod);
}
}
}];
}
// this method would simulate the captureStillImageAsynchronouslyFromConnection:completionHandler: method
- (void)anotherAsyncMethodWithItsOwnCompletion:(void (^)(NSData * completionDataFromSecondMethod))anotherCompletion {
// this is just to simulate some time waiting for the asnyc task to complete
// never call sleep in your own code
sleep(3);
if (anotherCompletion) {
// this simulates the fake CFSampleBufferRef passed back by the captureStillImage...
NSData *fakeCompletionData = [@"FakeCompletionString" dataUsingEncoding:NSUTF8StringEncoding];
anotherCompletion(fakeCompletionData);
}
}
以及如何称呼它的示例:
[self doSomethingAsynchronouslyWithCompletion:^(NSData *completionData) {
if (completionData.length > 0) {
// come back on the main queue to modify any UI Elements
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// this is where you want want to set your self.imageView.image
// self.imageView.image = [UIImage imageWithData:{{dataFromCompletion}}]
NSLog(@"The completionString result = %@", [[NSString alloc] initWithData:completionData encoding:NSUTF8StringEncoding]);
}];
}
}];
这个 link 可能有助于您开始使用块语法:http://goshdarnblocksyntax.com