Files
video-v1/vav2/docs/working/red-surface-nvdec-spec.md
2025-10-04 02:38:47 +09:00

8.6 KiB

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. 초기화 단계

// 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. 디코딩 단계

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. 검증 로직

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