Clean code

This commit is contained in:
2025-09-23 04:41:50 +09:00
parent bcae668204
commit e80e758a6c
5 changed files with 1 additions and 346 deletions

View File

@@ -97,12 +97,8 @@ namespace winrt::Vav2Player::implementation
}
m_renderBitmap = nullptr;
// Additional safety flags
m_isInitialized = false;
m_isLoaded = false;
m_isInitialized = false;
}
catch (...)
{
@@ -238,9 +234,6 @@ namespace winrt::Vav2Player::implementation
if (m_isLoaded && m_fileReader && m_fileReader->IsFileOpen())
{
InitializeVideoRenderer();
OutputDebugStringA(("Switched to " +
std::string(value ? "hardware D3D12" : "software CPU") +
" rendering\n").c_str());
}
else
{
@@ -363,7 +356,6 @@ namespace winrt::Vav2Player::implementation
m_playbackTimer.Interval(interval);
m_playbackTimer.Start();
// Process first frame immediately
ProcessSingleFrame();
}
@@ -408,22 +400,14 @@ namespace winrt::Vav2Player::implementation
void VideoPlayerControl::ProcessSingleFrame()
{
OutputDebugStringA("[DEBUG] ProcessSingleFrame() called\n");
// Simple validation
if (!m_isPlaying || !m_fileReader || !m_decoder) {
OutputDebugStringA(("[DEBUG] ProcessSingleFrame validation failed - playing:" +
std::string(m_isPlaying ? "true" : "false") +
" fileReader:" + std::string(m_fileReader ? "valid" : "null") +
" decoder:" + std::string(m_decoder ? "valid" : "null") + "\n").c_str());
return;
}
OutputDebugStringA("[DEBUG] Reading next packet...\n");
VideoPacket packet;
if (!m_fileReader->ReadNextPacket(packet))
{
OutputDebugStringA("[DEBUG] End of video - stopping playback\n");
// End of video - stop playback
m_isPlaying = false;
if (m_playbackTimer) m_playbackTimer.Stop();
@@ -431,14 +415,11 @@ namespace winrt::Vav2Player::implementation
return;
}
OutputDebugStringA("[DEBUG] Decoding frame...\n");
VideoFrame frame;
if (!m_decoder->DecodeFrame(packet, frame)) {
OutputDebugStringA("[DEBUG] Failed to decode frame - skipping\n");
return; // Skip failed frames
}
OutputDebugStringA("[DEBUG] Rendering frame to screen...\n");
RenderFrameToScreen(frame);
m_currentFrame++;
@@ -567,16 +548,13 @@ namespace winrt::Vav2Player::implementation
bgra_row[x * 4 + 3] = 255; // Alpha
}
}
OutputDebugStringA("[DEBUG] YUV to BGRA conversion completed\n");
}
void VideoPlayerControl::UpdateStatus(winrt::hstring const& message)
{
m_status = message;
OutputDebugStringA(("[DEBUG] Status: " + winrt::to_string(message) + "\n").c_str());
}
void VideoPlayerControl::InitializeVideoRenderer()
{
// Initialize rendering mode based on user selection
@@ -607,29 +585,21 @@ namespace winrt::Vav2Player::implementation
// Temporarily use CPU rendering until container size is available
VideoSwapChainPanel().Visibility(winrt::Microsoft::UI::Xaml::Visibility::Collapsed);
VideoImage().Visibility(winrt::Microsoft::UI::Xaml::Visibility::Visible);
// Don't change m_useHardwareRendering flag - keep user preference
return;
}
HRESULT hr = m_gpuRenderer->Initialize(VideoSwapChainPanel(), containerWidth, containerHeight);
if (SUCCEEDED(hr))
{
// GPU rendering initialized successfully
}
else
if (!SUCCEEDED(hr))
{
// GPU initialization failed - temporarily use CPU rendering
// Don't permanently change m_useHardwareRendering flag
VideoSwapChainPanel().Visibility(winrt::Microsoft::UI::Xaml::Visibility::Collapsed);
VideoImage().Visibility(winrt::Microsoft::UI::Xaml::Visibility::Visible);
// Keep GPU renderer for potential retry later
}
}
}
void VideoPlayerControl::ResetVideoState()
{
OutputDebugStringA("[DEBUG] ResetVideoState() called\n");
m_currentFrame = 0;
m_currentTime = 0.0;
m_isLoaded = false;
@@ -649,23 +619,18 @@ namespace winrt::Vav2Player::implementation
bool VideoPlayerControl::CreateDecoder()
{
OutputDebugStringA("[DEBUG] CreateDecoder() called\n");
m_decoder = VideoDecoderFactory::CreateDecoder(VideoCodecType::AV1, m_decoderType);
bool success = m_decoder != nullptr;
OutputDebugStringA(("[DEBUG] Decoder created: " + std::string(success ? "success" : "failed") + "\n").c_str());
return success;
}
bool VideoPlayerControl::InitializeDecoder()
{
OutputDebugStringA("[DEBUG] InitializeDecoder() called\n");
if (!m_decoder) {
OutputDebugStringA("[DEBUG] No decoder available\n");
return false;
}
auto metadata = m_fileReader->GetVideoMetadata();
bool success = m_decoder->Initialize(metadata);
OutputDebugStringA(("[DEBUG] Decoder initialized: " + std::string(success ? "success" : "failed") + "\n").c_str());
return success;
}
@@ -735,7 +700,6 @@ namespace winrt::Vav2Player::implementation
void VideoPlayerControl::Seek(double timeSeconds)
{
OutputDebugStringA(("[DEBUG] Seek to: " + std::to_string(timeSeconds) + "s\n").c_str());
if (!m_isLoaded || !m_fileReader) return;
// Stop playback during seek
@@ -758,8 +722,6 @@ namespace winrt::Vav2Player::implementation
}
UpdateStatus(L"Seeked");
} else {
OutputDebugStringA("[DEBUG] Seek operation failed\n");
}
}

View File

@@ -1,91 +0,0 @@
// YUVCopy.hlsl - GPU-based YUV plane copy compute shader
// Replaces CPU memcpy with GPU parallel processing for zero-copy optimization
// Constant buffer for copy parameters
cbuffer CopyParams : register(b0)
{
uint srcWidth; // Source width in pixels
uint srcHeight; // Source height in pixels
uint srcPitch; // Source row pitch in bytes
uint dstPitch; // Destination row pitch in bytes
uint bytesPerPixel; // Bytes per pixel (1 for Y, 1 for U/V)
uint padding[3]; // Padding for 16-byte alignment
};
// Input buffer (Ring Buffer mapped memory)
StructuredBuffer<uint> srcBuffer : register(t0);
// Output buffer (GPU upload buffer)
RWStructuredBuffer<uint> dstBuffer : register(u0);
// Thread group size: 8x8 = 64 threads per group
[numthreads(8, 8, 1)]
void CSMain(uint3 id : SV_DispatchThreadID)
{
uint x = id.x;
uint y = id.y;
// Bounds check
if (x >= srcWidth || y >= srcHeight)
return;
// Calculate byte offsets for source and destination
uint srcByteOffset = y * srcPitch + x * bytesPerPixel;
uint dstByteOffset = y * dstPitch + x * bytesPerPixel;
// Convert byte offsets to uint offsets (4 bytes per uint)
uint srcUintOffset = srcByteOffset / 4;
uint dstUintOffset = dstByteOffset / 4;
// Handle byte-aligned copies for different pixel sizes
if (bytesPerPixel == 1)
{
// For Y, U, V planes (1 byte per pixel)
uint srcUintIndex = srcUintOffset;
uint dstUintIndex = dstUintOffset;
uint byteIndexInUint = srcByteOffset % 4;
// Read source uint and extract the specific byte
uint srcValue = srcBuffer[srcUintIndex];
uint pixelValue = (srcValue >> (byteIndexInUint * 8)) & 0xFF;
// Update destination uint with the new pixel value
uint dstOriginal = dstBuffer[dstUintIndex];
uint dstByteIndex = dstByteOffset % 4;
uint mask = 0xFF << (dstByteIndex * 8);
uint newValue = (dstOriginal & ~mask) | (pixelValue << (dstByteIndex * 8));
dstBuffer[dstUintIndex] = newValue;
}
else
{
// For multi-byte pixels, copy full uints
dstBuffer[dstUintOffset] = srcBuffer[srcUintOffset];
}
}
// Alternative optimized version for aligned 4-byte copies
[numthreads(16, 16, 1)]
void CSMainAligned(uint3 id : SV_DispatchThreadID)
{
uint x = id.x;
uint y = id.y;
// Process 4 pixels at once for better efficiency
uint pixelsPerThread = 4;
uint actualX = x * pixelsPerThread;
if (actualX >= srcWidth || y >= srcHeight)
return;
// Calculate uint-aligned offsets
uint srcRowOffset = (y * srcPitch) / 4;
uint dstRowOffset = (y * dstPitch) / 4;
uint pixelOffset = actualX / 4;
uint srcIndex = srcRowOffset + pixelOffset;
uint dstIndex = dstRowOffset + pixelOffset;
// Copy one uint (4 bytes) containing 4 Y pixels or 4 U/V pixels
dstBuffer[dstIndex] = srcBuffer[srcIndex];
}

View File

@@ -1,79 +0,0 @@
// YUVToRGB.hlsl - High-performance YUV to RGB conversion shader
// Eliminates CPU-based color conversion bottleneck (11-19ms -> 0.1-0.5ms)
cbuffer ColorConversionConstants : register(b0)
{
matrix colorMatrix; // BT.709 or BT.2020 color conversion matrix
float4 yuvOffsets; // Y, U, V offsets for different formats
float4 yuvRanges; // Y, U, V ranges for normalization
int2 videoSize; // Video width and height
int2 padding; // Padding for 16-byte alignment
};
// Input textures
Texture2D yTexture : register(t0); // Y plane (luminance)
Texture2D uTexture : register(t1); // U plane (chroma)
Texture2D vTexture : register(t2); // V plane (chroma)
// Samplers
SamplerState linearSampler : register(s0);
struct VSInput
{
float4 position : POSITION;
float2 texCoord : TEXCOORD0;
};
struct PSInput
{
float4 position : SV_POSITION;
float2 texCoord : TEXCOORD0;
};
// Vertex Shader
PSInput VSMain(VSInput input)
{
PSInput output;
output.position = input.position;
output.texCoord = input.texCoord;
return output;
}
// Pixel Shader - Optimized BT.709 conversion
float4 PSMain(PSInput input) : SV_TARGET
{
// Sample YUV values
float y = yTexture.Sample(linearSampler, input.texCoord).r;
float u = uTexture.Sample(linearSampler, input.texCoord).r;
float v = vTexture.Sample(linearSampler, input.texCoord).r;
// Normalize to [0,1] range and apply offsets
y = (y - yuvOffsets.x) * yuvRanges.x;
u = (u - yuvOffsets.y) * yuvRanges.y - 0.5f;
v = (v - yuvOffsets.z) * yuvRanges.z - 0.5f;
// BT.709 conversion matrix (optimized constants)
float3 yuv = float3(y, u, v);
float3 rgb = mul(colorMatrix, yuv);
// Clamp to valid range
rgb = saturate(rgb);
return float4(rgb, 1.0f);
}
// Alternative high-performance version with manual matrix
float4 PSMainFast(PSInput input) : SV_TARGET
{
float y = yTexture.Sample(linearSampler, input.texCoord).r;
float u = uTexture.Sample(linearSampler, input.texCoord).r;
float v = vTexture.Sample(linearSampler, input.texCoord).r;
// BT.709 conversion with optimized constants
float3 rgb;
rgb.r = y + 1.402f * (v - 0.5f);
rgb.g = y - 0.344f * (u - 0.5f) - 0.714f * (v - 0.5f);
rgb.b = y + 1.772f * (u - 0.5f);
return float4(saturate(rgb), 1.0f);
}

View File

@@ -1,60 +0,0 @@
// Simple YUV-to-RGB Compute Shader for AV1 Video Playback
// Phase 3: Clean GPU pipeline implementation
// Input textures
Texture2D<float> YTexture : register(t0);
Texture2D<float> UTexture : register(t1);
Texture2D<float> VTexture : register(t2);
// Output texture
RWTexture2D<float4> OutputTexture : register(u0);
// Constants for YUV-to-RGB conversion
cbuffer ConversionConstants : register(b0)
{
uint VideoWidth;
uint VideoHeight;
uint OutputWidth;
uint OutputHeight;
};
// BT.709 YUV-to-RGB conversion matrix (standard for HD video)
static const float3x3 YUVToRGBMatrix = float3x3(
1.164f, 0.000f, 1.596f, // Y -> R
1.164f, -0.392f, -0.813f, // Y -> G
1.164f, 2.017f, 0.000f // Y -> B
);
// Offsets for limited range YUV (16-235 for Y, 16-240 for UV)
static const float3 YUVOffsets = float3(16.0f / 255.0f, 128.0f / 255.0f, 128.0f / 255.0f);
[numthreads(8, 8, 1)]
void main(uint3 id : SV_DispatchThreadID)
{
// Early exit if outside output bounds
if (id.x >= OutputWidth || id.y >= OutputHeight)
return;
// Calculate normalized coordinates for input sampling
float2 uv = float2(id.x, id.y) / float2(OutputWidth - 1, OutputHeight - 1);
// Sample Y (full resolution)
float Y = YTexture.SampleLevel(0, uv, 0).r;
// Sample U and V (half resolution for 4:2:0)
float2 uvChroma = uv * float2(VideoWidth, VideoHeight) * 0.5f;
float U = UTexture.SampleLevel(0, uvChroma / float2(VideoWidth * 0.5f, VideoHeight * 0.5f), 0).r;
float V = VTexture.SampleLevel(0, uvChroma / float2(VideoWidth * 0.5f, VideoHeight * 0.5f), 0).r;
// Convert from limited range to full range
float3 yuv = float3(Y, U, V) - YUVOffsets;
yuv.x *= 255.0f / 219.0f; // Y: 16-235 -> 0-255
yuv.yz *= 255.0f / 224.0f; // UV: 16-240 -> 0-255
// Apply YUV-to-RGB conversion matrix
float3 rgb = mul(YUVToRGBMatrix, yuv);
// Clamp to valid range and output
rgb = saturate(rgb);
OutputTexture[id.xy] = float4(rgb, 1.0f);
}

View File

@@ -1,77 +0,0 @@
// YUV to RGB Conversion Shader for AV1 Video Rendering
// Optimized for GPU performance with BT.709 color space
// Input YUV textures (separate planes for YUV420P)
Texture2D<float> YPlane : register(t0);
Texture2D<float> UPlane : register(t1);
Texture2D<float> VPlane : register(t2);
// Linear sampler for texture filtering
SamplerState linearSampler : register(s0);
// Output render target
struct VSOutput
{
float4 position : SV_POSITION;
float2 texCoord : TEXCOORD0;
};
// Vertex Shader - Full-screen quad
VSOutput VSMain(uint vertexID : SV_VertexID)
{
VSOutput output;
// Generate full-screen triangle using vertex ID
// Covers entire screen with minimal vertex processing
output.texCoord = float2((vertexID << 1) & 2, vertexID & 2);
output.position = float4(output.texCoord * 2.0 - 1.0, 0.0, 1.0);
output.position.y = -output.position.y; // Flip Y for D3D coordinate system
return output;
}
// Pixel Shader - YUV to RGB conversion
float4 PSMain(VSOutput input) : SV_TARGET
{
float2 texCoord = input.texCoord;
// Sample YUV values from separate texture planes
float Y = YPlane.Sample(linearSampler, texCoord).r;
// For YUV420P, UV planes are half resolution
// Sample with automatic bilinear filtering
float U = UPlane.Sample(linearSampler, texCoord).r;
float V = VPlane.Sample(linearSampler, texCoord).r;
// Convert from YUV [0,1] range to standard YUV ranges
// Y: [16/255, 235/255] -> [0, 1]
// UV: [16/255, 240/255] -> [-0.5, 0.5]
Y = (Y - 16.0/255.0) * 255.0/(235.0-16.0);
U = (U - 128.0/255.0);
V = (V - 128.0/255.0);
// BT.709 YUV to RGB conversion matrix (GPU optimized)
// R = Y + 1.5748 * V
// G = Y - 0.1873 * U - 0.4681 * V
// B = Y + 1.8556 * U
float3 rgb;
rgb.r = Y + 1.5748 * V;
rgb.g = Y - 0.1873 * U - 0.4681 * V;
rgb.b = Y + 1.8556 * U;
// Clamp to valid range and apply gamma correction
rgb = saturate(rgb);
// Apply slight contrast enhancement for better visual quality
rgb = pow(rgb, 0.95);
return float4(rgb, 1.0);
}
// Compute Shader version for batch processing (optional optimization)
[numthreads(8, 8, 1)]
void CSMain(uint3 id : SV_DispatchThreadID)
{
// TODO: Implement compute shader version for ultra-high resolution videos
// This would be used for 8K+ content where pixel shader becomes bandwidth limited
}