Skip to content

Commit

Permalink
Update remaining methods to be objc compatible
Browse files Browse the repository at this point in the history
Update readme
  • Loading branch information
Adrian Mateoaea committed Feb 18, 2019
1 parent fc6313d commit 54ef1ff
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 77 deletions.
81 changes: 36 additions & 45 deletions CameraKit/CameraKit/CKPhotoSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ extension CKSession.FlashMode {
case none, faces
}

public typealias CaptureCallback = (UIImage?, AVCaptureResolvedPhotoSettings?, CKError?) -> Void

@objc public var cameraPosition = CameraPosition.back {
didSet {
do {
Expand Down Expand Up @@ -83,7 +81,6 @@ extension CKSession.FlashMode {

let photoOutput = AVCapturePhotoOutput()

var captureCallback: CaptureCallback?
var faceDetectionBoxes: [UIView] = []

@objc public init(position: CameraPosition = .back, detection: CameraDetection = .none) {
Expand All @@ -102,13 +99,16 @@ extension CKSession.FlashMode {
self.faceDetectionBoxes.forEach({ $0.removeFromSuperview() })
}

// TODO: Fix mark as @objc
public func capture(_ callback: @escaping CaptureCallback) {
var captureCallback: (UIImage, AVCaptureResolvedPhotoSettings) -> Void = { (_, _) in }
var errorCallback: (Error) -> Void = { (_) in }

@objc public func capture(_ callback: @escaping (UIImage, AVCaptureResolvedPhotoSettings) -> Void, _ error: @escaping (Error) -> Void) {
self.captureCallback = callback

self.errorCallback = error

let settings = AVCapturePhotoSettings()
settings.flashMode = self.flashMode.captureFlashMode

self.photoOutput.capturePhoto(with: settings, delegate: self)
}

Expand Down Expand Up @@ -136,8 +136,7 @@ extension CKSession.FlashMode {
}
}

// TODO: Fix mark as @objc
public var resolution: CGSize? {
@objc public var resolution = CGSize.zero {
didSet {
guard let deviceInput = self.captureDeviceInput else {
return
Expand All @@ -147,8 +146,8 @@ extension CKSession.FlashMode {
try deviceInput.device.lockForConfiguration()

if
let resolution = self.resolution,
let format = CKSession.deviceInputFormat(input: deviceInput, width: Int(resolution.width), height: Int(resolution.height))
self.resolution.width > 0, self.resolution.height > 0,
let format = CKSession.deviceInputFormat(input: deviceInput, width: Int(self.resolution.width), height: Int(self.resolution.height))
{
deviceInput.device.activeFormat = format
} else {
Expand Down Expand Up @@ -176,73 +175,65 @@ extension CKSession.FlashMode {
}

@available(iOS 11.0, *)
private func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {

guard let captureCallback = self.captureCallback else {
return
public func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
defer {
self.captureCallback = { (_, _) in }
self.errorCallback = { (_) in }
}

defer { self.captureCallback = nil }


if let error = error {
captureCallback(nil, nil, CKError.error(error.localizedDescription))
self.errorCallback(error)
return
}

guard let data = photo.fileDataRepresentation() else {
captureCallback(nil, nil, CKError.error("Cannot get photo file data representation"))
self.errorCallback(CKError.error("Cannot get photo file data representation"))
return
}

self.processPhotoData(data: data, resolvedSettings: photo.resolvedSettings)
}

private func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photoSampleBuffer: CMSampleBuffer?, previewPhoto previewPhotoSampleBuffer: CMSampleBuffer?, resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Error?) {

guard let captureCallback = self.captureCallback else {
return
public func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photoSampleBuffer: CMSampleBuffer?, previewPhoto previewPhotoSampleBuffer: CMSampleBuffer?, resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Error?) {
defer {
self.captureCallback = { (_, _) in }
self.errorCallback = { (_) in }
}

defer { self.captureCallback = nil }


if let error = error {
captureCallback(nil, nil, CKError.error(error.localizedDescription))
self.errorCallback(error)
return
}

guard
let photoSampleBuffer = photoSampleBuffer, let previewPhotoSampleBuffer = previewPhotoSampleBuffer,
let data = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: photoSampleBuffer, previewPhotoSampleBuffer: previewPhotoSampleBuffer) else
{
captureCallback(nil, nil, CKError.error("Cannot get photo file data representation"))
self.errorCallback(CKError.error("Cannot get photo file data representation"))
return
}

self.processPhotoData(data: data, resolvedSettings: resolvedSettings)
}

private func processPhotoData(data: Data, resolvedSettings: AVCaptureResolvedPhotoSettings) {
guard let captureCallback = self.captureCallback else {
return
}

guard let image = UIImage(data: data) else {
captureCallback(nil, nil, CKError.error("Cannot get photo"))
self.errorCallback(CKError.error("Cannot get photo"))
return
}

if
let resolution = self.resolution,
let transformedImage = CKUtils.cropAndScale(image, width: Int(resolution.width), height: Int(resolution.height))
self.resolution.width > 0, self.resolution.height > 0,
let transformedImage = CKUtils.cropAndScale(image, width: Int(self.resolution.width), height: Int(self.resolution.height))
{
captureCallback(transformedImage, resolvedSettings, nil)
self.captureCallback(transformedImage, resolvedSettings)
return
}
captureCallback(image, resolvedSettings, nil)

self.captureCallback(image, resolvedSettings)
}

private func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
public func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
let faceMetadataObjects = metadataObjects.filter({ $0.type == .face })

if faceMetadataObjects.count > self.faceDetectionBoxes.count {
Expand Down
3 changes: 1 addition & 2 deletions CameraKit/CameraKit/CKPreviewView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ import AVFoundation
}
}

// TODO: Fix mark as @objc
private(set) public var gridView: CKGridView? {
@objc private(set) public var gridView: CKGridView? {
didSet {
oldValue?.removeFromSuperview()

Expand Down
23 changes: 11 additions & 12 deletions CameraKit/CameraKit/CKVideoSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ extension CKSession.FlashMode {

@objc public class CKVideoSession: CKSession, AVCaptureFileOutputRecordingDelegate {

public typealias RecordCallback = (URL?, CKError?) -> Void

@objc public private(set) var isRecording = false

@objc public var cameraPosition = CameraPosition.back {
Expand Down Expand Up @@ -88,8 +86,6 @@ extension CKSession.FlashMode {

let movieOutput = AVCaptureMovieFileOutput()

var recordCallback: RecordCallback?

@objc public init(position: CameraPosition = .back) {
super.init()

Expand All @@ -108,10 +104,14 @@ extension CKSession.FlashMode {
self.session.addOutput(self.movieOutput)
}

// TODO: Fix mark as @objc
public func record(url: URL? = nil, _ callback: @escaping RecordCallback) {
var recordCallback: (URL) -> Void = { (_) in }
var errorCallback: (Error) -> Void = { (_) in }

@objc public func record(url: URL? = nil, _ callback: @escaping (URL) -> Void, error: @escaping (Error) -> Void) {
if self.isRecording { return }

self.recordCallback = callback
self.errorCallback = error

let fileUrl: URL = url ?? {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
Expand Down Expand Up @@ -158,17 +158,16 @@ extension CKSession.FlashMode {
public func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
self.isRecording = false

guard let recordCallback = self.recordCallback else {
return
defer {
self.recordCallback = { (_) in }
self.errorCallback = { (_) in }
}

defer { self.recordCallback = nil }

if let error = error {
recordCallback(nil, CKError.error(error.localizedDescription))
self.errorCallback(error)
return
}

recordCallback(outputFileURL, nil)
self.recordCallback(outputFileURL)
}
}
3 changes: 1 addition & 2 deletions CameraKitDemo-Objc/CameraKitDemo-Objc/ViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>

@import CameraKit;

@interface ViewController ()
Expand All @@ -25,8 +26,6 @@ - (void)viewDidLoad {

CKPhotoSession *session = [[CKPhotoSession alloc] initWithPosition:CameraPositionBack detection:CameraDetectionNone];
previewView.session = session;
previewView.showGrid = YES;
}


@end
4 changes: 3 additions & 1 deletion CameraKitDemo/CameraKitDemo/PhotoViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,10 @@ class PhotoViewController: UIViewController, CKSessionDelegate {

@IBAction func handleCapture(_ sender: Any) {
if let session = self.previewView.session as? CKPhotoSession {
session.capture { (image, _, _) in
session.capture({ (image, _) in
self.performSegue(withIdentifier: "Preview", sender: image)
}) { (_) in
//
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion CameraKitDemo/CameraKitDemo/VideoViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,10 @@ class VideoViewController: UIViewController, CKSessionDelegate {
session.stopRecording()
} else {
sender.backgroundColor = UIColor.red
session.record { (url, _) in
session.record({ (url) in
self.performSegue(withIdentifier: "Preview", sender: url)
}) { (_) in
//
}
}
}
Expand Down
38 changes: 24 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,17 +125,21 @@ override func viewDidLoad() {
For capturing a image using the `CKPhotoSession` class use this code below:

```swift
session.capture { (image, settings, error) in
session.capture({ (image, settings) in
// TODO: Add your code here
}) { (error) in
// TODO: Handle error
}
```

If you want to record a video using the `CKVideoSession` class use this code below to start the recording:

```swift
// You can also specify a custom url for where to save the video file
session.record() { (url, error) in
session.record(url: URL(string: ""), { (url) in
// TODO: Add your code here
}) { (error) in
// TODO: Handle error
}
```

Expand All @@ -150,23 +154,29 @@ You can get the current record status via the `isRecording` property to determin

# Session properties and methods

| CKPhotoSession | CKVideoSession |
|--------------------------------------------------|-----------------------------------------------------------------|
| `zoom: Double` | `zoom: Double` |
| `resolution: CGSize?` | `isRecording: Bool` |
| `cameraPosition: CameraPosition` | `cameraPosition: CameraPosition` |
| `cameraDetection: CameraDetection` | `flashMode: FlashMode` |
| `flashMode: FlashMode` | `start()` |
| `start()` | `stop()` |
| `stop()` | `togglePosition()` |
| `focus(at point: CGPoint)` | `setWidth(_ width: Int, height: Int, frameRate: Int)` |
| `togglePosition()` | `record(url: URL? = nil, _ callback: @escaping RecordCallback)` |
| `capture(_ callback: @escaping CaptureCallback)` | `stopRecording()` |
| CKPhotoSession | CKVideoSession |
|----------------|----------------|
| `zoom: Double` | `zoom: Double` |
| `resolution: CGSize` | `isRecording: Bool` |
| `cameraPosition: CameraPosition` | `cameraPosition: CameraPosition` |
| `cameraDetection: CameraDetection` | `flashMode: FlashMode` |
| `flashMode: FlashMode` | `start()` |
| `start()` | `stop()` |
| `stop()` | `togglePosition()` |
| `focus(at point: CGPoint)` | `setWidth(_ width: Int, height: Int, frameRate: Int)` |
| `togglePosition()` | `record(url: URL? = nil, _ callback: @escaping (URL) -> Void, error: @escaping (Error) -> Void)` |
| `capture(_ callback: @escaping (UIImage, AVCaptureResolvedPhotoSettings) -> Void, _ error: @escaping (Error) -> Void)` | `stopRecording()` |

# Import into Objective-C projects

Go to `Project Settings`, `Build Settings`, `Always Embed Swift Standard Libraries` and set the value to `Yes`.

Then import the CameraKit framework using:

```objc
@import CameraKit;
```

# Creating custom sessions

CameraKit can be splitted into 2 main pieces: preview and sessions. The sessions are made by extending the base `CKSession` class. If you want a custom session you can extend the `CKSession` class and use its static helpers to initialize yours. Or you can also extend the built-in sessions and add custom logic.
Expand Down

0 comments on commit 54ef1ff

Please sign in to comment.