Files
video-v1/todo32.txt
ened 1223546fde Failed configuration
Vulkan 스펙 12.2.4에 따르면, YCbCr conversion을 사용하는 descriptor는 두 가지 방식 중 하나를 선택해야 합니다:

  1. Immutable samplers - descriptor set layout 생성 시 sampler 고정
  2. UPDATE_AFTER_BIND - 프레임마다 sampler 업데이트 허용
2025-11-20 21:28:08 +09:00

198 lines
7.7 KiB
Plaintext

vav2/platforms/windows/vavcore/src/VavCore.cpp 의 구현을 플랫폼별로 나누자. Windows 는 VavCore_Windows.cpp,
Android 는 VavCore_Android.cpp, iOS/macOS는 VavCore_Apple.cpp 형태로 나누자.
vav2 의 vavcore android 구현체에서 코드를 검토해보자. 오랫동안 해결하지 못한 Vulkan AV1 Decoding 에서 퀄컴기반의 CPU에서 AV1 decoding 처리에서 텍스처 색상이
이상하게 나오는 현상이 있다. windows_screenshot.png 가 정상적인 영상의 출력이고, 현재는 screenshot_final.png 처럼 출력이 되고 있다. 원인을 진단해보고
구체적으로 수정이 가능한지 검토만 해봐줘.
● 좋습니다! screenshot_fixed.png도 비슷한 왜곡이 있네요. 이제 실제 근본 원인을 찾았습니다.
🔍 재진단: 실제 문제
3가지 스크린샷 모두 동일한 패턴의 색상 왜곡이 있습니다:
- 마젠타/퍼플 배경
- 그린 톤 피부
- 전체적으로 차갑고 불쾌한 색상
이것은 컴포넌트 스왑 문제가 아니라 YCbCr→RGB 변환 매트릭스 문제입니다.
핵심 원인
392-393번 라인에서 MediaCodec이 제안하는 YCbCr 모델을 사용:
ycbcrConversionCreateInfo.ycbcrModel = static_cast<VkSamplerYcbcrModelConversion>(ahb_format_props.suggestedYcbcrModel);
ycbcrConversionCreateInfo.ycbcrRange = static_cast<VkSamplerYcbcrRange>(ahb_format_props.suggestedYcbcrRange);
문제는: MediaCodec이 퀄컴에서 잘못된 YCbCr 모델을 제안할 가능성이 있습니다.
VkSamplerYcbcrModelConversion 값
Vulkan 스펙에 따르면:
- VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY = 0 - RGB 패스스루 (YCbCr 변환 없음)
- VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY = 1 - YCbCr 패스스루 (변환 없음)
- VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709 = 2 - BT.709 (HD 비디오 표준)
- VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601 = 3 - BT.601 (SD 비디오 표준)
- VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 = 4 - BT.2020 (UHD)
VkSamplerYcbcrRange 값
- VK_SAMPLER_YCBCR_RANGE_ITU_FULL = 0 - Full range (0-255)
- VK_SAMPLER_YCBCR_RANGE_ITU_NARROW = 1 - Studio range (16-235 for Y, 16-240 for CbCr)
---
💡 해결 방법
테스트가 필요한 조합
현재 로그가 없어서 MediaCodec이 어떤 값을 제안하는지 모르지만, 일반적으로 AV1 비디오는:
- BT.709 색공간 (HD 이상)
- Studio range (16-235)
를 사용합니다.
Option 4: 강제 BT.709 + Studio Range 설정
MediaCodec 제안을 무시하고 표준 값 사용:
// 392-393번 라인을 다음으로 교체:
// WORKAROUND: Force BT.709 + Studio range for AV1 content
// MediaCodec may suggest incorrect YCbCr model on Qualcomm devices
ycbcrConversionCreateInfo.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709; // BT.709
ycbcrConversionCreateInfo.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW; // Studio range (16-235)
LogInfo(" FORCED BT.709 + Studio range (workaround for Qualcomm)");
Option 5: 조건부 오버라이드
퀄컴에서만 강제 설정:
// 392-393번 라인을 다음으로 교체:
if (is_qualcomm_gpu) {
// WORKAROUND: Qualcomm MediaCodec may suggest incorrect YCbCr model for AV1
ycbcrConversionCreateInfo.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709;
ycbcrConversionCreateInfo.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW;
LogInfo(" FORCED BT.709 + Studio range (Qualcomm workaround)");
LogInfo(" MediaCodec suggested model: " + std::to_string(ahb_format_props.suggestedYcbcrModel) + " (ignored)");
LogInfo(" MediaCodec suggested range: " + std::to_string(ahb_format_props.suggestedYcbcrRange) + " (ignored)");
} else {
ycbcrConversionCreateInfo.ycbcrModel = static_cast<VkSamplerYcbcrModelConversion>(ahb_format_props.suggestedYcbcrModel);
ycbcrConversionCreateInfo.ycbcrRange = static_cast<VkSamplerYcbcrRange>(ahb_format_props.suggestedYcbcrRange);
LogInfo(" Using MediaCodec suggested YCbCr model and range");
}
Option 6: BT.601 테스트 (SD 비디오)
만약 비디오가 SD (720p 이하)라면:
ycbcrConversionCreateInfo.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601; // BT.601
ycbcrConversionCreateInfo.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW;
---
🎯 추천 접근법
1. 먼저 로그 수집 - MediaCodec이 실제로 어떤 값을 제안하는지 확인
2. Option 5 적용 - 퀄컴에서만 BT.709 + Studio range 강제
3. 효과 없으면 Option 6 - BT.601 테스트
4. 여전히 안되면 - Full range (VK_SAMPLER_YCBCR_RANGE_ITU_FULL) 테스트
---
✅ Option 5 적용 완료
변경 내용
파일: vav2/platforms/windows/vavcore/src/Decoder/MediaCodecSurfaceManager.cpp:391-408
변경 사항:
- 퀄컴 GPU 감지 시 BT.709 + Studio range 강제 적용
- MediaCodec이 제안하는 YCbCr 모델/범위를 무시
- 다른 GPU는 기존대로 MediaCodec 제안 사용
빌드 및 테스트 방법
# 1. VavCore 라이브러리 빌드 (ARM64)
cd /d/Project/video-av1/vav2/platforms/android/vavcore
cmd /c "build_vavcore_android.bat arm64"
# 2. Android 앱 빌드 및 설치
cd ../applications/vav2player
./gradlew assembleDebug
adb install -r app/build/outputs/apk/debug/app-debug.apk
# 3. 비디오 재생 테스트
adb shell "am start -n com.vavcore.player/.MainActivity --es filepath '/sdcard/Download/test_video.webm'"
# 4. 로그 확인
adb logcat | grep -E "(VavCore-SurfaceManager|FORCED BT.709)"
예상 로그 출력
퀄컴 디바이스에서 다음과 같은 로그가 보여야 합니다:
VavCore-SurfaceManager: Qualcomm Adreno GPU detected → Using NV12 format with BT.601
VavCore-SurfaceManager: FORCED BT.709 + Studio range (Qualcomm workaround)
VavCore-SurfaceManager: MediaCodec suggested model: X (ignored)
VavCore-SurfaceManager: MediaCodec suggested range: Y (ignored)
VavCore-SurfaceManager: YcbcrModel: 2
VavCore-SurfaceManager: YcbcrRange: 1
- YcbcrModel: 2 = BT.709
- YcbcrRange: 1 = Studio range (16-235)
---
🔄 Option 6 준비 완료
만약 Option 5가 효과가 없으면, 다음과 같이 Option 6 (BT.601) 을 적용할 수 있습니다:
변경할 라인: MediaCodecSurfaceManager.cpp:394
// Option 6: BT.601로 변경
ycbcrConversionCreateInfo.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601; // BT.601 (SD)
또는 Full range 테스트:
// Option 6-2: Full range로 변경
ycbcrConversionCreateInfo.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL; // Full range (0-255)
---
Option 5 테스트 후 결과를 알려주시면, 필요 시 Option 6을 바로 적용하겠습니다!
● 아! 발견했습니다! 매우 중요한 문제를 찾았습니다!
🚨 핵심 문제 발견!
vulkan_renderer.cpp:1324-1352를 보면:
일반 VkSampler를 사용하고 있습니다!
YCbCr 텍스처를 샘플링할 때는 반드시 VkSamplerYcbcrConversionInfo를 sampler에 연결해야 하는데, 현재 코드는 그냥 일반 sampler를 만들고 있습니다!
MediaCodecSurfaceManager에서 VkSamplerYcbcrConversion을 생성했지만, vulkan_renderer.cpp가 이것을 사용하지 않고 있습니다!
이제 수정 방법을 제시하겠습니다.
1. ✅ YCbCr 변환 설정 - 모든 조합 시도했지만 동일
2. ✅ 컴포넌트 매핑 - 여러 조합 시도했지만 동일
3. ✅ Sampler에 YCbCr conversion 연결 - 이미 올바르게 구현됨
MediaCodec에 출력 컬러 포맷을 명시적으로 지정
// MediaCodec에 명시적으로 YUV 420 Flexible 포맷 요청
AMediaFormat_setInt32(m_format, AMEDIAFORMAT_KEY_COLOR_FORMAT, 0x7F420888);
COLOR_FormatYUV420Flexible은 Android가 정의한 플랫폼 독립적인 YUV 420 포맷으로, 벤더별 구현 차이를 추상화합니다.