2012-07-07 103 views
2

我正在使用AVFoundation访问用于制作视频的图像和音频。问题是当我加入像音频设备。使用AVFoundation访问图像和音频

AVCaptureDevice *audioDevice  = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeAudio]; 
AVCaptureDeviceInput * microphone_input = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:nil]; 
AVCaptureAudioDataOutput * audio_output = [[AVCaptureAudioDataOutput alloc] init]; 
[self.captureSession2 addInput:microphone_input]; 
[self.captureSession2 addOutput:audio_output]; 
dispatch_queue_t queue2; 
queue2 = dispatch_queue_create("Audio", NULL); 
[audio_output setSampleBufferDelegate:self queue:queue2]; 
dispatch_release(queue2); 

和相机的图像。

AVCaptureDevice *cameraDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 

//putting it on the input. 
AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput deviceInputWithDevice:cameraDevice error:nil]; 

//selecting the Output. 
AVCaptureVideoDataOutput *captureOutput = [[AVCaptureVideoDataOutput alloc] init]; 

[self.captureSession addInput:captureInput]; 
[self.captureSession addOutput:captureOutput]; 
dispatch_queue_t queue; 
queue = dispatch_queue_create("cameraQueue", 0); 
[captureOutput setSampleBufferDelegate:self queue:queue]; 
dispatch_release(queue); 

毕竟通过代表

- (void)captureOutput:(AVCaptureOutput *)captureOutput 
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
    fromConnection:(AVCaptureConnection *)connection 
{ 
if ([captureOutput isKindOfClass:[AVCaptureAudioDataOutput class]]) 
    [self sendAudeoRaw:sampleBuffer]; 
if ([captureOutput isKindOfClass:[AVCaptureVideoDataOutput class]]) 
    [self sendVideoRaw:sampleBuffer];} 

获取图像原始数据的速度大约为每秒2图像非常缓慢得到原始数据。我如何改善它,因为我正在寻找10-12图像/秒。 请帮助

+0

什么是'[self sendVideoRaw:sampleBuffer]'? – 2012-07-07 19:12:08

+0

另外,你可以在你的captureOutput代码中简单地比较指针,而不是使用isKindOfClass。例如'if(captureOutput == audio_output)'。你必须小心isKindOfClass。它可以返回一些你可能没有想到的东西。这通常只发生在容器类中。查看此[post](http://stackoverflow.com/questions/1096772/is-it-safe-to-use-iskindofclass-against-an-nsstring-instance-to-determine-type)进行讨论。最后一个想法。您不需要为音频和视频使用两个不同的捕捉会话。两个AV IO类都可以添加到同一个会话中。 – 2012-07-07 19:23:04

+0

@SteveMcFarlin分离音频和图像原始数据进行处理。 – 2012-07-09 05:38:46

回答

0

做这四件事开始:

创建一个全球性的队列,直到您解除分配封装对象不松开;指定“序列”作为队列的类型,并且使目标主队列:

_captureOutputQueue = dispatch_queue_create_with_target("bush.alan.james.PhotosRemote.captureOutputQueue", DISPATCH_QUEUE_SERIAL, dispatch_get_main_queue()); 

获得从每个样品缓冲器中的媒体类型描述来确定所述样品缓冲器中是否包含音频或视频数据:

CMFormatDescriptionRef formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer); 
CMMediaType mediaType = CMFormatDescriptionGetMediaType(formatDescription); 
if (mediaType == kCMMediaType_Audio)... 
if (mediaType == kCMMediaType_Video)... 

而不是通过方法调用发送样本缓冲区到另一个类,使其他类的数据输出委托;否则,你的工作翻倍。

最后,确保您在自己的队列中运行AVSession。每苹果的文档AVCaptureSession:

startRunning方法是一个阻塞调用,它可能需要一些时间, 因此,你应该上的串行队列,以便 主队列不会被阻止进行会话建立(这保持UI响应)。有关 实施示例,请参阅 AVCam-iOS: Using AVFoundation to Capture Images and Movies

这包括到配置摄像头,并在特定的方法作出任何电话,任何调用startRunning或AVCaptureSession的stopRunning方法:

dispatch_async(self.sessionQueue, ^{ 
    [self configureSession]; 
}); 

dispatch_async(self.sessionQueue, ^{ 
    [self.session startRunning]; 
}); 

dispatch_async(self.sessionQueue, ^{ 
    [self.session stopRunning]; 
}); 

如果不能设置委托作为类处理样品的缓冲区,你可以考虑把它们放在队列两类有权访问,然后通过一键:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection 
{ 
    static char kMyKey; // set key to any value; pass the key--not the sample buffer--to the receiver 
    dispatch_queue_set_specific(((AppDelegate *)[[UIApplication sharedApplication] delegate].serialQueue, 
           &kMyKey, 
           (void*)CFRetain(sampleBuffer), 
           (dispatch_function_t)CFRelease); 
    });  
} 

在接收机类:

dispatch_async(((AppDelegate *)[[UIApplication sharedApplication] delegate]).serialQueue, ^{ 
      CMSampleBufferRef sb = dispatch_get_specific(&kMyKey); 
      NSLog(@"sb: %i", CMSampleBufferIsValid(sb)); 
}); 
相关问题