Crunchy-Downloader/CRD/Utils/Parser/Segments/DurationTimeParser.cs

89 lines
3.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
namespace CRD.Utils.Parser.Segments;
public class DurationTimeParser{
public static int? ParseEndNumber(string endNumber){
if (!int.TryParse(endNumber, out var parsedEndNumber)){
return null;
}
return parsedEndNumber;
}
public static dynamic GetSegmentRangeStatic(dynamic attributes){
int timescale = attributes.timescale ?? 1;
double segmentDuration = (double)attributes.duration / timescale;
int? endNumber = ParseEndNumber(attributes.endNumber as string);
if (endNumber.HasValue){
return new{ start = 0, end = endNumber.Value };
}
if (attributes.periodDuration is double periodDuration){
return new{ start = 0, end = (int)(periodDuration / segmentDuration) };
}
return new{ start = 0, end = (int)(attributes.sourceDuration / segmentDuration) };
}
public static dynamic GetSegmentRangeDynamic(dynamic attributes){
long now = (attributes.NOW + attributes.clientOffset) / 1000;
long periodStartWC = attributes.availabilityStartTime + attributes.periodStart;
long periodEndWC = now + attributes.minimumUpdatePeriod;
long periodDuration = periodEndWC - periodStartWC;
int timescale = attributes.timescale ?? 1;
int segmentCount = (int)Math.Ceiling(periodDuration * timescale / (double)attributes.duration);
int availableStart = (int)Math.Floor((now - periodStartWC - attributes.timeShiftBufferDepth) * timescale / (double)attributes.duration);
int availableEnd = (int)Math.Floor((now - periodStartWC) * timescale / (double)attributes.duration);
int? endNumber = ParseEndNumber(attributes.endNumber as string);
int end = endNumber.HasValue ? endNumber.Value : Math.Min(segmentCount, availableEnd);
return new{ start = Math.Max(0, availableStart), end = end };
}
public static List<dynamic> ToSegments(dynamic attributes, int number){
int timescale = attributes.timescale ?? 1;
long periodStart = attributes.periodStart;
int startNumber = attributes.startNumber ?? 1;
return new List<dynamic>{
new{
number = startNumber + number,
duration = (double)attributes.duration / timescale,
timeline = periodStart,
time = number * attributes.duration
}
};
}
public static IEnumerable<dynamic> ParseByDuration(dynamic attributes){
var type = (string)attributes.type;
var rangeFunction = type == "static" ? (Func<dynamic, dynamic>)GetSegmentRangeStatic : GetSegmentRangeDynamic;
dynamic times = rangeFunction(attributes);
List<int> d = Range(times.start, times.end - times.start);
List<dynamic> segments = d.Select(number => ToSegments(attributes, number)).ToList();
// Adjust the duration of the last segment for static type
if (type == "static" && segments.Any()){
var lastSegmentIndex = segments.Count - 1;
double sectionDuration = attributes.periodDuration is double periodDuration ? periodDuration : attributes.sourceDuration;
segments[lastSegmentIndex].duration = sectionDuration - ((double)attributes.duration / (attributes.timescale ?? 1) * lastSegmentIndex);
}
return segments;
}
public static List<int> Range(int start, int end){
List<int> res = new List<int>();
for (int i = start; i < end; i++){
res.Add(i);
}
return res;
}
}