Vraag Kan AVCaptureVideoDataOutput en AVCaptureMovieFileOutput tegelijkertijd worden gebruikt?


Ik wil video opnemen en frames tegelijk bekijken met mijn code.

ik gebruik AVCaptureVideoDataOutput voor grab frames en AVCaptureMovieFileOutput voor video-opnames. Maar kan niet werken en krijg de foutcode -12780 terwijl hij op hetzelfde moment maar individueel werkt.

Ik heb dit probleem doorzocht maar krijg geen antwoord. Heeft iemand dezelfde ervaring of verklaring gehad? Het stoort me echt een tijdje.

bedankt.


29
2018-02-09 11:14


oorsprong


antwoorden:


Ik kan de specifieke vraag niet beantwoorden, maar ik heb met succes video's opgenomen en frames tegelijkertijd opgenomen met behulp van:

  • AVCaptureSession en AVCaptureVideoDataOutput om frames naar mijn eigen code te routeren
  • AVAssetWriter, AVAssetWriterInput en AVAssetWriterInputPixelBufferAdaptor om frames uit te schrijven naar een H.264-gecodeerd filmbestand

Dat is zonder audio te onderzoeken. Ik krijg uiteindelijk CMSampleBuffers van de opnamesessie en vervolgens in de pixelbufferadapter te duwen.

BEWERK: dus mijn code ziet er min of meer uit, met de stukjes heb je geen problemen met overrompeld worden en het negeren van kwesties van bereik:

/* to ensure I'm given incoming CMSampleBuffers */
AVCaptureSession *captureSession = alloc and init, set your preferred preset/etc;
AVCaptureDevice *captureDevice = default for video, probably;

AVCaptureDeviceInput *deviceInput = input with device as above, 
                                    and attach it to the session;

AVCaptureVideoDataOutput *output = output for 32BGRA pixel format, with me as the
                                   delegate and a suitable dispatch queue affixed.

/* to prepare for output; I'll output 640x480 in H.264, via an asset writer */
NSDictionary *outputSettings =
    [NSDictionary dictionaryWithObjectsAndKeys:

            [NSNumber numberWithInt:640], AVVideoWidthKey,
            [NSNumber numberWithInt:480], AVVideoHeightKey,
            AVVideoCodecH264, AVVideoCodecKey,

            nil];

AVAssetWriterInput *assetWriterInput = [AVAssetWriterInput 
                                   assetWriterInputWithMediaType:AVMediaTypeVideo
                                                  outputSettings:outputSettings];

/* I'm going to push pixel buffers to it, so will need a 
   AVAssetWriterPixelBufferAdaptor, to expect the same 32BGRA input as I've
   asked the AVCaptureVideDataOutput to supply */
AVAssetWriterInputPixelBufferAdaptor *pixelBufferAdaptor =
           [[AVAssetWriterInputPixelBufferAdaptor alloc] 
                initWithAssetWriterInput:assetWriterInput 
                sourcePixelBufferAttributes:
                     [NSDictionary dictionaryWithObjectsAndKeys:
                          [NSNumber numberWithInt:kCVPixelFormatType_32BGRA], 
                           kCVPixelBufferPixelFormatTypeKey,
                     nil]];

/* that's going to go somewhere, I imagine you've got the URL for that sorted,
   so create a suitable asset writer; we'll put our H.264 within the normal
   MPEG4 container */
AVAssetWriter *assetWriter = [[AVAssetWriter alloc]
                                initWithURL:URLFromSomwhere
                                fileType:AVFileTypeMPEG4
                                error:you need to check error conditions,
                                      this example is too lazy];
[assetWriter addInput:assetWriterInput];

/* we need to warn the input to expect real time data incoming, so that it tries
   to avoid being unavailable at inopportune moments */
assetWriterInput.expectsMediaDataInRealTime = YES;

... eventually ...

[assetWriter startWriting];
[assetWriter startSessionAtSourceTime:kCMTimeZero];
[captureSession startRunning];

... elsewhere ...

- (void)        captureOutput:(AVCaptureOutput *)captureOutput 
    didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
           fromConnection:(AVCaptureConnection *)connection
{
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);

    // a very dense way to keep track of the time at which this frame
    // occurs relative to the output stream, but it's just an example!
    static int64_t frameNumber = 0;
    if(assetWriterInput.readyForMoreMediaData)
        [pixelBufferAdaptor appendPixelBuffer:imageBuffer
                         withPresentationTime:CMTimeMake(frameNumber, 25)];
    frameNumber++;
}

... and, to stop, ensuring the output file is finished properly ...

[captureSession stopRunning];
[assetWriter finishWriting];

49
2018-02-09 12:03



Dit is een snelle versie van Tommy's antwoord.

 // Set up the Capture Session 
 // Add the Inputs 
 // Add the Outputs


 var outputSettings = [
    AVVideoWidthKey : Int(640),
    AVVideoHeightKey : Int(480),
    AVVideoCodecKey : .h264
]

    var assetWriterInput = AVAssetWriterInput(mediaType: AVMediaTypeVideo,outputSettings: outputSettings)

    var pixelBufferAdaptor = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput, sourcePixelBufferAttributes:
        [ kCVPixelBufferPixelFormatTypeKey : Int(kCVPixelFormatType_32BGRA)])


     var assetWriter = AVAssetWriter(url: URLFromSomwhere, fileType: AVFileTypeMPEG4 , error : Error )
         assetWriter.addInput(assetWriterInput)
         assetWriterInput.expectsMediaDataInRealTime = true
         assetWriter.startWriting()
         assetWriter.startSession(atSourceTime: kCMTimeZero)

    captureSession.startRunning()


  func captureOutput(_ captureOutput: AVCaptureOutput, didOutputSampleBuffer sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {

    var imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
    // a very dense way to keep track of the time at which this frame
    // occurs relative to the output stream, but it's just an example!
    var frameNumber: Int64 = 0

           if assetWriterInput.readyForMoreMediaData {
    pixelBufferAdaptor.appendPixelBuffer(imageBuffer, withPresentationTime: CMTimeMake(frameNumber, 25))
               }
                frameNumber += 1   }

      captureSession.stopRunning()
      assetWriter.finishWriting()

Ik garandeer echter geen 100% nauwkeurigheid, want ik ben nieuw om snel te zijn.


1
2018-01-05 11:14