【问题标题】:DIsplaying Asynchronous stillImageOutput from AVVideoCapture Session using AVFoundation使用 AVFoundation 显示来自 AVVideoCapture 会话的异步静止图像输出
【发布时间】:2019-02-08 23:35:03
【问题描述】:

我正在以预览模式捕捉视频,并希望显示相机捕捉到的静止图像。

我目前将图像和捕获输出保存到接口中定义的 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;

【问题讨论】:

    标签: ios objective-c avfoundation avcapture


    【解决方案1】:

    我会更改 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]);
                }];
            }
        }];
    

    此链接可能有助于您开始使用块语法:http://goshdarnblocksyntax.com

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-29
      相关资源
      最近更新 更多