using System; using System.Runtime.InteropServices; // VavCore Wrapper types - copied from VavCore.Wrapper for standalone testing namespace VavCore.Wrapper { public enum DecoderType { AUTO = 0, DAV1D = 1, NVDEC = 2, VPL = 3, AMF = 4, MEDIA_FOUNDATION = 5 } public enum SurfaceType { None = 0, Vulkan = 1, OpenGL = 2, D3D11 = 3, Metal = 4 } [StructLayout(LayoutKind.Sequential)] public struct PerformanceMetrics { public float CurrentFPS; public uint DroppedFrames; public uint TotalFrames; public float AverageDecodeTime; } public static class VavCore { private const string DllName = "VavCore-debug.dll"; [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr vavcore_get_version_string(); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] private static extern int vavcore_initialize(); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] private static extern void vavcore_cleanup(); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr vavcore_create_player(); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] private static extern void vavcore_destroy_player(IntPtr player); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] private static extern int vavcore_set_decoder_type(IntPtr player, DecoderType decoderType); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] private static extern int vavcore_supports_surface_type(IntPtr player, SurfaceType surfaceType); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] private static extern SurfaceType vavcore_get_optimal_surface_type(IntPtr player); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] private static extern PerformanceMetrics vavcore_get_performance_metrics(IntPtr player); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] private static extern int vavcore_open_file(IntPtr player, [MarshalAs(UnmanagedType.LPStr)] string filePath); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] private static extern void vavcore_close_file(IntPtr player); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] private static extern int vavcore_is_open(IntPtr player); [StructLayout(LayoutKind.Sequential)] public struct VavCoreVideoFrame { // Legacy CPU fields public IntPtr y_plane; // uint8_t* public IntPtr u_plane; // uint8_t* public IntPtr v_plane; // uint8_t* public int y_stride; // int public int u_stride; // int public int v_stride; // int // Frame metadata public int width; // int public int height; // int public ulong timestamp_us; // uint64_t public ulong frame_number; // uint64_t // Surface type public SurfaceType surface_type; // VavCoreSurfaceType // Union - mapped as fixed-size byte array (largest union member is ~64 bytes) [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] public byte[] surface_data; // Union data for all surface types } // Helper structures for accessing union data safely [StructLayout(LayoutKind.Sequential)] public struct D3D11SurfaceData { public IntPtr d3d11_texture; // ID3D11Texture2D* public IntPtr d3d11_device; // ID3D11Device* public uint subresource_index; } [StructLayout(LayoutKind.Sequential)] public struct VulkanSurfaceData { public IntPtr vk_image; // VkImage public IntPtr vk_device; // VkDevice public IntPtr vk_device_memory; // VkDeviceMemory public uint memory_offset; } [StructLayout(LayoutKind.Sequential)] public struct OpenGLSurfaceData { public uint texture_id; // GLuint public uint target; // GL_TEXTURE_2D public IntPtr gl_context; // OpenGL context } [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] private static extern int vavcore_decode_next_frame(IntPtr player, ref VavCoreVideoFrame frame); [StructLayout(LayoutKind.Sequential)] public struct VideoMetadata { public int width; public int height; public double frame_rate; public double duration_seconds; public ulong total_frames; public IntPtr codec_name; // const char* } [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] private static extern int vavcore_get_metadata(IntPtr player, ref VideoMetadata metadata); public static string GetVersion() { IntPtr ptr = vavcore_get_version_string(); return Marshal.PtrToStringAnsi(ptr) ?? "Unknown"; } public static bool Initialize() { return vavcore_initialize() == 0; } public static void Cleanup() { vavcore_cleanup(); } public static IntPtr CreatePlayer() { return vavcore_create_player(); } public static void DestroyPlayer(IntPtr player) { vavcore_destroy_player(player); } public static bool SetDecoderType(IntPtr player, DecoderType decoderType) { return vavcore_set_decoder_type(player, decoderType) == 0; } public static bool SupportsSurfaceType(IntPtr player, SurfaceType surfaceType) { return vavcore_supports_surface_type(player, surfaceType) != 0; } public static SurfaceType GetOptimalSurfaceType(IntPtr player) { return vavcore_get_optimal_surface_type(player); } public static PerformanceMetrics GetPerformanceMetrics(IntPtr player) { return vavcore_get_performance_metrics(player); } public static bool OpenFile(IntPtr player, string filePath) { return vavcore_open_file(player, filePath) == 0; } public static void CloseFile(IntPtr player) { vavcore_close_file(player); } public static bool IsOpen(IntPtr player) { return vavcore_is_open(player) != 0; } public static bool DecodeNextFrame(IntPtr player, ref VavCoreVideoFrame frame) { return vavcore_decode_next_frame(player, ref frame) == 0; } // Helper method to create a properly initialized VavCoreVideoFrame public static VavCoreVideoFrame CreateVideoFrame() { return new VavCoreVideoFrame { y_plane = IntPtr.Zero, u_plane = IntPtr.Zero, v_plane = IntPtr.Zero, y_stride = 0, u_stride = 0, v_stride = 0, width = 0, height = 0, timestamp_us = 0, frame_number = 0, surface_type = SurfaceType.None, surface_data = new byte[64] // Initialize the union data array }; } // Helper method to extract D3D11 surface data from union public static D3D11SurfaceData GetD3D11SurfaceData(VavCoreVideoFrame frame) { if (frame.surface_type != SurfaceType.D3D11 || frame.surface_data == null) return new D3D11SurfaceData(); unsafe { fixed (byte* ptr = frame.surface_data) { return *(D3D11SurfaceData*)ptr; } } } // Helper method to extract Vulkan surface data from union public static VulkanSurfaceData GetVulkanSurfaceData(VavCoreVideoFrame frame) { if (frame.surface_type != SurfaceType.Vulkan || frame.surface_data == null) return new VulkanSurfaceData(); unsafe { fixed (byte* ptr = frame.surface_data) { return *(VulkanSurfaceData*)ptr; } } } // Helper method to extract OpenGL surface data from union public static OpenGLSurfaceData GetOpenGLSurfaceData(VavCoreVideoFrame frame) { if (frame.surface_type != SurfaceType.OpenGL || frame.surface_data == null) return new OpenGLSurfaceData(); unsafe { fixed (byte* ptr = frame.surface_data) { return *(OpenGLSurfaceData*)ptr; } } } public static VideoMetadata GetMetadata(IntPtr player) { var metadata = new VideoMetadata(); int result = vavcore_get_metadata(player, ref metadata); if (result != 0) { throw new InvalidOperationException($"Failed to get metadata, error code: {result}"); } return metadata; } } } // Simple console test to verify VavCore DLL connection class TestVavCoreDLL { static void Main(string[] args) { Console.WriteLine("VavCore DLL Connection Test"); Console.WriteLine("==========================="); try { // Set DLL directory to help find the VavCore DLL string dllPath = @"D:\Project\video-av1\vav2\godot_extension\libs\windows-x86_64"; Environment.SetEnvironmentVariable("PATH", dllPath + ";" + Environment.GetEnvironmentVariable("PATH")); Console.WriteLine($"Looking for VavCore DLL in: {dllPath}"); // Test VavCore DLL connection Console.WriteLine("Testing VavCore DLL connection..."); // Get version string var version = VavCore.Wrapper.VavCore.GetVersion(); Console.WriteLine($"VavCore version: {version}"); // Initialize VavCore Console.WriteLine("Initializing VavCore..."); bool initSuccess = VavCore.Wrapper.VavCore.Initialize(); Console.WriteLine($"VavCore initialization: {(initSuccess ? "SUCCESS" : "FAILED")}"); if (initSuccess) { // Test player creation Console.WriteLine("Creating VavCore player..."); var player = VavCore.Wrapper.VavCore.CreatePlayer(); Console.WriteLine($"Player creation: {(player != IntPtr.Zero ? "SUCCESS" : "FAILED")}"); if (player != IntPtr.Zero) { // Test decoder type setting Console.WriteLine("Setting decoder type to AUTO..."); bool setDecoderSuccess = VavCore.Wrapper.VavCore.SetDecoderType(player, VavCore.Wrapper.DecoderType.AUTO); Console.WriteLine($"Set decoder type: {(setDecoderSuccess ? "SUCCESS" : "FAILED")}"); // Test surface type support Console.WriteLine("Checking Vulkan surface support..."); bool vulkanSupported = VavCore.Wrapper.VavCore.SupportsSurfaceType(player, VavCore.Wrapper.SurfaceType.Vulkan); Console.WriteLine($"Vulkan surface support: {(vulkanSupported ? "SUPPORTED" : "NOT SUPPORTED")}"); Console.WriteLine("Checking D3D11 surface support..."); bool d3d11Supported = VavCore.Wrapper.VavCore.SupportsSurfaceType(player, VavCore.Wrapper.SurfaceType.D3D11); Console.WriteLine($"D3D11 surface support: {(d3d11Supported ? "SUPPORTED" : "NOT SUPPORTED")}"); // Get optimal surface type Console.WriteLine("Getting optimal surface type..."); var optimalSurface = VavCore.Wrapper.VavCore.GetOptimalSurfaceType(player); Console.WriteLine($"Optimal surface type: {optimalSurface}"); // Test performance metrics Console.WriteLine("Getting performance metrics..."); var metrics = VavCore.Wrapper.VavCore.GetPerformanceMetrics(player); Console.WriteLine($"Performance metrics - FPS: {metrics.CurrentFPS:F2}, Dropped: {metrics.DroppedFrames}"); // Keep the player for video decoding test Console.WriteLine("Keeping player for video decoding test..."); } Console.WriteLine("\n=== VavCore DLL Connection Test COMPLETED SUCCESSFULLY ==="); // Now test actual AV1 video file decoding using the same player Console.WriteLine("\n" + new string('=', 50)); Console.WriteLine("TESTING REAL AV1 VIDEO FILE DECODING"); Console.WriteLine(new string('=', 50)); TestAV1VideoDecoding(player); // Clean up player after all tests Console.WriteLine("Destroying player..."); VavCore.Wrapper.VavCore.DestroyPlayer(player); Console.WriteLine("Player destroyed"); } // Clean up VavCore Console.WriteLine("Cleaning up VavCore..."); VavCore.Wrapper.VavCore.Cleanup(); Console.WriteLine("VavCore cleanup completed"); } catch (Exception ex) { Console.WriteLine($"\n=== VavCore DLL Connection Test FAILED ==="); Console.WriteLine($"Error: {ex.Message}"); Console.WriteLine($"Stack trace: {ex.StackTrace}"); return; } Console.WriteLine("\nPress any key to exit..."); Console.ReadKey(); } static void TestAV1VideoDecoding(IntPtr player) { try { // Test with available AV1 video files string[] testFiles = { @"D:\Project\video-av1\sample\simple_test.webm", @"D:\Project\video-av1\sample\output.webm" }; foreach (string testFile in testFiles) { Console.WriteLine($"\nTesting video file: {System.IO.Path.GetFileName(testFile)}"); if (!System.IO.File.Exists(testFile)) { Console.WriteLine($"File not found: {testFile}"); continue; } // Try to open the video file Console.WriteLine("Opening video file..."); bool openSuccess = VavCore.Wrapper.VavCore.OpenFile(player, testFile); Console.WriteLine($"File open: {(openSuccess ? "SUCCESS" : "FAILED")}"); if (openSuccess) { // Check if file is properly opened bool isOpen = VavCore.Wrapper.VavCore.IsOpen(player); Console.WriteLine($"File is open: {isOpen}"); if (isOpen) { try { // Get video metadata Console.WriteLine("Getting video metadata..."); var metadata = VavCore.Wrapper.VavCore.GetMetadata(player); Console.WriteLine($"Video dimensions: {metadata.width}x{metadata.height}"); Console.WriteLine($"Framerate: {metadata.frame_rate:F2} fps"); Console.WriteLine($"Duration: {metadata.duration_seconds:F2} seconds"); Console.WriteLine($"Total frames: {metadata.total_frames}"); string codecName = metadata.codec_name != IntPtr.Zero ? Marshal.PtrToStringAnsi(metadata.codec_name) ?? "Unknown" : "Unknown"; Console.WriteLine($"Codec: {codecName}"); // Try to decode a few frames with the proper VideoFrame structure Console.WriteLine("Testing frame decoding..."); try { for (int frameIndex = 0; frameIndex < 3; frameIndex++) { var frame = VavCore.Wrapper.VavCore.CreateVideoFrame(); bool decodeSuccess = VavCore.Wrapper.VavCore.DecodeNextFrame(player, ref frame); if (decodeSuccess) { Console.WriteLine($"Frame {frameIndex + 1}: {frame.width}x{frame.height}, " + $"timestamp: {frame.timestamp_us}us, " + $"surface_type: {frame.surface_type}"); // Check CPU plane data availability if (frame.surface_type == VavCore.Wrapper.SurfaceType.None && frame.y_plane != IntPtr.Zero) { Console.WriteLine($" CPU YUV data - Y stride: {frame.y_stride}, " + $"U stride: {frame.u_stride}, V stride: {frame.v_stride}"); } } else { Console.WriteLine($"Frame {frameIndex + 1}: Decode failed"); break; } } Console.WriteLine("Frame decoding test completed successfully"); } catch (Exception decodeEx) { Console.WriteLine($"Frame decoding error: {decodeEx.Message}"); } // Get updated performance metrics Console.WriteLine("Getting updated performance metrics..."); var metrics = VavCore.Wrapper.VavCore.GetPerformanceMetrics(player); Console.WriteLine($"Performance metrics - FPS: {metrics.CurrentFPS:F2}, Dropped: {metrics.DroppedFrames}, Total: {metrics.TotalFrames}"); } catch (Exception ex) { Console.WriteLine($"Error during video processing: {ex.Message}"); } } // Close the file Console.WriteLine("Closing video file..."); VavCore.Wrapper.VavCore.CloseFile(player); bool isStillOpen = VavCore.Wrapper.VavCore.IsOpen(player); Console.WriteLine($"File closed successfully: {!isStillOpen}"); } Console.WriteLine($"Completed test for: {System.IO.Path.GetFileName(testFile)}"); Console.WriteLine(new string('-', 40)); } Console.WriteLine("\n=== AV1 Video Decoding Test COMPLETED ==="); } catch (Exception ex) { Console.WriteLine($"\n=== AV1 Video Decoding Test FAILED ==="); Console.WriteLine($"Error: {ex.Message}"); Console.WriteLine($"Stack trace: {ex.StackTrace}"); } } }