Crunchy-Downloader/CRD/Utils/Parser/Segments/SegmentBase.cs
Elwador c4ba220d1b - Added **UseDefaults toggle** for endpoints to choose between **app defaults** (auto-updated with new releases) or **custom parameters**
- Added **authentication parameters** to the **Android TV endpoint**
- Changed **parser and HLS download handling** to support the new manifest/codec format
- Refactored **MKVMerge and FFmpeg command building**
- Updated android tv token
2026-03-24 12:15:22 +01:00

115 lines
No EOL
4.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Numerics;
using CRD.Utils.Parser.Utils;
namespace CRD.Utils.Parser.Segments;
public class SegmentBase{
public static List<dynamic> SegmentsFromBase(dynamic attributes, List<dynamic>? segmentTimeline = null){
var baseUrl = ObjectUtilities.GetMemberValue(attributes, "baseUrl");
var initialization = ObjectUtilities.GetMemberValue(attributes, "initialization") ?? new ExpandoObject();
var sourceDuration = ObjectUtilities.GetMemberValue(attributes, "sourceDuration");
var indexRange = ObjectUtilities.GetMemberValue(attributes, "indexRange") ?? "";
var periodStart = ObjectUtilities.GetMemberValue(attributes, "periodStart");
var presentationTime = ObjectUtilities.GetMemberValue(attributes, "presentationTime");
var number = ObjectUtilities.GetMemberValue(attributes, "number") ?? 0;
var duration = ObjectUtilities.GetMemberValue(attributes, "duration");
if (baseUrl == null){
throw new Exception("NO_BASE_URL");
}
dynamic initSegment = UrlType.UrlTypeToSegment(new{
baseUrl = baseUrl,
source = ObjectUtilities.GetMemberValue(initialization, "sourceURL"),
range = ObjectUtilities.GetMemberValue(initialization, "range")
});
dynamic segment = UrlType.UrlTypeToSegment(new{
baseUrl = baseUrl,
source = baseUrl,
indexRange = indexRange
});
segment.map = initSegment;
if (duration != null){
var segmentTimeInfo = DurationTimeParser.ParseByDuration(attributes);
if (segmentTimeInfo.Count > 0){
segment.duration = segmentTimeInfo[0].duration;
segment.timeline = segmentTimeInfo[0].timeline;
}
} else if (sourceDuration != null){
segment.duration = sourceDuration;
segment.timeline = periodStart;
}
segment.presentationTime = presentationTime ?? periodStart;
segment.number = number;
return new List<dynamic>{ segment };
}
public static dynamic AddSidxSegmentsToPlaylist(dynamic playlist, dynamic sidx, string baseUrl){
// Assume dynamic objects like sidx have properties similar to JavaScript objects
var initSegment = playlist.sidx.ContainsKey("map") ? playlist.sidx.map : null;
var sourceDuration = playlist.sidx.duration;
var timeline = playlist.timeline ?? 0;
dynamic sidxByteRange = playlist.sidx.byterange;
BigInteger sidxEnd = new BigInteger((long)sidxByteRange.offset + (long)sidxByteRange.length);
var timescale = (long)sidx.timescale;
var mediaReferences = ((List<dynamic>)sidx.references).Where(r => r.referenceType != 1).ToList();
var segments = new List<dynamic>();
var type = playlist.endList ? "static" : "dynamic";
var periodStart = (long)playlist.sidx.timeline;
BigInteger presentationTime = new BigInteger(periodStart);
var number = playlist.mediaSequence ?? 0;
BigInteger startIndex;
if (sidx.firstOffset is BigInteger){
startIndex = sidxEnd + (BigInteger)sidx.firstOffset;
} else{
startIndex = sidxEnd + new BigInteger((long)sidx.firstOffset);
}
foreach (var reference in mediaReferences){
var size = (long)reference.referencedSize;
var duration = (long)reference.subsegmentDuration;
BigInteger endIndex = startIndex + new BigInteger(size) - BigInteger.One;
var indexRange = $"{startIndex}-{endIndex}";
dynamic attributes = new ExpandoObject();
attributes.baseUrl = baseUrl;
attributes.timescale = timescale;
attributes.timeline = timeline;
attributes.periodStart = periodStart;
attributes.presentationTime = (long)presentationTime;
attributes.number = number;
attributes.duration = duration;
attributes.sourceDuration = sourceDuration;
attributes.indexRange = indexRange;
attributes.type = type;
var segment = SegmentsFromBase(attributes, new List<dynamic>())[0];
if (initSegment != null){
segment.map = initSegment;
}
segments.Add(segment);
startIndex += new BigInteger(size);
presentationTime += new BigInteger(duration) / new BigInteger(timescale);
number++;
}
playlist.segments = segments;
return playlist;
}
}