diff --git a/FFMpegCore.Test/FFMpegCore.Test.csproj b/FFMpegCore.Test/FFMpegCore.Test.csproj
index 5a0c11b..8b99510 100644
--- a/FFMpegCore.Test/FFMpegCore.Test.csproj
+++ b/FFMpegCore.Test/FFMpegCore.Test.csproj
@@ -27,6 +27,12 @@
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
PreserveNewest
@@ -81,6 +87,15 @@
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
diff --git a/FFMpegCore.Test/FFProbeTests.cs b/FFMpegCore.Test/FFProbeTests.cs
index 87e883c..01fb217 100644
--- a/FFMpegCore.Test/FFProbeTests.cs
+++ b/FFMpegCore.Test/FFProbeTests.cs
@@ -145,6 +145,9 @@ public async Task Probe_Async_Success()
{
var info = await FFProbe.AnalyseAsync(TestResources.Mp4Video);
Assert.AreEqual(3, info.Duration.Seconds);
+ Assert.AreEqual(8, info.PrimaryVideoStream.BitDepth);
+ // This video's audio stream is AAC, which is lossy, so bit depth is meaningless.
+ Assert.IsNull(info.PrimaryAudioStream.BitDepth);
}
[TestMethod, Timeout(10000)]
@@ -153,6 +156,8 @@ public void Probe_Success_FromStream()
using var stream = File.OpenRead(TestResources.WebmVideo);
var info = FFProbe.Analyse(stream);
Assert.AreEqual(3, info.Duration.Seconds);
+ // This video has no audio stream.
+ Assert.IsNull(info.PrimaryAudioStream);
}
[TestMethod, Timeout(10000)]
@@ -171,16 +176,60 @@ public async Task Probe_Success_Subtitle_Async()
Assert.AreEqual(1, info.SubtitleStreams.Count);
Assert.AreEqual(0, info.AudioStreams.Count);
Assert.AreEqual(0, info.VideoStreams.Count);
+ // BitDepth is meaningless for subtitles
+ Assert.IsNull(info.SubtitleStreams[0].BitDepth);
}
[TestMethod, Timeout(10000)]
public async Task Probe_Success_Disposition_Async()
{
- var info = await FFProbe.AnalyseAsync(TestResources.Mp4Video);
- Assert.IsNotNull(info.PrimaryAudioStream);
- Assert.IsNotNull(info.PrimaryAudioStream.Disposition);
- Assert.AreEqual(true, info.PrimaryAudioStream.Disposition["default"]);
- Assert.AreEqual(false, info.PrimaryAudioStream.Disposition["forced"]);
+ var info = await FFProbe.AnalyseAsync(TestResources.Mp4Video);
+ Assert.IsNotNull(info.PrimaryAudioStream);
+ Assert.IsNotNull(info.PrimaryAudioStream.Disposition);
+ Assert.AreEqual(true, info.PrimaryAudioStream.Disposition["default"]);
+ Assert.AreEqual(false, info.PrimaryAudioStream.Disposition["forced"]);
+ }
+
+ [TestMethod, Timeout(10000)]
+ public async Task Probe_Success_Mp3AudioBitDepthNull_Async()
+ {
+ var info = await FFProbe.AnalyseAsync(TestResources.Mp3Audio);
+ Assert.IsNotNull(info.PrimaryAudioStream);
+ // mp3 is lossy, so bit depth is meaningless.
+ Assert.IsNull(info.PrimaryAudioStream.BitDepth);
+ }
+
+ [TestMethod, Timeout(10000)]
+ public async Task Probe_Success_VocAudioBitDepth_Async()
+ {
+ var info = await FFProbe.AnalyseAsync(TestResources.AiffAudio);
+ Assert.IsNotNull(info.PrimaryAudioStream);
+ Assert.AreEqual(16, info.PrimaryAudioStream.BitDepth);
+ }
+
+ [TestMethod, Timeout(10000)]
+ public async Task Probe_Success_MkvVideoBitDepth_Async()
+ {
+ var info = await FFProbe.AnalyseAsync(TestResources.MkvVideo);
+ Assert.IsNotNull(info.PrimaryAudioStream);
+ Assert.AreEqual(8, info.PrimaryVideoStream.BitDepth);
+ Assert.IsNull(info.PrimaryAudioStream.BitDepth);
+ }
+
+ [TestMethod, Timeout(10000)]
+ public async Task Probe_Success_24BitWavBitDepth_Async()
+ {
+ var info = await FFProbe.AnalyseAsync(TestResources.Wav24Bit);
+ Assert.IsNotNull(info.PrimaryAudioStream);
+ Assert.AreEqual(24, info.PrimaryAudioStream.BitDepth);
+ }
+
+ [TestMethod, Timeout(10000)]
+ public async Task Probe_Success_32BitWavBitDepth_Async()
+ {
+ var info = await FFProbe.AnalyseAsync(TestResources.Wav32Bit);
+ Assert.IsNotNull(info.PrimaryAudioStream);
+ Assert.AreEqual(32, info.PrimaryAudioStream.BitDepth);
}
}
}
\ No newline at end of file
diff --git a/FFMpegCore.Test/Resources/24_bit_fixed.WAV b/FFMpegCore.Test/Resources/24_bit_fixed.WAV
new file mode 100644
index 0000000..acd1265
Binary files /dev/null and b/FFMpegCore.Test/Resources/24_bit_fixed.WAV differ
diff --git a/FFMpegCore.Test/Resources/32_bit_float.WAV b/FFMpegCore.Test/Resources/32_bit_float.WAV
new file mode 100644
index 0000000..46bfa29
Binary files /dev/null and b/FFMpegCore.Test/Resources/32_bit_float.WAV differ
diff --git a/FFMpegCore.Test/Resources/TestResources.cs b/FFMpegCore.Test/Resources/TestResources.cs
index 14f8abe..bf29960 100644
--- a/FFMpegCore.Test/Resources/TestResources.cs
+++ b/FFMpegCore.Test/Resources/TestResources.cs
@@ -21,5 +21,9 @@ public static class TestResources
public static readonly string PngImage = "./Resources/cover.png";
public static readonly string ImageCollection = "./Resources/images";
public static readonly string SrtSubtitle = "./Resources/sample.srt";
+ public static readonly string AiffAudio = "./Resources/sample3aiff.aiff";
+ public static readonly string MkvVideo = "./Resources/sampleMKV.mkv";
+ public static readonly string Wav24Bit = "./Resources/24_bit_fixed.WAV";
+ public static readonly string Wav32Bit = "./Resources/32_bit_float.WAV";
}
}
diff --git a/FFMpegCore.Test/Resources/sample3aiff.aiff b/FFMpegCore.Test/Resources/sample3aiff.aiff
new file mode 100644
index 0000000..b9973ae
Binary files /dev/null and b/FFMpegCore.Test/Resources/sample3aiff.aiff differ
diff --git a/FFMpegCore.Test/Resources/sampleMKV.mkv b/FFMpegCore.Test/Resources/sampleMKV.mkv
new file mode 100644
index 0000000..5b162de
Binary files /dev/null and b/FFMpegCore.Test/Resources/sampleMKV.mkv differ
diff --git a/FFMpegCore/FFProbe/FFProbeAnalysis.cs b/FFMpegCore/FFProbe/FFProbeAnalysis.cs
index eb65bb2..596c55f 100644
--- a/FFMpegCore/FFProbe/FFProbeAnalysis.cs
+++ b/FFMpegCore/FFProbe/FFProbeAnalysis.cs
@@ -25,7 +25,10 @@ public class FFProbeStream : ITagsContainer, IDispositionContainer
[JsonPropertyName("bits_per_raw_sample")]
public string BitsPerRawSample { get; set; } = null!;
-
+
+ [JsonPropertyName("bits_per_sample")]
+ public int BitsPerSample { get; set; } = 0;
+
[JsonPropertyName("bit_rate")]
public string BitRate { get; set; } = null!;
diff --git a/FFMpegCore/FFProbe/MediaAnalysis.cs b/FFMpegCore/FFProbe/MediaAnalysis.cs
index bb68c22..4f29447 100644
--- a/FFMpegCore/FFProbe/MediaAnalysis.cs
+++ b/FFMpegCore/FFProbe/MediaAnalysis.cs
@@ -47,6 +47,13 @@ private MediaFormat ParseFormat(Format analysisFormat)
public List AudioStreams { get; }
public List SubtitleStreams { get; }
public IReadOnlyList ErrorData { get; }
+
+ private int? GetBitDepth(FFProbeStream stream)
+ {
+ var bitDepth = int.TryParse(stream.BitsPerRawSample, out var bprs) ? bprs :
+ stream.BitsPerSample;
+ return bitDepth == 0 ? null : (int?)bitDepth;
+ }
private VideoStream ParseVideoStream(FFProbeStream stream)
{
@@ -72,12 +79,13 @@ private VideoStream ParseVideoStream(FFProbeStream stream)
Language = stream.GetLanguage(),
Disposition = MediaAnalysisUtils.FormatDisposition(stream.Disposition),
Tags = stream.Tags.ToCaseInsensitive(),
+ BitDepth = GetBitDepth(stream),
};
}
private AudioStream ParseAudioStream(FFProbeStream stream)
{
- return new AudioStream
+ return new AudioStream
{
Index = stream.Index,
BitRate = !string.IsNullOrEmpty(stream.BitRate) ? MediaAnalysisUtils.ParseLongInvariant(stream.BitRate) : default,
@@ -93,6 +101,7 @@ private AudioStream ParseAudioStream(FFProbeStream stream)
Language = stream.GetLanguage(),
Disposition = MediaAnalysisUtils.FormatDisposition(stream.Disposition),
Tags = stream.Tags.ToCaseInsensitive(),
+ BitDepth = GetBitDepth(stream),
};
}
diff --git a/FFMpegCore/FFProbe/MediaStream.cs b/FFMpegCore/FFProbe/MediaStream.cs
index ffab04b..36ecf56 100644
--- a/FFMpegCore/FFProbe/MediaStream.cs
+++ b/FFMpegCore/FFProbe/MediaStream.cs
@@ -17,6 +17,7 @@ public abstract class MediaStream
public string? Language { get; set; }
public Dictionary? Disposition { get; set; }
public Dictionary? Tags { get; set; }
+ public int? BitDepth { get; set; }
public Codec GetCodecInfo() => FFMpeg.GetCodec(CodecName);
}