2010-10-19 8 views
18

Devo essere in grado di utilizzare AVCaptureVideoDataOutput e AVCaptureMovieFileOutput contemporaneamente. Il codice seguente funziona, tuttavia, la registrazione video non lo fa. Il delegato didFinishRecordingToOutputFileAtURL viene chiamato direttamente dopo che è stato chiamato startRecordingToOutputFileURL. Ora, se rimuovo AVCaptureVideoDataOutput dal AVCaptureSession semplicemente commentando la riga:AVCaptureVideoDataOutput e AVCaptureMovieFileOutput simultanei

[captureSession addOutput:captureDataOutput];

Le opere registrazione video, ma poi il SampleBufferDelegate non si chiama (che ho bisogno).

Come posso fare per avere AVCaptureVideoDataOutput e AVCaptureMovieFileOutput che funzionano contemporaneamente.

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

devo aggiungere sto ottenendo l'errore:

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

da

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

Acclamazioni

+1

C'è una via che lavora dimostrato di fare questo. Altro in questa domanda: http://stackoverflow.com/questions/4944083/can-use-avcapturevideodataoutput-and-avcapturemoviefileoutput-at-the-same-time –

risposta

29

Ho contattato un ingegnere di supporto di Apple e mi ha detto che simultanea AVCaptureVideoDataOutput + AVCaptureMovieFileOutput l'uso non è supportato. Non so se lo supporteranno in futuro, ma ha usato la parola "non supportato in questo momento".

Ti incoraggio a compilare una segnalazione bug/richiesta di funzionalità su questo, come ho fatto io (bugreport.apple.com), in quanto misurano quanto le persone difficili vogliono qualcosa e forse possiamo vederlo in un prossimo futuro.

+2

Assicurati di vedere il commento di Oded sopra con una soluzione funzionante: http: //stackoverflow.com/questions/4944083/can-use-avcapturevideodataoutput-and-avcapturemoviefileoutput-at-the-same-time –

+0

@StanJames è ancora oggi il caso in cui la soluzione alternativa di oded è l'approccio migliore per utilizzare AVCaptureVideoDataOutput + AVCaptureMovieFileOutput contemporaneamente? – Crashalot

+0

@StanJames se l'obiettivo è quello di creare due video contemporaneamente, è possibile utilizzare due AVAssetWriters (con solo AVCaptureVideoDataOutput) anziché AVCaptureVideoDataOutput e AVCaptureMovieFileOutput? – Crashalot

2

Anche se non è possibile utilizzare AVCaptureVideoDataOutput, si possibile utilizzareAVCaptureVideoPreviewLayer contemporaneamente con AVCaptureMovieFileOutput. Vedere l'esempio "AVCam" sul sito Web di Apple.

Nel Xamarin.iOS, il codice simile a questo:

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

e come ottenere il buffer frame raw da AVCaptureVideoPreviewLayer? ... – user924