diff --git a/FFmpeg.AutoGen.Abstractions/generated/Enums.g.cs b/FFmpeg.AutoGen.Abstractions/generated/Enums.g.cs index 5ea7ecda..37c38481 100644 --- a/FFmpeg.AutoGen.Abstractions/generated/Enums.g.cs +++ b/FFmpeg.AutoGen.Abstractions/generated/Enums.g.cs @@ -1,3 +1,5 @@ +using System; + namespace FFmpeg.AutoGen.Abstractions; public enum AVActiveFormatDescription : int @@ -69,14 +71,15 @@ public enum AVAudioServiceType : int } /// @{ +[Flags] public enum AvBuffersrcFlag : int { /// Do not check for format changes. - @AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT = 1, + @AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT = 1 << 0, /// Immediately push the frame to the output. - @AV_BUFFERSRC_FLAG_PUSH = 4, + @AV_BUFFERSRC_FLAG_PUSH = 1 << 2, /// Keep a reference to the frame. If the frame if reference-counted, create a new reference; otherwise copy the frame data. - @AV_BUFFERSRC_FLAG_KEEP_REF = 8, + @AV_BUFFERSRC_FLAG_KEEP_REF = 1 << 3, } /// Audio channel layout utility functions @@ -222,7 +225,7 @@ public enum AVClassCategory : int public enum AVClassStateFlags : int { /// Object initialization has finished and it is now in the 'runtime' stage. This affects e.g. what options can be set on the object (only AV_OPT_FLAG_RUNTIME_PARAM options can be set on initialized objects). - @AV_CLASS_STATE_INITIALIZED = 1, + @AV_CLASS_STATE_INITIALIZED = 1 << 0, } public enum AVCodecConfig : int @@ -245,6 +248,7 @@ public enum AVCodecConfig : int @AV_CODEC_CONFIG_ALPHA_MODE = 7, } +[Flags] public enum AvCodecHwConfigMethod : int { /// The codec supports this format via the hw_device_ctx interface. @@ -1053,7 +1057,7 @@ public enum AVFormatCommandID : int public enum AvFrameCrop : int { /// Apply the maximum possible cropping, even if it requires setting the AVFrame.data[] entries to unaligned pointers. Passing unaligned data to FFmpeg API is generally not allowed, and causes undefined behavior (such as crashes). You can pass unaligned data only to FFmpeg APIs that are explicitly documented to accept it. Use this flag only if you absolutely know what you are doing. - @AV_FRAME_CROP_UNALIGNED = 1, + @AV_FRAME_CROP_UNALIGNED = 1 << 0, } /// @{ AVFrame is an abstraction for reference-counted raw multimedia data. @@ -1162,16 +1166,17 @@ public enum AVHWDeviceType : int } /// Flags to apply to frame mappings. +[Flags] public enum AvHwframeMap : int { /// The mapping must be readable. - @AV_HWFRAME_MAP_READ = 1, + @AV_HWFRAME_MAP_READ = 1 << 0, /// The mapping must be writeable. - @AV_HWFRAME_MAP_WRITE = 2, + @AV_HWFRAME_MAP_WRITE = 1 << 1, /// The mapped frame will be overwritten completely in subsequent operations, so the current frame data need not be loaded. Any values which are not overwritten are unspecified. - @AV_HWFRAME_MAP_OVERWRITE = 4, + @AV_HWFRAME_MAP_OVERWRITE = 1 << 2, /// The mapping must be direct. That is, there must not be any copying in the map or unmap steps. Note that performance of direct mappings may be much lower than normal memory. - @AV_HWFRAME_MAP_DIRECT = 8, + @AV_HWFRAME_MAP_DIRECT = 1 << 3, } public enum AVHWFrameTransferDirection : int @@ -1292,7 +1297,7 @@ public enum AVOptionType : int /// Underlying C type is unsigned int. @AV_OPT_TYPE_UINT = 20, /// May be combined with another regular option type to declare an array option. - @AV_OPT_TYPE_FLAG_ARRAY = 65536, + @AV_OPT_TYPE_FLAG_ARRAY = 1 << 16, } /// Types and functions for working with AVPacketSideData. @{ @@ -2017,24 +2022,26 @@ public enum AVSampleFormat : int @AV_SAMPLE_FMT_NB = 12, } +[Flags] public enum AVSideDataParamChangeFlags : int { @AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE = 4, @AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS = 8, } +[Flags] public enum AVSideDataProps : int { /// The side data type can be used in stream-global structures. Side data types without this property are only meaningful on per-frame basis. - @AV_SIDE_DATA_PROP_GLOBAL = 1, + @AV_SIDE_DATA_PROP_GLOBAL = 1 << 0, /// Multiple instances of this side data type can be meaningfully present in a single side data array. - @AV_SIDE_DATA_PROP_MULTI = 2, + @AV_SIDE_DATA_PROP_MULTI = 1 << 1, /// Side data depends on the video dimensions. Side data with this property loses its meaning when rescaling or cropping the image, unless either recomputed or adjusted to the new resolution. - @AV_SIDE_DATA_PROP_SIZE_DEPENDENT = 4, + @AV_SIDE_DATA_PROP_SIZE_DEPENDENT = 1 << 2, /// Side data depends on the video color space. Side data with this property loses its meaning when changing the video color encoding, e.g. by adapting to a different set of primaries or transfer characteristics. - @AV_SIDE_DATA_PROP_COLOR_DEPENDENT = 8, + @AV_SIDE_DATA_PROP_COLOR_DEPENDENT = 1 << 3, /// Side data depends on the channel layout. Side data with this property loses its meaning when downmixing or upmixing, unless either recomputed or adjusted to the new layout. - @AV_SIDE_DATA_PROP_CHANNEL_DEPENDENT = 16, + @AV_SIDE_DATA_PROP_CHANNEL_DEPENDENT = 1 << 4, } public enum AVStreamGroupParamsType : int @@ -2076,14 +2083,15 @@ public enum AVSubtitleType : int @SUBTITLE_ASS = 3, } +[Flags] public enum AVTimecodeFlag : int { /// timecode is drop frame - @AV_TIMECODE_FLAG_DROPFRAME = 1, + @AV_TIMECODE_FLAG_DROPFRAME = 1 << 0, /// timecode wraps after 24 hours - @AV_TIMECODE_FLAG_24HOURSMAX = 2, + @AV_TIMECODE_FLAG_24HOURSMAX = 1 << 1, /// negative time values are allowed - @AV_TIMECODE_FLAG_ALLOWNEGATIVE = 4, + @AV_TIMECODE_FLAG_ALLOWNEGATIVE = 1 << 2, } /// Dithering algorithms @@ -2137,21 +2145,22 @@ public enum SwsAlphaBlend : int @SWS_ALPHA_BLEND_MAX_ENUM = 2147483647, } +[Flags] public enum SwsBackend : int { /// Legacy bespoke format-specific code - @SWS_BACKEND_LEGACY = 1, + @SWS_BACKEND_LEGACY = 1 << 0, @SWS_BACKEND_STABLE = 1, /// Template-based C reference implementation - @SWS_BACKEND_C = 2, + @SWS_BACKEND_C = 1 << 1, /// Fast path using libc memcpy() / memset() - @SWS_BACKEND_MEMCPY = 4, + @SWS_BACKEND_MEMCPY = 1 << 2, /// Chained x86 SIMD kernels - @SWS_BACKEND_X86 = 8, + @SWS_BACKEND_X86 = 1 << 3, /// Chained AArch64 NEON kernels - @SWS_BACKEND_AARCH64 = 16, + @SWS_BACKEND_AARCH64 = 1 << 4, /// Vulkan SPIR-V backend - @SWS_BACKEND_SPIRV = 32, + @SWS_BACKEND_SPIRV = 1 << 5, @SWS_BACKEND_UNSTABLE = 62, @SWS_BACKEND_ALL = 63, /// force size to 32 bits, not a valid backend @@ -2171,48 +2180,49 @@ public enum SwsDither : int @SWS_DITHER_MAX_ENUM = 2147483647, } +[Flags] public enum SwsFlags : int { /// Return an error on underspecified conversions. Without this flag, unspecified fields are defaulted to sensible values. - @SWS_STRICT = 2048, + @SWS_STRICT = 1 << 11, /// Emit verbose log of scaling parameters. - @SWS_PRINT_INFO = 4096, + @SWS_PRINT_INFO = 1 << 12, /// Perform full chroma upsampling when upscaling to RGB. - @SWS_FULL_CHR_H_INT = 8192, + @SWS_FULL_CHR_H_INT = 1 << 13, /// Perform full chroma interpolation when downscaling RGB sources. - @SWS_FULL_CHR_H_INP = 16384, + @SWS_FULL_CHR_H_INP = 1 << 14, /// Force bit-exact output. This will prevent the use of platform-specific optimizations that may lead to slight difference in rounding, in favor of always maintaining exact bit output compatibility with the reference C code. - @SWS_ACCURATE_RND = 262144, + @SWS_ACCURATE_RND = 1 << 18, /// Force bit-exact output. This will prevent the use of platform-specific optimizations that may lead to slight difference in rounding, in favor of always maintaining exact bit output compatibility with the reference C code. - @SWS_BITEXACT = 524288, + @SWS_BITEXACT = 1 << 19, /// Allow/prefer using experimental new code paths. This may be faster, slower, or produce different output, with semantics subject to change at any point in time. For testing and debugging purposes only. - @SWS_UNSTABLE = 1048576, + @SWS_UNSTABLE = 1 << 20, /// This flag has no effect - @SWS_DIRECT_BGR = 32768, + @SWS_DIRECT_BGR = 1 << 15, /// Set `SwsContext.dither` instead - @SWS_ERROR_DIFFUSION = 8388608, + @SWS_ERROR_DIFFUSION = 1 << 23, /// fast bilinear filtering - @SWS_FAST_BILINEAR = 1, + @SWS_FAST_BILINEAR = 1 << 0, /// bilinear filtering - @SWS_BILINEAR = 2, + @SWS_BILINEAR = 1 << 1, /// 2-tap cubic B-spline - @SWS_BICUBIC = 4, + @SWS_BICUBIC = 1 << 2, /// experimental - @SWS_X = 8, + @SWS_X = 1 << 3, /// nearest neighbor - @SWS_POINT = 16, + @SWS_POINT = 1 << 4, /// area averaging - @SWS_AREA = 32, + @SWS_AREA = 1 << 5, /// bicubic luma, bilinear chroma - @SWS_BICUBLIN = 64, + @SWS_BICUBLIN = 1 << 6, /// gaussian approximation - @SWS_GAUSS = 128, + @SWS_GAUSS = 1 << 7, /// unwindowed sinc - @SWS_SINC = 256, + @SWS_SINC = 1 << 8, /// 3-tap sinc/sinc - @SWS_LANCZOS = 512, + @SWS_LANCZOS = 1 << 9, /// unwindowed natural cubic spline - @SWS_SPLINE = 1024, + @SWS_SPLINE = 1 << 10, } public enum SwsIntent : int diff --git a/FFmpeg.AutoGen.CppSharpUnsafeGenerator/Definitions/EnumerationDefinition.cs b/FFmpeg.AutoGen.CppSharpUnsafeGenerator/Definitions/EnumerationDefinition.cs index 9f648e0a..d3beab77 100644 --- a/FFmpeg.AutoGen.CppSharpUnsafeGenerator/Definitions/EnumerationDefinition.cs +++ b/FFmpeg.AutoGen.CppSharpUnsafeGenerator/Definitions/EnumerationDefinition.cs @@ -5,4 +5,7 @@ namespace FFmpeg.AutoGen.CppSharpUnsafeGenerator.Definitions; internal record EnumerationDefinition : NamedDefinition, IDefinition { public EnumerationItem[] Items { get; init; } = Array.Empty(); + + /// The members describe a bitmask rather than a sequence, so the enum gets [Flags]. + public bool IsFlags { get; init; } } diff --git a/FFmpeg.AutoGen.CppSharpUnsafeGenerator/Definitions/EnumerationItem.cs b/FFmpeg.AutoGen.CppSharpUnsafeGenerator/Definitions/EnumerationItem.cs index 4f161bb9..2dd9a91f 100644 --- a/FFmpeg.AutoGen.CppSharpUnsafeGenerator/Definitions/EnumerationItem.cs +++ b/FFmpeg.AutoGen.CppSharpUnsafeGenerator/Definitions/EnumerationItem.cs @@ -1,8 +1,17 @@ -namespace FFmpeg.AutoGen.CppSharpUnsafeGenerator.Definitions; +namespace FFmpeg.AutoGen.CppSharpUnsafeGenerator.Definitions; internal record EnumerationItem : ICanGenerateXmlDoc { public string Name { get; init; } + + /// The numeric value, as computed by the compiler. Macro bodies are built from this. public string Value { get; init; } + + /// + /// What the generated C# spells out. Same as unless the header wrote the + /// member as a bit shift, which is kept as-is so the binding reads like the header. + /// + public string Literal { get; init; } + public string Content { get; set; } } diff --git a/FFmpeg.AutoGen.CppSharpUnsafeGenerator/Generation/EnumsGenerator.cs b/FFmpeg.AutoGen.CppSharpUnsafeGenerator/Generation/EnumsGenerator.cs index 08590874..0b68d756 100644 --- a/FFmpeg.AutoGen.CppSharpUnsafeGenerator/Generation/EnumsGenerator.cs +++ b/FFmpeg.AutoGen.CppSharpUnsafeGenerator/Generation/EnumsGenerator.cs @@ -1,4 +1,6 @@ -using FFmpeg.AutoGen.CppSharpUnsafeGenerator.Definitions; +using System.Collections.Generic; +using System.Linq; +using FFmpeg.AutoGen.CppSharpUnsafeGenerator.Definitions; namespace FFmpeg.AutoGen.CppSharpUnsafeGenerator.Generation; @@ -14,17 +16,26 @@ public static void Generate(string path, GenerationContext context) g.Generate(); } + public override IEnumerable Usings() + { + if (Context.Definitions.OfType().Any(x => x.IsFlags)) + yield return "System"; + } + protected override void GenerateDefinition(EnumerationDefinition @enum) { this.WriteSummary(@enum); this.WriteObsoletion(@enum); + + if (@enum.IsFlags) WriteLine("[Flags]"); + WriteLine($"public enum {@enum.Name} : {@enum.TypeName}"); using (BeginBlock()) foreach (var item in @enum.Items) { this.WriteSummary(item); - WriteLine($"@{item.Name} = {item.Value},"); + WriteLine($"@{item.Name} = {item.Literal},"); } WriteLine(); diff --git a/FFmpeg.AutoGen.CppSharpUnsafeGenerator/Processing/EnumerationProcessor.cs b/FFmpeg.AutoGen.CppSharpUnsafeGenerator/Processing/EnumerationProcessor.cs index 315a70a6..72cebdb3 100644 --- a/FFmpeg.AutoGen.CppSharpUnsafeGenerator/Processing/EnumerationProcessor.cs +++ b/FFmpeg.AutoGen.CppSharpUnsafeGenerator/Processing/EnumerationProcessor.cs @@ -1,12 +1,14 @@ -using System; +using System; +using System.Globalization; using System.Linq; +using System.Text.RegularExpressions; using CppSharp.AST; using CppSharp.AST.Extensions; using FFmpeg.AutoGen.CppSharpUnsafeGenerator.Definitions; namespace FFmpeg.AutoGen.CppSharpUnsafeGenerator.Processing; -internal class EnumerationProcessor +internal partial class EnumerationProcessor { private readonly ProcessingContext _context; @@ -70,35 +72,108 @@ public void MakeDefinition(Enumeration enumeration, string name) name = string.IsNullOrEmpty(enumeration.Name) ? name : enumeration.Name; if (_context.Definitions.Any(d => d.Name == name)) return; + var typeName = TypeHelper.GetTypeName(enumeration.Type); + var primitiveType = enumeration.BuiltinType.Type; + var values = enumeration.Items.Select(x => ToValue(x.Value, primitiveType)).ToArray(); + var definition = new EnumerationDefinition { Name = name, - TypeName = TypeHelper.GetTypeName(enumeration.Type), + TypeName = typeName, Content = enumeration.Comment?.BriefText, Obsoletion = ObsoletionHelper.CreateObsoletion(enumeration), + IsFlags = IsBitmask(values), Items = enumeration.Items - .Select(x => - new EnumerationItem + .Zip(values, (item, value) => + { + var number = Format(value, primitiveType); + return new EnumerationItem { - Name = x.Name, - Value = ConvertValue(x.Value, enumeration.BuiltinType.Type).ToString(), - Content = x.Comment?.BriefText - }) + Name = item.Name, + Value = number, + Literal = ShiftLiteral(item.Expression, item.Value, typeName) ?? number, + Content = item.Comment?.BriefText + }; + }) .ToArray() }; _context.AddDefinition(definition); } - private static object ConvertValue(ulong value, PrimitiveType primitiveType) + // Members the header wrote as a bit shift, with or without the parentheses FFmpeg + // uses in places: "= 1 << 3", "= (1 << 3)". + [GeneratedRegex(@"=\s*\(?\s*1\s*<<\s*(?\d+)\s*\)?\s*$")] + private static partial Regex ShiftExpression(); + + // Keeps a shift spelled the way the header spells it, so the binding reads like the header. + private static string ShiftLiteral(string expression, ulong value, string typeName) { - return primitiveType switch + if (expression is null || ShiftExpression().Match(expression) is not { Success: true } match) return null; + + // C# masks the shift count (& 31 for int, & 63 for long), so a shift that does not + // reproduce the computed value would quietly compile to a different constant. + if (!int.TryParse(match.Groups["shift"].ValueSpan, CultureInfo.InvariantCulture, out var shift)) return null; + if (shift >= 64 || 1UL << shift != value) return null; + + // Taken from the type the enum is generated with, so it cannot drift away from TypeHelper. + return typeName switch { - PrimitiveType.Int => value > int.MaxValue ? (int)value : value, - PrimitiveType.UInt => value, - PrimitiveType.Long => value > long.MaxValue ? (long)value : value, - PrimitiveType.ULong => value, - _ => throw new NotSupportedException() + "int" => $"1 << {shift}", + "uint" => $"1U << {shift}", + "long" => $"1L << {shift}", + "ulong" => $"1UL << {shift}", + _ => null }; } + + // Whether the members describe a bitmask. Reads the values rather than how the header + // happens to spell them, so hex, parenthesised shifts and plain decimals agree, and + // reformatting upstream cannot silently change the answer. + private static bool IsBitmask(long[] values) + { + // A negative member means the values are a scale rather than a mask, as in AVDiscard. + if (values.Any(x => x < 0)) return false; + + // FFmpeg closes several enums with a *_MAX_ENUM = INT_MAX sentinel, which is not a member. + var members = values + .Where(x => x > 0 && x != int.MaxValue && x != uint.MaxValue && x != long.MaxValue) + .Distinct() + .Order() + .ToArray(); + + var bits = members.Where(IsSingleBit).ToArray(); + var aggregates = members.Except(bits).ToArray(); + var mask = bits.Aggregate(0L, (all, bit) => all | bit); + + return bits.Length >= 2 + // A named aggregate such as SWS_BACKEND_ALL is still a bitmask, but a run of + // ordinary numbers that happen to be unions of earlier ones is not. + && aggregates.Length <= 2 + && aggregates.All(x => (x | mask) == mask) + // 1, 2, 3 is a sequence that merely starts with powers of two. + && !IsConsecutive(members); + } + + private static bool IsSingleBit(long value) => (value & (value - 1)) == 0; + + private static bool IsConsecutive(long[] sorted) + => sorted.Length > 1 && sorted[^1] - sorted[0] == sorted.Length - 1; + + // The compiler hands every value over as ulong, whatever the enum is declared as. + private static long ToValue(ulong value, PrimitiveType primitiveType) + => primitiveType switch + { + PrimitiveType.Int => (int)value, + PrimitiveType.UInt => (uint)value, + PrimitiveType.Long or PrimitiveType.ULong => unchecked((long)value), + _ => throw new NotSupportedException() + }; + + // The generated file is C# source, so it must not pick up the current culture's negative + // sign - several locales render it as U+2212, which does not compile. + private static string Format(long value, PrimitiveType primitiveType) + => primitiveType == PrimitiveType.ULong + ? unchecked((ulong)value).ToString(CultureInfo.InvariantCulture) + : value.ToString(CultureInfo.InvariantCulture); } diff --git a/FFmpeg.AutoGen.Example/VideoFrameConverter.cs b/FFmpeg.AutoGen.Example/VideoFrameConverter.cs index e547c1ca..5d7c0e0a 100644 --- a/FFmpeg.AutoGen.Example/VideoFrameConverter.cs +++ b/FFmpeg.AutoGen.Example/VideoFrameConverter.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Drawing; using System.Runtime.InteropServices; using FFmpeg.AutoGen.Abstractions; @@ -13,6 +13,11 @@ public sealed unsafe class VideoFrameConverter : IDisposable private readonly int4 _dstLinesize; private readonly SwsContext* _pConvertContext; + // The low bits of SwsFlags pick the scaler and only one of them may be active; the rest are + // flags that combine with it. SwsFlags is a [Flags] enum, so the combination is written out + // rather than added up by hand, and sws_getContext takes it as an int. + private const SwsFlags ScalingOptions = SwsFlags.SWS_FAST_BILINEAR | SwsFlags.SWS_ACCURATE_RND; + public VideoFrameConverter(Size sourceSize, AVPixelFormat sourcePixelFormat, Size destinationSize, AVPixelFormat destinationPixelFormat) { @@ -24,7 +29,7 @@ public VideoFrameConverter(Size sourceSize, AVPixelFormat sourcePixelFormat, destinationSize.Width, destinationSize.Height, destinationPixelFormat, - (int)SwsFlags.SWS_FAST_BILINEAR, + (int)ScalingOptions, null, null, null); diff --git a/FFmpeg.AutoGen/generated/Enums.g.cs b/FFmpeg.AutoGen/generated/Enums.g.cs index 90659a81..51ce0a98 100644 --- a/FFmpeg.AutoGen/generated/Enums.g.cs +++ b/FFmpeg.AutoGen/generated/Enums.g.cs @@ -1,3 +1,5 @@ +using System; + namespace FFmpeg.AutoGen; public enum AVActiveFormatDescription : int @@ -69,14 +71,15 @@ public enum AVAudioServiceType : int } /// @{ +[Flags] public enum AvBuffersrcFlag : int { /// Do not check for format changes. - @AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT = 1, + @AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT = 1 << 0, /// Immediately push the frame to the output. - @AV_BUFFERSRC_FLAG_PUSH = 4, + @AV_BUFFERSRC_FLAG_PUSH = 1 << 2, /// Keep a reference to the frame. If the frame if reference-counted, create a new reference; otherwise copy the frame data. - @AV_BUFFERSRC_FLAG_KEEP_REF = 8, + @AV_BUFFERSRC_FLAG_KEEP_REF = 1 << 3, } /// Audio channel layout utility functions @@ -222,7 +225,7 @@ public enum AVClassCategory : int public enum AVClassStateFlags : int { /// Object initialization has finished and it is now in the 'runtime' stage. This affects e.g. what options can be set on the object (only AV_OPT_FLAG_RUNTIME_PARAM options can be set on initialized objects). - @AV_CLASS_STATE_INITIALIZED = 1, + @AV_CLASS_STATE_INITIALIZED = 1 << 0, } public enum AVCodecConfig : int @@ -245,6 +248,7 @@ public enum AVCodecConfig : int @AV_CODEC_CONFIG_ALPHA_MODE = 7, } +[Flags] public enum AvCodecHwConfigMethod : int { /// The codec supports this format via the hw_device_ctx interface. @@ -1053,7 +1057,7 @@ public enum AVFormatCommandID : int public enum AvFrameCrop : int { /// Apply the maximum possible cropping, even if it requires setting the AVFrame.data[] entries to unaligned pointers. Passing unaligned data to FFmpeg API is generally not allowed, and causes undefined behavior (such as crashes). You can pass unaligned data only to FFmpeg APIs that are explicitly documented to accept it. Use this flag only if you absolutely know what you are doing. - @AV_FRAME_CROP_UNALIGNED = 1, + @AV_FRAME_CROP_UNALIGNED = 1 << 0, } /// @{ AVFrame is an abstraction for reference-counted raw multimedia data. @@ -1162,16 +1166,17 @@ public enum AVHWDeviceType : int } /// Flags to apply to frame mappings. +[Flags] public enum AvHwframeMap : int { /// The mapping must be readable. - @AV_HWFRAME_MAP_READ = 1, + @AV_HWFRAME_MAP_READ = 1 << 0, /// The mapping must be writeable. - @AV_HWFRAME_MAP_WRITE = 2, + @AV_HWFRAME_MAP_WRITE = 1 << 1, /// The mapped frame will be overwritten completely in subsequent operations, so the current frame data need not be loaded. Any values which are not overwritten are unspecified. - @AV_HWFRAME_MAP_OVERWRITE = 4, + @AV_HWFRAME_MAP_OVERWRITE = 1 << 2, /// The mapping must be direct. That is, there must not be any copying in the map or unmap steps. Note that performance of direct mappings may be much lower than normal memory. - @AV_HWFRAME_MAP_DIRECT = 8, + @AV_HWFRAME_MAP_DIRECT = 1 << 3, } public enum AVHWFrameTransferDirection : int @@ -1292,7 +1297,7 @@ public enum AVOptionType : int /// Underlying C type is unsigned int. @AV_OPT_TYPE_UINT = 20, /// May be combined with another regular option type to declare an array option. - @AV_OPT_TYPE_FLAG_ARRAY = 65536, + @AV_OPT_TYPE_FLAG_ARRAY = 1 << 16, } /// Types and functions for working with AVPacketSideData. @{ @@ -2017,24 +2022,26 @@ public enum AVSampleFormat : int @AV_SAMPLE_FMT_NB = 12, } +[Flags] public enum AVSideDataParamChangeFlags : int { @AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE = 4, @AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS = 8, } +[Flags] public enum AVSideDataProps : int { /// The side data type can be used in stream-global structures. Side data types without this property are only meaningful on per-frame basis. - @AV_SIDE_DATA_PROP_GLOBAL = 1, + @AV_SIDE_DATA_PROP_GLOBAL = 1 << 0, /// Multiple instances of this side data type can be meaningfully present in a single side data array. - @AV_SIDE_DATA_PROP_MULTI = 2, + @AV_SIDE_DATA_PROP_MULTI = 1 << 1, /// Side data depends on the video dimensions. Side data with this property loses its meaning when rescaling or cropping the image, unless either recomputed or adjusted to the new resolution. - @AV_SIDE_DATA_PROP_SIZE_DEPENDENT = 4, + @AV_SIDE_DATA_PROP_SIZE_DEPENDENT = 1 << 2, /// Side data depends on the video color space. Side data with this property loses its meaning when changing the video color encoding, e.g. by adapting to a different set of primaries or transfer characteristics. - @AV_SIDE_DATA_PROP_COLOR_DEPENDENT = 8, + @AV_SIDE_DATA_PROP_COLOR_DEPENDENT = 1 << 3, /// Side data depends on the channel layout. Side data with this property loses its meaning when downmixing or upmixing, unless either recomputed or adjusted to the new layout. - @AV_SIDE_DATA_PROP_CHANNEL_DEPENDENT = 16, + @AV_SIDE_DATA_PROP_CHANNEL_DEPENDENT = 1 << 4, } public enum AVStreamGroupParamsType : int @@ -2076,14 +2083,15 @@ public enum AVSubtitleType : int @SUBTITLE_ASS = 3, } +[Flags] public enum AVTimecodeFlag : int { /// timecode is drop frame - @AV_TIMECODE_FLAG_DROPFRAME = 1, + @AV_TIMECODE_FLAG_DROPFRAME = 1 << 0, /// timecode wraps after 24 hours - @AV_TIMECODE_FLAG_24HOURSMAX = 2, + @AV_TIMECODE_FLAG_24HOURSMAX = 1 << 1, /// negative time values are allowed - @AV_TIMECODE_FLAG_ALLOWNEGATIVE = 4, + @AV_TIMECODE_FLAG_ALLOWNEGATIVE = 1 << 2, } /// Dithering algorithms @@ -2137,21 +2145,22 @@ public enum SwsAlphaBlend : int @SWS_ALPHA_BLEND_MAX_ENUM = 2147483647, } +[Flags] public enum SwsBackend : int { /// Legacy bespoke format-specific code - @SWS_BACKEND_LEGACY = 1, + @SWS_BACKEND_LEGACY = 1 << 0, @SWS_BACKEND_STABLE = 1, /// Template-based C reference implementation - @SWS_BACKEND_C = 2, + @SWS_BACKEND_C = 1 << 1, /// Fast path using libc memcpy() / memset() - @SWS_BACKEND_MEMCPY = 4, + @SWS_BACKEND_MEMCPY = 1 << 2, /// Chained x86 SIMD kernels - @SWS_BACKEND_X86 = 8, + @SWS_BACKEND_X86 = 1 << 3, /// Chained AArch64 NEON kernels - @SWS_BACKEND_AARCH64 = 16, + @SWS_BACKEND_AARCH64 = 1 << 4, /// Vulkan SPIR-V backend - @SWS_BACKEND_SPIRV = 32, + @SWS_BACKEND_SPIRV = 1 << 5, @SWS_BACKEND_UNSTABLE = 62, @SWS_BACKEND_ALL = 63, /// force size to 32 bits, not a valid backend @@ -2171,48 +2180,49 @@ public enum SwsDither : int @SWS_DITHER_MAX_ENUM = 2147483647, } +[Flags] public enum SwsFlags : int { /// Return an error on underspecified conversions. Without this flag, unspecified fields are defaulted to sensible values. - @SWS_STRICT = 2048, + @SWS_STRICT = 1 << 11, /// Emit verbose log of scaling parameters. - @SWS_PRINT_INFO = 4096, + @SWS_PRINT_INFO = 1 << 12, /// Perform full chroma upsampling when upscaling to RGB. - @SWS_FULL_CHR_H_INT = 8192, + @SWS_FULL_CHR_H_INT = 1 << 13, /// Perform full chroma interpolation when downscaling RGB sources. - @SWS_FULL_CHR_H_INP = 16384, + @SWS_FULL_CHR_H_INP = 1 << 14, /// Force bit-exact output. This will prevent the use of platform-specific optimizations that may lead to slight difference in rounding, in favor of always maintaining exact bit output compatibility with the reference C code. - @SWS_ACCURATE_RND = 262144, + @SWS_ACCURATE_RND = 1 << 18, /// Force bit-exact output. This will prevent the use of platform-specific optimizations that may lead to slight difference in rounding, in favor of always maintaining exact bit output compatibility with the reference C code. - @SWS_BITEXACT = 524288, + @SWS_BITEXACT = 1 << 19, /// Allow/prefer using experimental new code paths. This may be faster, slower, or produce different output, with semantics subject to change at any point in time. For testing and debugging purposes only. - @SWS_UNSTABLE = 1048576, + @SWS_UNSTABLE = 1 << 20, /// This flag has no effect - @SWS_DIRECT_BGR = 32768, + @SWS_DIRECT_BGR = 1 << 15, /// Set `SwsContext.dither` instead - @SWS_ERROR_DIFFUSION = 8388608, + @SWS_ERROR_DIFFUSION = 1 << 23, /// fast bilinear filtering - @SWS_FAST_BILINEAR = 1, + @SWS_FAST_BILINEAR = 1 << 0, /// bilinear filtering - @SWS_BILINEAR = 2, + @SWS_BILINEAR = 1 << 1, /// 2-tap cubic B-spline - @SWS_BICUBIC = 4, + @SWS_BICUBIC = 1 << 2, /// experimental - @SWS_X = 8, + @SWS_X = 1 << 3, /// nearest neighbor - @SWS_POINT = 16, + @SWS_POINT = 1 << 4, /// area averaging - @SWS_AREA = 32, + @SWS_AREA = 1 << 5, /// bicubic luma, bilinear chroma - @SWS_BICUBLIN = 64, + @SWS_BICUBLIN = 1 << 6, /// gaussian approximation - @SWS_GAUSS = 128, + @SWS_GAUSS = 1 << 7, /// unwindowed sinc - @SWS_SINC = 256, + @SWS_SINC = 1 << 8, /// 3-tap sinc/sinc - @SWS_LANCZOS = 512, + @SWS_LANCZOS = 1 << 9, /// unwindowed natural cubic spline - @SWS_SPLINE = 1024, + @SWS_SPLINE = 1 << 10, } public enum SwsIntent : int