threaded video decoding

pull/49/head
cosmonaut 2023-06-02 14:43:00 -07:00
parent 0f9511f0f6
commit 1954665c93
2 changed files with 69 additions and 65 deletions

View File

@ -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)

View File

@ -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)