using System.IO; using System.Windows.Media; using System.Windows.Media.Imaging; namespace ytLive.Services.Compositor; /// /// Decodes a layout asset's bytes into a tightly-packed BGRA8 /// once per content-hash asset id. The preview uses the WPF BitmapImage in /// ImageCache; the output path needs raw pixels, so assets decode here instead. /// public static class StaticPixelCache { private static readonly Dictionary Cache = new(StringComparer.Ordinal); public static VideoFrame? Get(string assetId) { if (string.IsNullOrWhiteSpace(assetId)) return null; if (Cache.TryGetValue(assetId, out var frame)) return frame; var bytes = LayoutStore.Instance?.GetAssetBytes(assetId); if (bytes == null || bytes.Length == 0) return null; var decoded = Decode(bytes); if (decoded != null) Cache[assetId] = decoded; return decoded; } public static VideoFrame? Decode(byte[] bytes) { try { using var stream = new MemoryStream(bytes, writable: false); var decoder = BitmapDecoder.Create(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad); var source = decoder.Frames[0]; var bgra = new FormatConvertedBitmap(source, PixelFormats.Bgra32, null, 0); var width = bgra.PixelWidth; var height = bgra.PixelHeight; var pixels = new byte[width * height * 4]; bgra.CopyPixels(pixels, width * 4, 0); return new VideoFrame(width, height, pixels); } catch { return null; } } }