|
@@ -1,16 +1,25 @@
|
|
|
using FFmpeg.AutoGen;
|
|
using FFmpeg.AutoGen;
|
|
|
|
|
+using Ryujinx.Common.Logging;
|
|
|
using System;
|
|
using System;
|
|
|
|
|
+using System.Runtime.InteropServices;
|
|
|
|
|
|
|
|
namespace Ryujinx.Graphics.Nvdec.H264
|
|
namespace Ryujinx.Graphics.Nvdec.H264
|
|
|
{
|
|
{
|
|
|
unsafe class FFmpegContext : IDisposable
|
|
unsafe class FFmpegContext : IDisposable
|
|
|
{
|
|
{
|
|
|
|
|
+ private 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()
|
|
|
{
|
|
{
|
|
|
|
|
+ _logFunc = Log;
|
|
|
|
|
+
|
|
|
|
|
+ // Redirect log output
|
|
|
|
|
+ ffmpeg.av_log_set_level(ffmpeg.AV_LOG_MAX_OFFSET);
|
|
|
|
|
+ ffmpeg.av_log_set_callback(_logFunc);
|
|
|
|
|
+
|
|
|
_codec = ffmpeg.avcodec_find_decoder(AVCodecID.AV_CODEC_ID_H264);
|
|
_codec = ffmpeg.avcodec_find_decoder(AVCodecID.AV_CODEC_ID_H264);
|
|
|
_context = ffmpeg.avcodec_alloc_context3(_codec);
|
|
_context = ffmpeg.avcodec_alloc_context3(_codec);
|
|
|
|
|
|
|
@@ -19,6 +28,42 @@ namespace Ryujinx.Graphics.Nvdec.H264
|
|
|
_packet = ffmpeg.av_packet_alloc();
|
|
_packet = ffmpeg.av_packet_alloc();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private void Log(void* p0, int level, string format, byte* vl)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (level > ffmpeg.av_log_get_level())
|
|
|
|
|
+ {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ int lineSize = 1024;
|
|
|
|
|
+ byte* lineBuffer = stackalloc byte[lineSize];
|
|
|
|
|
+ int printPrefix = 1;
|
|
|
|
|
+
|
|
|
|
|
+ ffmpeg.av_log_format_line(p0, level, format, vl, lineBuffer, lineSize, &printPrefix);
|
|
|
|
|
+
|
|
|
|
|
+ string line = Marshal.PtrToStringAnsi((IntPtr)lineBuffer).Trim();
|
|
|
|
|
+
|
|
|
|
|
+ switch (level)
|
|
|
|
|
+ {
|
|
|
|
|
+ case ffmpeg.AV_LOG_PANIC:
|
|
|
|
|
+ case ffmpeg.AV_LOG_FATAL:
|
|
|
|
|
+ case ffmpeg.AV_LOG_ERROR:
|
|
|
|
|
+ Logger.Error?.Print(LogClass.FFmpeg, line);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case ffmpeg.AV_LOG_WARNING:
|
|
|
|
|
+ Logger.Warning?.Print(LogClass.FFmpeg, line);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case ffmpeg.AV_LOG_INFO:
|
|
|
|
|
+ Logger.Info?.Print(LogClass.FFmpeg, line);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case ffmpeg.AV_LOG_VERBOSE:
|
|
|
|
|
+ case ffmpeg.AV_LOG_DEBUG:
|
|
|
|
|
+ case ffmpeg.AV_LOG_TRACE:
|
|
|
|
|
+ Logger.Debug?.Print(LogClass.FFmpeg, line);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
public int DecodeFrame(Surface output, ReadOnlySpan<byte> bitstream)
|
|
public int DecodeFrame(Surface output, ReadOnlySpan<byte> bitstream)
|
|
|
{
|
|
{
|
|
|
// Ensure the packet is clean before proceeding
|
|
// Ensure the packet is clean before proceeding
|