From 57e2585f52df1103fe1c7502503e074b50bdcbf8 Mon Sep 17 00:00:00 2001 From: alex6dj Date: Mon, 6 Sep 2021 23:08:36 -0400 Subject: [PATCH 1/2] Get extra disposition data in MediaStream Former-commit-id: 41ec1a10dd913bba9371b88500a7a78179546aa9 --- FFMpegCore.Test/FFProbeTests.cs | 9 +++++++++ FFMpegCore/FFProbe/FFProbeAnalysis.cs | 27 ++++++++++++++++++++++++--- FFMpegCore/FFProbe/MediaAnalysis.cs | 3 +++ FFMpegCore/FFProbe/MediaStream.cs | 3 ++- 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/FFMpegCore.Test/FFProbeTests.cs b/FFMpegCore.Test/FFProbeTests.cs index 7af92cd..91411d4 100644 --- a/FFMpegCore.Test/FFProbeTests.cs +++ b/FFMpegCore.Test/FFProbeTests.cs @@ -114,5 +114,14 @@ public async Task Probe_Success_Subtitle_Async() Assert.AreEqual(0, info.AudioStreams.Count); Assert.AreEqual(0, info.VideoStreams.Count); } + + [TestMethod, Timeout(10000)] + public async Task Probe_Success_Disposition_Async() + { + var info = await FFProbe.AnalyseAsync(TestResources.Mp4Video); + Assert.IsNotNull(info.PrimaryAudioStream); + Assert.AreEqual(1, info.PrimaryAudioStream.Disposition["default"]); + Assert.AreEqual(0, info.PrimaryAudioStream.Disposition["forced"]); + } } } \ No newline at end of file diff --git a/FFMpegCore/FFProbe/FFProbeAnalysis.cs b/FFMpegCore/FFProbe/FFProbeAnalysis.cs index 1997cc3..2177307 100644 --- a/FFMpegCore/FFProbe/FFProbeAnalysis.cs +++ b/FFMpegCore/FFProbe/FFProbeAnalysis.cs @@ -12,7 +12,7 @@ public class FFProbeAnalysis public Format Format { get; set; } = null!; } - public class FFProbeStream : ITagsContainer + public class FFProbeStream : ITagsContainer, IDispositionContainer { [JsonPropertyName("index")] public int Index { get; set; } @@ -71,9 +71,13 @@ public class FFProbeStream : ITagsContainer [JsonPropertyName("sample_rate")] public string SampleRate { get; set; } = null!; + [JsonPropertyName("disposition")] + public Dictionary Disposition { get; set; } = null!; + [JsonPropertyName("tags")] public Dictionary Tags { get; set; } = null!; } + public class Format : ITagsContainer { [JsonPropertyName("filename")] @@ -110,10 +114,16 @@ public class Format : ITagsContainer public Dictionary Tags { get; set; } = null!; } + public interface IDispositionContainer + { + Dictionary Disposition { get; set; } + } + public interface ITagsContainer { Dictionary Tags { get; set; } } + public static class TagExtensions { private static string? TryGetTagValue(ITagsContainer tagsContainer, string key) @@ -127,7 +137,18 @@ public static class TagExtensions public static string? GetCreationTime(this ITagsContainer tagsContainer) => TryGetTagValue(tagsContainer, "creation_time "); public static string? GetRotate(this ITagsContainer tagsContainer) => TryGetTagValue(tagsContainer, "rotate"); public static string? GetDuration(this ITagsContainer tagsContainer) => TryGetTagValue(tagsContainer, "duration"); - - + } + + public static class DispositionExtensions + { + private static int? TryGetDispositionValue(IDispositionContainer dispositionContainer, string key) + { + if (dispositionContainer.Disposition != null && dispositionContainer.Disposition.TryGetValue(key, out var dispositionValue)) + return dispositionValue; + return null; + } + + public static int? GetDefault(this IDispositionContainer tagsContainer) => TryGetDispositionValue(tagsContainer, "default"); + public static int? GetForced(this IDispositionContainer tagsContainer) => TryGetDispositionValue(tagsContainer, "forced"); } } diff --git a/FFMpegCore/FFProbe/MediaAnalysis.cs b/FFMpegCore/FFProbe/MediaAnalysis.cs index aea714c..174eb7e 100644 --- a/FFMpegCore/FFProbe/MediaAnalysis.cs +++ b/FFMpegCore/FFProbe/MediaAnalysis.cs @@ -67,6 +67,7 @@ private VideoStream ParseVideoStream(FFProbeStream stream) PixelFormat = stream.PixelFormat, Rotation = (int)float.Parse(stream.GetRotate() ?? "0"), Language = stream.GetLanguage(), + Disposition = stream.Disposition, Tags = stream.Tags, }; } @@ -87,6 +88,7 @@ private AudioStream ParseAudioStream(FFProbeStream stream) SampleRateHz = !string.IsNullOrEmpty(stream.SampleRate) ? MediaAnalysisUtils.ParseIntInvariant(stream.SampleRate) : default, Profile = stream.Profile, Language = stream.GetLanguage(), + Disposition = stream.Disposition, Tags = stream.Tags, }; } @@ -101,6 +103,7 @@ private SubtitleStream ParseSubtitleStream(FFProbeStream stream) CodecLongName = stream.CodecLongName, Duration = MediaAnalysisUtils.ParseDuration(stream), Language = stream.GetLanguage(), + Disposition = stream.Disposition, Tags = stream.Tags, }; } diff --git a/FFMpegCore/FFProbe/MediaStream.cs b/FFMpegCore/FFProbe/MediaStream.cs index 22186c5..9681ac9 100644 --- a/FFMpegCore/FFProbe/MediaStream.cs +++ b/FFMpegCore/FFProbe/MediaStream.cs @@ -15,8 +15,9 @@ public class MediaStream public int BitRate { get; internal set; } public TimeSpan Duration { get; internal set; } public string? Language { get; internal set; } + public Dictionary? Disposition { get; internal set; } public Dictionary? Tags { get; internal set; } - + public Codec GetCodecInfo() => FFMpeg.GetCodec(CodecName); } } \ No newline at end of file From 2b6a74dd7e09f0b8f88b49bde9914f65ef008144 Mon Sep 17 00:00:00 2001 From: alex6dj Date: Tue, 7 Sep 2021 12:48:05 -0400 Subject: [PATCH 2/2] Use boolean instead on generic int for disposition state value Former-commit-id: d79bbaef97f7bc4b043a4b4266db5d4d395b5852 --- FFMpegCore.Test/FFProbeTests.cs | 5 +++-- FFMpegCore/FFProbe/MediaAnalysis.cs | 31 ++++++++++++++++++++++++++--- FFMpegCore/FFProbe/MediaStream.cs | 2 +- 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/FFMpegCore.Test/FFProbeTests.cs b/FFMpegCore.Test/FFProbeTests.cs index 91411d4..aaadd4c 100644 --- a/FFMpegCore.Test/FFProbeTests.cs +++ b/FFMpegCore.Test/FFProbeTests.cs @@ -120,8 +120,9 @@ public async Task Probe_Success_Disposition_Async() { var info = await FFProbe.AnalyseAsync(TestResources.Mp4Video); Assert.IsNotNull(info.PrimaryAudioStream); - Assert.AreEqual(1, info.PrimaryAudioStream.Disposition["default"]); - Assert.AreEqual(0, info.PrimaryAudioStream.Disposition["forced"]); + Assert.IsNotNull(info.PrimaryAudioStream.Disposition); + Assert.AreEqual(true, info.PrimaryAudioStream.Disposition["default"]); + Assert.AreEqual(false, info.PrimaryAudioStream.Disposition["forced"]); } } } \ No newline at end of file diff --git a/FFMpegCore/FFProbe/MediaAnalysis.cs b/FFMpegCore/FFProbe/MediaAnalysis.cs index 174eb7e..f7338cc 100644 --- a/FFMpegCore/FFProbe/MediaAnalysis.cs +++ b/FFMpegCore/FFProbe/MediaAnalysis.cs @@ -67,7 +67,7 @@ private VideoStream ParseVideoStream(FFProbeStream stream) PixelFormat = stream.PixelFormat, Rotation = (int)float.Parse(stream.GetRotate() ?? "0"), Language = stream.GetLanguage(), - Disposition = stream.Disposition, + Disposition = MediaAnalysisUtils.FormatDisposition(stream.Disposition), Tags = stream.Tags, }; } @@ -88,7 +88,7 @@ private AudioStream ParseAudioStream(FFProbeStream stream) SampleRateHz = !string.IsNullOrEmpty(stream.SampleRate) ? MediaAnalysisUtils.ParseIntInvariant(stream.SampleRate) : default, Profile = stream.Profile, Language = stream.GetLanguage(), - Disposition = stream.Disposition, + Disposition = MediaAnalysisUtils.FormatDisposition(stream.Disposition), Tags = stream.Tags, }; } @@ -103,7 +103,7 @@ private SubtitleStream ParseSubtitleStream(FFProbeStream stream) CodecLongName = stream.CodecLongName, Duration = MediaAnalysisUtils.ParseDuration(stream), Language = stream.GetLanguage(), - Disposition = stream.Disposition, + Disposition = MediaAnalysisUtils.FormatDisposition(stream.Disposition), Tags = stream.Tags, }; } @@ -172,5 +172,30 @@ public static TimeSpan ParseDuration(FFProbeStream ffProbeStream) { return ParseDuration(ffProbeStream.Duration); } + + public static Dictionary? FormatDisposition(Dictionary? disposition) + { + if (disposition == null) + { + return null; + } + + var result = new Dictionary(disposition.Count); + + foreach (var pair in disposition) + { + result.Add(pair.Key, ToBool(pair.Value)); + } + + static bool ToBool(int value) => value switch + { + 0 => false, + 1 => true, + _ => throw new ArgumentOutOfRangeException(nameof(value), + $"Not expected disposition state value: {value}") + }; + + return result; + } } } \ No newline at end of file diff --git a/FFMpegCore/FFProbe/MediaStream.cs b/FFMpegCore/FFProbe/MediaStream.cs index 9681ac9..7d6ad20 100644 --- a/FFMpegCore/FFProbe/MediaStream.cs +++ b/FFMpegCore/FFProbe/MediaStream.cs @@ -15,7 +15,7 @@ public class MediaStream public int BitRate { get; internal set; } public TimeSpan Duration { get; internal set; } public string? Language { get; internal set; } - public Dictionary? Disposition { get; internal set; } + public Dictionary? Disposition { get; internal set; } public Dictionary? Tags { get; internal set; } public Codec GetCodecInfo() => FFMpeg.GetCodec(CodecName);