diff --git a/.gitignore b/.gitignore index 06416cc..838ab8c 100644 --- a/.gitignore +++ b/.gitignore @@ -344,16 +344,40 @@ FodyWeavers.xsd .idea/ *.sln.iml +# Android Studio / Gradle +.gradle/ +local.properties +*.apk +*.aab +*.jks +*.keystore +captures/ +.externalNativeBuild/ + # Project specific files +# 슬래시(/)를 앞에 붙여 프로젝트 루트 폴더에만 적용되도록 한정합니다. +/packages/ +/lib/ +/include/ +/oss/ +/build/ +/sample/ + +# Test data files *.mp4 *.webm *.mkv *.av1 -packages/ -lib/ -include/ -oss/ output.mp4 -build/ -sample/ + +# Visual Studio user settings *.user + +# Compiled libraries +# 참고: 안드로이드 프로젝트에서 사전 빌드된 .so 파일을 버전 관리에 포함해야 할 수 있습니다. +# 그럴 경우 이 줄을 주석 처리하거나 더 구체적인 경로를 지정해야 합니다. +*.a +*.so +/vav2/Vav2Player/packages/ +/vav2/VavCore/lib/ +/vav2/Vav2Player_Android/vavcore/build/ diff --git a/vav2/Android_dav1d_Build_Guide.md b/vav2/Android_dav1d_Build_Guide.md new file mode 100644 index 0000000..2781346 --- /dev/null +++ b/vav2/Android_dav1d_Build_Guide.md @@ -0,0 +1,390 @@ +# 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* \ No newline at end of file diff --git a/vav2/Vav2Player_Android/.gitignore b/vav2/Vav2Player_Android/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/vav2/Vav2Player_Android/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/vav2/Vav2Player_Android/app/.gitignore b/vav2/Vav2Player_Android/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/vav2/Vav2Player_Android/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/vav2/Vav2Player_Android/app/build.gradle.kts b/vav2/Vav2Player_Android/app/build.gradle.kts new file mode 100644 index 0000000..b518660 --- /dev/null +++ b/vav2/Vav2Player_Android/app/build.gradle.kts @@ -0,0 +1,60 @@ +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.kotlin.compose) +} + +android { + namespace = "com.ened.vav2player_android" + compileSdk = 36 + + defaultConfig { + applicationId = "com.ened.vav2player_android" + minSdk = 29 + targetSdk = 36 + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + kotlinOptions { + jvmTarget = "11" + } + buildFeatures { + compose = true + } +} + +dependencies { + implementation(project(":vavcore")) + + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.lifecycle.runtime.ktx) + implementation(libs.androidx.activity.compose) + implementation(platform(libs.androidx.compose.bom)) + implementation(libs.androidx.compose.ui) + implementation(libs.androidx.compose.ui.graphics) + implementation(libs.androidx.compose.ui.tooling.preview) + implementation(libs.androidx.compose.material3) + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.espresso.core) + androidTestImplementation(platform(libs.androidx.compose.bom)) + androidTestImplementation(libs.androidx.compose.ui.test.junit4) + debugImplementation(libs.androidx.compose.ui.tooling) + debugImplementation(libs.androidx.compose.ui.test.manifest) +} \ No newline at end of file diff --git a/vav2/Vav2Player_Android/app/proguard-rules.pro b/vav2/Vav2Player_Android/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/vav2/Vav2Player_Android/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/vav2/Vav2Player_Android/app/src/androidTest/java/com/ened/vav2player_android/ExampleInstrumentedTest.kt b/vav2/Vav2Player_Android/app/src/androidTest/java/com/ened/vav2player_android/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..2d3830d --- /dev/null +++ b/vav2/Vav2Player_Android/app/src/androidTest/java/com/ened/vav2player_android/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.ened.vav2player_android + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.ened.vav2player_android", appContext.packageName) + } +} \ No newline at end of file diff --git a/vav2/Vav2Player_Android/app/src/main/AndroidManifest.xml b/vav2/Vav2Player_Android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..7ffc916 --- /dev/null +++ b/vav2/Vav2Player_Android/app/src/main/AndroidManifest.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vav2/Vav2Player_Android/app/src/main/java/com/ened/vav2player_android/MainActivity.kt b/vav2/Vav2Player_Android/app/src/main/java/com/ened/vav2player_android/MainActivity.kt new file mode 100644 index 0000000..f07a39d --- /dev/null +++ b/vav2/Vav2Player_Android/app/src/main/java/com/ened/vav2player_android/MainActivity.kt @@ -0,0 +1,179 @@ +package com.ened.vav2player_android + +import android.content.Intent +import android.os.Bundle +import android.util.Log +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.ened.vav2player_android.ui.theme.Vav2Player_AndroidTheme +import com.vavcore.VavCore + +class MainActivity : ComponentActivity() { + private val TAG = "MainActivity" + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + enableEdgeToEdge() + setContent { + Vav2Player_AndroidTheme { + Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> + MainScreen( + modifier = Modifier.padding(innerPadding), + onVavCoreTestClick = { startVavCoreTest() }, + onMediaCodecTestClick = { startMediaCodecTest() }, + onVideoPlayerClick = { startVideoPlayer() }, + onPerformanceTestClick = { startPerformanceTest() } + ) + } + } + } + } + + private fun startVavCoreTest() { + // TODO: Implement VavCoreTestActivity + Log.i(TAG, "VavCore Test clicked") + } + + private fun startMediaCodecTest() { + // TODO: Implement MediaCodecTestActivity + Log.i(TAG, "MediaCodec Test clicked") + } + + private fun startVideoPlayer() { + // TODO: Implement VideoPlayerActivity + Log.i(TAG, "Video Player clicked") + } + + private fun startPerformanceTest() { + // TODO: Implement PerformanceTestActivity + Log.i(TAG, "Performance Test clicked") + } +} + +@Composable +fun MainScreen( + modifier: Modifier = Modifier, + onVavCoreTestClick: () -> Unit, + onMediaCodecTestClick: () -> Unit, + onVideoPlayerClick: () -> Unit, + onPerformanceTestClick: () -> Unit +) { + var statusText by remember { mutableStateOf("Initializing...") } + + LaunchedEffect(Unit) { + statusText = initializeVavCore() + } + + Column( + modifier = modifier + .fillMaxSize() + .padding(16.dp) + .verticalScroll(rememberScrollState()), + verticalArrangement = Arrangement.spacedBy(16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = "Vav2Player Android", + style = MaterialTheme.typography.headlineMedium + ) + + Spacer(modifier = Modifier.height(16.dp)) + + // Test Buttons + Button( + onClick = onVavCoreTestClick, + modifier = Modifier.fillMaxWidth() + ) { + Text("VavCore Test") + } + + Button( + onClick = onMediaCodecTestClick, + modifier = Modifier.fillMaxWidth() + ) { + Text("MediaCodec Test") + } + + Button( + onClick = onVideoPlayerClick, + modifier = Modifier.fillMaxWidth() + ) { + Text("Video Player") + } + + Button( + onClick = onPerformanceTestClick, + modifier = Modifier.fillMaxWidth() + ) { + Text("Performance Test") + } + + Spacer(modifier = Modifier.height(24.dp)) + + // Status Display + Card( + modifier = Modifier.fillMaxWidth() + ) { + Text( + text = statusText, + modifier = Modifier.padding(16.dp), + style = MaterialTheme.typography.bodyMedium + ) + } + } +} + +private fun initializeVavCore(): String { + return try { + val version = VavCore.getVersion() + val statusBuilder = StringBuilder("VavCore Version: $version\n") + + val initialized = VavCore.initialize() + if (initialized) { + statusBuilder.append("✅ VavCore initialized successfully\n") + + // List available decoders + val decoders = VavCore.listAvailableDecoders() + statusBuilder.append("Available decoders: ${decoders.joinToString(", ")}\n") + + // Test MediaCodec + val mediaCodecWorking = VavCore.isMediaCodecAvailable() + statusBuilder.append("MediaCodec: ${if (mediaCodecWorking) "✅ Available" else "❌ Not available"}\n") + + // Test dav1d + val dav1dWorking = VavCore.isDav1dAvailable() + statusBuilder.append("dav1d: ${if (dav1dWorking) "✅ Available" else "❌ Not available"}") + + } else { + statusBuilder.append("❌ Failed to initialize VavCore") + } + + statusBuilder.toString() + } catch (e: Exception) { + Log.e("MainActivity", "Error initializing VavCore", e) + "❌ VavCore initialization error: ${e.message}" + } +} + +@Preview(showBackground = true) +@Composable +fun MainScreenPreview() { + Vav2Player_AndroidTheme { + MainScreen( + onVavCoreTestClick = {}, + onMediaCodecTestClick = {}, + onVideoPlayerClick = {}, + onPerformanceTestClick = {} + ) + } +} \ No newline at end of file diff --git a/vav2/Vav2Player_Android/app/src/main/java/com/ened/vav2player_android/ui/theme/Color.kt b/vav2/Vav2Player_Android/app/src/main/java/com/ened/vav2player_android/ui/theme/Color.kt new file mode 100644 index 0000000..1d75848 --- /dev/null +++ b/vav2/Vav2Player_Android/app/src/main/java/com/ened/vav2player_android/ui/theme/Color.kt @@ -0,0 +1,11 @@ +package com.ened.vav2player_android.ui.theme + +import androidx.compose.ui.graphics.Color + +val Purple80 = Color(0xFFD0BCFF) +val PurpleGrey80 = Color(0xFFCCC2DC) +val Pink80 = Color(0xFFEFB8C8) + +val Purple40 = Color(0xFF6650a4) +val PurpleGrey40 = Color(0xFF625b71) +val Pink40 = Color(0xFF7D5260) \ No newline at end of file diff --git a/vav2/Vav2Player_Android/app/src/main/java/com/ened/vav2player_android/ui/theme/Theme.kt b/vav2/Vav2Player_Android/app/src/main/java/com/ened/vav2player_android/ui/theme/Theme.kt new file mode 100644 index 0000000..25acd11 --- /dev/null +++ b/vav2/Vav2Player_Android/app/src/main/java/com/ened/vav2player_android/ui/theme/Theme.kt @@ -0,0 +1,58 @@ +package com.ened.vav2player_android.ui.theme + +import android.app.Activity +import android.os.Build +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.dynamicDarkColorScheme +import androidx.compose.material3.dynamicLightColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext + +private val DarkColorScheme = darkColorScheme( + primary = Purple80, + secondary = PurpleGrey80, + tertiary = Pink80 +) + +private val LightColorScheme = lightColorScheme( + primary = Purple40, + secondary = PurpleGrey40, + tertiary = Pink40 + + /* Other default colors to override + background = Color(0xFFFFFBFE), + surface = Color(0xFFFFFBFE), + onPrimary = Color.White, + onSecondary = Color.White, + onTertiary = Color.White, + onBackground = Color(0xFF1C1B1F), + onSurface = Color(0xFF1C1B1F), + */ +) + +@Composable +fun Vav2Player_AndroidTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + // Dynamic color is available on Android 12+ + dynamicColor: Boolean = true, + content: @Composable () -> Unit +) { + val colorScheme = when { + dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + val context = LocalContext.current + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + } + + darkTheme -> DarkColorScheme + else -> LightColorScheme + } + + MaterialTheme( + colorScheme = colorScheme, + typography = Typography, + content = content + ) +} \ No newline at end of file diff --git a/vav2/Vav2Player_Android/app/src/main/java/com/ened/vav2player_android/ui/theme/Type.kt b/vav2/Vav2Player_Android/app/src/main/java/com/ened/vav2player_android/ui/theme/Type.kt new file mode 100644 index 0000000..d4033b3 --- /dev/null +++ b/vav2/Vav2Player_Android/app/src/main/java/com/ened/vav2player_android/ui/theme/Type.kt @@ -0,0 +1,34 @@ +package com.ened.vav2player_android.ui.theme + +import androidx.compose.material3.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +// Set of Material typography styles to start with +val Typography = Typography( + bodyLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp + ) + /* Other default text styles to override + titleLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 22.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp + ), + labelSmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 11.sp, + lineHeight = 16.sp, + letterSpacing = 0.5.sp + ) + */ +) \ No newline at end of file diff --git a/vav2/Vav2Player_Android/app/src/main/res/drawable/ic_launcher_background.xml b/vav2/Vav2Player_Android/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/vav2/Vav2Player_Android/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vav2/Vav2Player_Android/app/src/main/res/drawable/ic_launcher_foreground.xml b/vav2/Vav2Player_Android/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/vav2/Vav2Player_Android/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/vav2/Vav2Player_Android/app/src/main/res/mipmap-anydpi/ic_launcher.xml b/vav2/Vav2Player_Android/app/src/main/res/mipmap-anydpi/ic_launcher.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/vav2/Vav2Player_Android/app/src/main/res/mipmap-anydpi/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/vav2/Vav2Player_Android/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml b/vav2/Vav2Player_Android/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/vav2/Vav2Player_Android/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/vav2/Vav2Player_Android/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/vav2/Vav2Player_Android/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 Binary files /dev/null and b/vav2/Vav2Player_Android/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/vav2/Vav2Player_Android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/vav2/Vav2Player_Android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d Binary files /dev/null and b/vav2/Vav2Player_Android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/vav2/Vav2Player_Android/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/vav2/Vav2Player_Android/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 Binary files /dev/null and b/vav2/Vav2Player_Android/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/vav2/Vav2Player_Android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/vav2/Vav2Player_Android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d Binary files /dev/null and b/vav2/Vav2Player_Android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/vav2/Vav2Player_Android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/vav2/Vav2Player_Android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 Binary files /dev/null and b/vav2/Vav2Player_Android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/vav2/Vav2Player_Android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/vav2/Vav2Player_Android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 Binary files /dev/null and b/vav2/Vav2Player_Android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/vav2/Vav2Player_Android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/vav2/Vav2Player_Android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 Binary files /dev/null and b/vav2/Vav2Player_Android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/vav2/Vav2Player_Android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/vav2/Vav2Player_Android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 Binary files /dev/null and b/vav2/Vav2Player_Android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/vav2/Vav2Player_Android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/vav2/Vav2Player_Android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 Binary files /dev/null and b/vav2/Vav2Player_Android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/vav2/Vav2Player_Android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/vav2/Vav2Player_Android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 Binary files /dev/null and b/vav2/Vav2Player_Android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/vav2/Vav2Player_Android/app/src/main/res/values/colors.xml b/vav2/Vav2Player_Android/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..f8c6127 --- /dev/null +++ b/vav2/Vav2Player_Android/app/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/vav2/Vav2Player_Android/app/src/main/res/values/strings.xml b/vav2/Vav2Player_Android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..b86c1e6 --- /dev/null +++ b/vav2/Vav2Player_Android/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Vav2Player_Android + \ No newline at end of file diff --git a/vav2/Vav2Player_Android/app/src/main/res/values/themes.xml b/vav2/Vav2Player_Android/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..bf7a8be --- /dev/null +++ b/vav2/Vav2Player_Android/app/src/main/res/values/themes.xml @@ -0,0 +1,5 @@ + + + +