2017-01-23 3 views
2

После того, как мы потратили немало времени на проблему без результата, я решил задать ее здесь.Запись видео с использованием AVCaptureVideoDataOutput в Swift 3

Мы используем AVCaptureVideoDataOutput для получения данных о пикселях видео в реальном времени камеры и использования в функции captureOutput. Но мы также хотим записать видео, используя эти данные. Кроме того, мы задаемся вопросом, была ли эта видеозапись сжата так же сильно, как записанное видео, которое было сделано с AVCaptureMovieFileOutput.

Я хотел бы сообщить вам, что используя AVCaptureMovieFileOutput мы сделали запись без проблем. Но AVCaptureMovieFileOutput и AVCaptureVideoDataOutput не работают одновременно.

Здесь вы можете найти функцию captureOutput;

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

    let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)! 

    CVPixelBufferLockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0)) 

    let baseAddress    = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0) 
    let bytesPerRow    = CVPixelBufferGetBytesPerRow(imageBuffer) 
     videoWidth    = CVPixelBufferGetWidth(imageBuffer) 
     videoHeight    = CVPixelBufferGetHeight(imageBuffer) 
    let colorSpace    = CGColorSpaceCreateDeviceRGB() 

    var bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue) 

    let context = CGContext(data: baseAddress, width: videoWidth, height: videoHeight, bitsPerComponent: 8, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo.rawValue) 

    let imageRef = context!.makeImage() 

    CVPixelBufferUnlockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0)) 

    let data = imageRef!.dataProvider!.data as! NSData 
    let pixels = data.bytes.assumingMemoryBound(to: UInt8.self) 


    /* Because what we are doing with pixel data irrelevant to the question we omitted the rest of the code to make it simple */ 




} 

ответ

1

Проведя часть жизни, я нашел, как записывать видео, когда получаю информацию о пикселях, чтобы провести базовый анализ живого видео.

Сначала я устанавливаю AVAssetWriter и вызываю эту функцию, прежде чем указывать фактический порядок записи.

var sampleBufferGlobal : CMSampleBuffer? 
let writerFileName = "tempVideoAsset.mov" 
var presentationTime : CMTime! 
var outputSettings = [String: Any]() 
var videoWriterInput: AVAssetWriterInput! 
var assetWriter: AVAssetWriter! 


func setupAssetWriter() { 

    eraseFile(fileToErase: writerFileName) 

    presentationTime = CMSampleBufferGetPresentationTimeStamp(sampleBufferGlobal!) 

    outputSettings = [AVVideoCodecKey : AVVideoCodecH264, 
         AVVideoWidthKey : NSNumber(value: Float(videoWidth)), 
         AVVideoHeightKey : NSNumber(value: Float(videoHeight))] as [String : Any] 

    videoWriterInput = AVAssetWriterInput(mediaType: AVMediaTypeVideo, outputSettings: outputSettings) 


    assetWriter = try? AVAssetWriter(outputURL: createFileURL(writerFileName), fileType: AVFileTypeQuickTimeMovie) 

    assetWriter.add(videoWriterInput) 

} 

Я написал другую функцию, чтобы сделать запись и называется эту функцию в функции captureOutput, чтобы сделать запись после того, как я скопировал sampleBuffer в sampleBufferGlobal, sampleBufferGlobal = sampleBuffer, в одной и той же функции.

func writeVideoFromData() { 

    if assetWriter?.status == AVAssetWriterStatus.unknown { 

     if ((assetWriter?.startWriting) != nil) { 

      assetWriter?.startWriting() 
      assetWriter?.startSession(atSourceTime: presentationTime) 

     } 
    } 



     if assetWriter?.status == AVAssetWriterStatus.writing { 

      if (videoWriterInput.isReadyForMoreMediaData == true) { 


       if videoWriterInput.append(sampleBufferGlobal!) == false { 

        print(" we have a problem writing video") 

       } 
      } 
     }   
    } 

Тогда, чтобы прекратить запись я использовал нижеследующую функцию.

func stopAssetWriter() { 

    videoWriterInput.markAsFinished() 

    assetWriter?.finishWriting(completionHandler: { 


     if (self.assetWriter?.status == AVAssetWriterStatus.failed) { 

      print("creating movie file is failed ") 

     } else { 

      print(" creating movie file was a success ") 

      DispatchQueue.main.async(execute: {() -> Void in 




      }) 

     } 

    }) 

} 
Смежные вопросы