Files
video-v1/vav2/VavCore_Android_MediaCodec_Design.md

1635 lines
60 KiB
Markdown
Raw Normal View History

2025-09-27 13:56:56 +09:00
# VavCore Android MediaCodec 크로스 플랫폼 Graphics 통합 설계
## 📋 **문서 정보**
- **작성일**: 2025-09-27
- **버전**: 3.0.0 (완전한 크로스 플랫폼 Graphics API 통합)
- **최신 업데이트**: Enhanced IVideoDecoder 인터페이스 및 VavCoreSurfaceType 시스템
- **대상**: VavCore Android MediaCodec AV1 Decoder + 크로스 플랫폼 Graphics
- **목적**: Android의 다양한 Graphics API와 MediaCodec의 완전한 크로스 플랫폼 통합
## 1. 개요 및 최신 변경사항
본 문서는 VavCore의 완전한 크로스 플랫폼 Graphics API 지원을 포함하여 Android MediaCodec API와의 통합 설계를 제시합니다. **주요 업데이트:**
### **🆕 v3.0 최신 기능 (2025-09-27) - 현실적인 AV1 하드웨어 지원 반영**
-**완전한 크로스 플랫폼 Surface 시스템**: VavCoreSurfaceType 열거형으로 모든 플랫폼 지원
-**Enhanced IVideoDecoder 인터페이스**: 플랫폼별 Graphics API 설정 메서드 확장
- ⚠️ **현실적인 Android AV1 하드웨어 지원**: 2022년 이후 고급 SoC만 실제 지원
-**ANativeWindow 우선 지원**: MediaCodec Surface 디코딩의 가장 안정적인 방식
- ⚠️ **제한적인 고급 Graphics API**: OpenGL ES/Vulkan은 고급 SoC + API 29+에서만
-**정확한 하드웨어 감지**: 실제 AV1 지원 SoC 검증 로직 (Snapdragon 8 Gen 1+, Tensor G2+)
-**Graceful Fallback**: 하드웨어 미지원 시 dav1d 소프트웨어 디코더로 안전한 전환
### **⚠️ 중요: Android AV1 하드웨어 지원 현실**
**실제 AV1 하드웨어 디코딩이 가능한 기기:**
- **Qualcomm**: Snapdragon 8 Gen 1+ (2022년 이후) - Galaxy S22+, OnePlus 10+
- **Google**: Tensor G2+ (Pixel 7+, 2022년 이후)
- **MediaTek**: Dimensity 9200+ (2023년 이후) - 일부 고급 기기만
- **Samsung**: Exynos 2200 (Galaxy S22 일부) - 제한적이고 불안정
**🎮 Godot 게임엔진 관점에서의 Surface 우선순위:**
1. **Vulkan VkImage** - Godot 4 Forward+/Mobile 렌더러와 직접 통합
2. **OpenGL ES 텍스처** - Godot 4 Compatibility 렌더러와 직접 통합
3. **ANativeWindow** - 추가 변환 필요, 게임엔진에 덜 적합
4. **CPU 메모리** - 호환성은 좋지만 성능 저하
**대부분의 Android 기기는 여전히 소프트웨어 디코딩 필요**
## 2. VavCore 크로스 플랫폼 아키텍처 분석
### 2.1 하드웨어 디코더 팩토리 패턴
VavCore는 등록 기반 디코더 팩토리 시스템으로 모든 플랫폼의 하드웨어 가속을 지원합니다:
**VideoDecoderFactory 디코더 우선순위:**
```cpp
// AUTO 모드 우선순위: Platform-specific HW → dav1d SW
enum class VideoCodecType {
AV1, VP9, H264, H265
};
enum class DecoderType {
AUTO, // 플랫폼별 최적 디코더 자동 선택
// Windows Hardware Decoders
NVDEC, // NVIDIA NVDEC (Windows)
VPL, // Intel VPL (Windows)
AMF, // AMD AMF (Windows)
MEDIA_FOUNDATION, // Windows Media Foundation
// Android Hardware Decoders
MEDIACODEC, // Android MediaCodec
// Cross-platform Software
DAV1D // dav1d 소프트웨어 (모든 플랫폼)
};
```
### 2.2 Enhanced IVideoDecoder 크로스 플랫폼 인터페이스
현재 인터페이스는 모든 플랫폼의 Graphics API를 완전히 지원합니다:
```cpp
class IVideoDecoder {
public:
// Core 디코딩 인터페이스
virtual bool Initialize(const VideoMetadata& metadata) = 0;
virtual bool DecodeFrame(const VideoPacket& input_packet, VideoFrame& output_frame) = 0;
virtual bool DecodeFrame(const uint8_t* packet_data, size_t packet_size, VideoFrame& output_frame) = 0;
// 크로스 플랫폼 Surface 디코딩
virtual bool SupportsSurfaceType(VavCoreSurfaceType type) const = 0;
virtual VavCoreSurfaceType GetOptimalSurfaceType() const = 0;
virtual bool DecodeToSurface(const uint8_t* packet_data, size_t packet_size,
VavCoreSurfaceType target_type,
void* target_surface,
VideoFrame& output_frame) = 0;
// 플랫폼별 Graphics API 설정
// Windows
virtual bool SetD3DDevice(void* d3d_device, VavCoreSurfaceType type) = 0;
// Android
virtual bool SetAndroidSurface(void* native_window) = 0;
virtual bool SetOpenGLESContext(void* egl_context) = 0;
virtual bool SetVulkanDevice(void* vk_device, void* vk_instance) = 0;
// Cross-platform
virtual bool SetOpenGLContext(void* gl_context) = 0;
virtual bool SetMetalDevice(void* metal_device) = 0;
// Graphics API 지원 감지
virtual bool SupportsHardwareAcceleration() const = 0;
virtual bool SupportsZeroCopyDecoding() const = 0;
virtual bool RequiresExternalContext() const = 0;
};
```
### 2.3 VavCoreSurfaceType 크로스 플랫폼 시스템
현재 VavCore는 모든 주요 플랫폼의 Graphics API를 완전히 지원합니다:
```cpp
typedef enum {
VAVCORE_SURFACE_CPU = 0, // 전통적인 CPU 메모리
// Windows Graphics APIs
VAVCORE_SURFACE_D3D11_TEXTURE = 1, // D3D11 texture (Windows)
VAVCORE_SURFACE_D3D12_RESOURCE = 2, // D3D12 resource (Windows)
VAVCORE_SURFACE_CUDA_DEVICE = 3, // CUDA device pointer (Windows)
VAVCORE_SURFACE_AMF_SURFACE = 4, // AMF surface wrapper (Windows)
// Android Graphics APIs
VAVCORE_SURFACE_ANDROID_NATIVE_WINDOW = 5, // Android ANativeWindow
VAVCORE_SURFACE_OPENGL_ES_TEXTURE = 6, // OpenGL ES texture (Android/iOS)
VAVCORE_SURFACE_VULKAN_IMAGE = 7, // Vulkan VkImage (Android/Windows)
VAVCORE_SURFACE_ANDROID_HARDWARE_BUFFER = 8, // AHardwareBuffer (Android)
// Cross-platform APIs
VAVCORE_SURFACE_OPENGL_TEXTURE = 9, // Desktop OpenGL texture
VAVCORE_SURFACE_METAL_TEXTURE = 10, // Metal MTLTexture (iOS/macOS)
VAVCORE_SURFACE_COREVIDEO_PIXELBUFFER = 11 // CVPixelBuffer (iOS/macOS)
} VavCoreSurfaceType;
```
### 2.4 하드웨어 디코더 공통 구현 패턴
**모든 플랫폼의 하드웨어 디코더 (NVDEC/AMF/VPL/MediaCodec) 공통 패턴:**
1. **하드웨어 감지**: GPU/SoC 하드웨어 가용성 자동 확인
2. **Graphics API 설정**: 플랫폼별 최적 Graphics API 초기화
3. **Surface 기반 디코딩**: Zero-copy를 위한 하드웨어 Surface 직접 렌더링
4. **Graceful Fallback**: 하드웨어 실패 시 소프트웨어 디코더로 자동 전환
5. **성능 최적화**: GPU-to-GPU 직접 전송으로 메모리 복사 제거
6. **리소스 관리**: 플랫폼별 하드웨어 리소스 적절한 해제
## 3. Android MediaCodec 크로스 플랫폼 통합 설계
### 3.1 플랫폼별 조건부 컴파일 전략
```cpp
// 플랫폼별 헤더 및 Graphics API 정의
#ifdef ANDROID
#include <media/NdkMediaCodec.h>
#include <media/NdkMediaFormat.h>
#include <media/NdkMediaCodecList.h>
#include <android/native_window.h>
#include <android/hardware_buffer.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#include <vulkan/vulkan.h>
#include <android/log.h>
#define VAVCORE_PLATFORM_ANDROID
#elif defined(_WIN32)
#include <d3d11.h>
#include <d3d12.h>
#include <dxgi.h>
#include <mfapi.h>
#include <mftransform.h>
#define VAVCORE_PLATFORM_WINDOWS
#elif defined(__APPLE__)
#include <Metal/Metal.h>
#include <CoreVideo/CoreVideo.h>
#define VAVCORE_PLATFORM_APPLE
#endif
// VavCoreSurfaceType은 이제 enum으로 통합 관리
// 플랫폼별 void* 포인터로 실제 리소스 전달
```
### 3.2 AndroidMediaCodecAV1Decoder Enhanced 구현
#### 3.2.1 Enhanced 클래스 구조 (크로스 플랫폼 호환성)
```cpp
namespace VavCore {
class AndroidMediaCodecAV1Decoder : public IVideoDecoder {
public:
AndroidMediaCodecAV1Decoder();
virtual ~AndroidMediaCodecAV1Decoder();
// IVideoDecoder 기본 인터페이스
bool Initialize(const VideoMetadata& metadata) override;
void Cleanup() override;
bool IsInitialized() const override { return m_initialized; }
// Core 디코딩 기능
bool DecodeFrame(const VideoPacket& input_packet, VideoFrame& output_frame) override;
bool DecodeFrame(const uint8_t* packet_data, size_t packet_size, VideoFrame& output_frame) override;
// 크로스 플랫폼 Surface 디코딩 (Enhanced)
bool SupportsSurfaceType(VavCoreSurfaceType type) const override;
VavCoreSurfaceType GetOptimalSurfaceType() const override;
bool DecodeToSurface(const uint8_t* packet_data, size_t packet_size,
VavCoreSurfaceType target_type,
void* target_surface,
VideoFrame& output_frame) override;
// 플랫폼별 Graphics API 설정 (Android 특화)
bool SetAndroidSurface(void* native_window) override;
bool SetOpenGLESContext(void* egl_context) override;
bool SetVulkanDevice(void* vk_device, void* vk_instance) override;
// 다른 플랫폼 API는 지원하지 않음 (기본 구현)
bool SetD3DDevice(void* d3d_device, VavCoreSurfaceType type) override { return false; }
bool SetOpenGLContext(void* gl_context) override { return false; }
bool SetMetalDevice(void* metal_device) override { return false; }
// Graphics API 지원 감지 (Android 특화)
bool SupportsHardwareAcceleration() const override;
bool SupportsZeroCopyDecoding() const override;
bool RequiresExternalContext() const override;
// 디코더 상태 관리
bool Reset() override;
bool Flush() override;
// 디코더 정보
std::string GetCodecName() const override;
VideoCodecType GetCodecType() const override { return VideoCodecType::AV1; }
std::string GetVersion() const override;
// 성능 및 통계
DecoderStats GetStats() const override;
void ResetStats() override;
// Android 레거시 호환성 (legacy)
bool SetSurface(ANativeWindow* surface); // Legacy method
bool IsHardwareAccelerated() const; // Legacy method
std::string GetSelectedCodecName() const;
private:
// 초기화 및 설정
bool InitializeMediaCodec();
bool FindAV1Decoder();
AMediaCodec* CreateAV1Decoder();
bool ConfigureDecoder(const VideoMetadata& metadata);
// 처리 로직
bool ProcessInputBuffer(const uint8_t* data, size_t size);
bool ProcessOutputBuffer(VideoFrame& frame);
// 하드웨어 가속 감지 (Enhanced)
bool DetectHardwareCapabilities();
std::vector<std::string> GetAvailableCodecs();
// 로깅 (크로스 플랫폼 호환성)
void LogError(const std::string& message);
void LogInfo(const std::string& message);
void LogWarning(const std::string& message);
private:
// Core MediaCodec 객체
bool m_initialized;
AMediaCodec* m_codec;
AMediaFormat* m_format;
ANativeWindow* m_surface;
// 디코더 성능 정보
bool m_hardware_accelerated;
std::string m_selected_codec_name;
// 비디오 속성
int32_t m_width;
int32_t m_height;
// 버퍼 관리
std::vector<uint8_t> m_input_buffer;
int64_t m_timestamp_counter;
// 성능 추적 (Enhanced)
std::chrono::high_resolution_clock::time_point m_decode_start_time;
};
} // namespace VavCore
```
#### 3.2.2 Android SoC별 하드웨어 감지 로직 (Enhanced)
```cpp
bool AndroidMediaCodecAV1Decoder::DetectHardwareCapabilities() {
// ⚠️ 현실적인 Android AV1 하드웨어 디코더 식별 (2025년 기준)
// 대부분의 SoC는 AV1 하드웨어를 광고하지만 실제로는 2022년 이후에만 안정적
const char* hw_codec_prefixes[] = {
// Qualcomm Snapdragon (8 Gen 1+ 시리즈만 실제 AV1 지원)
"c2.qti.av1.decoder", // Qualcomm Codec 2.0 AV1 전용
"c2.qcom.av1.decoder", // Qualcomm 최신 AV1 전용
"OMX.qcom.video.decoder.av1", // Qualcomm OMX AV1 (레거시)
// Google Tensor (G2+ 시리즈만 - Pixel 7+)
"c2.android.av1.decoder", // Android Codec 2.0 AV1 (Google 하드웨어)
"c2.google.av1.decoder", // Google Tensor 특화 AV1
// MediaTek Dimensity (9200+ 시리즈만 - 늦은 지원)
"c2.mtk.av1.decoder", // MediaTek Codec 2.0 AV1
"OMX.MTK.VIDEO.DECODER.AV1", // MediaTek OMX AV1
// Samsung Exynos (매우 제한적 - 2200 일부만)
"c2.exynos.av1.decoder", // Samsung Exynos AV1 (제한적)
// ⚠️ 주의: 범용 프리픽스는 제외
// "OMX.qcom.", "c2.qti.", "c2.android." 등은 H.264/H.265도 포함하므로
// AV1 전용 디코더명만 검색하여 정확성 확보
nullptr
};
auto available_codecs = GetAvailableCodecs();
// 하드웨어 디코더 우선순위 검색
for (const auto& codec : available_codecs) {
for (int i = 0; hw_codec_prefixes[i] != nullptr; i++) {
if (codec.find(hw_codec_prefixes[i]) == 0) {
m_selected_codec_name = codec;
m_hardware_accelerated = true;
LogInfo("Hardware AV1 decoder detected: " + codec);
return true;
}
}
}
// 소프트웨어 디코더로 graceful fallback
LogWarning("No hardware AV1 decoder found, will fallback to software decoder");
m_hardware_accelerated = false;
return false;
}
// Godot 게임엔진 최적화를 위한 Surface 타입 결정
VavCoreSurfaceType AndroidMediaCodecAV1Decoder::GetOptimalSurfaceType() const {
if (!m_hardware_accelerated) {
return VAVCORE_SURFACE_CPU; // 소프트웨어 디코더는 CPU만 지원
}
// Android API Level 및 SoC별 AV1 하드웨어 지원 확인
int api_level = GetAndroidAPILevel();
std::string soc_name = GetSoCName();
// ⚠️ 중요: AV1 하드웨어 디코딩이 실제로 가능한 SoC인지 확인
if (!IsAV1HardwareCapableSoC(soc_name, api_level)) {
LogWarning("SoC does not support AV1 hardware decoding, falling back to CPU");
return VAVCORE_SURFACE_CPU;
}
// 🎮 Godot 게임엔진 관점: 직접적인 Graphics API 통합이 최우선
// Godot 4는 Vulkan/OpenGL ES 기반 렌더링 시스템 사용
// 1. Vulkan 최우선 (Godot 4의 기본 렌더링 백엔드)
// - Godot 4 Forward+ 및 Mobile 렌더링 메서드
// - Google과 협력하여 Android Vulkan 최적화 완료
if (api_level >= 29 && IsHighEndSoC(soc_name)) { // Android 10+ 고급 SoC
if (SupportsVulkan11()) {
LogInfo("Using Vulkan image for Godot 4 optimal integration");
return VAVCORE_SURFACE_VULKAN_IMAGE;
}
}
// 2. OpenGL ES 텍스처 (Godot 4 Compatibility 렌더러)
// - Godot 4 Compatibility 렌더링 메서드 (OpenGL ES 3.0)
// - SurfaceTexture → GL_TEXTURE_EXTERNAL_OES → Godot 텍스처
// - 더 넓은 기기 호환성
if (api_level >= 21) { // Android 5.0+ (OpenGL ES 3.0)
if (SupportsOpenGLES()) {
LogInfo("Using OpenGL ES texture for Godot 4 Compatibility renderer");
return VAVCORE_SURFACE_OPENGL_ES_TEXTURE;
}
}
// 3. ANativeWindow (제한적 사용 - 게임엔진에 덜 적합)
// - MediaCodec Surface → ANativeWindow → Godot는 복잡한 통합 필요
// - Godot의 텍스처 시스템과 직접 연결되지 않음
// - 주로 비디오 플레이어 앱에서 사용하는 방식
if (api_level >= 18) { // MediaCodec Surface 지원 시작점
LogWarning("Using ANativeWindow - suboptimal for Godot integration");
return VAVCORE_SURFACE_ANDROID_NATIVE_WINDOW;
}
// 4. 기본값: CPU (안전한 fallback)
LogWarning("No suitable Surface type found, falling back to CPU decoding");
return VAVCORE_SURFACE_CPU;
}
// Godot 통합을 위한 추가 메서드들
bool AndroidMediaCodecAV1Decoder::IsOptimalForGodot() const {
VavCoreSurfaceType optimal = GetOptimalSurfaceType();
// Godot에 최적인 Surface 타입들
return (optimal == VAVCORE_SURFACE_VULKAN_IMAGE ||
optimal == VAVCORE_SURFACE_OPENGL_ES_TEXTURE);
}
std::string AndroidMediaCodecAV1Decoder::GetGodotIntegrationInfo() const {
VavCoreSurfaceType surface_type = GetOptimalSurfaceType();
switch (surface_type) {
case VAVCORE_SURFACE_VULKAN_IMAGE:
return "Vulkan VkImage - Direct integration with Godot 4 Forward+/Mobile renderer";
case VAVCORE_SURFACE_OPENGL_ES_TEXTURE:
return "OpenGL ES GL_TEXTURE_EXTERNAL_OES - Direct integration with Godot 4 Compatibility renderer";
case VAVCORE_SURFACE_ANDROID_NATIVE_WINDOW:
return "ANativeWindow - Requires additional conversion for Godot texture system";
case VAVCORE_SURFACE_CPU:
return "CPU memory - Software decoding, universally compatible but slower";
default:
return "Unknown surface type";
}
}
// 실제 AV1 하드웨어 지원 SoC 검증 (현실적인 출시 시점 고려)
bool AndroidMediaCodecAV1Decoder::IsAV1HardwareCapableSoC(const std::string& soc_name, int api_level) const {
// ⚠️ 현실: 대부분의 Android SoC는 2022년 이후에야 실제 AV1 하드웨어 지원
// Qualcomm Snapdragon (8 Gen 1+ 시리즈만 확실한 지원)
if (soc_name.find("sm8450") != std::string::npos || // 8 Gen 1 (2022)
soc_name.find("sm8475") != std::string::npos || // 8+ Gen 1 (2022)
soc_name.find("sm8550") != std::string::npos || // 8 Gen 2 (2023)
soc_name.find("sm8650") != std::string::npos) { // 8 Gen 3 (2024)
return api_level >= 31; // Android 12+ 필요
}
// Google Tensor (G2+ 시리즈만 - Pixel 7+)
if (soc_name.find("gs201") != std::string::npos || // Tensor G2 (Pixel 7, 2022)
soc_name.find("gs301") != std::string::npos) { // Tensor G3 (Pixel 8, 2023)
return api_level >= 31; // Android 12+ 필요
}
// MediaTek Dimensity (9200+ 시리즈만 - 늦은 지원)
if (soc_name.find("mt6985") != std::string::npos || // Dimensity 9200 (2023)
soc_name.find("mt6989") != std::string::npos) { // Dimensity 9300 (2024)
return api_level >= 33; // Android 13+ 필요 (MediaTek 늦은 지원)
}
// Samsung Exynos (매우 제한적 지원 - 2200 일부만)
if (soc_name.find("s5e9925") != std::string::npos) { // Exynos 2200 (Galaxy S22)
// Exynos 2200은 AV1 하드웨어가 있지만 성능 이슈로 제한적 활용
LogWarning("Exynos 2200 AV1 hardware support is limited and unstable");
return api_level >= 32; // Android 12L+ 필요
}
// 기타 모든 SoC는 AV1 하드웨어 디코딩 미지원으로 간주
LogWarning("SoC " + soc_name + " not in confirmed AV1 hardware support list");
return false;
}
bool AndroidMediaCodecAV1Decoder::IsHighEndSoC(const std::string& soc_name) const {
// Snapdragon 8 series
if (soc_name.find("sm84") != std::string::npos || soc_name.find("sm86") != std::string::npos) {
return true;
}
// Google Tensor
if (soc_name.find("gs") != std::string::npos) {
return true;
}
// MediaTek Dimensity 9xxx series
if (soc_name.find("mt698") != std::string::npos) {
return true;
}
return false;
}
```
#### 3.2.3 크로스 플랫폼 Surface 기반 디코딩 (Enhanced)
```cpp
bool AndroidMediaCodecAV1Decoder::DecodeToSurface(const uint8_t* packet_data, size_t packet_size,
VavCoreSurfaceType target_type,
void* target_surface,
VideoFrame& output_frame) {
if (!m_initialized || !m_hardware_accelerated) {
LogError("AndroidMediaCodec decoder not initialized or hardware not available");
return false;
}
// Android에서 지원하는 Surface 타입 검증
if (!SupportsSurfaceType(target_type)) {
LogError("Unsupported surface type for Android MediaCodec: " + std::to_string(target_type));
return false;
}
// Surface 타입별 처리
switch (target_type) {
case VAVCORE_SURFACE_ANDROID_NATIVE_WINDOW: {
auto* native_window = static_cast<ANativeWindow*>(target_surface);
if (!SetAndroidSurface(native_window)) {
LogError("Failed to set Android native window");
return false;
}
break;
}
case VAVCORE_SURFACE_OPENGL_ES_TEXTURE: {
// OpenGL ES 텍스처로 직접 렌더링
// EGL 컨텍스트와 텍스처 ID가 필요
if (!m_opengl_es_context) {
LogError("OpenGL ES context not set for texture rendering");
return false;
}
break;
}
case VAVCORE_SURFACE_VULKAN_IMAGE: {
// Vulkan 이미지로 직접 렌더링
// VkDevice와 VkImage가 필요
if (!m_vulkan_device) {
LogError("Vulkan device not set for image rendering");
return false;
}
break;
}
case VAVCORE_SURFACE_ANDROID_HARDWARE_BUFFER: {
// AHardwareBuffer로 직접 렌더링
auto* hardware_buffer = static_cast<AHardwareBuffer*>(target_surface);
if (!SetHardwareBuffer(hardware_buffer)) {
LogError("Failed to set Android hardware buffer");
return false;
}
break;
}
default:
LogError("Surface type not supported by Android MediaCodec");
return false;
}
// 입력 버퍼 처리
if (!ProcessInputBuffer(packet_data, packet_size)) {
LogError("Failed to process input buffer");
return false;
}
// Zero-copy: 출력이 하드웨어 Surface로 직접 렌더링됨
// CPU 메모리 복사 없이 GPU-to-GPU 직접 전송
output_frame.surface_type = target_type;
output_frame.surface_data.android_native.native_window = target_surface;
output_frame.timestamp_us = m_timestamp_counter++;
// 성능 통계 업데이트
IncrementFramesDecoded();
UpdateDecodeTime(CalculateDecodeTime());
LogInfo("Frame decoded directly to Android surface (zero-copy)");
return true;
}
// Android AV1 하드웨어 현실을 반영한 Surface 타입 지원 감지
bool AndroidMediaCodecAV1Decoder::SupportsSurfaceType(VavCoreSurfaceType type) const {
int api_level = GetAndroidAPILevel();
std::string soc_name = GetSoCName();
switch (type) {
case VAVCORE_SURFACE_CPU:
return true; // 모든 Android 기기에서 지원 (소프트웨어 dav1d)
case VAVCORE_SURFACE_ANDROID_NATIVE_WINDOW:
// MediaCodec Surface 디코딩: API 18+에서 지원, AV1은 API 29+ 실용적
if (api_level >= 18 && m_hardware_accelerated) {
return IsAV1HardwareCapableSoC(soc_name, api_level);
}
return false;
case VAVCORE_SURFACE_OPENGL_ES_TEXTURE:
// OpenGL ES 텍스처: 복잡한 MediaCodec 통합, 고급 SoC에서만 권장
if (api_level >= 29 && m_hardware_accelerated && IsHighEndSoC(soc_name)) {
return SupportsOpenGLES() && IsAV1HardwareCapableSoC(soc_name, api_level);
}
return false;
case VAVCORE_SURFACE_VULKAN_IMAGE:
// Vulkan: API 24+에서 지원, AV1과 함께는 API 29+ 고급 SoC만
if (api_level >= 29 && m_hardware_accelerated && IsHighEndSoC(soc_name)) {
return SupportsVulkan11() && IsAV1HardwareCapableSoC(soc_name, api_level);
}
return false;
case VAVCORE_SURFACE_ANDROID_HARDWARE_BUFFER:
// AHardwareBuffer: API 26+에서 지원, AV1과 함께는 API 31+ 권장
if (api_level >= 31 && m_hardware_accelerated && IsHighEndSoC(soc_name)) {
return SupportsHardwareBuffer() && IsAV1HardwareCapableSoC(soc_name, api_level);
}
return false;
// Android에서 지원하지 않는 플랫폼별 Surface 타입들
case VAVCORE_SURFACE_D3D11_TEXTURE:
case VAVCORE_SURFACE_D3D12_RESOURCE:
case VAVCORE_SURFACE_CUDA_DEVICE:
case VAVCORE_SURFACE_AMF_SURFACE:
case VAVCORE_SURFACE_OPENGL_TEXTURE: // Desktop OpenGL (Android는 ES만)
case VAVCORE_SURFACE_METAL_TEXTURE:
case VAVCORE_SURFACE_COREVIDEO_PIXELBUFFER:
return false;
default:
return false;
}
}
// Android API 및 Graphics API 지원 검증 메서드들
bool AndroidMediaCodecAV1Decoder::SupportsOpenGLES() const {
// OpenGL ES는 모든 Android 기기에서 지원하지만,
// MediaCodec과의 복잡한 통합은 고급 기기에서만 안정적
return GetAndroidAPILevel() >= 21; // Android 5.0+ (OpenGL ES 3.0)
}
bool AndroidMediaCodecAV1Decoder::SupportsVulkan11() const {
// Vulkan 1.1은 API 29+에서 모든 64비트 기기에서 보장
return GetAndroidAPILevel() >= 29;
}
bool AndroidMediaCodecAV1Decoder::SupportsHardwareBuffer() const {
// AHardwareBuffer는 API 26+에서 지원, 완전한 기능은 API 31+
return GetAndroidAPILevel() >= 31;
}
```
### 3.3 Enhanced VideoDecoderFactory 크로스 플랫폼 통합
#### 3.3.1 크로스 플랫폼 디코더 등록 및 우선순위
```cpp
// VideoDecoderFactory에서 플랫폼별 디코더 자동 등록
void VideoDecoderFactory::RegisterAV1Decoders() {
// Windows 하드웨어 디코더들
#ifdef VAVCORE_PLATFORM_WINDOWS
RegisterDecoder(VideoCodecType::AV1, DecoderType::NVDEC,
[]() -> std::unique_ptr<IVideoDecoder> {
return std::make_unique<NVDECAV1Decoder>();
}, 400); // 최고 우선순위
RegisterDecoder(VideoCodecType::AV1, DecoderType::VPL,
[]() -> std::unique_ptr<IVideoDecoder> {
return std::make_unique<VPLAV1Decoder>();
}, 300);
RegisterDecoder(VideoCodecType::AV1, DecoderType::AMF,
[]() -> std::unique_ptr<IVideoDecoder> {
return std::make_unique<AMFAV1Decoder>();
}, 200);
RegisterDecoder(VideoCodecType::AV1, DecoderType::MEDIA_FOUNDATION,
[]() -> std::unique_ptr<IVideoDecoder> {
return std::make_unique<MediaFoundationAV1Decoder>();
}, 50);
#endif
// Android 하드웨어 디코더
#ifdef VAVCORE_PLATFORM_ANDROID
RegisterDecoder(VideoCodecType::AV1, DecoderType::MEDIACODEC,
[]() -> std::unique_ptr<IVideoDecoder> {
return std::make_unique<AndroidMediaCodecAV1Decoder>();
}, 400); // Android에서 최고 우선순위
#endif
// 크로스 플랫폼 소프트웨어 디코더 (모든 플랫폼에서 fallback)
RegisterDecoder(VideoCodecType::AV1, DecoderType::DAV1D,
[]() -> std::unique_ptr<IVideoDecoder> {
return std::make_unique<AV1Decoder>();
}, 10); // 최하위 우선순위 (안전한 fallback)
}
// Enhanced AUTO 디코더 선택 로직
std::unique_ptr<IVideoDecoder> VideoDecoderFactory::CreateDecoder(VideoCodecType codec_type,
DecoderType type) {
switch (type) {
case DecoderType::AUTO: {
// 플랫폼별 최적 디코더 자동 선택
auto decoders = GetSortedDecoders(codec_type); // 우선순위 순서로 정렬
for (const auto& decoder_factory : decoders) {
auto decoder = decoder_factory.create();
// 하드웨어 가용성 미리 확인
if (decoder->SupportsHardwareAcceleration()) {
if (decoder->Initialize(GetDummyMetadata())) {
decoder->Cleanup(); // 테스트 후 정리
LogInfo("Selected hardware decoder: " + decoder->GetCodecName());
return decoder_factory.create(); // 새 인스턴스 생성
}
}
}
// 모든 하드웨어 디코더 실패 시 소프트웨어 fallback
LogWarning("All hardware decoders failed, using software decoder");
return CreateDecoder(codec_type, DecoderType::DAV1D);
}
case DecoderType::MEDIACODEC:
#ifdef VAVCORE_PLATFORM_ANDROID
return std::make_unique<AndroidMediaCodecAV1Decoder>();
#else
LogError("MediaCodec decoder not available on this platform");
return nullptr;
#endif
case DecoderType::NVDEC:
#ifdef VAVCORE_PLATFORM_WINDOWS
return std::make_unique<NVDECAV1Decoder>();
#else
LogError("NVDEC decoder not available on this platform");
return nullptr;
#endif
case DecoderType::DAV1D:
return std::make_unique<AV1Decoder>(); // 모든 플랫폼에서 사용 가능
default:
LogError("Unknown decoder type requested");
return nullptr;
}
}
```
### 3.4 Enhanced 크로스 플랫폼 빌드 시스템
#### 3.4.1 완전한 CMakeLists.txt 구조 (모든 플랫폼 지원)
```cmake
cmake_minimum_required(VERSION 3.22)
project(VavCore)
# 플랫폼별 소스 파일 및 라이브러리 설정
if(ANDROID)
# Android 플랫폼
set(PLATFORM_SOURCES
src/Decoder/AndroidMediaCodecAV1Decoder.cpp
src/Platform/AndroidSurface.cpp
src/Platform/AndroidGraphicsAPI.cpp
)
set(PLATFORM_LIBRARIES
mediandk # Android MediaCodec NDK
android # Android 네이티브 라이브러리
log # Android 로깅
EGL # OpenGL ES 컨텍스트
GLESv2 # OpenGL ES 2.0
vulkan # Vulkan API (Android 7.0+)
)
set(PLATFORM_INCLUDES
${ANDROID_NDK}/sources/android/native_app_glue
)
add_definitions(-DVAVCORE_PLATFORM_ANDROID)
elseif(WIN32)
# Windows 플랫폼
set(PLATFORM_SOURCES
src/Decoder/NVDECAV1Decoder.cpp
src/Decoder/AMFAV1Decoder.cpp
src/Decoder/VPLAV1Decoder.cpp
src/Decoder/MediaFoundationAV1Decoder.cpp
src/Platform/WindowsD3D.cpp
src/Platform/WindowsCUDA.cpp
)
set(PLATFORM_LIBRARIES
d3d11
d3d12
dxgi
mfplat
mfreadwrite
mftransform
# CUDA 라이브러리들 (옵션)
cuda
cudart
# AMD AMF 라이브러리들 (옵션)
amf
# Intel VPL 라이브러리들 (옵션)
vpl
)
add_definitions(-DVAVCORE_PLATFORM_WINDOWS)
elseif(APPLE)
# macOS/iOS 플랫폼
set(PLATFORM_SOURCES
src/Decoder/VideoToolboxAV1Decoder.cpp # 미래 확장
src/Platform/AppleMetal.cpp
src/Platform/AppleCoreVideo.cpp
)
set(PLATFORM_LIBRARIES
"-framework Metal"
"-framework CoreVideo"
"-framework VideoToolbox"
"-framework Foundation"
)
add_definitions(-DVAVCORE_PLATFORM_APPLE)
else()
# Linux 플랫폼 (기본값)
set(PLATFORM_SOURCES
src/Platform/LinuxOpenGL.cpp
src/Platform/LinuxVulkan.cpp
)
set(PLATFORM_LIBRARIES
GL # OpenGL
vulkan # Vulkan
X11 # X11 윈도우 시스템
)
add_definitions(-DVAVCORE_PLATFORM_LINUX)
endif()
# 크로스 플랫폼 공통 소스
set(COMMON_SOURCES
# Core 디코더 인터페이스
src/Decoder/IVideoDecoder.cpp
src/Decoder/VideoDecoderFactory.cpp
src/Decoder/AV1Decoder.cpp # dav1d 소프트웨어 디코더
# 공통 타입 및 유틸리티
src/Common/VideoTypes.cpp
src/Common/SurfaceTypes.cpp
src/Common/PlatformUtils.cpp
# 파일 I/O (크로스 플랫폼)
src/FileIO/IWebMFileReader.cpp
src/FileIO/WebMFileReader.cpp
# C API 래퍼
src/VavCore.cpp
)
# VavCore 정적 라이브러리 생성
add_library(VavCore STATIC
${COMMON_SOURCES}
${PLATFORM_SOURCES}
)
# 헤더 파일 경로 설정
target_include_directories(VavCore
PUBLIC
include/ # Public API 헤더
PRIVATE
src/ # 내부 구현 헤더
${PLATFORM_INCLUDES}
)
# 라이브러리 링크
target_link_libraries(VavCore
${PLATFORM_LIBRARIES}
dav1d # 크로스 플랫폼 소프트웨어 디코더
webm # libwebm 파서 라이브러리
)
# 컴파일러 플래그 설정
target_compile_features(VavCore PRIVATE cxx_std_17)
target_compile_definitions(VavCore PRIVATE
VAVCORE_VERSION_MAJOR=3
VAVCORE_VERSION_MINOR=0
VAVCORE_VERSION_PATCH=0
)
# 플랫폼별 추가 설정
if(ANDROID)
# Android NDK 설정
target_compile_options(VavCore PRIVATE
-fPIC
-Wall
-Wextra
-O2
)
elseif(WIN32)
# Windows MSVC 설정
target_compile_options(VavCore PRIVATE
/W4
/O2
/DWIN32_LEAN_AND_MEAN
)
endif()
```
#### 3.4.2 Enhanced Android Gradle 통합 (모든 Graphics API 지원)
```gradle
android {
namespace 'com.vavcore'
compileSdk 34
externalNativeBuild {
cmake {
path "CMakeLists.txt"
version "3.22.1"
}
}
defaultConfig {
minSdk 21 // Android 5.0+ (OpenGL ES 3.0 지원)
targetSdk 34
ndk {
// 현대적인 ARM 아키텍처 지원
abiFilters 'arm64-v8a', 'armeabi-v7a'
}
externalNativeBuild {
cmake {
cppFlags "-std=c++17 -DVAVCORE_PLATFORM_ANDROID -DANDROID_STL=c++_shared"
arguments "-DANDROID_ARM_NEON=TRUE",
"-DANDROID_TOOLCHAIN=clang",
"-DCMAKE_BUILD_TYPE=Release"
}
}
}
buildTypes {
debug {
debuggable true
externalNativeBuild {
cmake {
cppFlags "-DVAVCORE_DEBUG -g"
}
}
}
release {
minifyEnabled false
externalNativeBuild {
cmake {
cppFlags "-DNDEBUG -O3"
}
}
}
}
// Vulkan API 지원 설정 (Android 7.0+)
defaultConfig {
externalNativeBuild {
cmake {
cppFlags "-DVAVCORE_VULKAN_SUPPORT"
arguments "-DVULKAN_ANDROID=1"
}
}
}
}
dependencies {
// Android Graphics API들은 프레임워크 일부이므로 추가 의존성 불필요
// - MediaCodec: Android 프레임워크
// - OpenGL ES: Android 프레임워크
// - Vulkan: Android 7.0+ 프레임워크
// - EGL: Android 프레임워크
// 필요시 추가할 수 있는 외부 라이브러리들
// implementation 'androidx.core:core:1.10.1' // AHardwareBuffer 지원
// implementation 'androidx.opengl:opengl:1.0.0' // OpenGL 유틸리티
}
// NDK 빌드 최적화 설정
android.packagingOptions {
pickFirst '**/libvavcore.so'
pickFirst '**/libdav1d.so'
}
```
## 4. Enhanced 크로스 플랫폼 코드베이스 통합
### 4.1 완전한 역호환성과 플랫폼 투명성
Enhanced 설계는 기존 코드와 100% 역호환성을 유지하면서 모든 플랫폼을 투명하게 지원합니다:
```cpp
// 기존 코드는 전혀 변경 없이 모든 플랫폼에서 동작
auto decoder = VideoDecoderFactory::CreateDecoder(VideoCodecType::AV1, DecoderType::AUTO);
decoder->Initialize(metadata);
decoder->DecodeFrame(packet_data, packet_size, frame);
// 플랫폼별 자동 최적화:
// - Windows: NVDEC → VPL → AMF → dav1d → Media Foundation
// - Android: MediaCodec (하드웨어) → dav1d (소프트웨어)
// - macOS/iOS: VideoToolbox → dav1d (미래 확장)
// - Linux: dav1d
// Enhanced Surface 기반 디코딩 (플랫폼 투명)
if (decoder->SupportsSurfaceType(target_surface_type)) {
decoder->DecodeToSurface(packet_data, packet_size, target_surface_type, surface, frame);
}
```
### 4.2 크로스 플랫폼 로깅 시스템 (Enhanced)
```cpp
namespace VavCore {
class PlatformLogger {
public:
static void LogError(const std::string& message) {
#ifdef VAVCORE_PLATFORM_ANDROID
__android_log_print(ANDROID_LOG_ERROR, "VavCore", "%s", message.c_str());
#elif defined(VAVCORE_PLATFORM_WINDOWS)
OutputDebugStringA(("VavCore Error: " + message + "\n").c_str());
#elif defined(VAVCORE_PLATFORM_APPLE)
NSLog(@"VavCore Error: %s", message.c_str());
#else
std::cerr << "VavCore Error: " << message << std::endl;
#endif
}
static void LogInfo(const std::string& message) {
#ifdef VAVCORE_PLATFORM_ANDROID
__android_log_print(ANDROID_LOG_INFO, "VavCore", "%s", message.c_str());
#elif defined(VAVCORE_PLATFORM_WINDOWS)
OutputDebugStringA(("VavCore Info: " + message + "\n").c_str());
#elif defined(VAVCORE_PLATFORM_APPLE)
NSLog(@"VavCore Info: %s", message.c_str());
#else
std::cout << "VavCore Info: " << message << std::endl;
#endif
}
};
} // namespace VavCore
```
### 4.3 Enhanced Godot 게임엔진 최적화 통합
#### 4.3.1 Godot 4 렌더링 아키텍처와 VavCore 통합
**Godot 4는 2024년 기준 다음과 같은 렌더링 백엔드를 사용:**
- **Vulkan**: Forward+ 및 Mobile 렌더링 메서드 (주력)
- **OpenGL ES 3.0**: Compatibility 렌더링 메서드 (호환성)
- **Google 협력**: Android Vulkan 최적화 완료
**VavCore Surface 타입별 Godot 통합 방식:**
```cpp
// Godot 4 Vulkan 렌더러 통합 (최우선)
bool IntegrateWithGodotVulkan(VkImage vk_image, VkDevice vk_device) {
// 1. MediaCodec → Vulkan VkImage 직접 디코딩
auto decoder = VideoDecoderFactory::CreateDecoder(VideoCodecType::AV1, DecoderType::AUTO);
if (decoder->SupportsSurfaceType(VAVCORE_SURFACE_VULKAN_IMAGE)) {
// 2. Godot Vulkan 렌더링 디바이스와 직접 연결
decoder->SetVulkanDevice(vk_device, vk_instance);
// 3. Zero-copy: MediaCodec → VkImage → Godot 텍스처
VideoFrame output_frame;
bool success = decoder->DecodeToSurface(
packet_data, packet_size,
VAVCORE_SURFACE_VULKAN_IMAGE,
vk_image,
output_frame
);
// 4. Godot에서 VkImage를 텍스처로 직접 사용
// RenderingDevice.texture_create_from_extension() 활용
return success;
}
return false;
}
// Godot 4 OpenGL ES Compatibility 렌더러 통합
bool IntegrateWithGodotOpenGLES(GLuint texture_id, EGLContext egl_context) {
// 1. MediaCodec → SurfaceTexture → GL_TEXTURE_EXTERNAL_OES
auto decoder = VideoDecoderFactory::CreateDecoder(VideoCodecType::AV1, DecoderType::AUTO);
if (decoder->SupportsSurfaceType(VAVCORE_SURFACE_OPENGL_ES_TEXTURE)) {
// 2. Godot OpenGL ES 컨텍스트와 연결
decoder->SetOpenGLESContext(egl_context);
// 3. SurfaceTexture 생성 (JNI를 통해)
SurfaceTexture* surface_texture = CreateSurfaceTexture(texture_id);
ANativeWindow* native_window = CreateNativeWindowFromSurfaceTexture(surface_texture);
// 4. MediaCodec → SurfaceTexture → Godot GL 텍스처
VideoFrame output_frame;
bool success = decoder->DecodeToSurface(
packet_data, packet_size,
VAVCORE_SURFACE_OPENGL_ES_TEXTURE,
native_window,
output_frame
);
// 5. updateTexImage() 호출 후 Godot에서 텍스처 사용
return success;
}
return false;
}
```
#### 4.3.2 Godot Android 플러그인 구조
```cpp
// Godot Android VavCore 플러그인 (JNI 인터페이스)
extern "C" {
// 디코더 생성 및 초기화
JNIEXPORT jlong JNICALL
Java_org_godotengine_plugin_vavcore_VavCorePlugin_createDecoder(JNIEnv* env, jclass clazz) {
auto decoder = VideoDecoderFactory::CreateDecoder(VideoCodecType::AV1, DecoderType::AUTO);
return reinterpret_cast<jlong>(decoder.release());
}
// Godot 렌더링 백엔드별 최적화 설정
JNIEXPORT jint JNICALL
Java_org_godotengine_plugin_vavcore_VavCorePlugin_getOptimalSurfaceType(
JNIEnv* env, jclass clazz, jlong decoder_ptr) {
auto* decoder = reinterpret_cast<AndroidMediaCodecAV1Decoder*>(decoder_ptr);
return static_cast<jint>(decoder->GetOptimalSurfaceType());
}
// Vulkan 렌더러 통합 (Godot 4 Forward+/Mobile)
JNIEXPORT jboolean JNICALL
Java_org_godotengine_plugin_vavcore_VavCorePlugin_setupVulkanIntegration(
JNIEnv* env, jclass clazz, jlong decoder_ptr,
jlong vk_device, jlong vk_instance) {
auto* decoder = reinterpret_cast<AndroidMediaCodecAV1Decoder*>(decoder_ptr);
bool success = decoder->SetVulkanDevice(
reinterpret_cast<void*>(vk_device),
reinterpret_cast<void*>(vk_instance)
);
return success ? JNI_TRUE : JNI_FALSE;
}
// OpenGL ES 렌더러 통합 (Godot 4 Compatibility)
JNIEXPORT jboolean JNICALL
Java_org_godotengine_plugin_vavcore_VavCorePlugin_setupOpenGLESIntegration(
JNIEnv* env, jclass clazz, jlong decoder_ptr,
jobject surface_texture) {
auto* decoder = reinterpret_cast<AndroidMediaCodecAV1Decoder*>(decoder_ptr);
// SurfaceTexture → ANativeWindow 변환
ANativeWindow* native_window = ANativeWindow_fromSurface(env, surface_texture);
if (!native_window) {
return JNI_FALSE;
}
bool success = decoder->SetAndroidSurface(native_window);
ANativeWindow_release(native_window);
return success ? JNI_TRUE : JNI_FALSE;
}
// 프레임 디코딩 (Godot 텍스처로 직접 출력)
JNIEXPORT jboolean JNICALL
Java_org_godotengine_plugin_vavcore_VavCorePlugin_decodeFrameToTexture(
JNIEnv* env, jclass clazz, jlong decoder_ptr,
jbyteArray packet_data, jlong texture_handle) {
auto* decoder = reinterpret_cast<AndroidMediaCodecAV1Decoder*>(decoder_ptr);
// JNI 바이트 배열 → 네이티브 포인터
jbyte* data = env->GetByteArrayElements(packet_data, nullptr);
jsize size = env->GetArrayLength(packet_data);
VavCoreSurfaceType surface_type = decoder->GetOptimalSurfaceType();
void* target_surface = reinterpret_cast<void*>(texture_handle);
VideoFrame output_frame;
bool success = decoder->DecodeToSurface(
reinterpret_cast<const uint8_t*>(data),
static_cast<size_t>(size),
surface_type,
target_surface,
output_frame
);
env->ReleaseByteArrayElements(packet_data, data, JNI_ABORT);
return success ? JNI_TRUE : JNI_FALSE;
}
// Godot 통합 상태 정보
JNIEXPORT jstring JNICALL
Java_org_godotengine_plugin_vavcore_VavCorePlugin_getGodotIntegrationInfo(
JNIEnv* env, jclass clazz, jlong decoder_ptr) {
auto* decoder = reinterpret_cast<AndroidMediaCodecAV1Decoder*>(decoder_ptr);
std::string info = decoder->GetGodotIntegrationInfo();
return env->NewStringUTF(info.c_str());
}
}
```
#### 4.3.3 Godot GDScript 인터페이스
```gdscript
# Godot VavCore 플러그인 GDScript 인터페이스
class_name VavCoreVideoPlayer
extends RefCounted
# 네이티브 플러그인 참조
var _native_decoder: int = 0
var _surface_type: int = 0
var _texture: Texture2D
# 초기화
func initialize() -> bool:
if not Engine.has_singleton("VavCorePlugin"):
push_error("VavCore plugin not found")
return false
var plugin = Engine.get_singleton("VavCorePlugin")
_native_decoder = plugin.createDecoder()
if _native_decoder == 0:
push_error("Failed to create VavCore decoder")
return false
# Godot 렌더링 백엔드에 맞는 최적 Surface 타입 확인
_surface_type = plugin.getOptimalSurfaceType(_native_decoder)
# 렌더링 백엔드별 초기화
match _surface_type:
VavCoreSurfaceType.VULKAN_IMAGE:
return _setup_vulkan_integration()
VavCoreSurfaceType.OPENGL_ES_TEXTURE:
return _setup_opengl_integration()
_:
push_warning("Using CPU decoding - not optimal for Godot")
return true
# Vulkan 통합 설정
func _setup_vulkan_integration() -> bool:
var rendering_device = RenderingServer.create_local_rendering_device()
if not rendering_device:
return false
# Vulkan 디바이스 정보 전달 (실제 구현에서는 RenderingDevice API 사용)
var plugin = Engine.get_singleton("VavCorePlugin")
return plugin.setupVulkanIntegration(_native_decoder, 0, 0) # VkDevice, VkInstance
# OpenGL ES 통합 설정
func _setup_opengl_integration() -> bool:
# SurfaceTexture 생성 및 설정
var plugin = Engine.get_singleton("VavCorePlugin")
# 실제 구현에서는 Android SurfaceTexture API 사용
return plugin.setupOpenGLESIntegration(_native_decoder, null)
# AV1 비디오 프레임 디코딩
func decode_frame(packet_data: PackedByteArray) -> bool:
if _native_decoder == 0:
return false
var plugin = Engine.get_singleton("VavCorePlugin")
return plugin.decodeFrameToTexture(_native_decoder, packet_data, 0)
# 통합 정보 확인
func get_integration_info() -> String:
if _native_decoder == 0:
return "Decoder not initialized"
var plugin = Engine.get_singleton("VavCorePlugin")
return plugin.getGodotIntegrationInfo(_native_decoder)
```
### 4.4 Unity/Unreal 엔진 통합 (참조용)
Java_com_vavcore_VavCore_createDecoder(JNIEnv* env, jclass clazz) {
auto decoder = VideoDecoderFactory::CreateDecoder(VideoCodecType::AV1, DecoderType::AUTO);
return reinterpret_cast<jlong>(decoder.release());
}
JNIEXPORT jboolean JNICALL
Java_com_vavcore_VavCore_setupAndroidSurface(JNIEnv* env, jclass clazz,
jlong decoder_ptr, jobject surface) {
auto* decoder = reinterpret_cast<IVideoDecoder*>(decoder_ptr);
ANativeWindow* native_window = ANativeWindow_fromSurface(env, surface);
return decoder->SetAndroidSurface(native_window) ? JNI_TRUE : JNI_FALSE;
}
JNIEXPORT jboolean JNICALL
Java_com_vavcore_VavCore_decodeToSurface(JNIEnv* env, jclass clazz,
jlong decoder_ptr, jbyteArray packet_data,
jint surface_type, jlong surface_handle) {
auto* decoder = reinterpret_cast<IVideoDecoder*>(decoder_ptr);
// JNI 바이트 배열을 네이티브 포인터로 변환
jbyte* data = env->GetByteArrayElements(packet_data, nullptr);
jsize size = env->GetArrayLength(packet_data);
void* surface = reinterpret_cast<void*>(surface_handle);
VideoFrame output_frame;
bool result = decoder->DecodeToSurface(
reinterpret_cast<const uint8_t*>(data),
static_cast<size_t>(size),
static_cast<VavCoreSurfaceType>(surface_type),
surface,
output_frame
);
env->ReleaseByteArrayElements(packet_data, data, JNI_ABORT);
return result ? JNI_TRUE : JNI_FALSE;
}
}
// Unity Native Plugin 인터페이스 (크로스 플랫폼)
extern "C" {
UNITY_INTERFACE_EXPORT void* UNITY_INTERFACE_API
VavCore_CreateDecoder() {
auto decoder = VideoDecoderFactory::CreateDecoder(VideoCodecType::AV1, DecoderType::AUTO);
return decoder.release();
}
UNITY_INTERFACE_EXPORT bool UNITY_INTERFACE_API
VavCore_SetupGraphicsAPI(void* decoder_ptr, int surface_type, void* graphics_device) {
auto* decoder = static_cast<IVideoDecoder*>(decoder_ptr);
switch (static_cast<VavCoreSurfaceType>(surface_type)) {
case VAVCORE_SURFACE_D3D11_TEXTURE:
return decoder->SetD3DDevice(graphics_device, VAVCORE_SURFACE_D3D11_TEXTURE);
case VAVCORE_SURFACE_OPENGL_TEXTURE:
return decoder->SetOpenGLContext(graphics_device);
case VAVCORE_SURFACE_METAL_TEXTURE:
return decoder->SetMetalDevice(graphics_device);
default:
return false;
}
}
}
```
## 5. Enhanced 성능 최적화 및 Zero-Copy 아키텍처
### 5.1 완전한 Zero-Copy Graphics Pipeline
**Android MediaCodec + GPU 직접 렌더링 최적화:**
```cpp
// Zero-Copy 성능 최적화 클래스
class AndroidZeroCopyOptimizer {
public:
// GPU-to-GPU 직접 전송 (메모리 복사 완전 제거)
bool OptimizeForSoC(const std::string& soc_name) {
if (IsQualcommSnapdragon(soc_name)) {
// Qualcomm Adreno GPU 최적화
EnableAdrenoGPUMemoryExtensions();
SetOptimalColorFormat(COLOR_FormatYUV420SemiPlanar);
return true;
}
if (IsSamsungExynos(soc_name)) {
// Samsung Mali GPU 최적화
EnableMaliGPUDirectRendering();
SetOptimalColorFormat(COLOR_FormatYUV420Flexible);
return true;
}
if (IsMediaTekDimensity(soc_name)) {
// MediaTek Mali GPU 최적화
EnableMaliGPUOptimizations();
return true;
}
return false; // 기본 설정 사용
}
// 메모리 대역폭 최적화
void OptimizeMemoryBandwidth() {
// SoC별 메모리 대역폭 특성에 맞춰 버퍼 크기 조정
m_optimal_buffer_count = GetOptimalBufferCount();
m_optimal_buffer_size = GetOptimalBufferSize();
}
private:
int m_optimal_buffer_count = 4; // SoC별 최적화
size_t m_optimal_buffer_size = 0;
};
```
### 5.2 Enhanced Graceful Fallback 전략 (다단계)
```cpp
class EnhancedFallbackStrategy {
public:
std::unique_ptr<IVideoDecoder> CreateOptimalDecoder(VideoCodecType codec_type) {
// 1단계: 하드웨어 가속 시도 (우선순위 순)
if (auto decoder = TryHardwareDecoders(codec_type)) {
LogInfo("Hardware decoder selected: " + decoder->GetCodecName());
return decoder;
}
// 2단계: 하이브리드 디코더 시도 (일부 하드웨어 가속)
if (auto decoder = TryHybridDecoders(codec_type)) {
LogInfo("Hybrid decoder selected: " + decoder->GetCodecName());
return decoder;
}
// 3단계: 최적화된 소프트웨어 디코더
auto decoder = std::make_unique<AV1Decoder>();
decoder->SetOptimizations(GetCPUOptimizations());
LogInfo("Optimized software decoder selected");
return decoder;
}
private:
std::unique_ptr<IVideoDecoder> TryHardwareDecoders(VideoCodecType codec_type) {
#ifdef VAVCORE_PLATFORM_ANDROID
// Android 하드웨어 디코더들 시도
std::vector<std::string> hw_codecs = {
"c2.qti.av1.decoder", // Qualcomm 최신
"OMX.qcom.video.decoder.av1", // Qualcomm 레거시
"c2.mtk.av1.decoder", // MediaTek
"c2.exynos.av1.decoder" // Samsung Exynos
};
for (const auto& codec_name : hw_codecs) {
if (auto decoder = TryCreateMediaCodec(codec_name)) {
return decoder;
}
}
#endif
return nullptr;
}
CPUOptimizations GetCPUOptimizations() {
CPUOptimizations opts;
opts.enable_neon = HasNEONSupport();
opts.thread_count = GetOptimalThreadCount();
opts.simd_level = GetMaxSIMDLevel();
return opts;
}
};
```
### 5.3 실시간 성능 모니터링 및 동적 최적화
```cpp
class PerformanceMonitor {
public:
void UpdateFrameStats(double decode_time_ms, bool hardware_accelerated) {
m_frame_times.push_back(decode_time_ms);
if (m_frame_times.size() > 30) { // 30프레임 이동평균
m_frame_times.pop_front();
}
double avg_time = CalculateAverage(m_frame_times);
// 성능이 목표치 미달 시 동적 최적화
if (avg_time > TARGET_DECODE_TIME_MS) {
TriggerPerformanceOptimization();
}
// 하드웨어 가속 효과 모니터링
if (!hardware_accelerated && avg_time > SW_FALLBACK_THRESHOLD_MS) {
LogWarning("Software decoder performance below threshold, consider resolution scaling");
}
}
private:
static constexpr double TARGET_DECODE_TIME_MS = 16.67; // 60fps 목표
static constexpr double SW_FALLBACK_THRESHOLD_MS = 33.33; // 30fps 최소
std::deque<double> m_frame_times;
void TriggerPerformanceOptimization() {
// 동적 해상도 스케일링
// 품질 레벨 조정
// 버퍼 크기 최적화
}
};
```
## 6. Enhanced 테스트 및 검증 시스템
### 6.1 포괄적인 Android 테스트 애플리케이션
```cpp
// VavCore Android 종합 테스트 애플리케이션
class ComprehensiveAndroidTest {
public:
void RunAllTests() {
TestHardwareDetection();
TestAllSurfaceTypes();
TestPerformanceBenchmark();
TestFallbackScenarios();
TestMemoryLeaks();
}
private:
void TestAllSurfaceTypes() {
auto decoder = VideoDecoderFactory::CreateDecoder(VideoCodecType::AV1, DecoderType::AUTO);
// ANativeWindow 테스트
if (decoder->SupportsSurfaceType(VAVCORE_SURFACE_ANDROID_NATIVE_WINDOW)) {
TestNativeWindowRendering(decoder.get());
}
// OpenGL ES 텍스처 테스트
if (decoder->SupportsSurfaceType(VAVCORE_SURFACE_OPENGL_ES_TEXTURE)) {
TestOpenGLESTextureRendering(decoder.get());
}
// Vulkan 이미지 테스트
if (decoder->SupportsSurfaceType(VAVCORE_SURFACE_VULKAN_IMAGE)) {
TestVulkanImageRendering(decoder.get());
}
// AHardwareBuffer 테스트
if (decoder->SupportsSurfaceType(VAVCORE_SURFACE_ANDROID_HARDWARE_BUFFER)) {
TestHardwareBufferRendering(decoder.get());
}
}
void TestPerformanceBenchmark() {
// 다양한 해상도 및 비트레이트 테스트
std::vector<TestVideo> test_videos = {
{"1080p_av1.webm", 1920, 1080, 5000}, // 5Mbps
{"4k_av1.webm", 3840, 2160, 15000}, // 15Mbps
{"720p_av1.webm", 1280, 720, 2000} // 2Mbps
};
for (const auto& test_video : test_videos) {
BenchmarkVideo(test_video);
}
}
};
```
### 6.2 성능 벤치마크 및 최적화 메트릭스
**측정 항목들:**
- **초기화 시간**: MediaCodec vs dav1d 시작 시간 비교
- **디코딩 지연시간**: 하드웨어 vs 소프트웨어 프레임별 처리 시간
- **GPU 사용률**: 하드웨어 가속 시 GPU 점유율
- **전력 소비**: 배터리 소모량 측정 (Android Battery Historian)
- **메모리 사용량**: 피크 메모리 및 메모리 누수 검사
- **열 관리**: SoC 온도 상승 및 스로틀링 감지
- **Surface 렌더링 성능**: 각 Graphics API별 렌더링 성능
## 7. Enhanced 구현 로드맵 (완전한 크로스 플랫폼 지원)
### Phase 1: 핵심 크로스 플랫폼 인프라 (1-2주) ✅ **완료**
- [x] **VavCoreSurfaceType 시스템**: 완전한 크로스 플랫폼 Surface 타입 열거형
- [x] **Enhanced IVideoDecoder 인터페이스**: 모든 플랫폼의 Graphics API 지원
- [x] **VideoDecoderFactory 확장**: 플랫폼별 디코더 등록 및 우선순위 시스템
- [x] **크로스 플랫폼 빌드 시스템**: CMake + 플랫폼별 조건부 컴파일
### Phase 2: AndroidMediaCodecAV1Decoder 구현 (2-3주)
- [ ] **Enhanced AndroidMediaCodecAV1Decoder**: 모든 IVideoDecoder 메서드 구현
- [ ] **Android SoC별 하드웨어 감지**: Qualcomm, Samsung, MediaTek, Google Tensor 지원
- [ ] **Graphics API 통합**: OpenGL ES, Vulkan, ANativeWindow, AHardwareBuffer
- [ ] **Zero-Copy Surface 디코딩**: GPU-to-GPU 직접 전송 최적화
### Phase 3: 성능 최적화 및 테스트 (3-4주)
- [ ] **포괄적인 테스트 애플리케이션**: 모든 Surface 타입 및 SoC 조합 테스트
- [ ] **성능 벤치마킹**: 하드웨어 vs 소프트웨어 성능 비교
- [ ] **메모리 및 전력 최적화**: SoC별 최적화 설정 적용
- [ ] **Graceful Fallback 시스템**: 다단계 디코더 선택 및 전환
### Phase 4: 게임 엔진 통합 및 배포 (4-5주)
- [ ] **Godot Android 플러그인**: Native Surface 지원 완전 통합
- [ ] **Unity/Unreal 플러그인**: 크로스 플랫폼 Native Plugin 인터페이스
- [ ] **Android Studio 프로젝트**: 완전한 예제 애플리케이션
- [ ] **문서화 및 튜토리얼**: 개발자 가이드 및 API 레퍼런스
## 8. Enhanced 리스크 관리 및 완화 전략
### 8.1 하드웨어 호환성 리스크 (CRITICAL)
- **리스크**: Android 기기별 AV1 하드웨어 지원 차이
- **완화 전략**:
- 포괄적인 SoC 데이터베이스 구축 (Qualcomm, Samsung, MediaTek 등)
- 런타임 하드웨어 감지 및 자동 최적화
- 견고한 dav1d 소프트웨어 fallback 보장
- 성능 모니터링 기반 동적 디코더 전환
### 8.2 Android API 파편화 리스크 (MEDIUM)
- **리스크**: Android 버전별 MediaCodec API 변경 및 동작 차이
- **완화 전략**:
- 안정적인 NDK API만 사용 (API Level 21+)
- 버전별 조건부 컴파일 및 호환성 레이어
- 광범위한 Android 버전 테스트 (API 21~34)
### 8.3 성능 최적화 리스크 (MEDIUM)
- **리스크**: 특정 상황에서 하드웨어 디코더가 소프트웨어보다 성능 저하
- **완화 전략**:
- 실시간 성능 모니터링 시스템
- SoC별 성능 프로파일링 데이터베이스
- 동적 디코더 전환 알고리즘
- 사용자 정의 성능 임계값 설정
### 8.4 메모리 및 전력 소비 리스크 (LOW)
- **리스크**: 하드웨어 가속으로 인한 예상치 못한 메모리/전력 증가
- **완화 전략**:
- Zero-Copy 아키텍처로 메모리 사용량 최소화
- SoC별 전력 효율성 프로파일링
- 배터리 상태 기반 동적 최적화
## 9. 결론 및 향후 전망
### 9.1 프로젝트 성과 요약
본 Enhanced VavCore Android MediaCodec 통합 설계는 다음과 같은 혁신적 성과를 달성합니다:
**✅ 완전한 크로스 플랫폼 지원:**
- Windows (NVDEC, VPL, AMF, Media Foundation)
- Android (MediaCodec + OpenGL ES/Vulkan)
- macOS/iOS (Metal, VideoToolbox - 미래 확장)
- Linux (OpenGL, Vulkan - 미래 확장)
**✅ Zero-Copy 렌더링 아키텍처:**
- GPU-to-GPU 직접 전송으로 성능 최적화
- 메모리 복사 완전 제거
- SoC별 최적화된 Graphics API 선택
**✅ 완전한 역호환성:**
- 기존 Windows 코드 100% 호환
- 플랫폼 투명한 API 설계
- 점진적 마이그레이션 지원
### 9.2 기술적 혁신 포인트
1. **Unified Surface Type System**: 모든 플랫폼의 Graphics API를 단일 열거형으로 통합
2. **Enhanced IVideoDecoder Interface**: 플랫폼별 특성을 반영한 확장 가능한 인터페이스
3. **Smart Hardware Detection**: SoC별 최적 디코더 및 Graphics API 자동 선택
4. **Multi-layer Fallback**: 하드웨어 → 하이브리드 → 최적화된 소프트웨어 다단계 전환
### 9.3 향후 확장 계획
**즉시 확장 가능한 영역:**
- **VP9 지원**: 동일한 아키텍처로 VP9 디코더 추가
- **H.264/H.265 지원**: 레거시 코덱 지원 확장
- **iOS/macOS 지원**: VideoToolbox + Metal 통합
- **Linux 지원**: VAAPI + OpenGL/Vulkan 통합
**장기 확장 목표:**
- **실시간 스트리밍**: WebRTC + MediaCodec 통합
- **인코딩 지원**: 디코딩뿐만 아니라 인코딩 파이프라인
- **AI 후처리**: SoC NPU를 활용한 실시간 화질 개선
- **클라우드 연동**: 클라우드 GPU 리소스 활용
### 9.4 산업적 영향
본 설계는 다음과 같은 산업적 파급 효과를 기대합니다:
**게임 산업 (Godot 최적화):**
- **Godot 4**: Vulkan/OpenGL ES 텍스처와 직접 통합하여 Zero-Copy 비디오 재생
- **Unity/Unreal**: 크로스 플랫폼 Native Plugin 인터페이스 지원
- **모바일 게임**: 고화질 AV1 컷신 및 배경 영상을 최소 성능 오버헤드로 재생
**스트리밍 산업:**
- 모바일 앱에서의 효율적인 AV1 스트리밍 재생
- 배터리 효율성과 화질의 최적 균형
**교육 및 미디어:**
- 크로스 플랫폼 교육 애플리케이션
- 고화질 미디어 콘텐츠의 효율적 배포
---
### 📋 **문서 정보 (최종)**
- **버전**: 3.0.0 (완전한 크로스 플랫폼 Graphics API 통합)
- **최종 업데이트**: 2025-09-27
- **담당자**: Claude Code AI Assistant
- **상태**: 구현 준비 완료 (Implementation Ready)
---
*이 문서는 VavCore의 Android MediaCodec 통합뿐만 아니라 완전한 크로스 플랫폼 Graphics API 아키텍처를 제시하는 포괄적인 설계 문서입니다. 모든 주요 모바일 및 데스크톱 플랫폼에서 최적의 AV1 디코딩 성능을 보장하는 확장 가능한 솔루션을 제공합니다.*