Skip to content

Commit 62ee5f4

Browse files
committed
Change: Display frame's based calculated duration on files list when file/stream durations not returned by FFProbe (for some raw files)
Change: TBR is used instead of FPS Change: '-probesize 20M' used while getting mediainfo to make detection more accurate
1 parent 6706430 commit 62ee5f4

9 files changed

Lines changed: 44 additions & 28 deletions

File tree

Converters.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public object Convert(object value, Type targetType, object parameter, CultureIn
9393
{
9494
if (value is Frames frames && frames.Count > 0 && frames.FramesDuration > 0)
9595
{
96-
return Math.Round((frames.Count / (double)frames.FramesDuration), 6).ToString() + " fps";
96+
return Helpers.RemoveTrailingZeroes((frames.Count / (double)frames.FramesDuration).ToString("0.000", CultureInfo.InvariantCulture)) + " fps";
9797
}
9898
return ConverterHelper.NA;
9999
}
@@ -147,8 +147,7 @@ public object Convert(object value, Type targetType, object parameter, CultureIn
147147
{
148148
if (value is Frames frames && frames.FramesStartTime != null)
149149
{
150-
string result = TimeSpan.FromSeconds(Math.Round((double)frames.FramesStartTime, 2)).ToString(@"hh\:mm\:ss\.ff");
151-
if (result != "00:00:00.00") return result;
150+
return TimeSpan.FromSeconds(Math.Round((double)frames.FramesStartTime, 2)).ToString(@"hh\:mm\:ss\.ff");
152151
}
153152
return ConverterHelper.NA;
154153
}
@@ -261,7 +260,8 @@ public class MediaInfoFrameRateConverter : IValueConverter
261260
{
262261
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
263262
{
264-
string? s = value is MediaInfo info && info.Video0?.FrameRateAvg != null ? (info.Video0?.FrameRateAvg?.ToString() + " fps (" + info.Video0?.FrameRateAvg?.Value + ")") : null;
263+
var framerate = value is MediaInfo info ? info.Video0?.GetFrameRate() : null;
264+
var s = framerate != null ? (framerate.ToString() + " fps (" + framerate.Value + ")") : null;
265265
return string.IsNullOrEmpty(s) ? ConverterHelper.NA : s;
266266
}
267267

FileItem.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ public string? FS { // File Spec
2222
}
2323
}
2424
public string? FN { get { return Get<string?>(); } private set { Set(value); } } // File Name
25-
public Frames? Frames { get { return Get<Frames?>(); } private set { Set(value); } }
25+
public Frames? Frames { get { return Get<Frames?>(); } private set { Set(value); OnPropertyChanged(nameof(Duration)); } }
2626
//public int? DropTarget { get { return Get<int?>(); } set { Set(value); } } // 1 -- top, 2 - bottom
27-
public double? Duration { get { return MediaInfo?.Video0?.Duration ?? MediaInfo?.Duration; } }
27+
public double? Duration { get { return MediaInfo?.Video0?.Duration ?? MediaInfo?.Duration ?? Frames?.Duration ?? Frames?.FramesDuration; } }
2828
public bool IsAdjustStartTime { get { return Get<bool>(); } set { Set(value); FramesIsAdjustStartTimeSet(value); } }
2929
public bool IsExists { get { return Get<bool>(); } private set { Set(value); OnPropertyChanged(nameof(IsReady)); } }
3030
public bool IsEnabled { get { return Get<bool>(); } set { Set(value); OnPropertyChanged(nameof(IsReady)); } }
@@ -87,7 +87,7 @@ public void FramesGet(CancellationToken cancellationToken, Action<int?, Frame, i
8787
if (o is Frame frame)
8888
{
8989
var pos = frames.Add(frame);
90-
action?.Invoke(pos, frame, line);
90+
if(pos != null) action?.Invoke(pos, frame, line);
9191
}
9292
});
9393

Frames.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -186,19 +186,19 @@ public class Frames
186186
public double? Duration { get { return Count > 0 ? (_frames[^1].EndTime - (IsAdjustStartTime ? StartTime : 0)) : null; } }
187187
public int Count { get { return _frames.Count; } }
188188
public double StartTime { get; set; } = 0;
189-
public double? FramesDuration { get { return Count > 0 ? double.Abs(_frames[^1].EndTime - _frames[0].StartTime) : null; } }
189+
public double? FramesDuration { get { return Count > 0 ? (_frames[^1].EndTime - _frames[0].StartTime) : null; } }
190190
public double? FramesEndTime { get { return Count > 0 ? _frames[^1].EndTime : null; } }
191191
public double? FramesStartTime { get { return Count > 0 ? _frames[0].StartTime : null; } }
192192

193193

194-
public int Add(Frame frame, bool? isForceOrder = null)
194+
public int? Add(Frame frame, bool? isForceOrder = null)
195195
{
196196
var isOrder = isForceOrder == true || !frame.IsOrdered;
197197
if (frame.Size > _maxSizeFrame) _maxSizeFrame = frame.Size;
198198
if (isOrder)
199199
{
200200
var pos = PosFind(frame);
201-
_frames.Insert(pos, frame);
201+
if(pos != null) _frames.Insert((int)pos, frame);
202202
return pos;
203203
}
204204
else
@@ -212,7 +212,7 @@ public void Analyze()
212212
{
213213
if (_isCalcStartTime)
214214
{
215-
CalcFramesStartTime(0);
215+
CalcFramesStartTime(StartTime);
216216
}
217217
}
218218

@@ -424,7 +424,7 @@ public FramesBitRates BitRatesCals()
424424
}
425425

426426

427-
private int PosFind(Frame frame)
427+
private int? PosFind(Frame frame)
428428
{
429429
// Searching position from the end as usually the frame that we are adding will be somewhere close to the end (but not always the last)
430430
// todo@ should probably stop loop if found key frame
@@ -434,13 +434,15 @@ private int PosFind(Frame frame)
434434
_isCalcStartTime = true;
435435
for (int idx = _frames.Count - 1; idx >= 0; --idx)
436436
{
437+
if (frame.Pos == _frames[idx].Pos) return null;
437438
if (frame.Pos > _frames[idx].Pos) return idx + 1;
438439
}
439440
}
440441
else
441442
{
442443
for (int idx = _frames.Count - 1; idx >= 0; --idx)
443444
{
445+
if (frame.StartTime == _frames[idx].StartTime) return null;
444446
if (frame.StartTime > _frames[idx].StartTime) return idx + 1;
445447
}
446448
}

Helpers.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class Helpers
2424
private static readonly Regex RemoveUnusedRegex2 = new Regex(@"(?:^| )-[a-zA-Z_:-]+ ('?)\{\{[^\}]+\}\}\1(?=$| )", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled);
2525
//private static readonly Regex CommaSplitRegex = new Regex(@"((?:[^,\(]+(?:\([^\)]*\))?)+)(?:,|$)", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled);
2626
private static readonly char[] DirSeparators = { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar };
27+
private static readonly Regex RemoveZeroes = new(@"\.?0+$");
2728
public static readonly int Threads = (Environment.ProcessorCount > 2) ? Environment.ProcessorCount - 1 : 0;
2829

2930

@@ -263,6 +264,11 @@ public static void RunAssociatedSystemProgram(string? fs)
263264
Process.Start(new ProcessStartInfo(fs) { UseShellExecute = true });
264265
}
265266

267+
public static string RemoveTrailingZeroes(string s)
268+
{
269+
return RemoveZeroes.Replace(s, "");
270+
}
271+
266272
}
267273

268274

MediaInfo.cs

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,6 @@ public enum VideoStreamToStringMode
438438
public class NDPair
439439
{
440440
private static readonly Regex NDPairRegex = new(@"^(\d+)/(\d+)$", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled);
441-
private static readonly Regex RemoveZeroes = new(@"\.?0+$");
442441
public int? Denominator { get; set; }
443442
public int? Numerator { get; set; }
444443
public string? Value { get; set; }
@@ -463,7 +462,7 @@ public NDPair(string? value)
463462
public override string? ToString() {
464463
var d = ToDouble();
465464
if (d == null) return null;
466-
return RemoveZeroes.Replace(((double)d).ToString("0.000", CultureInfo.InvariantCulture), "");
465+
return Helpers.RemoveTrailingZeroes(((double)d).ToString("0.000", CultureInfo.InvariantCulture));
467466
}
468467

469468

@@ -480,8 +479,8 @@ public class BaseStream
480479
public string? CodecTagString { get; set; }
481480
public double? Duration { get; set; }
482481
public long? DurationTS { get; set; }
483-
public NDPair? FrameRateAvg { get; set; }
484-
public NDPair? FrameRateR { get; set; } // todo@ what is this?
482+
public NDPair? FrameRateAvg { get; set; } // FPS
483+
public NDPair? FrameRateR { get; set; } // TBR
485484
public string? Id { get; set; }
486485
public int? Index { get; set; }
487486
public long? StartPTS { get; set; }
@@ -512,18 +511,15 @@ public class VideoStream : BaseStream
512511
public bool IsBitrateCalculated { get; set; }
513512
public string? Encoder { get; set; }
514513
public VideoStreamFormat Format { get; set; }
515-
//public UDouble? FPS { get; set; }
516514
public string? Profile { get; set; }
517515
public PInt? Resolution { get; set; }
518-
//public UDouble? TBR { get; set; }
519516

520517
public VideoStream(FFProbeStream info) : base(info)
521518
{
522519
Format = new VideoStreamFormat(info);
523520
Profile = info.Profile;
524521
if (info.BitRate != null) BitRate = new BitRate((int)info.BitRate);
525522
if (info.Width != null && info.Height != null) Resolution = new PInt((int)info.Width, (int)info.Height);
526-
//todo@ TBR
527523
}
528524

529525

@@ -533,10 +529,12 @@ public string ToString(VideoStreamToStringMode? mode = null)
533529
var sb = new StringBuilder(15);
534530
switch (mode)
535531
{
536-
case null: // FULL
532+
case null: {
533+
// FULL
537534
if (Resolution != null) sb.Append(Resolution.ToString('x'));
538535

539-
if (FrameRateAvg?.Value != null) sb.Append("-" + FrameRateAvg.ToString());
536+
var framerate = GetFrameRate();
537+
if (framerate?.Value != null) sb.Append("-" + framerate.ToString());
540538
sb.Append(Format?.ToString(VideoStreamFormatToStringMode.FIELD_TYPE));
541539
result.Add(sb.ToString());
542540

@@ -548,10 +546,12 @@ public string ToString(VideoStreamToStringMode? mode = null)
548546

549547
if (BitRate != null) result.Add(BitRate.ToString());
550548
break;
549+
}
551550

552-
case VideoStreamToStringMode.SHORT:
551+
case VideoStreamToStringMode.SHORT: {
553552
if (Resolution != null) sb.Append(Resolution.Y);
554-
if (FrameRateAvg?.Value != null) sb.Append("-" + FrameRateAvg.ToString());
553+
var framerate = GetFrameRate();
554+
if (framerate?.Value != null) sb.Append("-" + framerate.ToString());
555555
sb.Append(Format?.ToString(VideoStreamFormatToStringMode.FIELD_TYPE));
556556
if (sb.Length > 0) result.Add(sb.ToString());
557557

@@ -564,12 +564,20 @@ public string ToString(VideoStreamToStringMode? mode = null)
564564
if (!string.IsNullOrEmpty(s)) result.Add(s);
565565
}
566566
break;
567+
}
567568

568-
default:
569+
default: {
569570
break; // todo@ exception?
571+
}
570572
}
571573
return string.Join(", ", result);
572574
}
575+
576+
public NDPair? GetFrameRate()
577+
{
578+
return FrameRateR ?? FrameRateAvg;
579+
}
580+
573581
}
574582

575583

ProgramConfig.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public class FFProbeMediaInfoConfig
2020
// "-count_frames -count_packets" -- calculate frames & packets counts per stream and (returned in nb_frames/nb_packets), but this is much slower.
2121
// "-find_stream_info" -- fill-in missing information by actually read the streams instead of just parsing the header(s). It helps with corrupted files.
2222
// "-probesize 10000000" and "-analyzeduration 2000000" cab be used with -find_stream_info
23-
public string Template { get; set; } = "-hide_banner -threads {{threads}} -print_format json=compact=1 -loglevel fatal -show_error -show_format -show_streams -show_entries stream_tags=duration {{src}}";
23+
public string Template { get; set; } = "-hide_banner -threads {{threads}} -probesize 20M -print_format json=compact=1 -loglevel fatal -show_error -show_format -show_streams -show_entries stream_tags=duration {{src}}";
2424

2525
public int Timeout { get; set; } = 30_000; // milliseconds
2626
}

Properties/launchSettings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"profiles": {
33
"FFBitrateViewer": {
44
"commandName": "Project",
5-
"commandLineArgs": "--log-level=debug -plot-view-type=SECOND c:\\Vegas\\MainconceptBug2\\2012-11-22_095841.m2ts"
5+
"commandLineArgs": "--log-level=debug"
66
}
77
}
88
}

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ It is inspired by [Bitrate Viewer](https://web.archive.org/web/20160730053853/ht
55
FFBitrateViewer allows you to select multiple files without dealing with command line and get “per frame”, “per second” or “per GOP” info for all of them in one go.
66

77
Well, and play with interactive graphs (powered by OxyPlot):
8-
<p align="center"><img src="screenshots/screenshot.0.9.0.png" width="900"/></p>
8+
<p align="center"><img src="screenshots/screenshot.0.9.4.png" width="900"/></p>
99

1010

1111
## Features
@@ -21,7 +21,7 @@ Well, and play with interactive graphs (powered by OxyPlot):
2121

2222

2323
## Latest version
24-
- Latest Beta: [0.9.3 beta 1](https://github.com/fifonik/FFBitrateViewer/releases/tag/v0.9.3-beta.1)
24+
- Latest Beta: [0.9.4 beta 1](https://github.com/fifonik/FFBitrateViewer/releases/tag/v0.9.4-beta.1)
2525

2626

2727
## Requirements

screenshots/screenshot.0.9.4.png

98.4 KB
Loading

0 commit comments

Comments
 (0)