threaded video decoding
parent
0f9511f0f6
commit
1954665c93
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue