DIsplaying Асинхронный stillImageOutput из сеанса AVVideoCapture с использованием AVFoundation - PullRequest
0 голосов
/ 09 февраля 2019

Я снимаю видео в режиме предварительного просмотра и хотел бы отобразить неподвижное изображение, снятое камерой.

В настоящее время я сохраняю изображение и вывод изображения в виде иваров, определенных в интерфейсе как:

UIImage *snapshot
AVCaptureStillImageOutput* stillImageOutput;

Видео отображается нормально.Однако, когда я пытаюсь захватить и отобразить неподвижное изображение, ничего не появляется, и на самом деле отладчик показывает, что stillImageOutput и image равны нулю.Я думаю, что это может быть проблема синхронизации с асинхронным захватом и что мне нужно использовать обработчик завершения, но я слаб в обработчиках завершения.

Как правильно отобразить неподвижное изображение сразу после его захвата без привязки пользовательского интерфейса:

Код для захвата фотографии:

- (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;

1 Ответ

0 голосов
/ 09 февраля 2019

Я бы изменил метод 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

...