2012-07-07 84 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)); 
}); 
相關問題