Remove dependency for FFmpeg.AutoGen and Update FFmpeg to 5.0.1 for Windows (#3466)
* Remove dependency for FFMpeg.AutoGen Also prepare for FFMpeg 5.0 and 5.1 * Update Ryujinx.Graphics.Nvdec.Dependencies to 5.0.1-build10 * Address gdkchan's comments * Address Ack's comment * Address gdkchan's comment
This commit is contained in:
parent
70ec5def9c
commit
c5bddfeab8
@ -28,7 +28,7 @@
|
|||||||
<PackageReference Include="FluentAvaloniaUI" Version="1.4.1" />
|
<PackageReference Include="FluentAvaloniaUI" Version="1.4.1" />
|
||||||
|
|
||||||
<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="Ryujinx.Graphics.Nvdec.Dependencies" Version="4.4.0-build9" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build10" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
||||||
<PackageReference Include="OpenTK.Graphics" Version="4.7.2" />
|
<PackageReference Include="OpenTK.Graphics" Version="4.7.2" />
|
||||||
<PackageReference Include="SPB" Version="0.0.4-build17" />
|
<PackageReference Include="SPB" Version="0.0.4-build17" />
|
||||||
<PackageReference Include="SharpZipLib" Version="1.3.3" />
|
<PackageReference Include="SharpZipLib" Version="1.3.3" />
|
||||||
|
@ -1,23 +1,21 @@
|
|||||||
using FFmpeg.AutoGen;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Graphics.Nvdec.FFmpeg.Native;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.FFmpeg
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg
|
||||||
{
|
{
|
||||||
unsafe class FFmpegContext : IDisposable
|
unsafe class FFmpegContext : IDisposable
|
||||||
{
|
{
|
||||||
private readonly AVCodec_decode _decodeFrame;
|
private readonly FFCodec.AVCodec_decode _decodeFrame;
|
||||||
private static readonly av_log_set_callback_callback _logFunc;
|
private static readonly FFmpegApi.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(AVCodecID codecId)
|
public FFmpegContext(AVCodecID codecId)
|
||||||
{
|
{
|
||||||
_codec = ffmpeg.avcodec_find_decoder(codecId);
|
_codec = FFmpegApi.avcodec_find_decoder(codecId);
|
||||||
if (_codec == null)
|
if (_codec == null)
|
||||||
{
|
{
|
||||||
Logger.Error?.PrintMsg(LogClass.FFmpeg, $"Codec wasn't found. Make sure you have the {codecId} codec present in your FFmpeg installation.");
|
Logger.Error?.PrintMsg(LogClass.FFmpeg, $"Codec wasn't found. Make sure you have the {codecId} codec present in your FFmpeg installation.");
|
||||||
@ -25,7 +23,7 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_context = ffmpeg.avcodec_alloc_context3(_codec);
|
_context = FFmpegApi.avcodec_alloc_context3(_codec);
|
||||||
if (_context == null)
|
if (_context == null)
|
||||||
{
|
{
|
||||||
Logger.Error?.PrintMsg(LogClass.FFmpeg, "Codec context couldn't be allocated.");
|
Logger.Error?.PrintMsg(LogClass.FFmpeg, "Codec context couldn't be allocated.");
|
||||||
@ -33,14 +31,14 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ffmpeg.avcodec_open2(_context, _codec, null) != 0)
|
if (FFmpegApi.avcodec_open2(_context, _codec, null) != 0)
|
||||||
{
|
{
|
||||||
Logger.Error?.PrintMsg(LogClass.FFmpeg, "Codec couldn't be opened.");
|
Logger.Error?.PrintMsg(LogClass.FFmpeg, "Codec couldn't be opened.");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_packet = ffmpeg.av_packet_alloc();
|
_packet = FFmpegApi.av_packet_alloc();
|
||||||
if (_packet == null)
|
if (_packet == null)
|
||||||
{
|
{
|
||||||
Logger.Error?.PrintMsg(LogClass.FFmpeg, "Packet couldn't be allocated.");
|
Logger.Error?.PrintMsg(LogClass.FFmpeg, "Packet couldn't be allocated.");
|
||||||
@ -48,52 +46,39 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_decodeFrame = Marshal.GetDelegateForFunctionPointer<AVCodec_decode>(_codec->decode.Pointer);
|
int avCodecRawVersion = FFmpegApi.avcodec_version();
|
||||||
|
int avCodecMajorVersion = avCodecRawVersion >> 16;
|
||||||
|
int avCodecMinorVersion = (avCodecRawVersion >> 8) & 0xFF;
|
||||||
|
|
||||||
|
// libavcodec 59.24 changed AvCodec to move its private API and also move the codec function to an union.
|
||||||
|
if (avCodecMajorVersion > 59 || (avCodecMajorVersion == 59 && avCodecMinorVersion > 24))
|
||||||
|
{
|
||||||
|
_decodeFrame = Marshal.GetDelegateForFunctionPointer<FFCodec.AVCodec_decode>(((FFCodec*)_codec)->CodecCallback);
|
||||||
|
}
|
||||||
|
// libavcodec 59.x changed AvCodec private API layout.
|
||||||
|
else if (avCodecMajorVersion == 59)
|
||||||
|
{
|
||||||
|
_decodeFrame = Marshal.GetDelegateForFunctionPointer<FFCodec.AVCodec_decode>(((FFCodecLegacy<AVCodec>*)_codec)->Decode);
|
||||||
|
}
|
||||||
|
// libavcodec 58.x and lower
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_decodeFrame = Marshal.GetDelegateForFunctionPointer<FFCodec.AVCodec_decode>(((FFCodecLegacy<AVCodecLegacy>*)_codec)->Decode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static FFmpegContext()
|
static FFmpegContext()
|
||||||
{
|
{
|
||||||
SetRootPath();
|
|
||||||
|
|
||||||
_logFunc = Log;
|
_logFunc = Log;
|
||||||
|
|
||||||
// Redirect log output.
|
// Redirect log output.
|
||||||
ffmpeg.av_log_set_level(ffmpeg.AV_LOG_MAX_OFFSET);
|
FFmpegApi.av_log_set_level(AVLog.MaxOffset);
|
||||||
ffmpeg.av_log_set_callback(_logFunc);
|
FFmpegApi.av_log_set_callback(_logFunc);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetRootPath()
|
private static void Log(void* ptr, AVLog level, string format, byte* vl)
|
||||||
{
|
{
|
||||||
if (OperatingSystem.IsLinux())
|
if (level > FFmpegApi.av_log_get_level())
|
||||||
{
|
|
||||||
// Configure FFmpeg search path
|
|
||||||
Process lddProcess = Process.Start(new ProcessStartInfo
|
|
||||||
{
|
|
||||||
FileName = "/bin/sh",
|
|
||||||
Arguments = "-c \"ldd $(which ffmpeg 2>/dev/null) | grep libavfilter\" 2>/dev/null",
|
|
||||||
UseShellExecute = false,
|
|
||||||
RedirectStandardOutput = true
|
|
||||||
});
|
|
||||||
|
|
||||||
string lddOutput = lddProcess.StandardOutput.ReadToEnd();
|
|
||||||
|
|
||||||
lddProcess.WaitForExit();
|
|
||||||
lddProcess.Close();
|
|
||||||
|
|
||||||
if (lddOutput.Contains(" => "))
|
|
||||||
{
|
|
||||||
ffmpeg.RootPath = Path.GetDirectoryName(lddOutput.Split(" => ")[1]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.Error?.PrintMsg(LogClass.FFmpeg, "FFmpeg wasn't found. Make sure that you have it installed and up to date.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void Log(void* p0, int level, string format, byte* vl)
|
|
||||||
{
|
|
||||||
if (level > ffmpeg.av_log_get_level())
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -102,65 +87,67 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg
|
|||||||
byte* lineBuffer = stackalloc byte[lineSize];
|
byte* lineBuffer = stackalloc byte[lineSize];
|
||||||
int printPrefix = 1;
|
int printPrefix = 1;
|
||||||
|
|
||||||
ffmpeg.av_log_format_line(p0, level, format, vl, lineBuffer, lineSize, &printPrefix);
|
FFmpegApi.av_log_format_line(ptr, level, format, vl, lineBuffer, lineSize, &printPrefix);
|
||||||
|
|
||||||
string line = Marshal.PtrToStringAnsi((IntPtr)lineBuffer).Trim();
|
string line = Marshal.PtrToStringAnsi((IntPtr)lineBuffer).Trim();
|
||||||
|
|
||||||
switch (level)
|
switch (level)
|
||||||
{
|
{
|
||||||
case ffmpeg.AV_LOG_PANIC:
|
case AVLog.Panic:
|
||||||
case ffmpeg.AV_LOG_FATAL:
|
case AVLog.Fatal:
|
||||||
case ffmpeg.AV_LOG_ERROR:
|
case AVLog.Error:
|
||||||
Logger.Error?.Print(LogClass.FFmpeg, line);
|
Logger.Error?.Print(LogClass.FFmpeg, line);
|
||||||
break;
|
break;
|
||||||
case ffmpeg.AV_LOG_WARNING:
|
case AVLog.Warning:
|
||||||
Logger.Warning?.Print(LogClass.FFmpeg, line);
|
Logger.Warning?.Print(LogClass.FFmpeg, line);
|
||||||
break;
|
break;
|
||||||
case ffmpeg.AV_LOG_INFO:
|
case AVLog.Info:
|
||||||
Logger.Info?.Print(LogClass.FFmpeg, line);
|
Logger.Info?.Print(LogClass.FFmpeg, line);
|
||||||
break;
|
break;
|
||||||
case ffmpeg.AV_LOG_VERBOSE:
|
case AVLog.Verbose:
|
||||||
case ffmpeg.AV_LOG_DEBUG:
|
case AVLog.Debug:
|
||||||
case ffmpeg.AV_LOG_TRACE:
|
|
||||||
Logger.Debug?.Print(LogClass.FFmpeg, line);
|
Logger.Debug?.Print(LogClass.FFmpeg, line);
|
||||||
break;
|
break;
|
||||||
|
case AVLog.Trace:
|
||||||
|
Logger.Trace?.Print(LogClass.FFmpeg, line);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int DecodeFrame(Surface output, ReadOnlySpan<byte> bitstream)
|
public int DecodeFrame(Surface output, ReadOnlySpan<byte> bitstream)
|
||||||
{
|
{
|
||||||
ffmpeg.av_frame_unref(output.Frame);
|
FFmpegApi.av_frame_unref(output.Frame);
|
||||||
|
|
||||||
int result;
|
int result;
|
||||||
int gotFrame;
|
int gotFrame;
|
||||||
|
|
||||||
fixed (byte* ptr = bitstream)
|
fixed (byte* ptr = bitstream)
|
||||||
{
|
{
|
||||||
_packet->data = ptr;
|
_packet->Data = ptr;
|
||||||
_packet->size = bitstream.Length;
|
_packet->Size = bitstream.Length;
|
||||||
result = _decodeFrame(_context, output.Frame, &gotFrame, _packet);
|
result = _decodeFrame(_context, output.Frame, &gotFrame, _packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gotFrame == 0)
|
if (gotFrame == 0)
|
||||||
{
|
{
|
||||||
ffmpeg.av_frame_unref(output.Frame);
|
FFmpegApi.av_frame_unref(output.Frame);
|
||||||
|
|
||||||
// If the frame was not delivered, it was probably delayed.
|
// If the frame was not delivered, it was probably delayed.
|
||||||
// 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 = _decodeFrame(_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.
|
||||||
_context->has_b_frames = 0;
|
_context->HasBFrames = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ffmpeg.av_packet_unref(_packet);
|
FFmpegApi.av_packet_unref(_packet);
|
||||||
|
|
||||||
if (gotFrame == 0)
|
if (gotFrame == 0)
|
||||||
{
|
{
|
||||||
ffmpeg.av_frame_unref(output.Frame);
|
FFmpegApi.av_frame_unref(output.Frame);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -172,14 +159,14 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg
|
|||||||
{
|
{
|
||||||
fixed (AVPacket** ppPacket = &_packet)
|
fixed (AVPacket** ppPacket = &_packet)
|
||||||
{
|
{
|
||||||
ffmpeg.av_packet_free(ppPacket);
|
FFmpegApi.av_packet_free(ppPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
ffmpeg.avcodec_close(_context);
|
FFmpegApi.avcodec_close(_context);
|
||||||
|
|
||||||
fixed (AVCodecContext** ppContext = &_context)
|
fixed (AVCodecContext** ppContext = &_context)
|
||||||
{
|
{
|
||||||
ffmpeg.avcodec_free_context(ppContext);
|
FFmpegApi.avcodec_free_context(ppContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using FFmpeg.AutoGen;
|
using Ryujinx.Graphics.Nvdec.FFmpeg.Native;
|
||||||
using Ryujinx.Graphics.Video;
|
using Ryujinx.Graphics.Video;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
|
25
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVCodec.cs
Normal file
25
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVCodec.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||||
|
{
|
||||||
|
struct AVCodec
|
||||||
|
{
|
||||||
|
#pragma warning disable CS0649
|
||||||
|
public unsafe byte* Name;
|
||||||
|
public unsafe byte* LongName;
|
||||||
|
public int Type;
|
||||||
|
public AVCodecID Id;
|
||||||
|
public int Capabilities;
|
||||||
|
public byte MaxLowRes;
|
||||||
|
public unsafe AVRational* SupportedFramerates;
|
||||||
|
public IntPtr PixFmts;
|
||||||
|
public IntPtr SupportedSamplerates;
|
||||||
|
public IntPtr SampleFmts;
|
||||||
|
// Deprecated
|
||||||
|
public unsafe ulong* ChannelLayouts;
|
||||||
|
public unsafe IntPtr PrivClass;
|
||||||
|
public IntPtr Profiles;
|
||||||
|
public unsafe byte* WrapperName;
|
||||||
|
#pragma warning restore CS0649
|
||||||
|
}
|
||||||
|
}
|
171
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVCodecContext.cs
Normal file
171
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVCodecContext.cs
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
using Ryujinx.Common.Memory;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||||
|
{
|
||||||
|
struct AVCodecContext
|
||||||
|
{
|
||||||
|
#pragma warning disable CS0649
|
||||||
|
public unsafe IntPtr AvClass;
|
||||||
|
public int LogLevelOffset;
|
||||||
|
public int CodecType;
|
||||||
|
public unsafe AVCodecLegacy* Codec;
|
||||||
|
public AVCodecID CodecId;
|
||||||
|
public uint CodecTag;
|
||||||
|
public IntPtr PrivData;
|
||||||
|
public IntPtr Internal;
|
||||||
|
public IntPtr Opaque;
|
||||||
|
public long BitRate;
|
||||||
|
public int BitRateTolerance;
|
||||||
|
public int GlobalQuality;
|
||||||
|
public int CompressionLevel;
|
||||||
|
public int Flags;
|
||||||
|
public int Flags2;
|
||||||
|
public IntPtr ExtraData;
|
||||||
|
public int ExtraDataSize;
|
||||||
|
public AVRational TimeBase;
|
||||||
|
public int TicksPerFrame;
|
||||||
|
public int Delay;
|
||||||
|
public int Width;
|
||||||
|
public int Height;
|
||||||
|
public int CodedWidth;
|
||||||
|
public int CodedHeight;
|
||||||
|
public int GopSize;
|
||||||
|
public int PixFmt;
|
||||||
|
public IntPtr DrawHorizBand;
|
||||||
|
public IntPtr GetFormat;
|
||||||
|
public int MaxBFrames;
|
||||||
|
public float BQuantFactor;
|
||||||
|
public float BQuantOffset;
|
||||||
|
public int HasBFrames;
|
||||||
|
public float IQuantFactor;
|
||||||
|
public float IQuantOffset;
|
||||||
|
public float LumiMasking;
|
||||||
|
public float TemporalCplxMasking;
|
||||||
|
public float SpatialCplxMasking;
|
||||||
|
public float PMasking;
|
||||||
|
public float DarkMasking;
|
||||||
|
public int SliceCount;
|
||||||
|
public IntPtr SliceOffset;
|
||||||
|
public AVRational SampleAspectRatio;
|
||||||
|
public int MeCmp;
|
||||||
|
public int MeSubCmp;
|
||||||
|
public int MbCmp;
|
||||||
|
public int IldctCmp;
|
||||||
|
public int DiaSize;
|
||||||
|
public int LastPredictorCount;
|
||||||
|
public int MePreCmp;
|
||||||
|
public int PreDiaSize;
|
||||||
|
public int MeSubpelQuality;
|
||||||
|
public int MeRange;
|
||||||
|
public int SliceFlags;
|
||||||
|
public int MbDecision;
|
||||||
|
public IntPtr IntraMatrix;
|
||||||
|
public IntPtr InterMatrix;
|
||||||
|
public int IntraDcPrecision;
|
||||||
|
public int SkipTop;
|
||||||
|
public int SkipBottom;
|
||||||
|
public int MbLmin;
|
||||||
|
public int MbLmax;
|
||||||
|
public int BidirRefine;
|
||||||
|
public int KeyintMin;
|
||||||
|
public int Refs;
|
||||||
|
public int Mv0Threshold;
|
||||||
|
public int ColorPrimaries;
|
||||||
|
public int ColorPrc;
|
||||||
|
public int Colorspace;
|
||||||
|
public int ColorRange;
|
||||||
|
public int ChromaSampleLocation;
|
||||||
|
public int Slices;
|
||||||
|
public int FieldOrder;
|
||||||
|
public int SampleRate;
|
||||||
|
public int Channels;
|
||||||
|
public int SampleFmt;
|
||||||
|
public int FrameSize;
|
||||||
|
public int FrameNumber;
|
||||||
|
public int BlockAlign;
|
||||||
|
public int CutOff;
|
||||||
|
public ulong ChannelLayout;
|
||||||
|
public ulong RequestChannelLayout;
|
||||||
|
public int AudioServiceType;
|
||||||
|
public int RequestSampleFmt;
|
||||||
|
public IntPtr GetBuffer2;
|
||||||
|
public float QCompress;
|
||||||
|
public float QBlur;
|
||||||
|
public int QMin;
|
||||||
|
public int QMax;
|
||||||
|
public int MaxQdiff;
|
||||||
|
public int RcBufferSize;
|
||||||
|
public int RcOverrideCount;
|
||||||
|
public IntPtr RcOverride;
|
||||||
|
public long RcMaxRate;
|
||||||
|
public long RcMinRate;
|
||||||
|
public float RcMax_available_vbv_use;
|
||||||
|
public float RcMin_vbv_overflow_use;
|
||||||
|
public int RcInitialBufferOccupancy;
|
||||||
|
public int Trellis;
|
||||||
|
public IntPtr StatsOut;
|
||||||
|
public IntPtr StatsIn;
|
||||||
|
public int WorkaroundBugs;
|
||||||
|
public int StrictStdCompliance;
|
||||||
|
public int ErrorConcealment;
|
||||||
|
public int Debug;
|
||||||
|
public int ErrRecognition;
|
||||||
|
public long ReorderedOpaque;
|
||||||
|
public IntPtr HwAccel;
|
||||||
|
public IntPtr HwAccelContext;
|
||||||
|
public Array8<ulong> Error;
|
||||||
|
public int DctAlgo;
|
||||||
|
public int IdctAlgo;
|
||||||
|
public int BitsPerCodedSample;
|
||||||
|
public int BitsPerRawSample;
|
||||||
|
public int LowRes;
|
||||||
|
public int ThreadCount;
|
||||||
|
public int ThreadType;
|
||||||
|
public int ActiveThreadType;
|
||||||
|
public int ThreadSafeCallbacks;
|
||||||
|
public IntPtr Execute;
|
||||||
|
public IntPtr Execute2;
|
||||||
|
public int NsseWeight;
|
||||||
|
public int Profile;
|
||||||
|
public int Level;
|
||||||
|
public int SkipLoopFilter;
|
||||||
|
public int SkipIdct;
|
||||||
|
public int SkipFrame;
|
||||||
|
public IntPtr SubtitleHeader;
|
||||||
|
public int SubtitleHeaderSize;
|
||||||
|
public int InitialPadding;
|
||||||
|
public AVRational Framerate;
|
||||||
|
public int SwPixFmt;
|
||||||
|
public AVRational PktTimebase;
|
||||||
|
public IntPtr CodecDescriptor;
|
||||||
|
public long PtsCorrectionNumFaultyPts;
|
||||||
|
public long PtsCorrectionNumFaultyDts;
|
||||||
|
public long PtsCorrectionLastPts;
|
||||||
|
public long PtsCorrectionLastDts;
|
||||||
|
public IntPtr SubCharenc;
|
||||||
|
public int SubCharencMode;
|
||||||
|
public int SkipAlpha;
|
||||||
|
public int SeekPreroll;
|
||||||
|
public int DebugMv;
|
||||||
|
public IntPtr ChromaIntraMatrix;
|
||||||
|
public IntPtr DumpSeparator;
|
||||||
|
public IntPtr CodecWhitelist;
|
||||||
|
public uint Properties;
|
||||||
|
public IntPtr CodedSideData;
|
||||||
|
public int NbCodedSideData;
|
||||||
|
public IntPtr HwFramesCtx;
|
||||||
|
public int SubTextFormat;
|
||||||
|
public int TrailingPadding;
|
||||||
|
public long MaxPixels;
|
||||||
|
public IntPtr HwDeviceCtx;
|
||||||
|
public int HwAccelFlags;
|
||||||
|
public int applyCropping;
|
||||||
|
public int ExtraHwFrames;
|
||||||
|
public int DiscardDamagedPercentage;
|
||||||
|
public long MaxSamples;
|
||||||
|
public int ExportSideData;
|
||||||
|
public IntPtr GetEncodeBuffer;
|
||||||
|
#pragma warning restore CS0649
|
||||||
|
}
|
||||||
|
}
|
8
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVCodecID.cs
Normal file
8
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVCodecID.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||||
|
{
|
||||||
|
enum AVCodecID
|
||||||
|
{
|
||||||
|
AV_CODEC_ID_H264 = 27,
|
||||||
|
AV_CODEC_ID_VP8 = 139,
|
||||||
|
}
|
||||||
|
}
|
26
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVCodecLegacy.cs
Normal file
26
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVCodecLegacy.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||||
|
{
|
||||||
|
struct AVCodecLegacy
|
||||||
|
{
|
||||||
|
#pragma warning disable CS0649
|
||||||
|
public unsafe byte* Name;
|
||||||
|
public unsafe byte* LongName;
|
||||||
|
public int Type;
|
||||||
|
public AVCodecID Id;
|
||||||
|
public int Capabilities;
|
||||||
|
public byte MaxLowRes;
|
||||||
|
public unsafe AVRational* SupportedFramerates;
|
||||||
|
public IntPtr PixFmts;
|
||||||
|
public IntPtr SupportedSamplerates;
|
||||||
|
public IntPtr SampleFmts;
|
||||||
|
// Deprecated
|
||||||
|
public unsafe ulong* ChannelLayouts;
|
||||||
|
public unsafe IntPtr PrivClass;
|
||||||
|
public IntPtr Profiles;
|
||||||
|
public unsafe byte* WrapperName;
|
||||||
|
public IntPtr ChLayouts;
|
||||||
|
#pragma warning restore CS0649
|
||||||
|
}
|
||||||
|
}
|
37
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVFrame.cs
Normal file
37
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVFrame.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
using Ryujinx.Common.Memory;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||||
|
{
|
||||||
|
struct AVFrame
|
||||||
|
{
|
||||||
|
#pragma warning disable CS0649
|
||||||
|
public Array8<IntPtr> Data;
|
||||||
|
public Array8<int> LineSize;
|
||||||
|
public IntPtr ExtendedData;
|
||||||
|
public int Width;
|
||||||
|
public int Height;
|
||||||
|
public int NumSamples;
|
||||||
|
public int Format;
|
||||||
|
public int KeyFrame;
|
||||||
|
public int PictureType;
|
||||||
|
public AVRational SampleAspectRatio;
|
||||||
|
public long Pts;
|
||||||
|
public long PktDts;
|
||||||
|
public AVRational TimeBase;
|
||||||
|
public int CodedPictureNumber;
|
||||||
|
public int DisplayPictureNumber;
|
||||||
|
public int Quality;
|
||||||
|
public IntPtr Opaque;
|
||||||
|
public int RepeatPicture;
|
||||||
|
public int InterlacedFrame;
|
||||||
|
public int TopFieldFirst;
|
||||||
|
public int PaletteHasChanged;
|
||||||
|
public long ReorderedOpaque;
|
||||||
|
public int SampleRate;
|
||||||
|
public ulong ChannelLayout;
|
||||||
|
#pragma warning restore CS0649
|
||||||
|
|
||||||
|
// NOTE: There is more after, but the layout kind of changed a bit and we don't need more than this. This is safe as we only manipulate this behind a reference.
|
||||||
|
}
|
||||||
|
}
|
15
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVLog.cs
Normal file
15
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVLog.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||||
|
{
|
||||||
|
enum AVLog
|
||||||
|
{
|
||||||
|
Panic = 0,
|
||||||
|
Fatal = 8,
|
||||||
|
Error = 16,
|
||||||
|
Warning = 24,
|
||||||
|
Info = 32,
|
||||||
|
Verbose = 40,
|
||||||
|
Debug = 48,
|
||||||
|
Trace = 56,
|
||||||
|
MaxOffset = 64
|
||||||
|
}
|
||||||
|
}
|
26
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVPacket.cs
Normal file
26
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVPacket.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
using AVBufferRef = System.IntPtr;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||||
|
{
|
||||||
|
struct AVPacket
|
||||||
|
{
|
||||||
|
#pragma warning disable CS0649
|
||||||
|
public unsafe AVBufferRef *Buf;
|
||||||
|
public long Pts;
|
||||||
|
public long Dts;
|
||||||
|
public unsafe byte* Data;
|
||||||
|
public int Size;
|
||||||
|
public int StreamIndex;
|
||||||
|
public int Flags;
|
||||||
|
public IntPtr SizeData;
|
||||||
|
public int SizeDataElems;
|
||||||
|
public long Duration;
|
||||||
|
public long Position;
|
||||||
|
public IntPtr Opaque;
|
||||||
|
public unsafe AVBufferRef *OpaqueRef;
|
||||||
|
public AVRational TimeBase;
|
||||||
|
#pragma warning restore CS0649
|
||||||
|
}
|
||||||
|
}
|
8
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVRational.cs
Normal file
8
Ryujinx.Graphics.Nvdec.FFmpeg/Native/AVRational.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||||
|
{
|
||||||
|
public struct AVRational
|
||||||
|
{
|
||||||
|
public int Numerator;
|
||||||
|
public int Denominator;
|
||||||
|
}
|
||||||
|
}
|
23
Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFCodec.cs
Normal file
23
Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFCodec.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||||
|
{
|
||||||
|
struct FFCodec
|
||||||
|
{
|
||||||
|
public unsafe delegate int AVCodec_decode(AVCodecContext* avctx, void* outdata, int* got_frame_ptr, AVPacket* avpkt);
|
||||||
|
|
||||||
|
#pragma warning disable CS0649
|
||||||
|
public AVCodec Base;
|
||||||
|
public int CapsInternalOrCbType;
|
||||||
|
public int PrivDataSize;
|
||||||
|
public IntPtr UpdateThreadContext;
|
||||||
|
public IntPtr UpdateThreadContextForUser;
|
||||||
|
public IntPtr Defaults;
|
||||||
|
public IntPtr InitStaticData;
|
||||||
|
public IntPtr Init;
|
||||||
|
public IntPtr CodecCallback;
|
||||||
|
#pragma warning restore CS0649
|
||||||
|
|
||||||
|
// NOTE: There is more after, but the layout kind of changed a bit and we don't need more than this. This is safe as we only manipulate this behind a reference.
|
||||||
|
}
|
||||||
|
}
|
23
Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFCodecLegacy.cs
Normal file
23
Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFCodecLegacy.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||||
|
{
|
||||||
|
struct FFCodecLegacy<T> where T: struct
|
||||||
|
{
|
||||||
|
#pragma warning disable CS0649
|
||||||
|
public T Base;
|
||||||
|
public uint CapsInternalOrCbType;
|
||||||
|
public int PrivDataSize;
|
||||||
|
public IntPtr UpdateThreadContext;
|
||||||
|
public IntPtr UpdateThreadContextForUser;
|
||||||
|
public IntPtr Defaults;
|
||||||
|
public IntPtr InitStaticData;
|
||||||
|
public IntPtr Init;
|
||||||
|
public IntPtr EncodeSub;
|
||||||
|
public IntPtr Encode2;
|
||||||
|
public IntPtr Decode;
|
||||||
|
#pragma warning restore CS0649
|
||||||
|
|
||||||
|
// NOTE: There is more after, but the layout kind of changed a bit and we don't need more than this. This is safe as we only manipulate this behind a reference.
|
||||||
|
}
|
||||||
|
}
|
129
Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs
Normal file
129
Ryujinx.Graphics.Nvdec.FFmpeg/Native/FFmpegApi.cs
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||||
|
{
|
||||||
|
static class FFmpegApi
|
||||||
|
{
|
||||||
|
public const string AvCodecLibraryName = "avcodec";
|
||||||
|
public const string AvUtilLibraryName = "avutil";
|
||||||
|
|
||||||
|
private static readonly Dictionary<string, (int, int)> _librariesWhitelist = new Dictionary<string, (int, int)>
|
||||||
|
{
|
||||||
|
{ AvCodecLibraryName, (58, 59) },
|
||||||
|
{ AvUtilLibraryName, (56, 57) }
|
||||||
|
};
|
||||||
|
|
||||||
|
private static string FormatLibraryNameForCurrentOs(string libraryName, int version)
|
||||||
|
{
|
||||||
|
if (OperatingSystem.IsWindows())
|
||||||
|
{
|
||||||
|
return $"{libraryName}-{version}.dll";
|
||||||
|
}
|
||||||
|
else if (OperatingSystem.IsLinux())
|
||||||
|
{
|
||||||
|
return $"lib{libraryName}.so.{version}";
|
||||||
|
}
|
||||||
|
else if (OperatingSystem.IsMacOS())
|
||||||
|
{
|
||||||
|
return $"lib{libraryName}.{version}.dylib";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new NotImplementedException($"Unsupported OS for FFmpeg: {RuntimeInformation.RuntimeIdentifier}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static bool TryLoadWhitelistedLibrary(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, out IntPtr handle)
|
||||||
|
{
|
||||||
|
handle = IntPtr.Zero;
|
||||||
|
|
||||||
|
if (_librariesWhitelist.TryGetValue(libraryName, out var value))
|
||||||
|
{
|
||||||
|
(int minVersion, int maxVersion) = value;
|
||||||
|
|
||||||
|
for (int version = minVersion; version <= maxVersion; version++)
|
||||||
|
{
|
||||||
|
if (NativeLibrary.TryLoad(FormatLibraryNameForCurrentOs(libraryName, version), assembly, searchPath, out handle))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FFmpegApi()
|
||||||
|
{
|
||||||
|
NativeLibrary.SetDllImportResolver(typeof(FFmpegApi).Assembly, (name, assembly, path) =>
|
||||||
|
{
|
||||||
|
IntPtr handle;
|
||||||
|
|
||||||
|
if (name == AvUtilLibraryName && TryLoadWhitelistedLibrary(AvUtilLibraryName, assembly, path, out handle))
|
||||||
|
{
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
else if (name == AvCodecLibraryName && TryLoadWhitelistedLibrary(AvCodecLibraryName, assembly, path, out handle))
|
||||||
|
{
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IntPtr.Zero;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe delegate void av_log_set_callback_callback(void* a0, AVLog level, [MarshalAs(UnmanagedType.LPUTF8Str)] string a2, byte* a3);
|
||||||
|
|
||||||
|
[DllImport(AvUtilLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static unsafe extern AVFrame* av_frame_alloc();
|
||||||
|
|
||||||
|
[DllImport(AvUtilLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static unsafe extern void av_frame_unref(AVFrame* frame);
|
||||||
|
|
||||||
|
[DllImport(AvUtilLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static unsafe extern void av_free(AVFrame* frame);
|
||||||
|
|
||||||
|
[DllImport(AvUtilLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static unsafe extern void av_log_set_level(AVLog level);
|
||||||
|
|
||||||
|
[DllImport(AvUtilLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static unsafe extern void av_log_set_callback(av_log_set_callback_callback callback);
|
||||||
|
|
||||||
|
[DllImport(AvUtilLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static unsafe extern AVLog av_log_get_level();
|
||||||
|
|
||||||
|
[DllImport(AvUtilLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static unsafe extern void av_log_format_line(void* ptr, AVLog level, [MarshalAs(UnmanagedType.LPUTF8Str)] string fmt, byte* vl, byte* line, int lineSize, int* printPrefix);
|
||||||
|
|
||||||
|
[DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static unsafe extern AVCodec* avcodec_find_decoder(AVCodecID id);
|
||||||
|
|
||||||
|
[DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static unsafe extern AVCodecContext* avcodec_alloc_context3(AVCodec* codec);
|
||||||
|
|
||||||
|
[DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static unsafe extern int avcodec_open2(AVCodecContext* avctx, AVCodec* codec, void **options);
|
||||||
|
|
||||||
|
[DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static unsafe extern int avcodec_close(AVCodecContext* avctx);
|
||||||
|
|
||||||
|
[DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static unsafe extern void avcodec_free_context(AVCodecContext** avctx);
|
||||||
|
|
||||||
|
[DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static unsafe extern AVPacket* av_packet_alloc();
|
||||||
|
|
||||||
|
[DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static unsafe extern void av_packet_unref(AVPacket* pkt);
|
||||||
|
|
||||||
|
[DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static unsafe extern void av_packet_free(AVPacket** pkt);
|
||||||
|
|
||||||
|
[DllImport(AvCodecLibraryName, CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
internal static unsafe extern int avcodec_version();
|
||||||
|
}
|
||||||
|
}
|
@ -1,14 +1,10 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="FFmpeg.AutoGen" Version="4.4.1" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
<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" />
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using FFmpeg.AutoGen;
|
using Ryujinx.Graphics.Nvdec.FFmpeg.Native;
|
||||||
using Ryujinx.Graphics.Video;
|
using Ryujinx.Graphics.Video;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
@ -11,31 +11,31 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg
|
|||||||
public int RequestedWidth { get; }
|
public int RequestedWidth { get; }
|
||||||
public int RequestedHeight { 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);
|
||||||
|
|
||||||
public FrameField Field => Frame->interlaced_frame != 0 ? FrameField.Interlaced : FrameField.Progressive;
|
public FrameField Field => Frame->InterlacedFrame != 0 ? FrameField.Interlaced : FrameField.Progressive;
|
||||||
|
|
||||||
public int Width => Frame->width;
|
public int Width => Frame->Width;
|
||||||
public int Height => Frame->height;
|
public int Height => Frame->Height;
|
||||||
public int Stride => Frame->linesize[0];
|
public int Stride => Frame->LineSize[0];
|
||||||
public int UvWidth => (Width + 1) >> 1;
|
public int UvWidth => (Width + 1) >> 1;
|
||||||
public int UvHeight => (Height + 1) >> 1;
|
public int UvHeight => (Height + 1) >> 1;
|
||||||
public int UvStride => Frame->linesize[1];
|
public int UvStride => Frame->LineSize[1];
|
||||||
|
|
||||||
public Surface(int width, int height)
|
public Surface(int width, int height)
|
||||||
{
|
{
|
||||||
RequestedWidth = width;
|
RequestedWidth = width;
|
||||||
RequestedHeight = height;
|
RequestedHeight = height;
|
||||||
|
|
||||||
Frame = ffmpeg.av_frame_alloc();
|
Frame = FFmpegApi.av_frame_alloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
ffmpeg.av_frame_unref(Frame);
|
FFmpegApi.av_frame_unref(Frame);
|
||||||
ffmpeg.av_free(Frame);
|
FFmpegApi.av_free(Frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using FFmpeg.AutoGen;
|
using Ryujinx.Graphics.Nvdec.FFmpeg.Native;
|
||||||
using Ryujinx.Graphics.Video;
|
using Ryujinx.Graphics.Video;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<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="5.0.1-build10" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="GtkSharp" Version="3.22.25.128" />
|
<PackageReference Include="GtkSharp" Version="3.22.25.128" />
|
||||||
<PackageReference Include="GtkSharp.Dependencies" Version="1.1.1" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
|
<PackageReference Include="GtkSharp.Dependencies" Version="1.1.1" 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.Graphics.Nvdec.Dependencies" Version="5.0.1-build10" 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.7.2" />
|
<PackageReference Include="OpenTK.Graphics" Version="4.7.2" />
|
||||||
<PackageReference Include="SPB" Version="0.0.4-build17" />
|
<PackageReference Include="SPB" Version="0.0.4-build17" />
|
||||||
|
Loading…
Reference in New Issue
Block a user