# Red Surface NVDEC 테스트 프로젝트 명세서 ## 프로젝트 개요 **프로젝트 명:** red-surface-nvdec **위치:** `vav2/platforms/windows/tests/red-surface-nvdec/` **타입:** Console Application (Headless Test) **목적:** NVDEC AV1 디코더의 D3D12 surface 렌더링을 픽셀 단위 stripe 패턴 검증을 통해 확인 ## 목표 1. **NVDEC AV1 Decoder 테스트** - 명시적으로 D3D12 surface 출력 사용 2. **NV12 Texture 생성 검증** - CUDA-D3D12 interop 확인 3. **픽셀 정확도 검증** - D3D12 surface 데이터를 CPU로 읽어서 확인 4. **Stripe 문제 탐지** - 모든 프레임에서 8픽셀 단위 빨강/검정 패턴 체크 ## 테스트 입력 파일 ### 테스트 비디오 (위치: `D:/Project/video-av1/sample/`) 1. **test_720p_stripe.webm** - 해상도: 1280x720 - 코덱: AV1 - 패턴: 8픽셀 세로 줄무늬 (검정-빨강-검정-빨강...) - 길이: 1초 (25 프레임) 2. **test_1080p_stripe.webm** - 해상도: 1920x1080 - 코덱: AV1 - 패턴: 8픽셀 세로 줄무늬 (검정-빨강-검정-빨강...) - 길이: 1초 (25 프레임) ### 예상 패턴 ``` X 좌표: 0-7 8-15 16-23 24-31 ... 픽셀 색상: 검정 빨강 검정 빨강 ... RGB 값: (0,0,0) (255,0,0) (0,0,0) (255,0,0) ``` ## 아키텍처 ### 컴포넌트 ``` RedSurfaceNVDECTest (Console App) ├── D3D12 Device Manager │ ├── D3D12 device 생성 (headless) │ ├── Command queue/list 생성 │ └── CUDA interop이 가능한 NV12 texture 생성 ├── VavCore 통합 │ ├── VavCore 초기화 │ ├── 테스트 비디오 파일 열기 │ ├── Decoder 타입을 NVDEC으로 명시적 설정 │ └── Zero-copy를 위한 D3D12 device 설정 ├── 프레임 디코딩 루프 │ ├── D3D12 surface로 프레임 디코딩 │ ├── NV12 texture를 CPU 메모리로 Readback │ └── Stripe 패턴 검증 └── 픽셀 검증 ├── NV12 → RGB 변환 ├── 8픽셀 stripe 패턴 체크 └── 프레임별 pass/fail 리포트 ``` ## 테스트 플로우 ### 1. 초기화 단계 ```cpp // Step 1: D3D12 device 생성 (headless) ID3D12Device* device = CreateD3D12Device(); // Step 2: VavCore 초기화 vavcore_initialize(); // Step 3: VavCore player 생성 VavCorePlayer* player = vavcore_create_player(); // Step 4: Decoder 타입을 NVDEC으로 명시적 설정 vavcore_set_decoder_type(player, VAVCORE_DECODER_NVDEC); // Step 5: Zero-copy를 위한 D3D12 device 설정 vavcore_set_d3d_device(player, device, VAVCORE_SURFACE_D3D12); // Step 6: 테스트 비디오 열기 vavcore_open_file(player, "test_720p_stripe.webm"); ``` ### 2. 디코딩 단계 ```cpp for each frame: // Step 1: 이 프레임을 위한 NV12 texture 생성 ID3D12Resource* nv12Texture = CreateNV12Texture(width, height); // Step 2: D3D12 surface로 프레임 디코딩 result = vavcore_decode_to_surface( player, VAVCORE_SURFACE_D3D12, nv12Texture ); // Step 3: D3D12 texture를 CPU로 Readback uint8_t* cpuBuffer = ReadbackD3D12Texture(nv12Texture); // Step 4: Stripe 패턴 검증 bool passed = VerifyStripePattern(cpuBuffer, width, height); printf("Frame %d: %s\n", frameIndex, passed ? "PASS" : "FAIL"); ``` ### 3. 검증 로직 ```cpp bool VerifyStripePattern(uint8_t* nv12Data, int width, int height) { // NV12를 RGB로 변환 RGB* rgbData = ConvertNV12ToRGB(nv12Data, width, height); // 첫 번째 행 체크 (대표값) for (int x = 0; x < width; x++) { int stripeIndex = x / 8; // 8픽셀 stripe 폭 bool shouldBeRed = (stripeIndex % 2) == 1; RGB pixel = rgbData[x]; if (shouldBeRed) { // 빨강 기대: R=255, G=0, B=0 (오차 허용) if (pixel.r < 200 || pixel.g > 50 || pixel.b > 50) { printf("FAIL at X=%d: Expected red, got RGB(%d,%d,%d)\n", x, pixel.r, pixel.g, pixel.b); return false; } } else { // 검정 기대: R=0, G=0, B=0 (오차 허용) if (pixel.r > 50 || pixel.g > 50 || pixel.b > 50) { printf("FAIL at X=%d: Expected black, got RGB(%d,%d,%d)\n", x, pixel.r, pixel.g, pixel.b); return false; } } } return true; } ``` ## 기술 요구사항 ### 의존성 1. **VavCore Library** - Link: `VavCore-debug.lib` - Include: `VavCore/VavCore.h` 2. **D3D12** - Headers: `d3d12.h`, `dxgi1_6.h` - Libraries: `d3d12.lib`, `dxgi.lib` 3. **CUDA** (interop 검증용) - Headers: `cuda.h`, `cuda_d3d12_interop.h` - Libraries: `cuda.lib` ### 빌드 설정 - **플랫폼:** x64 - **구성:** Debug - **C++ 표준:** C++17 - **문자 집합:** Unicode - **하위 시스템:** Console ### Include 디렉토리 ``` $(ProjectDir)..\..\vavcore\include $(CUDA_PATH)\include ``` ### Library 디렉토리 ``` $(ProjectDir)..\..\vavcore\lib $(CUDA_PATH)\lib\x64 ``` ### 추가 종속성 ``` VavCore-debug.lib d3d12.lib dxgi.lib cuda.lib kernel32.lib user32.lib ``` ## 성공 기준 ### Pass 조건 1. **모든 프레임이 에러 없이 디코딩 성공** 2. **모든 프레임에서 stripe 패턴 검증 성공** 3. **UV plane copy 에러 없음** (이전 문제 해결 확인) 4. **시각적 artifact 없음** (stripe 정렬이 정확함) ### 출력 포맷 ``` [RedSurfaceNVDECTest] 테스트 시작... [RedSurfaceNVDECTest] 비디오: test_720p_stripe.webm (1280x720) [RedSurfaceNVDECTest] 디코더: NVDEC (명시적) [RedSurfaceNVDECTest] Surface: D3D12 Frame 0: PASS (25/25 stripe checks passed) Frame 1: PASS (25/25 stripe checks passed) Frame 2: PASS (25/25 stripe checks passed) ... Frame 24: PASS (25/25 stripe checks passed) [RedSurfaceNVDECTest] 결과: 25/25 프레임 PASSED [RedSurfaceNVDECTest] 테스트 성공 ``` ### 실패 출력 ``` Frame 5: FAIL at X=64: Expected red, got RGB(128,0,0) Frame 5: FAIL at X=72: Expected red, got RGB(64,0,0) Frame 5: Stripe pattern verification failed (2 errors) [RedSurfaceNVDECTest] 결과: 24/25 프레임 PASSED [RedSurfaceNVDECTest] 테스트 실패 ``` ## 테스트 대상 알려진 문제 ### 현재 문제 (이전 분석에서) 1. **UV plane copy failed: invalid argument** - 에러 코드: 1 (cudaMemcpy2D) - 원인: 불명 (texture height padding 불일치?) 2. **렌더링된 비디오의 Stripe artifacts** - 증상: 세로 줄무늬 또는 패턴 왜곡 - 원인: 불명 (pitch 불일치? UV offset 잘못됨?) 3. **D3D12 texture 할당 padding** - 할당된 높이: 2288 - 논리적 높이: 2160 - NVDEC과 D3D12 간의 UV offset 불일치 ### 예상 결과 - **테스트 통과 시:** NVDEC decoder와 D3D12 interop이 정상 작동 - **테스트 실패 시:** 정확히 어느 프레임/픽셀에서 손상이 발생하는지 식별 - **진단 가치:** 픽셀 레벨 검증으로 근본 원인 파악 ## 파일 구조 ``` vav2/platforms/windows/tests/red-surface-nvdec/ ├── RedSurfaceNVDECTest.vcxproj # MSBuild 프로젝트 파일 ├── src/ │ ├── main.cpp # Entry point │ ├── D3D12Manager.h # D3D12 device/resource 관리 │ ├── D3D12Manager.cpp │ ├── PixelVerifier.h # NV12→RGB + stripe 검증 │ ├── PixelVerifier.cpp │ └── VavCoreWrapper.h # VavCore 통합 │ VavCoreWrapper.cpp ├── bin/Debug/ # 출력 디렉토리 └── obj/Debug/ # 중간 파일 ``` ## 구현 계획 ### Phase 1: 프로젝트 설정 - .vcxproj 파일 생성 - 빌드 설정 구성 - VavCore 및 D3D12 라이브러리 링크 ### Phase 2: D3D12 인프라 - D3D12Manager 클래스 구현 - Device 생성 (headless) - NV12 texture 생성 - Texture readback (D3D12 → CPU) ### Phase 3: VavCore 통합 - VavCoreWrapper 클래스 구현 - VavCore 초기화 - 비디오 파일 열기 - D3D12 surface로 프레임 디코딩 ### Phase 4: 픽셀 검증 - PixelVerifier 클래스 구현 - NV12 → RGB 변환 - 8픽셀 stripe 패턴 체커 - 프레임별 리포팅 ### Phase 5: 테스트 - test_720p_stripe.webm으로 테스트 - test_1080p_stripe.webm으로 테스트 - 모든 프레임 통과 확인 ## 참조 - VavCore API: `vav2/platforms/windows/vavcore/include/VavCore/VavCore.h` - D3D12 문서: Microsoft Docs - NVDEC 구현: `vav2/platforms/windows/vavcore/src/Decoder/NVDECAV1Decoder.cpp` - 기존 테스트: `vav2/platforms/windows/tests/headless/SimpleVavCoreTest.vcxproj`