开发者

Simultaneous AVCaptureVideoDataOutput and AVCaptureMovieFileOutput

I need to be able to have AVCaptureVideoDataOutput and AVCaptureMovieFileOutput working at the same time. The below code works, however, the video recording does not. The didFinishRecordingToOutputFileAtURL delegate is called directly after startRecordingToOutputFileURL is called. Now if i remove AVCaptureVideoDataOutput from the AVCaptureSession by simply commenting out the line:

[captureSession addOutput:captureDataOutput];

The video recording works but then the SampleBufferDelegate is not called (which i need).

How can i go about having AVCaptureVideoDataOutput and AVCaptureMovieFileOutput working simultaneously.

- (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 = [[AVCaptur开发者_JS百科eMovieFileOutput 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
}

I should add i am getting the error:

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

from

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

Cheers


I have contacted an engineer at Apple's support and he told me that simultaneous AVCaptureVideoDataOutput + AVCaptureMovieFileOutput use is not supported. I don't know if they will support it in the future, but he used the word "not supported at this time".

I encourage you to fill a bug report / feature request on this, as I did (bugreport.apple.com), as they measure how hard people want something and we perhaps can see this in a near future.


Still 9 years later Apple apparently does not seem to want this to work together.

But you can easily work with AVAssetWriter.

You can't use AVCaptureVideoDataOutput and AVCaptureMovieFileOutput on the same time. But you can use AVCaptureVideoDataOutput and analyse or modify on the data, then use AVAsseWriter to write the frames to a file.

Source: https://developer.apple.com/forums/thread/98113

How to save video with output using AVAssetWriter:

Save AVCaptureVideoDataOutput to movie file using AVAssetWriter in Swift


Although you cannot use AVCaptureVideoDataOutput, you can use AVCaptureVideoPreviewLayer simultaneously with AVCaptureMovieFileOutput. See the "AVCam" example on Apple's Website.

In Xamarin.iOS, the code looks like this:

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);


XCode 14.1 is already support it.

  • XCode 13.4: Not works
  • XCode 14.1: works
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜