Правильный способ оптимизировать мой AVCaptureSession? - PullRequest
4 голосов
/ 23 ноября 2011

Я запустил AVCaptureSession, и он почти идеально дублирует пользовательский интерфейс Camera.app, однако через несколько секунд приложение вылетает, и я просто не могу понять, что я делаю неправильно.Я действительно надеюсь, что кто-то знает, как это оптимизировать!

I AM с использованием ARC;и снова весь сеанс работает нормально, но через некоторое время вылетает.Метод делегата AVCaptureSession вызывается так, как будто КАЖДУЮ секунду.Если есть способ вызвать этот метод только тогда, когда пользователь нажимает кнопку «сделать снимок», как я могу сделать это, сохраняя при этом слой «живого» предварительного просмотра?

Заранее спасибо!

Настройка сеанса

NSError *error = nil;
session = [[AVCaptureSession alloc] init];
session.sessionPreset = AVCaptureSessionPresetMedium;
device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
[session addInput:input];

output = [[AVCaptureVideoDataOutput alloc] init];
[session addOutput:output];

dispatch_queue_t queue = dispatch_queue_create("myQueue", NULL);
[output setSampleBufferDelegate:self queue:queue];
dispatch_release(queue);

output.videoSettings = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey];
if(version >= 4.0 && version < 5.0) {
    output.minFrameDuration = CMTimeMake(1, 15);
}
output.alwaysDiscardsLateVideoFrames = YES;

previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:session];
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[self.view.layer addSublayer:previewLayer];
[self.view addSubview:camera_overlay];
[session startRunning];

AVCaptureSession Вызываемый делегат:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
    UIImage *capture_image = [self imageFromSampleBuffer:sampleBuffer];
    return capture_image;
}

Метод, который получает UIImageиз буфера для образцов

- (UIImage *)imageFromSampleBuffer:(CMSampleBufferRef)sampleBuffer {

    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    CVPixelBufferLockBaseAddress(imageBuffer, 0); 
    void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer); 
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); 
    CGImageRef quartzImage = CGBitmapContextCreateImage(context); 
    CVPixelBufferUnlockBaseAddress(imageBuffer,0);
    CGContextRelease(context); 
    CGColorSpaceRelease(colorSpace);
    UIImage *image = [UIImage imageWithCGImage:quartzImage];
    CGImageRelease(quartzImage);

    return image;

}

Ответы [ 2 ]

5 голосов
/ 27 ноября 2011

Посмотрите на приложение AVCam Demo от Apple для полного примера.

Способ

- (void)captureOutput:(AVCaptureOutput *)captureOutput 
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
fromConnection:(AVCaptureConnection *)connection {

вызывается каждый раз, когда кадр камеры готов, и в вашем случае он вызывается 15 раз в секунду или, по крайней мере, должен вызываться 15 раз, поскольку вы указали частоту кадров как output.minFrameDuration = CMTimeMake(1, 15);

Из предоставленного вами кода я могу думать только о том, что вы не выпускаете UIImage *capture_image

Вы можете использовать инструменты XCode для профилирования своего приложения и понять, почему это происходит: Руководство по приборам

Инструмент «Утечки» - это ваша первая остановка в вашем случае, для него есть множество учебных пособий в Интернете, и вот одно из них: Отслеживание утечек памяти iPhone , написанное SO-пользователем OwenGross, если я м не ошибаюсь взято отсюда

0 голосов
/ 28 августа 2012

Пост выглядит довольно старым, но если кто-нибудь увидит это:

Кому вы возвращаете картинку в методе делегата (

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
    UIImage *capture_image = [self imageFromSampleBuffer:sampleBuffer];
    return capture_image;
}

)

Вы можете использовать кнопку, которая поднимает флаг. В методе делегата проверьте, был ли установлен флаг, и только затем создайте изображение. Изображение должно быть переменной экземпляра, иначе оно будет потеряно в любом случае.

Существуют также методы делегирования для захвата изображения. captureStillImageAsynchronouslyFromConnection

...