#include "TestFramework.h" #include "Decoder/MediaCodecAV1Decoder.h" #include "Common/VideoTypes.h" #include #include #include #ifndef PROP_VALUE_MAX #define PROP_VALUE_MAX 92 #endif namespace VavCoreTest { bool TestVulkanAvailability(std::string& error_msg) { LOGI("Testing Vulkan availability..."); // Test Android API level requirement char sdk_version[PROP_VALUE_MAX] = {}; int api_level = 29; // Default if (__system_property_get("ro.build.version.sdk", sdk_version) > 0) { api_level = std::atoi(sdk_version); } LOGI("Android API Level: %d", api_level); if (api_level < 29) { LOGW("Android API %d < 29, Vulkan AHardwareBuffer integration not fully supported", api_level); LOGI("⚠️ Vulkan availability test skipped (API level too low)"); return true; } // Test AHardwareBuffer availability (API 26+) if (api_level < 26) { LOGW("Android API %d < 26, AHardwareBuffer not available", api_level); error_msg = "AHardwareBuffer requires API 26+"; return false; } LOGI("✅ Vulkan availability requirements met"); return true; } bool TestAHardwareBufferCreation(std::string& error_msg) { LOGI("Testing AHardwareBuffer creation..."); // Check Android API level char sdk_version[PROP_VALUE_MAX] = {}; int api_level = 29; if (__system_property_get("ro.build.version.sdk", sdk_version) > 0) { api_level = std::atoi(sdk_version); } if (api_level < 26) { LOGW("AHardwareBuffer requires API 26+, current API: %d", api_level); LOGI("⚠️ AHardwareBuffer creation test skipped (API level too low)"); return true; } // Test AHardwareBuffer allocation AHardwareBuffer_Desc desc = {}; desc.width = 1920; desc.height = 1080; desc.layers = 1; desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM; // RGBA format (YV12 not available in NDK) desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER; AHardwareBuffer* buffer = nullptr; int result = AHardwareBuffer_allocate(&desc, &buffer); if (result != 0) { LOGW("AHardwareBuffer allocation failed with code: %d", result); LOGI("⚠️ AHardwareBuffer creation test skipped (allocation failed)"); return true; // Not a hard failure - device might not support this format } TEST_ASSERT_NOT_NULL(buffer, "AHardwareBuffer allocation returned null"); LOGI("AHardwareBuffer created successfully: %p", buffer); // Test buffer description retrieval AHardwareBuffer_Desc retrieved_desc; AHardwareBuffer_describe(buffer, &retrieved_desc); TEST_ASSERT_EQ(desc.width, retrieved_desc.width, "Buffer width mismatch"); TEST_ASSERT_EQ(desc.height, retrieved_desc.height, "Buffer height mismatch"); TEST_ASSERT_EQ(desc.format, retrieved_desc.format, "Buffer format mismatch"); LOGI("Buffer description verified: %ux%u, format: 0x%x", retrieved_desc.width, retrieved_desc.height, retrieved_desc.format); // Clean up AHardwareBuffer_release(buffer); LOGI("✅ AHardwareBuffer creation test passed"); return true; } bool TestAndroidMediaCodecVulkanSetup(std::string& error_msg) { LOGI("Testing MediaCodecAV1Decoder Vulkan setup..."); // Create decoder instance auto decoder = std::make_unique(); TEST_ASSERT_NOT_NULL(decoder.get(), "Failed to create MediaCodecAV1Decoder"); // Test video metadata VavCore::VideoMetadata metadata; metadata.codec_type = VavCore::VideoCodecType::AV1; metadata.width = 1920; metadata.height = 1080; metadata.frame_rate = 30.0; // Initialize decoder bool init_result = decoder->Initialize(metadata); if (!init_result) { LOGW("Decoder initialization failed - likely no hardware AV1 support"); LOGI("⚠️ AndroidMediaCodec Vulkan setup test skipped (no AV1 hardware support)"); return true; } LOGI("Decoder initialized successfully"); // Test hardware acceleration check bool is_hw_accelerated = decoder->IsHardwareAccelerated(); LOGI("Hardware acceleration: %s", is_hw_accelerated ? "YES" : "NO"); if (!is_hw_accelerated) { LOGW("No hardware acceleration available - Vulkan image output not supported"); LOGI("⚠️ AndroidMediaCodec Vulkan setup test skipped (no hardware acceleration)"); return true; } // Test Vulkan device setup (mock objects for testing) void* mock_vk_device = reinterpret_cast(0x12345678); // Mock Vulkan device void* mock_vk_instance = reinterpret_cast(0x87654321); // Mock Vulkan instance bool vulkan_result = decoder->SetVulkanDevice(mock_vk_device, mock_vk_instance); TEST_ASSERT(vulkan_result, "Failed to set Vulkan device"); LOGI("Vulkan device set successfully"); // Test Vulkan image creation bool image_result = decoder->CreateVulkanImage(mock_vk_device, mock_vk_instance); if (!image_result) { LOGW("Vulkan image creation failed - this might be expected on some devices"); LOGI("⚠️ Vulkan image creation test skipped (creation failed)"); return true; // Not a hard failure } LOGI("Vulkan image created successfully"); // Test optimal surface type for Vulkan VavCoreSurfaceType optimal_type = decoder->GetOptimalSurfaceType(); LOGI("Optimal surface type: %d", static_cast(optimal_type)); // Verify Vulkan image is supported bool supports_vulkan = decoder->SupportsSurfaceType(VAVCORE_SURFACE_VULKAN_IMAGE); LOGI("Vulkan image surface supported: %s", supports_vulkan ? "YES" : "NO"); // Test Godot integration info for Vulkan std::string godot_info = decoder->GetGodotIntegrationInfo(); LOGI("Godot integration info: %s", godot_info.c_str()); bool is_optimal_for_godot = decoder->IsOptimalForGodot(); LOGI("Optimal for Godot: %s", is_optimal_for_godot ? "YES" : "NO"); // Clean up decoder->Cleanup(); LOGI("✅ AndroidMediaCodec Vulkan setup test passed"); return true; } bool TestVulkanDecodeToSurface(std::string& error_msg) { LOGI("Testing Vulkan decode to surface..."); // Create decoder instance auto decoder = std::make_unique(); TEST_ASSERT_NOT_NULL(decoder.get(), "Failed to create MediaCodecAV1Decoder"); // Test video metadata VavCore::VideoMetadata metadata; metadata.codec_type = VavCore::VideoCodecType::AV1; metadata.width = 1280; metadata.height = 720; metadata.frame_rate = 30.0; // Initialize decoder bool init_result = decoder->Initialize(metadata); if (!init_result) { LOGW("Decoder initialization failed - skipping Vulkan decode to surface test"); LOGI("⚠️ Vulkan decode to surface test skipped (no AV1 hardware support)"); return true; } // Check hardware acceleration if (!decoder->IsHardwareAccelerated()) { LOGW("No hardware acceleration - skipping Vulkan decode to surface test"); LOGI("⚠️ Vulkan decode to surface test skipped (no hardware acceleration)"); return true; } // Set Vulkan device void* mock_vk_device = reinterpret_cast(0x12345678); void* mock_vk_instance = reinterpret_cast(0x87654321); bool vulkan_result = decoder->SetVulkanDevice(mock_vk_device, mock_vk_instance); TEST_ASSERT(vulkan_result, "Failed to set Vulkan device"); // Create Vulkan image bool image_result = decoder->CreateVulkanImage(mock_vk_device, mock_vk_instance); if (!image_result) { LOGW("Vulkan image creation failed - skipping decode to surface test"); LOGI("⚠️ Vulkan decode to surface test skipped (image creation failed)"); return true; } // Test DecodeToSurface with dummy data uint8_t dummy_packet[] = { 0x12, 0x00, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x01 }; // Minimal AV1 OBU size_t packet_size = sizeof(dummy_packet); VavCore::VideoFrame output_frame; bool decode_result = decoder->DecodeToSurface( dummy_packet, packet_size, VAVCORE_SURFACE_VULKAN_IMAGE, mock_vk_device, // Mock VkImage output_frame ); // Note: This will likely fail with real dummy data, but we're testing the API flow if (!decode_result) { LOGW("DecodeToSurface failed with dummy data - this is expected"); } else { LOGI("DecodeToSurface succeeded with dummy data"); // Verify frame metadata TEST_ASSERT_EQ(1280, output_frame.width, "Incorrect frame width"); TEST_ASSERT_EQ(720, output_frame.height, "Incorrect frame height"); LOGI("Frame metadata: %dx%d", output_frame.width, output_frame.height); } LOGI("✅ Vulkan decode to surface test completed"); return true; } bool TestVulkanSurfaceTypeOptimization(std::string& error_msg) { LOGI("Testing Vulkan surface type optimization..."); // Create decoder instance auto decoder = std::make_unique(); TEST_ASSERT_NOT_NULL(decoder.get(), "Failed to create MediaCodecAV1Decoder"); // Test video metadata VavCore::VideoMetadata metadata; metadata.codec_type = VavCore::VideoCodecType::AV1; metadata.width = 1920; metadata.height = 1080; metadata.frame_rate = 60.0; // Initialize decoder bool init_result = decoder->Initialize(metadata); if (!init_result) { LOGW("Decoder initialization failed - skipping surface type optimization test"); LOGI("⚠️ Vulkan surface type optimization test skipped (no AV1 hardware support)"); return true; } // Test all Vulkan-related surface types std::vector> surface_types = { { VAVCORE_SURFACE_VULKAN_IMAGE, "VULKAN_IMAGE" }, { VAVCORE_SURFACE_ANDROID_HARDWARE_BUFFER, "ANDROID_HARDWARE_BUFFER" }, { VAVCORE_SURFACE_OPENGL_ES_TEXTURE, "OPENGL_ES_TEXTURE" }, { VAVCORE_SURFACE_ANDROID_NATIVE_WINDOW, "ANDROID_NATIVE_WINDOW" }, { VAVCORE_SURFACE_CPU, "CPU" } }; for (const auto& surface_type_pair : surface_types) { VavCoreSurfaceType type = surface_type_pair.first; const std::string& name = surface_type_pair.second; bool supported = decoder->SupportsSurfaceType(type); LOGI("Surface type %s: %s", name.c_str(), supported ? "SUPPORTED" : "NOT SUPPORTED"); } // Test optimal surface type selection VavCoreSurfaceType optimal_type = decoder->GetOptimalSurfaceType(); LOGI("Optimal surface type for this device: %d", static_cast(optimal_type)); // Test Godot-specific optimization bool is_optimal_for_godot = decoder->IsOptimalForGodot(); LOGI("Optimal for Godot integration: %s", is_optimal_for_godot ? "YES" : "NO"); // Get detailed Godot integration information std::string godot_info = decoder->GetGodotIntegrationInfo(); LOGI("Godot integration details: %s", godot_info.c_str()); // Verify that at least CPU surface is supported (fallback) bool cpu_supported = decoder->SupportsSurfaceType(VAVCORE_SURFACE_CPU); TEST_ASSERT(cpu_supported, "CPU surface should always be supported"); LOGI("✅ Vulkan surface type optimization test passed"); return true; } // Test registration function void RegisterVulkanImageTests(TestFramework& framework) { framework.RegisterTest("Vulkan_Availability", TestVulkanAvailability); framework.RegisterTest("Vulkan_AHardwareBuffer", TestAHardwareBufferCreation); framework.RegisterTest("Vulkan_MediaCodecSetup", TestAndroidMediaCodecVulkanSetup); framework.RegisterTest("Vulkan_DecodeToSurface", TestVulkanDecodeToSurface); framework.RegisterTest("Vulkan_SurfaceOptimization", TestVulkanSurfaceTypeOptimization); } } // namespace VavCoreTest