From d700ea8290edfc8557ee913360e53ca20b5290dc Mon Sep 17 00:00:00 2001 From: Casey Bateman Date: Tue, 11 Feb 2025 09:06:30 -0600 Subject: [PATCH 1/5] feat: attempt .net8 target upgrade, remove newtonsoft.json dependency. --- Hudl.FFmpeg.Core/Hudl.FFmpeg.Core.csproj | 8 +- Hudl.FFmpeg.Core/packages.config | 5 - .../Command/Utility/CommandHelperUtility.cs | 213 +++++++++-------- Hudl.FFmpeg/Hudl.Ffmpeg.csproj | 9 +- Hudl.FFmpeg/Hudl.Ffmpeg.nuspec | 12 +- Hudl.FFmpeg/packages.config | 5 - Hudl.FFprobe/CodecTypes.cs | 15 +- Hudl.FFprobe/CodecTypesUtility.cs | 12 + Hudl.FFprobe/Command/FFprobeCommand.cs | 61 +++-- Hudl.FFprobe/Command/FFprobeCommandBuilder.cs | 37 ++- .../Command/FFprobeCommandProcessor.cs | 223 +++++++++--------- Hudl.FFprobe/Hudl.FFprobe.csproj | 8 +- Hudl.FFprobe/MediaLoader.cs | 93 ++++---- .../Metadata/Models/AudioFrameMetadata.cs | 34 ++- .../Metadata/Models/AudioStreamMetadata.cs | 38 ++- .../Metadata/Models/BaseFrameMetadata.cs | 76 +++--- .../Metadata/Models/BaseStreamMetadata.cs | 100 ++++---- .../Metadata/Models/ContainerMetadata.cs | 29 +-- .../Metadata/Models/DataStreamMetadata.cs | 14 +- .../Metadata/Models/FormatMetadata.cs | 61 +++-- .../Metadata/Models/VideoFrameMetadata.cs | 43 ++-- .../Metadata/Models/VideoStreamMetadata.cs | 73 +++--- .../Converters/FractionConverter.cs | 43 ++-- .../Converters/FrameConverter.cs | 84 ++----- .../Converters/NumberStringConverter.cs | 25 ++ .../Converters/RatioConverter.cs | 42 +--- .../Converters/StreamConverter.cs | 90 ++----- .../Converters/StringNumberConverter.cs | 49 ++++ .../Converters/TimeSpanConverter.cs | 43 ++-- .../Serialization/FFprobeSerialzier.cs | 40 +++- Hudl.FFprobe/Settings/PrintFormat.cs | 25 +- Hudl.FFprobe/Settings/ReadIntervals.cs | 21 +- Hudl.FFprobe/Settings/ShowFormat.cs | 11 +- Hudl.FFprobe/Settings/ShowFrames.cs | 11 +- Hudl.FFprobe/Settings/ShowStreams.cs | 11 +- Hudl.Ffmpeg.Tests/Assets/Utilities.cs | 54 +++-- Hudl.Ffmpeg.Tests/Hudl.Ffmpeg.Tests.csproj | 4 +- Hudl.Ffmpeg.Tests/Render/RenderTests.cs | 10 +- Hudl.Ffmpeg.Tests/packages.config | 7 - .../Hudl.FFmpeg.Samples.csproj | 3 +- 40 files changed, 826 insertions(+), 916 deletions(-) delete mode 100644 Hudl.FFmpeg.Core/packages.config delete mode 100644 Hudl.FFmpeg/packages.config create mode 100644 Hudl.FFprobe/CodecTypesUtility.cs create mode 100644 Hudl.FFprobe/Serialization/Converters/NumberStringConverter.cs create mode 100644 Hudl.FFprobe/Serialization/Converters/StringNumberConverter.cs delete mode 100644 Hudl.Ffmpeg.Tests/packages.config diff --git a/Hudl.FFmpeg.Core/Hudl.FFmpeg.Core.csproj b/Hudl.FFmpeg.Core/Hudl.FFmpeg.Core.csproj index 2d2309d..daf35b2 100644 --- a/Hudl.FFmpeg.Core/Hudl.FFmpeg.Core.csproj +++ b/Hudl.FFmpeg.Core/Hudl.FFmpeg.Core.csproj @@ -2,10 +2,10 @@ 7.0.0 - 7.0.0 + 8.0.0 2.0.0.0 - netstandard2.0 + net8.0 full Hudl.FFmpeg.Core Hudl.FFmpeg.Core @@ -18,10 +18,12 @@ false false false + 12 + enable - + diff --git a/Hudl.FFmpeg.Core/packages.config b/Hudl.FFmpeg.Core/packages.config deleted file mode 100644 index bfd3022..0000000 --- a/Hudl.FFmpeg.Core/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/Hudl.FFmpeg/Command/Utility/CommandHelperUtility.cs b/Hudl.FFmpeg/Command/Utility/CommandHelperUtility.cs index 85bcde2..ef001e5 100644 --- a/Hudl.FFmpeg/Command/Utility/CommandHelperUtility.cs +++ b/Hudl.FFmpeg/Command/Utility/CommandHelperUtility.cs @@ -8,152 +8,151 @@ using Hudl.FFmpeg.Settings; using Hudl.FFmpeg.Settings.BaseTypes; -namespace Hudl.FFmpeg.Command.Utility +namespace Hudl.FFmpeg.Command.Utility; + +internal class CommandHelperUtility { - internal class CommandHelperUtility + public static bool ReceiptBelongsToCommand(FFmpegCommand command, StreamIdentifier streamId) { - public static bool ReceiptBelongsToCommand(FFmpegCommand command, StreamIdentifier streamId) + return command.Owner.Id == streamId.FactoryId + && command.Id == streamId.CommandId; + } + + public static int IndexOfFilterchain(FFmpegCommand command, StreamIdentifier streamId) + { + var matchingFilterchain = FilterchainFromStreamIdentifier(command, streamId); + if (matchingFilterchain == null) { - return command.Owner.Id == streamId.FactoryId - && command.Id == streamId.CommandId; + return -1; } - public static int IndexOfFilterchain(FFmpegCommand command, StreamIdentifier streamId) - { - var matchingFilterchain = FilterchainFromStreamIdentifier(command, streamId); - if (matchingFilterchain == null) - { - return -1; - } + return command.Filtergraph.IndexOf(matchingFilterchain); + } - return command.Filtergraph.IndexOf(matchingFilterchain); + public static int IndexOfResource(FFmpegCommand command, StreamIdentifier streamId) + { + var matchingResource = CommandInputFromStreamIdentifier(command, streamId); + if (matchingResource == null) + { + return -1; } - public static int IndexOfResource(FFmpegCommand command, StreamIdentifier streamId) - { - var matchingResource = CommandInputFromStreamIdentifier(command, streamId); - if (matchingResource == null) - { - return -1; - } + return command.Inputs.IndexOf(matchingResource); + } - return command.Inputs.IndexOf(matchingResource); + public static int IndexOfOutput(FFmpegCommand command, StreamIdentifier streamId) + { + var matchingOutput = CommandOutputFromStreamIdentifier(command, streamId); + if (matchingOutput == null) + { + return -1; } - public static int IndexOfOutput(FFmpegCommand command, StreamIdentifier streamId) - { - var matchingOutput = CommandOutputFromStreamIdentifier(command, streamId); - if (matchingOutput == null) - { - return -1; - } + return command.Outputs.IndexOf(matchingOutput); + } - return command.Outputs.IndexOf(matchingOutput); + public static IStream StreamFromStreamIdentifier(FFmpegCommand command, StreamIdentifier streamId) + { + var commandInput = CommandInputFromStreamIdentifier(command, streamId); + if (commandInput != null) + { + return commandInput.Resource.Streams.FirstOrDefault(si => si.Map == streamId.Map); } - public static IStream StreamFromStreamIdentifier(FFmpegCommand command, StreamIdentifier streamId) + var commandOutput = CommandOutputFromStreamIdentifier(command, streamId); + if (commandOutput != null) { - var commandInput = CommandInputFromStreamIdentifier(command, streamId); - if (commandInput != null) - { - return commandInput.Resource.Streams.FirstOrDefault(si => si.Map == streamId.Map); - } - - var commandOutput = CommandOutputFromStreamIdentifier(command, streamId); - if (commandOutput != null) - { - return commandOutput.Resource.Streams.FirstOrDefault(si => si.Map == streamId.Map); - } - - var filterchain = FilterchainFromStreamIdentifier(command, streamId); - if (filterchain != null) - { - var filterchainOutput = filterchain.OutputList.First(si => si.Stream.Map == streamId.Map); - - return filterchainOutput.Stream; - } - - throw new StreamNotFoundException(); + return commandOutput.Resource.Streams.FirstOrDefault(si => si.Map == streamId.Map); } - public static CommandInput CommandInputFromStreamIdentifier(FFmpegCommand command, StreamIdentifier streamId) + var filterchain = FilterchainFromStreamIdentifier(command, streamId); + if (filterchain != null) { - if (streamId == null) - { - throw new ArgumentNullException("streamId"); - } + var filterchainOutput = filterchain.OutputList.First(si => si.Stream.Map == streamId.Map); - return command.Objects.Inputs.FirstOrDefault(i => i.GetStreamIdentifiers().Any(si => si.Map == streamId.Map)); + return filterchainOutput.Stream; } - public static CommandOutput CommandOutputFromStreamIdentifier(FFmpegCommand command, StreamIdentifier streamId) - { - if (streamId == null) - { - throw new ArgumentNullException("streamId"); - } + throw new StreamNotFoundException(); + } - return command.Objects.Outputs.FirstOrDefault(i => i.GetStreamIdentifiers().Any(si => si.Map == streamId.Map)); + public static CommandInput CommandInputFromStreamIdentifier(FFmpegCommand command, StreamIdentifier streamId) + { + if (streamId == null) + { + throw new ArgumentNullException("streamId"); } - public static Filterchain FilterchainFromStreamIdentifier(FFmpegCommand command, StreamIdentifier streamId) - { - if (streamId == null) - { - throw new ArgumentNullException("streamId"); - } + return command.Objects.Inputs.FirstOrDefault(i => i.GetStreamIdentifiers().Any(si => si.Map == streamId.Map)); + } - return command.Objects.Filtergraph.FilterchainList.FirstOrDefault(f => f.GetStreamIdentifiers().Any(r => r.Equals(streamId))); + public static CommandOutput CommandOutputFromStreamIdentifier(FFmpegCommand command, StreamIdentifier streamId) + { + if (streamId == null) + { + throw new ArgumentNullException("streamId"); } - public static CommandOutput SetupCommandOutputMaps(CommandStage stage, SettingsCollection settings, string fileName) - where TOutputType : class, IContainer, new() - { - var settingsCopy = settings.Copy(); - var commandOutput = CommandOutput.Create(Resource.CreateOutput(), settingsCopy); + return command.Objects.Outputs.FirstOrDefault(i => i.GetStreamIdentifiers().Any(si => si.Map == streamId.Map)); + } - stage.StreamIdentifiers.ForEach(streamId => - { - var theStream = StreamFromStreamIdentifier(stage.Command, streamId); - var theResource = CommandInputFromStreamIdentifier(stage.Command, streamId); + public static Filterchain FilterchainFromStreamIdentifier(FFmpegCommand command, StreamIdentifier streamId) + { + if (streamId == null) + { + throw new ArgumentNullException("streamId"); + } - if (theResource == null) - { - commandOutput.Settings.Merge(new Map(streamId), FFmpegMergeOptionType.NewWins); - } - else - { - var resourceIndex = IndexOfResource(stage.Command, streamId); + return command.Objects.Filtergraph.FilterchainList.FirstOrDefault(f => f.GetStreamIdentifiers().Any(r => r.Equals(streamId))); + } - commandOutput.Settings.Merge(new Map(string.Format("{0}:{1}", resourceIndex, theStream.ResourceIndicator)), - FFmpegMergeOptionType.NewWins); - } + public static CommandOutput SetupCommandOutputMaps(CommandStage stage, SettingsCollection settings, string fileName) + where TOutputType : class, IContainer, new() + { + var settingsCopy = settings.Copy(); + var commandOutput = CommandOutput.Create(Resource.CreateOutput(), settingsCopy); - commandOutput.Resource.Streams.Add(theStream.Copy()); - }); + stage.StreamIdentifiers.ForEach(streamId => + { + var theStream = StreamFromStreamIdentifier(stage.Command, streamId); + var theResource = CommandInputFromStreamIdentifier(stage.Command, streamId); - if (!string.IsNullOrWhiteSpace(fileName)) + if (theResource == null) { - commandOutput.Resource.Name = fileName; + commandOutput.Settings.Merge(new Map(streamId), FFmpegMergeOptionType.NewWins); } + else + { + var resourceIndex = IndexOfResource(stage.Command, streamId); - return commandOutput; - } + commandOutput.Settings.Merge(new Map(string.Format("{0}:{1}", resourceIndex, theStream.ResourceIndicator)), + FFmpegMergeOptionType.NewWins); + } + + commandOutput.Resource.Streams.Add(theStream.Copy()); + }); - public static CommandOutput SetupCommandOutput(FFmpegCommand command, SettingsCollection settings, string fileName) - where TOutputType : class, IContainer, new() + if (!string.IsNullOrWhiteSpace(fileName)) { - var settingsCopy = settings.Copy(); - var commandOutput = CommandOutput.Create(Resource.CreateOutput(), settingsCopy); + commandOutput.Resource.Name = fileName; + } - commandOutput.Resource.Streams.AddRange(command.Inputs.SelectMany(i => i.Resource.Streams.Select(s => s.Copy()))); + return commandOutput; + } - if (!string.IsNullOrWhiteSpace(fileName)) - { - commandOutput.Resource.Name = fileName; - } + public static CommandOutput SetupCommandOutput(FFmpegCommand command, SettingsCollection settings, string fileName) + where TOutputType : class, IContainer, new() + { + var settingsCopy = settings.Copy(); + var commandOutput = CommandOutput.Create(Resource.CreateOutput(), settingsCopy); + + commandOutput.Resource.Streams.AddRange(command.Inputs.SelectMany(i => i.Resource.Streams.Select(s => s.Copy()))); - return commandOutput; + if (!string.IsNullOrWhiteSpace(fileName)) + { + commandOutput.Resource.Name = fileName; } + + return commandOutput; } -} +} \ No newline at end of file diff --git a/Hudl.FFmpeg/Hudl.Ffmpeg.csproj b/Hudl.FFmpeg/Hudl.Ffmpeg.csproj index 4056c9b..f688730 100644 --- a/Hudl.FFmpeg/Hudl.Ffmpeg.csproj +++ b/Hudl.FFmpeg/Hudl.Ffmpeg.csproj @@ -2,10 +2,10 @@ 7.0.0 - 7.0.0 + 8.0.0 2.0.0.0 - netstandard2.0 + net8.0 full Hudl.FFmpeg Hudl.FFmpeg @@ -18,11 +18,12 @@ false false false + 12 + enable - - + diff --git a/Hudl.FFmpeg/Hudl.Ffmpeg.nuspec b/Hudl.FFmpeg/Hudl.Ffmpeg.nuspec index e7f3846..4a2fb42 100644 --- a/Hudl.FFmpeg/Hudl.Ffmpeg.nuspec +++ b/Hudl.FFmpeg/Hudl.Ffmpeg.nuspec @@ -10,11 +10,11 @@ https://raw.githubusercontent.com/hudl/HudlFfmpeg/master/hudl.png - - - - - - + + + + + + \ No newline at end of file diff --git a/Hudl.FFmpeg/packages.config b/Hudl.FFmpeg/packages.config deleted file mode 100644 index b4a7998..0000000 --- a/Hudl.FFmpeg/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/Hudl.FFprobe/CodecTypes.cs b/Hudl.FFprobe/CodecTypes.cs index 1c38464..0fad66a 100644 --- a/Hudl.FFprobe/CodecTypes.cs +++ b/Hudl.FFprobe/CodecTypes.cs @@ -1,9 +1,8 @@ -namespace Hudl.FFmpeg.Metadata.FFprobe.BaseTypes +namespace Hudl.FFprobe; + +internal enum CodecTypes { - internal enum CodecTypes - { - Video, - Audio, - Data, - } -} + Video, + Audio, + Data, +} \ No newline at end of file diff --git a/Hudl.FFprobe/CodecTypesUtility.cs b/Hudl.FFprobe/CodecTypesUtility.cs new file mode 100644 index 0000000..f86ac95 --- /dev/null +++ b/Hudl.FFprobe/CodecTypesUtility.cs @@ -0,0 +1,12 @@ +namespace Hudl.FFprobe; + +internal static class CodecTypesUtility +{ + public static CodecTypes? GetCodecTypeFromMediaType(string? mediaType) => mediaType?.ToLowerInvariant()?.Trim() switch + { + "video" => CodecTypes.Video, + "audio" => CodecTypes.Audio, + "data" => CodecTypes.Data, + _ => null, + }; +} \ No newline at end of file diff --git a/Hudl.FFprobe/Command/FFprobeCommand.cs b/Hudl.FFprobe/Command/FFprobeCommand.cs index 033fb3f..4413aa5 100644 --- a/Hudl.FFprobe/Command/FFprobeCommand.cs +++ b/Hudl.FFprobe/Command/FFprobeCommand.cs @@ -5,46 +5,45 @@ using Hudl.FFmpeg.Resources.Interfaces; using Hudl.FFmpeg.Settings.Interfaces; -namespace Hudl.FFprobe.Command +namespace Hudl.FFprobe.Command; + +public class FFprobeCommand : FFCommandBase { - public class FFprobeCommand : FFCommandBase + private FFprobeCommand(IContainer resource) { - private FFprobeCommand(IContainer resource) - { - Resource = resource; - Settings = new List(); - } + Resource = resource; + Settings = new List(); + } - public IContainer Resource { get; set; } + public IContainer Resource { get; set; } - public List Settings { get; set; } + public List Settings { get; set; } - public static FFprobeCommand Create(IContainer resource) - { - return new FFprobeCommand(resource); - } + public static FFprobeCommand Create(IContainer resource) + { + return new FFprobeCommand(resource); + } - public FFprobeCommand AddSetting(ISetting setting) + public FFprobeCommand AddSetting(ISetting setting) + { + if (setting == null) { - if (setting == null) - { - throw new ArgumentNullException("setting"); - } - - Settings.Add(setting); - - return this; + throw new ArgumentNullException("setting"); } - public ICommandProcessor Execute() - { - return Execute(null); - } + Settings.Add(setting); - public ICommandProcessor Execute(int? timeoutMilliseconds) - { - return ExecuteWith(timeoutMilliseconds); - } + return this; + } + public ICommandProcessor Execute() + { + return Execute(null); } -} + + public ICommandProcessor Execute(int? timeoutMilliseconds) + { + return ExecuteWith(timeoutMilliseconds); + } + +} \ No newline at end of file diff --git a/Hudl.FFprobe/Command/FFprobeCommandBuilder.cs b/Hudl.FFprobe/Command/FFprobeCommandBuilder.cs index 495db53..190ec46 100644 --- a/Hudl.FFprobe/Command/FFprobeCommandBuilder.cs +++ b/Hudl.FFprobe/Command/FFprobeCommandBuilder.cs @@ -4,27 +4,26 @@ using Hudl.FFmpeg.Settings.Interfaces; using Hudl.FFmpeg.Settings.Serialization; -namespace Hudl.FFprobe.Command +namespace Hudl.FFprobe.Command; + +internal class FFprobeCommandBuilder : FFCommandBuilderBase, ICommandBuilder { - internal class FFprobeCommandBuilder : FFCommandBuilderBase, ICommandBuilder + public void WriteCommand(ICommand command) { - public void WriteCommand(ICommand command) - { - WriteCommand((FFprobeCommand)command); - } + WriteCommand((FFprobeCommand)command); + } - public void WriteCommand(FFprobeCommand command) - { - var inputResource = new Input(command.Resource); - BuilderBase.Append(" "); - BuilderBase.Append(SettingSerializer.Serialize(inputResource)); + public void WriteCommand(FFprobeCommand command) + { + var inputResource = new Input(command.Resource); + BuilderBase.Append(" "); + BuilderBase.Append(SettingSerializer.Serialize(inputResource)); - command.Settings.ForEach(WriteSerializerSpecifier); - } - public void WriteSerializerSpecifier(ISetting setting) - { - BuilderBase.Append(" "); - BuilderBase.Append(SettingSerializer.Serialize(setting)); - } + command.Settings.ForEach(WriteSerializerSpecifier); + } + public void WriteSerializerSpecifier(ISetting setting) + { + BuilderBase.Append(" "); + BuilderBase.Append(SettingSerializer.Serialize(setting)); } -} +} \ No newline at end of file diff --git a/Hudl.FFprobe/Command/FFprobeCommandProcessor.cs b/Hudl.FFprobe/Command/FFprobeCommandProcessor.cs index a784e9b..8dabeb0 100644 --- a/Hudl.FFprobe/Command/FFprobeCommandProcessor.cs +++ b/Hudl.FFprobe/Command/FFprobeCommandProcessor.cs @@ -7,163 +7,162 @@ using Hudl.FFmpeg.Exceptions; using Hudl.FFmpeg.Logging; -namespace Hudl.FFprobe.Command +namespace Hudl.FFprobe.Command; + +internal class FFprobeCommandProcessor : ICommandProcessor { - internal class FFprobeCommandProcessor : ICommandProcessor + private static readonly LogUtility Log = LogUtility.GetLogger(typeof(FFprobeCommandProcessor)); + + public FFprobeCommandProcessor() { - private static readonly LogUtility Log = LogUtility.GetLogger(typeof(FFprobeCommandProcessor)); + Status = CommandProcessorStatus.Closed; + } - public FFprobeCommandProcessor() - { - Status = CommandProcessorStatus.Closed; - } + public Exception Error { get; protected set; } - public Exception Error { get; protected set; } + public string StdOut { get; protected set; } + public string Command { get; protected set; } - public string StdOut { get; protected set; } - public string Command { get; protected set; } + public CommandProcessorStatus Status { get; protected set; } - public CommandProcessorStatus Status { get; protected set; } + public bool Open() + { + if (Status != CommandProcessorStatus.Closed) + { + throw new InvalidOperationException(string.Format("Cannot open a command processor that is currently in the '{0}' state.", Status)); + } - public bool Open() + try { - if (Status != CommandProcessorStatus.Closed) - { - throw new InvalidOperationException(string.Format("Cannot open a command processor that is currently in the '{0}' state.", Status)); - } + Log.SetAttributes(ResourceManagement.CommandConfiguration.LoggingAttributes); - try - { - Log.SetAttributes(ResourceManagement.CommandConfiguration.LoggingAttributes); + Log.DebugFormat("Opening command processor."); - Log.DebugFormat("Opening command processor."); + Create(); - Create(); + Status = CommandProcessorStatus.Ready; + } + catch (Exception err) + { + Error = err; + Status = CommandProcessorStatus.Faulted; + return false; + } - Status = CommandProcessorStatus.Ready; - } - catch (Exception err) - { - Error = err; - Status = CommandProcessorStatus.Faulted; - return false; - } + return true; + } - return true; + public bool Close() + { + if (Status != CommandProcessorStatus.Ready) + { + throw new InvalidOperationException(string.Format("Cannot close a command processor that is currently in the '{0}' state.", Status)); } - public bool Close() + try { - if (Status != CommandProcessorStatus.Ready) - { - throw new InvalidOperationException(string.Format("Cannot close a command processor that is currently in the '{0}' state.", Status)); - } + Log.DebugFormat("Closing command processor."); - try - { - Log.DebugFormat("Closing command processor."); + Delete(); - Delete(); - - Status = CommandProcessorStatus.Closed; - } - catch (Exception err) - { - Error = err; - Status = CommandProcessorStatus.Faulted; - return false; - } - return true; + Status = CommandProcessorStatus.Closed; } - - public bool Send(string command) + catch (Exception err) { - return Send(command, null); + Error = err; + Status = CommandProcessorStatus.Faulted; + return false; } + return true; + } - public bool Send(string command, int? timeoutMilliseconds) + public bool Send(string command) + { + return Send(command, null); + } + + public bool Send(string command, int? timeoutMilliseconds) + { + if (Status != CommandProcessorStatus.Ready) { - if (Status != CommandProcessorStatus.Ready) - { - throw new InvalidOperationException(string.Format("Cannot process a command processor that is currently in the '{0}' state.", Status)); - } - if (string.IsNullOrWhiteSpace(command)) - { - throw new ArgumentException("Processing command cannot be null or empty.", "command"); - } + throw new InvalidOperationException(string.Format("Cannot process a command processor that is currently in the '{0}' state.", Status)); + } + if (string.IsNullOrWhiteSpace(command)) + { + throw new ArgumentException("Processing command cannot be null or empty.", "command"); + } - Command = command; + Command = command; - try - { - Status = CommandProcessorStatus.Processing; + try + { + Status = CommandProcessorStatus.Processing; - ProcessIt(command, timeoutMilliseconds); + ProcessIt(command, timeoutMilliseconds); - Status = CommandProcessorStatus.Ready; - } - catch (Exception err) - { - Error = err; - Status = CommandProcessorStatus.Faulted; - return false; - } - - return true; + Status = CommandProcessorStatus.Ready; + } + catch (Exception err) + { + Error = err; + Status = CommandProcessorStatus.Faulted; + return false; } - private void Create() + return true; + } + + private void Create() + { + if (ResourceManagement.CommandConfiguration.HasFlag(CommandConfigurationFlagTypes.PerformPreRenderSetup)) { - if (ResourceManagement.CommandConfiguration.HasFlag(CommandConfigurationFlagTypes.PerformPreRenderSetup)) - { - Log.DebugFormat("Creating temporary directories."); + Log.DebugFormat("Creating temporary directories."); - Directory.CreateDirectory(ResourceManagement.CommandConfiguration.TempPath); + Directory.CreateDirectory(ResourceManagement.CommandConfiguration.TempPath); - Directory.CreateDirectory(ResourceManagement.CommandConfiguration.OutputPath); - } + Directory.CreateDirectory(ResourceManagement.CommandConfiguration.OutputPath); } + } - private void Delete() + private void Delete() + { + if (ResourceManagement.CommandConfiguration.HasFlag(CommandConfigurationFlagTypes.PerformPostRenderCleanup)) { - if (ResourceManagement.CommandConfiguration.HasFlag(CommandConfigurationFlagTypes.PerformPostRenderCleanup)) - { - Log.DebugFormat("Removing temporary directories."); + Log.DebugFormat("Removing temporary directories."); - Directory.Delete(ResourceManagement.CommandConfiguration.TempPath, true); - } + Directory.Delete(ResourceManagement.CommandConfiguration.TempPath, true); } + } - private void ProcessIt(string command, int? timeoutMilliseconds) + private void ProcessIt(string command, int? timeoutMilliseconds) + { + using (var FFprobeProcess = new Process()) { - using (var FFprobeProcess = new Process()) + FFprobeProcess.StartInfo = new ProcessStartInfo { - FFprobeProcess.StartInfo = new ProcessStartInfo - { - FileName = ResourceManagement.CommandConfiguration.FFprobePath, - WorkingDirectory = ResourceManagement.CommandConfiguration.TempPath, - Arguments = command.Trim(), - CreateNoWindow = true, - UseShellExecute = false, - RedirectStandardOutput = true, - }; - - Log.DebugFormat("FFprobe.exe Args={0}.", FFprobeProcess.StartInfo.Arguments); + FileName = ResourceManagement.CommandConfiguration.FFprobePath, + WorkingDirectory = ResourceManagement.CommandConfiguration.TempPath, + Arguments = command.Trim(), + CreateNoWindow = true, + UseShellExecute = false, + RedirectStandardOutput = true, + }; + + Log.DebugFormat("FFprobe.exe Args={0}.", FFprobeProcess.StartInfo.Arguments); - FFprobeProcess.Start(); + FFprobeProcess.Start(); - StdOut = FFprobeProcess.StandardOutput.ReadToEnd(); + StdOut = FFprobeProcess.StandardOutput.ReadToEnd(); - FFprobeProcess.WaitForExit(); + FFprobeProcess.WaitForExit(); - Log.DebugFormat("FFprobe.exe Output={0}.", StdOut); + Log.DebugFormat("FFprobe.exe Output={0}.", StdOut); - var exitCode = FFprobeProcess.ExitCode; - if (exitCode != 0) - { - throw new FFmpegProcessingException(exitCode, StdOut); - } + var exitCode = FFprobeProcess.ExitCode; + if (exitCode != 0) + { + throw new FFmpegProcessingException(exitCode, StdOut); } } } -} +} \ No newline at end of file diff --git a/Hudl.FFprobe/Hudl.FFprobe.csproj b/Hudl.FFprobe/Hudl.FFprobe.csproj index e3981ce..a91dfd3 100644 --- a/Hudl.FFprobe/Hudl.FFprobe.csproj +++ b/Hudl.FFprobe/Hudl.FFprobe.csproj @@ -2,10 +2,10 @@ 7.0.0 - 7.0.0 + 8.0.0 2.0.0.0 - netstandard2.0 + net8.0 full Hudl.FFprobe Hudl.FFprobe @@ -18,11 +18,11 @@ false false false + enable - - + diff --git a/Hudl.FFprobe/MediaLoader.cs b/Hudl.FFprobe/MediaLoader.cs index 769993b..ca27041 100644 --- a/Hudl.FFprobe/MediaLoader.cs +++ b/Hudl.FFprobe/MediaLoader.cs @@ -5,64 +5,63 @@ using Hudl.FFprobe.Serialization; using Hudl.FFprobe.Settings; -namespace Hudl.FFprobe +namespace Hudl.FFprobe; + +public class MediaLoader { - public class MediaLoader + public MediaLoader(IContainer resource) + { + ReadInfo(resource); + } + + public void ReadInfo(IContainer resource) { - public MediaLoader(IContainer resource) + ReadInfo(resource, LoaderFlags.ShowFormat | LoaderFlags.ShowStreams); + } + + + public void ReadInfo(IContainer resource, LoaderFlags flags) + { + var ffprobeCommand = FFprobeCommand.Create(resource) + .AddSetting(new PrintFormat(PrintFormat.JsonFormat)); + + if (flags.HasFlag(LoaderFlags.ShowFormat)) { - ReadInfo(resource); + ffprobeCommand.AddSetting(new ShowFormat()); } - public void ReadInfo(IContainer resource) + if (flags.HasFlag(LoaderFlags.ShowStreams)) { - ReadInfo(resource, LoaderFlags.ShowFormat | LoaderFlags.ShowStreams); + ffprobeCommand.AddSetting(new ShowStreams()); } - - public void ReadInfo(IContainer resource, LoaderFlags flags) + if (flags.HasFlag(LoaderFlags.ShowFrames)) { - var ffprobeCommand = FFprobeCommand.Create(resource) - .AddSetting(new PrintFormat(PrintFormat.JsonFormat)); - - if (flags.HasFlag(LoaderFlags.ShowFormat)) - { - ffprobeCommand.AddSetting(new ShowFormat()); - } - - if (flags.HasFlag(LoaderFlags.ShowStreams)) - { - ffprobeCommand.AddSetting(new ShowStreams()); - } - - if (flags.HasFlag(LoaderFlags.ShowFrames)) - { - ffprobeCommand.AddSetting(new ShowFrames()); - } + ffprobeCommand.AddSetting(new ShowFrames()); + } - var commandProcessor = ffprobeCommand.Execute(null); + var commandProcessor = ffprobeCommand.Execute(null); - var containerMetadata = FFprobeSerializer.Serialize(commandProcessor); - - HasAudio = containerMetadata.Streams != null && containerMetadata.Streams.OfType().Any(); - HasVideo = containerMetadata.Streams != null && containerMetadata.Streams.OfType().Any(); - HasData = containerMetadata.Streams != null && containerMetadata.Streams.OfType().Any(); - HasFrames = containerMetadata.Frames != null && containerMetadata.Frames.Any(); - BaseData = containerMetadata; - } + var containerMetadata = FFprobeSerializer.Instance.Serialize(commandProcessor); - public enum LoaderFlags - { - None = 0, - ShowFormat = 1 << 0, - ShowStreams = 1 << 1, - ShowFrames = 1 << 2, - } + HasAudio = containerMetadata?.Streams?.OfType()?.ToList()?.Count > 0; + HasVideo = containerMetadata?.Streams?.OfType()?.ToList()?.Count > 0; + HasData = containerMetadata?.Streams?.OfType()?.ToList()?.Count > 0; + HasFrames = containerMetadata?.Frames?.Count > 0; + BaseData = containerMetadata; + } - public bool HasVideo { get; protected set; } - public bool HasAudio { get; protected set; } - public bool HasData { get; protected set; } - public bool HasFrames { get; protected set; } - public ContainerMetadata BaseData { get; protected set; } + public enum LoaderFlags + { + None = 0, + ShowFormat = 1 << 0, + ShowStreams = 1 << 1, + ShowFrames = 1 << 2, } -} + + public bool HasVideo { get; protected set; } + public bool HasAudio { get; protected set; } + public bool HasData { get; protected set; } + public bool HasFrames { get; protected set; } + public ContainerMetadata BaseData { get; protected set; } +} \ No newline at end of file diff --git a/Hudl.FFprobe/Metadata/Models/AudioFrameMetadata.cs b/Hudl.FFprobe/Metadata/Models/AudioFrameMetadata.cs index 5a90e29..7a798ef 100644 --- a/Hudl.FFprobe/Metadata/Models/AudioFrameMetadata.cs +++ b/Hudl.FFprobe/Metadata/Models/AudioFrameMetadata.cs @@ -1,25 +1,23 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; -namespace Hudl.FFprobe.Metadata.Models +namespace Hudl.FFprobe.Metadata.Models; + +public class AudioFrameMetadata : BaseFrameMetadata { - [JsonObject] - public class AudioFrameMetadata : BaseFrameMetadata - { - [JsonProperty(PropertyName = "sample_fmt")] - public string SampleFormat { get; set; } + [JsonPropertyName("sample_fmt")] + public string SampleFormat { get; set; } - [JsonProperty(PropertyName = "channels")] - public int Channels { get; set; } + [JsonPropertyName("channels")] + public int Channels { get; set; } - [JsonProperty(PropertyName = "channel_layout")] - public string ChannelLayout { get; set; } + [JsonPropertyName("channel_layout")] + public string ChannelLayout { get; set; } - [JsonProperty(PropertyName = "nb_samples")] - public int NumberOfSamples { get; set; } + [JsonPropertyName("nb_samples")] + public int NumberOfSamples { get; set; } - public AudioFrameMetadata Copy() - { - return (AudioFrameMetadata)MemberwiseClone(); - } + public AudioFrameMetadata Copy() + { + return (AudioFrameMetadata)MemberwiseClone(); } -} +} \ No newline at end of file diff --git a/Hudl.FFprobe/Metadata/Models/AudioStreamMetadata.cs b/Hudl.FFprobe/Metadata/Models/AudioStreamMetadata.cs index 8c43acc..acfd15b 100644 --- a/Hudl.FFprobe/Metadata/Models/AudioStreamMetadata.cs +++ b/Hudl.FFprobe/Metadata/Models/AudioStreamMetadata.cs @@ -1,28 +1,26 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; -namespace Hudl.FFprobe.Metadata.Models +namespace Hudl.FFprobe.Metadata.Models; + +public class AudioStreamMetadata : BaseStreamMetadata { - [JsonObject] - public class AudioStreamMetadata : BaseStreamMetadata - { - [JsonProperty(PropertyName = "sample_fmt")] - public string SampleFormat { get; set; } + [JsonPropertyName("sample_fmt")] + public string SampleFormat { get; set; } - [JsonProperty(PropertyName = "sample_rate")] - public int SampleRate { get; set; } + [JsonPropertyName("sample_rate")] + public int SampleRate { get; set; } - [JsonProperty(PropertyName = "channels")] - public int Channels { get; set; } + [JsonPropertyName("channels")] + public int Channels { get; set; } - [JsonProperty(PropertyName = "channel_layout")] - public string ChannelLayout { get; set; } + [JsonPropertyName("channel_layout")] + public string ChannelLayout { get; set; } - [JsonProperty(PropertyName = "bits_per_sample")] - public int BitsPerSample { get; set; } + [JsonPropertyName("bits_per_sample")] + public int BitsPerSample { get; set; } - public AudioStreamMetadata Copy() - { - return (AudioStreamMetadata)MemberwiseClone(); - } + public AudioStreamMetadata Copy() + { + return (AudioStreamMetadata)MemberwiseClone(); } -} +} \ No newline at end of file diff --git a/Hudl.FFprobe/Metadata/Models/BaseFrameMetadata.cs b/Hudl.FFprobe/Metadata/Models/BaseFrameMetadata.cs index b6c1c7e..ad35de4 100644 --- a/Hudl.FFprobe/Metadata/Models/BaseFrameMetadata.cs +++ b/Hudl.FFprobe/Metadata/Models/BaseFrameMetadata.cs @@ -1,58 +1,50 @@ using System; using System.Collections.Generic; +using System.Text.Json; +using System.Text.Json.Serialization; using Hudl.FFprobe.Serialization.Converters; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -namespace Hudl.FFprobe.Metadata.Models -{ - [JsonObject] - public class BaseFrameMetadata - { - public BaseFrameMetadata() - { - AdditionalData = new Dictionary(); - } - - [JsonProperty(PropertyName = "media_type")] - public string MediaType { get; set; } +namespace Hudl.FFprobe.Metadata.Models; - [JsonProperty(PropertyName = "stream_index")] - public int StreamIndex { get; set; } +public class BaseFrameMetadata +{ + [JsonPropertyName("media_type")] + public string MediaType { get; set; } - [JsonProperty(PropertyName = "key_frame")] - public long KeyFrame { get; set; } + [JsonPropertyName("stream_index")] + public int StreamIndex { get; set; } - [JsonProperty(PropertyName = "pkt_pts")] - public long PacketPresentationTimestamp { get; set; } + [JsonPropertyName("key_frame")] + public long KeyFrame { get; set; } - [JsonProperty(PropertyName = "pkt_pts_time")] - [JsonConverter(typeof(TimeSpanConverter))] - public TimeSpan PacketPresentationTimestampTime { get; set; } + [JsonPropertyName("pkt_pts")] + public long PacketPresentationTimestamp { get; set; } - [JsonProperty(PropertyName = "pkt_dts")] - public long PacketDecodingTimestamp { get; set; } + [JsonPropertyName("pkt_pts_time")] + [JsonConverter(typeof(TimeSpanConverter))] + public TimeSpan PacketPresentationTimestampTime { get; set; } - [JsonProperty(PropertyName = "pkt_dts_time")] - [JsonConverter(typeof(TimeSpanConverter))] - public TimeSpan PacketDecodingTimestampTime { get; set; } + [JsonPropertyName("pkt_dts")] + public long PacketDecodingTimestamp { get; set; } - [JsonProperty(PropertyName = "pkt_duration")] - public long PacketDuration { get; set; } + [JsonPropertyName("pkt_dts_time")] + [JsonConverter(typeof(TimeSpanConverter))] + public TimeSpan PacketDecodingTimestampTime { get; set; } - [JsonProperty(PropertyName = "pkt_duration_time")] - [JsonConverter(typeof(TimeSpanConverter))] - public TimeSpan PacketDurationTime { get; set; } + [JsonPropertyName("pkt_duration")] + public long PacketDuration { get; set; } - [JsonProperty(PropertyName = "best_effort_timestamp")] - public long BestEffortTimestamp { get; set; } + [JsonPropertyName("pkt_duration_time")] + [JsonConverter(typeof(TimeSpanConverter))] + public TimeSpan PacketDurationTime { get; set; } - [JsonProperty(PropertyName = "best_effort_timestamp_time")] - [JsonConverter(typeof(TimeSpanConverter))] - public TimeSpan BestEffortTimestampTime { get; set; } + [JsonPropertyName("best_effort_timestamp")] + public long BestEffortTimestamp { get; set; } - [JsonExtensionData] - public IDictionary AdditionalData; - } + [JsonPropertyName("best_effort_timestamp_time")] + [JsonConverter(typeof(TimeSpanConverter))] + public TimeSpan BestEffortTimestampTime { get; set; } -} + [JsonExtensionData] + public Dictionary AdditionalData { get; set; } = []; +} \ No newline at end of file diff --git a/Hudl.FFprobe/Metadata/Models/BaseStreamMetadata.cs b/Hudl.FFprobe/Metadata/Models/BaseStreamMetadata.cs index 5ea47b4..d0f7cd6 100644 --- a/Hudl.FFprobe/Metadata/Models/BaseStreamMetadata.cs +++ b/Hudl.FFprobe/Metadata/Models/BaseStreamMetadata.cs @@ -1,78 +1,70 @@ using System; using System.Collections.Generic; using Hudl.FFmpeg.DataTypes; -using Hudl.FFprobe.Serialization; using Hudl.FFprobe.Serialization.Converters; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -namespace Hudl.FFprobe.Metadata.Models -{ - [JsonObject] - public class BaseStreamMetadata - { - public BaseStreamMetadata() - { - AdditionalData = new Dictionary(); - } +using System.Text.Json; +using System.Text.Json.Serialization; - [JsonProperty(PropertyName = "index")] - public int Index { get; set; } +namespace Hudl.FFprobe.Metadata.Models; - [JsonProperty(PropertyName = "codec_name")] - public string CodecName { get; set; } +public class BaseStreamMetadata +{ + [JsonPropertyName("index")] + public int Index { get; set; } - [JsonProperty(PropertyName = "codec_long_name")] - public string CodecLongName { get; set; } + [JsonPropertyName("codec_name")] + public string CodecName { get; set; } - [JsonProperty(PropertyName = "codec_type")] - public string CodecType { get; set; } + [JsonPropertyName("codec_long_name")] + public string CodecLongName { get; set; } - [JsonProperty(PropertyName = "codec_time_base")] - [JsonConverter(typeof(FractionConverter))] - public Fraction CodecTimeBase { get; set; } + [JsonPropertyName("codec_type")] + public string CodecType { get; set; } - [JsonProperty(PropertyName = "codec_tag_string")] - public string CodecTagString { get; set; } + [JsonPropertyName("codec_time_base")] + [JsonConverter(typeof(FractionConverter))] + public Fraction CodecTimeBase { get; set; } - [JsonProperty(PropertyName = "codec_tag")] - public string CodecTag { get; set; } + [JsonPropertyName("codec_tag_string")] + public string CodecTagString { get; set; } - [JsonProperty(PropertyName = "profile")] - public string Profile { get; set; } + [JsonPropertyName("codec_tag")] + public string CodecTag { get; set; } - [JsonProperty(PropertyName = "time_base")] - [JsonConverter(typeof(FractionConverter))] - public Fraction TimeBase { get; set; } + [JsonPropertyName("profile")] + public string Profile { get; set; } - [JsonProperty(PropertyName = "bit_rate")] - public long BitRate { get; set; } + [JsonPropertyName("time_base")] + [JsonConverter(typeof(FractionConverter))] + public Fraction TimeBase { get; set; } - [JsonProperty(PropertyName = "start_pts")] - public long StartTimeTs { get; set; } + [JsonPropertyName("bit_rate")] + public long BitRate { get; set; } - [JsonProperty(PropertyName = "start_time")] - [JsonConverter(typeof(TimeSpanConverter))] - public TimeSpan StartTime { get; set; } + [JsonPropertyName("start_pts")] + public long StartTimeTs { get; set; } - [JsonProperty(PropertyName = "duration_ts")] - public long DurationTs { get; set; } + [JsonPropertyName("start_time")] + [JsonConverter(typeof(TimeSpanConverter))] + public TimeSpan StartTime { get; set; } - [JsonProperty(PropertyName = "duration")] - [JsonConverter(typeof(TimeSpanConverter))] - public TimeSpan Duration { get; set; } + [JsonPropertyName("duration_ts")] + public long DurationTs { get; set; } - [JsonProperty(PropertyName = "nb_frames")] - public int NumberOfFrames { get; set; } + [JsonPropertyName("duration")] + [JsonConverter(typeof(TimeSpanConverter))] + public TimeSpan Duration { get; set; } - [JsonProperty(PropertyName = "disposition")] - public Dictionary Disposition { get; set; } + [JsonPropertyName("nb_frames")] + public int NumberOfFrames { get; set; } - [JsonProperty(PropertyName = "tags")] - public Dictionary Tags { get; set; } + [JsonPropertyName("disposition")] + public Dictionary Disposition { get; set; } - [JsonExtensionData] - public IDictionary AdditionalData; - } + [JsonPropertyName("tags")] + public Dictionary Tags { get; set; } -} + [JsonExtensionData] + public Dictionary AdditionalData { get; set; } = []; +} \ No newline at end of file diff --git a/Hudl.FFprobe/Metadata/Models/ContainerMetadata.cs b/Hudl.FFprobe/Metadata/Models/ContainerMetadata.cs index f370c17..14e2426 100644 --- a/Hudl.FFprobe/Metadata/Models/ContainerMetadata.cs +++ b/Hudl.FFprobe/Metadata/Models/ContainerMetadata.cs @@ -1,22 +1,19 @@ using System.Collections.Generic; -using Hudl.FFprobe.Serialization; +using System.Text.Json.Serialization; using Hudl.FFprobe.Serialization.Converters; -using Newtonsoft.Json; -namespace Hudl.FFprobe.Metadata.Models +namespace Hudl.FFprobe.Metadata.Models; + +public class ContainerMetadata { - [JsonObject] - public class ContainerMetadata - { - [JsonProperty(PropertyName = "format")] - public FormatMetadata Format { get; set; } + [JsonPropertyName("format")] + public FormatMetadata Format { get; set; } - [JsonProperty(PropertyName = "streams")] - [JsonConverter(typeof(StreamConverter))] - public List Streams { get; set; } + [JsonPropertyName("streams")] + [JsonConverter(typeof(StreamConverter))] + public List Streams { get; set; } - [JsonProperty(PropertyName = "frames")] - [JsonConverter(typeof(FrameConverter))] - public List Frames { get; set; } - } -} + [JsonPropertyName("frames")] + [JsonConverter(typeof(FrameConverter))] + public List Frames { get; set; } +} \ No newline at end of file diff --git a/Hudl.FFprobe/Metadata/Models/DataStreamMetadata.cs b/Hudl.FFprobe/Metadata/Models/DataStreamMetadata.cs index 7a8eded..3a6c811 100644 --- a/Hudl.FFprobe/Metadata/Models/DataStreamMetadata.cs +++ b/Hudl.FFprobe/Metadata/Models/DataStreamMetadata.cs @@ -1,13 +1,9 @@ -using Newtonsoft.Json; +namespace Hudl.FFprobe.Metadata.Models; -namespace Hudl.FFprobe.Metadata.Models +public class DataStreamMetadata : BaseStreamMetadata { - [JsonObject] - public class DataStreamMetadata : BaseStreamMetadata + public DataStreamMetadata Copy() { - public DataStreamMetadata Copy() - { - return (DataStreamMetadata)MemberwiseClone(); - } + return (DataStreamMetadata)MemberwiseClone(); } -} +} \ No newline at end of file diff --git a/Hudl.FFprobe/Metadata/Models/FormatMetadata.cs b/Hudl.FFprobe/Metadata/Models/FormatMetadata.cs index f14dd40..9d45f27 100644 --- a/Hudl.FFprobe/Metadata/Models/FormatMetadata.cs +++ b/Hudl.FFprobe/Metadata/Models/FormatMetadata.cs @@ -1,47 +1,44 @@ using System; using System.Collections.Generic; -using Hudl.FFprobe.Serialization; +using System.Text.Json.Serialization; using Hudl.FFprobe.Serialization.Converters; -using Newtonsoft.Json; -namespace Hudl.FFprobe.Metadata.Models +namespace Hudl.FFprobe.Metadata.Models; + +public class FormatMetadata { - [JsonObject] - public class FormatMetadata - { - [JsonProperty(PropertyName = "filename")] - public string FileName { get; set; } + [JsonPropertyName("filename")] + public string FileName { get; set; } - [JsonProperty(PropertyName = "nb_streams")] - public int NumberOfStreams { get; set; } + [JsonPropertyName("nb_streams")] + public int NumberOfStreams { get; set; } - [JsonProperty(PropertyName = "nb_programs")] - public int NumberOfPrograms { get; set; } + [JsonPropertyName("nb_programs")] + public int NumberOfPrograms { get; set; } - [JsonProperty(PropertyName = "format_name")] - public string FormatName { get; set; } + [JsonPropertyName("format_name")] + public string FormatName { get; set; } - [JsonProperty(PropertyName = "format_long_name")] - public string FormatLongName { get; set; } + [JsonPropertyName("format_long_name")] + public string FormatLongName { get; set; } - [JsonProperty(PropertyName = "start_time")] - [JsonConverter(typeof(TimeSpanConverter))] - public TimeSpan StartTime { get; set; } + [JsonPropertyName("start_time")] + [JsonConverter(typeof(TimeSpanConverter))] + public TimeSpan StartTime { get; set; } - [JsonProperty(PropertyName = "duration")] - [JsonConverter(typeof(TimeSpanConverter))] - public TimeSpan Duration { get; set; } + [JsonPropertyName("duration")] + [JsonConverter(typeof(TimeSpanConverter))] + public TimeSpan Duration { get; set; } - [JsonProperty(PropertyName = "size")] - public string Size { get; set; } + [JsonPropertyName("size")] + public string Size { get; set; } - [JsonProperty(PropertyName = "bit_rate")] - public long BitRate { get; set; } + [JsonPropertyName("bit_rate")] + public long BitRate { get; set; } - [JsonProperty(PropertyName = "probe_score")] - public int ProbeScore { get; set; } + [JsonPropertyName("probe_score")] + public int ProbeScore { get; set; } - [JsonProperty(PropertyName = "tags")] - public Dictionary Tags { get; set; } - } -} + [JsonPropertyName("tags")] + public Dictionary Tags { get; set; } +} \ No newline at end of file diff --git a/Hudl.FFprobe/Metadata/Models/VideoFrameMetadata.cs b/Hudl.FFprobe/Metadata/Models/VideoFrameMetadata.cs index b18f872..1828478 100644 --- a/Hudl.FFprobe/Metadata/Models/VideoFrameMetadata.cs +++ b/Hudl.FFprobe/Metadata/Models/VideoFrameMetadata.cs @@ -1,32 +1,29 @@ -using Hudl.FFmpeg.DataTypes; -using Hudl.FFprobe.Serialization; +using System.Text.Json.Serialization; +using Hudl.FFmpeg.DataTypes; using Hudl.FFprobe.Serialization.Converters; -using Newtonsoft.Json; -namespace Hudl.FFprobe.Metadata.Models +namespace Hudl.FFprobe.Metadata.Models; + +public class VideoFrameMetadata : BaseFrameMetadata { - [JsonObject] - public class VideoFrameMetadata : BaseFrameMetadata - { - [JsonProperty(PropertyName = "width")] - public int Width { get; set; } + [JsonPropertyName("width")] + public int Width { get; set; } - [JsonProperty(PropertyName = "height")] - public int Height { get; set; } + [JsonPropertyName("height")] + public int Height { get; set; } - [JsonProperty(PropertyName = "sample_aspect_ratio")] - [JsonConverter(typeof(RatioConverter))] - public Ratio SampleAspectRatio { get; set; } + [JsonPropertyName("sample_aspect_ratio")] + [JsonConverter(typeof(RatioConverter))] + public Ratio SampleAspectRatio { get; set; } - [JsonProperty(PropertyName = "pix_fmt")] - public string PixelFormat { get; set; } + [JsonPropertyName("pix_fmt")] + public string PixelFormat { get; set; } - [JsonProperty(PropertyName = "pict_type")] - public string PictureType { get; set; } + [JsonPropertyName("pict_type")] + public string PictureType { get; set; } - public VideoFrameMetadata Copy() - { - return (VideoFrameMetadata) MemberwiseClone(); - } + public VideoFrameMetadata Copy() + { + return (VideoFrameMetadata) MemberwiseClone(); } -} +} \ No newline at end of file diff --git a/Hudl.FFprobe/Metadata/Models/VideoStreamMetadata.cs b/Hudl.FFprobe/Metadata/Models/VideoStreamMetadata.cs index d944fad..3784a89 100644 --- a/Hudl.FFprobe/Metadata/Models/VideoStreamMetadata.cs +++ b/Hudl.FFprobe/Metadata/Models/VideoStreamMetadata.cs @@ -1,53 +1,50 @@ -using Hudl.FFmpeg.DataTypes; -using Hudl.FFprobe.Serialization; +using System.Text.Json.Serialization; +using Hudl.FFmpeg.DataTypes; using Hudl.FFprobe.Serialization.Converters; -using Newtonsoft.Json; -namespace Hudl.FFprobe.Metadata.Models +namespace Hudl.FFprobe.Metadata.Models; + +public class VideoStreamMetadata : BaseStreamMetadata { - [JsonObject] - public class VideoStreamMetadata : BaseStreamMetadata - { - [JsonProperty(PropertyName = "width")] - public int Width { get; set; } + [JsonPropertyName("width")] + public int Width { get; set; } - [JsonProperty(PropertyName = "height")] - public int Height { get; set; } + [JsonPropertyName("height")] + public int Height { get; set; } - [JsonProperty(PropertyName = "coded_width")] - public int CodedWidth { get; set; } + [JsonPropertyName("coded_width")] + public int CodedWidth { get; set; } - [JsonProperty(PropertyName = "coded_height")] - public int CodedHeight { get; set; } + [JsonPropertyName("coded_height")] + public int CodedHeight { get; set; } - [JsonProperty(PropertyName = "has_b_frames")] - public int HasBFrames { get; set; } + [JsonPropertyName("has_b_frames")] + public int HasBFrames { get; set; } - [JsonProperty(PropertyName = "sample_aspect_ratio")] - [JsonConverter(typeof(RatioConverter))] - public Ratio SampleAspectRatio { get; set; } + [JsonPropertyName("sample_aspect_ratio")] + [JsonConverter(typeof(RatioConverter))] + public Ratio SampleAspectRatio { get; set; } - [JsonProperty(PropertyName = "display_aspect_ratio")] - [JsonConverter(typeof(RatioConverter))] - public Ratio DisplayAspectRatio { get; set; } + [JsonPropertyName("display_aspect_ratio")] + [JsonConverter(typeof(RatioConverter))] + public Ratio DisplayAspectRatio { get; set; } - [JsonProperty(PropertyName = "pix_fmt")] - public string PixelFormat { get; set; } + [JsonPropertyName("pix_fmt")] + public string PixelFormat { get; set; } - [JsonProperty(PropertyName = "level")] - public int Level { get; set; } + [JsonPropertyName("level")] + public int Level { get; set; } - [JsonProperty(PropertyName = "r_frame_rate")] - [JsonConverter(typeof(FractionConverter))] - public Fraction RFrameRate { get; set; } + [JsonPropertyName("r_frame_rate")] + [JsonConverter(typeof(FractionConverter))] + public Fraction RFrameRate { get; set; } - [JsonProperty(PropertyName = "avg_frame_rate")] - [JsonConverter(typeof(FractionConverter))] - public Fraction AverageFrameRate { get; set; } + [JsonPropertyName("avg_frame_rate")] + [JsonConverter(typeof(FractionConverter))] + public Fraction AverageFrameRate { get; set; } - public VideoStreamMetadata Copy() - { - return (VideoStreamMetadata) MemberwiseClone(); - } + public VideoStreamMetadata Copy() + { + return (VideoStreamMetadata) MemberwiseClone(); } -} +} \ No newline at end of file diff --git a/Hudl.FFprobe/Serialization/Converters/FractionConverter.cs b/Hudl.FFprobe/Serialization/Converters/FractionConverter.cs index 11cfd87..4c12d4f 100644 --- a/Hudl.FFprobe/Serialization/Converters/FractionConverter.cs +++ b/Hudl.FFprobe/Serialization/Converters/FractionConverter.cs @@ -1,39 +1,24 @@ using System; +using System.Text.Json; +using System.Text.Json.Serialization; using Hudl.FFmpeg.DataTypes; -using Newtonsoft.Json; -namespace Hudl.FFprobe.Serialization.Converters +namespace Hudl.FFprobe.Serialization.Converters; + +internal class FractionConverter : JsonConverter { - internal class FractionConverter : JsonConverter + public override Fraction Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - public override bool CanConvert(Type objectType) + if (reader.TokenType != JsonTokenType.String) { - return objectType == typeof (string); + throw new Exception($"Unexpected token parsing Fraction, expected String, got {reader.TokenType}"); } - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - if (reader.TokenType != JsonToken.String) - { - throw new Exception(string.Format("Unexpected token parsing Fraction, expected String, got {0}", reader.TokenType)); - } - - Fraction fraction; - - Fraction.TryParse(reader.Value.ToString(), out fraction); + _ = Fraction.TryParse(reader.GetString()!, out var fraction); - return fraction; - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - - throw new NotImplementedException("Unnecessary because CanWrite is false. the type will skip when converted"); - } - - public override bool CanWrite - { - get { return false; } - } + return fraction; } -} + + public override void Write(Utf8JsonWriter writer, Fraction value, JsonSerializerOptions options) => + throw new NotImplementedException("Unnecessary because CanWrite is false. the type will skip when converted"); +} \ No newline at end of file diff --git a/Hudl.FFprobe/Serialization/Converters/FrameConverter.cs b/Hudl.FFprobe/Serialization/Converters/FrameConverter.cs index 2c6b22f..fe6f593 100644 --- a/Hudl.FFprobe/Serialization/Converters/FrameConverter.cs +++ b/Hudl.FFprobe/Serialization/Converters/FrameConverter.cs @@ -1,73 +1,31 @@ using System; using System.Collections.Generic; -using Hudl.FFmpeg.Metadata.FFprobe.BaseTypes; +using System.Linq; +using System.Text.Json; +using System.Text.Json.Serialization; using Hudl.FFprobe.Metadata.Models; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; -using Newtonsoft.Json.Linq; -namespace Hudl.FFprobe.Serialization.Converters +namespace Hudl.FFprobe.Serialization.Converters; + +internal class FrameConverter : JsonConverter> { - internal class FrameConverter : CustomCreationConverter> + public override List? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - public override List Create(Type objectType) - { - throw new NotImplementedException(); - } - - public BaseFrameMetadata Create(Type objectType, JObject jsonObject) - { - var codecType = (string)jsonObject.Property("media_type"); - if (string.Equals(codecType, CodecTypes.Video.ToString(), StringComparison.InvariantCultureIgnoreCase)) - { - return new VideoFrameMetadata(); - } - - if (string.Equals(codecType, CodecTypes.Audio.ToString(), StringComparison.InvariantCultureIgnoreCase)) - { - return new AudioFrameMetadata(); - } - - return null; - } - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - var jsonArray = JArray.Load(reader); - - var returnList = new List(); - - foreach (var jsonToken in jsonArray) - { - if (jsonToken.Type != JTokenType.Object) - { - throw new Exception(string.Format("Expected a token type of Object, got {0} instead", jsonToken.Type)); - } + var jsonArray = JsonSerializer.Deserialize(ref reader, options); - var targetObject = jsonToken.Value(); - var targetType = Create(objectType, targetObject); - if (targetType == null) + return (from jsonElement in jsonArray + let targetType = CodecTypesUtility.GetCodecTypeFromMediaType(jsonElement.GetProperty("media_type").GetString()) switch { - //unsupported type, dont wanna worry about it. - continue; + CodecTypes.Video => typeof(VideoFrameMetadata), + CodecTypes.Audio => typeof(AudioFrameMetadata), + _ => null, } - - serializer.Populate(targetObject.CreateReader(), targetType); - - returnList.Add(targetType); - } - - return returnList; - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - throw new NotImplementedException("Unnecessary because CanWrite is false. the type will skip when converted"); - } - - public override bool CanWrite - { - get { return false; } - } + select new { Type = targetType, Element = jsonElement }) + .Select(selected => JsonSerializer.Deserialize((string)selected.Element.GetRawText(), selected.Type, options)) + .Cast() + .ToList(); } -} + + public override void Write(Utf8JsonWriter writer, List value, JsonSerializerOptions options) => + throw new NotImplementedException("Unnecessary because CanWrite is false. the type will skip when converted"); +} \ No newline at end of file diff --git a/Hudl.FFprobe/Serialization/Converters/NumberStringConverter.cs b/Hudl.FFprobe/Serialization/Converters/NumberStringConverter.cs new file mode 100644 index 0000000..a0dfe12 --- /dev/null +++ b/Hudl.FFprobe/Serialization/Converters/NumberStringConverter.cs @@ -0,0 +1,25 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Hudl.FFmpeg.DataTypes; + +namespace Hudl.FFprobe.Serialization.Converters; + +internal class NumberStringConverter : JsonConverter +{ + public override bool CanConvert(Type typeToConvert) => typeof(string) == typeToConvert; + + public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return reader.TokenType switch + { + JsonTokenType.String => reader.GetString() ?? default, + JsonTokenType.Number => reader.TryGetInt64(out var value) ? value.ToString() : default, + _ => throw new Exception( + $"Unexpected token parsing String, expected {JsonTokenType.String} or {JsonTokenType.Number}, got {reader.TokenType}") + }; + } + + public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) => + throw new NotImplementedException("Unnecessary because CanWrite is false. the type will skip when converted"); +} \ No newline at end of file diff --git a/Hudl.FFprobe/Serialization/Converters/RatioConverter.cs b/Hudl.FFprobe/Serialization/Converters/RatioConverter.cs index 05af31a..edae16d 100644 --- a/Hudl.FFprobe/Serialization/Converters/RatioConverter.cs +++ b/Hudl.FFprobe/Serialization/Converters/RatioConverter.cs @@ -1,39 +1,23 @@ using System; +using System.Text.Json; using Hudl.FFmpeg.DataTypes; -using Newtonsoft.Json; +using System.Text.Json.Serialization; -namespace Hudl.FFprobe.Serialization.Converters +namespace Hudl.FFprobe.Serialization.Converters; + +internal class RatioConverter : JsonConverter { - internal class RatioConverter : JsonConverter + public override Ratio? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - public override bool CanConvert(Type objectType) - { - return objectType == typeof(string); - } - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + if (reader.TokenType != JsonTokenType.String) { - if (reader.TokenType != JsonToken.String) - { - throw new Exception(string.Format("Unexpected token parsing Ratio, expected String, got {0}", reader.TokenType)); - } - - Ratio ratio; - - Ratio.TryParse(reader.Value.ToString(), out ratio); - - return ratio; + throw new Exception($"Unexpected token parsing Ratio, expected {JsonTokenType.String}, got {reader.TokenType}"); } - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - - throw new NotImplementedException("Unnecessary because CanWrite is false. the type will skip when converted"); - } + _ = Ratio.TryParse(reader.GetString()!, out var ratio); - public override bool CanWrite - { - get { return false; } - } + return ratio; } -} + public override void Write(Utf8JsonWriter writer, Ratio value, JsonSerializerOptions options) => + throw new NotImplementedException("Unnecessary because CanWrite is false. the type will skip when converted"); +} \ No newline at end of file diff --git a/Hudl.FFprobe/Serialization/Converters/StreamConverter.cs b/Hudl.FFprobe/Serialization/Converters/StreamConverter.cs index 42003f4..aaa4b30 100644 --- a/Hudl.FFprobe/Serialization/Converters/StreamConverter.cs +++ b/Hudl.FFprobe/Serialization/Converters/StreamConverter.cs @@ -1,78 +1,32 @@ using System; using System.Collections.Generic; -using Hudl.FFmpeg.Metadata.FFprobe.BaseTypes; +using System.Linq; +using System.Text.Json; +using System.Text.Json.Serialization; using Hudl.FFprobe.Metadata.Models; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; -using Newtonsoft.Json.Linq; -namespace Hudl.FFprobe.Serialization.Converters +namespace Hudl.FFprobe.Serialization.Converters; + +internal class StreamConverter : JsonConverter> { - internal class StreamConverter : CustomCreationConverter> + public override List Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - public override List Create(Type objectType) - { - throw new NotImplementedException(); - } - - public BaseStreamMetadata Create(Type objectType, JObject jsonObject) - { - var codecType = (string)jsonObject.Property("codec_type"); - if (string.Equals(codecType, CodecTypes.Video.ToString(), StringComparison.InvariantCultureIgnoreCase)) - { - return new VideoStreamMetadata(); - } - - if (string.Equals(codecType, CodecTypes.Audio.ToString(), StringComparison.InvariantCultureIgnoreCase)) - { - return new AudioStreamMetadata(); - } - - if (string.Equals(codecType, CodecTypes.Data.ToString(), StringComparison.InvariantCultureIgnoreCase)) - { - return new DataStreamMetadata(); - } - - return null; - } + var jsonArray = JsonSerializer.Deserialize(ref reader, options); - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - var jsonArray = JArray.Load(reader); - - var returnList = new List(); - - foreach (var jsonToken in jsonArray) - { - if (jsonToken.Type != JTokenType.Object) + return (from jsonElement in jsonArray + let targetType = CodecTypesUtility.GetCodecTypeFromMediaType(jsonElement.GetProperty("codec_type").GetString()) switch { - throw new Exception(string.Format("Expected a token type of Object, got {0} instead", jsonToken.Type)); + CodecTypes.Video => typeof(VideoStreamMetadata), + CodecTypes.Audio => typeof(AudioStreamMetadata), + CodecTypes.Data => typeof(DataStreamMetadata), + _ => null, } - - var targetObject = jsonToken.Value(); - var targetType = Create(objectType, targetObject); - if (targetType == null) - { - //unsupported type, dont wanna worry about it. - continue; - } - - serializer.Populate(targetObject.CreateReader(), targetType); - - returnList.Add(targetType); - } - - return returnList; - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - throw new NotImplementedException("Unnecessary because CanWrite is false. the type will skip when converted"); - } - - public override bool CanWrite - { - get { return false; } - } + select new { Type = targetType, Element = jsonElement }) + .Select(selected => JsonSerializer.Deserialize((string)selected.Element.GetRawText(), selected.Type, options)) + .Cast() + .ToList(); } -} + + public override void Write(Utf8JsonWriter writer, List value, JsonSerializerOptions options) => + throw new NotImplementedException("Unnecessary because CanWrite is false. the type will skip when converted"); +} \ No newline at end of file diff --git a/Hudl.FFprobe/Serialization/Converters/StringNumberConverter.cs b/Hudl.FFprobe/Serialization/Converters/StringNumberConverter.cs new file mode 100644 index 0000000..ba79375 --- /dev/null +++ b/Hudl.FFprobe/Serialization/Converters/StringNumberConverter.cs @@ -0,0 +1,49 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Hudl.FFmpeg.DataTypes; + +namespace Hudl.FFprobe.Serialization.Converters; + + +internal abstract class BaseStringNumberConverter : JsonConverter +{ + protected abstract TNumberType? GetNumberValue(ref Utf8JsonReader reader); + protected abstract TNumberType? GetNumberValueFromString(ref Utf8JsonReader reader); + + public override bool CanConvert(Type typeToConvert) => typeof(TNumberType) == typeToConvert; + + public override TNumberType? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return reader.TokenType switch + { + JsonTokenType.String => GetNumberValueFromString(ref reader) ?? default, + JsonTokenType.Number => GetNumberValue(ref reader), + _ => throw new Exception( + $"Unexpected token parsing Number, expected {JsonTokenType.String} or {JsonTokenType.Number}, got {reader.TokenType}") + }; + } + + public override void Write(Utf8JsonWriter writer, TNumberType value, JsonSerializerOptions options) => + throw new NotImplementedException("Unnecessary because CanWrite is false. the type will skip when converted"); +} + +internal class ShortNumberConverter : BaseStringNumberConverter +{ + private const short DefaultShort = 0; + + protected override short GetNumberValue(ref Utf8JsonReader reader) => reader.TryGetInt16(out short value) ? value : DefaultShort; + protected override short GetNumberValueFromString(ref Utf8JsonReader reader) => (short.TryParse(reader.GetString(), out var result) ? result : DefaultShort); +} + +internal class IntNumberConverter : BaseStringNumberConverter +{ + protected override int GetNumberValue(ref Utf8JsonReader reader) => reader.TryGetInt32(out int value) ? value : 0; + protected override int GetNumberValueFromString(ref Utf8JsonReader reader) => (int.TryParse(reader.GetString(), out var result) ? result : 0); +} + +internal class LongNumberConverter : BaseStringNumberConverter +{ + protected override long GetNumberValue(ref Utf8JsonReader reader) => reader.TryGetInt64(out long value) ? value : 0L; + protected override long GetNumberValueFromString(ref Utf8JsonReader reader) => (long.TryParse(reader.GetString(), out var result) ? result : 0L); +} \ No newline at end of file diff --git a/Hudl.FFprobe/Serialization/Converters/TimeSpanConverter.cs b/Hudl.FFprobe/Serialization/Converters/TimeSpanConverter.cs index d1fcc8b..5094f84 100644 --- a/Hudl.FFprobe/Serialization/Converters/TimeSpanConverter.cs +++ b/Hudl.FFprobe/Serialization/Converters/TimeSpanConverter.cs @@ -1,39 +1,24 @@ using System; using System.Globalization; -using Newtonsoft.Json; +using System.Text.Json; +using System.Text.Json.Serialization; -namespace Hudl.FFprobe.Serialization.Converters +namespace Hudl.FFprobe.Serialization.Converters; + +internal class TimeSpanConverter : JsonConverter { - internal class TimeSpanConverter : JsonConverter + public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - public override bool CanConvert(Type objectType) + if (reader.TokenType != JsonTokenType.String) { - return objectType == typeof(string); + throw new Exception($"Unexpected token parsing Ratio, expected {JsonTokenType.String}, got {reader.TokenType}"); } - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - if (reader.TokenType != JsonToken.String) - { - throw new Exception(string.Format("Unexpected token parsing Ratio, expected String, got {0}", reader.TokenType)); - } - - double timespan; - - double.TryParse(reader.Value.ToString(), NumberStyles.Number, CultureInfo.InvariantCulture, out timespan); + _ = double.TryParse(reader.GetString(), NumberStyles.Number, CultureInfo.InvariantCulture, out var timespan); - return TimeSpan.FromSeconds(timespan); - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - - throw new NotImplementedException("Unnecessary because CanWrite is false. the type will skip when converted"); - } - - public override bool CanWrite - { - get { return false; } - } + return TimeSpan.FromSeconds(timespan); } -} + + public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options) => + throw new NotImplementedException("Unnecessary because CanWrite is false. the type will skip when converted"); +} \ No newline at end of file diff --git a/Hudl.FFprobe/Serialization/FFprobeSerialzier.cs b/Hudl.FFprobe/Serialization/FFprobeSerialzier.cs index 3c7ab7d..239ca5d 100644 --- a/Hudl.FFprobe/Serialization/FFprobeSerialzier.cs +++ b/Hudl.FFprobe/Serialization/FFprobeSerialzier.cs @@ -1,22 +1,36 @@ -using Hudl.FFmpeg.Command; +using System.Text.Json; +using Hudl.FFmpeg.Command; using Hudl.FFmpeg.Command.BaseTypes; using Hudl.FFprobe.Metadata.Models; -using Newtonsoft.Json; +using Hudl.FFprobe.Serialization.Converters; -namespace Hudl.FFprobe.Serialization +namespace Hudl.FFprobe.Serialization; + +public class FFprobeSerializer { - public class FFprobeSerializer + private static FFprobeSerializer? _instance = null; + private readonly JsonSerializerOptions _jsonSerializerOptions; + + private FFprobeSerializer() + { + _jsonSerializerOptions = new JsonSerializerOptions(); + _jsonSerializerOptions.Converters.Add(new ShortNumberConverter()); + _jsonSerializerOptions.Converters.Add(new IntNumberConverter()); + _jsonSerializerOptions.Converters.Add(new LongNumberConverter()); + _jsonSerializerOptions.Converters.Add(new NumberStringConverter()); + } + + public static FFprobeSerializer Instance => _instance ??= new FFprobeSerializer(); + public ContainerMetadata? Serialize(ICommandProcessor processor) { - public static ContainerMetadata Serialize(ICommandProcessor processor) + if (processor.Status == CommandProcessorStatus.Faulted) { - if (processor.Status == CommandProcessorStatus.Faulted) - { - return null; - } + return null; + } - var standardOutputString = processor.StdOut; + var standardOutputString = processor.StdOut; - return JsonConvert.DeserializeObject(standardOutputString); - } + + return JsonSerializer.Deserialize(standardOutputString, _jsonSerializerOptions); } -} +} \ No newline at end of file diff --git a/Hudl.FFprobe/Settings/PrintFormat.cs b/Hudl.FFprobe/Settings/PrintFormat.cs index e03da5b..8dd1f92 100644 --- a/Hudl.FFprobe/Settings/PrintFormat.cs +++ b/Hudl.FFprobe/Settings/PrintFormat.cs @@ -1,19 +1,18 @@ using Hudl.FFmpeg.Settings.Attributes; using Hudl.FFmpeg.Settings.Interfaces; -namespace Hudl.FFprobe.Settings -{ - [Setting(Name = "print_format")] - public class PrintFormat : ISetting - { - public const string JsonFormat = "json"; +namespace Hudl.FFprobe.Settings; - public PrintFormat(string format) - { - Format = format; - } +[Setting(Name = "print_format")] +public class PrintFormat : ISetting +{ + public const string JsonFormat = "json"; - [SettingParameter] - public string Format { get; set; } + public PrintFormat(string format) + { + Format = format; } -} + + [SettingParameter] + public string Format { get; set; } +} \ No newline at end of file diff --git a/Hudl.FFprobe/Settings/ReadIntervals.cs b/Hudl.FFprobe/Settings/ReadIntervals.cs index 050191c..0296a95 100644 --- a/Hudl.FFprobe/Settings/ReadIntervals.cs +++ b/Hudl.FFprobe/Settings/ReadIntervals.cs @@ -1,17 +1,16 @@ using Hudl.FFmpeg.Settings.Attributes; using Hudl.FFmpeg.Settings.Interfaces; -namespace Hudl.FFprobe.Settings +namespace Hudl.FFprobe.Settings; + +[Setting(Name = "read_intervals")] +public class ReadIntervals : ISetting { - [Setting(Name = "read_intervals")] - public class ReadIntervals : ISetting + public ReadIntervals(string expression) { - public ReadIntervals(string expression) - { - Expression = expression; - } - - [SettingParameter] - public string Expression { get; set; } + Expression = expression; } -} + + [SettingParameter] + public string Expression { get; set; } +} \ No newline at end of file diff --git a/Hudl.FFprobe/Settings/ShowFormat.cs b/Hudl.FFprobe/Settings/ShowFormat.cs index a4dc0f7..d5ff351 100644 --- a/Hudl.FFprobe/Settings/ShowFormat.cs +++ b/Hudl.FFprobe/Settings/ShowFormat.cs @@ -1,10 +1,9 @@ using Hudl.FFmpeg.Settings.Attributes; using Hudl.FFmpeg.Settings.Interfaces; -namespace Hudl.FFprobe.Settings +namespace Hudl.FFprobe.Settings; + +[Setting(Name = "show_format", IsParameterless = true)] +public class ShowFormat : ISetting { - [Setting(Name = "show_format", IsParameterless = true)] - public class ShowFormat : ISetting - { - } -} +} \ No newline at end of file diff --git a/Hudl.FFprobe/Settings/ShowFrames.cs b/Hudl.FFprobe/Settings/ShowFrames.cs index 1d00d02..73dead8 100644 --- a/Hudl.FFprobe/Settings/ShowFrames.cs +++ b/Hudl.FFprobe/Settings/ShowFrames.cs @@ -1,10 +1,9 @@ using Hudl.FFmpeg.Settings.Attributes; using Hudl.FFmpeg.Settings.Interfaces; -namespace Hudl.FFprobe.Settings +namespace Hudl.FFprobe.Settings; + +[Setting(Name = "show_frames", IsParameterless = true)] +public class ShowFrames : ISetting { - [Setting(Name = "show_frames", IsParameterless = true)] - public class ShowFrames : ISetting - { - } -} +} \ No newline at end of file diff --git a/Hudl.FFprobe/Settings/ShowStreams.cs b/Hudl.FFprobe/Settings/ShowStreams.cs index bd0d57c..405fd5d 100644 --- a/Hudl.FFprobe/Settings/ShowStreams.cs +++ b/Hudl.FFprobe/Settings/ShowStreams.cs @@ -1,10 +1,9 @@ using Hudl.FFmpeg.Settings.Attributes; using Hudl.FFmpeg.Settings.Interfaces; -namespace Hudl.FFprobe.Settings +namespace Hudl.FFprobe.Settings; + +[Setting(Name = "show_streams", IsParameterless = true)] +public class ShowStreams : ISetting { - [Setting(Name = "show_streams", IsParameterless = true)] - public class ShowStreams : ISetting - { - } -} +} \ No newline at end of file diff --git a/Hudl.Ffmpeg.Tests/Assets/Utilities.cs b/Hudl.Ffmpeg.Tests/Assets/Utilities.cs index 2d30423..2f2c1c4 100644 --- a/Hudl.Ffmpeg.Tests/Assets/Utilities.cs +++ b/Hudl.Ffmpeg.Tests/Assets/Utilities.cs @@ -1,34 +1,36 @@ using System.IO; +using System.Runtime.InteropServices; using Hudl.FFmpeg.Command; -namespace Hudl.FFmpeg.Tests.Assets +namespace Hudl.FFmpeg.Tests.Assets; + +public static class Utilities { - public class Utilities + private static string GetAssetsDirectory() + { + return (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + ? Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), @"..\..\..\..\samples\assets")) + : Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), @"../../../../Samples/Assets")); + } + public static string GetAudioFile() + { + return Path.Combine(GetAssetsDirectory(), "sample-audio.m4a"); + } + public static string GetVideoFile() { - public static string GetAssetsDirectory() - { - return Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), @"..\..\..\..\samples\assets")); - } - public static string GetAudioFile() - { - return Path.Combine(GetAssetsDirectory(), "sample-audio.m4a"); - } - public static string GetVideoFile() - { - return Path.Combine(GetAssetsDirectory(), "sample-video.mp4"); - } - public static string GetImageFile() - { - return Path.Combine(GetAssetsDirectory(), "sample-image.jpg"); - } + return Path.Combine(GetAssetsDirectory(), "sample-video.mp4"); + } + public static string GetImageFile() + { + return Path.Combine(GetAssetsDirectory(), "sample-image.jpg"); + } - public static void SetGlobalAssets() - { - const string outputPath = "c:/source/ffmpeg/bin/temp"; - const string ffmpegPath = "c:/source/ffmpeg/bin/ffmpeg.exe"; - const string ffprobePath = "c:/source/ffmpeg/bin/ffprobe.exe"; + public static void SetGlobalAssets() + { + var outputPath = Path.GetTempPath(); + var ffmpegPath = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? "ffmpeg.exe" : "ffmpeg"; + var ffprobePath = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? "ffprobe.exe" : "ffprobe"; - ResourceManagement.CommandConfiguration = CommandConfiguration.Create(outputPath, ffmpegPath, ffprobePath); - } + ResourceManagement.CommandConfiguration = CommandConfiguration.Create(outputPath, ffmpegPath, ffprobePath); } -} +} \ No newline at end of file diff --git a/Hudl.Ffmpeg.Tests/Hudl.Ffmpeg.Tests.csproj b/Hudl.Ffmpeg.Tests/Hudl.Ffmpeg.Tests.csproj index 214b06d..742d4a7 100644 --- a/Hudl.Ffmpeg.Tests/Hudl.Ffmpeg.Tests.csproj +++ b/Hudl.Ffmpeg.Tests/Hudl.Ffmpeg.Tests.csproj @@ -1,9 +1,11 @@ - netcoreapp2.1 + net8.0 false + + 12 diff --git a/Hudl.Ffmpeg.Tests/Render/RenderTests.cs b/Hudl.Ffmpeg.Tests/Render/RenderTests.cs index c1eae4f..4761c2f 100644 --- a/Hudl.Ffmpeg.Tests/Render/RenderTests.cs +++ b/Hudl.Ffmpeg.Tests/Render/RenderTests.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using System.Runtime.InteropServices; using Hudl.FFmpeg.Enums; using Hudl.FFmpeg.Filters.Templates; @@ -18,10 +19,9 @@ public class RenderTests public void RenderVideoWEffects() { #if DEBUG - ResourceManagement.CommandConfiguration = CommandConfiguration.Create( - "c:/source/ffmpeg/bin/temp", - "c:/source/ffmpeg/bin/ffmpeg.exe", - "c:/source/ffmpeg/bin/FFprobe.exe"); + Assets.Utilities.SetGlobalAssets(); + + var temporaryDirectory = Path.GetTempPath(); var outputSettings = SettingsCollection.ForOutput( new OverwriteOutput(), @@ -36,7 +36,7 @@ public void RenderVideoWEffects() .WithInput(Assets.Utilities.GetVideoFile()) .WithInput(Assets.Utilities.GetVideoFile()) .Filter(new Dissolve(1)) - .MapTo("c:/source/ffmpeg/bin/temp/output-test.mp4", outputSettings); + .MapTo(Path.Combine(temporaryDirectory, "output-test.mp4"), outputSettings); factory.Render(); #endif diff --git a/Hudl.Ffmpeg.Tests/packages.config b/Hudl.Ffmpeg.Tests/packages.config deleted file mode 100644 index dd3357d..0000000 --- a/Hudl.Ffmpeg.Tests/packages.config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/Samples/Hudl.FFmpeg.Samples/Hudl.FFmpeg.Samples.csproj b/Samples/Hudl.FFmpeg.Samples/Hudl.FFmpeg.Samples.csproj index b83fbc2..4cb4ca9 100644 --- a/Samples/Hudl.FFmpeg.Samples/Hudl.FFmpeg.Samples.csproj +++ b/Samples/Hudl.FFmpeg.Samples/Hudl.FFmpeg.Samples.csproj @@ -1,7 +1,8 @@ - netstandard2.0 + net8.0 + 12 From e96ad09b63a8af849568609e7c7fdf7c1dd5ef15 Mon Sep 17 00:00:00 2001 From: Casey Bateman Date: Tue, 11 Feb 2025 09:46:06 -0600 Subject: [PATCH 2/5] fix: revert to netstandard2.0 --- Hudl.FFmpeg.Core/Hudl.FFmpeg.Core.csproj | 2 +- Hudl.FFmpeg/Hudl.Ffmpeg.csproj | 3 ++- Hudl.FFmpeg/Hudl.Ffmpeg.nuspec | 12 ++++++------ Hudl.FFprobe/Hudl.FFprobe.csproj | 4 +++- Hudl.Ffmpeg.Tests/Hudl.Ffmpeg.Tests.csproj | 2 +- .../Hudl.FFmpeg.Samples/Hudl.FFmpeg.Samples.csproj | 2 +- 6 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Hudl.FFmpeg.Core/Hudl.FFmpeg.Core.csproj b/Hudl.FFmpeg.Core/Hudl.FFmpeg.Core.csproj index daf35b2..335fe0b 100644 --- a/Hudl.FFmpeg.Core/Hudl.FFmpeg.Core.csproj +++ b/Hudl.FFmpeg.Core/Hudl.FFmpeg.Core.csproj @@ -5,7 +5,7 @@ 8.0.0 2.0.0.0 - net8.0 + netstandard2.0 full Hudl.FFmpeg.Core Hudl.FFmpeg.Core diff --git a/Hudl.FFmpeg/Hudl.Ffmpeg.csproj b/Hudl.FFmpeg/Hudl.Ffmpeg.csproj index f688730..defe170 100644 --- a/Hudl.FFmpeg/Hudl.Ffmpeg.csproj +++ b/Hudl.FFmpeg/Hudl.Ffmpeg.csproj @@ -5,7 +5,7 @@ 8.0.0 2.0.0.0 - net8.0 + netstandard2.0 full Hudl.FFmpeg Hudl.FFmpeg @@ -24,6 +24,7 @@ + diff --git a/Hudl.FFmpeg/Hudl.Ffmpeg.nuspec b/Hudl.FFmpeg/Hudl.Ffmpeg.nuspec index 4a2fb42..c1dd9bc 100644 --- a/Hudl.FFmpeg/Hudl.Ffmpeg.nuspec +++ b/Hudl.FFmpeg/Hudl.Ffmpeg.nuspec @@ -10,11 +10,11 @@ https://raw.githubusercontent.com/hudl/HudlFfmpeg/master/hudl.png - - - - - - + + + + + + \ No newline at end of file diff --git a/Hudl.FFprobe/Hudl.FFprobe.csproj b/Hudl.FFprobe/Hudl.FFprobe.csproj index a91dfd3..2eff68f 100644 --- a/Hudl.FFprobe/Hudl.FFprobe.csproj +++ b/Hudl.FFprobe/Hudl.FFprobe.csproj @@ -5,7 +5,7 @@ 8.0.0 2.0.0.0 - net8.0 + netstandard2.0 full Hudl.FFprobe Hudl.FFprobe @@ -19,10 +19,12 @@ false false enable + 12 + diff --git a/Hudl.Ffmpeg.Tests/Hudl.Ffmpeg.Tests.csproj b/Hudl.Ffmpeg.Tests/Hudl.Ffmpeg.Tests.csproj index 742d4a7..7cab897 100644 --- a/Hudl.Ffmpeg.Tests/Hudl.Ffmpeg.Tests.csproj +++ b/Hudl.Ffmpeg.Tests/Hudl.Ffmpeg.Tests.csproj @@ -1,7 +1,7 @@ - net8.0 + netstandard2.0 false diff --git a/Samples/Hudl.FFmpeg.Samples/Hudl.FFmpeg.Samples.csproj b/Samples/Hudl.FFmpeg.Samples/Hudl.FFmpeg.Samples.csproj index 4cb4ca9..695a78f 100644 --- a/Samples/Hudl.FFmpeg.Samples/Hudl.FFmpeg.Samples.csproj +++ b/Samples/Hudl.FFmpeg.Samples/Hudl.FFmpeg.Samples.csproj @@ -1,7 +1,7 @@ - net8.0 + netstandard2.0 12 From 9110dad0ce0e25b2d6e5ae73ff2dfcf6aa684345 Mon Sep 17 00:00:00 2001 From: Casey Bateman Date: Tue, 11 Feb 2025 09:51:16 -0600 Subject: [PATCH 3/5] fix: update xunit visual studio runner package --- Hudl.Ffmpeg.Tests/Hudl.Ffmpeg.Tests.csproj | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Hudl.Ffmpeg.Tests/Hudl.Ffmpeg.Tests.csproj b/Hudl.Ffmpeg.Tests/Hudl.Ffmpeg.Tests.csproj index 7cab897..0b4f855 100644 --- a/Hudl.Ffmpeg.Tests/Hudl.Ffmpeg.Tests.csproj +++ b/Hudl.Ffmpeg.Tests/Hudl.Ffmpeg.Tests.csproj @@ -9,9 +9,12 @@ - - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + From 718f385f84d2f40fb3d8e65acd6365f58e63a5a6 Mon Sep 17 00:00:00 2001 From: Casey Bateman Date: Tue, 11 Feb 2025 09:55:27 -0600 Subject: [PATCH 4/5] fix: downgrade to cslangversion 10 for CI/CD --- Hudl.FFmpeg.Core/Hudl.FFmpeg.Core.csproj | 2 +- Hudl.FFmpeg/Hudl.Ffmpeg.csproj | 2 +- Hudl.FFprobe/Hudl.FFprobe.csproj | 2 +- Hudl.FFprobe/Metadata/Models/BaseFrameMetadata.cs | 2 +- Hudl.FFprobe/Metadata/Models/BaseStreamMetadata.cs | 2 +- Hudl.Ffmpeg.Tests/Hudl.Ffmpeg.Tests.csproj | 2 +- Samples/Hudl.FFmpeg.Samples/Hudl.FFmpeg.Samples.csproj | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Hudl.FFmpeg.Core/Hudl.FFmpeg.Core.csproj b/Hudl.FFmpeg.Core/Hudl.FFmpeg.Core.csproj index 335fe0b..7ab05ae 100644 --- a/Hudl.FFmpeg.Core/Hudl.FFmpeg.Core.csproj +++ b/Hudl.FFmpeg.Core/Hudl.FFmpeg.Core.csproj @@ -18,7 +18,7 @@ false false false - 12 + 10 enable diff --git a/Hudl.FFmpeg/Hudl.Ffmpeg.csproj b/Hudl.FFmpeg/Hudl.Ffmpeg.csproj index defe170..4701a62 100644 --- a/Hudl.FFmpeg/Hudl.Ffmpeg.csproj +++ b/Hudl.FFmpeg/Hudl.Ffmpeg.csproj @@ -18,7 +18,7 @@ false false false - 12 + 10 enable diff --git a/Hudl.FFprobe/Hudl.FFprobe.csproj b/Hudl.FFprobe/Hudl.FFprobe.csproj index 2eff68f..d5b1757 100644 --- a/Hudl.FFprobe/Hudl.FFprobe.csproj +++ b/Hudl.FFprobe/Hudl.FFprobe.csproj @@ -19,7 +19,7 @@ false false enable - 12 + 10 diff --git a/Hudl.FFprobe/Metadata/Models/BaseFrameMetadata.cs b/Hudl.FFprobe/Metadata/Models/BaseFrameMetadata.cs index ad35de4..f766a19 100644 --- a/Hudl.FFprobe/Metadata/Models/BaseFrameMetadata.cs +++ b/Hudl.FFprobe/Metadata/Models/BaseFrameMetadata.cs @@ -46,5 +46,5 @@ public class BaseFrameMetadata public TimeSpan BestEffortTimestampTime { get; set; } [JsonExtensionData] - public Dictionary AdditionalData { get; set; } = []; + public Dictionary AdditionalData { get; set; } = new(); } \ No newline at end of file diff --git a/Hudl.FFprobe/Metadata/Models/BaseStreamMetadata.cs b/Hudl.FFprobe/Metadata/Models/BaseStreamMetadata.cs index d0f7cd6..725bf0c 100644 --- a/Hudl.FFprobe/Metadata/Models/BaseStreamMetadata.cs +++ b/Hudl.FFprobe/Metadata/Models/BaseStreamMetadata.cs @@ -66,5 +66,5 @@ public class BaseStreamMetadata public Dictionary Tags { get; set; } [JsonExtensionData] - public Dictionary AdditionalData { get; set; } = []; + public Dictionary AdditionalData { get; set; } = new(); } \ No newline at end of file diff --git a/Hudl.Ffmpeg.Tests/Hudl.Ffmpeg.Tests.csproj b/Hudl.Ffmpeg.Tests/Hudl.Ffmpeg.Tests.csproj index 0b4f855..e227c75 100644 --- a/Hudl.Ffmpeg.Tests/Hudl.Ffmpeg.Tests.csproj +++ b/Hudl.Ffmpeg.Tests/Hudl.Ffmpeg.Tests.csproj @@ -5,7 +5,7 @@ false - 12 + 10 diff --git a/Samples/Hudl.FFmpeg.Samples/Hudl.FFmpeg.Samples.csproj b/Samples/Hudl.FFmpeg.Samples/Hudl.FFmpeg.Samples.csproj index 695a78f..df709c9 100644 --- a/Samples/Hudl.FFmpeg.Samples/Hudl.FFmpeg.Samples.csproj +++ b/Samples/Hudl.FFmpeg.Samples/Hudl.FFmpeg.Samples.csproj @@ -2,7 +2,7 @@ netstandard2.0 - 12 + 10 From 9c60b236060b57e33d81b6bb8b5f741c72a0e6f8 Mon Sep 17 00:00:00 2001 From: Casey Bateman Date: Wed, 18 Jun 2025 15:55:59 -0500 Subject: [PATCH 5/5] fix: fix nuspec file casing --- Hudl.FFmpeg/{Hudl.Ffmpeg.nuspec => Hudl.FFmpeg.nuspec} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Hudl.FFmpeg/{Hudl.Ffmpeg.nuspec => Hudl.FFmpeg.nuspec} (100%) diff --git a/Hudl.FFmpeg/Hudl.Ffmpeg.nuspec b/Hudl.FFmpeg/Hudl.FFmpeg.nuspec similarity index 100% rename from Hudl.FFmpeg/Hudl.Ffmpeg.nuspec rename to Hudl.FFmpeg/Hudl.FFmpeg.nuspec