Record camera output before Vision recognises event

93 views Asked by At

My app recognises an event using Vision and uses CMSampleBuffer to do so. After the event I am recording the video already using AVWriter successfully.

Now I want to record the full motion and thus record 1-2 seconds before the event occurred.

I tried pushing the CMSampleBuffer into a ring buffer, but that starves the camera of buffers.

func captureOutput(_ output: AVCaptureOutput,
                       didOutput sampleBuffer: CMSampleBuffer,
                       from connection: AVCaptureConnection) {
// sends that to detectBall
  /// Gets called by the camera every time there is a new buffer available
 func detectBall(inBuffer buffer: CMSampleBuffer,
                      ballDetectionRequest: VNCoreMLRequest,
                      orientation: CGImagePropertyOrientation,
                      frame: NormalizedPoint,
                      updatingRingBuffer: PassthroughSubject<AppEnvironment.AVState.RingBufferItem, Never>
  ) throws {
    // I tried to convert it into a CVPixelBuffer but its a shallow copy as well so it also starves the camera
    let imageBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer(buffer)!
    /// rotated 90 because of the cameras native landscape orientation
   
    
    let visionHandler = VNImageRequestHandler(ciImage: croppedImage, options: [:])
    try visionHandler.perform([ballDetectionRequest])
    if let results = ballDetectionRequest as? [VNClassificationObservation] {
      // Filter out classification results with low confidence
      let filteredResults = results.filter { $0.confidence > 0.9 }
      guard let topResult = results.first,
            topResult.confidence > 0.9 else { return }
      // print("       its a: \(topResult.identifier)")
      // print("copy buffer")
      
      updatingRingBuffer.send(AppEnvironment.AVState.RingBufferItem(
    /// HERE IS THE PROBLEM: AS SOON AS I SEND IT SOMEWHERE ELSE THE CAMERA IS STARVED
                                buffer: imageBuffer,
                                ball: topResult.identifier == "ball")

How can I achieve to store these 1-2 seconds of video continuously without writing it to disk and then prepending it to the video file?

Thanks!

0

There are 0 answers