Last active
September 25, 2022 00:42
-
-
Save bgayman/6b27428ea48750e8306975c735bd517e to your computer and use it in GitHub Desktop.
Setup AVCaptureSession with CIFilter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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 | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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?