Skip to content

Instantly share code, notes, and snippets.

@bgayman
Last active September 25, 2022 00:42
Show Gist options
  • Save bgayman/6b27428ea48750e8306975c735bd517e to your computer and use it in GitHub Desktop.
Save bgayman/6b27428ea48750e8306975c735bd517e to your computer and use it in GitHub Desktop.
Setup AVCaptureSession with CIFilter
//
// ViewController.swift
// CameraFilter
//
import UIKit
import AVFoundation
class ViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {
var captureSession = AVCaptureSession()
var backCamera: AVCaptureDevice?
var frontCamera: AVCaptureDevice?
var currentCamera: AVCaptureDevice?
var photoOutput: AVCapturePhotoOutput?
var orientation: AVCaptureVideoOrientation = .portrait
let context = CIContext()
@IBOutlet weak var filteredImage: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
setupDevice()
setupInputOutput()
}
override func viewDidLayoutSubviews() {
orientation = AVCaptureVideoOrientation(rawValue: UIApplication.shared.statusBarOrientation.rawValue)!
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if AVCaptureDevice.authorizationStatus(for: AVMediaType.video) != .authorized
{
AVCaptureDevice.requestAccess(for: AVMediaType.video, completionHandler:
{ (authorized) in
DispatchQueue.main.async
{
if authorized
{
self.setupInputOutput()
}
}
})
}
}
func setupDevice() {
let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera], mediaType: AVMediaType.video, position: AVCaptureDevice.Position.unspecified)
let devices = deviceDiscoverySession.devices
for device in devices {
if device.position == AVCaptureDevice.Position.back {
backCamera = device
}
else if device.position == AVCaptureDevice.Position.front {
frontCamera = device
}
}
currentCamera = backCamera
}
func setupInputOutput() {
do {
setupCorrectFramerate(currentCamera: currentCamera!)
let captureDeviceInput = try AVCaptureDeviceInput(device: currentCamera!)
captureSession.sessionPreset = AVCaptureSession.Preset.hd1280x720
if captureSession.canAddInput(captureDeviceInput) {
captureSession.addInput(captureDeviceInput)
}
let videoOutput = AVCaptureVideoDataOutput()
videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "sample buffer delegate", attributes: []))
if captureSession.canAddOutput(videoOutput) {
captureSession.addOutput(videoOutput)
}
captureSession.startRunning()
} catch {
print(error)
}
}
func setupCorrectFramerate(currentCamera: AVCaptureDevice) {
for vFormat in currentCamera.formats {
//see available types
//print("\(vFormat) \n")
var ranges = vFormat.videoSupportedFrameRateRanges as [AVFrameRateRange]
let frameRates = ranges[0]
do {
//set to 240fps - available types are: 30, 60, 120 and 240 and custom
// lower framerates cause major stuttering
if frameRates.maxFrameRate == 240 {
try currentCamera.lockForConfiguration()
currentCamera.activeFormat = vFormat as AVCaptureDevice.Format
//for custom framerate set min max activeVideoFrameDuration to whatever you like, e.g. 1 and 180
currentCamera.activeVideoMinFrameDuration = frameRates.minFrameDuration
currentCamera.activeVideoMaxFrameDuration = frameRates.maxFrameDuration
}
}
catch {
print("Could not set active format")
print(error)
}
}
}
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
connection.videoOrientation = orientation
let comicEffect = CIFilter(name: "CIComicEffect")
let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
let cameraImage = CIImage(cvImageBuffer: pixelBuffer!)
comicEffect!.setValue(cameraImage, forKey: kCIInputImageKey)
let cgImage = self.context.createCGImage(comicEffect!.outputImage!, from: cameraImage.extent)!
DispatchQueue.main.async {
let filteredImage = UIImage(cgImage: cgImage)
self.filteredImage.image = filteredImage
}
}
}
@chunibyo-wly
Copy link

Hello, thanks for your example code.
But I have a question is that function captureOutput maximum frate is only 30 when I set device frame rates to 240?
Do you have a same question?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment