mirror of
https://github.com/rosenbjerg/FFMpegCore.git
synced 2024-11-10 00:24:14 +01:00
Added ability to retrieve bit depth from media streams for lossless encodings (#359)
* Added ability to retrieve bit depth from media streams for lossless encodings
* Shortened sample AIFF file used in tests
Former-commit-id: db7e1e4995
This commit is contained in:
parent
910ec6c759
commit
7dfefbdfdb
10 changed files with 88 additions and 7 deletions
|
@ -27,6 +27,12 @@
|
|||
<Content Include="ffmpeg.config.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<None Update="Resources\24_bit_fixed.WAV">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Resources\32_bit_float.WAV">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Resources\input.webm">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
@ -81,6 +87,15 @@
|
|||
<None Update="Resources\sample.srt">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Resources\sample3aiff.aiff">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Resources\sampleMKV.mkv">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Resources\sampleVOC.voc">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
BIN
FFMpegCore.Test/Resources/24_bit_fixed.WAV
Normal file
BIN
FFMpegCore.Test/Resources/24_bit_fixed.WAV
Normal file
Binary file not shown.
BIN
FFMpegCore.Test/Resources/32_bit_float.WAV
Normal file
BIN
FFMpegCore.Test/Resources/32_bit_float.WAV
Normal file
Binary file not shown.
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
|
BIN
FFMpegCore.Test/Resources/sample3aiff.aiff
Normal file
BIN
FFMpegCore.Test/Resources/sample3aiff.aiff
Normal file
Binary file not shown.
BIN
FFMpegCore.Test/Resources/sampleMKV.mkv
Normal file
BIN
FFMpegCore.Test/Resources/sampleMKV.mkv
Normal file
Binary file not shown.
|
@ -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!;
|
||||
|
||||
|
|
|
@ -47,6 +47,13 @@ private MediaFormat ParseFormat(Format analysisFormat)
|
|||
public List<AudioStream> AudioStreams { get; }
|
||||
public List<SubtitleStream> SubtitleStreams { get; }
|
||||
public IReadOnlyList<string> 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),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ public abstract class MediaStream
|
|||
public string? Language { get; set; }
|
||||
public Dictionary<string, bool>? Disposition { get; set; }
|
||||
public Dictionary<string, string>? Tags { get; set; }
|
||||
public int? BitDepth { get; set; }
|
||||
|
||||
public Codec GetCodecInfo() => FFMpeg.GetCodec(CodecName);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue