스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.
-
Core Media IO로 카메라 확장 프로그램 만들기
Core Media IO를 사용하여 소프트웨어 카메라, 하드웨어 카메라 및 크리에이티브 카메라를 위한 macOS 시스템 확장 프로그램을 손쉽게 만드는 방법을 확인하세요. 레거시 DAL 플러그인을 대체하는 최신 기능을 소개합니다. 이러한 확장 프로그램은 안전하고 빠르며 카메라 입력을 사용하는 모든 앱과 완벽히 호환됩니다. Core Media IO API에 대해 안내하고 이를 통해 카메라 제조업체, 특수 효과 기능이 있는 화상 회의 앱, 창의적인 앱 아이디어 등을 지원하는 방법을 알려드리겠습니다.
리소스
- Capture setup
- Core Media I/O
- Creating a camera extension with Core Media I/O
- Overriding the default USB video class extension
- System Extensions and DriverKit
관련 비디오
WWDC19
-
다운로드
♪ ♪
안녕하세요, 여러분 환영합니다 Camera Software Engineering 팀의 Brad Ford입니다 오늘은 macOS 용 카메라 드라이버 아키텍처인 CoreMedia IO에 대해 소개해 드리려고 하는데요 macOS용 현대 카메라 드라이버 아키텍처로
DAL 플러그인을 대체하죠 가상 카메라를 만들 수 있게 해주는 기술입니다 macOS 10.7부터 도입됐으니 꽤 오래 됐죠
이건 macOS를 풍성한 미디어 플랫폼으로 확장해 제3 카메라에 대한 지원을 프로와 소비자에 제공합니다
그리고 이건 바로 그 'Mac'을 만든 일부죠
하지만 DAL 플러그인에는 몇 가지 문제가 있습니다 신뢰할 수 없는 코드를 앱 프로세스에 직접 로딩하여 플러그인에 버그가 생기거나 멜웨어 공격을 받았을 때 취약하게 만들죠 이런 이유로 FaceTime QuickTime Player, PhotoBooth 등 Apple 앱과는 작동하지 못하죠 제3 카메라 앱들과도 잘 작동이 안됩니다 해당 앱들이 라이브러리 검증을 일부러 비활성했거나 시스템 통합 보호 기능을 사용자가 끈 게 아니라면요 이런 사례는 권장하지 않습니다 시스템을 더 불안하고 불안정하게 만드니까요 DAL 플러그인은 개발하기도 어렵습니다 2011년 경 C API가 생겨났고 C++ SDK 헬퍼 클래스를 통해 배우실 수 있습니다 그리고 무엇보다도 산발적으로 문서화되어 있죠
업그레이드가 필요한 때죠 macOS 12.3에는 Camera Extension이라는 DAL 플러그인의 대체 아키텍처가 도입됐는데요
이건 사용자 보안을 우선으로 두는 아키텍처입니다 작동 원리를 알아보죠 먼저 기술에 대해 간략하게 설명해 드릴게요 다음으로 Camera Extensions를 만드는 방법을 보여드릴게요 그 다음 API의 주요 클래스와 함수를 소개하고 CoreMedia IO가 출력 디바이스로 사용되는 원리도 설명해 드리죠 마지막으로 DAL 플러그인 지원 중단 계획을 말씀드릴게요 시작해 봅시다 이건 CoreMedia IO라고도 하는데 카메라 드라이버를 Mac 앱에 포장 및 전달할 수 있는 새로운 방법이죠
안전합니다 익스텐션 코드는 샌드박스화 되어 역할 사용자로 작동하며 데몬 프로세스로 갈 수 없습니다 익스텐션 제공하는 버퍼는 모두 앱으로 전달되기 전에 검증되고요 또, 정말 빠릅니다 이 프레임워크는 익스텐션 프로세스와 앱 사이의 IPC 계층을 처리합니다 성능에 초점을 맞춰서요 또 다수의 동시 클라이언트에 버퍼를 전달할 수 있고요 현대적이기도 합니다 Swift나 Objective-C에서 쓸 수 있죠
이들은 단순합니다 알아야 할 클래스가 몇 개 밖에 없죠 깨워서 실행해야 할 시행 프로토콜도 별로 없고요 다양한 보일러플레이트 코드를 다루기도 합니다
이용하기 쉽거든요 App Store의 앱으로 출시할 수도 있고요
카메라 익스텐션은 기존 AVFoundation 캡처 API와 함께 100% 하위 호환됩니다
Apple 앱을 포함한 모든 카메라 앱의 빌트인 카메라 같은 거죠 카메라 익스텐션이 FaceTime 카메라 피커에서 어떻게 나타나는지 예시를 한 번 보시죠 카메라 익스텐션으로 어떤 경험을 만들 수 있을지 3개의 사용 사례를 통해 공부해 봅시다 가장 단순한 사용법은 소프트웨어용 카메라인데요 프로그램에 따라 다양한 프레임 레이트나 해상도의 이미지를 생성하는 특수 테스트 패턴인 컬러 바를 보여주는 카메라나 A/V 동기화 테스트를 위해 영화 속 프레임처럼 이미 렌더링된 콘텐츠가 흐르는 카메라에 쓰일 수 있죠
두 번재는 Mac에 물리적으로 연결하거나 무선 발견하도록 만든 카메라 드라이버입니다 이건 핫플러깅과 언플러깅을 완전 지원합니다 하드웨어를 다룰 때는 몇 가지 선택권이 있죠 선호되는 방법은 전체적으로 사용자 공간에서 실행되는 DriverKit Extension 즉, DEXT를 사용하는 겁니다 하드웨어가 커널 수준에서 처리되어야 한다면 IOVideoFamily kext 경로를 사용할 수 있습니다 새로운 켁스트 코드 개발은 권장하지 않습니다 켁스트는 내재적으로 불안정하여 시스템 불안정으로 이어지거든요
Apple은 USB 비디오 클래스 즉, UVC 카메라에 대한 클래스 준수 익스텐션을 제공합니다 UVC 스펙에 일치하는 카메라에서 잘 작동합니다
그러나 비표준 프로토콜을 사용하고 UVC 스펙 외 추가 기능을 가지는 USB 카메라 지원이 필요할 경우 Apple의 UVC를 뛰어넘는 걸 만드실 수 있을 겁니다 그럼 여러분께는 특정 제품과 벤더 ID가 필요하겠죠 이 부분에 대해 더 학습하고 싶으시다면 다음 제목을 가지는 developer.apple.com의 아티클을 참조하세요 이건 최소 DEXT 번들을 만드는 방법과 함께 Info.plist에서 어떤 IOKitPersonalities 키를 무시해야 할지 알려줍니다
세 번째는 창의적인 카메라인데요 소프트웨어와 하드웨어의 하이브리드 카메라일 겁니다
여러분의 익스텐션은 Mac 부착된 실제 카메라의 비디오 스트림에 액세스하고 버퍼에 효과를 적용해 새로운 카메라 스트림으로 클라이언트에 보냅니다
아니면 여러 카메라의 스트림에 액세스하고 합성해 앱으로 보내는 카메라일 수 있습니다
이들은 합성을 제어하거나 필터를 매개 변수화하기 위해 구성 앱을 사용할 수 있습니다 창의적인 카메라의 가능성은 정말 끝이 없죠
주요 사용 사례를 살펴 보았으니 이제 CoreMedia IO Extensions를 해부해 봅시다 먼저, 'CoreMedia IO' 파트입니다
CoreMedia IO는 카메라 드라이버를 퍼블리싱하거나 발견하기 위한 로우 레벨 프레임워크입니다 레거시 DAL API를 포함하고 이걸 대체하는 새로운 카메라 익스텐션 API를 포함한다는 건 아실 겁니다 강력한 로우 레벨 C API 여러 개도 포함하죠 앱 개발자들이 시스템에서 카메라를 발견하고 점검하도록요
'Extension' 파트는 그렇다면 뭘까요?
CoreMedia IO Extensions는 macOS Catalina에서 처음 나타난 SystemExtensions 프레임워크의 최상단에 있는 건데요 삭제 인스톨러의 필요성을 없애 줍니다 대신 앱 내부에 익스텐션을 보내죠 실행 가능한 익스텐션은 앱 번들 내부에 삽니다 SystemExtensions 프레임워크로 호출함으로써 앱은 시스템의 모든 사용자에 대해 익스텐션을 설치하거나 업, 다운그레이드 가능합니다 삭제는 순식간에 이루어지죠 앱을 삭제하면 SystemExtensions 프레임워크는 모든 사용자에 대한 카메라 익스텐션을 삭제합니다 전달 메커니즘은 App Store 사용이 승인되어 광범위한 오디언스가 이용하기 쉽게 만들죠
시스템 익스텐션 프레임워크를 더 알아보고 싶으시다면 developer.apple.com/documentation/systemextensions에서 문서들을 읽어보실 수 있습니다
다음의 WWDC 2019 세션도 꼭 확인해 보세요
카메라 익스텐션 기술 설명은 여기서 마치겠습니다 실제로 하나 만들어 볼건데요 카메라 익스텐션이 깨워져 실행되는 방법을 빠른 데모로 함께 살펴 봅시다
ExampleCam이라고 불리는 단일 윈도우 macOS를 만들었는데요 이 지점에서 코드를 몇 줄 추가했습니다
메인 스토리보드에 버튼을 2개 추가했고요 AppDelegate는 변하지 않습니다 하나는 익스텐션 설치 다른 하나는 삭제 버튼입니다 텍스트 필드는 상태를 보여주고요
설치 및 삭제 버튼을 연결하기 위해 ViewController 클래스에 IBActions를 추가했습니다
이 함수는 앱 번들 내에서 발견되는 익스텐션을 활성화하거나 비활성화하기 위해 OSSystemExtensionRequests를 만듭니다 하단에는 상태를 기록하는 OSSystemExtensionRequestDelegate 함수의 골격 구현을 추가했는데요
앱의 자격관리 파일은 보통 App Sandbox를 가지고 AppGroup을 규정합니다
저는 'System Extension'키만 추가했습니다 앱이 시스템 익스텐션을 설치한다면 필요한 키죠 이 지점에서 앱을 실행해 'Install Extension' 버튼을 누르면 치명적인 오류가 나타납니다 앱이 아직 존재하지 않는 익스텐션을 찾고 있어 치명적인 오류가 발생합니다
시스템 익스텐션을 만들어 포함시키기 위해 'File-New-Tartget'을 누릅니다 macOS에서는 'System Extensions'가 스크롤 맨 하단에 위치하는데요 'Camera Extension'을 누르고 이름을 'Extension'이라고 입력한 다음 'Embedded in Application'이 설정되었는지 확인한 후 'Finish'를 클릭합니다 새로운 익스텐션 폴더에 새로운 파일이 생겼네요 Info.plist는 이것을 MachServiceName이라고 정의함으로써 CIMOExtension으로 식별합니다
이건 중요한 정보인데요 익스텐션이 제시되지 않으면 개시되지 않습니다
여기에서는 시스템 익스텐션을 위해 Usage Description을 입력합시다 자격 관리 파일은 이게 앱 샌드박스화됐음을 보여줍니다 여기서는 익스텐션의 앱 그룹이 검증을 거치기 위해 MachServiceName에 의해 앞에 고정됐는데요
여기서 이 부분을 복사해서 Extension의 자격 관리 파일에 붙여넣겠습니다 다 됐네요
main-swift는 익스텐션의 진입점으로서 서비스를 시작합니다 ExtensionProvider.swift 파일은 완전 기능 카메라가 되고요 여기에는 DeviceSource StreamSource, ProviderSource가 포함됩니다 모두 순수 소프트웨어 카메라를 만들기 위해 필요한 겁니다 나쁘지 않은 템플릿이죠
이 파일에서 'SampleCapture'를 검색할게요 이걸 'ExampleCam'으로 바꾸겠습니다 카메라 이름, 모델, 제조사가 모두 적절한 이름으로 바뀌어야 하니까요
다 됐으니 컴파일링하고 실행해 볼까요?
'Install' 버튼을 누를게요 이럴 수가, 안되네요 그건 바로 시스템 익스텐션이 /Applications에 있는 앱에 의해서만 설치될 수 있기 때문입니다 이동시킨 다음 다시 해보죠
이번에는 성공했네요 블록된 익스텐션의 설치를 허용하려고 하는데요 System Settings에서 인증이 필요합니다 Privacy & Security로 들어가시고요 'Allow' 버튼을 눌러주세요
비밀 번호를 입력해 인증하시면 되고요 결과값이 0으로 바뀌어서 오류가 나지 않네요 systemextensionsctl list 툴을 사용하면 성공한 게 확인되고 시스템에 익스텐션이 하나 활성화되게 됩니다 이제 카메라 앱을 열어서 어떤지 한 번 볼까요?
FaceTime을 실행해 보죠 카메라 피커에 ExampleCam이 나타납니다 70년대 '퐁' 게임 같네요 60FPS 마다 프레임이 위아래로 움직이는 흰색 수평선이 그려지네요
카메라를 제거하기 위해선 앱을 지워야 합니다
이 시스템은 앱을 삭제함으로써 익스텐션을 삭제 중이라는 걸 확인하게 해주죠
소프트웨어 카메라 만들기가 얼마나 쉬운지 알 수 있습니다 이제 소프트웨어 카메라를 창의적인 카메라로 바꿔 한 단계 더 올라가 보죠
두 번째 예시를 CIFilterCam이라고 할게요 CI는 CoreImage를 뜻합니다 스틸 이미지나 영상에 적용할 수 있는 일련의 효과 필터죠
CIFilterCam을 만들기 위해 ExampleCam 셸로 시작했지만 인스톨러뿐 아니라 구성 앱으로 만들기로 결정했습니다 카메라 피커 버튼 필터 피커 버튼 효과 건너뛰기 버튼을 추가했습니다 라이브 영상 미리보기를 위해 뷰도 추가했고요 AVCaptureVideoPreviewLayer에 의해 지원되어 필터 카메라의 작동을 볼 수 있는 표준 뷰입니다 'Bypass' 버튼을 해제하면 영상에 다양한 필터와 다양한 색깔 효과 다양한 왜곡 필터가 적용되는게 보이시죠
저는 범프 왜곡을 좋아하는데요
이걸 내장된 Face Time 카메라나 Mac에 부착된 실제 카메라에 적용할 수 있습니다
iPhone을 근처에 두고 Continuity Camera로 설정했습니다
사용해 보죠
CIFilterCam 앱은 그 자체로는 특별하지 않은 효과 카메라 앱일 뿐입니다 하지만 이 앱이 모든 앱이 사용할 수 있는 가상 필터 카메라의 프론트 엔드라는 점이 흥미롭죠 FaceTime과 PhotoBooth를 실행해 볼게요 둘 다 CIFilterCam에 지정되는지 확인해 보겠습니다 이제 구성 앱에서 필터를 바꿨기 때문에 CIFilterCam을 사용하는 모든 앱에서도 동시에 바뀝니다
다른 소스 카메라를 고른다면 모든 카메라 앱도 변화하죠
앱에서 모든 버튼 클릭은 필터 카메라 익스텐션에게 '이 카메라 사용해', 아니면 '이 필터 사용해'라고 말하는 단순 프로퍼티 호출로 번역됩니다
계속 다른 필터로
바꾸라고 말하는 거죠
익스텐션 내 하드웨어 카메라의 실행을 지원하려면 macOS Ventura가 필요합니다 익스텐션 자격관리 파일에 com.apple.security.device.camera 키를 추가해야 하고요 이는 다른 카메라를 사용하게 될 거란 뜻입니다 카메라를 사용할 것이기 때문에 사용자는 익스텐션에 허가를 부여하게 됩니다 따라서 Info.plist에 NSCameraUsageDescription를 제공해야 하고요
이건 카메라 익스텐션 구축의 기본을 정리하는 겁니다 이제 API로 넘어가 보죠
데몬 프로세스는 스택의 밑바닥에 있고 퍼스트 파티나 써드 파티의 익스텐션에 해당합니다
카메라 앱 프로세스 내에서는 여러 계층이 작동하는데요 프로세스 통신을 통해 카메라 익스텐션에 말하는 전용 프레임워크 코드로 시작됩니다 한 계층 위에는 CoreMedia IO Extension의 호출을 레거시 DAL 플러그인 호출로 번역하는 또다른 전용 계층이 있습니다
다시 한 번 DAL 플러그인을 퍼블리싱하는 오픈 API가 있고요 이 인터페이스이 클라이언트에게는 두 가지의 차이가 없습니다 모두 DAL 플러그인처럼 보이죠 마지막으로 최상위에는 AVFoundation이 있습니다 CoreMedia IO의 클라이언트죠 DAL 플러그인을 AVCaptureDevices로 리퍼블리싱합니다
레거시 DAL 플러그인 아키텍처와는 다르게 DAL 플러그인에는 데몬 조각이 있거나 없지만 모두 앱 프로세스에서 직접 CoreMedia IO 프레임워크에 로딩된 코드를 실행합니다 이 때문에 앱은 멜웨어에 취약해집니다 카메라 익스텐션은 이 공격 벡터를 완전 제거하죠 익스텐션은 앱 샌드박스이거나 실행이 허용되면 안됩니다
Apple의 registerassistantservice는 CMIOExtensionMachServiceName을 통해 이걸 식별하여 _cmiodalassistants라고 불리는 역할 사용자 계정으로 실행하죠 샌드박스는 커스텀 프로필을 프로세스에 적용합니다 카메라 사용 사례에 맞춤화 되어 있죠
커스텀 샌드박스 프로필로 예상 공용 하드웨어 인터페이스를 통해 통신이 가능합니다 클라이언트는 아니지만 포트를 공개하는 서버인 USB, 블루투스, WiFi부터 Firewire까지 가능하고 자체 컨테이너 및 tmp에서 익스텐션이 읽고 쓸 수 있죠
샌드박스 프로필은 보통 앱보다 더 폐쇄형입니다 할 수 없는 것들로는 forking, exec'ing, posix spawning 윈도우 서버 액세스 포그라운드 사용자에 연결하기 범용 네임스페이스 내 마크 서비스 등록 등이 있죠
익스텐션을 개발하다가 타당한 캡처 사례에 대해 샌드박스가 너무 제한적이라면 Feedback Assistant를 통해 피드백을 주시기 바랍니다 제한 완화를 고려해 볼테니까요 이전의 아키텍처 표는 버퍼를 앱 계층에 직접 통과시키는 카메라 익스텐션의 데몬 프로세스를 보여주었는데요 관련 보안 계층이 실제로는 하나 더 있습니다
데몬과 앱 사이에 registerassistantservice라는 프록시 서비스죠 이 서비스는 투명도와 동의, 제어 정책을 강제합니다 앱이 처음으로 카메라를 사용하려 할 때 시스템은 사용자에게 괜찮냐고 묻죠 모든 카메라에 대해 이 동의가 부여되어야 합니다 빌트인 카메라 뿐 아니라요 프록시 서비스는 여러분을 대표해 동의를 처리하죠 사용자가 카메라 액세스를 거부하면 프록시는 버퍼가 앱으로 가는 것을 막습니다 어트리뷰션도 처리하여 시스템이 특정 카메라가 특정 앱에서 사용 중이라는 걸 알 수 있게 해주죠 데몬이 소모한 전력은 카메라를 사용 중인 앱 때문일 수도 있습니다
CoreMedia IO Extensions에는 4개의 클래스가 있는데요 제공자, 디바이스, 스트림입니다
제공자에게는 디바이스가 있고 디바이스는 스트림을 가지죠 세 가지 모두 프로퍼티를 가집니다
ProviderSource, DeviceSource, StreamSource를 소스로 제공함으로써 메인 클래스 각각을 만듭니다
ExtensionProvider는 최하위 객체입니다 필요한 경우 디바이스를 추가하고 제거하게 합니다
클라이언트의 연결 시도 시 프로세스를 알고 있기 때문에 디바이스가 특정 앱에 대해 퍼블리싱하는 것을 제한할 수 있죠 또한 프로퍼티 구현에 대해 제공자 소스를 컨설팅합니다
익스텐션의 메인 진입점은 이렇게 생겼습니다 ExtensionProviderSource를 만듭니다 CMIOExtensionProviderSource 프로토콜에 일치하고 ExtensionProvider를 만들죠 서비스 개시를 위해 제공자 클래스 메소드인 startService를 포출하고 제공자 인스턴스를 통과시킵니다
ExtensionProvider는 익스텐션 생애 평생 변하지 않는 2개의 읽기 전용 프로퍼티를 구현하죠 바로 '제조자'와 '제공자'입니다 둘 다 문자열이죠
다음은 CMIOExtensionDevice입니다 필요할 경우 추가하고 제거하며 스트림을 관리하죠 디바이스는 다수의 스트림을 제시할 수 있지만 AVFoundation은 첫 입력 스트림을 제외한 모든 스트림을 무시합니다
디바이스를 만들 때 디바이스 소스를 제공하죠 로컬명이나 UUID로 나타나는 deviceID 선택적으로는 legacyID 문자열도요 이 프로퍼티들은 최상단까지 쭉 스며들어 있습니다
디바이스의 로컬명은 AVCaptureDevice의 localizedName이 되고요 구체화된 deviceID는 legacyDeviceID를 제공하지 않으면 AVCaptureDevice의 uniqueIdentifier가 됩니다 DAL 플러그인을 현대화 중이고 이전에 보낸 uniqueIdentifier로 하위 호환성 유지가 필요하면 legacyDeviceID를 제공해야 합니다
이걸 제공하게 되면 AVCaptureDevice는 이걸 uniqueIdentifier로 사용하죠
CMIOExtensionDeviceSource로 CMIOExtensionDevice를 만드는데 이건 deviceModel 같은 다른 프로퍼티를 선택적으로 구현합니다 동일 모델의 모든 카메라에서 동일하게 적용되죠 홍채 인식 기능 사용 때처럼 디바이스가 정지 상태가 되면 isSuspended가 구현되어야 합니다 Apple 노트북의 빌트인 카메라는 클랩셸이 닫히면 정지 상태에 들어가고요 디바이스의 트랜스포트 타입은 USB, 블루투스, Firewire 등 연결 방식을 보여줍니다
마지막으로 카메라에 마이크가 실제 연결되어 있다면 연결된 디바이스에 노출시킬 수 있습니다 이 프로퍼티들은 모두 읽기 전용입니다 다음은 제일 중요한 CMIOExtensionStream인데요 CMIOExtension에서 꽤 힘든 작업입니다 영상 포맷을 퍼블리싱하고 유효 프레임 레이트를 정의하며 활성 포맷을 구성합니다 호스트 타임 클록과 같은 표준 클록을 사용하거나 커스텀 클록을 제공하여 생성하는 각 버퍼에 대한 타이밍을 도출하죠 샘플 버퍼를 클라이언트에게 보낸다는 점이 중요합니다
익스텐션 스트림 소스는 CMIOExtensionStreamFormats를 퍼블리싱합니다 그건 AVCaptureDeviceFormats가 됩니다 클라이언트는 활성 포맷 변경을 위해 활성 포맷 인덱스를 읽고 쓸 수 있고요
프레임 지속 시간은 최대 프레임 레이트입니다 최대 프레임 지속 시간은 분당 프레임 레이트와 동일하죠
DAL 플러그인 세계는 DAL controls를 노출합니다 플러그인 개발자들은 이 인터페이스를 자동 노출, 밝기 등 기능 노출을 위해 사용하죠 강력하지만 일관적으로 구현되지 않습니다 그래서 앱 개발자들이 사용하기가 어렵죠 CMIOExtension 아키텍처에서는 대체 제공하지 않습니다 대신 모든 것이 프로퍼티가 되죠
공급자, 디바이스 스트림 수준에서 이미 많은 표준 프로퍼티를 보셨을 겁니다 여러분만의 프로퍼티를 만들 수도 있고 제가 한 것처럼 앱 계층에 전파할 수 있죠
CoreMedia IO의 C 프로퍼티 인터페이스는 프로퍼티 선택자, 영역, 요소 식별을 위해 C 구조입니다 이게 어드레스로 여겨지고요
선택자는 네 글자로 된 코드로 프로퍼티의 이름입니다 custom의 'cust'같이요 영역은 전역적이거나 입력, 출력 영역일 수 있고 요소는 원하는 수 아무거나 가능합니다 주요 요소는 항상 0이고요 CMIOExtensions는 프로퍼티를 기존 세계와 연결해 줍니다 프로퍼티 어드레스 요소를 커스텀 프로퍼티명으로 코딩하죠 문자 4cc_ 다음에는 선택자, 영역, 요소 순입니다 네 자리로 된 코드가 _로 나뉘어져 있는데요 이렇게 문자열이나 데이터 값을 앱 계층에 전달할 수 있습니다
커스텀 프로퍼티는 AVFoundation에서 사용할 수 없어 CoreMedia IO C API를 유지해야 합니다 구성 앱에 커스텀 프로퍼티를 써야 한다면요 다만 이게 이 API의 전부는 아닙니다 이제 출력 디바이스에 대해 이야기해 보죠
DAL 플러그인의 기능 중 덜 알려진 건 출력 디바이스의 정반대를 제시할 수 있다는 겁니다 영상을 제공하기보다는 앱에서 실시간 스트리밍하죠 이건 CoreMedia IO에서 'O'에 해당합니다 입력과 출력이죠 출력 디바이스는 프로 세계에는 흔합니다 일부는 영상 시그널이 외부 레코더로 전송되거나 실시간 미리보기 모니터링이 이루어지는 경우에 해당되죠 SDI 입력의 프로 덱 같은 거죠
여기서 주목해야 할 건 출력 디바이스에는 AVFoundation API와 유사한 게 없단 겁니다 프레임을 출력 디바이스에 보내려면 CoreMedia IO C API를 직접 사용해야 하죠
CMIOExtension 스트림은 소스나 싱크의 지시로 만들어집니다 싱크 스트림은 앱에서 데이터를 소비합니다 클라이언트는 샘플 버퍼를 단순 대기열에 삽입해 싱크 스트림을 공급하는데 consumeSampleBuffer를 호출하는 겁니다 일단 해당 버퍼를 소비하면 notifyScheduledOutputChanged로 클라이언트에게 알리는 거고요
출력 디바이스에 대한 특정 스트림 프로퍼티는 많아요 시작 전 버퍼링 프레임 수 게산 모든 데이터 소비 시 신호 등 대기열 사이징을 주로 처리합니다
이제 마지막 주제로 넘어가 보죠
전반 부에 DAL 플러그인의 아키텍처를 보여드렸었는데요 DAL 플러그인의 보안 문제로 말씀드렸었습니다 Camera Extensions로 문제를 해결했고 지속 개발하려 전력을 다했죠 Camera Extensions은 우리의 미래입니다 그럼 그건 DAL 플러그인에 어떤 의미가 될까요? 바로 그 끝이 거의 다가왔단 뜻일 겁니다
macOS 12.3부터 이미 지원 중단 샅애거든요 따라서 만들 때 컴파일 경고를 받죠 시작은 좋았지만 여기까지 충분합니다 레거시 DAL 플러그인 로딩이 허용되는 한 카메라 앱에는 위험이 계속 존재하겠죠
모든 사용자에 대해 보안 취약성을 완전 해결하려면 macOS Ventura 이후 주요 발매 기기에서 DAL 플러그인 전체를 이용 못하게 해야 할 겁니다
이건 여러분들께 어떤 의미일까요? 어떤 의미인지 명확하게 전달되었길 바랍니다 현재도 DAL 플러그인을 사용 중이시라면 이제 Camera Extensions로 넘어가 보세요
그리고 꼭 만나는 문제점들을 알려주세요 우리는 문제를 해결해 많은 기능을 제공할 겁니다 여러분과 함께 할 날을 고대할게요 오늘 세션은 이만 마무리하겠습니다 여러분들께서 Mac에 어떤 카메라 경험을 가져다 주실지 기대되네요 즐겁게 해보시길 바랍니다 안녕히 계세요
-
-
찾고 계신 콘텐츠가 있나요? 위에 주제를 입력하고 원하는 내용을 바로 검색해 보세요.
쿼리를 제출하는 중에 오류가 발생했습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.