2017-06-18 11 views
2

誰でも私にAVFoundationのキューを使用する際のガイダンスを教えていただけますか?AVAssetWriterキューの推測Swift 3

後で私のアプリケーションでは、私はAVCaptureVideoDataOutputを使用する必要があるので、個々のフレームでいくつかの処理を行いたいと思います。

AVAssetWriterを使用してイメージをキャプチャして(未処理のまま)書き込むと思って始めました。

私は成功し、次のようにAVCaptureセッションを設定することにより、カメラからの画像プレビューにフレームをストリーミングしています

func initializeCameraAndMicrophone() { 

// set up the captureSession 
    captureSession = AVCaptureSession() 
    captureSession.sessionPreset = AVCaptureSessionPreset1280x720 // set resolution to Medium 

// set up the camera 
    let camera = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo) 

    do { 
     let cameraInput = try AVCaptureDeviceInput(device: camera) 
     if captureSession.canAddInput(cameraInput){ 
      captureSession.addInput(cameraInput) 
     } 
    } catch { 
     print("Error setting device camera input: \(error)") 
     return 
    } 

    videoOutputStream.setSampleBufferDelegate(self, queue: DispatchQueue(label: "sampleBuffer", attributes: [])) 

    if captureSession.canAddOutput(videoOutputStream) 
    { 
     captureSession.addOutput(videoOutputStream) 
    } 

    captureSession.startRunning() 


} 

それぞれの新しいフレームは、その後captureOutput委任をトリガー:

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

    let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) 
    let cameraImage = CIImage(cvPixelBuffer: pixelBuffer!) 
    let bufferImage = UIImage(ciImage: cameraImage) 

    DispatchQueue.main.async 
     { 

     // send captured frame to the videoPreview 
     self.videoPreview.image = bufferImage 


     // if recording is active append bufferImage to video frame 
     while (recordingNow == true){ 

      print("OK we're recording!") 

      /// Append images to video 
      while (writerInput.isReadyForMoreMediaData) { 

       let lastFrameTime = CMTimeMake(Int64(frameCount), videoFPS) 
       let presentationTime = frameCount == 0 ? lastFrameTime : CMTimeAdd(lastFrameTime, frameDuration) 

       pixelBufferAdaptor.append(pixelBuffer!, withPresentationTime: presentationTime) 


       frameCount += 1    
      } 
     } 
    } 
} 

だから、これはフレームをストリーム「startVideoRecording」関数(AVAssetWriterを設定する)を呼び出すレコードボタンを押すまで、イメージプレビューに完全に渡します。デリゲートのその点から、再び呼び出されることはありません!

AVAssetWriterは次のように設定されている:

func startVideoRecording() { 


    guard let assetWriter = createAssetWriter(path: filePath!, size: videoSize) else { 
     print("Error converting images to video: AVAssetWriter not created") 
     return 
    } 

    // AVAssetWriter exists so create AVAssetWriterInputPixelBufferAdaptor 
    let writerInput = assetWriter.inputs.filter{ $0.mediaType == AVMediaTypeVideo }.first! 


    let sourceBufferAttributes : [String : AnyObject] = [ 
     kCVPixelBufferPixelFormatTypeKey as String : Int(kCVPixelFormatType_32ARGB) as AnyObject, 
     kCVPixelBufferWidthKey as String : videoSize.width as AnyObject, 
     kCVPixelBufferHeightKey as String : videoSize.height as AnyObject, 
     ] 

    let pixelBufferAdaptor = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: writerInput, sourcePixelBufferAttributes: sourceBufferAttributes) 

    // Start writing session 
    assetWriter.startWriting() 
    assetWriter.startSession(atSourceTime: kCMTimeZero) 
    if (pixelBufferAdaptor.pixelBufferPool == nil) { 
     print("Error converting images to video: pixelBufferPool nil after starting session") 

     assetWriter.finishWriting{ 
      print("assetWritter stopped!") 
     } 
     recordingNow = false 

     return 
    } 

    frameCount = 0 

    print("Recording started!") 

} 

私はAVFoundationに新しいですが、私は、私はどこかで自分のキューを台無しだと思います。私は何時間もこれを見てきたので、何か助けやヒントが大いにありがとう!

答えて

1

ビデオ/オーディオのキャプチャに別のシリアルキューを使用する必要があります。

  1. あなたのクラスにこのキューのプロパティを追加します。

    let captureSessionQueue: DispatchQueue = DispatchQueue(label: "sampleBuffer", attributes: []) 
    
  2. は、Appleのドキュメントによると、captureSessionQueue上でセッションを開始し

    : startRunning()メソッドは、いくつかの時間がかかることがブロッキング呼び出しですしたがって、 シリアルキューでセッションセットアップを実行して、メインキューがブロックされないようにする必要があります(UIを応答可能に保ちます)。

    captureSessionQueue.async { 
        captureSession.startRunning() 
    } 
    
  3. キャプチャ出力ピクセルバッファデリゲートに設定されたこのキューを:captureSessionQueue内部

    videoOutputStream.setSampleBufferDelegate(self, queue: captureSessionQueue) 
    
  4. コールstartVideoRecording:captureOutputのデリゲートメソッドで

    captureSessionQueue.async { 
        startVideoRecording() 
    } 
    
  5. はすべてAVFoundationメソッド呼び出しを置きますcaptureSessionQueue.asyncに:

    DispatchQueue.main.async 
        { 
    
        // send captured frame to the videoPreview 
        self.videoPreview.image = bufferImage 
    
        captureSessionQueue.async { 
         // if recording is active append bufferImage to video frame 
         while (recordingNow == true){ 
    
          print("OK we're recording!") 
    
          /// Append images to video 
          while (writerInput.isReadyForMoreMediaData) { 
    
           let lastFrameTime = CMTimeMake(Int64(frameCount), videoFPS) 
           let presentationTime = frameCount == 0 ? lastFrameTime : CMTimeAdd(lastFrameTime, frameDuration) 
    
           pixelBufferAdaptor.append(pixelBuffer!, withPresentationTime: presentationTime) 
    
    
           frameCount += 1    
          } 
         } 
        } 
    }