Insta360–Unity streaming plugin
CrossGaussian에는 사전에 만든 3D 장면뿐 아니라 현장의 현재 모습도 필요했다. 이를 위해 Insta360 X3가 보내는 실시간 영상을 Unity 안에서 바로 보여 주는 Windows 네이티브 플러그인을 구현했다.
카메라 SDK에서 앞·뒤 렌즈의 H.264 스트림을 받아 각각 디코딩하고, 네이티브 플러그인과 C# 스크립트를 거쳐 Unity의 듀얼 fish-eye skybox에 연결했다.
영상 디코딩과 텍스처 갱신
카메라에서 받은 H.264 패킷은 Unity에서 곧바로 쓸 수 있는 이미지가 아니다. FFmpeg의 NVIDIA 하드웨어 디코더로 패킷을 풀고, NPP로 NV12 프레임의 색 공간을 변환했다. 카메라 콜백과 Unity 렌더 스레드가 같은 데이터에 동시에 접근하지 않도록 앞·뒤 렌즈의 프레임은 각각 별도 큐에 담았다.
Unity에서는 렌더 이벤트가 발생할 때 큐에서 프레임을 꺼내 RGBA 텍스처를 갱신했다. 카메라 콜백과 Unity 렌더링이 서로 다른 시점에 실행되므로 프레임 수신과 텍스처 갱신도 분리했다.
Direct3D 12 전환
처음에는 Direct3D 11을 사용하는 CrossGaussian에 맞춰 플러그인을 구현했다. 이후 프로젝트의 그래픽스 API를 Direct3D 12로 바꾸면서 플러그인의 텍스처 처리도 함께 변경했다.
플러그인의 역할은 그대로였고, 프로젝트 환경에 맞춰 그래픽스 API와 프레임 전달 방식을 수정했다.
구현 범위
카메라 연결에는 Insta360 Camera SDK를 사용했다. 영상 디코딩에는 FFmpeg와 NVIDIA CUDA를, 색 변환에는 NVIDIA NPP를 사용했다. 그래픽스 API 골격과 Unity 인터페이스 헤더는 Unity의 Native Rendering Plugin 예제를 기반으로 한다. 나는 여기에 카메라 스트림 수신과 앞·뒤 프레임 처리, Unity 렌더 이벤트와 텍스처 갱신, 듀얼 fish-eye skybox 연동을 추가했다.
현재 한계
현재 구현은 GPU에서 디코딩한 프레임을 CPU 메모리로 내린 뒤 Direct3D 12 텍스처로 다시 올린다. 영상은 실시간으로 표시되지만 불필요한 GPU–CPU 왕복 복사가 남아 있다. Insta360 X3 이외의 카메라와 다양한 GPU·드라이버·Unity 버전에서도 동작하는지는 확인하지 못했다. 지연 시간과 프레임 손실, 장시간 실행 안정성도 같은 조건에서 반복 측정한 자료가 없다.
다시 개선한다면 먼저 카메라 입력부터 화면 표시까지 구간별 지연과 프레임 손실을 측정하겠다. 그 결과를 기준으로 CUDA와 Direct3D 리소스를 직접 공유하는 경로를 설계하겠다. 복사를 줄이기 전후의 차이도 같은 조건에서 비교할 것이다.