diff --git a/.claude/settings.local.json b/.claude/settings.local.json
index 6a13d8f..0a4d4ae 100644
--- a/.claude/settings.local.json
+++ b/.claude/settings.local.json
@@ -19,30 +19,17 @@
"Bash(start Vav1Player.exe)",
"Bash(dotnet run:*)",
"Bash(cmake:*)",
- "Bash(\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\MSBuild.exe\" \"Vav2Player.vcxproj\" \"/p:Configuration=Release\" \"/p:Platform=x64\")",
"Bash(msbuild:*)",
- "Bash(\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\MSBuild.exe\" Vav2Player.vcxproj /p:Configuration=Debug /p:Platform=x64 /v:minimal)",
"Read(//c/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/**)",
- "Bash(\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\MSBuild.exe\" /noautoresponse Vav2Player.vcxproj /p:Configuration=Debug /p:Platform=x64)",
- "Bash(\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\MSBuild.exe\" Vav2Player.vcxproj /p:Configuration=Debug /p:Platform=x64)",
- "Bash(\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\MSBuild.exe\" Vav2Player.vcxproj \"/p:Configuration=Debug\" \"/p:Platform=x64\")",
"Bash(cmd /c:*)",
- "Bash(\"C:/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" Vav2Player.vcxproj \"/p:Configuration=Debug\" \"/p:Platform=x64\")",
- "Bash(\"C:/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" Vav2Player.vcxproj /p:Configuration=Debug /p:Platform=x64)",
"Bash(dir:*)",
"Bash(set MSBUILD_EXE=\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\MSBuild\\Current\\Bin\\MSBuild.exe\")",
"Bash(%MSBUILD_EXE% \"Vav2Player.sln\" /p:Configuration=Debug /p:Platform=x64 /m)",
- "Bash(/c/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe Vav2Player.vcxproj //p:Configuration=Debug //p:Platform=x64 //v:minimal)",
- "Bash(python:*)",
"Bash(start:*)",
- "Bash(\"/c/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" Vav2Player.vcxproj //p:Configuration=Debug //p:Platform=x64 //v:minimal)",
- "Bash(\"/c/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" Vav2Player.vcxproj /p:Configuration=Debug /p:Platform=x64 /v:minimal)",
"Bash(\"/c/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" Vav2PlayerHeadless.vcxproj //p:Configuration=Debug //p:Platform=x64 //v:minimal)",
"Bash(\"./Vav2PlayerHeadless.exe\")",
"Bash(\"./x64/Debug/Headless/Vav2PlayerHeadless.exe\" \"D:\\Project\\video-av1\\sample\\output.webm\")",
"Bash(\".\\Vav2PlayerHeadless.exe\" \"D:\\Project\\video-av1\\sample\\simple_test.webm\")",
- "Bash(\"/c/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" Vav2Player.vcxproj \"/p:Configuration=Debug\" \"/p:Platform=x64\" \"/v:minimal\")",
- "Bash(\"C:/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" Vav2Player.vcxproj //p:Configuration=Debug //p:Platform=x64 //v:minimal)",
"Bash(\"/c/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" \"/d/Project/video-av1/vav2/Vav2Player/Vav2Player/Vav2Player.vcxproj\" //p:Configuration=Debug //p:Platform=x64 //v:minimal)",
"Bash(\"/c/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" \"/d/Project/video-av1/vav2/Vav2Player/Vav2Player/Vav2PlayerHeadless.vcxproj\" //p:Configuration=Debug //p:Platform=x64 //v:minimal)",
"Bash(\"./Vav2PlayerHeadless.exe\" \"D:/Project/video-av1/sample/simple_test.webm\")",
@@ -52,24 +39,10 @@
"Bash(%MSBUILD_EXE% \"Vav2Player.vcxproj\" /p:Configuration=Debug /p:Platform=x64 /m)",
"Bash(.Vav2PlayerHeadless.exe \"D:\\Project\\video-av1\\sample\\simple_test.webm\")",
"Bash(.Vav2PlayerHeadless.exe \"D:/Project/video-av1/sample/simple_test.webm\")",
- "Bash(\"D:\\Project\\video-av1\\vav2\\Vav2Player\\Vav2Player\\x64\\Debug\\Headless\\Vav2PlayerHeadless.exe\" \"D:/Project/video-av1/sample/simple_test.webm\")",
"Bash(\"/c/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" \"D:/Project/video-av1/vav2/Vav2Player/Vav2Player/Vav2Player.vcxproj\" \"/p:Configuration=Debug\" \"/p:Platform=x64\" \"/v:minimal\")",
"Bash(\"/c/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" \"D:/Project/video-av1/vav2/Vav2Player/Vav2Player/Vav2Player.vcxproj\" \"//p:Configuration=Debug\" \"//p:Platform=x64\" \"//v:minimal\")",
- "Bash(\"C:/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" /noautoresponse Vav2Player.vcxproj /p:Configuration=Debug /p:Platform=x64)",
"Bash(timeout:*)",
- "Bash(\"/c/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" /noautoresponse Vav2PlayerHeadless.vcxproj \"/p:Configuration=Debug\" \"/p:Platform=x64\" \"/v:minimal\")",
- "Bash(/c/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe \"D:/Project/video-av1/vav2/Vav2Player/Vav2Player/Vav2PlayerHeadless.vcxproj\" //p:Configuration=Debug //p:Platform=x64 //v:minimal)",
- "Bash(\"D:\\Project\\video-av1\\vav2\\Vav2Player\\Vav2Player\\x64\\Debug\\Headless\\Vav2PlayerHeadless.exe\" \"D:\\Project\\video-av1\\sample\\simple_test.webm\")",
- "Bash(/c/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe \"D:/Project/video-av1/vav2/Vav2Player/Vav2Player/Vav2Player.vcxproj\" //p:Configuration=Debug //p:Platform=x64 //v:minimal)",
- "Bash(\"/c/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" \"D:/Project/video-av1/vav2/Vav2Player/Vav2Player/Vav2PlayerHeadless.vcxproj\" \"/p:Configuration=Debug\" \"/p:Platform=x64\" \"/v:minimal\")",
- "Bash(\"/c/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" \"D:/Project/video-av1/vav2/Vav2Player/Vav2Player/Vav2PlayerHeadless.vcxproj\" \"//p:Configuration=Debug\" \"//p:Platform=x64\" \"//v:minimal\")",
- "Bash(/c/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe Vav2PlayerHeadless.vcxproj //p:Configuration=Debug //p:Platform=x64 //v:minimal)",
- "Bash(\"/c/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" Vav2Player.vcxproj \"//p:Configuration=Debug\" \"//p:Platform=x64\" \"//v:minimal\")",
- "Bash(python3:*)",
"Bash(find:*)",
- "Bash(\"/c/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" Vav2PlayerHeadless.vcxproj \"/p:Configuration=Debug\" \"/p:Platform=x64\" \"/v:minimal\")",
- "Bash(cmd:*)",
- "Bash(\"C:/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" Vav2Player.vcxproj /p:Configuration=Debug /p:Platform=x64 /v:minimal)",
],
"deny": [],
"ask": []
diff --git a/.gitignore b/.gitignore
index c980487..5bf3187 100644
--- a/.gitignore
+++ b/.gitignore
@@ -355,4 +355,5 @@ lib/
include/
oss/
output.mp4
-prompt.txt
\ No newline at end of file
+prompt.txt
+.user
diff --git a/build_dav1d.bat b/build_dav1d.bat
index ba65774..551c5eb 100644
--- a/build_dav1d.bat
+++ b/build_dav1d.bat
@@ -1,12 +1,12 @@
@echo off
-echo Building dav1d static library (Release + Debug) for win64...
+echo Building dav1d dynamic library (Release + Debug) for win64...
REM Clean previous build
echo Cleaning previous build...
if exist lib\dav1d rmdir /S /Q lib\dav1d
if exist include\dav1d rmdir /S /Q include\dav1d
-if exist oss\dav1d\build_static_release rmdir /S /Q oss\dav1d\build_static_release
-if exist oss\dav1d\build_static_debug rmdir /S /Q oss\dav1d\build_static_debug
+if exist oss\dav1d\build_shared_release rmdir /S /Q oss\dav1d\build_shared_release
+if exist oss\dav1d\build_shared_debug rmdir /S /Q oss\dav1d\build_shared_debug
REM Create output directories
echo Creating output directories...
@@ -14,56 +14,56 @@ mkdir lib\dav1d 2>nul
mkdir include\dav1d 2>nul
REM =============================================================================
-REM Build Release version (STATIC)
+REM Build Release version (SHARED)
REM =============================================================================
echo.
echo ========================================
-echo Building RELEASE static version of dav1d...
+echo Building RELEASE shared version of dav1d...
echo ========================================
REM Create build directory
cd oss\dav1d
-REM Configure with Meson (Release Static)
-echo Configuring dav1d Release static build...
-meson setup build_static_release --buildtype=release --default-library=static --prefix="D:/Project/video-av1/build_output/release" -Denable_tools=false -Denable_tests=false -Denable_examples=false
+REM Configure with Meson (Release Shared)
+echo Configuring dav1d Release shared build...
+meson setup build_shared_release --buildtype=release --default-library=shared --prefix="D:/Project/video-av1/build_output/release" -Denable_tools=false -Denable_tests=false -Denable_examples=false
if %ERRORLEVEL% neq 0 (
- echo Meson Release static configuration failed!
+ echo Meson Release shared configuration failed!
cd ..\..
exit /b 1
)
REM Build the library (Release)
-echo Building dav1d Release static...
-meson compile -C build_static_release
+echo Building dav1d Release shared...
+meson compile -C build_shared_release
if %ERRORLEVEL% neq 0 (
- echo Release static build failed!
+ echo Release shared build failed!
cd ..\..
exit /b 1
)
REM =============================================================================
-REM Build Debug version (STATIC)
+REM Build Debug version (SHARED)
REM =============================================================================
echo.
echo ========================================
-echo Building DEBUG static version of dav1d...
+echo Building DEBUG shared version of dav1d...
echo ========================================
-REM Configure with Meson (Debug Static)
-echo Configuring dav1d Debug static build...
-meson setup build_static_debug --buildtype=debug --default-library=static --prefix="D:/Project/video-av1/build_output/debug" -Denable_tools=false -Denable_tests=false -Denable_examples=false
+REM Configure with Meson (Debug Shared)
+echo Configuring dav1d Debug shared build...
+meson setup build_shared_debug --buildtype=debug --default-library=shared --prefix="D:/Project/video-av1/build_output/debug" -Denable_tools=false -Denable_tests=false -Denable_examples=false
if %ERRORLEVEL% neq 0 (
- echo Meson Debug static configuration failed!
+ echo Meson Debug shared configuration failed!
cd ..\..
exit /b 1
)
REM Build the library (Debug)
-echo Building dav1d Debug static...
-meson compile -C build_static_debug
+echo Building dav1d Debug shared...
+meson compile -C build_shared_debug
if %ERRORLEVEL% neq 0 (
- echo Debug static build failed!
+ echo Debug shared build failed!
cd ..\..
exit /b 1
)
@@ -85,7 +85,7 @@ if %ERRORLEVEL% neq 0 (
REM Copy generated version header
echo Copying generated version header...
-copy "oss\dav1d\build_static_release\include\vcs_version.h" "include\dav1d\"
+copy "oss\dav1d\build_shared_release\include\vcs_version.h" "include\dav1d\"
if %ERRORLEVEL% neq 0 (
echo WARNING: Failed to copy vcs_version.h, but continuing...
) else (
@@ -93,37 +93,47 @@ if %ERRORLEVEL% neq 0 (
)
REM =============================================================================
-REM Install static library files
+REM Install shared library files
REM =============================================================================
echo.
-echo Installing static library files...
+echo Installing shared library files...
-REM Copy Release static library
-echo Copying Release static library...
-copy "oss\dav1d\build_static_release\src\libdav1d.a" "lib\dav1d\dav1d.lib"
+REM Copy Release shared library files
+echo Copying Release shared library...
+copy "oss\dav1d\build_shared_release\src\libdav1d.dll.a" "lib\dav1d\dav1d.lib"
+copy "oss\dav1d\build_shared_release\src\libdav1d-*.dll" "lib\dav1d\"
if %ERRORLEVEL% neq 0 (
- echo Failed to copy Release static library!
+ echo Failed to copy Release shared library!
exit /b 1
)
-REM Copy Debug static library (with -debug postfix)
-echo Copying Debug static library...
-copy "oss\dav1d\build_static_debug\src\libdav1d.a" "lib\dav1d\dav1d-debug.lib"
+REM Copy Debug shared library files (with -debug postfix)
+echo Copying Debug shared library...
+copy "oss\dav1d\build_shared_debug\src\libdav1d.dll.a" "lib\dav1d\dav1d-debug.lib"
+copy "oss\dav1d\build_shared_debug\src\libdav1d-*.dll" "lib\dav1d\"
+if exist "lib\dav1d\libdav1d-*.dll" (
+ for %%f in ("lib\dav1d\libdav1d-*.dll") do (
+ set filename=%%~nf
+ ren "%%f" "!filename!-debug.dll"
+ )
+)
if %ERRORLEVEL% neq 0 (
- echo Failed to copy Debug static library!
+ echo Failed to copy Debug shared library!
exit /b 1
)
echo.
echo ========================================
-echo dav1d static build completed successfully!
+echo dav1d shared build completed successfully!
echo ========================================
-echo Release Static Library:
-echo - lib\dav1d\dav1d.lib
-echo Debug Static Library:
-echo - lib\dav1d\dav1d-debug.lib
+echo Release Shared Library:
+echo - lib\dav1d\dav1d.lib (import library)
+echo - lib\dav1d\libdav1d-*.dll (runtime library)
+echo Debug Shared Library:
+echo - lib\dav1d\dav1d-debug.lib (import library)
+echo - lib\dav1d\libdav1d-*-debug.dll (runtime library)
echo Headers: include\dav1d\
echo.
-echo NOTE: Static libraries are now integrated into the final executable.
-echo No DLL files are needed for runtime distribution.
+echo NOTE: DLL files must be distributed with your application.
+echo Place DLL files in the same directory as your executable.
echo.
\ No newline at end of file
diff --git a/build_libwebm.bat b/build_libwebm.bat
index 1eeb173..88c5204 100644
--- a/build_libwebm.bat
+++ b/build_libwebm.bat
@@ -1,5 +1,5 @@
@echo off
-echo Building libwebm library (Release + Debug) for win64...
+echo Building libwebm dynamic library (Release + Debug) for win64...
REM Clean previous build
echo Cleaning previous build...
@@ -14,11 +14,11 @@ mkdir lib\libwebm 2>nul
mkdir include\libwebm 2>nul
REM =============================================================================
-REM Build Release version
+REM Build Release version (SHARED)
REM =============================================================================
echo.
echo ========================================
-echo Building RELEASE version of libwebm...
+echo Building RELEASE shared version of libwebm...
echo ========================================
REM Create build directory
@@ -26,20 +26,20 @@ cd oss\libwebm
mkdir build_win64 2>nul
cd build_win64
-REM Configure with CMake (Release)
-echo Configuring libwebm Release build...
-cmake -G "Visual Studio 17 2022" -A x64 -DENABLE_TESTS=OFF -DENABLE_SAMPLE_PROGRAMS=OFF -DCMAKE_INSTALL_PREFIX="D:/Project/video-av1" ..
+REM Configure with CMake (Release Shared)
+echo Configuring libwebm Release shared build...
+cmake -G "Visual Studio 17 2022" -A x64 -DBUILD_SHARED_LIBS=ON -DENABLE_TESTS=OFF -DENABLE_SAMPLE_PROGRAMS=OFF -DCMAKE_INSTALL_PREFIX="D:/Project/video-av1" ..
if %ERRORLEVEL% neq 0 (
- echo CMake Release configuration failed!
+ echo CMake Release shared configuration failed!
cd ..\..\..
exit /b 1
)
REM Build the library (Release)
-echo Building libwebm Release...
+echo Building libwebm Release shared...
cmake --build . --config Release
if %ERRORLEVEL% neq 0 (
- echo Release build failed!
+ echo Release shared build failed!
cd ..\..\..
exit /b 1
)
@@ -48,36 +48,36 @@ REM Go back to libwebm source directory
cd ..
REM =============================================================================
-REM Build Debug version
+REM Build Debug version (SHARED)
REM =============================================================================
echo.
echo ========================================
-echo Building DEBUG version of libwebm...
+echo Building DEBUG shared version of libwebm...
echo ========================================
REM Create debug build directory
mkdir build_debug 2>nul
cd build_debug
-REM Configure with CMake (Debug)
-echo Configuring libwebm Debug build...
-cmake -G "Visual Studio 17 2022" -A x64 -DENABLE_TESTS=OFF -DENABLE_SAMPLE_PROGRAMS=OFF ..
+REM Configure with CMake (Debug Shared)
+echo Configuring libwebm Debug shared build...
+cmake -G "Visual Studio 17 2022" -A x64 -DBUILD_SHARED_LIBS=ON -DENABLE_TESTS=OFF -DENABLE_SAMPLE_PROGRAMS=OFF ..
if %ERRORLEVEL% neq 0 (
- echo CMake Debug configuration failed!
+ echo CMake Debug shared configuration failed!
cd ..\..\..
exit /b 1
)
REM Build the library (Debug)
-echo Building libwebm Debug...
+echo Building libwebm Debug shared...
cmake --build . --config Debug
if %ERRORLEVEL% neq 0 (
- echo Debug build failed!
+ echo Debug shared build failed!
cd ..\..\..
exit /b 1
)
-REM Rename debug library immediately after build
+REM Rename debug library and DLL immediately after build
echo Renaming debug library...
if exist Debug\webm.lib (
ren Debug\webm.lib webm-debug.lib
@@ -86,6 +86,13 @@ if exist Debug\webm.lib (
echo WARNING: webm.lib not found in debug build!
)
+if exist Debug\webm.dll (
+ ren Debug\webm.dll webm-debug.dll
+ echo Renamed webm.dll to webm-debug.dll
+) else (
+ echo WARNING: webm.dll not found in debug build!
+)
+
REM Go back to root directory
cd ..\..\.
@@ -126,34 +133,41 @@ if %ERRORLEVEL% neq 0 (
)
REM =============================================================================
-REM Install library files
+REM Install shared library files
REM =============================================================================
echo.
-echo Installing library files...
+echo Installing shared library files...
-REM Copy Release library
-echo Copying Release library...
+REM Copy Release shared library files
+echo Copying Release shared library...
copy "oss\libwebm\build_win64\Release\webm.lib" "lib\libwebm\"
+copy "oss\libwebm\build_win64\Release\webm.dll" "lib\libwebm\"
if %ERRORLEVEL% neq 0 (
- echo Failed to copy Release library!
+ echo Failed to copy Release shared library!
exit /b 1
)
-REM Copy Debug library (already renamed)
-echo Copying Debug library...
+REM Copy Debug shared library files (already renamed)
+echo Copying Debug shared library...
copy "oss\libwebm\build_debug\Debug\webm-debug.lib" "lib\libwebm\"
+copy "oss\libwebm\build_debug\Debug\webm-debug.dll" "lib\libwebm\"
if %ERRORLEVEL% neq 0 (
- echo Failed to copy Debug library!
+ echo Failed to copy Debug shared library!
exit /b 1
)
echo.
echo ========================================
-echo libwebm build completed successfully!
+echo libwebm shared build completed successfully!
echo ========================================
-echo Release Library:
-echo - lib\libwebm\webm.lib
-echo Debug Library:
-echo - lib\libwebm\webm-debug.lib
+echo Release Shared Library:
+echo - lib\libwebm\webm.lib (import library)
+echo - lib\libwebm\webm.dll (runtime library)
+echo Debug Shared Library:
+echo - lib\libwebm\webm-debug.lib (import library)
+echo - lib\libwebm\webm-debug.dll (runtime library)
echo Headers: include\libwebm\
+echo.
+echo NOTE: DLL files must be distributed with your application.
+echo Place DLL files in the same directory as your executable.
echo.
\ No newline at end of file
diff --git a/prompt.txt b/prompt.txt
new file mode 100644
index 0000000..9ed6746
--- /dev/null
+++ b/prompt.txt
@@ -0,0 +1,17 @@
+av1 영상을 재생하는 app 을 개발하고자 한다.
+기본적으로 영상을 디코딩하여 D3D12 의 텍스처에 영상을 그리도록 처리를 하고자 한다.
+
+개발 언어는 C# 을 이용하여, Windows App 으로 개발하기를 원한다.
+개발할 app 이름은 vav1 이고, vav1 디렉토리안에 개발한다.
+
+다음의 2가지 SDK 또는 소스를 이용하여 디코딩 처리하고자 한다.
+1. dav1d 소스를 이용하여 구현한다.
+2. NVIDIA Video Codec SDK 을 이용한다.
+3. Media Foundation 이용하여 구현한다.
+4. DirectX Video Acceleration 이용한여 구현한다.
+
+우선 1번을 이용하여 구현한다.
+
+1번의 라이브러리 소스는 dav1d 디렉토리에 있다.
+2번의 SDK 바이너리는 nvidia-video-codec 디렉토리에 있다.
+3번과 4번은 추후에 지원할 예정이다.
diff --git a/vav2/CLAUDE.md b/vav2/CLAUDE.md
index 52b1e44..db93674 100644
--- a/vav2/CLAUDE.md
+++ b/vav2/CLAUDE.md
@@ -1,25 +1,78 @@
# Vav2Player - AV1 Video Player 개발 프로젝트
-## 🔥 **URGENT: 적응형 품질 제어 시스템 구현**
+## ⚠️ **CRITICAL: 코딩 규칙 및 가이드라인**
-**⚠️ 최우선 작업**: [ADAPTIVE_QUALITY_CONTROL_DESIGN.md](./ADAPTIVE_QUALITY_CONTROL_DESIGN.md) **반드시 읽고 진행**
+### 📝 **주석 언어 규칙 (REQUIRED)**
+**🚨 중요**: 모든 소스 코드 파일의 주석은 **영어로 작성**해야 합니다.
-**현재 상황**: 프레임 스킵 대신 동적 해상도/품질 조정 시스템 구현
-- **목표**: 끊김 없는 부드러운 비디오 재생 실현
-- **방식**: NVDEC 기반 실시간 해상도 조정 + 성능 모니터링
-- **이유**: 프레임 드롭의 시각적 불연속성 문제 근본 해결
+#### 적용 범위
+- `.h` 헤더 파일의 모든 주석
+- `.cpp` 소스 파일의 모든 주석
+- `.xaml.h` WinUI 헤더 파일의 모든 주석
+- `.xaml.cpp` WinUI 소스 파일의 모든 주석
+
+#### 예시
+```cpp
+// ❌ 잘못된 예 (한국어 주석)
+// 버퍼 크기 확인 및 재할당 최소화
+size_t required_size = frame.width * frame.height * 4;
+
+// ✅ 올바른 예 (영어 주석)
+// Check buffer size and minimize reallocation
+size_t required_size = frame.width * frame.height * 4;
+```
+
+#### 이유
+1. **국제화 지원**: 영어 주석으로 코드의 국제적 접근성 향상
+2. **컴파일러 호환성**: 일부 컴파일러에서 비ASCII 문자로 인한 인코딩 문제 방지
+3. **협업 효율성**: 다양한 배경의 개발자들과의 협업 용이성
+4. **유지보수성**: 장기적인 코드 유지보수 시 언어 장벽 제거
+
+#### ⚠️ 필수 조치사항
+- **기존 한국어 주석 발견 시 즉시 영어로 변환**
+- 새로운 코드 작성 시 처음부터 영어 주석 사용
+- 함수명, 변수명은 기존 명명 규칙 유지 (영어만 가능)
+
+### 🚫 **이모지 사용 금지 규칙 (REQUIRED)**
+**🚨 중요**: 모든 소스 코드, 주석, 문자열에서 **이모지 사용을 금지**합니다.
+
+#### 적용 범위
+- 모든 소스 코드 파일의 주석 (`.h`, `.cpp`, `.xaml.h`, `.xaml.cpp`)
+- 코드 내 문자열 리터럴 (예: `"Success!"`, `L"Video Player"`)
+- XAML 파일의 주석 및 텍스트 속성
+- 로그 메시지 및 디버그 출력
+
+#### 권장 대체 방안
+```cpp
+// ✅ 권장 대체 방안
+// [PERFORMANCE] GPU acceleration enabled
+// [SUCCESS] Frame decode completed
+// [WARNING] Fallback to CPU rendering
+// [ERROR] Failed to initialize D3D12 device
+```
+
+---
+
+## 🔥 **URGENT: VavCore Static Library 구현**
+
+**⚠️ 최우선 작업**: [VavCore_Library_Design.md](VavCore_Library_Design.md) **반드시 읽고 진행**
+
+**현재 상황**: AV1 디코딩 및 렌더링 모듈을 재사용 가능한 Static Library로 분리
+- **목표**: VavCore.lib 형태의 독립적인 AV1 디코딩 라이브러리 제작
+- **방식**: 기존 Vav2Player 핵심 컴포넌트 추출 및 Public API 설계
+- **이유**: 코드 재사용성, 모듈화, 다른 프로젝트 통합 용이성
### 📋 **최우선 작업 순서 (2025-09-24 업데이트)**
-#### **🚀 새로운 최우선 작업: 적응형 품질 제어**
-**목표**: 프레임 스킵 없는 부드러운 재생 구현
-**예상 소요**: 3-5일
+#### **🚀 새로운 최우선 작업: VavCore Static Library**
+**목표**: 재사용 가능한 AV1 디코딩 라이브러리 구현
+**예상 소요**: 2-3주
**작업 내용**:
-1. [ADAPTIVE_QUALITY_CONTROL_DESIGN.md](./ADAPTIVE_QUALITY_CONTROL_DESIGN.md) 설계 문서 기반 구현
-2. AdaptiveNVDECDecoder 클래스 통합 및 테스트
-3. 5단계 품질 레벨 시스템 (ULTRA → MINIMUM) 구현
-4. 실시간 성능 모니터링 및 자동 품질 조정 로직
-5. VideoPlayerControl과 통합하여 end-to-end 테스트
+1. [VavCore_Library_Design.md](VavCore_Library_Design.md) 설계 문서 기반 구현
+2. 기존 컴포넌트를 Static Library로 분리 (Decoder, FileIO, Common)
+3. Public API 설계 및 구현 (Simple + Advanced API)
+4. CMake 빌드 시스템 구축
+5. 예제 프로그램 및 문서화 완료
### 📋 **완료된 설계 및 구현 (참조용)**
@@ -51,54 +104,76 @@
- [x] VideoDecoderFactory에서 NVDEC → dav1d → MediaFoundation 우선순위 설정
- [x] 하드웨어 가용성 자동 감지 및 graceful fallback 구현
+#### **✅ 적응형 품질 제어 시스템 완료**
+- [x] AdaptiveNVDECDecoder 구현 (NVDEC 기반 동적 해상도 조정)
+- [x] AdaptiveAV1Decoder 구현 (dav1d 기반 포스트 디코딩 스케일링)
+- [x] 5단계 품질 레벨 시스템 (ULTRA, HIGH, MEDIUM, LOW, MINIMUM)
+- [x] 실시간 성능 모니터링 (30프레임 이동평균, 히스테리시스 제어)
+- [x] 3단계 품질 모드 (CONSERVATIVE, FAST, ULTRA_FAST) 구현 및 최적화
+- [x] 프레임 스킵 제거를 통한 부드러운 비디오 재생 실현
+- [x] 4K AV1 디코딩 성능 최적화 (27.7fps 달성)
+
---
-## 🎯 **현재 프로젝트 상태 요약 (2025-09-24 업데이트)**
+## 🎯 **현재 프로젝트 상태 요약 (2025-09-25 업데이트)**
### ✅ **구현 완료된 주요 컴포넌트**
1. **Core Video Infrastructure**: WebMFileReader, AV1Decoder, VideoDecoderFactory ✅
2. **Hardware Acceleration**: NVDECAV1Decoder, CUDA 13.0 통합, NVDEC 우선 디코더 설정 ✅
-3. **GPU Rendering System**: SimpleGPURenderer, D3D12VideoRenderer 구현 ✅
-4. **UI Integration**: VideoPlayerControl 단순화 및 WinUI3 통합 ✅
-5. **Build System**: 모든 프로젝트 빌드 성공 (GUI/Headless/UnitTest) ✅
-6. **Test Infrastructure**: 47개 Unit Test, Mock 시스템, NVDEC 헤드리스 테스트 구축 ✅
-7. **Code Quality**: 한글 주석 → 영어 변환, 코딩 가이드라인 준수 ✅
+3. **Adaptive Quality Control**: AdaptiveAV1Decoder, AdaptiveNVDECDecoder 완전 구현 ✅
+4. **Quality Mode System**: CONSERVATIVE, FAST, ULTRA_FAST 모드 구현 및 최적화 ✅
+5. **GPU Rendering System**: SimpleGPURenderer, D3D12VideoRenderer 구현 ✅
+6. **UI Integration**: VideoPlayerControl 단순화 및 WinUI3 통합 ✅
+7. **Build System**: 모든 프로젝트 빌드 성공 (GUI/Headless/UnitTest) ✅
+8. **Test Infrastructure**: 47개 Unit Test, Mock 시스템, NVDEC 헤드리스 테스트 구축 ✅
+9. **Code Quality**: 한글 주석 → 영어 변환, 코딩 가이드라인 준수, VavCore 네임스페이스 통일 ✅
+10. **Performance Optimization**: 4K AV1 디코딩 27.7fps 달성 (ULTRA_FAST 모드) ✅
-### 🚀 **다음 단계: 적응형 품질 제어 시스템**
+### ✅ **VavCore Static Library 구현 완료**
-#### **새로운 목표: 프레임 스킵 제거**
-- **현재 문제**: 성능 부족 시 프레임 스킵으로 인한 끊김 현상
-- **새로운 접근**: 동적 해상도/품질 조정으로 부드러운 재생 유지
-- **기술 기반**: NVDEC `cuvidReconfigureDecoder()` API 활용
+#### **✅ 달성된 목표: 재사용 가능한 라이브러리 제작**
+- **✅ 완료**: 기존 AV1 디코딩 시스템을 독립 라이브러리로 분리
+- **✅ 완료**: Public API 설계를 통한 모듈화 및 재사용성 극대화
+- **📋 다음**: CMake 빌드 시스템과 Static Library 구조 최적화
-#### **핵심 개선 효과**
-- **시각적 연속성**: 끊김 없는 부드러운 재생 (+400%)
-- **오디오 동기화**: 완벽한 A/V 싱크 유지 (+100%)
-- **사용자 경험**: 매끄러운 재생 경험 (+500%)
-- **시스템 적응**: 하드웨어 성능에 자동 최적화
+#### **✅ 달성된 핵심 개선 효과**
+- **✅ 코드 재사용**: VavCore 라이브러리로 독립 모듈화 완료
+- **✅ 모듈 독립성**: 디코딩 로직과 UI 로직 완전 분리 달성
+- **✅ 아키텍처 통합**: 중복 구현 제거 및 단일 소스 관리
+- **✅ 확장성**: IAdaptiveVideoDecoder 인터페이스로 새로운 코덱 지원 준비
-## 🎮 **적응형 품질 제어 구현 계획**
+## 🎮 **VavCore Static Library 구현 계획**
-### **Phase 1: 핵심 시스템 구현** (3-5일)
-1. **AdaptiveNVDECDecoder 통합**
- - 기존 NVDECAV1Decoder 확장
- - IAdaptiveDecoder 인터페이스 구현
- - 5단계 품질 레벨 시스템 (ULTRA → MINIMUM)
+### **✅ Phase 1: Core Library 구조 완료** (2025-09-25)
+1. **✅ 라이브러리 프로젝트 생성**
+ - ✅ VavCore.vcxproj 프로젝트 파일 생성
+ - ✅ Static Library 타입으로 설정
+ - ✅ 기존 컴포넌트 의존성 정리
-2. **성능 모니터링 시스템**
- - 실시간 디코딩/렌더링 시간 측정
- - 30프레임 이동평균 기반 안정성 제어
- - 히스테리시스 적용으로 oscillation 방지
+2. **✅ Public API 설계 및 구현**
+ - ✅ VavCore.h 메인 헤더 파일 (C API)
+ - ✅ Simple API 완전 구현 (vavcore_* 함수들)
+ - ✅ Advanced API 준비 (IAdaptiveVideoDecoder 인터페이스)
-3. **VideoPlayerControl 통합**
- - 적응형 디코더 사용으로 전환
- - 품질 변경 로그 및 UI 피드백
- - end-to-end 테스트 및 검증
+3. **✅ 컴포넌트 분리 및 통합**
+ - ✅ Decoder 모듈 (AdaptiveAV1Decoder, AdaptiveNVDECDecoder, MediaFoundationAV1Decoder)
+ - ✅ FileIO 모듈 (WebMFileReader)
+ - ✅ Common 모듈 (VideoTypes, FramePool, IAdaptiveVideoDecoder)
-### **Phase 2: 다른 디코더 확장** (2-3일)
-1. **dav1d 적응형 구현**: 포스트 디코딩 스케일링 방식
-2. **MediaFoundation 적응형 구현**: MFT 출력 타입 재설정 방식
-3. **범용 적응형 팩토리**: 디코더별 최적 전략 자동 선택
+4. **✅ VavCore 아키텍처 통합 완료**
+ - ✅ 중복 구현 제거 (vav2/VavCore → vav2/Vav2Player/VavCore)
+ - ✅ Pimpl 패턴 적용으로 C/C++ ABI 호환성 확보
+ - ✅ 600줄 완전 구현으로 모든 VavCore C API 함수 제공
+ - ✅ VavCore_Library_Design.md 설계 문서 준수
+ - ✅ VavCore 네임스페이스 일관성 수정 완료 (2025-09-25)
+ - ✅ 모든 한글 주석 영어 변환 완료 (2025-09-25)
+ - ✅ Release 모드 빌드 성공 및 헤드리스 테스트 완료 (2025-09-25)
+
+### **📋 Phase 2: 빌드 시스템 및 문서화 (다음 단계)**
+1. **CMake 빌드 시스템**: 크로스플랫폼 빌드 지원
+2. **예제 프로그램**: 라이브러리 사용법 데모
+3. **API 문서**: 상세한 사용 가이드 및 레퍼런스
+4. **Godot 통합 준비**: C# 래퍼 및 Git 서브모듈 설정
#### ✅ 완료된 사전 작업
- SwapChainPanel XAML 설정 완료
@@ -168,6 +243,49 @@ WinUI 3 C++로 작성된 AV1 파일 재생 플레이어
- 현재 단계: 파일 출력 기반 스트리밍 파이프라인 구현 (렌더링은 추후)
- 목표 성능: 30fps 끊김없는 실시간 재생
+## 📁 프로젝트 파일 경로 (Project File Locations)
+
+### **메인 프로젝트 파일들**
+- **GUI 프로젝트**: `D:\Project\video-av1\vav2\Vav2Player\Vav2Player\Vav2Player.vcxproj`
+- **헤드리스 테스트**: `D:\Project\video-av1\vav2\Vav2Player\Vav2Player\Vav2PlayerHeadless.vcxproj`
+- **유닛 테스트**: `D:\Project\video-av1\vav2\Vav2Player\Vav2Player\Vav2UnitTest.vcxproj`
+- **VavCore 라이브러리**: `D:\Project\video-av1\vav2\Vav2Player\VavCore\VavCore.vcxproj`
+- **솔루션 파일**: `D:\Project\video-av1\vav2\Vav2Player\Vav2Player.sln`
+
+### **빌드 명령어 템플릿**
+```bash
+# GUI 프로젝트 빌드
+cd "D:\Project\video-av1\vav2\Vav2Player\Vav2Player"
+"C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe" Vav2Player.vcxproj //p:Configuration=Debug //p:Platform=x64 //v:minimal
+
+# VavCore 라이브러리 빌드
+cd "D:\Project\video-av1\vav2\Vav2Player\VavCore"
+"C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe" VavCore.vcxproj //p:Configuration=Debug //p:Platform=x64 //v:minimal
+
+# 헤드리스 테스트 빌드
+cd "D:\Project\video-av1\vav2\Vav2Player\Vav2Player"
+"C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe" Vav2PlayerHeadless.vcxproj //p:Configuration=Debug //p:Platform=x64 //v:minimal
+
+# 유닛 테스트 빌드
+cd "D:\Project\video-av1\vav2\Vav2Player\Vav2Player"
+"C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe" Vav2UnitTest.vcxproj //p:Configuration=Debug //p:Platform=x64 //v:minimal
+
+# 전체 솔루션 빌드
+cd "D:\Project\video-av1\vav2\Vav2Player"
+"C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe" Vav2Player.sln //p:Configuration=Debug //p:Platform=x64 //v:minimal
+```
+
+### **실행 파일 경로**
+- **GUI 실행파일**: `D:\Project\video-av1\vav2\Vav2Player\Vav2Player\x64\Debug\Vav2Player\Vav2Player.exe`
+- **헤드리스 실행파일**: `D:\Project\video-av1\vav2\Vav2Player\Vav2Player\x64\Debug\Headless\Vav2PlayerHeadless.exe`
+- **VavCore 라이브러리**: `D:\Project\video-av1\vav2\Vav2Player\VavCore\x64\Debug\VavCore\VavCore.lib`
+
+### **주요 디렉토리**
+- **소스 코드**: `D:\Project\video-av1\vav2\Vav2Player\Vav2Player\src\`
+- **헤드리스 소스**: `D:\Project\video-av1\vav2\Vav2Player\Vav2Player\headless\`
+- **VavCore 소스**: `D:\Project\video-av1\vav2\Vav2Player\VavCore\src\`
+- **VavCore 헤더**: `D:\Project\video-av1\vav2\Vav2Player\VavCore\include\VavCore\`
+
## 프로젝트 구조
```
D:\Project\video-av1\
@@ -279,191 +397,6 @@ D:\Project\video-av1\
- 언어 표준: C++17 이상
- 런타임: Windows App SDK 1.8
-## 코딩 규칙 및 가이드라인
-
-### 주석 언어 규칙
-**중요**: 모든 소스 코드 파일의 주석은 **영어로 작성**해야 합니다.
-
-#### 적용 범위
-- `.h` 헤더 파일의 모든 주석
-- `.cpp` 소스 파일의 모든 주석
-- `.xaml.h` WinUI 헤더 파일의 모든 주석
-- `.xaml.cpp` WinUI 소스 파일의 모든 주석
-
-#### 예시
-```cpp
-// ❌ 잘못된 예 (한국어 주석)
-// 버퍼 크기 확인 및 재할당 최소화
-size_t required_size = frame.width * frame.height * 4;
-
-// ✅ 올바른 예 (영어 주석)
-// Check buffer size and minimize reallocation
-size_t required_size = frame.width * frame.height * 4;
-```
-
-#### 이유
-1. **국제화 지원**: 영어 주석으로 코드의 국제적 접근성 향상
-2. **컴파일러 호환성**: 일부 컴파일러에서 비ASCII 문자로 인한 인코딩 문제 방지
-3. **협업 효율성**: 다양한 배경의 개발자들과의 협업 용이성
-4. **유지보수성**: 장기적인 코드 유지보수 시 언어 장벽 제거
-
-#### 주의사항
-- 기존 한국어 주석 발견 시 즉시 영어로 변환
-- 새로운 코드 작성 시 처음부터 영어 주석 사용
-- 함수명, 변수명은 기존 명명 규칙 유지 (영어 또는 한국어 혼용 가능)
-
-### 이모지 사용 금지 규칙
-**중요**: 모든 소스 코드, 주석, 문자열에서 **이모지 사용을 금지**합니다.
-
-#### 적용 범위
-- 모든 소스 코드 파일의 주석 (`.h`, `.cpp`, `.xaml.h`, `.xaml.cpp`)
-- 코드 내 문자열 리터럴 (예: `"Success!"`, `L"Video Player"`)
-- XAML 파일의 주석 및 텍스트 속성
-- 로그 메시지 및 디버그 출력
-- 변수명, 함수명, 클래스명
-- 파일명 및 디렉터리명
-
-#### 금지 예시
-```cpp
-// ❌ 잘못된 예 (이모지 사용)
-// 🚀 Initialize video decoder with GPU acceleration
-std::cout << "[AV1Decoder] Decode successful! 🎉" << std::endl;
-std::string status = "Ready ✅";
-
-// ✅ 올바른 예 (이모지 없음)
-// Initialize video decoder with GPU acceleration
-std::cout << "[AV1Decoder] Decode successful!" << std::endl;
-std::string status = "Ready";
-```
-
-```xml
-
-
-
-
-
-
-
-```
-
-#### 이유
-1. **컴파일러 호환성**: 일부 컴파일러에서 Unicode 이모지로 인한 인코딩 문제 방지
-2. **텍스트 처리 안정성**: 로그 파싱, 텍스트 검색 시 문제 방지
-3. **프로페셔널 코드**: 산업 표준 코딩 스타일 준수
-4. **크로스플랫폼 호환성**: 다양한 개발 환경에서 안정적 동작 보장
-5. **가독성**: 코드 리뷰 및 디버깅 시 집중력 향상
-
-#### 대체 방안
-- 이모지 대신 명확한 텍스트 설명 사용
-- 로그 레벨로 중요도 표현 (INFO, WARNING, ERROR)
-- 주석에서 구조화된 마크다운 문법 활용
-
-```cpp
-// ✅ 권장 대체 방안
-// [PERFORMANCE] GPU acceleration enabled
-// [SUCCESS] Frame decode completed
-// [WARNING] Fallback to CPU rendering
-// [ERROR] Failed to initialize D3D12 device
-```
-
-### XAML 파일 작성 규칙
-**중요**: WinUI XAML 파일에서도 모든 주석과 문자열은 **영어로 작성**해야 합니다.
-
-#### 적용 범위
-- `.xaml` 파일의 모든 XML 주석 (``)
-- XAML 속성값의 텍스트 문자열 (예: `Text="..."`, `Content="..."`)
-- 사용자에게 표시되지 않는 내부 문자열도 영어 권장
-
-#### 예시
-```xml
-
-
-
-
-
-
-
-```
-
-#### XAML 파싱 주의사항
-- **대량 주석 블록 금지**: 긴 주석 처리된 XAML 코드는 파싱 오류를 일으킬 수 있음
-- **사용하지 않는 컨트롤**: 주석 처리보다는 완전 제거 권장
-- **이벤트 핸들러**: XAML에서 제거된 컨트롤의 이벤트 핸들러는 .h/.cpp에서도 제거
-
-#### XAML 주석 작성 가이드라인
-**목적**: 코드 가독성과 유지보수성을 위한 XAML 주석 작성 규칙
-
-**주석 작성 원칙**:
-- 모든 주요 UI 섹션에 영어 주석으로 목적 설명
-- 복잡한 레이아웃이나 데이터 바인딩에는 상세 주석 추가
-- 조건부 표시/숨김 로직이 있는 컨트롤에는 설명 추가
-
-**권장 주석 패턴**:
-```xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-```
-
-**주석이 필요한 경우**:
-- UI 레이아웃의 주요 섹션 (상단 바, 메인 콘텐츠, 하단 상태바 등)
-- 동적으로 변경되는 Visibility나 IsEnabled 속성을 가진 컨트롤
-- 복잡한 Grid 구조나 중첩된 StackPanel
-- 특별한 목적을 가진 Border나 Canvas 컨트롤
-
-### 라이브러리 링크 설정
-```xml
-
-$(ProjectDir)..\..\include\libwebm;
-$(ProjectDir)..\..\include\dav1d;
-
-
-$(ProjectDir)..\..\lib\libwebm;
-$(ProjectDir)..\..\lib\dav1d;
-
-
-webm.lib;
-dav1d.lib;
-```
-
-### MSBuild 사용법
-
-**프로젝트 디렉터리에서 빌드하기:**
-```bash
-cd vav2/Vav2Player/Vav2Player
-/c/Program\ Files/Microsoft\ Visual\ Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe Vav2Player.vcxproj //p:Configuration=Debug //p:Platform=x64 //v:minimal
-```
-
-**주요 옵션들:**
-- `//p:Configuration=Debug` 또는 `//p:Configuration=Release` - 빌드 구성
-- `//p:Platform=x64` - 플랫폼 (x64 고정)
-- `//v:minimal` - 최소한의 출력 (오류만 표시)
-- `//v:normal` - 기본 출력 레벨
-- `//v:detailed` - 상세한 출력
-
-**Git Bash에서 주의사항:**
-- Windows 경로에 공백이 있으므로 따옴표로 감싸거나 백슬래시 이스케이프 사용
-- Git Bash 경로 확장 문제를 피하기 위해 `/c/Program Files/...` 형식 사용
-- MSBuild 매개변수는 이중 슬래시 `//` 사용 (Git Bash 경로 확장 방지)
-
-**빌드 출력 위치:**
-- 실행 파일: `vav2/Vav2Player/Vav2Player/x64/Debug/Vav2Player/Vav2Player.exe`
-- 라이브러리: `vav2/Vav2Player/Vav2Player/x64/Debug/Vav2Player/Vav2Player.lib`
-
## 다음 작업
1. **1단계 구현 시작**: WebMFileReader 클래스 구현
2. **프로젝트 설정**: vcxproj 파일에 include/lib 경로 및 종속성 추가
@@ -847,6 +780,58 @@ cd "D:\Project\video-av1\vav2\Vav2Player\Vav2Player"
vstest.console.exe "x64\Debug\UnitTest\Vav2UnitTest.dll"
```
+#### **🔧 Unit Test 전략: VavCore 내부 API 직접 참조**
+
+**핵심 원칙**: Unit test에서는 VavCore 내부 구현을 테스트해야 하므로, **복사 없이 직접 참조**로 내부 헤더에 접근
+
+**구현 방법**:
+1. **Include Path 설정**: `$(ProjectDir)..\VavCore\src` 추가로 VavCore 내부 헤더 접근 가능
+2. **직접 참조**: 헤더 파일을 복사하지 않고 원본 파일을 직접 include
+3. **네임스페이스 통합**: `using namespace VavCore;`로 내부 API 사용
+
+**Vav2UnitTest.vcxproj 설정**:
+```xml
+
+ $(ProjectDir)unit-test;
+ $(ProjectDir)..\VavCore\include;
+ $(ProjectDir)..\VavCore\src;
+ %(AdditionalIncludeDirectories)
+
+```
+
+**unit-test/pch.h 구조**:
+```cpp
+// VavCore public API (C API)
+#include "VavCore/VavCore.h"
+
+// VavCore internal APIs for unit testing (via direct reference, not copy)
+#include "Common/VideoTypes.h"
+#include "Decoder/IVideoDecoder.h"
+#include "FileIO/IWebMFileReader.h"
+#include "Common/IAdaptiveVideoDecoder.h"
+
+using namespace VavCore;
+```
+
+**장점**:
+- ✅ **실제 구현 테스트**: 내부 클래스와 구조체를 직접 테스트 가능
+- ✅ **코드 중복 없음**: 헤더 파일을 복사하지 않고 원본 참조
+- ✅ **자동 동기화**: VavCore 내부 구조 변경 시 자동으로 테스트에 반영
+- ✅ **C/C++ API 동시 테스트**: Public C API와 Internal C++ API 모두 검증 가능
+
+**테스트 범위**:
+- **Public API**: VavCore C API 함수들 (`vavcore_*` 함수들)
+- **Internal API**: VavCore 네임스페이스의 C++ 클래스들
+- **양방향 호환성**: C API ↔ Internal C++ API 변환 검증
+
+**현재 활성화된 테스트**:
+- `VideoTypesTest.cpp`: VavCore::VideoFrame, VideoMetadata, VideoPacket + VavCoreVideoFrame
+- `VavCoreTest.cpp`: VavCore C API 함수들 검증
+
+**임시 비활성화된 테스트** (Mock 클래스 업데이트 대기):
+- MockWebMFileReader, MockVideoRenderer 관련 테스트들
+- 복잡한 통합 테스트들
+
#### **새로운 테스트 파일 추가 가이드**
**1. 테스트 파일 생성**
diff --git a/vav2/Vav2Player/Vav2Player.sln b/vav2/Vav2Player/Vav2Player.sln
index 5792468..bfcc706 100644
--- a/vav2/Vav2Player/Vav2Player.sln
+++ b/vav2/Vav2Player/Vav2Player.sln
@@ -8,6 +8,11 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Vav2PlayerHeadless", "Vav2Player\Vav2PlayerHeadless.vcxproj", "{E8B13F42-1234-5678-9ABC-123456789ABC}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Vav2UnitTest", "Vav2Player\Vav2UnitTest.vcxproj", "{2F8B5F4C-7E8D-4A9B-8C6D-1E3F5A7B9C2D}"
+ ProjectSection(ProjectDependencies) = postProject
+ {B8F7E8E0-F8F7-4A8A-9A8A-8A8A8A8A8A8A} = {B8F7E8E0-F8F7-4A8A-9A8A-8A8A8A8A8A8A}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VavCore", "VavCore\VavCore.vcxproj", "{B8F7E8E0-F8F7-4A8A-9A8A-8A8A8A8A8A8A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -53,6 +58,14 @@ Global
{2F8B5F4C-7E8D-4A9B-8C6D-1E3F5A7B9C2D}.Release|x64.ActiveCfg = Release|x64
{2F8B5F4C-7E8D-4A9B-8C6D-1E3F5A7B9C2D}.Release|x64.Build.0 = Release|x64
{2F8B5F4C-7E8D-4A9B-8C6D-1E3F5A7B9C2D}.Release|x86.ActiveCfg = Release|x64
+ {B8F7E8E0-F8F7-4A8A-9A8A-8A8A8A8A8A8A}.Debug|ARM64.ActiveCfg = Debug|x64
+ {B8F7E8E0-F8F7-4A8A-9A8A-8A8A8A8A8A8A}.Debug|x64.ActiveCfg = Debug|x64
+ {B8F7E8E0-F8F7-4A8A-9A8A-8A8A8A8A8A8A}.Debug|x64.Build.0 = Debug|x64
+ {B8F7E8E0-F8F7-4A8A-9A8A-8A8A8A8A8A8A}.Debug|x86.ActiveCfg = Debug|x64
+ {B8F7E8E0-F8F7-4A8A-9A8A-8A8A8A8A8A8A}.Release|ARM64.ActiveCfg = Release|x64
+ {B8F7E8E0-F8F7-4A8A-9A8A-8A8A8A8A8A8A}.Release|x64.ActiveCfg = Release|x64
+ {B8F7E8E0-F8F7-4A8A-9A8A-8A8A8A8A8A8A}.Release|x64.Build.0 = Release|x64
+ {B8F7E8E0-F8F7-4A8A-9A8A-8A8A8A8A8A8A}.Release|x86.ActiveCfg = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/vav2/Vav2Player/Vav2Player/App.xaml.cpp b/vav2/Vav2Player/Vav2Player/App.xaml.cpp
index 46f97ae..0eb64d9 100644
--- a/vav2/Vav2Player/Vav2Player/App.xaml.cpp
+++ b/vav2/Vav2Player/Vav2Player/App.xaml.cpp
@@ -1,17 +1,53 @@
#include "pch.h"
#include "App.xaml.h"
#include "MainWindow.xaml.h"
-#include "MultiVideoTestWindow.xaml.h"
+#include "VavCore/VavCore.h"
using namespace winrt;
using namespace winrt::Microsoft::UI::Xaml;
namespace winrt::Vav2Player::implementation
{
+ // Simple VavCore test function
+ void TestVavCoreIntegration()
+ {
+ // Test VavCore C API
+ VavCoreResult result = vavcore_initialize();
+ if (result == VAVCORE_SUCCESS)
+ {
+ const char* version = vavcore_get_version_string();
+ OutputDebugStringA("VavCore initialized successfully, version: ");
+ OutputDebugStringA(version);
+ OutputDebugStringA("\n");
+
+ // Test creating a player
+ VavCorePlayer* player = vavcore_create_player();
+ if (player)
+ {
+ OutputDebugStringA("VavCore player created successfully\n");
+ vavcore_destroy_player(player);
+ }
+
+ // C++ wrapper test disabled for now (only using C API)
+ // VavCore::VideoPlayer cppPlayer;
+ // OutputDebugStringA("VavCore C++ player created successfully\n");
+
+ vavcore_cleanup();
+ OutputDebugStringA("VavCore cleanup completed\n");
+ }
+ else
+ {
+ OutputDebugStringA("Failed to initialize VavCore\n");
+ }
+ }
+
App::App()
{
InitializeComponent();
+ // Test VavCore integration on startup
+ TestVavCoreIntegration();
+
#if defined _DEBUG && !defined DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION
UnhandledException([](IInspectable const&, UnhandledExceptionEventArgs const& e)
{
@@ -26,7 +62,7 @@ namespace winrt::Vav2Player::implementation
void App::OnLaunched(LaunchActivatedEventArgs const&)
{
- window = make();
+ window = make();
window.Activate();
}
}
\ No newline at end of file
diff --git a/vav2/Vav2Player/Vav2Player/LayeredVideoPage.idl b/vav2/Vav2Player/Vav2Player/LayeredVideoPage.idl
new file mode 100644
index 0000000..2e18eea
--- /dev/null
+++ b/vav2/Vav2Player/Vav2Player/LayeredVideoPage.idl
@@ -0,0 +1,8 @@
+namespace Vav2Player
+{
+ [default_interface]
+ runtimeclass LayeredVideoPage : Microsoft.UI.Xaml.Controls.Page
+ {
+ LayeredVideoPage();
+ }
+}
\ No newline at end of file
diff --git a/vav2/Vav2Player/Vav2Player/LayeredVideoPage.xaml b/vav2/Vav2Player/Vav2Player/LayeredVideoPage.xaml
new file mode 100644
index 0000000..0df40de
--- /dev/null
+++ b/vav2/Vav2Player/Vav2Player/LayeredVideoPage.xaml
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vav2/Vav2Player/Vav2Player/LayeredVideoPage.xaml.cpp b/vav2/Vav2Player/Vav2Player/LayeredVideoPage.xaml.cpp
new file mode 100644
index 0000000..212bdfa
--- /dev/null
+++ b/vav2/Vav2Player/Vav2Player/LayeredVideoPage.xaml.cpp
@@ -0,0 +1,116 @@
+#include "pch.h"
+#include "LayeredVideoPage.xaml.h"
+#if __has_include("LayeredVideoPage.g.cpp")
+#include "LayeredVideoPage.g.cpp"
+#endif
+
+using namespace winrt;
+using namespace winrt::Microsoft::UI::Xaml;
+
+namespace winrt::Vav2Player::implementation
+{
+ LayeredVideoPage::LayeredVideoPage()
+ {
+ InitializeComponent();
+ UpdateActiveLayerCount();
+ UpdateStatus(L"Layered Video - Ready");
+ }
+
+ // File load handlers
+ void LayeredVideoPage::LoadBackground_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ LoadVideoFileForLayer(1);
+ }
+
+ void LayeredVideoPage::LoadOverlay_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ LoadVideoFileForLayer(2);
+ }
+
+ void LayeredVideoPage::LoadPiP_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ LoadVideoFileForLayer(3);
+ }
+
+ // Opacity control handlers
+ void LayeredVideoPage::Layer1Opacity_Changed(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs const& e)
+ {
+ Layer1().Opacity(e.NewValue());
+ }
+
+ void LayeredVideoPage::Layer2Opacity_Changed(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs const& e)
+ {
+ Layer2().Opacity(e.NewValue());
+ }
+
+ void LayeredVideoPage::Layer3Opacity_Changed(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs const& e)
+ {
+ Layer3().Opacity(e.NewValue());
+ }
+
+ // Playback control handlers
+ void LayeredVideoPage::PlayAllLayers_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ VideoLayer1().Play();
+ VideoLayer2().Play();
+ VideoLayer3().Play();
+ UpdateStatus(L"Playing all layers");
+ }
+
+ void LayeredVideoPage::PauseAllLayers_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ VideoLayer1().Pause();
+ VideoLayer2().Pause();
+ VideoLayer3().Pause();
+ UpdateStatus(L"Paused all layers");
+ }
+
+ void LayeredVideoPage::StopAllLayers_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ VideoLayer1().Stop();
+ VideoLayer2().Stop();
+ VideoLayer3().Stop();
+ UpdateStatus(L"Stopped all layers");
+ }
+
+ // Helper methods
+ void LayeredVideoPage::UpdateActiveLayerCount()
+ {
+ // TODO: Implement proper layer counting
+ ActiveLayerCount().Text(L"0/3");
+ }
+
+ winrt::Windows::Foundation::IAsyncAction LayeredVideoPage::LoadVideoFileForLayer(int layerIndex)
+ {
+ // TODO: Implement file loading for specific layer
+ co_await resume_background();
+
+ // Update status based on layer
+ switch (layerIndex) {
+ case 1:
+ UpdateStatus(L"Loading background video - Coming soon");
+ break;
+ case 2:
+ UpdateStatus(L"Loading overlay video - Coming soon");
+ break;
+ case 3:
+ UpdateStatus(L"Loading PiP video - Coming soon");
+ break;
+ default:
+ UpdateStatus(L"Invalid layer index");
+ break;
+ }
+ }
+
+ void LayeredVideoPage::UpdateStatus(winrt::hstring const& message)
+ {
+ try {
+ if (LayeredVideoStatusText()) {
+ LayeredVideoStatusText().Text(message);
+ }
+ } catch (...) {
+ // Ignore if UI not ready yet
+ }
+ OutputDebugStringA((winrt::to_string(message) + "\n").c_str());
+ }
+}
\ No newline at end of file
diff --git a/vav2/Vav2Player/Vav2Player/LayeredVideoPage.xaml.h b/vav2/Vav2Player/Vav2Player/LayeredVideoPage.xaml.h
new file mode 100644
index 0000000..dcdff1a
--- /dev/null
+++ b/vav2/Vav2Player/Vav2Player/LayeredVideoPage.xaml.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#include "LayeredVideoPage.g.h"
+
+namespace winrt::Vav2Player::implementation
+{
+ struct LayeredVideoPage : LayeredVideoPageT
+ {
+ LayeredVideoPage();
+
+ // File load handlers
+ void LoadBackground_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void LoadOverlay_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void LoadPiP_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+
+ // Opacity control handlers
+ void Layer1Opacity_Changed(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs const& e);
+ void Layer2Opacity_Changed(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs const& e);
+ void Layer3Opacity_Changed(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs const& e);
+
+ // Playback control handlers
+ void PlayAllLayers_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void PauseAllLayers_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void StopAllLayers_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+
+ private:
+ // Helper methods
+ void UpdateActiveLayerCount();
+ winrt::Windows::Foundation::IAsyncAction LoadVideoFileForLayer(int layerIndex);
+ void UpdateStatus(winrt::hstring const& message);
+ };
+}
+
+namespace winrt::Vav2Player::factory_implementation
+{
+ struct LayeredVideoPage : LayeredVideoPageT
+ {
+ };
+}
\ No newline at end of file
diff --git a/vav2/Vav2Player/Vav2Player/LayeredVideoWindow.idl b/vav2/Vav2Player/Vav2Player/LayeredVideoWindow.idl
new file mode 100644
index 0000000..199383b
--- /dev/null
+++ b/vav2/Vav2Player/Vav2Player/LayeredVideoWindow.idl
@@ -0,0 +1,8 @@
+namespace Vav2Player
+{
+ [default_interface]
+ runtimeclass LayeredVideoWindow : Microsoft.UI.Xaml.Window
+ {
+ LayeredVideoWindow();
+ }
+}
\ No newline at end of file
diff --git a/vav2/Vav2Player/Vav2Player/LayeredVideoWindow.xaml b/vav2/Vav2Player/Vav2Player/LayeredVideoWindow.xaml
new file mode 100644
index 0000000..236d61d
--- /dev/null
+++ b/vav2/Vav2Player/Vav2Player/LayeredVideoWindow.xaml
@@ -0,0 +1,135 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vav2/Vav2Player/Vav2Player/LayeredVideoWindow.xaml.cpp b/vav2/Vav2Player/Vav2Player/LayeredVideoWindow.xaml.cpp
new file mode 100644
index 0000000..68c4240
--- /dev/null
+++ b/vav2/Vav2Player/Vav2Player/LayeredVideoWindow.xaml.cpp
@@ -0,0 +1,164 @@
+#include "pch.h"
+#include "LayeredVideoWindow.xaml.h"
+#if __has_include("LayeredVideoWindow.g.cpp")
+#include "LayeredVideoWindow.g.cpp"
+#endif
+
+using namespace winrt;
+using namespace winrt::Microsoft::UI::Xaml;
+
+namespace winrt::Vav2Player::implementation
+{
+ LayeredVideoWindow::LayeredVideoWindow()
+ {
+ InitializeComponent();
+ UpdateActiveLayerCount();
+ }
+
+ // Menu navigation handlers
+ void LayeredVideoWindow::SwitchToMainWindow_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ // TODO: Switch to main window
+ LayeredVideoStatusText().Text(L"Switching to Main Window...");
+ }
+
+ void LayeredVideoWindow::SwitchToMultiVideoTest_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ // TODO: Switch to multi video test window
+ LayeredVideoStatusText().Text(L"Switching to Multi Video Test...");
+ }
+
+ void LayeredVideoWindow::SwitchToLayeredVideo_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ // Already in layered video window
+ LayeredVideoStatusText().Text(L"Already in Layered Video window");
+ }
+
+ void LayeredVideoWindow::Exit_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ this->Close();
+ }
+
+ // Layer management handlers
+ void LayeredVideoWindow::AddLayer_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ LayeredVideoStatusText().Text(L"Add Layer functionality - Coming soon");
+ }
+
+ void LayeredVideoWindow::RemoveLayer_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ LayeredVideoStatusText().Text(L"Remove Layer functionality - Coming soon");
+ }
+
+ void LayeredVideoWindow::BringToFront_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ LayeredVideoStatusText().Text(L"Bring to Front functionality - Coming soon");
+ }
+
+ void LayeredVideoWindow::SendToBack_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ LayeredVideoStatusText().Text(L"Send to Back functionality - Coming soon");
+ }
+
+ // Effects handlers
+ void LayeredVideoWindow::FadeTransition_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ LayeredVideoStatusText().Text(L"Fade Transition functionality - Coming soon");
+ }
+
+ void LayeredVideoWindow::SlideTransition_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ LayeredVideoStatusText().Text(L"Slide Transition functionality - Coming soon");
+ }
+
+ void LayeredVideoWindow::BlendMode_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ LayeredVideoStatusText().Text(L"Blend Mode functionality - Coming soon");
+ }
+
+ // File load handlers
+ void LayeredVideoWindow::LoadBackground_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ LoadVideoFileForLayer(1);
+ }
+
+ void LayeredVideoWindow::LoadOverlay_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ LoadVideoFileForLayer(2);
+ }
+
+ void LayeredVideoWindow::LoadPiP_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ LoadVideoFileForLayer(3);
+ }
+
+ // Opacity control handlers
+ void LayeredVideoWindow::Layer1Opacity_Changed(IInspectable const&, Microsoft::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs const& e)
+ {
+ Layer1().Opacity(e.NewValue());
+ }
+
+ void LayeredVideoWindow::Layer2Opacity_Changed(IInspectable const&, Microsoft::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs const& e)
+ {
+ Layer2().Opacity(e.NewValue());
+ }
+
+ void LayeredVideoWindow::Layer3Opacity_Changed(IInspectable const&, Microsoft::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs const& e)
+ {
+ Layer3().Opacity(e.NewValue());
+ }
+
+ // Playback control handlers
+ void LayeredVideoWindow::PlayAllLayers_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ VideoLayer1().Play();
+ VideoLayer2().Play();
+ VideoLayer3().Play();
+ LayeredVideoStatusText().Text(L"Playing all layers");
+ }
+
+ void LayeredVideoWindow::PauseAllLayers_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ VideoLayer1().Pause();
+ VideoLayer2().Pause();
+ VideoLayer3().Pause();
+ LayeredVideoStatusText().Text(L"Paused all layers");
+ }
+
+ void LayeredVideoWindow::StopAllLayers_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ VideoLayer1().Stop();
+ VideoLayer2().Stop();
+ VideoLayer3().Stop();
+ LayeredVideoStatusText().Text(L"Stopped all layers");
+ }
+
+ // Helper methods
+ void LayeredVideoWindow::UpdateActiveLayerCount()
+ {
+ // TODO: Implement proper layer counting
+ ActiveLayerCount().Text(L"0/3");
+ }
+
+ Windows::Foundation::IAsyncAction LayeredVideoWindow::LoadVideoFileForLayer(int layerIndex)
+ {
+ // TODO: Implement file loading for specific layer
+ co_await resume_background();
+
+ // Update status based on layer
+ switch (layerIndex) {
+ case 1:
+ LayeredVideoStatusText().Text(L"Loading background video - Coming soon");
+ break;
+ case 2:
+ LayeredVideoStatusText().Text(L"Loading overlay video - Coming soon");
+ break;
+ case 3:
+ LayeredVideoStatusText().Text(L"Loading PiP video - Coming soon");
+ break;
+ default:
+ LayeredVideoStatusText().Text(L"Invalid layer index");
+ break;
+ }
+ }
+}
\ No newline at end of file
diff --git a/vav2/Vav2Player/Vav2Player/LayeredVideoWindow.xaml.h b/vav2/Vav2Player/Vav2Player/LayeredVideoWindow.xaml.h
new file mode 100644
index 0000000..e95331b
--- /dev/null
+++ b/vav2/Vav2Player/Vav2Player/LayeredVideoWindow.xaml.h
@@ -0,0 +1,55 @@
+#pragma once
+
+#include "LayeredVideoWindow.g.h"
+
+namespace winrt::Vav2Player::implementation
+{
+ struct LayeredVideoWindow : LayeredVideoWindowT
+ {
+ LayeredVideoWindow();
+
+ // Menu event handlers
+ void SwitchToMainWindow_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void SwitchToMultiVideoTest_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void SwitchToLayeredVideo_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void Exit_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+
+ // Layer menu handlers
+ void AddLayer_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void RemoveLayer_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void BringToFront_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void SendToBack_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+
+ // Effects menu handlers
+ void FadeTransition_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void SlideTransition_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void BlendMode_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+
+ // File load handlers
+ void LoadBackground_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void LoadOverlay_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void LoadPiP_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+
+ // Opacity control handlers
+ void Layer1Opacity_Changed(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs const& e);
+ void Layer2Opacity_Changed(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs const& e);
+ void Layer3Opacity_Changed(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs const& e);
+
+ // Playback control handlers
+ void PlayAllLayers_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void PauseAllLayers_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void StopAllLayers_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+
+ private:
+ // Helper methods
+ void UpdateActiveLayerCount();
+ winrt::Windows::Foundation::IAsyncAction LoadVideoFileForLayer(int layerIndex);
+ };
+}
+
+namespace winrt::Vav2Player::factory_implementation
+{
+ struct LayeredVideoWindow : LayeredVideoWindowT
+ {
+ };
+}
\ No newline at end of file
diff --git a/vav2/Vav2Player/Vav2Player/MainVideoPage.idl b/vav2/Vav2Player/Vav2Player/MainVideoPage.idl
new file mode 100644
index 0000000..25e68e2
--- /dev/null
+++ b/vav2/Vav2Player/Vav2Player/MainVideoPage.idl
@@ -0,0 +1,8 @@
+namespace Vav2Player
+{
+ [default_interface]
+ runtimeclass MainVideoPage : Microsoft.UI.Xaml.Controls.Page
+ {
+ MainVideoPage();
+ }
+}
\ No newline at end of file
diff --git a/vav2/Vav2Player/Vav2Player/MainVideoPage.xaml b/vav2/Vav2Player/Vav2Player/MainVideoPage.xaml
new file mode 100644
index 0000000..9f21715
--- /dev/null
+++ b/vav2/Vav2Player/Vav2Player/MainVideoPage.xaml
@@ -0,0 +1,144 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vav2/Vav2Player/Vav2Player/MainVideoPage.xaml.cpp b/vav2/Vav2Player/Vav2Player/MainVideoPage.xaml.cpp
new file mode 100644
index 0000000..01becb3
--- /dev/null
+++ b/vav2/Vav2Player/Vav2Player/MainVideoPage.xaml.cpp
@@ -0,0 +1,299 @@
+#include "pch.h"
+#include "MainVideoPage.xaml.h"
+#if __has_include("MainVideoPage.g.cpp")
+#include "MainVideoPage.g.cpp"
+#endif
+
+using namespace winrt;
+using namespace winrt::Microsoft::UI::Xaml;
+
+namespace winrt::Vav2Player::implementation
+{
+ MainVideoPage::MainVideoPage()
+ {
+ InitializeComponent();
+ }
+
+ winrt::Windows::Foundation::IAsyncAction MainVideoPage::OpenFileButton_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ try
+ {
+ // Create file picker
+ winrt::Windows::Storage::Pickers::FileOpenPicker picker;
+ picker.ViewMode(winrt::Windows::Storage::Pickers::PickerViewMode::Thumbnail);
+ picker.SuggestedStartLocation(winrt::Windows::Storage::Pickers::PickerLocationId::VideosLibrary);
+
+ // Add supported video file types
+ picker.FileTypeFilter().Append(L".webm");
+ picker.FileTypeFilter().Append(L".mkv");
+ picker.FileTypeFilter().Append(L".mp4");
+ picker.FileTypeFilter().Append(L".avi");
+
+ // Initialize picker with window handle - use simple approach for Page
+ try {
+ auto initializeWithWindow = picker.as();
+
+ // Get the active window handle
+ HWND hWnd = GetActiveWindow();
+ if (hWnd == nullptr)
+ {
+ hWnd = GetForegroundWindow();
+ }
+
+ if (hWnd != nullptr)
+ {
+ initializeWithWindow->Initialize(hWnd);
+ }
+ }
+ catch (...)
+ {
+ // If window handle initialization fails, continue without it
+ // FileOpenPicker might still work in some cases
+ }
+
+ // Show picker and get selected file
+ auto file = co_await picker.PickSingleFileAsync();
+ if (file != nullptr)
+ {
+ auto filePath = file.Path();
+
+ // Load video using VideoPlayerControl
+ if (VideoPlayer()) {
+ VideoPlayer().LoadVideo(filePath);
+ }
+
+ // Update UI
+ if (StatusText()) {
+ StatusText().Text(L"Loading video: " + filePath);
+ }
+ if (PlayButton()) PlayButton().IsEnabled(true);
+ if (PauseButton()) PauseButton().IsEnabled(true);
+ if (StopButton()) StopButton().IsEnabled(true);
+ }
+ else
+ {
+ if (StatusText()) {
+ StatusText().Text(L"No file selected");
+ }
+ }
+ }
+ catch (...)
+ {
+ if (StatusText()) {
+ StatusText().Text(L"Failed to open file picker or load video");
+ }
+ }
+ }
+
+ void MainVideoPage::TestDecodeButton_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ try {
+ if (StatusText()) {
+ StatusText().Text(L"Test decode functionality - Coming soon");
+ }
+ } catch (...) {
+ // Ignore errors during initialization
+ }
+ }
+
+ void MainVideoPage::PlayButton_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ try {
+ if (VideoPlayer()) {
+ VideoPlayer().Play();
+ }
+ if (StatusText()) {
+ StatusText().Text(L"Playing video...");
+ }
+ } catch (...) {
+ if (StatusText()) {
+ StatusText().Text(L"Failed to play video");
+ }
+ }
+ }
+
+ void MainVideoPage::PauseButton_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ try {
+ if (VideoPlayer()) {
+ VideoPlayer().Pause();
+ }
+ if (StatusText()) {
+ StatusText().Text(L"Video paused");
+ }
+ } catch (...) {
+ if (StatusText()) {
+ StatusText().Text(L"Failed to pause video");
+ }
+ }
+ }
+
+ void MainVideoPage::StopButton_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ try {
+ if (VideoPlayer()) {
+ VideoPlayer().Stop();
+ }
+ if (StatusText()) {
+ StatusText().Text(L"Video stopped");
+ }
+ } catch (...) {
+ if (StatusText()) {
+ StatusText().Text(L"Failed to stop video");
+ }
+ }
+ }
+
+ void MainVideoPage::DecoderSelectionComboBox_SelectionChanged(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const&)
+ {
+ try {
+ if (StatusText()) {
+ StatusText().Text(L"Decoder selection changed");
+ }
+ } catch (...) {
+ // Ignore errors during initialization
+ }
+ }
+
+ void MainVideoPage::EnableFileOutputCheckBox_Checked(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ try {
+ if (OutputFormatComboBox()) {
+ OutputFormatComboBox().IsEnabled(true);
+ }
+ if (StatusText()) {
+ StatusText().Text(L"File output enabled");
+ }
+ } catch (...) {
+ // Ignore errors during initialization
+ }
+ }
+
+ void MainVideoPage::EnableFileOutputCheckBox_Unchecked(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ try {
+ if (OutputFormatComboBox()) {
+ OutputFormatComboBox().IsEnabled(false);
+ }
+ if (StatusText()) {
+ StatusText().Text(L"File output disabled");
+ }
+ } catch (...) {
+ // Ignore errors during initialization
+ }
+ }
+
+ void MainVideoPage::OutputFormatComboBox_SelectionChanged(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const&)
+ {
+ try {
+ if (StatusText()) {
+ StatusText().Text(L"Output format changed");
+ }
+ } catch (...) {
+ // Ignore errors during initialization
+ }
+ }
+
+ // Helper methods - actual implementations
+ void MainVideoPage::ConvertYUVToBGRA(const VavCoreVideoFrame& yuv_frame, uint8_t* bgra_buffer, uint32_t width, uint32_t height)
+ {
+ const uint8_t* y_plane = yuv_frame.y_plane;
+ const uint8_t* u_plane = yuv_frame.u_plane;
+ const uint8_t* v_plane = yuv_frame.v_plane;
+
+ const int32_t y_stride = yuv_frame.y_stride;
+ const int32_t u_stride = yuv_frame.u_stride;
+ const int32_t v_stride = yuv_frame.v_stride;
+
+ // Lookup table optimization
+ static bool lookup_initialized = false;
+ static int16_t r_v_table[256];
+ static int16_t g_u_table[256];
+ static int16_t g_v_table[256];
+ static int16_t b_u_table[256];
+
+ if (!lookup_initialized) {
+ for (int i = 0; i < 256; i++) {
+ int uv_val = i - 128;
+ r_v_table[i] = (409 * uv_val + 128) >> 8;
+ g_u_table[i] = (100 * uv_val + 128) >> 8;
+ g_v_table[i] = (208 * uv_val + 128) >> 8;
+ b_u_table[i] = (516 * uv_val + 128) >> 8;
+ }
+ lookup_initialized = true;
+ }
+
+ // Process 4 pixels at a time for cache efficiency
+ for (uint32_t row = 0; row < height; row += 2) {
+ for (uint32_t col = 0; col < width; col += 2) {
+ // UV values are one per 2x2 block
+ uint32_t uv_row = row / 2;
+ uint32_t uv_col = col / 2;
+
+ if (uv_row >= height / 2 || uv_col >= width / 2) continue;
+
+ int u = u_plane[uv_row * u_stride + uv_col];
+ int v = v_plane[uv_row * v_stride + uv_col];
+
+ // Get conversion coefficients from lookup table
+ int r_offset = r_v_table[v];
+ int g_u_offset = g_u_table[u];
+ int g_v_offset = g_v_table[v];
+ int b_offset = b_u_table[u];
+
+ // Process 4 pixels in 2x2 block
+ for (int dy = 0; dy < 2 && (row + dy) < height; dy++) {
+ for (int dx = 0; dx < 2 && (col + dx) < width; dx++) {
+ uint32_t pixel_row = row + dy;
+ uint32_t pixel_col = col + dx;
+
+ int y = y_plane[pixel_row * y_stride + pixel_col];
+ int y_scaled = (298 * (y - 16) + 128) >> 8;
+
+ // RGB calculation
+ int r = std::clamp(y_scaled + r_offset, 0, 255);
+ int g = std::clamp(y_scaled - g_u_offset - g_v_offset, 0, 255);
+ int b = std::clamp(y_scaled + b_offset, 0, 255);
+
+ // Store as BGRA format
+ uint32_t pixel_offset = (pixel_row * width + pixel_col) * 4;
+ bgra_buffer[pixel_offset + 0] = static_cast(b);
+ bgra_buffer[pixel_offset + 1] = static_cast(g);
+ bgra_buffer[pixel_offset + 2] = static_cast(r);
+ bgra_buffer[pixel_offset + 3] = 255;
+ }
+ }
+ }
+ }
+ }
+
+ void MainVideoPage::RenderFrameToScreen(const VavCoreVideoFrame& frame, winrt::Microsoft::UI::Xaml::Media::Imaging::WriteableBitmap& bitmap, std::vector& bgra_buffer)
+ {
+ // Check for valid frame and bitmap
+ if (!frame.y_plane || !bitmap) {
+ return;
+ }
+
+ try {
+ // Convert YUV to BGRA
+ ConvertYUVToBGRA(frame, bgra_buffer.data(), frame.width, frame.height);
+
+ // Get direct access to WriteableBitmap pixel buffer
+ auto buffer = bitmap.PixelBuffer();
+ auto byteAccess = buffer.as<::IBufferByteAccess>();
+ uint8_t* dest_pixels = nullptr;
+ byteAccess->Buffer(&dest_pixels);
+
+ if (dest_pixels) {
+ // Direct memory copy to minimize overhead
+ memcpy(dest_pixels, bgra_buffer.data(), bgra_buffer.size());
+
+ // Invalidate bitmap to trigger UI update
+ bitmap.Invalidate();
+ }
+ }
+ catch (...) {
+ // Ignore rendering errors
+ }
+ }
+}
\ No newline at end of file
diff --git a/vav2/Vav2Player/Vav2Player/MainVideoPage.xaml.h b/vav2/Vav2Player/Vav2Player/MainVideoPage.xaml.h
new file mode 100644
index 0000000..1c7922f
--- /dev/null
+++ b/vav2/Vav2Player/Vav2Player/MainVideoPage.xaml.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "MainVideoPage.g.h"
+#include "VavCore/VavCore.h"
+
+namespace winrt::Vav2Player::implementation
+{
+ struct MainVideoPage : MainVideoPageT
+ {
+ MainVideoPage();
+
+ winrt::Windows::Foundation::IAsyncAction OpenFileButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void TestDecodeButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void PlayButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void PauseButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void StopButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void DecoderSelectionComboBox_SelectionChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const& e);
+ void EnableFileOutputCheckBox_Checked(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void EnableFileOutputCheckBox_Unchecked(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void OutputFormatComboBox_SelectionChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const& e);
+
+ // Helper methods
+ static void ConvertYUVToBGRA(const VavCoreVideoFrame& yuv_frame, uint8_t* bgra_buffer, uint32_t width, uint32_t height);
+ static void RenderFrameToScreen(const VavCoreVideoFrame& frame, winrt::Microsoft::UI::Xaml::Media::Imaging::WriteableBitmap& bitmap, std::vector& bgra_buffer);
+ };
+}
+
+namespace winrt::Vav2Player::factory_implementation
+{
+ struct MainVideoPage : MainVideoPageT
+ {
+ };
+}
\ No newline at end of file
diff --git a/vav2/Vav2Player/Vav2Player/MainWindow.xaml b/vav2/Vav2Player/Vav2Player/MainWindow.xaml
index 8159c8e..3750511 100644
--- a/vav2/Vav2Player/Vav2Player/MainWindow.xaml
+++ b/vav2/Vav2Player/Vav2Player/MainWindow.xaml
@@ -11,135 +11,24 @@
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
diff --git a/vav2/Vav2Player/Vav2Player/MainWindow.xaml.cpp b/vav2/Vav2Player/Vav2Player/MainWindow.xaml.cpp
index 9ce6fdb..a296c74 100644
--- a/vav2/Vav2Player/Vav2Player/MainWindow.xaml.cpp
+++ b/vav2/Vav2Player/Vav2Player/MainWindow.xaml.cpp
@@ -1,14 +1,15 @@
#include "pch.h"
#include "MainWindow.xaml.h"
+#include "MainVideoPage.xaml.h"
+#include "MultiVideoTestPage.xaml.h"
+#include "LayeredVideoPage.xaml.h"
#if __has_include("MainWindow.g.cpp")
#include "MainWindow.g.cpp"
#endif
using namespace winrt;
using namespace winrt::Microsoft::UI::Xaml;
-
-// To learn more about WinUI, the WinUI project structure,
-// and more about our project templates, see: http://aka.ms/winui-project-info.
+using namespace winrt::Windows::UI::Xaml::Interop;
namespace winrt::Vav2Player::implementation
{
@@ -16,228 +17,64 @@ namespace winrt::Vav2Player::implementation
{
InitializeComponent();
- // Configure VideoPlayerControl
- VideoPlayer().UseHardwareRendering(true);
- VideoPlayer().ShowControls(false);
- VideoPlayer().AutoPlay(false);
+ // Load Multi Video Test as default page (시작화면)
+ TypeName pageTypeName;
+ pageTypeName.Name = winrt::name_of();
+ pageTypeName.Kind = TypeKind::Metadata;
+ ContentFrame().Navigate(pageTypeName);
+ }
+
+ // Navigation event handlers
+ void MainWindow::SwitchToMainView_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ TypeName pageTypeName;
+ pageTypeName.Name = winrt::name_of();
+ pageTypeName.Kind = TypeKind::Metadata;
+ ContentFrame().Navigate(pageTypeName);
+ }
+
+ void MainWindow::SwitchToMultiVideoView_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ TypeName pageTypeName;
+ pageTypeName.Name = winrt::name_of();
+ pageTypeName.Kind = TypeKind::Metadata;
+ ContentFrame().Navigate(pageTypeName);
+ }
+
+ void MainWindow::SwitchToLayeredVideoView_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ TypeName pageTypeName;
+ pageTypeName.Name = winrt::name_of();
+ pageTypeName.Kind = TypeKind::Metadata;
+ ContentFrame().Navigate(pageTypeName);
+ }
+
+ void MainWindow::Exit_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ this->Close();
}
- // 성능 최적화된 YUV to BGRA 변환 함수
- void MainWindow::ConvertYUVToBGRA(const VideoFrame& yuv_frame, uint8_t* bgra_buffer, uint32_t width, uint32_t height)
+ void MainWindow::Settings_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
{
- const uint8_t* y_plane = yuv_frame.y_plane.get();
- const uint8_t* u_plane = yuv_frame.u_plane.get();
- const uint8_t* v_plane = yuv_frame.v_plane.get();
-
- const int32_t y_stride = yuv_frame.y_stride;
- const int32_t u_stride = yuv_frame.u_stride;
- const int32_t v_stride = yuv_frame.v_stride;
-
- // 룩업 테이블을 사용한 최적화
- static bool lookup_initialized = false;
- static int16_t r_v_table[256];
- static int16_t g_u_table[256];
- static int16_t g_v_table[256];
- static int16_t b_u_table[256];
-
- if (!lookup_initialized) {
- for (int i = 0; i < 256; i++) {
- int uv_val = i - 128;
- r_v_table[i] = (409 * uv_val + 128) >> 8;
- g_u_table[i] = (100 * uv_val + 128) >> 8;
- g_v_table[i] = (208 * uv_val + 128) >> 8;
- b_u_table[i] = (516 * uv_val + 128) >> 8;
- }
- lookup_initialized = true;
- }
-
- // 4픽셀씩 처리하여 캐시 효율성 향상
- for (uint32_t row = 0; row < height; row += 2) {
- for (uint32_t col = 0; col < width; col += 2) {
- // UV값은 2x2 블록당 하나
- uint32_t uv_row = row / 2;
- uint32_t uv_col = col / 2;
-
- if (uv_row >= height / 2 || uv_col >= width / 2) continue;
-
- int u = u_plane[uv_row * u_stride + uv_col];
- int v = v_plane[uv_row * v_stride + uv_col];
-
- // 룩업 테이블에서 변환 계수 가져오기
- int r_offset = r_v_table[v];
- int g_u_offset = g_u_table[u];
- int g_v_offset = g_v_table[v];
- int b_offset = b_u_table[u];
-
- // 2x2 블록의 4개 픽셀 처리
- for (int dy = 0; dy < 2 && (row + dy) < height; dy++) {
- for (int dx = 0; dx < 2 && (col + dx) < width; dx++) {
- uint32_t pixel_row = row + dy;
- uint32_t pixel_col = col + dx;
-
- int y = y_plane[pixel_row * y_stride + pixel_col];
- int y_scaled = (298 * (y - 16) + 128) >> 8;
-
- // RGB 계산
- int r = std::clamp(y_scaled + r_offset, 0, 255);
- int g = std::clamp(y_scaled - g_u_offset - g_v_offset, 0, 255);
- int b = std::clamp(y_scaled + b_offset, 0, 255);
-
- // BGRA 형식으로 저장
- uint32_t pixel_offset = (pixel_row * width + pixel_col) * 4;
- bgra_buffer[pixel_offset + 0] = static_cast(b);
- bgra_buffer[pixel_offset + 1] = static_cast(g);
- bgra_buffer[pixel_offset + 2] = static_cast(r);
- bgra_buffer[pixel_offset + 3] = 255;
- }
- }
- }
- }
+ // Could implement Settings functionality
+ // For now, just show a message (no status bar in frame layout)
}
- // 성능 최적화된 프레임 렌더링 함수
- void MainWindow::RenderFrameToScreen(const VideoFrame& frame, Media::Imaging::WriteableBitmap& bitmap, std::vector& bgra_buffer)
+ void MainWindow::About_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
{
- if (!frame.is_valid || !bitmap) {
- return;
- }
-
- try {
- // YUV를 BGRA로 변환
- ConvertYUVToBGRA(frame, bgra_buffer.data(), frame.width, frame.height);
-
- // WriteableBitmap의 픽셀 버퍼에 직접 액세스
- auto buffer = bitmap.PixelBuffer();
- auto byteAccess = buffer.as<::IBufferByteAccess>();
- uint8_t* dest_pixels = nullptr;
- byteAccess->Buffer(&dest_pixels);
-
- if (dest_pixels) {
- // 메모리 복사를 최소화하기 위해 직접 복사
- memcpy(dest_pixels, bgra_buffer.data(), bgra_buffer.size());
-
- // 비트맵 무효화하여 UI 업데이트 트리거
- bitmap.Invalidate();
- }
- }
- catch (...) {
- // 렌더링 오류 무시
- }
+ // Could implement About dialog
+ // For now, just show a message (no status bar in frame layout)
}
- winrt::Windows::Foundation::IAsyncAction MainWindow::OpenFileButton_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ // Helper methods moved to MainVideoPage
+ void MainWindow::ConvertYUVToBGRA(const VavCoreVideoFrame& yuv_frame, uint8_t* bgra_buffer, uint32_t width, uint32_t height)
{
- try
- {
- // Create file picker
- winrt::Windows::Storage::Pickers::FileOpenPicker picker;
- picker.ViewMode(winrt::Windows::Storage::Pickers::PickerViewMode::Thumbnail);
- picker.SuggestedStartLocation(winrt::Windows::Storage::Pickers::PickerLocationId::VideosLibrary);
-
- // Add supported video file types
- picker.FileTypeFilter().Append(L".webm");
- picker.FileTypeFilter().Append(L".mkv");
- picker.FileTypeFilter().Append(L".mp4");
- picker.FileTypeFilter().Append(L".avi");
-
- // Initialize picker with window handle
- auto initializeWithWindow = picker.as();
- auto windowNative = this->try_as();
- HWND hWnd = nullptr;
- if (windowNative)
- {
- windowNative->get_WindowHandle(&hWnd);
- }
- initializeWithWindow->Initialize(hWnd);
-
- // Show picker and get selected file
- auto file = co_await picker.PickSingleFileAsync();
- if (file != nullptr)
- {
- auto filePath = file.Path();
-
- // Load video using VideoPlayerControl
- VideoPlayer().LoadVideo(filePath);
-
- // Update UI
- StatusText().Text(L"Loading video: " + filePath);
- PlayButton().IsEnabled(true);
- PauseButton().IsEnabled(true);
- StopButton().IsEnabled(true);
- }
- else
- {
- StatusText().Text(L"No file selected");
- }
- }
- catch (...)
- {
- StatusText().Text(L"Failed to open file picker or load video");
- }
+ // Implementation moved to MainVideoPage
}
- void MainWindow::TestDecodeButton_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ void MainWindow::RenderFrameToScreen(const VavCoreVideoFrame& frame, winrt::Microsoft::UI::Xaml::Media::Imaging::WriteableBitmap& bitmap, std::vector& bgra_buffer)
{
- // Not implemented
- }
-
- void MainWindow::PlayButton_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
- {
- try
- {
- VideoPlayer().Play();
- StatusText().Text(L"Playing video...");
- }
- catch (...)
- {
- StatusText().Text(L"Failed to play video");
- }
- }
-
- void MainWindow::PauseButton_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
- {
- try
- {
- VideoPlayer().Pause();
- StatusText().Text(L"Video paused");
- }
- catch (...)
- {
- StatusText().Text(L"Failed to pause video");
- }
- }
-
- void MainWindow::StopButton_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
- {
- try
- {
- VideoPlayer().Stop();
- StatusText().Text(L"Video stopped");
- }
- catch (...)
- {
- StatusText().Text(L"Failed to stop video");
- }
- }
-
- void MainWindow::DecoderSelectionComboBox_SelectionChanged(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const&)
- {
- // Not implemented
- }
-
- void MainWindow::EnableFileOutputCheckBox_Checked(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
- {
- // Not implemented
- }
-
- void MainWindow::EnableFileOutputCheckBox_Unchecked(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
- {
- // Not implemented
- }
-
- void MainWindow::OutputFormatComboBox_SelectionChanged(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const&)
- {
- // Not implemented
+ // Implementation moved to MainVideoPage
}
}
\ No newline at end of file
diff --git a/vav2/Vav2Player/Vav2Player/MainWindow.xaml.h b/vav2/Vav2Player/Vav2Player/MainWindow.xaml.h
index 0f92bef..6bd9362 100644
--- a/vav2/Vav2Player/Vav2Player/MainWindow.xaml.h
+++ b/vav2/Vav2Player/Vav2Player/MainWindow.xaml.h
@@ -1,6 +1,7 @@
#pragma once
#include "MainWindow.g.h"
+#include "VavCore/VavCore.h"
namespace winrt::Vav2Player::implementation
{
@@ -8,22 +9,19 @@ namespace winrt::Vav2Player::implementation
{
MainWindow();
- winrt::Windows::Foundation::IAsyncAction OpenFileButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
- void TestDecodeButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
- void PlayButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
- void PauseButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
- void StopButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
- void DecoderSelectionComboBox_SelectionChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const& e);
- void EnableFileOutputCheckBox_Checked(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
- void EnableFileOutputCheckBox_Unchecked(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
- void OutputFormatComboBox_SelectionChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const& e);
-
-
+ // These methods are no longer needed - moved to MainVideoPage
+ // Navigation event handlers
+ void SwitchToMainView_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void SwitchToMultiVideoView_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void SwitchToLayeredVideoView_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void Exit_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void Settings_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void About_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
// 성능 최적화된 비디오 렌더링 함수들
- static void ConvertYUVToBGRA(const VideoFrame& yuv_frame, uint8_t* bgra_buffer, uint32_t width, uint32_t height);
- static void RenderFrameToScreen(const VideoFrame& frame, winrt::Microsoft::UI::Xaml::Media::Imaging::WriteableBitmap& bitmap, std::vector& bgra_buffer);
+ static void ConvertYUVToBGRA(const VavCoreVideoFrame& yuv_frame, uint8_t* bgra_buffer, uint32_t width, uint32_t height);
+ static void RenderFrameToScreen(const VavCoreVideoFrame& frame, winrt::Microsoft::UI::Xaml::Media::Imaging::WriteableBitmap& bitmap, std::vector& bgra_buffer);
};
}
diff --git a/vav2/Vav2Player/Vav2Player/MainWindow_old.xaml.cpp b/vav2/Vav2Player/Vav2Player/MainWindow_old.xaml.cpp
new file mode 100644
index 0000000..093e4de
--- /dev/null
+++ b/vav2/Vav2Player/Vav2Player/MainWindow_old.xaml.cpp
@@ -0,0 +1,290 @@
+#include "pch.h"
+#include "MainWindow.xaml.h"
+#include "MainVideoPage.xaml.h"
+#include "MultiVideoTestPage.xaml.h"
+#include "LayeredVideoPage.xaml.h"
+#if __has_include("MainWindow.g.cpp")
+#include "MainWindow.g.cpp"
+#endif
+
+using namespace winrt;
+using namespace winrt::Microsoft::UI::Xaml;
+
+// To learn more about WinUI, the WinUI project structure,
+// and more about our project templates, see: http://aka.ms/winui-project-info.
+
+namespace winrt::Vav2Player::implementation
+{
+ MainWindow::MainWindow()
+ {
+ InitializeComponent();
+
+ // Load Multi Video Test as default page (시작화면)
+ ContentFrame().Navigate(winrt::xaml_typename());
+ }
+
+
+ // 성능 최적화된 YUV to BGRA 변환 함수
+ void MainWindow::ConvertYUVToBGRA(const VavCoreVideoFrame& yuv_frame, uint8_t* bgra_buffer, uint32_t width, uint32_t height)
+ {
+ const uint8_t* y_plane = yuv_frame.y_plane;
+ const uint8_t* u_plane = yuv_frame.u_plane;
+ const uint8_t* v_plane = yuv_frame.v_plane;
+
+ const int32_t y_stride = yuv_frame.y_stride;
+ const int32_t u_stride = yuv_frame.u_stride;
+ const int32_t v_stride = yuv_frame.v_stride;
+
+ // 룩업 테이블을 사용한 최적화
+ static bool lookup_initialized = false;
+ static int16_t r_v_table[256];
+ static int16_t g_u_table[256];
+ static int16_t g_v_table[256];
+ static int16_t b_u_table[256];
+
+ if (!lookup_initialized) {
+ for (int i = 0; i < 256; i++) {
+ int uv_val = i - 128;
+ r_v_table[i] = (409 * uv_val + 128) >> 8;
+ g_u_table[i] = (100 * uv_val + 128) >> 8;
+ g_v_table[i] = (208 * uv_val + 128) >> 8;
+ b_u_table[i] = (516 * uv_val + 128) >> 8;
+ }
+ lookup_initialized = true;
+ }
+
+ // 4픽셀씩 처리하여 캐시 효율성 향상
+ for (uint32_t row = 0; row < height; row += 2) {
+ for (uint32_t col = 0; col < width; col += 2) {
+ // UV값은 2x2 블록당 하나
+ uint32_t uv_row = row / 2;
+ uint32_t uv_col = col / 2;
+
+ if (uv_row >= height / 2 || uv_col >= width / 2) continue;
+
+ int u = u_plane[uv_row * u_stride + uv_col];
+ int v = v_plane[uv_row * v_stride + uv_col];
+
+ // 룩업 테이블에서 변환 계수 가져오기
+ int r_offset = r_v_table[v];
+ int g_u_offset = g_u_table[u];
+ int g_v_offset = g_v_table[v];
+ int b_offset = b_u_table[u];
+
+ // 2x2 블록의 4개 픽셀 처리
+ for (int dy = 0; dy < 2 && (row + dy) < height; dy++) {
+ for (int dx = 0; dx < 2 && (col + dx) < width; dx++) {
+ uint32_t pixel_row = row + dy;
+ uint32_t pixel_col = col + dx;
+
+ int y = y_plane[pixel_row * y_stride + pixel_col];
+ int y_scaled = (298 * (y - 16) + 128) >> 8;
+
+ // RGB 계산
+ int r = std::clamp(y_scaled + r_offset, 0, 255);
+ int g = std::clamp(y_scaled - g_u_offset - g_v_offset, 0, 255);
+ int b = std::clamp(y_scaled + b_offset, 0, 255);
+
+ // BGRA 형식으로 저장
+ uint32_t pixel_offset = (pixel_row * width + pixel_col) * 4;
+ bgra_buffer[pixel_offset + 0] = static_cast(b);
+ bgra_buffer[pixel_offset + 1] = static_cast(g);
+ bgra_buffer[pixel_offset + 2] = static_cast(r);
+ bgra_buffer[pixel_offset + 3] = 255;
+ }
+ }
+ }
+ }
+ }
+
+ // 성능 최적화된 프레임 렌더링 함수
+ void MainWindow::RenderFrameToScreen(const VavCoreVideoFrame& frame, Media::Imaging::WriteableBitmap& bitmap, std::vector& bgra_buffer)
+ {
+ // VavCoreVideoFrame doesn't have is_valid, check for null pointers instead
+ if (!frame.y_plane || !bitmap) {
+ return;
+ }
+
+ try {
+ // YUV를 BGRA로 변환
+ ConvertYUVToBGRA(frame, bgra_buffer.data(), frame.width, frame.height);
+
+ // WriteableBitmap의 픽셀 버퍼에 직접 액세스
+ auto buffer = bitmap.PixelBuffer();
+ auto byteAccess = buffer.as<::IBufferByteAccess>();
+ uint8_t* dest_pixels = nullptr;
+ byteAccess->Buffer(&dest_pixels);
+
+ if (dest_pixels) {
+ // 메모리 복사를 최소화하기 위해 직접 복사
+ memcpy(dest_pixels, bgra_buffer.data(), bgra_buffer.size());
+
+ // 비트맵 무효화하여 UI 업데이트 트리거
+ bitmap.Invalidate();
+ }
+ }
+ catch (...) {
+ // 렌더링 오류 무시
+ }
+ }
+
+ winrt::Windows::Foundation::IAsyncAction MainWindow::OpenFileButton_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ try
+ {
+ // Create file picker
+ winrt::Windows::Storage::Pickers::FileOpenPicker picker;
+ picker.ViewMode(winrt::Windows::Storage::Pickers::PickerViewMode::Thumbnail);
+ picker.SuggestedStartLocation(winrt::Windows::Storage::Pickers::PickerLocationId::VideosLibrary);
+
+ // Add supported video file types
+ picker.FileTypeFilter().Append(L".webm");
+ picker.FileTypeFilter().Append(L".mkv");
+ picker.FileTypeFilter().Append(L".mp4");
+ picker.FileTypeFilter().Append(L".avi");
+
+ // Initialize picker with window handle
+ auto initializeWithWindow = picker.as();
+ auto windowNative = this->try_as();
+ HWND hWnd = nullptr;
+ if (windowNative)
+ {
+ windowNative->get_WindowHandle(&hWnd);
+ }
+ initializeWithWindow->Initialize(hWnd);
+
+ // Show picker and get selected file
+ auto file = co_await picker.PickSingleFileAsync();
+ if (file != nullptr)
+ {
+ auto filePath = file.Path();
+
+ // Load video using VideoPlayerControl
+ VideoPlayer().LoadVideo(filePath);
+
+ // Update UI
+ StatusText().Text(L"Loading video: " + filePath);
+ PlayButton().IsEnabled(true);
+ PauseButton().IsEnabled(true);
+ StopButton().IsEnabled(true);
+ }
+ else
+ {
+ StatusText().Text(L"No file selected");
+ }
+ }
+ catch (...)
+ {
+ StatusText().Text(L"Failed to open file picker or load video");
+ }
+ }
+
+ void MainWindow::TestDecodeButton_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ // Not implemented
+ }
+
+ void MainWindow::PlayButton_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ try
+ {
+ VideoPlayer().Play();
+ StatusText().Text(L"Playing video...");
+ }
+ catch (...)
+ {
+ StatusText().Text(L"Failed to play video");
+ }
+ }
+
+ void MainWindow::PauseButton_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ try
+ {
+ VideoPlayer().Pause();
+ StatusText().Text(L"Video paused");
+ }
+ catch (...)
+ {
+ StatusText().Text(L"Failed to pause video");
+ }
+ }
+
+ void MainWindow::StopButton_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ try
+ {
+ VideoPlayer().Stop();
+ StatusText().Text(L"Video stopped");
+ }
+ catch (...)
+ {
+ StatusText().Text(L"Failed to stop video");
+ }
+ }
+
+ void MainWindow::DecoderSelectionComboBox_SelectionChanged(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const&)
+ {
+ // Not implemented
+ }
+
+ void MainWindow::EnableFileOutputCheckBox_Checked(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ // Not implemented
+ }
+
+ void MainWindow::EnableFileOutputCheckBox_Unchecked(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ // Not implemented
+ }
+
+ void MainWindow::OutputFormatComboBox_SelectionChanged(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const&)
+ {
+ // Not implemented
+ }
+
+ // Navigation event handlers
+ void MainWindow::SwitchToMainView_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ ContentFrame().Navigate(winrt::xaml_typename());
+ }
+
+ void MainWindow::SwitchToMultiVideoView_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ ContentFrame().Navigate(winrt::xaml_typename());
+ }
+
+ void MainWindow::SwitchToLayeredVideoView_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ ContentFrame().Navigate(winrt::xaml_typename());
+ }
+
+ void MainWindow::Exit_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ this->Close();
+ }
+
+ void MainWindow::VavCoreTest_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ // Could implement VavCore Test functionality
+ // For now, just show a message (no status bar in frame layout)
+ }
+
+ void MainWindow::PerformanceBenchmark_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ // Could implement Performance Benchmark functionality
+ // For now, just show a message (no status bar in frame layout)
+ }
+
+ void MainWindow::Settings_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ // Could implement Settings functionality
+ // For now, just show a message (no status bar in frame layout)
+ }
+
+ void MainWindow::About_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ // Could implement About dialog
+ // For now, just show a message (no status bar in frame layout)
+ }
+}
\ No newline at end of file
diff --git a/vav2/Vav2Player/Vav2Player/MultiVideoTestPage.idl b/vav2/Vav2Player/Vav2Player/MultiVideoTestPage.idl
new file mode 100644
index 0000000..3db4463
--- /dev/null
+++ b/vav2/Vav2Player/Vav2Player/MultiVideoTestPage.idl
@@ -0,0 +1,8 @@
+namespace Vav2Player
+{
+ [default_interface]
+ runtimeclass MultiVideoTestPage : Microsoft.UI.Xaml.Controls.Page
+ {
+ MultiVideoTestPage();
+ }
+}
\ No newline at end of file
diff --git a/vav2/Vav2Player/Vav2Player/MultiVideoTestPage.xaml b/vav2/Vav2Player/Vav2Player/MultiVideoTestPage.xaml
new file mode 100644
index 0000000..1983544
--- /dev/null
+++ b/vav2/Vav2Player/Vav2Player/MultiVideoTestPage.xaml
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vav2/Vav2Player/Vav2Player/MultiVideoTestPage.xaml.cpp b/vav2/Vav2Player/Vav2Player/MultiVideoTestPage.xaml.cpp
new file mode 100644
index 0000000..fb411c0
--- /dev/null
+++ b/vav2/Vav2Player/Vav2Player/MultiVideoTestPage.xaml.cpp
@@ -0,0 +1,245 @@
+#include "pch.h"
+#include "MultiVideoTestPage.xaml.h"
+#if __has_include("MultiVideoTestPage.g.cpp")
+#include "MultiVideoTestPage.g.cpp"
+#endif
+
+using namespace winrt;
+using namespace winrt::Microsoft::UI::Xaml;
+using namespace winrt::Microsoft::UI::Xaml::Controls;
+
+namespace winrt::Vav2Player::implementation
+{
+ MultiVideoTestPage::MultiVideoTestPage()
+ {
+ InitializeComponent();
+ UpdateStatus(L"Multi Video Test - Ready");
+ }
+
+ winrt::Windows::Foundation::IAsyncAction MultiVideoTestPage::LoadVideoButton_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ try
+ {
+ // Create file picker
+ winrt::Windows::Storage::Pickers::FileOpenPicker picker;
+ picker.ViewMode(winrt::Windows::Storage::Pickers::PickerViewMode::Thumbnail);
+ picker.SuggestedStartLocation(winrt::Windows::Storage::Pickers::PickerLocationId::VideosLibrary);
+
+ // Add supported video file types
+ picker.FileTypeFilter().Append(L".webm");
+ picker.FileTypeFilter().Append(L".mkv");
+ picker.FileTypeFilter().Append(L".mp4");
+ picker.FileTypeFilter().Append(L".avi");
+
+ // Initialize picker with window handle - use simple approach for Page
+ try {
+ auto initializeWithWindow = picker.as();
+
+ // Get the active window handle
+ HWND hWnd = GetActiveWindow();
+ if (hWnd == nullptr)
+ {
+ hWnd = GetForegroundWindow();
+ }
+
+ if (hWnd != nullptr)
+ {
+ initializeWithWindow->Initialize(hWnd);
+ }
+ }
+ catch (...)
+ {
+ // If window handle initialization fails, continue without it
+ // FileOpenPicker might still work in some cases
+ }
+
+ // Show picker and get selected file
+ auto file = co_await picker.PickSingleFileAsync();
+ if (file != nullptr)
+ {
+ auto filePath = file.Path();
+ m_currentVideoPath = filePath;
+
+ // Load video to all players
+ UpdateStatus(L"Loading video to all players...");
+ for (auto& player : m_videoPlayers)
+ {
+ player.LoadVideo(filePath);
+ }
+ UpdateStatus(winrt::hstring(L"Video loaded to " + std::to_wstring(m_videoPlayers.size()) + L" players: " + filePath.c_str()));
+ }
+ else
+ {
+ UpdateStatus(L"No file selected");
+ }
+ }
+ catch (...)
+ {
+ UpdateStatus(L"Error opening file picker");
+ }
+ }
+
+ void MultiVideoTestPage::PlayAllButton_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ for (auto& player : m_videoPlayers)
+ {
+ if (player.IsVideoLoaded())
+ {
+ player.Play();
+ }
+ }
+ UpdateStatus(L"Playing all videos");
+ }
+
+ void MultiVideoTestPage::PauseAllButton_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ for (auto& player : m_videoPlayers)
+ {
+ if (player.IsVideoPlaying())
+ {
+ player.Pause();
+ }
+ }
+ UpdateStatus(L"Paused all videos");
+ }
+
+ void MultiVideoTestPage::StopAllButton_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ for (auto& player : m_videoPlayers)
+ {
+ if (player.IsVideoLoaded())
+ {
+ player.Stop();
+ }
+ }
+ UpdateStatus(L"Stopped all videos");
+ }
+
+ void MultiVideoTestPage::LayoutComboBox_SelectionChanged(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const& e)
+ {
+ // Skip if UI not ready yet
+ try {
+ if (!VideoGrid() || e.AddedItems().Size() == 0) {
+ return;
+ }
+
+ if (auto comboBox = e.AddedItems().GetAt(0).try_as())
+ {
+ auto content = comboBox.Content().as();
+ if (content == L"Single Video")
+ {
+ CreateVideoGrid(LayoutType::Single);
+ }
+ else if (content == L"2x2 Grid")
+ {
+ CreateVideoGrid(LayoutType::Grid2x2);
+ }
+ else if (content == L"1x4 Strip")
+ {
+ CreateVideoGrid(LayoutType::Strip1x4);
+ }
+ else if (content == L"3x3 Grid")
+ {
+ CreateVideoGrid(LayoutType::Grid3x3);
+ }
+ }
+ }
+ catch (...) {
+ // Ignore errors during initialization
+ }
+ }
+
+ void MultiVideoTestPage::UseHardwareRenderingCheckBox_Checked(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ UpdateStatus(L"Hardware rendering enabled");
+ }
+
+ void MultiVideoTestPage::UseHardwareRenderingCheckBox_Unchecked(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
+ {
+ UpdateStatus(L"Hardware rendering disabled");
+ }
+
+ // Helper methods - simplified implementations
+ void MultiVideoTestPage::CreateVideoGrid(LayoutType layout)
+ {
+ try {
+ if (!VideoGrid()) {
+ return;
+ }
+
+ ClearVideoGrid();
+ m_currentLayout = layout;
+
+ int rows = 1, cols = 1;
+ switch (layout)
+ {
+ case LayoutType::Single: rows = 1; cols = 1; break;
+ case LayoutType::Grid2x2: rows = 2; cols = 2; break;
+ case LayoutType::Strip1x4: rows = 1; cols = 4; break;
+ case LayoutType::Grid3x3: rows = 3; cols = 3; break;
+ }
+
+ VideoGrid().RowDefinitions().Clear();
+ VideoGrid().ColumnDefinitions().Clear();
+
+ for (int r = 0; r < rows; ++r)
+ {
+ auto rowDef = RowDefinition();
+ rowDef.Height(GridLengthHelper::FromValueAndType(1, GridUnitType::Star));
+ VideoGrid().RowDefinitions().Append(rowDef);
+ }
+
+ for (int c = 0; c < cols; ++c)
+ {
+ auto colDef = ColumnDefinition();
+ colDef.Width(GridLengthHelper::FromValueAndType(1, GridUnitType::Star));
+ VideoGrid().ColumnDefinitions().Append(colDef);
+ }
+
+ UpdateStatus(L"Created video grid");
+ }
+ catch (...) {
+ // Ignore errors during grid creation
+ UpdateStatus(L"Error creating video grid");
+ }
+ }
+
+ void MultiVideoTestPage::ClearVideoGrid()
+ {
+ try {
+ if (VideoGrid()) {
+ VideoGrid().Children().Clear();
+ }
+ m_videoPlayers.clear();
+ }
+ catch (...) {
+ // Ignore errors during clearing
+ }
+ }
+
+ winrt::Windows::Foundation::IAsyncAction MultiVideoTestPage::LoadVideoToAllPlayers(winrt::hstring const& videoPath)
+ {
+ co_await resume_background();
+ // Implementation would load video to all players
+ co_return;
+ }
+
+ winrt::Windows::Foundation::IAsyncAction MultiVideoTestPage::PickVideoFile()
+ {
+ co_await resume_background();
+ // Implementation would show file picker
+ co_return;
+ }
+
+ void MultiVideoTestPage::UpdateStatus(winrt::hstring const& message)
+ {
+ try {
+ if (StatusDisplay()) {
+ StatusDisplay().Text(message);
+ }
+ } catch (...) {
+ // Ignore if UI not ready yet
+ }
+ OutputDebugStringA((winrt::to_string(message) + "\n").c_str());
+ }
+}
\ No newline at end of file
diff --git a/vav2/Vav2Player/Vav2Player/MultiVideoTestPage.xaml.h b/vav2/Vav2Player/Vav2Player/MultiVideoTestPage.xaml.h
new file mode 100644
index 0000000..c379cbb
--- /dev/null
+++ b/vav2/Vav2Player/Vav2Player/MultiVideoTestPage.xaml.h
@@ -0,0 +1,51 @@
+#pragma once
+
+#include "MultiVideoTestPage.g.h"
+#include "VideoPlayerControl.xaml.h"
+#include
+#include
+
+namespace winrt::Vav2Player::implementation
+{
+ struct MultiVideoTestPage : MultiVideoTestPageT
+ {
+ MultiVideoTestPage();
+
+ // Event handlers
+ winrt::Windows::Foundation::IAsyncAction LoadVideoButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void PlayAllButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void PauseAllButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void StopAllButton_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void LayoutComboBox_SelectionChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const& e);
+ void UseHardwareRenderingCheckBox_Checked(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+ void UseHardwareRenderingCheckBox_Unchecked(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
+
+ private:
+ std::vector m_videoPlayers;
+ winrt::hstring m_currentVideoPath;
+
+ enum class LayoutType
+ {
+ Single, // 1x1
+ Grid2x2, // 2x2
+ Strip1x4, // 1x4
+ Grid3x3 // 3x3
+ };
+
+ LayoutType m_currentLayout = LayoutType::Single;
+
+ // Helper methods
+ void CreateVideoGrid(LayoutType layout);
+ void ClearVideoGrid();
+ winrt::Windows::Foundation::IAsyncAction LoadVideoToAllPlayers(winrt::hstring const& videoPath);
+ winrt::Windows::Foundation::IAsyncAction PickVideoFile();
+ void UpdateStatus(winrt::hstring const& message);
+ };
+}
+
+namespace winrt::Vav2Player::factory_implementation
+{
+ struct MultiVideoTestPage : MultiVideoTestPageT
+ {
+ };
+}
\ No newline at end of file
diff --git a/vav2/Vav2Player/Vav2Player/MultiVideoTestWindow.xaml b/vav2/Vav2Player/Vav2Player/MultiVideoTestWindow.xaml
index 5266a27..9bf16bb 100644
--- a/vav2/Vav2Player/Vav2Player/MultiVideoTestWindow.xaml
+++ b/vav2/Vav2Player/Vav2Player/MultiVideoTestWindow.xaml
@@ -11,12 +11,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+