forked from Mirror/Ryujinx
Fix H264 output frame size when decoding videos of different sizes (#1606)
This commit is contained in:
parent
c482718d2e
commit
14fd9aa640
2 changed files with 25 additions and 4 deletions
|
@ -11,18 +11,33 @@ namespace Ryujinx.Graphics.Nvdec.H264
|
||||||
|
|
||||||
private readonly byte[] _workBuffer = new byte[WorkBufferSize];
|
private readonly byte[] _workBuffer = new byte[WorkBufferSize];
|
||||||
|
|
||||||
private readonly FFmpegContext _context = new FFmpegContext();
|
private FFmpegContext _context = new FFmpegContext();
|
||||||
|
|
||||||
|
private int _oldOutputWidth;
|
||||||
|
private int _oldOutputHeight;
|
||||||
|
|
||||||
public ISurface CreateSurface(int width, int height)
|
public ISurface CreateSurface(int width, int height)
|
||||||
{
|
{
|
||||||
return new Surface();
|
return new Surface(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Decode(ref H264PictureInfo pictureInfo, ISurface output, ReadOnlySpan<byte> bitstream)
|
public bool Decode(ref H264PictureInfo pictureInfo, ISurface output, ReadOnlySpan<byte> bitstream)
|
||||||
{
|
{
|
||||||
|
Surface outSurf = (Surface)output;
|
||||||
|
|
||||||
|
if (outSurf.RequestedWidth != _oldOutputWidth ||
|
||||||
|
outSurf.RequestedHeight != _oldOutputHeight)
|
||||||
|
{
|
||||||
|
_context.Dispose();
|
||||||
|
_context = new FFmpegContext();
|
||||||
|
|
||||||
|
_oldOutputWidth = outSurf.RequestedWidth;
|
||||||
|
_oldOutputHeight = outSurf.RequestedHeight;
|
||||||
|
}
|
||||||
|
|
||||||
Span<byte> bs = Prepend(bitstream, SpsAndPpsReconstruction.Reconstruct(ref pictureInfo, _workBuffer));
|
Span<byte> bs = Prepend(bitstream, SpsAndPpsReconstruction.Reconstruct(ref pictureInfo, _workBuffer));
|
||||||
|
|
||||||
return _context.DecodeFrame((Surface)output, bs) == 0;
|
return _context.DecodeFrame(outSurf, bs) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] Prepend(ReadOnlySpan<byte> data, ReadOnlySpan<byte> prep)
|
private static byte[] Prepend(ReadOnlySpan<byte> data, ReadOnlySpan<byte> prep)
|
||||||
|
|
|
@ -8,6 +8,9 @@ namespace Ryujinx.Graphics.Nvdec.H264
|
||||||
{
|
{
|
||||||
public AVFrame* Frame { get; }
|
public AVFrame* Frame { get; }
|
||||||
|
|
||||||
|
public int RequestedWidth { get; }
|
||||||
|
public int RequestedHeight { get; }
|
||||||
|
|
||||||
public Plane YPlane => new Plane((IntPtr)Frame->data[0], Stride * Height);
|
public Plane YPlane => new Plane((IntPtr)Frame->data[0], Stride * Height);
|
||||||
public Plane UPlane => new Plane((IntPtr)Frame->data[1], UvStride * UvHeight);
|
public Plane UPlane => new Plane((IntPtr)Frame->data[1], UvStride * UvHeight);
|
||||||
public Plane VPlane => new Plane((IntPtr)Frame->data[2], UvStride * UvHeight);
|
public Plane VPlane => new Plane((IntPtr)Frame->data[2], UvStride * UvHeight);
|
||||||
|
@ -19,8 +22,11 @@ namespace Ryujinx.Graphics.Nvdec.H264
|
||||||
public int UvHeight => (Frame->height + 1) >> 1;
|
public int UvHeight => (Frame->height + 1) >> 1;
|
||||||
public int UvStride => Frame->linesize[1];
|
public int UvStride => Frame->linesize[1];
|
||||||
|
|
||||||
public Surface()
|
public Surface(int width, int height)
|
||||||
{
|
{
|
||||||
|
RequestedWidth = width;
|
||||||
|
RequestedHeight = height;
|
||||||
|
|
||||||
Frame = ffmpeg.av_frame_alloc();
|
Frame = ffmpeg.av_frame_alloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in a new issue