2017-03-06 36 views
0

我正在使用基本viewController封装的摄像头,它具有用于回调的委托样式接口,所以我必须作为客户端执行的所有操作都是子类相机视图控制器,实现委托方法,并添加UI按钮。 我的问题是关于录制视频。视频录制在独特的后台任务上启动,以确保录制内容可以写入临时文件。这是对我的 private let sessionQueue = DispatchQueue(label: "com.andrewferrarone.sessionQueue")会话队列完成:从另一个队列派发代表回调到主队列AVFoundation

public func startRecording() 
{ 
    guard let movieFileOutput = self.movieFileOutput else { return } 

    //get video preview layer's video orientation on main queue 
    guard let videoPreviewLayerOrientation = self.previewView.videoPreviewLayer?.connection.videoOrientation else { 
     print("handleRecord: videoPreviewLayer is nil") 
     return 
    } 

    self.sessionQueue.async { 

     if !movieFileOutput.isRecording { 
      if UIDevice.current.isMultitaskingSupported { 

       self.backgroundRecordingID = UIApplication.shared.beginBackgroundTask(expirationHandler: nil) 
     } 

     //update orientation on the movie file output video connection before recording 
     let movieFileOutputConnection = self.movieFileOutput?.connection(withMediaType: AVMediaTypeVideo) 
      movieFileOutputConnection?.videoOrientation = videoPreviewLayerOrientation 

     //start recording to a temporary file: 
     let outputFileName = UUID().uuidString 
     let outputFilePath = (NSTemporaryDirectory() as NSString).appendingPathComponent((outputFileName as NSString).appendingPathExtension("mov")!) 
      movieFileOutput.startRecording(toOutputFileURL: URL(fileURLWithPath: outputFilePath), recordingDelegate: self) 
     } 
    } 
} 

所以录音效果设置为后台任务分派到self.sessionQueue。当我停止录制时,我收到一个AVCaptureFileOutputRecordingDelegate方法。在这种方法中,我想用文件路径回调我的委托,然后清理。如何在清除发生并删除临时文件之前,确保委托可以从临时文件路径持续记录?

public func capture(_ captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAt outputFileURL: URL!, fromConnections connections: [Any]!, error: Error!) 
{ 
    //cleanup func for later 
    func cleanup() 
    { 
     let path = outputFileURL.path 

     if FileManager.default.fileExists(atPath: path) { 
      do { 
       try FileManager.default.removeItem(atPath: path) 
      } 
      catch let error { 
       print("Could not remove file at url: \(outputFileURL), error: \(error.localizedDescription)") 
      } 
     } 

     if let currentBackgroundRecordingID = self.backgroundRecordingID { 
      self.backgroundRecordingID = UIBackgroundTaskInvalid 

      if currentBackgroundRecordingID != UIBackgroundTaskInvalid { 
       UIApplication.shared.endBackgroundTask(currentBackgroundRecordingID) 
      } 
     } 
    } 

    var success = true 

    if error != nil { 
     print("Movie file finishing error: \(error)") 
     success = ((error as NSError).userInfo[AVErrorRecordingSuccessfullyFinishedKey] as AnyObject).boolValue 
    } 

    DispatchQueue.main.async { 
     self.delegate?.camera(self, didFinishRecordingToOutputFileAt: outputFileURL, success: success) 
    } 

    cleanup() 
} 

所以我打电话给我的委托回到主队列的结果,但我需要调用cleanup()我应该叫回我的委托后立即做这个主队列?这是安全的吗?或者如果我以现在的方式离开它,那么我们在self.sessionQueue,我不确定cleanup()将在代表方法实现有时间持续记录之前发生。如果任何人都能给我一些关于正在发生的事情以及在这里最安全的事情的见解,那将会很棒。根据苹果,文档说,不要假设AVCaptureFileOutputRecordingDelegate didFinishRecordingToOutputFileAt方法在特定的线程上被调用。感谢您的时间和帮助!

回答

1

如何:

DispatchQueue.main.async { 
    self.delegate?.camera(self, didFinishRecordingToOutputFileAt: outputFileURL, success: success) 
    self.sessionQueue.async { 
     cleanup() 
    } 
} 

我认为这将是处理这种情况的标准方式。委托方法完成后,您认为委托已完成该文件(或将其复制到其他位置)。

相关问题