2010-10-19 16 views
18

que tienen que ser capaces de tener AVCaptureVideoDataOutput y AVCaptureMovieFileOutput de trabajo al mismo tiempo. El siguiente código funciona, sin embargo, la grabación de video no. El delegado didFinishRecordingToOutputFileAtURL se llama directamente después de llamar al startRecordingToOutputFileURL. Ahora bien, si quito AVCaptureVideoDataOutput del AVCaptureSession simplemente comentando la línea:simultánea AVCaptureVideoDataOutput y AVCaptureMovieFileOutput

[captureSession addOutput:captureDataOutput];

Los trabajos de grabación de vídeo, pero entonces el SampleBufferDelegate no se llama (que necesito).

¿Cómo puedo hacer para que AVCaptureVideoDataOutput y AVCaptureMovieFileOutput funcionen simultáneamente?

- (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 
} 

debo añadir que estoy recibiendo el error:

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 

Saludos

+1

No es una forma de trabajo probada para hacer esto. Más en esta pregunta: http://stackoverflow.com/questions/4944083/can-use-avcapturevideodataoutput-and-avcapturemoviefileoutput-at-the-same-time –

Respuesta

29

Me he contactado con un ingeniero de soporte de Apple y me dijo que simultánea AVCaptureVideoDataOutput + AVCaptureMovieFileOutput no se admite el uso. No sé si lo apoyarán en el futuro, pero usó la palabra "no compatible en este momento".

Lo aliento a que complete una solicitud de informe/función de error, como hice (bugreport.apple.com), ya que miden qué tan duro la gente quiere algo y quizás podamos ver esto en un futuro próximo.

+2

Asegúrese de ver el comentario de Oded anterior con una solución de trabajo: http: //stackoverflow.com/questions/4944083/can-use-avcapturevideodataoutput-and-avcapturemoviefileoutput-at-the-same-time –

+0

@StanJames ¿Sigue siendo el caso hoy en día cuando la solución de oded es la mejor manera de utilizar AVCaptureVideoDataOutput + AVCaptureMovieFileOutput simultáneamente? – Crashalot

+0

@StanJames si el objetivo es crear dos videos simultáneamente, ¿podría usar dos AVAssetWriters (con solo AVCaptureVideoDataOutput) en lugar de AVCaptureVideoDataOutput y AVCaptureMovieFileOutput? – Crashalot

2

Aunque no se puede utilizar AVCaptureVideoDataOutput, que puede utilizar simultáneamente con AVCaptureVideoPreviewLayerAVCaptureMovieFileOutput. Vea el ejemplo "AVCam" en el sitio web de Apple.

En Xamarin.iOS, el código es el siguiente:

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

y cómo obtener el buffer de cuadro sin formato de AVCaptureVideoPreviewLayer? ... – user924

Cuestiones relacionadas