-
-
Save ming-chu/7c8429bd7f83beb2e4de5fe0667b158d to your computer and use it in GitHub Desktop.
Setup AVCaptureSession with CIFilter
This file contains hidden or 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 videoOutput = AVCaptureVideoDataOutput() | |
videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue.main) | |
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