Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions FFMpegCore.Test/FFMpegCore.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,15 @@
<None Update="Resources\input_audio_only_10sec.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Resources\input_dovi.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Resources\input_hdr.mov">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Resources\input_interlaced.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Resources\input_video_only_3sec.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
39 changes: 39 additions & 0 deletions FFMpegCore.Test/FFProbeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ public void Probe_Success()
Assert.AreEqual(1, info.PrimaryVideoStream.SampleAspectRatio.Height);
Assert.AreEqual("yuv420p", info.PrimaryVideoStream.PixelFormat);
Assert.AreEqual(31, info.PrimaryVideoStream.Level);
Assert.AreEqual("progressive", info.PrimaryVideoStream.FieldOrder);
Assert.AreEqual(1280, info.PrimaryVideoStream.Width);
Assert.AreEqual(720, info.PrimaryVideoStream.Height);
Assert.AreEqual(25, info.PrimaryVideoStream.AvgFrameRate);
Expand Down Expand Up @@ -208,6 +209,44 @@ public void Probe_HDR()
Assert.AreEqual("bt2020", info.PrimaryVideoStream.ColorPrimaries);
}

[TestMethod]
[Timeout(10000, CooperativeCancellation = true)]
public void Probe_Dovi()
{
var info = FFProbe.Analyse(TestResources.DoviVideo);

Assert.IsNotNull(info.PrimaryVideoStream);
Assert.AreEqual("tv", info.PrimaryVideoStream.ColorRange);
Assert.HasCount(1, info.PrimaryVideoStream.SideData);
Assert.HasCount(10, info.PrimaryVideoStream.SideData[0]);
Assert.IsTrue(info.PrimaryVideoStream.SideData[0].ContainsKey("side_data_type"));
Assert.AreEqual(5, (int)info.PrimaryVideoStream.SideData[0]["dv_profile"]);
}

[TestMethod]
[Timeout(10000, CooperativeCancellation = true)]
public void FrameAnalysis_Dovi()
{
var frameAnalysis = FFProbe.GetFrames(TestResources.DoviVideo);

Assert.HasCount(32, frameAnalysis.Frames);
Assert.IsTrue(frameAnalysis.Frames.All(f => f.PixelFormat == "yuv420p10le"));
Assert.IsTrue(frameAnalysis.Frames.All(f => f.MediaType == "video"));
Assert.IsTrue(frameAnalysis.Frames.All(f => f.SideData.Count == 2));
Assert.IsTrue(frameAnalysis.Frames.All(f => (int)f.SideData[1]["signal_color_space"] == 2));
}

[TestMethod]
[Timeout(10000, CooperativeCancellation = true)]
public void Probe_Interlaced()
{
var info = FFProbe.Analyse(TestResources.InterlacedVideo);

Assert.IsNotNull(info.PrimaryVideoStream);
Assert.AreEqual("tv", info.PrimaryVideoStream.ColorRange);
Assert.AreEqual("tt", info.PrimaryVideoStream.FieldOrder);
}

[TestMethod]
[Timeout(10000, CooperativeCancellation = true)]
public async Task Probe_Success_Subtitle_Async()
Expand Down
2 changes: 2 additions & 0 deletions FFMpegCore.Test/Resources/TestResources.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ public static class TestResources
public static readonly string Mp4VideoRotationNegative = "./Resources/input_3sec_rotation_negative_90deg.mp4";
public static readonly string WebmVideo = "./Resources/input_3sec.webm";
public static readonly string HdrVideo = "./Resources/input_hdr.mov";
public static readonly string DoviVideo = "./Resources/input_dovi.mp4";
public static readonly string InterlacedVideo = "./Resources/input_interlaced.mp4";
public static readonly string Mp4WithoutVideo = "./Resources/input_audio_only_10sec.mp4";
public static readonly string Mp4WithoutAudio = "./Resources/input_video_only_3sec.mp4";
public static readonly string RawAudio = "./Resources/audio.raw";
Expand Down
Binary file added FFMpegCore.Test/Resources/input_dovi.mp4
Binary file not shown.
Binary file added FFMpegCore.Test/Resources/input_interlaced.mp4
Binary file not shown.
2 changes: 2 additions & 0 deletions FFMpegCore/FFProbe/FFProbeAnalysis.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ public class FFProbeStream : ITagsContainer, IDispositionContainer

[JsonPropertyName("level")] public int Level { get; set; }

[JsonPropertyName("field_order")] public string FieldOrder { get; set; } = null!;

[JsonPropertyName("sample_rate")] public string SampleRate { get; set; } = null!;

[JsonPropertyName("side_data_list")] public List<Dictionary<string, JsonValue>> SideData { get; set; } = null!;
Expand Down
5 changes: 4 additions & 1 deletion FFMpegCore/FFProbe/FrameAnalysis.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text.Json.Serialization;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;

namespace FFMpegCore;

Expand Down Expand Up @@ -54,6 +55,8 @@ public class FFProbeFrameAnalysis
[JsonPropertyName("repeat_pict")] public int RepeatPicture { get; set; }

[JsonPropertyName("chroma_location")] public string ChromaLocation { get; set; } = null!;

[JsonPropertyName("side_data_list")] public List<Dictionary<string, JsonNode>> SideData { get; set; } = null!;
}

public class FFProbeFrames
Expand Down
12 changes: 8 additions & 4 deletions FFMpegCore/FFProbe/MediaAnalysis.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ internal MediaAnalysis(FFProbeAnalysis analysis)
VideoStreams = analysis.Streams.Where(stream => stream.CodecType == "video").Select(ParseVideoStream).ToList();
AudioStreams = analysis.Streams.Where(stream => stream.CodecType == "audio").Select(ParseAudioStream).ToList();
SubtitleStreams = analysis.Streams.Where(stream => stream.CodecType == "subtitle").Select(ParseSubtitleStream).ToList();
ErrorData = analysis.ErrorData;
ErrorData = analysis.ErrorData ?? Array.Empty<string>();
}

public TimeSpan Duration => new[] { Format.Duration, PrimaryVideoStream?.Duration ?? TimeSpan.Zero, PrimaryAudioStream?.Duration ?? TimeSpan.Zero }.Max();
Expand Down Expand Up @@ -88,6 +88,7 @@ private VideoStream ParseVideoStream(FFProbeStream stream)
Profile = stream.Profile,
PixelFormat = stream.PixelFormat,
Level = stream.Level,
FieldOrder = stream.FieldOrder,
ColorRange = stream.ColorRange,
ColorSpace = stream.ColorSpace,
ColorTransfer = stream.ColorTransfer,
Expand All @@ -96,7 +97,8 @@ private VideoStream ParseVideoStream(FFProbeStream stream)
Language = stream.GetLanguage(),
Disposition = MediaAnalysisUtils.FormatDisposition(stream.Disposition),
Tags = stream.Tags.ToCaseInsensitive(),
BitDepth = GetBitDepth(stream)
BitDepth = GetBitDepth(stream),
SideData = stream.SideData
};
}

Expand All @@ -119,7 +121,8 @@ private AudioStream ParseAudioStream(FFProbeStream stream)
Language = stream.GetLanguage(),
Disposition = MediaAnalysisUtils.FormatDisposition(stream.Disposition),
Tags = stream.Tags.ToCaseInsensitive(),
BitDepth = GetBitDepth(stream)
BitDepth = GetBitDepth(stream),
SideData = stream.SideData
};
}

Expand All @@ -135,7 +138,8 @@ private SubtitleStream ParseSubtitleStream(FFProbeStream stream)
StartTime = MediaAnalysisUtils.ParseDuration(stream.StartTime),
Language = stream.GetLanguage(),
Disposition = MediaAnalysisUtils.FormatDisposition(stream.Disposition),
Tags = stream.Tags.ToCaseInsensitive()
Tags = stream.Tags.ToCaseInsensitive(),
SideData = stream.SideData
};
}
}
Expand Down
4 changes: 3 additions & 1 deletion FFMpegCore/FFProbe/MediaStream.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using FFMpegCore.Enums;
using System.Text.Json.Nodes;
using FFMpegCore.Enums;

namespace FFMpegCore;

Expand All @@ -16,6 +17,7 @@ public abstract class MediaStream : ITagsContainer
public Dictionary<string, bool>? Disposition { get; set; }
public int? BitDepth { get; set; }
public Dictionary<string, string>? Tags { get; set; }
public List<Dictionary<string, JsonValue>>? SideData { get; set; }

public Codec GetCodecInfo()
{
Expand Down
1 change: 1 addition & 0 deletions FFMpegCore/FFProbe/VideoStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class VideoStream : MediaStream
public double FrameRate { get; set; }
public string PixelFormat { get; set; } = null!;
public int Level { get; set; }
public string FieldOrder { get; set; } = null!;
public int Rotation { get; set; }
public double AverageFrameRate { get; set; }
public string ColorRange { get; set; } = null!;
Expand Down