/**
@class AVCaptureSession
@abstract
AVCaptureSession is the central hub of the AVFoundation capture classes.
@discussion
To perform a real-time capture, a client may instantiate AVCaptureSession and add appropriate AVCaptureInputs, such as AVCaptureDeviceInput, and outputs, such as AVCaptureMovieFileOutput. [AVCaptureSession startRunning] starts the flow of data from the inputs to the outputs, and [AVCaptureSession stopRunning] stops the flow. A client may set the sessionPreset property to customize the quality level or bitrate of the output.
*/
@available(iOS 4.0, *)
open class AVCaptureSession : NSObject {
. . .
AVCaptureSession이란 실시간으로 입력(카메라 입력)으로부터 출력 장치로의 데이터 흐름을 제어하는 데 사용하는 클래스이다.
AVCaptureSession 하위에는 다양한 개념이 있다.
본 글에서는 개중에 자주 사용되는 개념들에 대해 알아볼 것이다.
/**
@property sessionPreset
@abstract
Indicates the session preset currently in use by the receiver.
@discussion
The value of this property is an AVCaptureSessionPreset indicating the current session preset in use by the receiver. The sessionPreset property may be set while the receiver is running.
*/
open var sessionPreset: AVCaptureSession.Preset
사용자는 Preset
을 통해 출력의 형식을 설정할 수 있다.
Preset에는 다음과 같은 값을 설정할 수 있다.
captureSession.sessionPreset = .photo
captureSession.sessionPreset = .high
captureSession.sessionPreset = .medium
captureSession.sessionPreset = .low
captureSession.sessionPreset = .cif352x288
captureSession.sessionPreset = .vga640x480
captureSession.sessionPreset = .hd1280x720
captureSession.sessionPreset = .hd1920x1080
captureSession.sessionPreset = .hd4K3840x2160
captureSession.sessionPreset = .iFrame960x540
captureSession.sessionPreset = .iFrame1280x720
captureSession.sessionPreset = .inputPriority
각각 화질에 대한 값을 설정하는 것을 확인할 수 있는데
마지막의 inputPriority는 동적으로 입출력 포맷을 설정하길 원할 때 사용할 수 있겠다.
디바이스별로 Resolution이 차이가 있으므로 실제로 사용할 때에는 다음과 같이 사용할 수도 있다.
if captureSession.canSetSessionPreset(.hd4K3840x2160) {
captureSession.sessionPreset = .hd4K3840x2160
} else if captureSession.canSetSessionPreset(.hd1920x1080) {
captureSession.sessionPreset = .hd1920x1080
} else {
captureSession.sessionPreset = .hd1280x720
}
AVCaptureSession에는 inputs라는 property가 존재한다.
/**
@property inputs
@abstract
An NSArray of AVCaptureInputs currently added to the receiver.
@discussion
The value of this property is an NSArray of AVCaptureInputs currently added to the receiver. Clients can add AVCaptureInputs to a session by calling -addInput:.
*/
open var inputs: [AVCaptureInput] { get }
inputs는 AVCaptureInput의 배열 형태를 가지고 있는데
AVCaptureInput은 하나 이상의 미디어 데이터 스트림을 제공하는 추상 클래스 이다.
이는 오디오 및 비디오 데이터를 모두 제공할 수 있다.
실제 사용 예시는 다음과 같다.
fileprivate func configureFrontCamera(for captureSession: AVCaptureSession) throws -> (device: AVCaptureDevice, resolution: CGSize) {
let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: .video, position: .front)
if let device = deviceDiscoverySession.devices.first {
if let deviceInput = try? AVCaptureDeviceInput(device: device) {
if captureSession.canAddInput(deviceInput) {
captureSession.addInput(deviceInput)
}
if let highestResolution = self.highestResolution420Format(for: device) {
try device.lockForConfiguration()
device.activeFormat = highestResolution.format
device.unlockForConfiguration()
return (device, highestResolution.resolution)
}
}
}
throw NSError(domain: "ViewController", code: 1, userInfo: nil)
}
위 코드에서 AVCaptureDeviceInput
은 추상 클래스인 AVCaptureInput
을 상속받는 클래스이다.
APCaptureSession에서 canAddInput 함수로 input의 추가 가능 여부를 확인하고
addInput 함수를 통해 APCaptureSession에 input을 추가한다.
AVCaptureSession에는 outputs라는 property가 존재한다.
/**
@property outputs
@abstract
An NSArray of AVCaptureOutputs currently added to the receiver.
@discussion
The value of this property is an NSArray of AVCaptureOutputs currently added to the receiver. Clients can add AVCaptureOutputs to a session by calling -addOutput:.
*/
open var outputs: [AVCaptureOutput] { get }
APCaptureInput과 마찬가지로 추상클래스이다. Session의 출력 데이터를 관리한다.
사용 예시는 아래와 같다.
fileprivate func configureVideoDataOutput(for inputDevice: AVCaptureDevice, resolution: CGSize, captureSession: AVCaptureSession) {
let videoDataOutput = AVCaptureVideoDataOutput()
videoDataOutput.alwaysDiscardsLateVideoFrames = true
// Create a serial dispatch queue used for the sample buffer delegate as well as when a still image is captured.
// A serial dispatch queue must be used to guarantee that video frames will be delivered in order.
let videoDataOutputQueue = DispatchQueue(label: "com.example.apple-samplecode.VisionFaceTrack")
videoDataOutput.setSampleBufferDelegate(self, queue: videoDataOutputQueue)
if captureSession.canAddOutput(videoDataOutput) {
captureSession.addOutput(videoDataOutput)
}
videoDataOutput.connection(with: .video)?.isEnabled = true
if let captureConnection = videoDataOutput.connection(with: AVMediaType.video) {
if captureConnection.isCameraIntrinsicMatrixDeliverySupported {
captureConnection.isCameraIntrinsicMatrixDeliveryEnabled = true
}
}
self.videoDataOutput = videoDataOutput
self.videoDataOutputQueue = videoDataOutputQueue
self.captureDevice = inputDevice
self.captureDeviceResolution = resolution
}
AVCaptureVideoDataOutput
도 AVCaptureOutput
을 상속받은 클래스이다.
Input과 마찬가지로 canAddOutput 함수로 AVCaptureSession에 output을 추가할 수 있는지 확인하고
addOutput 함수로 outputdmf 추가한다.
이 때 videoDataOutput.connection이라는 property에 접근하게 되는데
해당 개념은 AVCaptureConnection에서 설명하겠다
/**
@class AVCaptureConnection
@abstract
AVCaptureConnection represents a connection between an AVCaptureInputPort or ports, and an AVCaptureOutput or AVCaptureVideoPreviewLayer present in an AVCaptureSession.
@discussion
AVCaptureInputs have one or more AVCaptureInputPorts. AVCaptureOutputs can accept data from one or more sources (example - an AVCaptureMovieFileOutput accepts both video and audio data). AVCaptureVideoPreviewLayers can accept data from one AVCaptureInputPort whose mediaType is AVMediaTypeVideo. When an input or output is added to a session, or a video preview layer is associated with a session, the session greedily forms connections between all the compatible AVCaptureInputs' ports and AVCaptureOutputs or AVCaptureVideoPreviewLayers. Iterating through an output's connections or a video preview layer's sole connection, a client may enable or disable the flow of data from a given input to a given output or preview layer.
Connections involving audio expose an array of AVCaptureAudioChannel objects, which can be used for monitoring levels.
Connections involving video expose video specific properties, such as videoMirrored and videoRotationAngle.
*/
@available(iOS 4.0, *)
open class AVCaptureConnection : NSObject {
설명에 따르면
AVCaptureConnection
은 캡처 인풋으로부터 캡처 아웃풋으로 이어지는 연결을 나타내는 객체이다.
Capture Input은 하나 혹은 하나 이상의 Input Port(AVCaptureInput.Port의 인스턴스)를 가지고 있다. Capture Output은 하나 혹은 하나 이상의 소스로부터 데이터를 받을 수 있다(예를 들어 AVCaptureMovieFileOutput
객체는 비디오와 오디오 데이터를 받는다).
canAddConnection(_:)
메소드가 true를 반환하는 경우에만 addConnection(_:)
메소드를 사용해 AVCaptureConnection
인스턴스를 추가할 수 있다. addInput(_:)
혹은 addOutput(_:)
메소드를 사용하고 있는 경우 세션은 호환 가능한 모든 인풋 및 아웃풋 연결을 자동으로 형성gks다. 연결이 없는 input 혹은 output을 추가하는 경우에 직접 연결을 추가하기만 하면 된다. 주어진 input으로부터 혹은 주어진 input으로 데이터의 흐름을 가능, 불가능하게 하기 위해 Connection을 사용할 수도 있다.