Files
video-v1/vav2/docs/completed/android/Android_Vulkan_AV1_Player_Design.md
2025-09-30 00:34:20 +09:00

16 KiB

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 초기화 시퀀스

// 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):

#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):

#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. 렌더링 파이프라인

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

// 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일)

  • 설계 문서 작성
  • 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 관련

Vulkan 참고자료

Android MediaCodec


문서 작성일: 2025-09-29 작성자: Claude Code 버전: 1.0 상태: 설계 완료 → 구현 준비

이 설계 문서를 기반으로 Android Vulkan AV1 Player 개발을 시작합니다.