Commit 0dfcc81b by Daniel Dahan

Capture now supports video

parent 60626aba
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
import UIKit import UIKit
import MaterialKit import MaterialKit
import AVFoundation
class ViewController: UIViewController, CaptureSessionDelegate { class ViewController: UIViewController, CaptureSessionDelegate {
private lazy var captureView: CaptureView = CaptureView() private lazy var captureView: CaptureView = CaptureView()
...@@ -50,7 +51,7 @@ class ViewController: UIViewController, CaptureSessionDelegate { ...@@ -50,7 +51,7 @@ class ViewController: UIViewController, CaptureSessionDelegate {
btn1.pulseFill = true btn1.pulseFill = true
btn1.setImage(img1, forState: .Normal) btn1.setImage(img1, forState: .Normal)
btn1.setImage(img1, forState: .Highlighted) btn1.setImage(img1, forState: .Highlighted)
btn1.addTarget(self, action: "handleFlash:", forControlEvents: .TouchUpInside) btn1.addTarget(self, action: "handleFlashButton:", forControlEvents: .TouchUpInside)
let img2: UIImage? = UIImage(named: "ic_switch_camera_white") let img2: UIImage? = UIImage(named: "ic_switch_camera_white")
let btn2: FlatButton = FlatButton() let btn2: FlatButton = FlatButton()
...@@ -58,6 +59,7 @@ class ViewController: UIViewController, CaptureSessionDelegate { ...@@ -58,6 +59,7 @@ class ViewController: UIViewController, CaptureSessionDelegate {
btn2.pulseFill = true btn2.pulseFill = true
btn2.setImage(img2, forState: .Normal) btn2.setImage(img2, forState: .Normal)
btn2.setImage(img2, forState: .Highlighted) btn2.setImage(img2, forState: .Highlighted)
btn2.addTarget(self, action: "handleSwitchCameraButton:", forControlEvents: .TouchUpInside)
let img3: UIImage? = UIImage(named: "ic_close_white") let img3: UIImage? = UIImage(named: "ic_close_white")
let btn3: FlatButton = FlatButton() let btn3: FlatButton = FlatButton()
...@@ -74,6 +76,7 @@ class ViewController: UIViewController, CaptureSessionDelegate { ...@@ -74,6 +76,7 @@ class ViewController: UIViewController, CaptureSessionDelegate {
captureButton.shadowDepth = .None captureButton.shadowDepth = .None
captureButton.setImage(img4, forState: .Normal) captureButton.setImage(img4, forState: .Normal)
captureButton.setImage(img4, forState: .Highlighted) captureButton.setImage(img4, forState: .Highlighted)
captureButton.addTarget(self, action: "handleCaptureButton:", forControlEvents: .TouchUpInside)
captureView.captureSession.delegate = self captureView.captureSession.delegate = self
captureView.captureButton = captureButton captureView.captureButton = captureButton
...@@ -94,7 +97,28 @@ class ViewController: UIViewController, CaptureSessionDelegate { ...@@ -94,7 +97,28 @@ class ViewController: UIViewController, CaptureSessionDelegate {
navigationBarView.rightButtons = [btn1, btn2] navigationBarView.rightButtons = [btn1, btn2]
} }
internal func handleFlash(sender: AnyObject) { /**
:name: handleCaptureButton
*/
internal func handleCaptureButton(button: UIButton) {
if captureView.captureSession.isRecording {
captureView.captureSession.stopRecording()
} else {
captureView.captureSession.startRecording()
}
}
/**
:name: handleSwitchCameraButton
*/
internal func handleSwitchCameraButton(button: UIButton) {
captureView.captureSession.switchCameras()
}
/**
:name: handleFlashButton
*/
internal func handleFlashButton(sender: AnyObject) {
var img: UIImage? var img: UIImage?
switch captureView.captureSession.flashMode { switch captureView.captureSession.flashMode {
...@@ -123,9 +147,32 @@ class ViewController: UIViewController, CaptureSessionDelegate { ...@@ -123,9 +147,32 @@ class ViewController: UIViewController, CaptureSessionDelegate {
print(error) print(error)
} }
func captureStillImageAsynchronously(capture: CaptureSession, image: UIImage?, error: NSError?) { /**
print(image) :name: captureStillImageAsynchronously
print(error) */
func captureStillImageAsynchronously(capture: CaptureSession, image: UIImage) {
print("Capture Image \(image)")
}
/**
:name: captureCreateMovieFileFailedWithError
*/
func captureCreateMovieFileFailedWithError(capture: CaptureSession, error: NSError) {
print("Capture Failed \(error)")
}
/**
:name: captureDidStartRecordingToOutputFileAtURL
*/
func captureDidStartRecordingToOutputFileAtURL(capture: CaptureSession, captureOutput: AVCaptureFileOutput, fileURL: NSURL, fromConnections connections: [AnyObject]) {
print("Capture Started Recording")
}
/**
:name: captureDidFinishRecordingToOutputFileAtURL
*/
func captureDidFinishRecordingToOutputFileAtURL(capture: CaptureSession, captureOutput: AVCaptureFileOutput, outputFileURL: NSURL, fromConnections connections: [AnyObject], error: NSError!) {
print("Capture Stopped Recording")
} }
} }
...@@ -45,11 +45,36 @@ public protocol CaptureSessionDelegate { ...@@ -45,11 +45,36 @@ public protocol CaptureSessionDelegate {
/** /**
:name: captureStillImageAsynchronously :name: captureStillImageAsynchronously
*/ */
optional func captureStillImageAsynchronously(capture: CaptureSession, image: UIImage?, error: NSError?) optional func captureStillImageAsynchronously(capture: CaptureSession, image: UIImage)
/**
:name: captureStillImageAsynchronouslyFailedWithError
*/
optional func captureStillImageAsynchronouslyFailedWithError(capture: CaptureSession, error: NSError)
/**
:name: captureCreateMovieFileFailedWithError
*/
optional func captureCreateMovieFileFailedWithError(capture: CaptureSession, error: NSError)
/**
:name: captureMovieFailedWithError
*/
optional func captureMovieFailedWithError(capture: CaptureSession, error: NSError)
/**
:name: captureDidStartRecordingToOutputFileAtURL
*/
optional func captureDidStartRecordingToOutputFileAtURL(capture: CaptureSession, captureOutput: AVCaptureFileOutput, fileURL: NSURL, fromConnections connections: [AnyObject])
/**
:name: captureDidFinishRecordingToOutputFileAtURL
*/
optional func captureDidFinishRecordingToOutputFileAtURL(capture: CaptureSession, captureOutput: AVCaptureFileOutput, outputFileURL: NSURL, fromConnections connections: [AnyObject], error: NSError!)
} }
@objc(CaptureSession) @objc(CaptureSession)
public class CaptureSession : NSObject { public class CaptureSession : NSObject, AVCaptureFileOutputRecordingDelegate {
/** /**
:name: videoQueue :name: videoQueue
*/ */
...@@ -86,6 +111,16 @@ public class CaptureSession : NSObject { ...@@ -86,6 +111,16 @@ public class CaptureSession : NSObject {
public private(set) lazy var isRunning: Bool = false public private(set) lazy var isRunning: Bool = false
/** /**
:name: isRecording
*/
public private(set) lazy var isRecording: Bool = false
/**
:name: movieOutputURL
*/
public private(set) var movieOutputURL: NSURL?
/**
:name: activeCamera :name: activeCamera
*/ */
public var activeCamera: AVCaptureDevice? { public var activeCamera: AVCaptureDevice? {
...@@ -451,11 +486,62 @@ public class CaptureSession : NSObject { ...@@ -451,11 +486,62 @@ public class CaptureSession : NSObject {
imageOutput.captureStillImageAsynchronouslyFromConnection(connection) { (sampleBuffer: CMSampleBuffer!, error: NSError!) -> Void in imageOutput.captureStillImageAsynchronouslyFromConnection(connection) { (sampleBuffer: CMSampleBuffer!, error: NSError!) -> Void in
if nil == error { if nil == error {
let data: NSData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer) let data: NSData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)
self.delegate?.captureStillImageAsynchronously?(self, image: UIImage(data: data), error: nil) self.delegate?.captureStillImageAsynchronously?(self, image: UIImage(data: data)!)
} else { } else {
self.delegate?.captureStillImageAsynchronously?(self, image: nil, error: error) self.delegate?.captureStillImageAsynchronouslyFailedWithError?(self, error: error!)
} }
}
}
/**
:name: startRecording
*/
public func startRecording() {
if !isRecording {
let connection: AVCaptureConnection = movieOutput.connectionWithMediaType(AVMediaTypeVideo)
connection.videoOrientation = currentVideoOrientation
connection.preferredVideoStabilizationMode = .Auto
let device: AVCaptureDevice = activeCamera!
if device.smoothAutoFocusSupported {
do {
try device.lockForConfiguration()
device.smoothAutoFocusEnabled = true
device.unlockForConfiguration()
} catch let e as NSError {
delegate?.captureSessionFailedWithError?(self, error: e)
}
}
movieOutputURL = uniqueURL()
if let v: NSURL = movieOutputURL {
movieOutput.startRecordingToOutputFileURL(v, recordingDelegate: self)
}
}
}
/**
:name: captureOutput
*/
public func captureOutput(captureOutput: AVCaptureFileOutput!, didStartRecordingToOutputFileAtURL fileURL: NSURL!, fromConnections connections: [AnyObject]!) {
isRecording = true
delegate?.captureDidStartRecordingToOutputFileAtURL?(self, captureOutput: captureOutput, fileURL: fileURL, fromConnections: connections)
}
/**
:name: captureOutput
*/
public func captureOutput(captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAtURL outputFileURL: NSURL!, fromConnections connections: [AnyObject]!, error: NSError!) {
isRecording = false
delegate?.captureDidFinishRecordingToOutputFileAtURL?(self, captureOutput: captureOutput, outputFileURL: outputFileURL, fromConnections: connections, error: error)
}
/**
:name: stopRecording
*/
public func stopRecording() {
if isRecording {
movieOutput.stopRecording()
} }
} }
...@@ -528,4 +614,17 @@ public class CaptureSession : NSObject { ...@@ -528,4 +614,17 @@ public class CaptureSession : NSObject {
} }
return nil return nil
} }
/**
:name: uniqueURL
*/
private func uniqueURL() -> NSURL? {
do {
let directory: NSURL = try NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true)
return directory.URLByAppendingPathComponent("temp_movie.mov")
} catch let e as NSError {
delegate?.captureCreateMovieFileFailedWithError?(self, error: e)
}
return nil
}
} }
...@@ -37,26 +37,12 @@ public class CaptureView : MaterialView, CaptureSessionDelegate, CapturePreviewV ...@@ -37,26 +37,12 @@ public class CaptureView : MaterialView, CaptureSessionDelegate, CapturePreviewV
/** /**
:name: captureButton :name: captureButton
*/ */
public var captureButton: UIButton? { public var captureButton: UIButton?
didSet {
if let v: UIButton = captureButton {
v.removeTarget(self, action: "handleCaptureButton:", forControlEvents: .TouchUpInside)
v.addTarget(self, action: "handleCaptureButton:", forControlEvents: .TouchUpInside)
}
}
}
/** /**
:name: switchCamerasButton :name: switchCamerasButton
*/ */
public var switchCamerasButton: UIButton? { public var switchCamerasButton: UIButton?
didSet {
if let v: UIButton = switchCamerasButton {
v.removeTarget(self, action: "handleSwitchCameraButton:", forControlEvents: .TouchUpInside)
v.addTarget(self, action: "handleSwitchCameraButton:", forControlEvents: .TouchUpInside)
}
}
}
/** /**
:name: flashButton :name: flashButton
...@@ -152,20 +138,6 @@ public class CaptureView : MaterialView, CaptureSessionDelegate, CapturePreviewV ...@@ -152,20 +138,6 @@ public class CaptureView : MaterialView, CaptureSessionDelegate, CapturePreviewV
} }
/** /**
:name: handleCaptureButton
*/
internal func handleCaptureButton(button: UIButton) {
captureSession.captureStillImage()
}
/**
:name: handleSwitchCameraButton
*/
internal func handleSwitchCameraButton(button: UIButton) {
captureSession.switchCameras()
}
/**
:name: preparePreviewView :name: preparePreviewView
*/ */
private func preparePreviewView() { private func preparePreviewView() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment