186 lines
5.2 KiB
C#
186 lines
5.2 KiB
C#
using Godot;
|
|
using System;
|
|
using VideoOrchestra.Platform;
|
|
|
|
namespace VideoOrchestra
|
|
{
|
|
/// <summary>
|
|
/// Main VP9 multi-stream video decoder manager for Godot Engine
|
|
/// Handles simultaneous decoding of up to 3 VP9 video streams with alpha channels
|
|
/// Supports Windows (Media Foundation), Android (MediaCodec), iOS/macOS (VideoToolbox)
|
|
/// </summary>
|
|
public partial class VideoOrchestraManager : Node
|
|
{
|
|
private const int MAX_STREAMS = 3;
|
|
|
|
// Platform decoder interface
|
|
private IVP9PlatformDecoder _platformDecoder;
|
|
private VP9PlatformInfo _platformInfo;
|
|
private bool _initialized = false;
|
|
|
|
// Stream configuration
|
|
[Export] public int StreamWidth { get; set; } = 1920;
|
|
[Export] public int StreamHeight { get; set; } = 1080;
|
|
[Export] public bool UseHardwareDecoding { get; set; } = true;
|
|
[Export] public bool ShowPlatformInfo { get; set; } = true;
|
|
|
|
// Events
|
|
[Signal] public delegate void StreamDecodedEventHandler(int streamId);
|
|
[Signal] public delegate void DecoderErrorEventHandler(int streamId, string error);
|
|
[Signal] public delegate void DecoderInitializedEventHandler(string platformName, bool hardwareEnabled);
|
|
|
|
public override void _Ready()
|
|
{
|
|
InitializePlatformDecoder();
|
|
}
|
|
|
|
private void InitializePlatformDecoder()
|
|
{
|
|
try
|
|
{
|
|
// Get platform information
|
|
_platformInfo = VP9PlatformFactory.GetPlatformInfo();
|
|
|
|
if (ShowPlatformInfo)
|
|
{
|
|
GD.Print($"VP9 Platform Info: {_platformInfo}");
|
|
}
|
|
|
|
// Create platform-specific decoder
|
|
_platformDecoder = VP9PlatformFactory.CreateDecoder(UseHardwareDecoding);
|
|
|
|
if (_platformDecoder == null)
|
|
{
|
|
GD.PrintErr("Failed to create platform decoder");
|
|
return;
|
|
}
|
|
|
|
// Initialize the decoder
|
|
_initialized = _platformDecoder.Initialize(StreamWidth, StreamHeight, UseHardwareDecoding);
|
|
|
|
if (_initialized)
|
|
{
|
|
bool hardwareEnabled = UseHardwareDecoding && _platformDecoder.IsHardwareDecodingSupported;
|
|
GD.Print($"VP9 Orchestra initialized: {StreamWidth}x{StreamHeight} on {_platformDecoder.PlatformName}");
|
|
GD.Print($"Hardware acceleration: {(hardwareEnabled ? "Enabled" : "Disabled")}");
|
|
|
|
EmitSignal(SignalName.DecoderInitialized, _platformDecoder.PlatformName, hardwareEnabled);
|
|
}
|
|
else
|
|
{
|
|
GD.PrintErr($"Failed to initialize {_platformDecoder.PlatformName} VP9 decoder");
|
|
}
|
|
}
|
|
catch (PlatformNotSupportedException ex)
|
|
{
|
|
GD.PrintErr($"Platform not supported: {ex.Message}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
GD.PrintErr($"Error initializing VP9 decoder: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Decode a VP9 frame for the specified stream
|
|
/// </summary>
|
|
/// <param name="frameData">VP9 encoded frame data</param>
|
|
/// <param name="streamId">Stream identifier (0-2)</param>
|
|
/// <returns>True if decoding succeeded</returns>
|
|
public bool DecodeFrame(byte[] frameData, int streamId)
|
|
{
|
|
if (!_initialized || streamId < 0 || streamId >= MAX_STREAMS || _platformDecoder == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
bool success = _platformDecoder.DecodeFrame(frameData, streamId);
|
|
|
|
if (success)
|
|
{
|
|
EmitSignal(SignalName.StreamDecoded, streamId);
|
|
}
|
|
else
|
|
{
|
|
EmitSignal(SignalName.DecoderError, streamId, "Decode failed");
|
|
}
|
|
|
|
return success;
|
|
}
|
|
catch (VP9DecoderException vpEx)
|
|
{
|
|
GD.PrintErr($"VP9 decoder error: {vpEx.Message}");
|
|
EmitSignal(SignalName.DecoderError, streamId, vpEx.Message);
|
|
return false;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
GD.PrintErr($"Error decoding frame for stream {streamId}: {ex.Message}");
|
|
EmitSignal(SignalName.DecoderError, streamId, ex.Message);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the decoded texture for the specified stream
|
|
/// </summary>
|
|
/// <param name="streamId">Stream identifier (0-2)</param>
|
|
/// <returns>ImageTexture containing decoded frame, or null if not available</returns>
|
|
public ImageTexture GetStreamTexture(int streamId)
|
|
{
|
|
if (!_initialized || streamId < 0 || streamId >= MAX_STREAMS || _platformDecoder == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return _platformDecoder.GetDecodedTexture(streamId);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get platform-specific native texture ID for the specified stream
|
|
/// </summary>
|
|
/// <param name="streamId">Stream identifier (0-2)</param>
|
|
/// <returns>Native texture ID (OpenGL/DirectX/Metal), or 0 if not available</returns>
|
|
public uint GetNativeTextureId(int streamId)
|
|
{
|
|
if (!_initialized || streamId < 0 || streamId >= MAX_STREAMS || _platformDecoder == null)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return _platformDecoder.GetNativeTextureId(streamId);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get current platform information
|
|
/// </summary>
|
|
/// <returns>VP9 platform capabilities information</returns>
|
|
public VP9PlatformInfo GetPlatformInfo()
|
|
{
|
|
return _platformInfo;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get current decoder status
|
|
/// </summary>
|
|
/// <returns>Current decoder status</returns>
|
|
public VP9DecoderStatus GetDecoderStatus()
|
|
{
|
|
return _platformDecoder?.GetStatus() ?? VP9DecoderStatus.Uninitialized;
|
|
}
|
|
|
|
public override void _ExitTree()
|
|
{
|
|
if (_platformDecoder != null)
|
|
{
|
|
_platformDecoder.Dispose();
|
|
_platformDecoder = null;
|
|
}
|
|
|
|
_initialized = false;
|
|
}
|
|
}
|
|
}
|