mirror of
https://github.com/unclshura/splitter.git
synced 2026-06-21 16:12:01 +00:00
SAR/DAR support added
This commit is contained in:
parent
4f83fc1dd2
commit
a408d43b61
@ -10,25 +10,15 @@ namespace Splitter_UI.ViewModels;
|
||||
|
||||
public partial class JobViewModel : ObservableObject
|
||||
{
|
||||
public SingleJob Job { get; }
|
||||
public VideoInfo? Probe { get; set; }
|
||||
[ObservableProperty]
|
||||
private PreviewData? _preview = new(null, [], null);
|
||||
public ProgressInfo? Progress { get; set; }
|
||||
public SingleJob Job { get; }
|
||||
|
||||
[ObservableProperty]
|
||||
private Bitmap? _thumbnail;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _suggestedAction = "";
|
||||
|
||||
// This updates continuously
|
||||
[ObservableProperty]
|
||||
private double _sliderLiveValue;
|
||||
|
||||
// This updates only on release
|
||||
[ObservableProperty]
|
||||
private double _positionSeconds;
|
||||
[ObservableProperty] private VideoInfo? _probe;
|
||||
[ObservableProperty] private PreviewData? _preview = new(null, [], null);
|
||||
[ObservableProperty] private ProgressInfo? _progress;
|
||||
[ObservableProperty] private Bitmap? _thumbnail;
|
||||
[ObservableProperty] private string _suggestedAction = "";
|
||||
[ObservableProperty] private double _sliderLiveValue;
|
||||
[ObservableProperty] private double _positionSeconds;
|
||||
|
||||
public double DurationSeconds => Probe?.Duration ?? 0;
|
||||
|
||||
|
||||
@ -9,6 +9,8 @@ public partial class PreviewPaneViewModel : ObservableObject
|
||||
private JobViewModel? _selected;
|
||||
|
||||
public PreviewData? Preview => Selected?.Preview;
|
||||
public Point2f? Sar => Selected?.Probe?.Sar;
|
||||
public Point2f? Dar => Selected?.Probe?.Dar;
|
||||
|
||||
partial void OnSelectedChanged(JobViewModel? oldValue, JobViewModel? newValue)
|
||||
{
|
||||
@ -19,12 +21,20 @@ public partial class PreviewPaneViewModel : ObservableObject
|
||||
newValue.PropertyChanged += SelectedPropertyChanged;
|
||||
|
||||
OnPropertyChanged(nameof(Preview));
|
||||
OnPropertyChanged(nameof(Sar));
|
||||
OnPropertyChanged(nameof(Dar));
|
||||
}
|
||||
|
||||
private void SelectedPropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == nameof(JobViewModel.Preview))
|
||||
OnPropertyChanged(nameof(Preview));
|
||||
|
||||
if (e.PropertyName == nameof(JobViewModel.Probe))
|
||||
{
|
||||
OnPropertyChanged(nameof(Sar));
|
||||
OnPropertyChanged(nameof(Dar));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -10,6 +10,10 @@ public sealed class PreviewCanvas : Control
|
||||
{
|
||||
public static readonly StyledProperty<PreviewData?> PreviewProperty =
|
||||
AvaloniaProperty.Register<PreviewCanvas, PreviewData?>(nameof(Preview));
|
||||
public static readonly StyledProperty<Point2f?> SarProperty =
|
||||
AvaloniaProperty.Register<PreviewCanvas, Point2f?>(nameof(Sar));
|
||||
public static readonly StyledProperty<Point2f?> DarProperty =
|
||||
AvaloniaProperty.Register<PreviewCanvas, Point2f?>(nameof(Dar));
|
||||
|
||||
public PreviewData? Preview
|
||||
{
|
||||
@ -17,6 +21,18 @@ public sealed class PreviewCanvas : Control
|
||||
set => SetValue(PreviewProperty, value);
|
||||
}
|
||||
|
||||
public Point2f? Sar
|
||||
{
|
||||
get => GetValue(SarProperty);
|
||||
set => SetValue(SarProperty, value);
|
||||
}
|
||||
|
||||
public Point2f? Dar
|
||||
{
|
||||
get => GetValue(DarProperty);
|
||||
set => SetValue(DarProperty, value);
|
||||
}
|
||||
|
||||
static PreviewCanvas()
|
||||
{
|
||||
PreviewProperty.Changed.AddClassHandler<PreviewCanvas>(
|
||||
@ -56,7 +72,7 @@ public sealed class PreviewCanvas : Control
|
||||
var preview = Preview;
|
||||
if (preview?.Frame is null)
|
||||
return;
|
||||
|
||||
|
||||
var frame = preview.Frame;
|
||||
var rawW = frame.PixelSize.Width;
|
||||
var rawH = frame.PixelSize.Height;
|
||||
@ -67,34 +83,64 @@ public sealed class PreviewCanvas : Control
|
||||
if (dispW <= 0 || dispH <= 0)
|
||||
return;
|
||||
|
||||
var scale = Math.Min(dispW / rawW, dispH / rawH);
|
||||
// SAR
|
||||
var sar = Sar ?? new Point2f(1, 1);
|
||||
var sarX = (double)sar.X;
|
||||
var sarY = (double)sar.Y;
|
||||
|
||||
var scaledW = rawW * scale;
|
||||
var scaledH = rawH * scale;
|
||||
if (sarX <= 0 || sarY <= 0)
|
||||
{
|
||||
sarX = 1;
|
||||
sarY = 1;
|
||||
}
|
||||
|
||||
// DAR override (only if SAR missing or invalid)
|
||||
if ((sarX == 1 && sarY == 1) && Dar is { } dar && dar.X > 0 && dar.Y > 0)
|
||||
{
|
||||
var darRatio = dar.X / dar.Y;
|
||||
var encodedRatio = rawW / (double)rawH;
|
||||
|
||||
// recompute SAR from DAR
|
||||
sarX = darRatio / encodedRatio;
|
||||
sarY = 1;
|
||||
}
|
||||
|
||||
var pixelAspect = sarX / sarY;
|
||||
|
||||
// display size after SAR correction
|
||||
var displayW = rawW * pixelAspect;
|
||||
var displayH = rawH;
|
||||
|
||||
var scale = Math.Min(dispW / displayW, dispH / displayH);
|
||||
|
||||
var scaledW = displayW * scale;
|
||||
var scaledH = displayH * scale;
|
||||
|
||||
var offsetX = (dispW - scaledW) / 2;
|
||||
var offsetY = (dispH - scaledH) / 2;
|
||||
|
||||
// draw frame
|
||||
context.DrawImage(frame,
|
||||
context.DrawImage(
|
||||
frame,
|
||||
new Rect(0, 0, rawW, rawH),
|
||||
new Rect(offsetX, offsetY, scaledW, scaledH));
|
||||
|
||||
// draw overlays
|
||||
if (preview.DetectedBoxes is { Count: > 0 })
|
||||
// overlays
|
||||
if (preview.DetectedBoxes is { Count: > 0 })
|
||||
{
|
||||
var pen = new Pen(Brushes.Lime, 2);
|
||||
|
||||
foreach (var r in preview.DetectedBoxes )
|
||||
foreach (var r in preview.DetectedBoxes)
|
||||
{
|
||||
var rr = new Rect(
|
||||
offsetX + r.X * scale,
|
||||
offsetY + r.Y * scale,
|
||||
r.Width * scale,
|
||||
r.Height * scale);
|
||||
offsetX + (r.X * pixelAspect) * scale,
|
||||
offsetY + r.Y * scale,
|
||||
(r.Width * pixelAspect) * scale,
|
||||
r.Height * scale);
|
||||
|
||||
context.DrawRectangle(null, pen, rr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -11,7 +11,9 @@
|
||||
|
||||
<local:PreviewCanvas
|
||||
Grid.Row="0"
|
||||
Preview="{Binding Preview}" />
|
||||
Preview="{Binding Preview}"
|
||||
Sar="{Binding Sar}"
|
||||
Dar="{Binding Dar}" />
|
||||
|
||||
<Grid Grid.Row="1"
|
||||
ColumnDefinitions="Auto,*,Auto"
|
||||
|
||||
40
splitter-cli/FfprobeFormat.cs
Normal file
40
splitter-cli/FfprobeFormat.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace splitter;
|
||||
|
||||
public sealed class FfprobeFormat
|
||||
{
|
||||
public string? Filename { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Nb_streams { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Nb_programs { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Nb_stream_groups { get; set; }
|
||||
|
||||
public string? Format_name { get; set; }
|
||||
public string? Format_long_name { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleDoubleConverter))]
|
||||
public double? Start_time { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleDoubleConverter))]
|
||||
public double? Duration { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleLongConverter))]
|
||||
public long? Size { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleLongConverter))]
|
||||
public long? Bit_rate { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Probe_score { get; set; }
|
||||
|
||||
public Dictionary<string, string>? Tags { get; set; }
|
||||
}
|
||||
12
splitter-cli/FfprobeResult.cs
Normal file
12
splitter-cli/FfprobeResult.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using static splitter.ProbeVideo;
|
||||
|
||||
namespace splitter;
|
||||
|
||||
public sealed class FfprobeResult
|
||||
{
|
||||
public List<FfprobeStream>? Streams { get; set; }
|
||||
public FfprobeFormat? Format { get; set; }
|
||||
}
|
||||
129
splitter-cli/FfprobeStream.cs
Normal file
129
splitter-cli/FfprobeStream.cs
Normal file
@ -0,0 +1,129 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace splitter;
|
||||
|
||||
public sealed class FfprobeStream
|
||||
{
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Index { get; set; }
|
||||
|
||||
public string? Codec_name { get; set; }
|
||||
public string? Codec_long_name { get; set; }
|
||||
public string? Profile { get; set; }
|
||||
public string? Codec_type { get; set; }
|
||||
public string? Codec_tag_string { get; set; }
|
||||
public string? Codec_tag { get; set; }
|
||||
public string? Mime_codec_string { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Width { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Height { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Coded_width { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Coded_height { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Closed_captions { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Film_grain { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Has_b_frames { get; set; }
|
||||
|
||||
public string? Sample_aspect_ratio { get; set; }
|
||||
public string? Display_aspect_ratio { get; set; }
|
||||
|
||||
public string? Pix_fmt { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Level { get; set; }
|
||||
|
||||
public string? Color_range { get; set; }
|
||||
public string? Color_space { get; set; }
|
||||
public string? Color_transfer { get; set; }
|
||||
public string? Color_primaries { get; set; }
|
||||
public string? Chroma_location { get; set; }
|
||||
public string? Field_order { get; set; }
|
||||
|
||||
public string? Is_avc { get; set; }
|
||||
public string? Nal_length_size { get; set; }
|
||||
|
||||
public string? Id { get; set; }
|
||||
public string? R_frame_rate { get; set; }
|
||||
public string? Avg_frame_rate { get; set; }
|
||||
public string? Time_base { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleLongConverter))]
|
||||
public long? Start_pts { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleDoubleConverter))]
|
||||
public double? Start_time { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleLongConverter))]
|
||||
public long? Duration_ts { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleDoubleConverter))]
|
||||
public double? Duration { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleLongConverter))]
|
||||
public long? Bit_rate { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleLongConverter))]
|
||||
public long? Max_bit_rate { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Bits_per_raw_sample { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Bits_per_sample { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleLongConverter))]
|
||||
public long? Nb_frames { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Extradata_size { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Channels { get; set; }
|
||||
|
||||
public string? Channel_layout { get; set; }
|
||||
public string? Sample_fmt { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Sample_rate { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Initial_padding { get; set; }
|
||||
|
||||
public string? Disposition_raw { get; set; }
|
||||
public Dictionary<string, int>? Disposition { get; set; }
|
||||
|
||||
public Dictionary<string, string>? Tags { get; set; }
|
||||
|
||||
public string? Language { get; set; }
|
||||
public string? Title { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Bits_per_coded_sample { get; set; }
|
||||
|
||||
public string? Codec_time_base { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleDoubleConverter))]
|
||||
public double? Start_pts_time { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleDoubleConverter))]
|
||||
public double? Duration_time { get; set; }
|
||||
|
||||
public string? Extradata { get; set; }
|
||||
public string? Default { get; set; }
|
||||
public string? Forced { get; set; }
|
||||
}
|
||||
@ -5,17 +5,6 @@ using System.Text.Json.Serialization;
|
||||
|
||||
namespace splitter;
|
||||
|
||||
public record VideoInfo(
|
||||
double Duration,
|
||||
int Width,
|
||||
int Height,
|
||||
double Fps,
|
||||
double Bitrate,
|
||||
double SarX,
|
||||
double SarY,
|
||||
int Rotation = 0
|
||||
);
|
||||
|
||||
public static class ProbeVideo
|
||||
{
|
||||
static ProbeVideo()
|
||||
@ -43,170 +32,6 @@ public static class ProbeVideo
|
||||
return rotation;
|
||||
}
|
||||
|
||||
public sealed class FfprobeResult
|
||||
{
|
||||
public List<FfprobeStream>? Streams { get; set; }
|
||||
public FfprobeFormat? Format { get; set; }
|
||||
}
|
||||
|
||||
public sealed class FfprobeFormat
|
||||
{
|
||||
public string? Filename { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Nb_streams { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Nb_programs { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Nb_stream_groups { get; set; }
|
||||
|
||||
public string? Format_name { get; set; }
|
||||
public string? Format_long_name { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleDoubleConverter))]
|
||||
public double? Start_time { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleDoubleConverter))]
|
||||
public double? Duration { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleLongConverter))]
|
||||
public long? Size { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleLongConverter))]
|
||||
public long? Bit_rate { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Probe_score { get; set; }
|
||||
|
||||
public Dictionary<string, string>? Tags { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public sealed class FfprobeStream
|
||||
{
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Index { get; set; }
|
||||
|
||||
public string? Codec_name { get; set; }
|
||||
public string? Codec_long_name { get; set; }
|
||||
public string? Profile { get; set; }
|
||||
public string? Codec_type { get; set; }
|
||||
public string? Codec_tag_string { get; set; }
|
||||
public string? Codec_tag { get; set; }
|
||||
public string? Mime_codec_string { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Width { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Height { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Coded_width { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Coded_height { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Closed_captions { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Film_grain { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Has_b_frames { get; set; }
|
||||
|
||||
public string? Sample_aspect_ratio { get; set; }
|
||||
public string? Display_aspect_ratio { get; set; }
|
||||
|
||||
public string? Pix_fmt { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Level { get; set; }
|
||||
|
||||
public string? Color_range { get; set; }
|
||||
public string? Color_space { get; set; }
|
||||
public string? Color_transfer { get; set; }
|
||||
public string? Color_primaries { get; set; }
|
||||
public string? Chroma_location { get; set; }
|
||||
public string? Field_order { get; set; }
|
||||
|
||||
public string? Is_avc { get; set; }
|
||||
public string? Nal_length_size { get; set; }
|
||||
|
||||
public string? Id { get; set; }
|
||||
public string? R_frame_rate { get; set; }
|
||||
public string? Avg_frame_rate { get; set; }
|
||||
public string? Time_base { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleLongConverter))]
|
||||
public long? Start_pts { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleDoubleConverter))]
|
||||
public double? Start_time { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleLongConverter))]
|
||||
public long? Duration_ts { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleDoubleConverter))]
|
||||
public double? Duration { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleLongConverter))]
|
||||
public long? Bit_rate { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleLongConverter))]
|
||||
public long? Max_bit_rate { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Bits_per_raw_sample { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Bits_per_sample { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleLongConverter))]
|
||||
public long? Nb_frames { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Extradata_size { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Channels { get; set; }
|
||||
|
||||
public string? Channel_layout { get; set; }
|
||||
public string? Sample_fmt { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Sample_rate { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Initial_padding { get; set; }
|
||||
|
||||
public string? Disposition_raw { get; set; }
|
||||
public Dictionary<string, int>? Disposition { get; set; }
|
||||
|
||||
public Dictionary<string, string>? Tags { get; set; }
|
||||
|
||||
public string? Language { get; set; }
|
||||
public string? Title { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleIntConverter))]
|
||||
public int? Bits_per_coded_sample { get; set; }
|
||||
|
||||
public string? Codec_time_base { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleDoubleConverter))]
|
||||
public double? Start_pts_time { get; set; }
|
||||
|
||||
[JsonConverter(typeof(FlexibleDoubleConverter))]
|
||||
public double? Duration_time { get; set; }
|
||||
|
||||
public string? Extradata { get; set; }
|
||||
public string? Default { get; set; }
|
||||
public string? Forced { get; set; }
|
||||
}
|
||||
|
||||
private static readonly JsonSerializerOptions _ffprobeJsonOptions =
|
||||
new ()
|
||||
{
|
||||
@ -265,36 +90,29 @@ public static class ProbeVideo
|
||||
|
||||
var bitrate = stream?.Bit_rate ?? 0.0;
|
||||
|
||||
var (sarX, sarY) = ParseSar(stream?.Sample_aspect_ratio);
|
||||
var sar = ParseAspectRatio(stream?.Sample_aspect_ratio);
|
||||
var dar = ParseAspectRatio(stream?.Display_aspect_ratio);
|
||||
|
||||
return new VideoInfo(duration, width, height, fps, bitrate, sarX, sarY);
|
||||
return new VideoInfo(duration, width, height, fps, bitrate, sar, dar);
|
||||
}
|
||||
|
||||
static double ParseDouble(string? s)
|
||||
{
|
||||
if (double.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var v))
|
||||
return v;
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
private static (double x, double y) ParseSar(string? sar)
|
||||
private static Point2f ParseAspectRatio(string? sar)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(sar))
|
||||
return (1.0, 1.0);
|
||||
return new Point2f(1.0f, 1.0f);
|
||||
|
||||
var parts = sar.Split(':');
|
||||
if (parts.Length != 2)
|
||||
return (1.0, 1.0);
|
||||
return new(1.0f, 1.0f);
|
||||
|
||||
if (double.TryParse(parts[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var num) &&
|
||||
double.TryParse(parts[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var den) &&
|
||||
if (float.TryParse(parts[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var num) &&
|
||||
float.TryParse(parts[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var den) &&
|
||||
den != 0)
|
||||
{
|
||||
return (num, den);
|
||||
return new(num, den);
|
||||
}
|
||||
|
||||
return (1.0, 1.0);
|
||||
return new(1.0f, 1.0f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
12
splitter-cli/VideoInfo.cs
Normal file
12
splitter-cli/VideoInfo.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace splitter;
|
||||
|
||||
public record VideoInfo(
|
||||
double Duration,
|
||||
int Width,
|
||||
int Height,
|
||||
double Fps,
|
||||
double Bitrate,
|
||||
Point2f Sar,
|
||||
Point2f Dar,
|
||||
int Rotation = 0
|
||||
);
|
||||
Loading…
x
Reference in New Issue
Block a user