• 501 세션을 보고 오라는데, 영상이 내려갔다.

  • AVCapturePhotoOutput: AVFoundation에서 지원하는 카메라 캡쳐 API(iOS 10+)

    • 지원 포맷: 라이브 포토, RAW+DNG, Wide Color, 프리뷰 혹은 썸네일
    • 기존 인터페이스인 AVCaptureStillImageOutput을 대체한다.
    • 함수형 프로그래밍 모델 채택 - mutable과 immutable의 구분
    • AVCapturePhotoSetting으로 capture request별 설정을 추상화
    • delegate 형태로 request 결과를 추적(AVCapturephotCaptureDelegate)
      • 모든 메소드의 반환값은 AVCaptureResolvedPhotoSetting이라는 immutable 객체
  • Scene Monitoring

    • scene의 상태를 확인 - ex) 어두울 때 플래시 활성화

    • scene 모니터링의 대상

      • flash scene
      • still image stabilization scene(SIS Scene)
        • 서로 다르게 노출된 이미지를 합쳐서 빛이 적은 상태에서의 얼룩을 줄이는 기술
        • 어두우면 빛을 더 많이 받기 위해 노출 시간이 길어지므로, 흔들릴 위험도 늘어난다.
        • 그래서 이 기능은 사실상 어두운 상태에서 유용한 기능인데, 딱봐서는 드러나지 않는다. 그래서 API에서도 혼동이 있을 수 있다.
      • SIS 활성화에 따라서 밝은 지 아닌지에 대한 판단이 달라질 수 있기 떄문에, 모니터링할때 이를 확인할 필요가 있다.
      public var photoSettingsForSceneMonitoring: AVCapturePhotoSettings?
      
      public var isStillImageStabilizationScene: Bool { get }
      public var isFlashScene: Bool { get } 
      
      func setupSceneMonitoring() {
      	let settingsForMotitoring = AVCapturePhotoSettings()
      	settingsForMonitoring.flashMode = .auto
      	settingForMonitoring.isAutoStillImageStabilizationEnabled = true
      	photoOutput.photoSettingsForSceneMonitoring = settingsForMotitoring
      
      	photoOutput.addObserver(self, forKeyPath: "isFlashScene", options: .new, context: nil)
      	photoOutput.addObserver(self, forKeyPath: "isStillImageStabilizationScene", options: .new, context: nil)
      }
      
      • photoSettingsForSceneMonitoring은 nullable한 프로퍼티다. null이면 모니터링을 안하는 것이다.
      • flashMode가 .off면, isFlashScene은 언제나 false로 나온다.
      • UI적으로 신호를 줄게 아니면, 모니터링할 필요는 없다.
        • 오토 플래시만 가지고 캡쳐할꺼면 SIS를 모니터링할 필요는 없다는 것이다.
  • Resource Preparation and Reclamation

    • AVCaptureSession의 데이터 흐름

      • AVCapureDevice의 데이터는 실시간으로 Output으로 스트리밍된다. → 스트리밍 방식으로 연결되면, 설정을 바꾸려면 렌더 파이프라인을 재구성해야한다.

        • AVCaptureVideoPreviewLayer - 프리뷰용
        • AVCaptureMovieFileOutput - 동영상용. delegate를 통해서 버퍼 형태로 제공된다.
      • AVCapturePhotoOutput은 필요에 따라 그때그때 가져온다. (CMSampleBuffer의 형태로)

        • 설정을 바꿔도 렌더 파이프라인을 재구성할 필요가 없다.
        photoOutput.capturePhoto(with:, delegate:)
        
        • 이미지를 어떻게 가져올 것인가에 따라서 필요한 리소스가 달라진다. 심지어 얘들은 섞일 수도 있다.
          • Uncompressed 420: 카메라가 보는 데이터를 그대로 가져옴. 리소스 소모량 최소
          • Process: 특정 포맷으로 변환.(EGRA, JPEG 등)포맷 변환으로 인한 리소스 추가 필요.
          • Flash: 하드웨어 리소스 필요(플래시 이전의 화면과 이를 이후 화면과 동기화하기 위한 데이터들)
          • Still Image Stabilization: 사진을 합치기 위한 다중 버퍼 필요
          • RAW: 엄청 큰 크기의 버퍼 필요
          • RAW+JPEG: 둘을 합친것만큼 더 필요
          • Exposure Bracke: 라이브 포토같은 것일 듯. Bracket 사이의 이미지들을 모두 반환하기 위한 버퍼
        • 이러한 리소스는 딱맞춰서 준비하지 않으면, 리소스가 낭비되거나 데이터가 유실될 수 있다.
        • 그래서 AVCapturePhotoOutput에 어떤 캡쳐를 사용할 것인지를 미리 알려줄 수 있다.
          • 기본값은 [AVCapturePhotoSettings()]로, JPEG에 AutoStillImageStabilization이 true다.
        public func setPreparedPhotoSettingsArray(
        		_ preparedPhotoSettingsArray: [AVCapturePhotoSettings],
        			completionHandler handler: ((Bool, NSError!) -> Swift.Void)!)
        
        public var preparePhotoSettingsArray: [AVCapturePhotoSettings] { get }
        
        • begin / commitConfiguration 쌍으로 한꺼번에 바꿀수도 있다.

        • completionHandler는 session이 멈춰져 있는 상태에서는 호출되지 않고, startRunning() 호출이 되면 불린다.

        • setPreparedPhotoSettingsArray을 여러번 호출하면, 이전 호출은 completionHandler에 false가 전달되고 끝난다. 이 경우는 세션 실행 여부와 상관없이 전달된다.

        • 권장사항

          • 준비해라. capture를 일단 시작하고 볼 수도 있지만, 이러면 첫 이미지를 늦게 받을 수도 있다.
          • 세션 시작전에 미리 준비해라. 미리 준비하면 메모리를 아낄 수 있다.
          • UI 변경시에만 다시 준비해라. 캡쳐 타입이 바뀔 때에만 다시 준비하면 된다.
        • Non-prepared feature

          // 이 프로퍼티들을 재설정하기 위해서는, 전체 그래프를 다시 만들어야 한다.
          public var isHighResolutionCaptureEnabled: Bool
          public var isLivePhotoCaptureEnabled: Bool
          public var isLivePhotoAutoTrimmingEnabled: Bool
          
  • Camera Privacy Policy Changes in iOS 10

    • iOS7부터 카메라나 마이크에 접근하려면, 최초1회 사용자에게 얼럿이 띄워졌다.
    • iOS10부터는 민감한 정보(사진첩, 카메라, 마이크 등)에 접근하기 위해서는 접근 이유를 직접 제공해야한다.
      • 메시지는 info.plist에서 privacy 쪽에 -UsageDescription으로 존재한다.