Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2021 Photos & Camera

WWDC21 · 36 min · Photos & Camera

What’s new in camera capture

Learn how you can interact with Video Effects in Control Center including Center Stage, Portrait mode, and Mic modes. We’ll show you how to detect when these features have been enabled for your app and explore ways to adopt custom interfaces to make them controllable from within your app. Discover how to enable 10-bit HDR video capture and take advantage of minimum-focus-distance reporting for improved camera capture experiences. Explore support for IOSurface compression and delivering optimal performance in camera capture. To learn more about camera capture, we also recommend watching "Capture high-quality photos using video formats" from WWDC21.

Watch at developer.apple.com ↗

Transcript all transcripts

Code shown on screen · 5 snippets

Optimize QR code scanning swift · at 0:01 ↗
// Optimize the user experience for scanning QR codes down to sizes of 20mm x 20mm.

let deviceFieldOfView = self.videoDeviceInput.device.activeFormat.videoFieldOfView

let minSubjectDistance = minSubjectDistanceForCode(
  fieldOfView: deviceFieldOfView,
  minimumCodeSize: 20,
  previewFillPercentage: Float(rectOfInterestWidth))
minSubjectDistance swift · at 0:02 ↗
private func minSubjectDistance(
  fieldOfView: Float,
  minimumCodeSize: Float,
  previewFillPercentage: Float) -> Float {
    let radians = degreesToRadians(fieldOfView / 2)
    let filledCodeSize = minimumCodeSize / previewFillPercentage
    return filledCodeSize / tan(radians)
}
Lock device for configuration swift · at 0:03 ↗
let deviceMinimumFocusDistance = Float(self.videoDeviceInput.device.minimumFocusDistance)
if minimumSubjectDistanceForCode < deviceMinimumFocusDistance {
  let zoomFactor = deviceMinimumFocusDistance / minimumSubjectDistanceForCode
  do {
    try videoDeviceInput.device.lockForConfiguration()
    videoDeviceInput.device.videoZoomFactor = CGFloat(zoomFactor)
    videoDeviceInput.device.unlockForConfiguration()
  } catch {
    print("Could not lock for configuration: \(error)")
  }
}
firstTenBitFormatOfDevice swift · at 0:04 ↗
func firstTenBitFormatOfDevice(device: AVCaptureDevice) -> AVCaptureDevice.Format? {
  for format in device.formats {
    let pixelFormat = CMFormatDescriptionGetMediaSubType(format.formatDescription)

    if pixelFormat == kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange /* 'x420' */ {
      return format
    }
  }
  return nil
}
captureOutput swift · at 0:05 ↗
func captureOutput(
  _ output: AVCaptureOutput,
  didDrop sampleBuffer: CMSampleBuffer,
  from connection: AVCaptureConnection) {
    guard let attachment = sampleBuffer.attachments[.droppedFrameReason],
          let reason = attachment.value as? String else { return }
    switch reason as CFString {
    case kCMSampleBufferDroppedFrameReason_FrameWasLate:
      // Handle the late frame case.
      break
    case kCMSampleBufferDroppedFrameReason_OutOfBuffer:
      // Handle the out of buffers case.
      break
    case kCMSampleBufferDroppedFrameReason_Discontinuity:
      // Handle the discontinuity case.
      break
    default:
      fatalError("A frame dropped for an undefined reason.")
    }
}

Resources