Files
video-v1/vav2/docs/completed/android/Android_Vulkan_AV1_Player_Design.md

450 lines
16 KiB
Markdown
Raw Normal View History

# Android Vulkan AV1 Player 설계 문서
**프로젝트**: VavCore Android Vulkan Surface AV1 Player
**날짜**: 2025-09-29
**상태**: 🚧 설계 단계
**플랫폼**: Android (API Level 29+, Vulkan 1.0+)
---
## 🎯 **프로젝트 개요**
Android에서 Vulkan Surface를 사용하여 직접 렌더링하는 고성능 AV1 비디오 플레이어를 구현합니다. VavCore JNI 라이브러리와 Android MediaCodec 하드웨어 가속을 활용하여 최적의 성능을 달성합니다.
### **핵심 목표**
- **Vulkan Direct Rendering**: CPU 메모리 복사 없이 GPU Surface 직접 렌더링
- **하드웨어 가속**: MediaCodec + Vulkan 파이프라인으로 최대 성능 달성
- **실시간 성능**: 4K AV1 비디오 60fps 재생 목표
- **사용자 경험**: 직관적인 비디오 컨트롤 UI
---
## 🏗️ **전체 아키텍처**
### **시스템 구성도**
```
┌─────────────────────────────────────────────────────────────┐
│ Android Application Layer │
├─────────────────────────────────────────────────────────────┤
│ Java/Kotlin UI │ VulkanVideoView (Custom View) │
│ - Load Video Button │ - Vulkan Surface │
│ - Play/Pause/Stop │ - YUV → RGB Conversion │
│ - Progress Bar │ - AspectFit Rendering │
│ - Performance Stats │ - Touch Controls │
├─────────────────────────────────────────────────────────────┤
│ JNI Bridge Layer │
│ - VavCore JNI Wrapper │ - Vulkan JNI Native │
│ - Video Control APIs │ - Surface Management │
│ - Performance Metrics │ - Texture Binding │
├─────────────────────────────────────────────────────────────┤
│ Native C++ Layer │
│ VavCore Library │ Vulkan Renderer │
│ - MediaCodec Decoder │ - VkSurface Creation │
│ - dav1d Fallback │ - YUV Shader Pipeline │
│ - Frame Management │ - Command Buffer Management │
├─────────────────────────────────────────────────────────────┤
│ Hardware Layer │
│ Android MediaCodec │ Vulkan GPU Driver │
│ - AV1 HW Decoding │ - GPU YUV Processing │
│ - Surface Output │ - Synchronized Rendering │
└─────────────────────────────────────────────────────────────┘
```
---
## 📱 **Android 앱 구조**
### **프로젝트 디렉토리 구조**
```
vav2/platforms/android/applications/vav2player/
├── app/
│ ├── src/main/
│ │ ├── java/com/vavcore/player/
│ │ │ ├── MainActivity.java # 메인 액티비티
│ │ │ ├── VulkanVideoView.java # 커스텀 Vulkan 뷰
│ │ │ ├── VideoController.java # 비디오 컨트롤 로직
│ │ │ └── PerformanceMonitor.java # 성능 모니터링
│ │ ├── cpp/
│ │ │ ├── vulkan_renderer.cpp # Vulkan 렌더링 엔진
│ │ │ ├── vulkan_jni.cpp # Vulkan JNI 바인딩
│ │ │ ├── yuv_shader.cpp # YUV → RGB 쉐이더
│ │ │ └── surface_manager.cpp # Surface 관리
│ │ ├── res/
│ │ │ ├── layout/
│ │ │ │ ├── activity_main.xml # 메인 UI 레이아웃
│ │ │ │ └── video_controls.xml # 비디오 컨트롤 UI
│ │ │ ├── values/
│ │ │ │ ├── strings.xml # 문자열 리소스
│ │ │ │ └── colors.xml # 색상 테마
│ │ │ └── drawable/ # 아이콘 리소스
│ │ └── AndroidManifest.xml # 앱 매니페스트
│ ├── build.gradle # 앱 빌드 설정
│ └── CMakeLists.txt # 네이티브 빌드 설정
├── vavcore/ # VavCore JNI 모듈 (기존)
└── build.gradle # 프로젝트 빌드 설정
```
---
## 🎮 **UI 설계**
### **메인 화면 레이아웃**
```
┌─────────────────────────────────────────────────────────────┐
│ App Title Bar │
├─────────────────────────────────────────────────────────────┤
│ │
│ │
│ VulkanVideoView │
│ (Vulkan Surface) │
│ │
│ │
├─────────────────────────────────────────────────────────────┤
│ [Load Video] [Play] [Pause] [Stop] Progress: 45% │
├─────────────────────────────────────────────────────────────┤
│ Decoder: MediaCodec | FPS: 60 | Resolution: 3840x2160 │
│ Frame Time: 12ms | GPU Memory: 245MB | Dropped: 0 │
└─────────────────────────────────────────────────────────────┘
```
### **UI 컴포넌트 사양**
#### **VulkanVideoView (커스텀 뷰)**
- **기능**: Vulkan Surface 렌더링 및 비디오 표시
- **특징**:
- Touch 이벤트 처리 (탭해서 Play/Pause)
- AspectFit 자동 조정
- 성능 오버레이 표시 옵션
- **크기**: Match parent (전체 화면 비율 유지)
#### **비디오 컨트롤 버튼**
- **Load Video**: 파일 선택 다이얼로그 → AV1 파일 로드
- **Play**: 비디오 재생 시작
- **Pause**: 재생 일시정지 (Resume 가능)
- **Stop**: 재생 중지 및 처음으로 되돌리기
#### **진행률 표시**
- **Progress Bar**: 현재 재생 위치 (SeekBar로 탐색 가능)
- **시간 표시**: "02:34 / 05:42" 형식
#### **성능 모니터링 패널**
- **디코더 정보**: 현재 사용 중인 디코더 (MediaCodec/dav1d)
- **실시간 FPS**: 현재 렌더링 프레임레이트
- **해상도**: 비디오 원본 해상도
- **프레임 타임**: 디코딩 + 렌더링 시간
- **GPU 메모리**: 현재 GPU 메모리 사용량
- **드롭된 프레임**: 성능 부족으로 건너뛴 프레임 수
---
## 🔧 **Vulkan 렌더링 엔진**
### **Vulkan 파이프라인 설계**
#### **1. Vulkan 초기화 시퀀스**
```cpp
// 1. Vulkan Instance 생성
VkInstance instance;
VkApplicationInfo appInfo = {};
appInfo.pApplicationName = "VavCore AV1 Player";
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.pEngineName = "VavCore Vulkan Engine";
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.apiVersion = VK_API_VERSION_1_0;
// 2. Android Surface 생성
VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo = {};
surfaceCreateInfo.window = androidWindow; // ANativeWindow*
// 3. Physical Device 및 Queue Family 선택
VkPhysicalDevice physicalDevice;
uint32_t graphicsQueueFamilyIndex;
uint32_t presentQueueFamilyIndex;
// 4. Logical Device 생성
VkDevice device;
VkQueue graphicsQueue;
VkQueue presentQueue;
// 5. Swapchain 설정
VkSwapchainKHR swapchain;
VkFormat swapchainImageFormat = VK_FORMAT_R8G8B8A8_UNORM;
VkExtent2D swapchainExtent;
```
#### **2. YUV → RGB 변환 쉐이더**
**Vertex Shader (yuv_vertex.vert)**:
```glsl
#version 450
layout(location = 0) in vec2 inPosition;
layout(location = 1) in vec2 inTexCoord;
layout(location = 0) out vec2 fragTexCoord;
layout(push_constant) uniform PushConstants {
mat4 transform;
} pc;
void main() {
gl_Position = pc.transform * vec4(inPosition, 0.0, 1.0);
fragTexCoord = inTexCoord;
}
```
**Fragment Shader (yuv_fragment.frag)**:
```glsl
#version 450
layout(location = 0) in vec2 fragTexCoord;
layout(location = 0) out vec4 outColor;
layout(binding = 0) uniform sampler2D yTexture;
layout(binding = 1) uniform sampler2D uTexture;
layout(binding = 2) uniform sampler2D vTexture;
// BT.709 YUV to RGB conversion matrix
const mat3 yuvToRgb = mat3(
1.0000, 1.0000, 1.0000,
0.0000, -0.1873, 1.8556,
1.5748, -0.4681, 0.0000
);
void main() {
float y = texture(yTexture, fragTexCoord).r;
float u = texture(uTexture, fragTexCoord).r - 0.5;
float v = texture(vTexture, fragTexCoord).r - 0.5;
vec3 yuv = vec3(y, u, v);
vec3 rgb = yuvToRgb * yuv;
outColor = vec4(rgb, 1.0);
}
```
#### **3. 렌더링 파이프라인**
```cpp
class VulkanVideoRenderer {
public:
struct VideoFrame {
VkImage yImage, uImage, vImage;
VkDeviceMemory yMemory, uMemory, vMemory;
VkImageView yImageView, uImageView, vImageView;
uint32_t width, height;
};
// 프레임 렌더링 메인 함수
void RenderFrame(const VideoFrame& frame) {
// 1. Command Buffer 시작
BeginCommandBuffer();
// 2. Render Pass 시작
BeginRenderPass();
// 3. YUV 텍스처 바인딩
BindYUVTextures(frame);
// 4. 변환 행렬 업데이트 (AspectFit)
UpdateTransformMatrix(frame.width, frame.height);
// 5. 그리기 명령
DrawFullscreenQuad();
// 6. Render Pass 종료
EndRenderPass();
// 7. Command Buffer 제출
SubmitCommandBuffer();
// 8. Present
PresentFrame();
}
private:
void UpdateTransformMatrix(uint32_t videoWidth, uint32_t videoHeight);
void BindYUVTextures(const VideoFrame& frame);
void DrawFullscreenQuad();
};
```
---
## 🔗 **JNI 통합 레이어**
### **VavCore JNI 확장**
#### **vulkan_jni.cpp**
```cpp
// Vulkan Surface 생성 및 관리
extern "C" JNIEXPORT jlong JNICALL
Java_com_vavcore_player_VulkanVideoView_nativeCreateVulkanRenderer(
JNIEnv* env, jobject thiz, jobject surface) {
ANativeWindow* window = ANativeWindow_fromSurface(env, surface);
VulkanVideoRenderer* renderer = new VulkanVideoRenderer();
if (renderer->Initialize(window)) {
return reinterpret_cast<jlong>(renderer);
}
delete renderer;
return 0;
}
// 프레임 렌더링 (VavCore에서 디코딩된 프레임 받아서 Vulkan 렌더링)
extern "C" JNIEXPORT void JNICALL
Java_com_vavcore_player_VulkanVideoView_nativeRenderFrame(
JNIEnv* env, jobject thiz, jlong rendererPtr, jlong framePtr) {
VulkanVideoRenderer* renderer = reinterpret_cast<VulkanVideoRenderer*>(rendererPtr);
VavCoreVideoFrame* frame = reinterpret_cast<VavCoreVideoFrame*>(framePtr);
// VavCore 프레임을 Vulkan 텍스처로 변환
VulkanVideoRenderer::VideoFrame vulkanFrame;
ConvertVavCoreFrameToVulkan(frame, vulkanFrame);
// Vulkan 렌더링
renderer->RenderFrame(vulkanFrame);
}
// 성능 메트릭 수집
extern "C" JNIEXPORT jobject JNICALL
Java_com_vavcore_player_VulkanVideoView_nativeGetPerformanceMetrics(
JNIEnv* env, jobject thiz, jlong rendererPtr) {
VulkanVideoRenderer* renderer = reinterpret_cast<VulkanVideoRenderer*>(rendererPtr);
auto metrics = renderer->GetPerformanceMetrics();
// Java PerformanceMetrics 객체 생성 및 반환
return CreateJavaPerformanceMetrics(env, metrics);
}
```
---
## 📊 **성능 최적화 전략**
### **1. Zero-Copy 파이프라인**
```
MediaCodec → Surface → Vulkan Texture → GPU Rendering
↑ ↑ ↑ ↑
HW Decode Direct Bind GPU Memory Zero Copy
```
### **2. 메모리 최적화**
- **Texture Pooling**: 프레임 텍스처 재사용
- **Staging Buffer**: GPU 메모리 전송 최적화
- **Memory Mapping**: Persistent 메모리 매핑 사용
### **3. 렌더링 최적화**
- **Double Buffering**: Swapchain 이미지 2개 사용
- **Async Rendering**: 디코딩과 렌더링 파이프라인 분리
- **GPU Synchronization**: VkSemaphore로 동기화
### **4. Android 특화 최적화**
- **ANativeWindow 직접 사용**: Java Surface 오버헤드 제거
- **Vulkan 1.0 호환성**: 최대 디바이스 지원
- **Battery Optimization**: 불필요한 GPU 연산 최소화
---
## 🛠️ **개발 단계별 계획**
### **Phase 1: Vulkan 기반 구조 구축** (1-2일)
- [x] 설계 문서 작성
- [ ] Android 프로젝트 구조 생성
- [ ] Vulkan 초기화 및 Surface 생성
- [ ] 기본 렌더링 파이프라인 구현
### **Phase 2: YUV 렌더링 시스템** (2-3일)
- [ ] YUV → RGB 쉐이더 구현
- [ ] VavCore JNI 연동
- [ ] 텍스처 관리 시스템
- [ ] AspectFit 렌더링 로직
### **Phase 3: UI 및 컨트롤** (1-2일)
- [ ] Java/Kotlin UI 구현
- [ ] 비디오 컨트롤 버튼 기능
- [ ] 파일 로더 및 진행률 표시
- [ ] 터치 인터랙션
### **Phase 4: 성능 최적화** (1-2일)
- [ ] 성능 모니터링 시스템
- [ ] 메모리 및 GPU 최적화
- [ ] MediaCodec 벤치마킹
- [ ] 배터리 사용량 최적화
### **Phase 5: 테스트 및 검증** (1일)
- [ ] 다양한 AV1 파일 테스트
- [ ] 성능 벤치마크 수행
- [ ] 메모리 누수 검사
- [ ] 사용자 테스트
---
## 📋 **기술 요구사항**
### **Android 요구사항**
- **API Level**: 29+ (Android 10+)
- **Vulkan 지원**: Vulkan 1.0 이상
- **NDK 버전**: r25+
- **Build Tools**: CMake 3.22+, Gradle 8.0+
### **하드웨어 요구사항**
- **GPU**: Vulkan 지원 GPU (Adreno 640+, Mali-G76+)
- **메모리**: 4GB+ RAM 권장
- **저장공간**: 100MB+ 앱 크기
### **성능 목표**
- **4K AV1**: 30fps 안정적 재생
- **1080p AV1**: 60fps 재생
- **메모리 사용량**: 500MB 이하
- **배터리**: 1시간 재생 시 20% 이하 소모
---
## 🔍 **리스크 및 대응방안**
### **기술적 리스크**
1. **Vulkan 호환성**: 일부 구형 디바이스 미지원
- **대응**: OpenGL ES 3.0 fallback 구현
2. **MediaCodec 안정성**: 디바이스별 구현 차이
- **대응**: dav1d 소프트웨어 디코더로 fallback
3. **메모리 사용량**: 4K 비디오의 높은 메모리 요구
- **대응**: 동적 해상도 조정 및 메모리 풀링
### **플랫폼 리스크**
1. **Android 버전 호환성**: Vulkan API 변경
- **대응**: Vulkan 1.0 baseline 사용
2. **OEM 커스터마이징**: 제조사별 드라이버 이슈
- **대응**: 광범위한 디바이스 테스트
---
## 📚 **참고 문서 및 리소스**
### **VavCore 관련**
- [Android VavCore Lazy Initialization Success](../completed/milestones/Android_VavCore_Lazy_Initialization_Success_2025-09-29.md)
- [VavCore Android MediaCodec Design](../completed/cross-platform/VavCore_Android_MediaCodec_Design.md)
### **Vulkan 참고자료**
- [Vulkan Tutorial](https://vulkan-tutorial.com/)
- [Android Vulkan API Guide](https://developer.android.com/ndk/guides/graphics/vulkan)
- [Vulkan Memory Allocation Guide](https://gpuopen.com/vulkan-memory-allocator/)
### **Android MediaCodec**
- [MediaCodec API Reference](https://developer.android.com/reference/android/media/MediaCodec)
- [Surface to Surface Copy](https://developer.android.com/ndk/reference/group/media)
---
**문서 작성일**: 2025-09-29
**작성자**: Claude Code
**버전**: 1.0
**상태**: ✅ 설계 완료 → 구현 준비
*이 설계 문서를 기반으로 Android Vulkan AV1 Player 개발을 시작합니다.*