Skip to content

Commit

Permalink
Updates to v3.5.2 / v1.1.24 (Patch)
Browse files Browse the repository at this point in the history
Fixes a critical compatibility issue for ffmpeg5 with AVPixelFormat
  • Loading branch information
SuRGeoNix committed May 29, 2022
1 parent d8f9e77 commit 9e058b6
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 101 deletions.
2 changes: 1 addition & 1 deletion FlyleafLib.Controls.WPF/FlyleafLib.Controls.WPF.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFrameworks>net6.0-windows;net5.0-windows;net472</TargetFrameworks>
<UseWindowsForms>true</UseWindowsForms>
<UseWPF>true</UseWPF>
<Version>1.1.23</Version>
<Version>1.1.24</Version>
<Authors>SuRGeoNix</Authors>
<Copyright>SuRGeoNix © 2022</Copyright>
<PackageLicenseExpression>LGPL-3.0-or-later</PackageLicenseExpression>
Expand Down
22 changes: 10 additions & 12 deletions FlyleafLib/Engine/Engine.FFmpeg.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -58,18 +56,18 @@ 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()}");
};

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);
}
}
Expand Down
2 changes: 1 addition & 1 deletion FlyleafLib/FlyleafLib.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<PackageIconUrl />
<RepositoryUrl></RepositoryUrl>
<Description>Media Player .NET Library for WPF/WinForms (based on FFmpeg/DirectX)</Description>
<Version>3.5.1</Version>
<Version>3.5.2</Version>
<Authors>SuRGeoNix</Authors>
<Copyright>SuRGeoNix © 2022</Copyright>
<PackageLicenseExpression>LGPL-3.0-or-later</PackageLicenseExpression>
Expand Down
72 changes: 5 additions & 67 deletions FlyleafLib/MediaFramework/FFmpegBindings/ffmpegEx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,9 @@ namespace FFmpeg.AutoGen
/// </summary>
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;
Expand Down Expand Up @@ -236,6 +231,7 @@ public unsafe struct HLSPlaylistv5
}
#endregion

#region misc
public struct FFIOContext
{
AVIOContext pub;
Expand All @@ -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;
Expand Down Expand Up @@ -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
}
}
40 changes: 31 additions & 9 deletions FlyleafLib/MediaFramework/MediaDecoder/VideoDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,20 @@ public ConcurrentQueue<VideoFrame>
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)
Expand All @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion Samples/FlyleafPlayer (WPF Control) (WPF)/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -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">
<Grid>
<fl:VideoView Player="{Binding Player}">
<Grid>
Expand Down
23 changes: 13 additions & 10 deletions Samples/FlyleafPlayer (WPF Control) (WPF)/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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

Expand Down

0 comments on commit 9e058b6

Please sign in to comment.