• 하드웨어 기반 인코딩은 유저 경험을 향상시킬 수 있다.
    • 좋은 성능
    • 높은 효율성
    • 배터리 지속시간 상승
  • What you will learn
    • Case Studies
      1. 네트워크로 들어오는 H.264 스트림을 앱의 특정 레이어에 송출한다.
      2. 단순히 보여주는 게 아니라 실제 디코딩 된 버퍼에 접근한다.
      3. 카메라나 여타 다른 곳에서 들어오는 이미지 시퀀스를 동영상 파일로 압축한다.
      4. 압축된 버퍼에 접근해서 이를 네트워크로 바로 전송한다.
    • iOS 8, OS X Yosemite에 추가된 multi-pass 인코딩 API
  • Media Interface Overview(비디오에 포커싱해서)
    • AVKit - 최상단에 위치해서 뷰 수준의 인터페이스를 제공
    • AVFoundation - 여러 미디어 작업들에 대해서 Objective-C 인터페이스를 제공
      • 물론 지금은 Swift 인터페이스로 점점 진화중
    • Video Toolbox
      • 한동안 OS X에만 있다가 iOS에 헤더가 포함되었다.
      • 하드웨어 encoder/decoder에 직접 접근할 수 있게 해준다.
    • 그 아래 Core Media와 Core Video
      • 위의 다른 스택들에서 사용할 필수적인 타입들을 제공
  • 이번 세션에서는 AVFoundation과 Video Toolbox에 집중한다.
    • AVFoundation
      • 화면에 출력하기 위해서 압축 해제하기
      • 압축해서 파일에 넣기
    • Video ToolBox
      • CVPixelBuffer에 압축 해제하기
      • CMSampleBuffer에 압축해넣기
  • 그러면 하드웨어 가속을 위해서는 무조건 Video ToolBox까지 내려가야 하나?
    • iOS에서는 AVKit, AVFoundation, Video ToolBox가 항상 하드웨어 코덱을 쓴다.
    • OS X에서는 AVKit과 AVFoundation은 가능한 하드웨어 코덱을 쓰고, Video Toolbox는 추가적으로 하드웨어 코덱을 쓰겠다고 명시해야 한다.
  • 인터페이스들에서 사용될 타입들 소개
    • CVPixelBuffer
      • 압축되지 않은 레스터 이미지 버퍼를 감싸는 Wrapper
      • 내부 이미지 버퍼를 올바르게 해석하기 위한 모든 정보를 가진다.(width, height, pixelformat 등)
    • CVPixelBufferPool
      • CVPixelBuffer는 매번 할당하고 해제하면서 쓰기에는 굉장히 무겁다.
      • 그래서 CVPixelBufferPool을 사용해서 재사용한다.
      • How?
        • CVPixelBuffer를 Pool을 사용해서 할당하면, 다른 곳에서 모두 해제되었을 때 다시 pool로 돌아가서 다음 할당 때 사용된다.
    • pixelBufferAttributes
      • 실제 타입은 아니지만, 인터페이스에서 자주 보게 되는 것.
      • CVPixelBuffer나 CVPixelBuffer의 요구사항을 담고 있는 CFDictionary
        • ex) dimension(width/height), Pixel format type(32BGRA, YCbCr420), Compatibility(OpenGL ES, Core Animation)
    • CMTime
      • 시간 표현
      • 64bit 시간 값과 32bit의 스케일 값으로 구성
      • 미디어 파이프 라인 전체에서 손실 없이 넘길 수 있는 형태로 구성
    • CMVideoFormatDescription
      • 비디오 데이터에 대한 descriptor
      • dimension, pixel format, 그 외 여러 확장들이 있다.
        • 디스플레이를 위해서는 pixel aspect ratio, color space 등
        • H.264 데이터를 위한 확장도 존재(추후에 다시 이야기)
    • CMBlockBuffer
      • Core Media의 임의의 데이터 블록을 을 감싸는 기본적인 방법.
      • 비디오 파이프라인에서 압축된 비디오 데이터들은 여기에 감싸져서 나온다.
    • CMSampleBuffer
      • 데이터 샘플을 래핑한것
      • 압축된 것과 압축 안된 것을 모두 담을 수 있다.
        • 공통적으로 CMTime과 CMVideoFormatDescription을 가진다.
        • 압축 된 경우는 CMBlockBuffer를 가지고, 압축되지 않은 경우는 CVPixelBuffer나 CMBlockBuffer 중에서 하나를 가진다.
    • CMClock
      • 시간 소스에 대한 Core Media의 Wrapper 타입
      • 항상 증가하는 방향으로 움직인다.
      • 가장 자주 쓰는 Clock이 CMClockgetHostTimeClock()인데, 이는 mach_absolute_time()을 래핑한 것이다.
    • CMTimebase
      • CMClock은 컨트롤이 어렵기 때문에, 좀 더 컨트롤하기 좋은 형태.
  • Case 1: 네트워크로 들어오는 H.264 스트림을 앱의 특정 레이어에 송출한다.
    • Overview

      스크린샷 2023-05-02 오후 6.05.21.png

    • AVSampleBufferDisplayLayer

      • iOS 8에 추가되었다.
      • 압축된 프레임 시퀀스를 CMSampleBuffer로 감싸서 입력을 받는다.
      • 내부적으로 video decoder가 있어서 이 프레임들을 CVPixelBuffer 형태로 디코딩하고 이를 큐에 넣으면 적절한 시점에 보여준다.
    • 근데 네트워크로 받으니 처음부터 CMSampleBuffer 형태가 아니다. 그래서 가공을 해야한다.

      • H.264 스펙에서 정의하는 몇가지 패키징 방법이 있다.
        • Elementary Stream packaging
          • 주로 스트림과 관련된 것들에 사용
        • MPEG-4 packaging
          • 동영상 파일과 mp4 파일등에 사용
          • CMSampleBuffer를 다루는 Core Media와 AVFoundation은 이걸로 패키징 된 데이터만 받아들일 수 있다.
    • H.264 스트림 심층 분석

      • 스트림은 NAL(Network Abstraction Layer) Unit으로 패키징된 블록의 시퀀스로 이루어져있다.
      • 비디오 프레임은 하나의 NAL Unit에 담길수도 있고, 여러 NAL Unit에 걸쳐서 존재할 수도 있다.
      • 비디오 프레임 뿐 아니라 매개변수 집합도 가질 수 있다.
    • 두 패키징 방법의 차이

    • AVSampleBufferDisplayLayer와 시간

    • AVSampleBufferDisplayLayer에 CMSampleBuffer 제공하기

  • Case 2: 단순히 보여주는 게 아니라 실제 디코딩 된 버퍼에 접근한다.
  • Case 3: 카메라나 여타 다른 곳에서 들어오는 이미지 시퀀스를 동영상 파일로 압축한다.
  • Case 4: 압축된 버퍼에 접근해서 이를 네트워크로 바로 전송한다.
  • Multi-Pass Encoding
  • Single-Pass Encoding?
  • Multi-Pass Encoding?
  • Single Pass와 Multi Pass의 비교
  • New API
  • Video Toolbox
  • 유즈 케이스 고려해서 결정하기
  • 컨텐츠에 따라서 고려해보기