Move old notes
This commit is contained in:
132
vav2/notes/av1-dpb.txt
Normal file
132
vav2/notes/av1-dpb.txt
Normal file
@@ -0,0 +1,132 @@
|
||||
|
||||
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ > NVDEC API 에 관해서 질문이 있다. 각 프레임을 디코딩해서 Video Frame 으로 얻어 와서 cuvidMapVideoFrame() 를 통해서 실제 │
|
||||
│ frame data 를 얻어온다. │
|
||||
│ 그런데 AV1 디코딩은 최대 16개 이상의 프레임을 보관했다가, frame reordering 에 의해서 이전에 디코딩했던 프레임을 화면에 │
|
||||
│ 렌더링할 경우가 있다. NVDEC 에서 video frame 에 대해서 캐싱을 지원하고 있는지 궁금하다. 현재까지의 실험으로는 캐싱을 하지 │
|
||||
│ 않는 것으로 밝혀졌는데, 사실인지 검증이 필요하다. 필요하면 웹서칭을 통해서 사실 검증을 진행해도 좋다. │
|
||||
│ 만약, video frame 캐싱을 지원하지 않는다면 NVDEC API 로 비디오 렌더링을 구현할 때 사용자가 직접 16개의 프레임을 직접 │
|
||||
│ 캐싱해서 보관해야 하는지 궁금하고, D3D12 texture 에 렌더링까지 해서 캐싱하는 것이 유리할지 (메모리나 연산 측면에서), │
|
||||
│ 아니면 CUDA video frame 으로 캐싱을 가지고 있다가, 나중에 D3D12 texture 로 렌더링할 때 그 때 데이터 변환을 수행하는 것이 │
|
||||
│ 좋은지도 궁금하다. │
|
||||
│ 결론으로 AV1 frame format 의 순서와 렌더링 순서는 서로 뒤바뀌는 현상이 있어서 16개의 frame 정도는 캐싱할 필요가 있는데, │
|
||||
│ NVDEC CUDA layer 에서 이를 지원해주는지, 지원해주지 않는다면 application 에서 어떻게 캐싱을 구현하는 것이 좋은지 │
|
||||
│ 메모리/연산 측면에서 효율적인 방안에 대해서 검토를 부탁한다. │
|
||||
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
|
||||
✦ 훌륭한 질문입니다. AV1 디코딩과 NVDEC API의 동작 방식, 그리고 애플리케이션 레벨에서의 효율적인 렌더링 전략에 대한 핵심적인
|
||||
내용이 모두 포함되어 있습니다. 질문을 세 부분으로 나누어 상세히 답변해 드리겠습니다.
|
||||
|
||||
|
||||
1. NVDEC API는 프레임 캐싱/재정렬을 지원하는가?
|
||||
- NVDEC의 역할: NVDEC는 저수준(low-level) 하드웨어 가속 디코더입니다. 주된 역할은 압축된 비디오 비트스트림(AV1, HEVC 등)을
|
||||
입력받아 디코딩된 원본 비디오 프레임(YUV 포맷)을 최대한 빨리 GPU 메모리에 출력하는 것입니다. 즉, 디코딩 순서(Decode
|
||||
Order)대로 동작합니다.
|
||||
따라서 AV1처럼 프레임 재정렬이 필수적인 코덱을 사용하려면, 사용자가 말씀하신 대로 애플리케이션에서 직접 최대 16개(또는 그
|
||||
이상)의 프레임을 보관할 캐시(버퍼)를 구현해야 합니다.
|
||||
|
||||
---
|
||||
|
||||
|
||||
2. 프레임 캐싱 구현 방안: CUDA Frame vs D3D12 Texture
|
||||
방안 A: CUDA 비디오 프레임(CUvideoptr)으로 캐싱
|
||||
- 동작 방식:
|
||||
- 장점:
|
||||
- 단점:
|
||||
- 동작 방식:
|
||||
- 단점:
|
||||
압도적으로 `방안 A`, 즉 CUDA 비디오 프레임 형태로 캐싱하는 것을 권장합니다.
|
||||
|
||||
현대적인 고성능 비디오 플레이어는 모두 이 방식을 사용합니다. 이유는 다음과 같습니다.
|
||||
|
||||
|
||||
1. 메모리가 핵심입니다: 비디오 재생, 특히 4K/8K 고해상도 비디오에서 가장 큰 병목은 VRAM입니다. CUDA 프레임(NV12)으로 캐싱하는
|
||||
것은 D3D12 RGB 텍스처로 캐싱하는 것에 비해 VRAM을 절반 이하로 사용하므로, 더 높은 해상도와 더 많은 캐시 프레임을
|
||||
안정적으로 유지할 수 있습니다.
|
||||
- NVDEC는 프레임 재정렬을 해주지 않으므로, 애플리케이션에서 직접 프레임 캐시(DPB)를 구현해야 합니다.
|
||||
|
||||
╭──────────────╮
|
||||
│ > continue │
|
||||
╰──────────────╯
|
||||
|
||||
✦ 알겠습니다. 이어서 NVDEC와 D3D12를 사용한 고성능 비디오 렌더링 파이프라인을 구축할 때 고려해야 할 추가적인 기술적 세부사항과
|
||||
구현 팁에 대해 설명하겠습니다.
|
||||
|
||||
|
||||
4. 애플리케이션 DPB(Decoded Picture Buffer) 구현 전략
|
||||
CUDA 프레임 인덱스를 캐싱하기로 결정했으니, 이제 이 DPB를 어떻게 효율적으로 관리할지에 대한 구체적인 전략이 필요합니다.
|
||||
|
||||
|
||||
- 자료구조 선택:
|
||||
- 버퍼 관리 로직:
|
||||
5. CUDA-D3D12 Interoperability 심화
|
||||
1. 외부 메모리 할당: cuvidCtxLock으로 컨텍스트를 잠근 후, cuMemCreate를 사용하여 외부 메모리 핸들(External Memory Handle)을
|
||||
생성할 D3D12 리소스(ID3D12Resource)를 준비합니다. 이 리소스는 디코더의 출력 포맷(예: DXGI_FORMAT_NV12)과 일치해야 합니다.
|
||||
|
||||
이 방식은 NVDEC가 직접 D3D12 리소스에 디코딩 결과를 쓰는 가장 효율적인 경로입니다. cuvidMapVideoFrame을 사용하는 것보다 한
|
||||
단계 더 최적화된 방법이라고 할 수 있습니다.
|
||||
|
||||
### 6. 동기화 문제 (Synchronization)
|
||||
|
||||
CUDA와 D3D12는 서로 다른 비동기식 커맨드 큐를 사용하므로, 둘 사이의 작업 순서를 보장하기 위한 명시적인 동기화가 필수적입니다.
|
||||
|
||||
|
||||
- `cudaExternalSemaphore` 사용:
|
||||
이러한 동기화는 파이프라인의 안정성을 보장하고, 리소스 접근 충돌로 인한 크래시나 깨진 화면을 방지하는 데 매우 중요합니다.
|
||||
|
||||
### 최종 요약 및 제언
|
||||
|
||||
|
||||
- DPB 관리: PTS를 키로 사용하는 맵을 구현하고, pfnDisplayPicture 콜백을 통해 표시할 프레임을 식별하며, 더 이상 필요 없는
|
||||
프레임은 즉시 해제하여 디코더 버퍼 고갈을 방지하세요.
|
||||
이러한 개념들을 VavCore 프로젝트에 적용한다면, CPU 부하를 최소화하면서 매우 높은 성능을 내는 하드웨어 가속 비디오 플레이어를
|
||||
구현할 수 있을 것입니다. 현재 VavCore의 아키텍처는 이러한 저수준 최적화를 적용하기에 매우 적합한 구조로 보입니다.
|
||||
|
||||
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ > NVDEC API 에 관해서 질문이 있다. 각 프레임을 디코딩해서 Video Frame 으로 얻어 와서 cuvidMapVideoFrame() 를 통해서 실제 │
|
||||
│ frame data 를 얻어온다. │
|
||||
│ 그런데 AV1 디코딩은 최대 16개 이상의 프레임을 보관했다가, frame reordering 에 의해서 이전에 디코딩했던 프레임을 화면에 │
|
||||
│ 렌더링할 경우가 있다. NVDEC 에서 video frame 에 대해서 캐싱을 지원하고 있는지 궁금하다. 현재까지의 실험으로는 캐싱을 하지 │
|
||||
│ 않는 것으로 밝혀졌는데, 사실인지 검증이 필요하다. 필요하면 웹서칭을 통해서 사실 검증을 진행해도 좋다. │
|
||||
│ 만약, video frame 캐싱을 지원하지 않는다면 NVDEC API 로 비디오 렌더링을 구현할 때 사용자가 직접 16개의 프레임을 직접 │
|
||||
│ 캐싱해서 보관해야 하는지 궁금하고, D3D12 texture 에 렌더링까지 해서 캐싱하는 것이 유리할지 (메모리나 연산 측면에서), │
|
||||
│ 아니면 CUDA video frame 으로 캐싱을 가지고 있다가, 나중에 D3D12 texture 로 렌더링할 때 그 때 데이터 변환을 수행하는 것이 │
|
||||
│ 좋은지도 궁금하다. │
|
||||
│ 결론으로 AV1 frame format 의 순서와 렌더링 순서는 서로 뒤바뀌는 현상이 있어서 16개의 frame 정도는 캐싱할 필요가 있는데, │
|
||||
│ NVDEC CUDA layer 에서 이를 지원해주는지, 지원해주지 않는다면 application 에서 어떻게 캐싱을 구현하는 것이 좋은지 │
|
||||
│ 메모리/연산 측면에서 효율적인 방안에 대해서 검토를 부탁한다. │
|
||||
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
|
||||
✦ 네, 다시 한번 질문의 핵심을 요약하고 명확히 답변해 드리겠습니다. 이전에 답변 드린 내용의 핵심을 정리하는 방식으로
|
||||
설명하겠습니다.
|
||||
|
||||
### 질문 요약
|
||||
|
||||
|
||||
1. NVDEC의 자동 캐싱/재정렬 지원 여부: AV1의 프레임 재정렬에 필요한 캐싱(버퍼링)을 NVDEC가 자동으로 처리해주는가?
|
||||
1. NVDEC의 자동 캐싱 지원 여부: 지원하지 않음
|
||||
- 사용자의 실험 결과가 정확합니다. NVDEC는 디코딩 순서(Decode Order)에 따라 비디오 프레임을 생성할 뿐, 표시
|
||||
순서(Presentation Order)에 맞춰 프레임을 캐싱하거나 재정렬하는 기능은 제공하지 않습니다.
|
||||
메모리와 연산 효율성을 종합적으로 고려했을 때, 디코딩된 CUDA 비디오 프레임(`CUvideoptr` 또는 관련 인덱스) 형태로 캐싱하는
|
||||
것이 압도적으로 유리합니다.
|
||||
|
||||
|
||||
| 항목 | 방안 A: CUDA 프레임으로 캐싱 (권장) | 방안 B: D3D12 텍스처로 캐싱 |
|
||||
| :--- | :--- | :--- |
|
||||
| 메모리 효율성 | 매우 높음. YUV(NV12 등) 포맷으로 저장하여 VRAM 사용량 최소화. (RGB 대비 1/2 ~ 1/3 수준) | 매우 낮음. 비압축
|
||||
RGB 포맷으로 저장하여 VRAM 사용량 극대화. 고해상도에서 치명적. |
|
||||
| 렌더링 시 연산 | YUV->RGB 색상 변환 셰이더 실행 필요. (현대 GPU에서 부담이 거의 없는 저비용 연산) | 이미 변환된 텍스처를
|
||||
복사(Blit)만 하면 됨. (연산 비용 가장 낮음) |
|
||||
| 구현 복잡도 | 렌더링 시 색상 변환 로직이 추가되나, 표준적인 방식. | 렌더링 로직은 단순해지나, 디코딩 직후 변환 과정이
|
||||
추가됨. |
|
||||
| 유연성 | 렌더링 시점에 색 공간, 톤 매핑 등을 유연하게 변경 가능. | 모든 효과가 미리 적용된 상태로 '구워져' 유연성 낮음. |
|
||||
|
||||
### 최종 결론
|
||||
|
||||
|
||||
AV1의 프레임 재정렬 문제를 해결하기 위해 애플리케이션에서 직접 프레임 버퍼를 구현해야 하며, VRAM을 효율적으로 사용하기 위해
|
||||
디코딩된 프레임을 원본 YUV 포맷(CUDA 프레임) 그대로 버퍼에 저장하고, 실제 화면에 렌더링하는 시점에 셰이더를 통해 실시간으로
|
||||
YUV->RGB 색상 변환을 수행하는 것이 최적의 방안입니다.
|
||||
|
||||
|
||||
이 방식은 현대적인 고성능 비디오 플레이어의 표준적인 아키텍처입니다.
|
||||
Reference in New Issue
Block a user