From 9e058b6c29cdb171f573d072909ceba334f5a80c Mon Sep 17 00:00:00 2001 From: SuRGeoNix Date: Mon, 30 May 2022 02:02:40 +0300 Subject: [PATCH] Updates to v3.5.2 / v1.1.24 (Patch) Fixes a critical compatibility issue for ffmpeg5 with AVPixelFormat --- .../FlyleafLib.Controls.WPF.csproj | 2 +- FlyleafLib/Engine/Engine.FFmpeg.cs | 22 +++--- FlyleafLib/FlyleafLib.csproj | 2 +- .../MediaFramework/FFmpegBindings/ffmpegEx.cs | 72 ++----------------- .../MediaDecoder/VideoDecoder.cs | 40 ++++++++--- .../MainWindow.xaml | 2 +- .../MainWindow.xaml.cs | 23 +++--- 7 files changed, 62 insertions(+), 101 deletions(-) diff --git a/FlyleafLib.Controls.WPF/FlyleafLib.Controls.WPF.csproj b/FlyleafLib.Controls.WPF/FlyleafLib.Controls.WPF.csproj index 54693072..8ebb6bdf 100644 --- a/FlyleafLib.Controls.WPF/FlyleafLib.Controls.WPF.csproj +++ b/FlyleafLib.Controls.WPF/FlyleafLib.Controls.WPF.csproj @@ -4,7 +4,7 @@ net6.0-windows;net5.0-windows;net472 true true - 1.1.23 + 1.1.24 SuRGeoNix SuRGeoNix © 2022 LGPL-3.0-or-later diff --git a/FlyleafLib/Engine/Engine.FFmpeg.cs b/FlyleafLib/Engine/Engine.FFmpeg.cs index e9fcdd5b..d8107804 100644 --- a/FlyleafLib/Engine/Engine.FFmpeg.cs +++ b/FlyleafLib/Engine/Engine.FFmpeg.cs @@ -12,23 +12,21 @@ public class FFmpegEngine public string Version { get; private set; } public bool IsVer5 { get; private set; } - public static int BUFFER_SIZE = 5 * 1024; + public static int AV_LOG_BUFFER_SIZE = 5 * 1024; internal FFmpegEngine() { try { Engine.Log.Info($"Loading FFmpeg libraries from '{Engine.Config.FFmpegPath}'"); - Folder = Utils.GetFolderPath(Engine.Config.FFmpegPath); - RootPath = Folder; - uint ver = avformat_version(); - - IsVer5 = ver >> 16 > 58; + Folder = Utils.GetFolderPath(Engine.Config.FFmpegPath); + RootPath= Folder; + uint ver= avformat_version(); + IsVer5 = ver >> 16 > 58; Version = $"{ver >> 16}.{ver >> 8 & 255}.{ver & 255}"; - // Requires additional libraries avdevice, avfitler, postproc if (Engine.Config.FFmpegDevices) - avdevice_register_all(); + try { avdevice_register_all(); } catch { Engine.Log.Error("FFmpeg failed to load avdevices/avfilters/postproc"); } SetLogLevel(); @@ -58,9 +56,9 @@ internal void SetLogLevel() { if (level > av_log_get_level()) return; - var buffer = stackalloc byte[BUFFER_SIZE]; + var buffer = stackalloc byte[AV_LOG_BUFFER_SIZE]; var printPrefix = 1; - av_log_format_line2(p0, level, format, vl, buffer, BUFFER_SIZE, &printPrefix); + av_log_format_line2(p0, level, format, vl, buffer, AV_LOG_BUFFER_SIZE, &printPrefix); var line = Marshal.PtrToStringAnsi((IntPtr)buffer); Logger.Output($"{DateTime.Now.ToString("hh.mm.ss.fff")} |FFmpeg | {((FFmpegLogLevel)level).ToString().PadRight(7, ' ')} | {line.Trim()}"); @@ -68,8 +66,8 @@ internal void SetLogLevel() internal unsafe static string ErrorCodeToMsg(int error) { - byte* buffer = stackalloc byte[BUFFER_SIZE]; - av_strerror(error, buffer, (ulong)BUFFER_SIZE); + byte* buffer = stackalloc byte[AV_LOG_BUFFER_SIZE]; + av_strerror(error, buffer, (ulong)AV_LOG_BUFFER_SIZE); return Marshal.PtrToStringAnsi((IntPtr)buffer); } } diff --git a/FlyleafLib/FlyleafLib.csproj b/FlyleafLib/FlyleafLib.csproj index 3e834939..1c374a48 100644 --- a/FlyleafLib/FlyleafLib.csproj +++ b/FlyleafLib/FlyleafLib.csproj @@ -8,7 +8,7 @@ Media Player .NET Library for WPF/WinForms (based on FFmpeg/DirectX) - 3.5.1 + 3.5.2 SuRGeoNix SuRGeoNix © 2022 LGPL-3.0-or-later diff --git a/FlyleafLib/MediaFramework/FFmpegBindings/ffmpegEx.cs b/FlyleafLib/MediaFramework/FFmpegBindings/ffmpegEx.cs index f293a648..b94b2985 100644 --- a/FlyleafLib/MediaFramework/FFmpegBindings/ffmpegEx.cs +++ b/FlyleafLib/MediaFramework/FFmpegBindings/ffmpegEx.cs @@ -7,14 +7,9 @@ namespace FFmpeg.AutoGen /// internal unsafe partial class ffmpegEx { - #pragma warning disable CS0649 +#pragma warning disable CS0649 +#pragma warning disable CS0169 #region hls demuxer - - public interface IHLSPlaylist - { - - } - public unsafe struct HLSContext { public AVClass *avclass; @@ -236,6 +231,7 @@ public unsafe struct HLSPlaylistv5 } #endregion + #region misc public struct FFIOContext { AVIOContext pub; @@ -257,65 +253,6 @@ public struct HLSAudioSetupInfo UInt16 priming; byte_array10 setup_data; } - - #region mpegts demuxer - public struct MpegTSContext - { - public AVClass* @class; - /* user data */ - public AVFormatContext *stream; - /* raw packet size, including FEC if present */ - public int raw_packet_size; - - public long pos47_full; - - /* if true, all pids are analyzed to find streams */ - public int auto_guess; - - /* compute exact PCR for each transport stream packet */ - public int mpeg2ts_compute_pcr; - - /* fix dvb teletext pts */ - public int fix_teletext_pts; - - public long cur_pcr; /*< used to estimate the exact PCR */ - public long pcr_incr; /*< used to estimate the exact PCR */ - - /* data needed to handle file based ts */ - /* stop parsing loop */ - public int stop_parse; - /* packet containing Audio/Video data */ - public AVPacket *pkt; - /* to detect seek */ - public long last_pos; - - public int skip_changes; - public int skip_clear; - public int skip_unknown_pmt; - - public int scan_all_pmts; - - public int resync_size; - public int merge_pmt_versions; - - /******************************************/ - /* private mpegts data */ - /* scan context */ - /* structure to keep track of Program->pids mapping */ - //public uint nb_prg; - //public struct Program *prg; - - //public int8_t crc_validity[NB_PID_MAX]; - /* filters for various streams specified by PMT + for the PAT and PMT */ - //public MpegTSFilter *pids[NB_PID_MAX]; - //public int current_pid; - - //public AVStream *epg_stream; - //public AVBufferPool* pools[32]; - } - #endregion - - #region misc public unsafe struct byte_array4096 { public static readonly int Size = 4096; @@ -421,6 +358,7 @@ public void UpdateFrom(int[] array) public static implicit operator int[](int_array16 @struct) => @struct.ToArray(); } #endregion - #pragma warning restore CS0649 +#pragma warning restore CS0169 +#pragma warning restore CS0649 } } diff --git a/FlyleafLib/MediaFramework/MediaDecoder/VideoDecoder.cs b/FlyleafLib/MediaFramework/MediaDecoder/VideoDecoder.cs index 31189243..2531783d 100644 --- a/FlyleafLib/MediaFramework/MediaDecoder/VideoDecoder.cs +++ b/FlyleafLib/MediaFramework/MediaDecoder/VideoDecoder.cs @@ -64,6 +64,20 @@ public ConcurrentQueue public VideoDecoder(Config config, int uniqueId = -1) : base(config, uniqueId) { getHWformat = new AVCodecContext_get_format(get_format); + + HW_PIX_FMT = (int)AVPixelFormat.AV_PIX_FMT_D3D11; + AV_PIX_FMT_P010LE = (int)AVPixelFormat.AV_PIX_FMT_P010LE; + AV_PIX_FMT_P010BE = (int)AVPixelFormat.AV_PIX_FMT_P010BE; + AV_PIX_FMT_YUV420P10LE = (int)AVPixelFormat.AV_PIX_FMT_YUV420P10LE; + + if (Engine.FFmpeg.IsVer5) + { + HW_PIX_FMT -= 2; + AV_PIX_FMT_P010LE -= 2; + AV_PIX_FMT_P010BE -= 2; + AV_PIX_FMT_YUV420P10LE -= 2; + + } } public void CreateRenderer(Control control = null) @@ -79,7 +93,14 @@ public void CreateRenderer(Control control = null) #region Video Acceleration (Should be disposed seperately) const int AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX = 0x01; const AVHWDeviceType HW_DEVICE = AVHWDeviceType.AV_HWDEVICE_TYPE_D3D11VA; // To fully support Win7/8 should consider AV_HWDEVICE_TYPE_DXVA2 - const AVPixelFormat HW_PIX_FMT = AVPixelFormat.AV_PIX_FMT_D3D11; + //const AVPixelFormat HW_PIX_FMT = AVPixelFormat.AV_PIX_FMT_D3D11; + + // We can't use AVPixelFormat enum as it is different between ffmpeg v4 and v5 (two new entries after 44 so we need -2 for >46 ) + static int HW_PIX_FMT; + static int AV_PIX_FMT_YUV420P10LE; + static int AV_PIX_FMT_P010LE; + static int AV_PIX_FMT_P010BE; + internal ID3D11Texture2D textureFFmpeg; AVCodecContext_get_format @@ -95,8 +116,8 @@ internal static bool CheckCodecSupport(AVCodec* codec) AVCodecHWConfig* config = avcodec_get_hw_config(codec, i); if (config == null) break; if ((config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX) == 0 || config->pix_fmt == AVPixelFormat.AV_PIX_FMT_NONE) continue; - - if (config->device_type == HW_DEVICE && config->pix_fmt == HW_PIX_FMT) return true; + + if (config->device_type == HW_DEVICE && (int)config->pix_fmt == HW_PIX_FMT) return true; } return false; @@ -146,7 +167,7 @@ private AVPixelFormat get_format(AVCodecContext* avctx, AVPixelFormat* pix_fmts) { if (CanTrace) Log.Trace($"{*pix_fmts}"); - if (*pix_fmts == AVPixelFormat.AV_PIX_FMT_D3D11) + if ((int)(*pix_fmts) == HW_PIX_FMT) { foundHWformat = true; break; @@ -166,7 +187,7 @@ private AVPixelFormat get_format(AVCodecContext* avctx, AVPixelFormat* pix_fmts) textDesc.Format = textureFFmpeg.Description.Format; - return AVPixelFormat.AV_PIX_FMT_D3D11; + return (AVPixelFormat)HW_PIX_FMT; } lock (lockCodecCtx) @@ -213,7 +234,7 @@ private AVPixelFormat get_format(AVCodecContext* avctx, AVPixelFormat* pix_fmts) VideoStream.Height = codecCtx->height; } - return AVPixelFormat.AV_PIX_FMT_D3D11; + return (AVPixelFormat)HW_PIX_FMT; } } private int ShouldAllocateNew() // 0: No, 1: Yes, 2: Yes+Codec Changed @@ -232,12 +253,13 @@ private int ShouldAllocateNew() // 0: No, 1: Yes, 2: Yes+Codec Changed if (codecCtx->coded_height != t2->height) return 2; - var fmt = codecCtx->sw_pix_fmt == AVPixelFormat.AV_PIX_FMT_YUV420P10LE ? AVPixelFormat.AV_PIX_FMT_P010LE : (codecCtx->sw_pix_fmt == AVPixelFormat.AV_PIX_FMT_P010BE ? AVPixelFormat.AV_PIX_FMT_P010BE : AVPixelFormat.AV_PIX_FMT_NV12); + var fmt = codecCtx->sw_pix_fmt == (AVPixelFormat)AV_PIX_FMT_YUV420P10LE ? (AVPixelFormat)AV_PIX_FMT_P010LE : (codecCtx->sw_pix_fmt == (AVPixelFormat)AV_PIX_FMT_P010BE ? (AVPixelFormat)AV_PIX_FMT_P010BE : AVPixelFormat.AV_PIX_FMT_NV12); if (fmt != t2->sw_format) return 2; return 0; } + private int AllocateHWFrames() { if (hwframes != null) @@ -249,7 +271,7 @@ private int AllocateHWFrames() if (codecCtx->hw_frames_ctx != null) av_buffer_unref(&codecCtx->hw_frames_ctx); - if (avcodec_get_hw_frames_parameters(codecCtx, codecCtx->hw_device_ctx, AVPixelFormat.AV_PIX_FMT_D3D11, &codecCtx->hw_frames_ctx) != 0) + if (avcodec_get_hw_frames_parameters(codecCtx, codecCtx->hw_device_ctx, (AVPixelFormat)HW_PIX_FMT, &codecCtx->hw_frames_ctx) != 0) return -1; AVHWFramesContext* hw_frames_ctx = (AVHWFramesContext*)(codecCtx->hw_frames_ctx->data); @@ -364,7 +386,7 @@ protected override int Setup(AVCodec* codec) if (Config.Decoder.AllowProfileMismatch) codecCtx->hwaccel_flags |= AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH; - codecCtx->pix_fmt = AVPixelFormat.AV_PIX_FMT_D3D11; + codecCtx->pix_fmt = (AVPixelFormat)HW_PIX_FMT; codecCtx->get_format = getHWformat; disableGetFormat = false; } diff --git a/Samples/FlyleafPlayer (WPF Control) (WPF)/MainWindow.xaml b/Samples/FlyleafPlayer (WPF Control) (WPF)/MainWindow.xaml index e4e438cf..1b9bcd67 100644 --- a/Samples/FlyleafPlayer (WPF Control) (WPF)/MainWindow.xaml +++ b/Samples/FlyleafPlayer (WPF Control) (WPF)/MainWindow.xaml @@ -9,7 +9,7 @@ xmlns:flwpf="clr-namespace:FlyleafLib.Controls.WPF;assembly=FlyleafLib.Controls.WPF" mc:Ignorable="d" - Title="Flyleaf v3.5" Height="450" Width="800" Background="Black" Loaded="Window_Loaded" Icon="/Flyleaf.ico"> + Title="Flyleaf v3.5.2" Height="450" Width="800" Background="Black" Loaded="Window_Loaded" Icon="/Flyleaf.ico"> diff --git a/Samples/FlyleafPlayer (WPF Control) (WPF)/MainWindow.xaml.cs b/Samples/FlyleafPlayer (WPF Control) (WPF)/MainWindow.xaml.cs index 3494439b..a33b00fb 100644 --- a/Samples/FlyleafPlayer (WPF Control) (WPF)/MainWindow.xaml.cs +++ b/Samples/FlyleafPlayer (WPF Control) (WPF)/MainWindow.xaml.cs @@ -63,8 +63,8 @@ public MainWindow() InitializeComponent(); // Allow Flyleaf WPF Control to Load UIConfig and Save both Config & UIConfig (Save button will be available in settings) - flyleafControl.ConfigPath = "Flyleaf.Config.xml"; - flyleafControl.EnginePath = "Flyleaf.Engine.xml"; + flyleafControl.ConfigPath = "Flyleaf.Config.xml"; + flyleafControl.EnginePath = "Flyleaf.Engine.xml"; flyleafControl.UIConfigPath = "Flyleaf.UIConfig.xml"; // If the user requests reverse playback allocate more frames once @@ -84,16 +84,16 @@ private EngineConfig DefaultEngineConfig() { EngineConfig engineConfig = new EngineConfig(); - engineConfig.PluginsPath = ":Plugins"; - engineConfig.FFmpegPath = ":FFmpeg"; - engineConfig.HighPerformaceTimers = false; - engineConfig.UIRefresh = true; - engineConfig.FFmpegDevices = false; + engineConfig.PluginsPath = ":Plugins"; + engineConfig.FFmpegPath = ":FFmpeg"; + engineConfig.HighPerformaceTimers + = false; + engineConfig.UIRefresh = true; #if RELEASE engineConfig.LogOutput = "Flyleaf.FirstRun.log"; engineConfig.LogLevel = LogLevel.Debug; - try { engineConfig.Save("Flyleaf.Engine.xml"); } catch { } + engineConfig.FFmpegDevices = true; #else engineConfig.LogOutput = ":debug"; engineConfig.LogLevel = LogLevel.Debug; @@ -128,8 +128,11 @@ private void Window_Loaded(object sender, RoutedEventArgs e) // Stops Logging (First Run) if (!engineConfig.Loaded) { - engineConfig.LogOutput = null; - engineConfig.LogLevel = LogLevel.Quiet; + engineConfig.LogOutput = null; + engineConfig.LogLevel = LogLevel.Quiet; + engineConfig.FFmpegDevices = false; + + try { engineConfig.Save("Flyleaf.Engine.xml"); } catch { } } #endif