From 5d70d9d3d29125e2fd09166257a1b760c175ead3 Mon Sep 17 00:00:00 2001 From: ened Date: Sun, 28 Sep 2025 19:41:58 +0900 Subject: [PATCH] Lazy initialization for DLL library --- .../Vav2Player/Vav2Player.vcxproj.filters | 18 ++- .../platforms/windows/vavcore/VavCore.vcxproj | 14 +- .../vavcore/src/Decoder/AMFAV1Decoder.cpp | 11 +- .../vavcore/src/Decoder/AV1Decoder.cpp | 2 - .../Decoder/AndroidMediaCodecAV1Decoder.cpp | 2 - .../src/Decoder/MediaFoundationAV1Decoder.cpp | 2 +- .../vavcore/src/Decoder/NVDECAV1Decoder.cpp | 2 - .../vavcore/src/Decoder/VPLAV1Decoder.cpp | 4 +- .../src/Decoder/VideoDecoderFactory.cpp | 27 ++-- .../vavcore/src/Decoder/VideoDecoderFactory.h | 3 - .../platforms/windows/vavcore/src/DllMain.cpp | 120 ++++++++++++++++++ .../platforms/windows/vavcore/src/VavCore.cpp | 34 +++-- 12 files changed, 181 insertions(+), 58 deletions(-) create mode 100644 vav2/platforms/windows/vavcore/src/DllMain.cpp diff --git a/vav2/platforms/windows/applications/vav2player/Vav2Player/Vav2Player.vcxproj.filters b/vav2/platforms/windows/applications/vav2player/Vav2Player/Vav2Player.vcxproj.filters index e50056f..362f95a 100644 --- a/vav2/platforms/windows/applications/vav2player/Vav2Player/Vav2Player.vcxproj.filters +++ b/vav2/platforms/windows/applications/vav2player/Vav2Player/Vav2Player.vcxproj.filters @@ -6,7 +6,11 @@ - + + + + + @@ -14,12 +18,24 @@ + + + + + + + + + + + + diff --git a/vav2/platforms/windows/vavcore/VavCore.vcxproj b/vav2/platforms/windows/vavcore/VavCore.vcxproj index c15272d..ff3d742 100644 --- a/vav2/platforms/windows/vavcore/VavCore.vcxproj +++ b/vav2/platforms/windows/vavcore/VavCore.vcxproj @@ -45,8 +45,6 @@ true - $(ProjectDir)lib\ - $(ProjectDir)obj\$(Configuration)\ VavCore-debug @@ -77,6 +75,11 @@ webm-debug.lib;dav1d-debug.lib;amf-debug.lib;vpld.lib;mfplat.lib;mf.lib;mfuuid.lib;nvcuvid.lib;cuda.lib;d3d11.lib;%(AdditionalDependencies) $(ProjectDir)..\..\..\..\lib\libwebm;$(ProjectDir)..\..\..\..\lib\dav1d;$(ProjectDir)..\..\..\..\lib\amf;$(ProjectDir)..\..\..\..\lib\libvpl;$(ProjectDir)..\..\..\..\oss\nvidia-video-codec\Lib\x64;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.0\lib\x64;%(AdditionalLibraryDirectories) + + echo Copying VavCore Debug DLL... +copy "$(TargetPath)" "$(ProjectDir)lib\$(TargetFileName)" +echo DLL copy completed. + @@ -90,6 +93,7 @@ pch.h $(ProjectDir)include;$(ProjectDir)..\..\..\..\include\libwebm;$(ProjectDir)..\..\..\..\include\dav1d;$(ProjectDir)..\..\..\..\include\amf;$(ProjectDir)..\..\..\..\include\libvpl;$(ProjectDir)..\..\..\..\oss\nvidia-video-codec\Interface;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.0\include;%(AdditionalIncludeDirectories) stdcpp20 + true @@ -99,6 +103,7 @@ true webm.lib;dav1d.lib;amf.lib;vpl.lib;mfplat.lib;mf.lib;mfuuid.lib;nvcuvid.lib;cuda.lib;d3d11.lib;%(AdditionalDependencies) $(ProjectDir)..\..\..\..\lib\libwebm;$(ProjectDir)..\..\..\..\lib\dav1d;$(ProjectDir)..\..\..\..\lib\amf;$(ProjectDir)..\..\..\..\lib\libvpl;$(ProjectDir)..\..\..\..\oss\nvidia-video-codec\Lib\x64;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.0\lib\x64;%(AdditionalLibraryDirectories) + /OPT:REF /OPT:ICF=5 /OPT:LBR %(AdditionalOptions) webm.lib;dav1d.lib;amf.lib;vpl.lib;mfplat.lib;mf.lib;mfuuid.lib;nvcuvid.lib;cuda.lib;d3d11.lib;%(AdditionalDependencies) @@ -109,8 +114,8 @@ echo "Copying VavCore DLL to Godot extension directory..." if not exist "$(ProjectDir)..\godot-plugin\libs\windows-x86_64\" mkdir "$(ProjectDir)..\godot-plugin\libs\windows-x86_64\" copy "$(TargetPath)" "$(ProjectDir)..\godot-plugin\libs\windows-x86_64\" - echo "VavCore DLL copied successfully" - + copy "$(TargetPath)" "$(ProjectDir)lib\$(TargetFileName)" + echo "VavCore DLL copied successfully" Installing VavCore DLL to Godot extension @@ -137,6 +142,7 @@ Create + diff --git a/vav2/platforms/windows/vavcore/src/Decoder/AMFAV1Decoder.cpp b/vav2/platforms/windows/vavcore/src/Decoder/AMFAV1Decoder.cpp index 5dc368c..898e8a5 100644 --- a/vav2/platforms/windows/vavcore/src/Decoder/AMFAV1Decoder.cpp +++ b/vav2/platforms/windows/vavcore/src/Decoder/AMFAV1Decoder.cpp @@ -1,4 +1,4 @@ -#include "pch.h" +#include "pch.h" #include // MUST follow header include order to avoid build error @@ -869,14 +869,5 @@ void RegisterAMFDecoders() { }); } -// Static initialization for registration -namespace { - struct AMFDecoderRegistration { - AMFDecoderRegistration() { - RegisterAMFDecoders(); - } - }; - static AMFDecoderRegistration s_amfRegistration; -} } // namespace VavCore \ No newline at end of file diff --git a/vav2/platforms/windows/vavcore/src/Decoder/AV1Decoder.cpp b/vav2/platforms/windows/vavcore/src/Decoder/AV1Decoder.cpp index 28f4123..32d39f3 100644 --- a/vav2/platforms/windows/vavcore/src/Decoder/AV1Decoder.cpp +++ b/vav2/platforms/windows/vavcore/src/Decoder/AV1Decoder.cpp @@ -293,7 +293,5 @@ void RegisterAV1Decoders() { }); } -// Static initialization for auto-registration -static bool s_av1_registered = (RegisterAV1Decoders(), true); } // namespace VavCore \ No newline at end of file diff --git a/vav2/platforms/windows/vavcore/src/Decoder/AndroidMediaCodecAV1Decoder.cpp b/vav2/platforms/windows/vavcore/src/Decoder/AndroidMediaCodecAV1Decoder.cpp index 4be9c88..1e117c1 100644 --- a/vav2/platforms/windows/vavcore/src/Decoder/AndroidMediaCodecAV1Decoder.cpp +++ b/vav2/platforms/windows/vavcore/src/Decoder/AndroidMediaCodecAV1Decoder.cpp @@ -952,8 +952,6 @@ void RegisterAndroidMediaCodecDecoders() { }); } -// Static initialization for auto-registration (Android only) -static bool s_mediacodec_registered = (RegisterAndroidMediaCodecDecoders(), true); } // namespace VavCore diff --git a/vav2/platforms/windows/vavcore/src/Decoder/MediaFoundationAV1Decoder.cpp b/vav2/platforms/windows/vavcore/src/Decoder/MediaFoundationAV1Decoder.cpp index 6209922..0d1cdae 100644 --- a/vav2/platforms/windows/vavcore/src/Decoder/MediaFoundationAV1Decoder.cpp +++ b/vav2/platforms/windows/vavcore/src/Decoder/MediaFoundationAV1Decoder.cpp @@ -1,4 +1,4 @@ -#include "pch.h" +#include "pch.h" #include "MediaFoundationAV1Decoder.h" #include #include diff --git a/vav2/platforms/windows/vavcore/src/Decoder/NVDECAV1Decoder.cpp b/vav2/platforms/windows/vavcore/src/Decoder/NVDECAV1Decoder.cpp index fef4551..9d17915 100644 --- a/vav2/platforms/windows/vavcore/src/Decoder/NVDECAV1Decoder.cpp +++ b/vav2/platforms/windows/vavcore/src/Decoder/NVDECAV1Decoder.cpp @@ -689,7 +689,5 @@ void RegisterNVDECDecoders() { }); } -// Static initialization for auto-registration -static bool s_nvdec_registered = (RegisterNVDECDecoders(), true); } // namespace VavCore \ No newline at end of file diff --git a/vav2/platforms/windows/vavcore/src/Decoder/VPLAV1Decoder.cpp b/vav2/platforms/windows/vavcore/src/Decoder/VPLAV1Decoder.cpp index 74a6916..f663ad5 100644 --- a/vav2/platforms/windows/vavcore/src/Decoder/VPLAV1Decoder.cpp +++ b/vav2/platforms/windows/vavcore/src/Decoder/VPLAV1Decoder.cpp @@ -1,4 +1,4 @@ -#include "pch.h" +#include "pch.h" #include "VPLAV1Decoder.h" #include "VideoDecoderFactory.h" #include @@ -1019,7 +1019,5 @@ void RegisterVPLDecoders() { }); } -// Static initialization for auto-registration -static bool s_vpl_registered = (RegisterVPLDecoders(), true); } // namespace VavCore \ No newline at end of file diff --git a/vav2/platforms/windows/vavcore/src/Decoder/VideoDecoderFactory.cpp b/vav2/platforms/windows/vavcore/src/Decoder/VideoDecoderFactory.cpp index 3c4b7d6..700fe54 100644 --- a/vav2/platforms/windows/vavcore/src/Decoder/VideoDecoderFactory.cpp +++ b/vav2/platforms/windows/vavcore/src/Decoder/VideoDecoderFactory.cpp @@ -5,9 +5,6 @@ namespace VavCore { -// Static member initialization -std::vector VideoDecoderFactory::s_av1_decoders; -std::vector VideoDecoderFactory::s_vp9_decoders; std::unique_ptr VideoDecoderFactory::CreateDecoder(VideoCodecType codec_type, DecoderType decoder_type) { auto& decoders = GetDecoderList(codec_type); @@ -163,10 +160,11 @@ std::vector VideoDecoderFactory::GetAvailableDecoders(VideoCodecTyp } void VideoDecoderFactory::RegisterAV1Decoder(const DecoderRegistration& registration) { - s_av1_decoders.push_back(registration); + auto& decoders = GetDecoderList(VideoCodecType::AV1); + decoders.push_back(registration); // Sort by priority (lower numbers = higher priority) - std::sort(s_av1_decoders.begin(), s_av1_decoders.end(), [](const auto& a, const auto& b) { + std::sort(decoders.begin(), decoders.end(), [](const auto& a, const auto& b) { return a.priority < b.priority; }); @@ -175,10 +173,11 @@ void VideoDecoderFactory::RegisterAV1Decoder(const DecoderRegistration& registra } void VideoDecoderFactory::RegisterVP9Decoder(const DecoderRegistration& registration) { - s_vp9_decoders.push_back(registration); + auto& decoders = GetDecoderList(VideoCodecType::VP9); + decoders.push_back(registration); // Sort by priority (lower numbers = higher priority) - std::sort(s_vp9_decoders.begin(), s_vp9_decoders.end(), [](const auto& a, const auto& b) { + std::sort(decoders.begin(), decoders.end(), [](const auto& a, const auto& b) { return a.priority < b.priority; }); @@ -236,8 +235,8 @@ void VideoDecoderFactory::InitializeFactory() { void VideoDecoderFactory::CleanupFactory() { // Clear all registrations - s_av1_decoders.clear(); - s_vp9_decoders.clear(); + GetDecoderList(VideoCodecType::AV1).clear(); + GetDecoderList(VideoCodecType::VP9).clear(); std::cout << "[VideoDecoderFactory] Factory cleanup completed" << std::endl; } @@ -252,13 +251,17 @@ VideoCodecType VideoDecoderFactory::DetectCodecTypeFromId(const std::string& cod } std::vector& VideoDecoderFactory::GetDecoderList(VideoCodecType codec_type) { + // Lazy initialization to avoid DLL loading issues + static std::vector s_av1_decoders_local; + static std::vector s_vp9_decoders_local; + switch (codec_type) { case VideoCodecType::AV1: - return s_av1_decoders; + return s_av1_decoders_local; case VideoCodecType::VP9: - return s_vp9_decoders; + return s_vp9_decoders_local; default: - return s_av1_decoders; // Default to AV1 + return s_av1_decoders_local; // Default to AV1 } } diff --git a/vav2/platforms/windows/vavcore/src/Decoder/VideoDecoderFactory.h b/vav2/platforms/windows/vavcore/src/Decoder/VideoDecoderFactory.h index 5476516..8b5b1f3 100644 --- a/vav2/platforms/windows/vavcore/src/Decoder/VideoDecoderFactory.h +++ b/vav2/platforms/windows/vavcore/src/Decoder/VideoDecoderFactory.h @@ -67,9 +67,6 @@ private: VideoDecoderFactory(const VideoDecoderFactory&) = delete; VideoDecoderFactory& operator=(const VideoDecoderFactory&) = delete; - // Codec-specific registered decoder arrays - static std::vector s_av1_decoders; - static std::vector s_vp9_decoders; // Helper functions static std::vector& GetDecoderList(VideoCodecType codec_type); diff --git a/vav2/platforms/windows/vavcore/src/DllMain.cpp b/vav2/platforms/windows/vavcore/src/DllMain.cpp new file mode 100644 index 0000000..67b0db2 --- /dev/null +++ b/vav2/platforms/windows/vavcore/src/DllMain.cpp @@ -0,0 +1,120 @@ +#include "pch.h" +#include +#include + +// Forward declarations for decoder registration functions +namespace VavCore { + extern void RegisterAV1Decoders(); + extern void RegisterNVDECDecoders(); + extern void RegisterVPLDecoders(); + extern void RegisterAMFDecoders(); +} + +// Global state for DLL-level initialization +static bool g_dll_initialized = false; +static CRITICAL_SECTION g_dll_cs; + +// Safe initialization flag - only allow initialization once per process +static bool g_safe_to_initialize = false; + +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + { + // Initialize critical section for thread safety + InitializeCriticalSection(&g_dll_cs); + + // Mark that we're ready for safe initialization + g_safe_to_initialize = true; + + std::cout << "[DllMain] VavCore.dll loaded - Process Attach" << std::endl; + std::cout << "[DllMain] Safe to initialize: Ready for vavcore_initialize() call" << std::endl; + } + break; + + case DLL_THREAD_ATTACH: + // Thread-specific initialization if needed + break; + + case DLL_THREAD_DETACH: + // Thread-specific cleanup if needed + break; + + case DLL_PROCESS_DETACH: + { + EnterCriticalSection(&g_dll_cs); + + if (g_dll_initialized) { + std::cout << "[DllMain] VavCore.dll unloading - cleaning up decoders" << std::endl; + + // Cleanup all decoder registrations + // Note: We don't call VideoDecoderFactory::CleanupFactory() here + // because it might cause issues during DLL unload + + g_dll_initialized = false; + } + + g_safe_to_initialize = false; + LeaveCriticalSection(&g_dll_cs); + DeleteCriticalSection(&g_dll_cs); + + std::cout << "[DllMain] VavCore.dll unloaded - Process Detach" << std::endl; + } + break; + } + return TRUE; +} + +// Safe initialization function called from vavcore_initialize() +extern "C" bool PerformSafeDllInitialization() +{ + EnterCriticalSection(&g_dll_cs); + + bool result = false; + + if (!g_safe_to_initialize) { + std::cout << "[DllMain] ERROR: DLL not ready for initialization" << std::endl; + LeaveCriticalSection(&g_dll_cs); + return false; + } + + if (g_dll_initialized) { + std::cout << "[DllMain] Already initialized, skipping" << std::endl; + result = true; + } + else { + try { + std::cout << "[DllMain] Performing safe decoder registration..." << std::endl; + + // Register all decoders in safe runtime environment + VavCore::RegisterAV1Decoders(); + VavCore::RegisterNVDECDecoders(); + VavCore::RegisterVPLDecoders(); + VavCore::RegisterAMFDecoders(); + + g_dll_initialized = true; + result = true; + + std::cout << "[DllMain] Safe decoder registration completed successfully" << std::endl; + } + catch (const std::exception& e) { + std::cout << "[DllMain] ERROR during initialization: " << e.what() << std::endl; + result = false; + } + catch (...) { + std::cout << "[DllMain] ERROR: Unknown exception during initialization" << std::endl; + result = false; + } + } + + LeaveCriticalSection(&g_dll_cs); + return result; +} + +// Check if DLL is ready for safe operations +extern "C" bool IsDllReadyForInitialization() +{ + return g_safe_to_initialize; +} \ No newline at end of file diff --git a/vav2/platforms/windows/vavcore/src/VavCore.cpp b/vav2/platforms/windows/vavcore/src/VavCore.cpp index 8377ebf..1c2465f 100644 --- a/vav2/platforms/windows/vavcore/src/VavCore.cpp +++ b/vav2/platforms/windows/vavcore/src/VavCore.cpp @@ -14,13 +14,9 @@ // Use VavCore namespace internally using namespace VavCore; -// Forward declarations for decoder registration functions -namespace VavCore { - extern void RegisterAV1Decoders(); - extern void RegisterNVDECDecoders(); - extern void RegisterVPLDecoders(); - extern void RegisterAMFDecoders(); -} +// Forward declarations for DllMain-based initialization +extern "C" bool PerformSafeDllInitialization(); +extern "C" bool IsDllReadyForInitialization(); // Global state static bool g_initialized = false; @@ -164,19 +160,21 @@ VAVCORE_API VavCoreResult vavcore_initialize(void) { return VAVCORE_SUCCESS; } - try { - // Initialize decoder factories and other subsystems - // Force decoder registration (in case static initialization fails) - RegisterAV1Decoders(); - RegisterNVDECDecoders(); - RegisterVPLDecoders(); - RegisterAMFDecoders(); - - g_initialized = true; - return VAVCORE_SUCCESS; - } catch (...) { + // Check if DLL is ready for safe initialization + if (!IsDllReadyForInitialization()) { + std::cout << "[vavcore_initialize] ERROR: DLL not ready for initialization" << std::endl; return VAVCORE_ERROR_INIT_FAILED; } + + // Perform safe DLL-level initialization + if (!PerformSafeDllInitialization()) { + std::cout << "[vavcore_initialize] ERROR: Safe DLL initialization failed" << std::endl; + return VAVCORE_ERROR_INIT_FAILED; + } + + std::cout << "[vavcore_initialize] VavCore initialization completed successfully" << std::endl; + g_initialized = true; + return VAVCORE_SUCCESS; } VAVCORE_API void vavcore_cleanup(void) {