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 ↗Code shown on screen · 5 snippets
Optimize QR code scanning
// 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
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
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
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
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
Related sessions
-
20 min -
18 min -
27 min -
15 min -
24 min -
1h 0m