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
|
@ -5,27 +5,26 @@ using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.H264
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg
|
||||||
{
|
{
|
||||||
unsafe class FFmpegContext : IDisposable
|
unsafe class FFmpegContext : IDisposable
|
||||||
{
|
{
|
||||||
private readonly AVCodec_decode _h264Decode;
|
private readonly AVCodec_decode _decodeFrame;
|
||||||
private static readonly av_log_set_callback_callback _logFunc;
|
private static readonly av_log_set_callback_callback _logFunc;
|
||||||
private readonly AVCodec* _codec;
|
private readonly AVCodec* _codec;
|
||||||
private AVPacket* _packet;
|
private AVPacket* _packet;
|
||||||
private AVCodecContext* _context;
|
private AVCodecContext* _context;
|
||||||
|
|
||||||
public FFmpegContext()
|
public FFmpegContext(AVCodecID codecId)
|
||||||
{
|
{
|
||||||
_codec = ffmpeg.avcodec_find_decoder(AVCodecID.AV_CODEC_ID_H264);
|
_codec = ffmpeg.avcodec_find_decoder(codecId);
|
||||||
_context = ffmpeg.avcodec_alloc_context3(_codec);
|
_context = ffmpeg.avcodec_alloc_context3(_codec);
|
||||||
_context->debug |= ffmpeg.FF_DEBUG_MMCO;
|
|
||||||
|
|
||||||
ffmpeg.avcodec_open2(_context, _codec, null);
|
ffmpeg.avcodec_open2(_context, _codec, null);
|
||||||
|
|
||||||
_packet = ffmpeg.av_packet_alloc();
|
_packet = ffmpeg.av_packet_alloc();
|
||||||
|
|
||||||
_h264Decode = Marshal.GetDelegateForFunctionPointer<AVCodec_decode>(_codec->decode.Pointer);
|
_decodeFrame = Marshal.GetDelegateForFunctionPointer<AVCodec_decode>(_codec->decode.Pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FFmpegContext()
|
static FFmpegContext()
|
||||||
|
@ -115,7 +114,7 @@ namespace Ryujinx.Graphics.Nvdec.H264
|
||||||
{
|
{
|
||||||
_packet->data = ptr;
|
_packet->data = ptr;
|
||||||
_packet->size = bitstream.Length;
|
_packet->size = bitstream.Length;
|
||||||
result = _h264Decode(_context, output.Frame, &gotFrame, _packet);
|
result = _decodeFrame(_context, output.Frame, &gotFrame, _packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gotFrame == 0)
|
if (gotFrame == 0)
|
||||||
|
@ -126,7 +125,7 @@ namespace Ryujinx.Graphics.Nvdec.H264
|
||||||
// Get the next delayed frame by passing a 0 length packet.
|
// Get the next delayed frame by passing a 0 length packet.
|
||||||
_packet->data = null;
|
_packet->data = null;
|
||||||
_packet->size = 0;
|
_packet->size = 0;
|
||||||
result = _h264Decode(_context, output.Frame, &gotFrame, _packet);
|
result = _decodeFrame(_context, output.Frame, &gotFrame, _packet);
|
||||||
|
|
||||||
// We need to set B frames to 0 as we already consumed all delayed frames.
|
// We need to set B frames to 0 as we already consumed all delayed frames.
|
||||||
// This prevents the decoder from trying to return a delayed frame next time.
|
// This prevents the decoder from trying to return a delayed frame next time.
|
||||||
|
@ -138,6 +137,7 @@ namespace Ryujinx.Graphics.Nvdec.H264
|
||||||
if (gotFrame == 0)
|
if (gotFrame == 0)
|
||||||
{
|
{
|
||||||
ffmpeg.av_frame_unref(output.Frame);
|
ffmpeg.av_frame_unref(output.Frame);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
using Ryujinx.Graphics.Video;
|
using FFmpeg.AutoGen;
|
||||||
|
using Ryujinx.Graphics.Video;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.H264
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg.H264
|
||||||
{
|
{
|
||||||
public sealed class Decoder : IH264Decoder
|
public sealed class Decoder : IH264Decoder
|
||||||
{
|
{
|
||||||
|
@ -11,7 +12,7 @@ namespace Ryujinx.Graphics.Nvdec.H264
|
||||||
|
|
||||||
private readonly byte[] _workBuffer = new byte[WorkBufferSize];
|
private readonly byte[] _workBuffer = new byte[WorkBufferSize];
|
||||||
|
|
||||||
private FFmpegContext _context = new FFmpegContext();
|
private FFmpegContext _context = new FFmpegContext(AVCodecID.AV_CODEC_ID_H264);
|
||||||
|
|
||||||
private int _oldOutputWidth;
|
private int _oldOutputWidth;
|
||||||
private int _oldOutputHeight;
|
private int _oldOutputHeight;
|
||||||
|
@ -29,7 +30,7 @@ namespace Ryujinx.Graphics.Nvdec.H264
|
||||||
outSurf.RequestedHeight != _oldOutputHeight)
|
outSurf.RequestedHeight != _oldOutputHeight)
|
||||||
{
|
{
|
||||||
_context.Dispose();
|
_context.Dispose();
|
||||||
_context = new FFmpegContext();
|
_context = new FFmpegContext(AVCodecID.AV_CODEC_ID_H264);
|
||||||
|
|
||||||
_oldOutputWidth = outSurf.RequestedWidth;
|
_oldOutputWidth = outSurf.RequestedWidth;
|
||||||
_oldOutputHeight = outSurf.RequestedHeight;
|
_oldOutputHeight = outSurf.RequestedHeight;
|
|
@ -1,7 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.H264
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg.H264
|
||||||
{
|
{
|
||||||
struct H264BitStreamWriter
|
struct H264BitStreamWriter
|
||||||
{
|
{
|
|
@ -2,7 +2,7 @@
|
||||||
using Ryujinx.Graphics.Video;
|
using Ryujinx.Graphics.Video;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.H264
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg.H264
|
||||||
{
|
{
|
||||||
static class SpsAndPpsReconstruction
|
static class SpsAndPpsReconstruction
|
||||||
{
|
{
|
|
@ -1,4 +1,4 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
@ -6,10 +6,11 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FFmpeg.AutoGen" Version="4.4.0" />
|
<PackageReference Include="FFmpeg.AutoGen" Version="4.4.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Video\Ryujinx.Graphics.Video.csproj" />
|
<ProjectReference Include="..\Ryujinx.Graphics.Video\Ryujinx.Graphics.Video.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
using Ryujinx.Graphics.Video;
|
using Ryujinx.Graphics.Video;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.H264
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg
|
||||||
{
|
{
|
||||||
unsafe class Surface : ISurface
|
unsafe class Surface : ISurface
|
||||||
{
|
{
|
53
Ryujinx.Graphics.Nvdec.FFmpeg/Vp8/Decoder.cs
Normal file
53
Ryujinx.Graphics.Nvdec.FFmpeg/Vp8/Decoder.cs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
using FFmpeg.AutoGen;
|
||||||
|
using Ryujinx.Graphics.Video;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Vp8
|
||||||
|
{
|
||||||
|
public sealed class Decoder : IDecoder
|
||||||
|
{
|
||||||
|
public bool IsHardwareAccelerated => false;
|
||||||
|
|
||||||
|
private readonly FFmpegContext _context = new FFmpegContext(AVCodecID.AV_CODEC_ID_VP8);
|
||||||
|
|
||||||
|
public ISurface CreateSurface(int width, int height)
|
||||||
|
{
|
||||||
|
return new Surface(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Decode(ref Vp8PictureInfo pictureInfo, ISurface output, ReadOnlySpan<byte> bitstream)
|
||||||
|
{
|
||||||
|
Surface outSurf = (Surface)output;
|
||||||
|
|
||||||
|
int uncompHeaderSize = pictureInfo.KeyFrame ? 10 : 3;
|
||||||
|
|
||||||
|
byte[] frame = new byte[bitstream.Length + uncompHeaderSize];
|
||||||
|
|
||||||
|
uint firstPartSizeShifted = pictureInfo.FirstPartSize << 5;
|
||||||
|
|
||||||
|
frame[0] = (byte)(pictureInfo.KeyFrame ? 0 : 1);
|
||||||
|
frame[0] |= (byte)((pictureInfo.Version & 7) << 1);
|
||||||
|
frame[0] |= 1 << 4;
|
||||||
|
frame[0] |= (byte)firstPartSizeShifted;
|
||||||
|
frame[1] |= (byte)(firstPartSizeShifted >> 8);
|
||||||
|
frame[2] |= (byte)(firstPartSizeShifted >> 16);
|
||||||
|
|
||||||
|
if (pictureInfo.KeyFrame)
|
||||||
|
{
|
||||||
|
frame[3] = 0x9d;
|
||||||
|
frame[4] = 0x01;
|
||||||
|
frame[5] = 0x2a;
|
||||||
|
frame[6] = (byte)pictureInfo.FrameWidth;
|
||||||
|
frame[7] = (byte)((pictureInfo.FrameWidth >> 8) & 0x3F);
|
||||||
|
frame[8] = (byte)pictureInfo.FrameHeight;
|
||||||
|
frame[9] = (byte)((pictureInfo.FrameHeight >> 8) & 0x3F);
|
||||||
|
}
|
||||||
|
|
||||||
|
bitstream.CopyTo(new Span<byte>(frame).Slice(uncompHeaderSize));
|
||||||
|
|
||||||
|
return _context.DecodeFrame(outSurf, frame) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose() => _context.Dispose();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
using Ryujinx.Graphics.Nvdec.H264;
|
using Ryujinx.Graphics.Nvdec.FFmpeg.H264;
|
||||||
using Ryujinx.Graphics.Nvdec.Image;
|
using Ryujinx.Graphics.Nvdec.Image;
|
||||||
using Ryujinx.Graphics.Nvdec.Types.H264;
|
using Ryujinx.Graphics.Nvdec.Types.H264;
|
||||||
using Ryujinx.Graphics.Video;
|
using Ryujinx.Graphics.Video;
|
||||||
|
@ -10,7 +10,7 @@ namespace Ryujinx.Graphics.Nvdec
|
||||||
{
|
{
|
||||||
private const int MbSizeInPixels = 16;
|
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);
|
PictureInfo pictureInfo = rm.Gmm.DeviceRead<PictureInfo>(state.SetPictureInfoOffset);
|
||||||
H264PictureInfo info = pictureInfo.Convert();
|
H264PictureInfo info = pictureInfo.Convert();
|
||||||
|
@ -25,7 +25,7 @@ namespace Ryujinx.Graphics.Nvdec
|
||||||
uint lumaOffset = state.SetSurfaceLumaOffset[surfaceIndex];
|
uint lumaOffset = state.SetSurfaceLumaOffset[surfaceIndex];
|
||||||
uint chromaOffset = state.SetSurfaceChromaOffset[surfaceIndex];
|
uint chromaOffset = state.SetSurfaceChromaOffset[surfaceIndex];
|
||||||
|
|
||||||
Decoder decoder = context.GetDecoder();
|
Decoder decoder = context.GetH264Decoder();
|
||||||
|
|
||||||
ISurface outputSurface = rm.Cache.Get(decoder, 0, 0, width, height);
|
ISurface outputSurface = rm.Cache.Get(decoder, 0, 0, width, height);
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,29 @@
|
||||||
using Ryujinx.Graphics.Nvdec.H264;
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec
|
namespace Ryujinx.Graphics.Nvdec
|
||||||
{
|
{
|
||||||
class NvdecDecoderContext : IDisposable
|
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()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_decoder?.Dispose();
|
_h264Decoder?.Dispose();
|
||||||
_decoder = null;
|
_h264Decoder = null;
|
||||||
|
|
||||||
|
_vp8Decoder?.Dispose();
|
||||||
|
_vp8Decoder = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -68,6 +68,9 @@ namespace Ryujinx.Graphics.Nvdec
|
||||||
case CodecId.H264:
|
case CodecId.H264:
|
||||||
H264Decoder.Decode(_currentContext, _rm, ref _state.State);
|
H264Decoder.Decode(_currentContext, _rm, ref _state.State);
|
||||||
break;
|
break;
|
||||||
|
case CodecId.Vp8:
|
||||||
|
Vp8Decoder.Decode(_currentContext, _rm, ref _state.State);
|
||||||
|
break;
|
||||||
case CodecId.Vp9:
|
case CodecId.Vp9:
|
||||||
Vp9Decoder.Decode(_rm, ref _state.State);
|
Vp9Decoder.Decode(_rm, ref _state.State);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Device\Ryujinx.Graphics.Device.csproj" />
|
<ProjectReference Include="..\Ryujinx.Graphics.Device\Ryujinx.Graphics.Device.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.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.Nvdec.Vp9\Ryujinx.Graphics.Nvdec.Vp9.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Texture\Ryujinx.Graphics.Texture.csproj" />
|
<ProjectReference Include="..\Ryujinx.Graphics.Texture\Ryujinx.Graphics.Texture.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Video\Ryujinx.Graphics.Video.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
Ryujinx.Graphics.Video/Vp8PictureInfo.cs
Normal file
11
Ryujinx.Graphics.Video/Vp8PictureInfo.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
namespace Ryujinx.Graphics.Video
|
||||||
|
{
|
||||||
|
public ref struct Vp8PictureInfo
|
||||||
|
{
|
||||||
|
public bool KeyFrame;
|
||||||
|
public uint FirstPartSize;
|
||||||
|
public uint Version;
|
||||||
|
public ushort FrameWidth;
|
||||||
|
public ushort FrameHeight;
|
||||||
|
}
|
||||||
|
}
|
14
Ryujinx.sln
14
Ryujinx.sln
|
@ -51,8 +51,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec.Vp9"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vic", "Ryujinx.Graphics.Vic\Ryujinx.Graphics.Vic.csproj", "{81BB2C11-9408-4EA3-822E-42987AF54429}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vic", "Ryujinx.Graphics.Vic\Ryujinx.Graphics.Vic.csproj", "{81BB2C11-9408-4EA3-822E-42987AF54429}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec.H264", "Ryujinx.Graphics.Nvdec.H264\Ryujinx.Graphics.Nvdec.H264.csproj", "{990F9601-343E-46CB-8529-B498FA761A92}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Video", "Ryujinx.Graphics.Video\Ryujinx.Graphics.Video.csproj", "{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Video", "Ryujinx.Graphics.Video\Ryujinx.Graphics.Video.csproj", "{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.OpenAL", "Ryujinx.Audio.Backends.OpenAL\Ryujinx.Audio.Backends.OpenAL.csproj", "{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.OpenAL", "Ryujinx.Audio.Backends.OpenAL\Ryujinx.Audio.Backends.OpenAL.csproj", "{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}"
|
||||||
|
@ -67,7 +65,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.SDL2.Common", "Ryuj
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SDL2", "Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj", "{D99A395A-8569-4DB0-B336-900647890052}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SDL2", "Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj", "{D99A395A-8569-4DB0-B336-900647890052}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Headless.SDL2", "Ryujinx.Headless.SDL2\Ryujinx.Headless.SDL2.csproj", "{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Headless.SDL2", "Ryujinx.Headless.SDL2\Ryujinx.Headless.SDL2.csproj", "{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Graphics.Nvdec.FFmpeg", "Ryujinx.Graphics.Nvdec.FFmpeg\Ryujinx.Graphics.Nvdec.FFmpeg.csproj", "{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
@ -159,10 +159,6 @@ Global
|
||||||
{81BB2C11-9408-4EA3-822E-42987AF54429}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{81BB2C11-9408-4EA3-822E-42987AF54429}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{81BB2C11-9408-4EA3-822E-42987AF54429}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{81BB2C11-9408-4EA3-822E-42987AF54429}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{81BB2C11-9408-4EA3-822E-42987AF54429}.Release|Any CPU.Build.0 = Release|Any CPU
|
{81BB2C11-9408-4EA3-822E-42987AF54429}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{990F9601-343E-46CB-8529-B498FA761A92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{990F9601-343E-46CB-8529-B498FA761A92}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{990F9601-343E-46CB-8529-B498FA761A92}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{990F9601-343E-46CB-8529-B498FA761A92}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
@ -195,6 +191,10 @@ Global
|
||||||
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Release|Any CPU.Build.0 = Release|Any CPU
|
{390DC343-5CB4-4C79-A5DD-E3ED235E4C49}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
<PackageReference Include="DiscordRichPresence" Version="1.0.175" />
|
<PackageReference Include="DiscordRichPresence" Version="1.0.175" />
|
||||||
<PackageReference Include="GtkSharp" Version="3.22.25.128" />
|
<PackageReference Include="GtkSharp" Version="3.22.25.128" />
|
||||||
<PackageReference Include="GtkSharp.Dependencies" Version="1.1.0" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
<PackageReference Include="GtkSharp.Dependencies" Version="1.1.0" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
||||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="4.4.0-build7" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="4.4.0-build9" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
||||||
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
||||||
<PackageReference Include="OpenTK.Graphics" Version="4.5.0" />
|
<PackageReference Include="OpenTK.Graphics" Version="4.5.0" />
|
||||||
<PackageReference Include="SPB" Version="0.0.3-build15" />
|
<PackageReference Include="SPB" Version="0.0.3-build15" />
|
||||||
|
|
Reference in a new issue