2012-07-07 3 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]'란 무엇입니까? –

+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 클래스는 동일한 세션에 추가 될 수 있습니다. –

+0

@SteveMcFarlin 처리를 위해 오디오 및 이미지 원시 데이터를 분리합니다. –

답변

0

시작하려면 다음 네 가지를 수행 도와주세요 :

글로벌 큐를 작성하고 캡슐화 객체의 할당을 해제 할 때까지 공개하지 않는다; 큐의 유형으로서 "직렬"지정한 대상을 메인 큐합니다

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

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

샘플 버퍼가 오디오 또는 비디오 데이터를 포함하는지 여부를 결정하기 위해 각각의 샘플 버퍼로부터의 미디어 타입 정보를 받기를

메서드 호출로 다른 클래스에 샘플 버퍼를 보내는 대신 다른 클래스를 데이터 출력 대리자로 만듭니다. 너는 그 일을 두 배로하고있어.

마지막으로 자체 대기열에서 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)); 
}); 
관련 문제