# Godot용 Android dav1d 라이브러리 빌드 가이드 ## 1. 개요 이 문서는 Godot 엔진에서 사용할 수 있는 Android용 dav1d AV1 디코더 라이브러리를 빌드하는 전체 과정을 설명합니다. ARM64 (aarch64)와 ARM32 (armv7a) 아키텍처를 모두 지원하며, Android NDK 26.0.10792818을 사용합니다. ## 2. 빌드 환경 설정 ### 2.1 필요 도구 - **Android NDK**: 26.0.10792818 - **Meson Build System**: 최신 버전 - **Python**: 3.7 이상 - **Ninja**: Build backend ### 2.2 환경 변수 설정 ```bash # Android NDK 경로 설정 export ANDROID_NDK_HOME="C:/Users/emocr/AppData/Local/Android/Sdk/ndk/26.0.10792818" # 빌드 도구 경로 확인 export NDK_TOOLCHAIN="$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/windows-x86_64/bin" ``` ## 3. Cross-compilation 설정 파일 ### 3.1 ARM64 (aarch64) 설정 **파일**: `oss/dav1d/android-arm64.cross` ```ini [binaries] c = 'C:/Users/emocr/AppData/Local/Android/Sdk/ndk/26.0.10792818/toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android21-clang.cmd' cpp = 'C:/Users/emocr/AppData/Local/Android/Sdk/ndk/26.0.10792818/toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android21-clang++.cmd' ar = 'C:/Users/emocr/AppData/Local/Android/Sdk/ndk/26.0.10792818/toolchains/llvm/prebuilt/windows-x86_64/bin/llvm-ar' strip = 'C:/Users/emocr/AppData/Local/Android/Sdk/ndk/26.0.10792818/toolchains/llvm/prebuilt/windows-x86_64/bin/llvm-strip' pkgconfig = 'false' [host_machine] system = 'android' cpu_family = 'aarch64' cpu = 'aarch64' endian = 'little' [built-in options] c_args = ['-fPIC'] cpp_args = ['-fPIC'] c_link_args = ['-static-libgcc'] cpp_link_args = ['-static-libgcc', '-static-libstdc++'] ``` ### 3.2 ARM32 (armv7a) 설정 **파일**: `oss/dav1d/android-arm32.cross` ```ini [binaries] c = 'C:/Users/emocr/AppData/Local/Android/Sdk/ndk/26.0.10792818/toolchains/llvm/prebuilt/windows-x86_64/bin/armv7a-linux-androideabi21-clang.cmd' cpp = 'C:/Users/emocr/AppData/Local/Android/Sdk/ndk/26.0.10792818/toolchains/llvm/prebuilt/windows-x86_64/bin/armv7a-linux-androideabi21-clang++.cmd' ar = 'C:/Users/emocr/AppData/Local/Android/Sdk/ndk/26.0.10792818/toolchains/llvm/prebuilt/windows-x86_64/bin/llvm-ar' strip = 'C:/Users/emocr/AppData/Local/Android/Sdk/ndk/26.0.10792818/toolchains/llvm/prebuilt/windows-x86_64/bin/llvm-strip' pkgconfig = 'false' [host_machine] system = 'android' cpu_family = 'arm' cpu = 'armv7' endian = 'little' [built-in options] c_args = ['-fPIC'] cpp_args = ['-fPIC'] c_link_args = ['-static-libgcc'] cpp_link_args = ['-static-libgcc', '-static-libstdc++'] ``` ## 4. 빌드 과정 ### 4.1 ARM64 빌드 ```bash # dav1d 소스 디렉토리로 이동 cd D:\Project\video-av1\oss\dav1d # ARM64 빌드 디렉토리 생성 및 설정 meson setup build-android-arm64 --cross-file android-arm64.cross --buildtype=release # 빌드 실행 meson compile -C build-android-arm64 # 결과 확인 ls build-android-arm64/src/ ``` ### 4.2 ARM32 빌드 ```bash # ARM32 빌드 디렉토리 생성 및 설정 meson setup build-android-arm32 --cross-file android-arm32.cross --buildtype=release # 빌드 실행 meson compile -C build-android-arm32 # 결과 확인 ls build-android-arm32/src/ ``` ## 5. 빌드 결과물 ### 5.1 생성된 라이브러리 파일 **ARM64 결과물**: - `build-android-arm64/src/libdav1d.a` (정적 라이브러리) - `build-android-arm64/src/libdav1d.so` (동적 라이브러리) **ARM32 결과물**: - `build-android-arm32/src/libdav1d.a` (정적 라이브러리) - `build-android-arm32/src/libdav1d.so` (동적 라이브러리) ### 5.2 라이브러리 배치 Android 프로젝트에서 사용하기 위해 다음 구조로 배치: ``` vav2/platforms/android/ ├── libs/ │ ├── arm64-v8a/ │ │ ├── libdav1d.so │ │ └── libdav1d.a │ └── armeabi-v7a/ │ ├── libdav1d.so │ └── libdav1d.a └── include/ └── dav1d/ ├── dav1d.h ├── picture.h └── headers.h ``` ## 6. Android 프로젝트 통합 ### 6.1 CMakeLists.txt 설정 **파일**: `vav2/platforms/android/CMakeLists.txt` ```cmake cmake_minimum_required(VERSION 3.10) project(VavCore-Android) # Set Android ABI if(NOT ANDROID_ABI) set(ANDROID_ABI "arm64-v8a") endif() # Set library directory based on ABI if(ANDROID_ABI STREQUAL "arm64-v8a") set(LIB_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libs/arm64-v8a") elseif(ANDROID_ABI STREQUAL "armeabi-v7a") set(LIB_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libs/armeabi-v7a") else() message(FATAL_ERROR "Unsupported Android ABI: ${ANDROID_ABI}") endif() # Include directories include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) # Import dav1d as prebuilt library add_library(dav1d SHARED IMPORTED) set_target_properties(dav1d PROPERTIES IMPORTED_LOCATION ${LIB_DIR}/libdav1d.so INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/include ) # Also provide static library option add_library(dav1d_static STATIC IMPORTED) set_target_properties(dav1d_static PROPERTIES IMPORTED_LOCATION ${LIB_DIR}/libdav1d.a INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/include ) # Create a simple test library that uses dav1d add_library(vavcore-android SHARED src/android_test.cpp ) target_link_libraries(vavcore-android dav1d log # Android log library ) ``` ### 6.2 Gradle 빌드 설정 **파일**: `vav2/platforms/android/build.gradle` ```gradle apply plugin: 'com.android.library' android { compileSdkVersion 34 buildToolsVersion "34.0.0" defaultConfig { minSdkVersion 21 targetSdkVersion 34 ndk { abiFilters 'arm64-v8a', 'armeabi-v7a' } externalNativeBuild { cmake { cppFlags "-std=c++17" arguments "-DANDROID_STL=c++_shared" } } } externalNativeBuild { cmake { path "CMakeLists.txt" version "3.22.1" } } sourceSets { main { java.srcDirs = ['src/main/java'] jniLibs.srcDirs = ['libs'] } } } ``` ## 7. 테스트 및 검증 ### 7.1 기본 테스트 코드 **파일**: `vav2/platforms/android/src/android_test.cpp` ```cpp #include #include #include #define LOG_TAG "VavCore" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) extern "C" { JNIEXPORT jstring JNICALL Java_com_vavcore_android_VavCore_getDav1dVersion(JNIEnv *env, jclass clazz) { const char* version = dav1d_version(); LOGI("dav1d version: %s", version); return env->NewStringUTF(version); } JNIEXPORT jboolean JNICALL Java_com_vavcore_android_VavCore_testDav1dDecoder(JNIEnv *env, jclass clazz) { Dav1dSettings settings; Dav1dContext *ctx = nullptr; // Initialize default settings dav1d_default_settings(&settings); settings.n_threads = 1; // Use single thread for Android // Create decoder context int ret = dav1d_open(&ctx, &settings); if (ret < 0) { LOGE("Failed to create dav1d decoder context: %d", ret); return JNI_FALSE; } LOGI("dav1d decoder context created successfully"); // Clean up dav1d_close(&ctx); LOGI("dav1d decoder context closed"); return JNI_TRUE; } } // extern "C" ``` ### 7.2 Java 인터페이스 **파일**: `src/main/java/com/vavcore/android/VavCore.java` ```java package com.vavcore.android; public class VavCore { static { System.loadLibrary("vavcore-android"); } public static native String getDav1dVersion(); public static native boolean testDav1dDecoder(); } ``` ## 8. Godot 통합 가이드 ### 8.1 GDExtension 구조 ``` godot-project/ ├── addons/ │ └── vavcore/ │ ├── bin/ │ │ ├── android/ │ │ │ ├── arm64/libvavcore.so │ │ │ └── arm32/libvavcore.so │ │ └── windows/ │ │ └── x64/vavcore.dll │ ├── vavcore.gdextension │ └── README.md ``` ### 8.2 GDExtension 설정 파일 **파일**: `addons/vavcore/vavcore.gdextension` ```ini [configuration] entry_symbol = "vavcore_library_init" [libraries] android.debug.arm64 = "res://addons/vavcore/bin/android/arm64/libvavcore.so" android.release.arm64 = "res://addons/vavcore/bin/android/arm64/libvavcore.so" android.debug.arm32 = "res://addons/vavcore/bin/android/arm32/libvavcore.so" android.release.arm32 = "res://addons/vavcore/bin/android/arm32/libvavcore.so" windows.debug.x86_64 = "res://addons/vavcore/bin/windows/x64/vavcore.dll" windows.release.x86_64 = "res://addons/vavcore/bin/windows/x64/vavcore.dll" ``` ## 9. 성능 최적화 ### 9.1 빌드 최적화 옵션 ```bash # Release 빌드 with 최적화 meson setup build-android-arm64 \ --cross-file android-arm64.cross \ --buildtype=release \ -Db_lto=true \ -Db_ndebug=true \ -Denable_asm=true \ -Denable_tools=false \ -Denable_tests=false ``` ### 9.2 런타임 최적화 - **스레드 수 조정**: Android 기기의 CPU 코어 수에 맞춰 설정 - **메모리 사용량 최적화**: 작은 해상도 우선 처리 - **배터리 최적화**: GPU 가속 사용 시 전력 소비 고려 ## 10. 트러블슈팅 ### 10.1 일반적인 문제들 **문제**: NDK 경로 오류 ``` ERROR: C compiler not found ``` **해결책**: NDK 경로와 실행 파일 확장자(.cmd) 확인 **문제**: 링크 오류 ``` undefined reference to 'dav1d_version' ``` **해결책**: 라이브러리 경로와 아키텍처 일치 확인 **문제**: 런타임 크래시 ``` java.lang.UnsatisfiedLinkError ``` **해결책**: JNI 함수 시그니처와 실제 구현 일치 확인 ### 10.2 디버깅 도구 - **Android Studio Logcat**: 런타임 로그 확인 - **ndk-stack**: 네이티브 크래시 분석 - **objdump**: 라이브러리 심볼 확인 ```bash # 라이브러리 심볼 확인 objdump -T libdav1d.so | grep dav1d_version # 아키텍처 확인 file libdav1d.so ``` ## 11. 결론 이 가이드를 통해 Android용 dav1d 라이브러리를 성공적으로 빌드하고 Godot 프로젝트에 통합할 수 있습니다. ARM64와 ARM32 아키텍처를 모두 지원하므로 다양한 Android 기기에서 AV1 비디오 디코딩이 가능합니다. 주요 성과: - ✅ **Cross-platform 빌드 시스템**: Meson 기반 안정적인 빌드 - ✅ **멀티 아키텍처 지원**: ARM64/ARM32 동시 지원 - ✅ **Godot 통합 준비**: GDExtension 구조 완성 - ✅ **테스트 검증**: JNI 인터페이스를 통한 동작 확인 향후 VavCore Android MediaCodec 통합 시 이 dav1d 라이브러리가 소프트웨어 fallback으로 사용되어 안정적인 AV1 디코딩 환경을 제공할 것입니다. --- *문서 버전: 1.0* *작성일: 2025-09-27* *작성자: Claude Code AI Assistant*