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 Width => width;
public int Height => height; public int Height => height;
public double FramesPerSecond => 28.97; public double FramesPerSecond { get; set; }
public Dav1dfile.PixelLayout PixelLayout => pixelLayout; public Dav1dfile.PixelLayout PixelLayout => pixelLayout;
public int UVWidth { get; } public int UVWidth { get; }
public int UVHeight { get; } public int UVHeight { get; }
private int width; private int width;
private int height; private int height;
private double fps;
private Dav1dfile.PixelLayout pixelLayout; private Dav1dfile.PixelLayout pixelLayout;
bool IsDisposed; bool IsDisposed;
public VideoAV1(string filename) public VideoAV1(string filename, double framesPerSecond)
{ {
if (!File.Exists(filename)) if (!File.Exists(filename))
{ {
@ -55,6 +54,8 @@ namespace MoonWorks.Video
{ {
throw new NotSupportedException("Unrecognized YUV format!"); throw new NotSupportedException("Unrecognized YUV format!");
} }
FramesPerSecond = framesPerSecond;
} }
protected virtual void Dispose(bool disposing) protected virtual void Dispose(bool disposing)

View File

@ -21,17 +21,26 @@ namespace MoonWorks.Video
private Texture vTexture = null; private Texture vTexture = null;
private Sampler LinearSampler; 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 int currentFrame;
private Stopwatch timer; private Stopwatch timer;
private double lastTimestamp; private double lastTimestamp;
private double timeElapsed; private double timeElapsed;
private Stopwatch profilingTimer = new Stopwatch();
private bool disposed; private bool disposed;
public VideoPlayer(GraphicsDevice graphicsDevice, AudioDevice audioDevice) public VideoPlayer(GraphicsDevice graphicsDevice)
{ {
GraphicsDevice = graphicsDevice; GraphicsDevice = graphicsDevice;
if (GraphicsDevice.VideoPipeline == null) if (GraphicsDevice.VideoPipeline == null)
@ -154,11 +163,6 @@ namespace MoonWorks.Video
Video = null; Video = null;
} }
public void Update()
{
if (Video == null) { return; }
}
public void Render() public void Render()
{ {
if (Video == null || State == VideoState.Stopped) if (Video == null || State == VideoState.Stopped)
@ -172,27 +176,13 @@ namespace MoonWorks.Video
int thisFrame = ((int) (timeElapsed / (1000.0 / Video.FramesPerSecond))); int thisFrame = ((int) (timeElapsed / (1000.0 / Video.FramesPerSecond)));
if (thisFrame > currentFrame) if (thisFrame > currentFrame)
{ {
profilingTimer.Restart(); if (frameDataUpdated)
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)
{ {
UpdateRenderTexture(yData, uData, vData, yDataLength, uvDataLength, yStride, uvStride); UpdateRenderTexture();
} }
currentFrame = thisFrame; currentFrame = thisFrame;
System.Threading.Tasks.Task.Run(ReadNextFrame);
} }
bool ended = Dav1dfile.df_eos(Video.Handle) == 1; 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( commandBuffer.SetTextureDataYUV(
yTexture, yTexture,
uTexture, uTexture,
vTexture, vTexture,
yData, yDataHandle,
uData, uDataHandle,
vData, vDataHandle,
yDataLength, yDataLength,
uvDataLength, uvDataLength,
yStride, yStride,
uvStride uvStride
); );
commandBuffer.BeginRenderPass( commandBuffer.BeginRenderPass(
new ColorAttachmentInfo(RenderTexture, Color.Black) new ColorAttachmentInfo(RenderTexture, Color.Black)
); );
commandBuffer.BindGraphicsPipeline(GraphicsDevice.VideoPipeline); commandBuffer.BindGraphicsPipeline(GraphicsDevice.VideoPipeline);
commandBuffer.BindFragmentSamplers( commandBuffer.BindFragmentSamplers(
new TextureSamplerBinding(yTexture, LinearSampler), new TextureSamplerBinding(yTexture, LinearSampler),
new TextureSamplerBinding(uTexture, LinearSampler), new TextureSamplerBinding(uTexture, LinearSampler),
new TextureSamplerBinding(vTexture, 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) private static Texture CreateRenderTexture(GraphicsDevice graphicsDevice, int width, int height)
@ -276,20 +269,30 @@ namespace MoonWorks.Video
private void InitializeDav1dStream() private void InitializeDav1dStream()
{ {
// Grab the first video frame ASAP. System.Threading.Tasks.Task.Run(ReadNextFrame);
Dav1dfile.df_readvideo(
Video.Handle,
1,
out var _,
out var _,
out var _,
out var _,
out var _,
out var _,
out var _);
currentFrame = -1; 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) protected virtual void Dispose(bool disposing)
{ {
if (!disposed) if (!disposed)