nvdec: Adding Vp8 codec support (#2707)
* first try * second try * working update * Final impl * Fixes nits * Fix everything * remove leftover * Update FFmpegContext.cs * Update Surface.cs * Addresses gdkchan feedback * bool not byte * Addresses gdkchan feedback
This commit is contained in:
parent
a7109c767b
commit
d1604aa762
16 changed files with 220 additions and 35 deletions
|
@ -1,4 +1,4 @@
|
|||
using Ryujinx.Graphics.Nvdec.H264;
|
||||
using Ryujinx.Graphics.Nvdec.FFmpeg.H264;
|
||||
using Ryujinx.Graphics.Nvdec.Image;
|
||||
using Ryujinx.Graphics.Nvdec.Types.H264;
|
||||
using Ryujinx.Graphics.Video;
|
||||
|
@ -10,7 +10,7 @@ namespace Ryujinx.Graphics.Nvdec
|
|||
{
|
||||
private const int MbSizeInPixels = 16;
|
||||
|
||||
public unsafe static void Decode(NvdecDecoderContext context, ResourceManager rm, ref NvdecRegisters state)
|
||||
public static void Decode(NvdecDecoderContext context, ResourceManager rm, ref NvdecRegisters state)
|
||||
{
|
||||
PictureInfo pictureInfo = rm.Gmm.DeviceRead<PictureInfo>(state.SetPictureInfoOffset);
|
||||
H264PictureInfo info = pictureInfo.Convert();
|
||||
|
@ -25,7 +25,7 @@ namespace Ryujinx.Graphics.Nvdec
|
|||
uint lumaOffset = state.SetSurfaceLumaOffset[surfaceIndex];
|
||||
uint chromaOffset = state.SetSurfaceChromaOffset[surfaceIndex];
|
||||
|
||||
Decoder decoder = context.GetDecoder();
|
||||
Decoder decoder = context.GetH264Decoder();
|
||||
|
||||
ISurface outputSurface = rm.Cache.Get(decoder, 0, 0, width, height);
|
||||
|
||||
|
|
|
@ -1,21 +1,29 @@
|
|||
using Ryujinx.Graphics.Nvdec.H264;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec
|
||||
{
|
||||
class NvdecDecoderContext : IDisposable
|
||||
{
|
||||
private Decoder _decoder;
|
||||
private FFmpeg.H264.Decoder _h264Decoder;
|
||||
private FFmpeg.Vp8.Decoder _vp8Decoder;
|
||||
|
||||
public Decoder GetDecoder()
|
||||
public FFmpeg.H264.Decoder GetH264Decoder()
|
||||
{
|
||||
return _decoder ??= new Decoder();
|
||||
return _h264Decoder ??= new FFmpeg.H264.Decoder();
|
||||
}
|
||||
|
||||
public FFmpeg.Vp8.Decoder GetVp8Decoder()
|
||||
{
|
||||
return _vp8Decoder ??= new FFmpeg.Vp8.Decoder();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_decoder?.Dispose();
|
||||
_decoder = null;
|
||||
_h264Decoder?.Dispose();
|
||||
_h264Decoder = null;
|
||||
|
||||
_vp8Decoder?.Dispose();
|
||||
_vp8Decoder = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -68,6 +68,9 @@ namespace Ryujinx.Graphics.Nvdec
|
|||
case CodecId.H264:
|
||||
H264Decoder.Decode(_currentContext, _rm, ref _state.State);
|
||||
break;
|
||||
case CodecId.Vp8:
|
||||
Vp8Decoder.Decode(_currentContext, _rm, ref _state.State);
|
||||
break;
|
||||
case CodecId.Vp9:
|
||||
Vp9Decoder.Decode(_rm, ref _state.State);
|
||||
break;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Device\Ryujinx.Graphics.Device.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Nvdec.H264\Ryujinx.Graphics.Nvdec.H264.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Nvdec.FFmpeg\Ryujinx.Graphics.Nvdec.FFmpeg.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Nvdec.Vp9\Ryujinx.Graphics.Nvdec.Vp9.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Texture\Ryujinx.Graphics.Texture.csproj" />
|
||||
<ProjectReference Include="..\Ryujinx.Graphics.Video\Ryujinx.Graphics.Video.csproj" />
|
||||
|
|
75
Ryujinx.Graphics.Nvdec/Types/Vp8/PictureInfo.cs
Normal file
75
Ryujinx.Graphics.Nvdec/Types/Vp8/PictureInfo.cs
Normal file
|
@ -0,0 +1,75 @@
|
|||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.Video;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.Types.Vp8
|
||||
{
|
||||
struct PictureInfo
|
||||
{
|
||||
#pragma warning disable CS0649
|
||||
public Array13<uint> Unknown0;
|
||||
public uint GpTimerTimeoutValue;
|
||||
public ushort FrameWidth;
|
||||
public ushort FrameHeight;
|
||||
public byte KeyFrame; // 1: key frame - 0: not
|
||||
public byte Version;
|
||||
public byte Flags0;
|
||||
// TileFormat : 2 // 0: TBL; 1: KBL;
|
||||
// GobHeight : 3 // Set GOB height, 0: GOB_2, 1: GOB_4, 2: GOB_8, 3: GOB_16, 4: GOB_32 (NVDEC3 onwards)
|
||||
// ReserverdSurfaceFormat : 3
|
||||
public byte ErrorConcealOn; // 1: error conceal on - 0: off
|
||||
public uint FirstPartSize; // the size of first partition (frame header and mb header partition)
|
||||
public uint HistBufferSize; // in units of 256
|
||||
public uint VLDBufferSize; // in units of 1
|
||||
public Array2<uint> FrameStride; // [y_c]
|
||||
public uint LumaTopOffset; // offset of luma top field in units of 256
|
||||
public uint LumaBotOffset; // offset of luma bottom field in units of 256
|
||||
public uint LumaFrameOffset; // offset of luma frame in units of 256
|
||||
public uint ChromaTopOffset; // offset of chroma top field in units of 256
|
||||
public uint ChromaBotOffset; // offset of chroma bottom field in units of 256
|
||||
public uint ChromaFrameOffset; // offset of chroma frame in units of 256
|
||||
public uint Flags1;
|
||||
// EnableTFOutput : 1; // =1, enable dbfdma to output the display surface; if disable, then the following configure on tf is useless.
|
||||
// Remap for VC1
|
||||
// VC1MapYFlag : 1
|
||||
// MapYValue : 3
|
||||
// VC1MapUVFlag : 1
|
||||
// MapUVValue : 3
|
||||
// TF
|
||||
// OutStride : 8
|
||||
// TilingFormat : 3;
|
||||
// OutputStructure : 1 // 0:frame, 1:field
|
||||
// Reserved0 : 11
|
||||
public Array2<int> OutputTop; // in units of 256
|
||||
public Array2<int> OutputBottom; // in units of 256
|
||||
// Histogram
|
||||
public uint Flags2;
|
||||
// EnableHistogram : 1 // enable histogram info collection
|
||||
// HistogramStartX : 12 // start X of Histogram window
|
||||
// HistogramStartY : 12 // start Y of Histogram window
|
||||
// Reserved1 : 7
|
||||
// HistogramEndX : 12 // end X of Histogram window
|
||||
// HistogramEndY : 12 // end y of Histogram window
|
||||
// Reserved2 : 8
|
||||
// Decode picture buffer related
|
||||
public sbyte CurrentOutputMemoryLayout;
|
||||
public Array3<sbyte> OutputMemoryLayout; // output NV12/NV24 setting. item 0:golden - 1: altref - 2: last
|
||||
public byte SegmentationFeatureDataUpdate;
|
||||
public Array3<byte> Reserved3;
|
||||
public uint ResultValue; // ucode return result
|
||||
public Array8<uint> PartitionOffset;
|
||||
public Array3<uint> Reserved4;
|
||||
#pragma warning restore CS0649
|
||||
|
||||
public Vp8PictureInfo Convert()
|
||||
{
|
||||
return new Vp8PictureInfo()
|
||||
{
|
||||
KeyFrame = KeyFrame != 0,
|
||||
FirstPartSize = FirstPartSize,
|
||||
Version = Version,
|
||||
FrameWidth = FrameWidth,
|
||||
FrameHeight = FrameHeight
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
33
Ryujinx.Graphics.Nvdec/Vp8Decoder.cs
Normal file
33
Ryujinx.Graphics.Nvdec/Vp8Decoder.cs
Normal file
|
@ -0,0 +1,33 @@
|
|||
using Ryujinx.Graphics.Nvdec.FFmpeg.Vp8;
|
||||
using Ryujinx.Graphics.Nvdec.Image;
|
||||
using Ryujinx.Graphics.Nvdec.Types.Vp8;
|
||||
using Ryujinx.Graphics.Video;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec
|
||||
{
|
||||
static class Vp8Decoder
|
||||
{
|
||||
public static void Decode(NvdecDecoderContext context, ResourceManager rm, ref NvdecRegisters state)
|
||||
{
|
||||
PictureInfo pictureInfo = rm.Gmm.DeviceRead<PictureInfo>(state.SetPictureInfoOffset);
|
||||
ReadOnlySpan<byte> bitstream = rm.Gmm.DeviceGetSpan(state.SetBitstreamOffset, (int)pictureInfo.VLDBufferSize);
|
||||
|
||||
Decoder decoder = context.GetVp8Decoder();
|
||||
|
||||
ISurface outputSurface = rm.Cache.Get(decoder, 0, 0, pictureInfo.FrameWidth, pictureInfo.FrameHeight);
|
||||
|
||||
Vp8PictureInfo info = pictureInfo.Convert();
|
||||
|
||||
uint lumaOffset = state.SetSurfaceLumaOffset[3];
|
||||
uint chromaOffset = state.SetSurfaceChromaOffset[3];
|
||||
|
||||
if (decoder.Decode(ref info, outputSurface, bitstream))
|
||||
{
|
||||
SurfaceWriter.Write(rm.Gmm, outputSurface, lumaOffset, chromaOffset);
|
||||
}
|
||||
|
||||
rm.Cache.Put(outputSurface);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue