2010-10-19 7 views
18

Je dois pouvoir avoir AVCaptureVideoDataOutput et AVCaptureMovieFileOutput en même temps. Le code ci-dessous fonctionne, cependant, l'enregistrement vidéo ne fonctionne pas. Le délégué didFinishRecordingToOutputFileAtURL est appelé directement après l'appel de startRecordingToOutputFileURL. Maintenant, si je retire AVCaptureVideoDataOutput du AVCaptureSession simplement en commentant la ligne:AVCaptureVideoDataOutput et AVCaptureMovieFileOutput simultanés

[captureSession addOutput:captureDataOutput];

Les travaux d'enregistrement vidéo mais le SampleBufferDelegate n'est pas appelé (dont j'ai besoin).

Comment puis-je faire fonctionner AVCaptureVideoDataOutput et AVCaptureMovieFileOutput simultanément.

- (void)initCapture { 
AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput deviceInputWithDevice:[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo] error:NULL]; 

captureDataOutput = [[AVCaptureVideoDataOutput alloc] init]; 
[captureDataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()]; 

m_captureFileOutput = [[AVCaptureMovieFileOutput alloc] init]; 

NSString* key = (NSString*)kCVPixelBufferPixelFormatTypeKey; 
NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA]; 
NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:value forKey:key]; 

[captureDataOutput setVideoSettings:videoSettings]; 

captureSession = [[AVCaptureSession alloc] init]; 

[captureSession addInput:captureInput]; 
[captureSession addOutput:m_captureFileOutput]; 
[captureSession addOutput:captureDataOutput]; 

[captureSession beginConfiguration]; 
[captureSession setSessionPreset:AVCaptureSessionPresetLow]; 
[captureSession commitConfiguration]; 

[self performSelector:@selector(startRecording) withObject:nil afterDelay:10.0]; 
[self performSelector:@selector(stopRecording) withObject:nil afterDelay:15.0]; 

[captureSession startRunning]; 
} 


- (void) startRecording 
{ 
    [m_captureFileOutput startRecordingToOutputFileURL:[self tempFileURL] recordingDelegate:self]; 

} 

- (void) stopRecording 
{ 
    if([m_captureFileOutput isRecording]) 
[m_captureFileOutput stopRecording]; 

} 


- (NSURL *) tempFileURL 
{ 
NSString *outputPath = [[NSString alloc] initWithFormat:@"%@%@", NSTemporaryDirectory(), @"camera.mov"]; 
NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:outputPath]; 
NSFileManager *fileManager = [NSFileManager defaultManager]; 
if ([fileManager fileExistsAtPath:outputPath]) { 
    [[NSFileManager defaultManager] removeItemAtPath:outputPath error:nil]; 
[outputPath release]; 
return [outputURL autorelease]; 
} 



- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didStartRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray *)connections 
{ 
NSLog(@"start record video"); 
} 

- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error 
{ 
NSLog(@"end record"); 
} 


- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection 
{ 
     // do stuff with sampleBuffer 
} 

Je dois ajouter que je reçois l'erreur:

Error Domain=NSOSStatusErrorDomain Code=-12780 "The operation couldn’t be completed. (OSStatus error -12780.)" UserInfo=0x23fcd0 {AVErrorRecordingSuccessfullyFinishedKey=false} 

de

- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error 

Vive

+1

Il existe un moyen de travail éprouvée de le faire. Plus dans cette question: http://stackoverflow.com/questions/4944083/can-use-avcapturevideodataoutput-and-avcapturemoviefileoutput-at-the-same-time –

Répondre

29

J'ai contacté un ingénieur à l'appui d'Apple et il m'a dit que simultanée AVCaptureVideoDataOutput + AVCaptureMovieFileOutput l'utilisation n'est pas supportée. Je ne sais pas s'ils vont l'appuyer à l'avenir, mais il a utilisé le mot «non soutenu en ce moment». Je vous encourage à remplir un rapport de bogue/demande de fonctionnalité à ce sujet, comme je l'ai fait (bugreport.apple.com), car ils mesurent à quel point les gens veulent quelque chose et nous pouvons peut-être voir cela dans un proche avenir.

+2

Soyez sûr de voir le commentaire d'Oded ci-dessus avec une solution de travail: http: //stackoverflow.com/questions/4944083/can-use-avcapturevideodataoutput-and-avcapturemoviefileoutput-at-the-same-time –

+0

@StanJames est-il toujours le cas aujourd'hui où la solution de contournement d'oded est la meilleure approche pour utiliser simultanément AVCaptureVideoDataOutput + AVCaptureMovieFileOutput? – Crashalot

+0

@StanJames Si le but est de créer deux vidéos simultanément, pourriez-vous utiliser deux AVAssetWriters (avec seulement AVCaptureVideoDataOutput) au lieu de AVCaptureVideoDataOutput et AVCaptureMovieFileOutput? – Crashalot

2

Bien que vous ne pouvez pas utiliser AVCaptureVideoDataOutput, vous pouvez utiliser AVCaptureVideoPreviewLayer simultanément avec AVCaptureMovieFileOutput. Voir l'exemple "AVCam" sur le site Web d'Apple.

En Xamarin.iOS, le code ressemble à ceci:

var session = new AVCaptureSession(); 

var camera = AVCaptureDevice.DefaultDeviceWithMediaType(AVMediaType.Video); 
var mic = AVCaptureDevice.DefaultDeviceWithMediaType(AVMediaType.Audio); 
if(camera == null || mic == null){ 
    throw new Exception("Can't find devices"); 
} 

if(session.CanAddInput(camera)){ 
    session.AddInput(camera); 
} 
if(session.CanAddInput(mic)){ 
    session.AddInput(mic); 
} 

var layer = new AVCaptureVideoPreviewLayer(session); 
layer.LayerVideoGravity = AVLayerVideoGravity.ResizeAspectFill; 
layer.VideoGravity = AVCaptureVideoPreviewLayer.GravityResizeAspectFill; 

cameraView = new UIView(); 
cameraView.Layer.AddSublayer(layer); 

var filePath = System.IO.Path.Combine(Path.GetTempPath(), "temporary.mov"); 
var fileUrl = NSUrl.FromFilename(filePath); 

var movieFileOutput = new AVCaptureMovieFileOutput(); 
var recordingDelegate = new MyRecordingDelegate(); 
session.AddOutput(movieFileOutput); 

movieFileOutput.StartRecordingToOutputFile(fileUrl, recordingDelegate); 
+0

et comment obtenir une mémoire tampon d'image brute à partir de AVCaptureVideoPreviewLayer? ... – user924

Questions connexes