Files
video-v1/vav2/platforms/windows/godot-plugin/README.md

12 KiB

VavCore Godot 4.x Extension

Cross-platform C# extension for hardware-accelerated AV1 video decoding in Godot 4.x using VavCore library.

🎯 Features

🚀 Hardware-Accelerated AV1 Decoding

  • Windows: NVIDIA NVDEC, Intel VPL, AMD AMF, Media Foundation
  • Linux: NVIDIA NVDEC, Intel VPL, AMD AMF, dav1d fallback
  • macOS: VideoToolbox, dav1d fallback
  • Android: MediaCodec, dav1d fallback (via Android plugin)
  • iOS: VideoToolbox, dav1d fallback

🎮 Godot 4.x Integration

  • High-level Nodes: Easy-to-use video player components
  • Low-level API: Direct decoder control for advanced use cases
  • Resource System: Godot-native video file and settings resources
  • Editor Integration: Asset importers, custom inspectors, dock widgets

🔧 Cross-Platform Architecture

  • VavCore.Wrapper: P/Invoke layer for C API access
  • VavCore.Godot: Godot-specific nodes and utilities
  • Platform Plugins: Native Android/iOS integration when needed

📁 Project Structure

vav2/godot_extension/
├── VavCoreGodot.sln                 # Visual Studio solution
├── src/
│   ├── VavCore.Wrapper/             # P/Invoke wrapper library
│   │   ├── VavCore.Wrapper.csproj   # .NET 6.0 library project
│   │   ├── VavCoreTypes.cs          # C# data types matching C API
│   │   ├── VavCoreNative.cs         # P/Invoke declarations
│   │   └── VavCoreWrapper.cs        # High-level C# wrapper
│   └── VavCore.Godot/               # Godot extension library
│       ├── VavCore.Godot.csproj     # Godot 4.x project
│       ├── Nodes/                   # Godot nodes
│       │   ├── VavCoreVideoPlayer.cs    # High-level video player
│       │   ├── VavCoreVideoTexture.cs   # Video texture with YUV conversion
│       │   └── VavCoreVideoStream.cs    # Low-level stream control
│       ├── Resources/               # Godot resources
│       │   ├── VavCoreVideoFile.cs      # Video file metadata resource
│       │   └── VavCoreDecoderSettings.cs # Decoder configuration resource
│       ├── Utilities/               # Helper utilities
│       │   ├── VavCoreGodotUtils.cs     # Platform detection and optimization
│       │   └── VavCoreImageConverter.cs # Optimized YUV→RGB conversion
│       └── Plugin/                  # Editor integration
│           └── VavCorePlugin.cs         # Editor plugin and importers
├── libs/                            # Native library binaries
│   ├── windows-x86_64/             # Windows VavCore.dll
│   ├── linux-x86_64/               # Linux libVavCore.so
│   └── osx-x86_64/                 # macOS libVavCore.dylib
└── README.md                       # This file

🚀 Getting Started

1. Prerequisites

  • Godot 4.2.1+ with C# support
  • .NET 6.0 SDK or higher
  • Visual Studio 2022 or VS Code with C# extension
  • VavCore library binaries for your platform
  • VavCore C API implementation (vavcore_* functions)

2. Building the Extension

# Clone or navigate to the extension directory
cd vav2/godot_extension/

# Restore NuGet packages
dotnet restore

# Build the solution
dotnet build --configuration Release

# Or build specific projects
dotnet build src/VavCore.Wrapper/VavCore.Wrapper.csproj --configuration Release
dotnet build src/VavCore.Godot/VavCore.Godot.csproj --configuration Release

3. Installing in Godot Project

Option A: Add as Project Reference

<!-- In your Godot project's .csproj file -->
<ItemGroup>
  <ProjectReference Include="path/to/vav2/godot_extension/src/VavCore.Godot/VavCore.Godot.csproj" />
</ItemGroup>

Option B: Copy Built Assemblies

# Copy built DLLs to your Godot project
cp src/VavCore.Wrapper/bin/Release/net6.0/VavCore.Wrapper.dll /path/to/godot/project/
cp src/VavCore.Godot/bin/Release/net6.0/VavCore.Godot.dll /path/to/godot/project/

# Copy native libraries
cp libs/windows-x86_64/* /path/to/godot/project/  # Windows
cp libs/linux-x86_64/* /path/to/godot/project/    # Linux
cp libs/osx-x86_64/* /path/to/godot/project/      # macOS

🎮 Usage Examples

Simple Video Player

using Godot;
using VavCore.Wrapper;

public partial class MyVideoPlayer : Control
{
    private VavCoreWrapper _player;

    public override void _Ready()
    {
        // Initialize VavCore library
        if (!VavCoreWrapper.Initialize())
        {
            GD.PrintErr("Failed to initialize VavCore");
            return;
        }

        // Create video player
        _player = new VavCoreWrapper();

        // Open and play video
        if (_player.OpenFile("res://videos/sample.webm"))
        {
            // Get metadata
            if (_player.GetMetadata(out var metadata))
            {
                GD.Print($"Video: {metadata.Width}x{metadata.Height}, {metadata.DurationSeconds:F2}s");
            }

            // Decode frames
            DecodeFrames();
        }
    }

    private void DecodeFrames()
    {
        while (!_player.IsEndOfFile)
        {
            if (_player.DecodeNextFrame(out var frame))
            {
                GD.Print($"Decoded frame {frame.FrameNumber}: {frame.Width}x{frame.Height}");

                // Convert to RGB if needed
                // VavCoreWrapper.ConvertYuvToRgb(frame, rgbBuffer, stride);
            }
        }
    }

    public override void _ExitTree()
    {
        _player?.Dispose();
        VavCoreWrapper.Cleanup();
    }
}

Advanced Stream Control

using VavCore.Godot.Nodes;
using VavCore.Wrapper;

public partial class AdvancedVideoControl : Node
{
    private VavCoreVideoStream _videoStream;

    public override void _Ready()
    {
        _videoStream = new VavCoreVideoStream();

        // Connect to low-level events
        _videoStream.PacketRead += OnPacketRead;
        _videoStream.FrameDecoded += OnFrameDecoded;
        _videoStream.StreamError += OnStreamError;

        // Open stream with specific decoder
        _videoStream.OpenStream("res://videos/4k_video.webm", VavCoreTypes.DecoderType.NVDEC);
    }

    private void DecodeManualFrame()
    {
        // Manual frame-by-frame decoding
        if (_videoStream.ReadNextPacket(out var packet))
        {
            if (_videoStream.DecodePacket(packet, out var frame))
            {
                // Process decoded frame
                GD.Print($"Decoded frame {frame.FrameIndex}: {frame.Width}x{frame.Height}");
            }
        }
    }

    private void OnPacketRead(ulong frameIndex, double timestamp, uint packetSize)
    {
        GD.Print($"Read packet {frameIndex}: {packetSize} bytes at {timestamp:F3}s");
    }

    private void OnFrameDecoded(ulong frameIndex, double timestamp, Vector2I resolution)
    {
        GD.Print($"Decoded frame {frameIndex}: {resolution.X}x{resolution.Y} at {timestamp:F3}s");
    }

    private void OnStreamError(string errorMessage)
    {
        GD.PrintErr($"Stream error: {errorMessage}");
    }
}

Custom Decoder Settings

using VavCore.Godot.Resources;

public partial class VideoSettings : Control
{
    public override void _Ready()
    {
        // Create optimal settings for current platform
        var settings = VavCore.Godot.Utilities.VavCoreGodotUtils.CreateOptimalSettings();

        // Customize settings
        settings.PreferredDecoderType = VavCoreTypes.DecoderType.NVDEC;
        settings.EnableHardwareAcceleration = true;
        settings.MaxFrameBufferSize = 15;
        settings.EnableZeroCopyDecoding = true;

        // Apply quality preset
        settings.ApplyPreset(VavCoreDecoderSettings.QualityPreset.Ultra);

        // Save settings as resource
        ResourceSaver.Save(settings, "user://vavcore_settings.tres");

        // Load settings
        var loadedSettings = GD.Load<VavCoreDecoderSettings>("user://vavcore_settings.tres");
    }
}

Video File Metadata

using VavCore.Godot.Resources;

public partial class VideoMetadata : Control
{
    public override void _Ready()
    {
        // Create video file resource
        var videoFile = new VavCoreVideoFile("res://videos/sample.webm");

        if (videoFile.IsValid)
        {
            // Access metadata
            GD.Print($"Resolution: {videoFile.VideoWidth}x{videoFile.VideoHeight}");
            GD.Print($"Duration: {videoFile.DurationSeconds:F2} seconds");
            GD.Print($"Frame rate: {videoFile.FrameRate:F2} FPS");
            GD.Print($"Codec: {videoFile.CodecType}");
            GD.Print($"File size: {videoFile.GetFormattedFileSize()}");

            // Get detailed info
            var info = videoFile.GetVideoInfo();
            foreach (var key in info.Keys)
            {
                GD.Print($"{key}: {info[key]}");
            }

            // Check decoder compatibility
            var compatibleDecoders = videoFile.GetCompatibleDecoders();
            GD.Print($"Compatible decoders: {string.Join(", ", compatibleDecoders)}");

            var recommendedDecoder = videoFile.GetRecommendedDecoder();
            GD.Print($"Recommended decoder: {recommendedDecoder}");
        }
        else
        {
            GD.PrintErr($"Invalid video file: {videoFile.ErrorMessage}");
        }
    }
}

🔧 Configuration

Decoder Settings Presets

// Ultra Quality (High-end systems)
settings.ApplyPreset(VavCoreDecoderSettings.QualityPreset.Ultra);

// High Quality (Gaming systems)
settings.ApplyPreset(VavCoreDecoderSettings.QualityPreset.High);

// Balanced (Most systems)
settings.ApplyPreset(VavCoreDecoderSettings.QualityPreset.Balanced);

// Performance (Lower-end systems)
settings.ApplyPreset(VavCoreDecoderSettings.QualityPreset.Performance);

// Power Saver (Mobile/battery)
settings.ApplyPreset(VavCoreDecoderSettings.QualityPreset.PowerSaver);

Platform-Specific Optimization

// Get platform information
var platformInfo = VavCoreGodotUtils.GetPlatformInfo();
GD.Print($"Platform: {platformInfo["platform"]}");
GD.Print($"Optimal decoder: {platformInfo["optimal_decoder"]}");
GD.Print($"Hardware acceleration: {platformInfo["hardware_acceleration"]}");

// Check hardware acceleration support
bool hwSupported = VavCoreGodotUtils.IsHardwareAccelerationSupported();
string perfCategory = VavCoreGodotUtils.GetPerformanceCategory();
string optimalAPI = VavCoreGodotUtils.GetOptimalGraphicsAPI();

// Validate video file
var (isValid, errorMessage) = VavCoreGodotUtils.ValidateVideoFile("path/to/video.webm");

📊 Performance Monitoring

// Get performance statistics
var stats = videoPlayer.GetPerformanceStats();
GD.Print($"Frames decoded: {stats["frames_decoded"]}");
GD.Print($"Frames dropped: {stats["frames_dropped"]}");
GD.Print($"Average decode time: {stats["avg_decode_time_ms"]} ms");

// Format stats for display
string formattedStats = VavCoreGodotUtils.FormatPerformanceStats(stats);
GD.Print(formattedStats);

// Monitor hardware capabilities
var capabilities = videoPlayer.GetHardwareCapabilities();
GD.Print($"Hardware acceleration: {capabilities["hardware_acceleration"]}");
GD.Print($"Zero-copy decoding: {capabilities["zero_copy_decoding"]}");

🐛 Troubleshooting

Common Issues

  1. VavCore library not found

    Error: Could not load VavCore.dll/libVavCore.so
    Solution: Ensure native libraries are in the correct path
    
  2. Hardware acceleration not available

    Check: VavCoreGodotUtils.IsHardwareAccelerationSupported()
    Solution: Use software decoder fallback
    
  3. Video file not supported

    Check: VavCoreVideoFile.IsFormatSupported(filePath)
    Solution: Convert to WebM/MKV with AV1 codec
    

Debug Information

// Log comprehensive system information
VavCoreGodotUtils.LogSystemInfo();

// Create detailed system report
var systemReport = VavCoreGodotUtils.CreateSystemReport();

// Check video file validation
var (isValid, error) = VavCoreGodotUtils.ValidateVideoFile(videoPath);

🎯 Next Steps

  1. Audio Support: Future integration with VavCore audio decoding
  2. Streaming: Network video streaming support
  3. GPU Integration: Direct GPU surface rendering optimization
  4. Mobile Optimization: Enhanced Android/iOS performance

🎮 Cross-platform AV1 video decoding made easy for Godot 4.x! Hardware acceleration with software fallback for maximum compatibility!