From 1954665c938cc70c90c6398010f29cfb8e1da708 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Fri, 2 Jun 2023 14:43:00 -0700 Subject: [PATCH] threaded video decoding --- src/Video/VideoAV1.cs | 7 ++- src/Video/VideoPlayer.cs | 127 ++++++++++++++++++++------------------- 2 files changed, 69 insertions(+), 65 deletions(-) diff --git a/src/Video/VideoAV1.cs b/src/Video/VideoAV1.cs index e423284..6cb238b 100644 --- a/src/Video/VideoAV1.cs +++ b/src/Video/VideoAV1.cs @@ -10,19 +10,18 @@ namespace MoonWorks.Video public int Width => width; public int Height => height; - public double FramesPerSecond => 28.97; + public double FramesPerSecond { get; set; } public Dav1dfile.PixelLayout PixelLayout => pixelLayout; public int UVWidth { get; } public int UVHeight { get; } private int width; private int height; - private double fps; private Dav1dfile.PixelLayout pixelLayout; bool IsDisposed; - public VideoAV1(string filename) + public VideoAV1(string filename, double framesPerSecond) { if (!File.Exists(filename)) { @@ -55,6 +54,8 @@ namespace MoonWorks.Video { throw new NotSupportedException("Unrecognized YUV format!"); } + + FramesPerSecond = framesPerSecond; } protected virtual void Dispose(bool disposing) diff --git a/src/Video/VideoPlayer.cs b/src/Video/VideoPlayer.cs index 5372768..ce95001 100644 --- a/src/Video/VideoPlayer.cs +++ b/src/Video/VideoPlayer.cs @@ -21,17 +21,26 @@ namespace MoonWorks.Video private Texture vTexture = null; private Sampler LinearSampler; + private object readLock = new object(); + private bool frameDataUpdated; + + private IntPtr yDataHandle; + private IntPtr uDataHandle; + private IntPtr vDataHandle; + private uint yDataLength; + private uint uvDataLength; + private uint yStride; + private uint uvStride; + private int currentFrame; private Stopwatch timer; private double lastTimestamp; private double timeElapsed; - private Stopwatch profilingTimer = new Stopwatch(); - private bool disposed; - public VideoPlayer(GraphicsDevice graphicsDevice, AudioDevice audioDevice) + public VideoPlayer(GraphicsDevice graphicsDevice) { GraphicsDevice = graphicsDevice; if (GraphicsDevice.VideoPipeline == null) @@ -154,11 +163,6 @@ namespace MoonWorks.Video Video = null; } - public void Update() - { - if (Video == null) { return; } - } - public void Render() { if (Video == null || State == VideoState.Stopped) @@ -172,27 +176,13 @@ namespace MoonWorks.Video int thisFrame = ((int) (timeElapsed / (1000.0 / Video.FramesPerSecond))); if (thisFrame > currentFrame) { - profilingTimer.Restart(); - int readResult = Dav1dfile.df_readvideo( - Video.Handle, - thisFrame - currentFrame, - out var yData, - out var uData, - out var vData, - out var yDataLength, - out var uvDataLength, - out var yStride, - out var uvStride - ); - profilingTimer.Stop(); - System.Console.WriteLine($"Frame decoded in: {profilingTimer.Elapsed.TotalMilliseconds}"); - - if (readResult == 1 || currentFrame == -1) + if (frameDataUpdated) { - UpdateRenderTexture(yData, uData, vData, yDataLength, uvDataLength, yStride, uvStride); + UpdateRenderTexture(); } currentFrame = thisFrame; + System.Threading.Tasks.Task.Run(ReadNextFrame); } bool ended = Dav1dfile.df_eos(Video.Handle) == 1; @@ -217,39 +207,42 @@ namespace MoonWorks.Video } } - private void UpdateRenderTexture(IntPtr yData, IntPtr uData, IntPtr vData, uint yDataLength, uint uvDataLength, uint yStride, uint uvStride) + private void UpdateRenderTexture() { - var commandBuffer = GraphicsDevice.AcquireCommandBuffer(); + lock (readLock) + { + var commandBuffer = GraphicsDevice.AcquireCommandBuffer(); - commandBuffer.SetTextureDataYUV( - yTexture, - uTexture, - vTexture, - yData, - uData, - vData, - yDataLength, - uvDataLength, - yStride, - uvStride - ); + commandBuffer.SetTextureDataYUV( + yTexture, + uTexture, + vTexture, + yDataHandle, + uDataHandle, + vDataHandle, + yDataLength, + uvDataLength, + yStride, + uvStride + ); - commandBuffer.BeginRenderPass( - new ColorAttachmentInfo(RenderTexture, Color.Black) - ); + commandBuffer.BeginRenderPass( + new ColorAttachmentInfo(RenderTexture, Color.Black) + ); - commandBuffer.BindGraphicsPipeline(GraphicsDevice.VideoPipeline); - commandBuffer.BindFragmentSamplers( - new TextureSamplerBinding(yTexture, LinearSampler), - new TextureSamplerBinding(uTexture, LinearSampler), - new TextureSamplerBinding(vTexture, LinearSampler) - ); + commandBuffer.BindGraphicsPipeline(GraphicsDevice.VideoPipeline); + commandBuffer.BindFragmentSamplers( + new TextureSamplerBinding(yTexture, LinearSampler), + new TextureSamplerBinding(uTexture, LinearSampler), + new TextureSamplerBinding(vTexture, LinearSampler) + ); - commandBuffer.DrawPrimitives(0, 1, 0, 0); + commandBuffer.DrawPrimitives(0, 1, 0, 0); - commandBuffer.EndRenderPass(); + commandBuffer.EndRenderPass(); - GraphicsDevice.Submit(commandBuffer); + GraphicsDevice.Submit(commandBuffer); + } } private static Texture CreateRenderTexture(GraphicsDevice graphicsDevice, int width, int height) @@ -276,20 +269,30 @@ namespace MoonWorks.Video private void InitializeDav1dStream() { - // Grab the first video frame ASAP. - Dav1dfile.df_readvideo( - Video.Handle, - 1, - out var _, - out var _, - out var _, - out var _, - out var _, - out var _, - out var _); + System.Threading.Tasks.Task.Run(ReadNextFrame); currentFrame = -1; } + private void ReadNextFrame() + { + lock (readLock) + { + if (Dav1dfile.df_readvideo( + Video.Handle, + 1, + out yDataHandle, + out uDataHandle, + out vDataHandle, + out yDataLength, + out uvDataLength, + out yStride, + out uvStride) == 1 + ) { + frameDataUpdated = true; + } + } + } + protected virtual void Dispose(bool disposing) { if (!disposed)