Lazy initialization for DLL library
This commit is contained in:
@@ -6,7 +6,11 @@
|
||||
<ItemGroup>
|
||||
<Page Include="MainWindow.xaml" />
|
||||
<Page Include="VideoPlayerControl.xaml" />
|
||||
<Page Include="MultiVideoTestWindow.xaml" />
|
||||
<Page Include="MainVideoPage.xaml" />
|
||||
<Page Include="MultiVideoPage.xaml" />
|
||||
<Page Include="LayeredVideoPage.xaml" />
|
||||
<Page Include="LogMessagePage.xaml" />
|
||||
<Page Include="SettingsPage.xaml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="MainWindow.idl" />
|
||||
@@ -14,12 +18,24 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp" />
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
<ClCompile Include="src\Rendering\D3D12VideoRenderer.cpp" />
|
||||
<ClCompile Include="src\Rendering\GlobalD3D12SyncManager.cpp" />
|
||||
<ClCompile Include="src\Rendering\SimpleGPURenderer.cpp" />
|
||||
<ClCompile Include="src\Logger\LogManager.cpp" />
|
||||
<ClCompile Include="src\Logger\LogOutputs.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="src\Rendering\D3D12VideoRenderer.h" />
|
||||
<ClInclude Include="src\Rendering\SimpleGPURenderer.h" />
|
||||
<ClInclude Include="src\Rendering\GlobalD3D12SyncManager.h" />
|
||||
<ClInclude Include="src\Rendering\d3dx12.h" />
|
||||
<ClInclude Include="src\Rendering\IVideoRenderer.h" />
|
||||
<ClInclude Include="src\Logger\SimpleLogger.h" />
|
||||
<ClInclude Include="src\Logger\ILogManager.h" />
|
||||
<ClInclude Include="src\Logger\ILogOutput.h" />
|
||||
<ClInclude Include="src\Logger\LogManager.h" />
|
||||
<ClInclude Include="src\Logger\LogOutputs.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="Assets\Wide310x150Logo.scale-200.png">
|
||||
|
||||
@@ -45,8 +45,6 @@
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(ProjectDir)lib\</OutDir>
|
||||
<IntDir>$(ProjectDir)obj\$(Configuration)\</IntDir>
|
||||
<TargetName>VavCore-debug</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
@@ -77,6 +75,11 @@
|
||||
<AdditionalDependencies>webm-debug.lib;dav1d-debug.lib;amf-debug.lib;vpld.lib;mfplat.lib;mf.lib;mfuuid.lib;nvcuvid.lib;cuda.lib;d3d11.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(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)</AdditionalLibraryDirectories>
|
||||
</Lib>
|
||||
<PostBuildEvent>
|
||||
<Command>echo Copying VavCore Debug DLL...
|
||||
copy "$(TargetPath)" "$(ProjectDir)lib\$(TargetFileName)"
|
||||
echo DLL copy completed.</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
@@ -90,6 +93,7 @@
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<AdditionalIncludeDirectories>$(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)</AdditionalIncludeDirectories>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
<StringPooling>true</StringPooling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>
|
||||
@@ -99,6 +103,7 @@
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>webm.lib;dav1d.lib;amf.lib;vpl.lib;mfplat.lib;mf.lib;mfuuid.lib;nvcuvid.lib;cuda.lib;d3d11.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(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)</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>/OPT:REF /OPT:ICF=5 /OPT:LBR %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalDependencies>webm.lib;dav1d.lib;amf.lib;vpl.lib;mfplat.lib;mf.lib;mfuuid.lib;nvcuvid.lib;cuda.lib;d3d11.lib;%(AdditionalDependencies)</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"
|
||||
</Command>
|
||||
copy "$(TargetPath)" "$(ProjectDir)lib\$(TargetFileName)"
|
||||
echo "VavCore DLL copied successfully"</Command>
|
||||
<Message>Installing VavCore DLL to Godot extension</Message>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
@@ -137,6 +142,7 @@
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\VavCore.cpp" />
|
||||
<ClCompile Include="src\DllMain.cpp" />
|
||||
<ClCompile Include="src\Decoder\AV1Decoder.cpp" />
|
||||
<ClCompile Include="src\Decoder\AdaptiveAV1Decoder.cpp" />
|
||||
<ClCompile Include="src\Decoder\AdaptiveNVDECDecoder.cpp" />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "pch.h"
|
||||
#include "pch.h"
|
||||
#include <sstream>
|
||||
|
||||
// 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
|
||||
@@ -293,7 +293,5 @@ void RegisterAV1Decoders() {
|
||||
});
|
||||
}
|
||||
|
||||
// Static initialization for auto-registration
|
||||
static bool s_av1_registered = (RegisterAV1Decoders(), true);
|
||||
|
||||
} // namespace VavCore
|
||||
@@ -952,8 +952,6 @@ void RegisterAndroidMediaCodecDecoders() {
|
||||
});
|
||||
}
|
||||
|
||||
// Static initialization for auto-registration (Android only)
|
||||
static bool s_mediacodec_registered = (RegisterAndroidMediaCodecDecoders(), true);
|
||||
|
||||
} // namespace VavCore
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "pch.h"
|
||||
#include "pch.h"
|
||||
#include "MediaFoundationAV1Decoder.h"
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
@@ -689,7 +689,5 @@ void RegisterNVDECDecoders() {
|
||||
});
|
||||
}
|
||||
|
||||
// Static initialization for auto-registration
|
||||
static bool s_nvdec_registered = (RegisterNVDECDecoders(), true);
|
||||
|
||||
} // namespace VavCore
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "pch.h"
|
||||
#include "pch.h"
|
||||
#include "VPLAV1Decoder.h"
|
||||
#include "VideoDecoderFactory.h"
|
||||
#include <iostream>
|
||||
@@ -1019,7 +1019,5 @@ void RegisterVPLDecoders() {
|
||||
});
|
||||
}
|
||||
|
||||
// Static initialization for auto-registration
|
||||
static bool s_vpl_registered = (RegisterVPLDecoders(), true);
|
||||
|
||||
} // namespace VavCore
|
||||
@@ -5,9 +5,6 @@
|
||||
|
||||
namespace VavCore {
|
||||
|
||||
// Static member initialization
|
||||
std::vector<DecoderRegistration> VideoDecoderFactory::s_av1_decoders;
|
||||
std::vector<DecoderRegistration> VideoDecoderFactory::s_vp9_decoders;
|
||||
|
||||
std::unique_ptr<IVideoDecoder> VideoDecoderFactory::CreateDecoder(VideoCodecType codec_type, DecoderType decoder_type) {
|
||||
auto& decoders = GetDecoderList(codec_type);
|
||||
@@ -163,10 +160,11 @@ std::vector<std::string> 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<DecoderRegistration>& VideoDecoderFactory::GetDecoderList(VideoCodecType codec_type) {
|
||||
// Lazy initialization to avoid DLL loading issues
|
||||
static std::vector<DecoderRegistration> s_av1_decoders_local;
|
||||
static std::vector<DecoderRegistration> 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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,9 +67,6 @@ private:
|
||||
VideoDecoderFactory(const VideoDecoderFactory&) = delete;
|
||||
VideoDecoderFactory& operator=(const VideoDecoderFactory&) = delete;
|
||||
|
||||
// Codec-specific registered decoder arrays
|
||||
static std::vector<DecoderRegistration> s_av1_decoders;
|
||||
static std::vector<DecoderRegistration> s_vp9_decoders;
|
||||
|
||||
// Helper functions
|
||||
static std::vector<DecoderRegistration>& GetDecoderList(VideoCodecType codec_type);
|
||||
|
||||
120
vav2/platforms/windows/vavcore/src/DllMain.cpp
Normal file
120
vav2/platforms/windows/vavcore/src/DllMain.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
#include "pch.h"
|
||||
#include <windows.h>
|
||||
#include <iostream>
|
||||
|
||||
// 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;
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user