Сохранение выходного буфера выборки AVCaptureSession в CoreData

Я использую AVCaptureSession для захвата кадров с камеры с помощью метода setSampleBufferDelegate из класса AVCaptureVideoDataOutput. Метод делегата выглядит следующим образом. Вы можете видеть, что я конвертирую в UIImage и помещаю его в UIImageView. Я хотел бы сохранить каждый UIImage на диск и сохранить URL-адрес в новом управляемом объекте, но я не знаю, как правильно получить manageObjectContext, поскольку каждый вызов порождает новый поток с использованием очереди последовательной отправки. Может ли кто-нибудь предложить решение для использования CoreData и очередей отправки таким образом, чтобы я мог создать коллекцию изображений, которые хранятся на диске и соответствуют управляемому объекту.

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
/*Lock the image buffer*/
CVPixelBufferLockBaseAddress(imageBuffer,0); 
/*Get information about the image*/
uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer); 
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
size_t width = CVPixelBufferGetWidth(imageBuffer); 
size_t height = CVPixelBufferGetHeight(imageBuffer);  

/*Create a CGImageRef from the CVImageBufferRef*/
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
CGContextRef newContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
CGImageRef newImage = CGBitmapContextCreateImage(newContext); 

    /*We release some components*/
    CGContextRelease(newContext); 
    CGColorSpaceRelease(colorSpace);

/*We display the result on the image view (We need to change the orientation of the image so that the video is displayed correctly).
     Same thing as for the CALayer we are not in the main thread so ...*/
    UIImage *image= [UIImage imageWithCGImage:newImage scale:1.0 orientation:UIImageOrientationRight];

/*We relase the CGImageRef*/
CGImageRelease(newImage);

[self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];

/*We unlock the  image buffer*/
CVPixelBufferUnlockBaseAddress(imageBuffer,0);

[pool drain];
}

person Ankur    schedule 16.04.2011    source источник


Ответы (1)


рекомендуемое решение — создать новый NSManagedObjectContext для каждого потока, каждый из которых указывает на один NSPersistentStoreCoordinator. Вы также можете прослушивать NSManagedObjectContextDidSaveNotification, чтобы объединить изменения в контекст основного потока (используя метко названный mergeChangesFromContextDidSaveNotification:).

Лично мне нравится использовать подобное средство доступа в центральном месте для обработки контекстов для каждого потока:

- (NSManagedObjectContext *) managedObjectContext {
    NSManagedObjectContext *context = [[[NSThread currentThread] threadDictionary] objectForKey:@"NSManagedObjectContext"];
    if (context == nil) {
        context = [[[NSManagedObjectContext alloc] init] autorelease];
        [context setPersistentStoreCoordinator:self.persistentStoreCoordinator];
        [[[NSThread currentThread] threadDictionary] setObject:context forKey:@"NSManagedObjectContext"];
    }
    return context;
}

Помните, что вы не можете передавать NSManagedObjects между потоками проще, чем вы можете передавать контексты. Вместо этого вы должны передать NSManagedObjectID (из свойства objectID объекта), а затем в целевом потоке использовать метод objectWithID: контекста этого потока, чтобы вернуть эквивалентный объект.

person Anomie    schedule 16.04.2011