Files
video-v1/vav2/docs/completed/cross-platform/Android_dav1d_Build_Guide.md

390 lines
11 KiB
Markdown
Raw Permalink Normal View History

2025-09-27 13:56:56 +09:00
# 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 <jni.h>
#include <android/log.h>
#include <dav1d/dav1d.h>
#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*