Files
video-orchestra/godot-project/scripts/VP9TestController.cs

275 lines
6.6 KiB
C#

using Godot;
using System;
using System.IO;
namespace VideoOrchestra
{
/// <summary>
/// Test controller for VP9 video loading and playback
/// Demonstrates usage of VideoOrchestraManager with sample VP9 streams
/// </summary>
public partial class VP9TestController : Control
{
private VideoOrchestraManager _orchestraManager;
private TextureRect[] _textureRects;
private Label _statusLabel;
private Button _loadButton;
private Button _playButton;
private Button _stopButton;
// Test VP9 streams (would be loaded from files in real usage)
private byte[][] _testStreams;
private bool _isPlaying = false;
private int _currentFrame = 0;
public override void _Ready()
{
SetupUI();
InitializeOrchestra();
}
private void SetupUI()
{
// Get UI references
_textureRects = new TextureRect[3];
_textureRects[0] = GetNode<TextureRect>("UI/StreamContainer/Stream0/TextureRect0");
_textureRects[1] = GetNode<TextureRect>("UI/StreamContainer/Stream1/TextureRect1");
_textureRects[2] = GetNode<TextureRect>("UI/StreamContainer/Stream2/TextureRect2");
_statusLabel = GetNode<Label>("UI/StatusLabel");
_loadButton = GetNode<Button>("UI/Controls/LoadButton");
_playButton = GetNode<Button>("UI/Controls/PlayButton");
_stopButton = GetNode<Button>("UI/Controls/StopButton");
// Connect button signals
_loadButton.Pressed += OnLoadButtonPressed;
_playButton.Pressed += OnPlayButtonPressed;
_stopButton.Pressed += OnStopButtonPressed;
// Initial state
_playButton.Disabled = true;
_stopButton.Disabled = true;
UpdateStatus("Ready - Click Load to initialize VP9 streams");
}
private void InitializeOrchestra()
{
_orchestraManager = GetNode<VideoOrchestraManager>("VideoOrchestraManager");
if (_orchestraManager == null)
{
UpdateStatus("Error: VideoOrchestraManager not found!");
return;
}
// Connect signals
_orchestraManager.StreamDecoded += OnStreamDecoded;
_orchestraManager.DecoderError += OnDecoderError;
_orchestraManager.DecoderInitialized += OnDecoderInitialized;
}
private void OnDecoderInitialized(string platformName, bool hardwareEnabled)
{
var platformInfo = _orchestraManager.GetPlatformInfo();
var hardwareStatus = hardwareEnabled ? "Hardware" : "Software";
UpdateStatus($"VP9 decoder initialized on {platformName} ({hardwareStatus} decoding)");
GD.Print($"Platform capabilities: {platformInfo}");
}
private void OnLoadButtonPressed()
{
UpdateStatus("Loading VP9 test streams...");
try
{
// Load test VP9 data (in real usage, this would load from .vp9 files)
LoadTestStreams();
if (_testStreams != null && _testStreams.Length > 0)
{
_loadButton.Disabled = true;
_playButton.Disabled = false;
UpdateStatus($"Loaded {_testStreams.Length} test streams - Ready to play");
}
else
{
UpdateStatus("Error: No test streams loaded");
}
}
catch (Exception ex)
{
UpdateStatus($"Error loading streams: {ex.Message}");
GD.PrintErr($"Failed to load test streams: {ex}");
}
}
private void LoadTestStreams()
{
// Create dummy VP9 frame data for testing
// In real usage, this would read from actual .vp9 files
_testStreams = new byte[3][];
// Create test frame data (VP9 header + dummy payload)
for (int i = 0; i < 3; i++)
{
_testStreams[i] = CreateDummyVP9Frame(i);
}
}
private byte[] CreateDummyVP9Frame(int streamId)
{
// Create a dummy VP9 frame for testing
// This is not a real VP9 frame - just placeholder data
var frameData = new byte[1024];
// VP9 frame header (simplified)
frameData[0] = 0x82; // VP9 signature
frameData[1] = 0x49; // VP9 signature
frameData[2] = 0x83; // VP9 signature
frameData[3] = 0x42; // VP9 signature
// Fill with test pattern based on stream ID
for (int i = 4; i < frameData.Length; i++)
{
frameData[i] = (byte)((i + streamId) % 256);
}
return frameData;
}
private void OnPlayButtonPressed()
{
if (!_isPlaying)
{
StartPlayback();
}
}
private void OnStopButtonPressed()
{
if (_isPlaying)
{
StopPlayback();
}
}
private void StartPlayback()
{
_isPlaying = true;
_playButton.Text = "Playing...";
_playButton.Disabled = true;
_stopButton.Disabled = false;
_currentFrame = 0;
UpdateStatus("Starting VP9 playback...");
// Start decoding frames
DecodeNextFrames();
}
private void StopPlayback()
{
_isPlaying = false;
_playButton.Text = "Play";
_playButton.Disabled = false;
_stopButton.Disabled = true;
UpdateStatus("Playback stopped");
}
private void DecodeNextFrames()
{
if (!_isPlaying || _testStreams == null)
return;
try
{
// Decode frames for all streams
bool anySuccess = false;
for (int streamId = 0; streamId < Math.Min(3, _testStreams.Length); streamId++)
{
bool success = _orchestraManager.DecodeFrame(_testStreams[streamId], streamId);
if (success)
{
anySuccess = true;
UpdateStreamTexture(streamId);
}
}
if (anySuccess)
{
_currentFrame++;
UpdateStatus($"Decoded frame {_currentFrame} for all streams");
// Schedule next frame (simulate 30fps)
GetTree().CreateTimer(1.0f / 30.0f).Timeout += DecodeNextFrames;
}
else
{
UpdateStatus("Error: Failed to decode frames");
StopPlayback();
}
}
catch (Exception ex)
{
UpdateStatus($"Decode error: {ex.Message}");
GD.PrintErr($"Error decoding frames: {ex}");
StopPlayback();
}
}
private void UpdateStreamTexture(int streamId)
{
if (streamId < 0 || streamId >= _textureRects.Length)
return;
try
{
var texture = _orchestraManager.GetStreamTexture(streamId);
if (texture != null)
{
_textureRects[streamId].Texture = texture;
}
}
catch (Exception ex)
{
GD.PrintErr($"Error updating texture for stream {streamId}: {ex.Message}");
}
}
private void OnStreamDecoded(int streamId)
{
GD.Print($"Stream {streamId} decoded successfully");
}
private void OnDecoderError(int streamId, string error)
{
GD.PrintErr($"Decoder error for stream {streamId}: {error}");
UpdateStatus($"Error in stream {streamId}: {error}");
if (_isPlaying)
{
StopPlayback();
}
}
private void UpdateStatus(string message)
{
if (_statusLabel != null)
{
_statusLabel.Text = $"Status: {message}";
}
GD.Print($"VP9Orchestra: {message}");
}
public override void _ExitTree()
{
if (_isPlaying)
{
StopPlayback();
}
}
}
}