Одновременный AVCaptureVideoDataOutput и AVCaptureMovieFileOutput - PullRequest
22 голосов
/ 19 октября 2010

Мне нужно, чтобы AVCaptureVideoDataOutput и AVCaptureMovieFileOutput работали одновременно.Приведенный ниже код работает, однако запись видео - нет.Делегат didFinishRecordingToOutputFileAtURL вызывается сразу после вызова startRecordingToOutputFileURL.Теперь, если я удаляю AVCaptureVideoDataOutput из AVCaptureSession, просто закомментировав строку:

[captureSession addOutput:captureDataOutput];

Запись видео работает, но тогда SampleBufferDelegate не вызывается (что мне нужно).

Как мне работать одновременно AVCaptureVideoDataOutput и AVCaptureMovieFileOutput.

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

Я должен добавить, что я получаю ошибку:

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

от

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

Приветствия

Ответы [ 2 ]

33 голосов
/ 13 февраля 2011

Я связался с инженером службы поддержки Apple, и он сказал, что одновременное использование AVCaptureVideoDataOutput + AVCaptureMovieFileOutput не поддерживается. Я не знаю, поддержат ли они это в будущем, но он использовал слово «не поддерживается в настоящее время».

Я призываю вас заполнить отчет об ошибке / запрос функции, как я сделал (bugreport.apple.com), поскольку они измеряют, насколько сильно люди хотят чего-то, и мы, возможно, увидим это в ближайшем будущем.

3 голосов
/ 08 октября 2013

Хотя вы не можете использовать AVCaptureVideoDataOutput, вы можете использовать AVCaptureVideoPreviewLayer одновременно с AVCaptureMovieFileOutput. Смотрите пример «AVCam» на сайте Apple.

В Xamarin.iOS код выглядит так:

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