AVCaptureVideoDataOutput en iOS 8 no publica búferes de muestra en la queue de envío especificada

Cuando se utiliza AVCaptureVideoDataOutput y se define un delegado de búfer de muestra con una queue de despacho (setSampleBufferDelegate: queue), en iOS 8 experimentamos que AVFoundation no publica los búferes de muestra en la queue de despacho especificada, sino que siempre utiliza "com.apple.avfoundation.videodataoutput .bufferqueue ".

Esto funciona como se esperaba en iOS7.

Alguien más ha experimentado esto?

Una solución obvia es llamar manualmente a dispatch_sync en la callback para sincronizar el procesamiento a la queue de envío personalizado, pero esto, extrañamente, provoca un interlocking …

Código de ejemplo que produce este problema:

- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. AVCaptureSession *session = [[AVCaptureSession alloc] init]; session.sessionPreset = AVCaptureSessionPresetMedium; AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session]; captureVideoPreviewLayer.frame = self.view.bounds; [self.view.layer addSublayer:captureVideoPreviewLayer]; [session addInput:[AVCaptureDeviceInput deviceInputWithDevice:[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo] error:nil]]; AVCaptureVideoDataOutput *output = [[AVCaptureVideoDataOutput alloc] init]; queue = dispatch_queue_create("our.dispatch.queue", DISPATCH_QUEUE_SERIAL); [output setSampleBufferDelegate:self queue:queue]; [session addOutput:output]; [session startRunning]; } - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { NSLog(@"Running on queue %@, queue that was set is %@, this is %s", dispatch_get_current_queue(), [captureOutput performSelector:@selector(sampleBufferCallbackQueue)], queue == dispatch_get_current_queue() ? "our queue" : "not our queue!!!"); } 

Lo que probablemente está sucediendo aquí es que su queue, com.apple.avfoundation.videodataoutput.bufferqueue , se ha configurado para apuntar a la suya utilizando dispatch_set_target_queue . Esto es funcionalmente equivalente a despachar a su queue, pero explicaría el nombre, y también explicaría el punto muerto cuando trató de enviar de nuevo a su queue.

En otras palabras, solo porque el nombre de queue no sea igual al nombre de su queue no significa que el bloque no se esté ejecutando en su queue.

Para solucionar este problema, tuve que modificar mi -captureOutput: ::

 - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { dispatch_queue_t queue = ((MyAppDelegate *)UIApplication.shanetworkingApplication.delegate).videoDataOutputQueue; CFRetain(sampleBuffer); dispatch_async(queue, ^{ for (id<AVCaptureVideoDataOutputSampleBufferDelegate> target in captureTargets.copy) [target captureOutput:captureOutput didOutputSampleBuffer:sampleBuffer fromConnection:connection]; CFRelease(sampleBuffer); }); }