@ -42,7 +42,7 @@ live_1760874038_001138.m4s
@@ -42,7 +42,7 @@ live_1760874038_001138.m4s
# EXT - X - PROGRAM - DATE - TIME : 2 0 2 1 - 1 0 - 0 8 T08 : 3 4 : 5 7.320 - 0 5 0 0
live_1760874038_001139 . m4s ").Split(Environment.NewLine);
TrimPlaylistResult result = _ hlsPlaylistFilter . TrimPlaylist (
TrimPlaylistResult result = Unwrap ( _ hlsPlaylistFilter . TrimPlaylist (
new Dictionary < long , int >
{
[1760874038] = 1
@ -52,7 +52,7 @@ live_1760874038_001139.m4s").Split(Environment.NewLine);
@@ -52,7 +52,7 @@ live_1760874038_001139.m4s").Split(Environment.NewLine);
start . AddSeconds ( - 3 0 ) ,
new FakeHlsInitSegmentCache ( ) ,
input ,
maybeMaxSegments : 1 0 ) ;
maybeMaxSegments : 1 0 ) ) ;
result . PlaylistStart . ShouldBe ( start ) ;
result . Sequence . ShouldBe ( 1 1 3 7 ) ;
@ -99,7 +99,7 @@ live_1760874038_001138.m4s
@@ -99,7 +99,7 @@ live_1760874038_001138.m4s
# EXT - X - PROGRAM - DATE - TIME : 2 0 2 1 - 1 0 - 0 8 T08 : 3 4 : 5 7.320 - 0 5 0 0
live_1760874038_001139 . m4s ").Split(Environment.NewLine);
TrimPlaylistResult result = _ hlsPlaylistFilter . TrimPlaylist (
TrimPlaylistResult result = Unwrap ( _ hlsPlaylistFilter . TrimPlaylist (
new Dictionary < long , int >
{
[1760874038] = 1
@ -109,7 +109,7 @@ live_1760874038_001139.m4s").Split(Environment.NewLine);
@@ -109,7 +109,7 @@ live_1760874038_001139.m4s").Split(Environment.NewLine);
start . AddSeconds ( - 3 0 ) ,
new FakeHlsInitSegmentCache ( ) ,
input ,
2 ) ;
2 ) ) ;
result . PlaylistStart . ShouldBe ( start ) ;
result . Sequence . ShouldBe ( 1 1 3 7 ) ;
@ -153,7 +153,7 @@ live_1760874038_001138.m4s
@@ -153,7 +153,7 @@ live_1760874038_001138.m4s
# EXT - X - PROGRAM - DATE - TIME : 2 0 2 1 - 1 0 - 0 8 T08 : 3 4 : 5 7.320 - 0 5 0 0
live_1760874038_001139 . m4s ").Split(Environment.NewLine);
TrimPlaylistResult result = _ hlsPlaylistFilter . TrimPlaylistWithDiscontinuity (
TrimPlaylistResult result = Unwrap ( _ hlsPlaylistFilter . TrimPlaylistWithDiscontinuity (
new Dictionary < long , int >
{
[1760874038] = 1
@ -162,7 +162,7 @@ live_1760874038_001139.m4s").Split(Environment.NewLine);
@@ -162,7 +162,7 @@ live_1760874038_001139.m4s").Split(Environment.NewLine);
start ,
start . AddSeconds ( - 3 0 ) ,
new FakeHlsInitSegmentCache ( ) ,
input ) ;
input ) ) ;
result . PlaylistStart . ShouldBe ( start ) ;
result . Sequence . ShouldBe ( 1 1 3 7 ) ;
@ -210,7 +210,7 @@ live_1760874038_001138.m4s
@@ -210,7 +210,7 @@ live_1760874038_001138.m4s
# EXT - X - PROGRAM - DATE - TIME : 2 0 2 1 - 1 0 - 0 8 T08 : 3 4 : 5 7.320 - 0 5 0 0
live_1760874038_001139 . m4s ").Split(Environment.NewLine);
TrimPlaylistResult result = _ hlsPlaylistFilter . TrimPlaylist (
TrimPlaylistResult result = Unwrap ( _ hlsPlaylistFilter . TrimPlaylist (
new Dictionary < long , int >
{
[1760874038] = 1
@ -220,7 +220,7 @@ live_1760874038_001139.m4s").Split(Environment.NewLine);
@@ -220,7 +220,7 @@ live_1760874038_001139.m4s").Split(Environment.NewLine);
start . AddSeconds ( 6 ) ,
new FakeHlsInitSegmentCache ( ) ,
input ,
1 ) ;
1 ) ) ;
result . PlaylistStart . ShouldBe ( start . AddSeconds ( 8 ) ) ;
result . Sequence . ShouldBe ( 1 1 3 9 ) ;
@ -262,7 +262,7 @@ live_1760874042_001138.m4s
@@ -262,7 +262,7 @@ live_1760874042_001138.m4s
# EXT - X - PROGRAM - DATE - TIME : 2 0 2 1 - 1 0 - 0 8 T08 : 3 4 : 5 7.320 - 0 5 0 0
live_1760874042_001139 . m4s ").Split(Environment.NewLine);
TrimPlaylistResult result = _ hlsPlaylistFilter . TrimPlaylist (
TrimPlaylistResult result = Unwrap ( _ hlsPlaylistFilter . TrimPlaylist (
new Dictionary < long , int >
{
[1760874038] = 1 ,
@ -273,7 +273,7 @@ live_1760874042_001139.m4s").Split(Environment.NewLine);
@@ -273,7 +273,7 @@ live_1760874042_001139.m4s").Split(Environment.NewLine);
start . AddSeconds ( 6 ) ,
new FakeHlsInitSegmentCache ( ) ,
input ,
maybeMaxSegments : 1 0 ) ;
maybeMaxSegments : 1 0 ) ) ;
result . PlaylistStart . ShouldBe ( start ) ;
result . Sequence . ShouldBe ( 1 1 3 7 ) ;
@ -564,7 +564,7 @@ live_1760874138_000081.m4s
@@ -564,7 +564,7 @@ live_1760874138_000081.m4s
# EXT - X - PROGRAM - DATE - TIME : 2 0 2 2 - 0 5 - 2 5 T20 : 1 3 : 2 6.007 - 0 5 0 0
live_1760874138_000082 . m4s ").Split(Environment.NewLine);
TrimPlaylistResult result = _ hlsPlaylistFilter . TrimPlaylist (
TrimPlaylistResult result = Unwrap ( _ hlsPlaylistFilter . TrimPlaylist (
new Dictionary < long , int >
{
[1760874038] = 1 ,
@ -575,7 +575,7 @@ live_1760874138_000082.m4s").Split(Environment.NewLine);
@@ -575,7 +575,7 @@ live_1760874138_000082.m4s").Split(Environment.NewLine);
start . AddSeconds ( 2 2 0 ) ,
new FakeHlsInitSegmentCache ( ) ,
input ,
maybeMaxSegments : 1 0 ) ;
maybeMaxSegments : 1 0 ) ) ;
// result.PlaylistStart.ShouldBe(start);
result . Sequence . ShouldBe ( 5 6 ) ;
@ -648,7 +648,7 @@ live_1760874040_000048.m4s
@@ -648,7 +648,7 @@ live_1760874040_000048.m4s
// filter 'live000046.m4s'
var filterBefore = start . AddSeconds ( 2 ) ;
TrimPlaylistResult result = _ hlsPlaylistFilter . TrimPlaylist (
TrimPlaylistResult result = Unwrap ( _ hlsPlaylistFilter . TrimPlaylist (
new Dictionary < long , int >
{
[1760874038] = 2 ,
@ -659,7 +659,7 @@ live_1760874040_000048.m4s
@@ -659,7 +659,7 @@ live_1760874040_000048.m4s
filterBefore ,
new FakeHlsInitSegmentCache ( ) ,
input ,
2 ) ;
2 ) ) ;
result . Sequence . ShouldBe ( 4 7 ) ;
@ -782,7 +782,7 @@ live_1760874038_000064.m4s
@@ -782,7 +782,7 @@ live_1760874038_000064.m4s
// filter 'live000046.m4s'
var filterBefore = start . AddSeconds ( 3 2 ) ;
TrimPlaylistResult result = _ hlsPlaylistFilter . TrimPlaylist (
TrimPlaylistResult result = Unwrap ( _ hlsPlaylistFilter . TrimPlaylist (
new Dictionary < long , int >
{
[1760874038] = 2
@ -792,7 +792,7 @@ live_1760874038_000064.m4s
@@ -792,7 +792,7 @@ live_1760874038_000064.m4s
filterBefore ,
new FakeHlsInitSegmentCache ( ) ,
input ,
1 0 ) ;
1 0 ) ) ;
result . Sequence . ShouldBe ( 4 6 ) ;
@ -939,7 +939,7 @@ live_1760874038_000064.m4s
@@ -939,7 +939,7 @@ live_1760874038_000064.m4s
// filter 'live000046.m4s'
var filterBefore = start . AddSeconds ( 3 6 ) ;
TrimPlaylistResult result = _ hlsPlaylistFilter . TrimPlaylist (
TrimPlaylistResult result = Unwrap ( _ hlsPlaylistFilter . TrimPlaylist (
new Dictionary < long , int >
{
[1760874038] = 2
@ -949,7 +949,7 @@ live_1760874038_000064.m4s
@@ -949,7 +949,7 @@ live_1760874038_000064.m4s
filterBefore ,
new FakeHlsInitSegmentCache ( ) ,
input ,
1 0 ) ;
1 0 ) ) ;
result . Sequence . ShouldBe ( 4 7 ) ;
@ -1021,7 +1021,7 @@ live_1760874038_001138.m4s
@@ -1021,7 +1021,7 @@ live_1760874038_001138.m4s
# EXT - X - PROGRAM - DATE - TIME : 2 0 2 1 - 1 0 - 0 8 T08 : 3 4 : 5 7.320 - 0 5 0 0
live_1760874038_001139 . m4s ").Split(Environment.NewLine);
TrimPlaylistResult result = _ hlsPlaylistFilter . TrimPlaylistWithDiscontinuity (
TrimPlaylistResult result = Unwrap ( _ hlsPlaylistFilter . TrimPlaylistWithDiscontinuity (
new Dictionary < long , int >
{
[1760874038] = 1
@ -1030,12 +1030,43 @@ live_1760874038_001139.m4s").Split(Environment.NewLine);
@@ -1030,12 +1030,43 @@ live_1760874038_001139.m4s").Split(Environment.NewLine);
start ,
start . AddSeconds ( 6 0 ) ,
new FakeHlsInitSegmentCache ( ) ,
input ) ;
input ) ) ;
result . SegmentCount . ShouldBeGreaterThan ( 0 ) ;
result . Playlist . ShouldContain ( "#EXTINF" ) ;
}
[Test]
public void HlsPlaylistFilter_ShouldReturnNone_WhenPlaylistIsMalformed ( )
{
// a malformed playlist used to produce an "empty" result (no segments, sequence 0)
// that callers served to players and wrote over the on-disk playlist
var start = new DateTimeOffset ( 2 0 2 1 , 1 0 , 9 , 8 , 0 , 0 , TimeSpan . FromHours ( - 5 ) ) ;
string [ ] input = NormalizeLineEndings (
@ "#EXTM3U
# EXT - X - VERSION : 7
# EXT - X - TARGETDURATION : 4
# EXTINF : not - a - number ,
live_1760874038_001137 . m4s ").Split(Environment.NewLine);
Option < TrimPlaylistResult > result = _ hlsPlaylistFilter . TrimPlaylist (
new Dictionary < long , int > ( ) ,
OutputFormatKind . HlsMp4 ,
start ,
start . AddSeconds ( - 3 0 ) ,
new FakeHlsInitSegmentCache ( ) ,
input ,
maybeMaxSegments : 1 0 ) ;
result . IsNone . ShouldBeTrue ( ) ;
}
private static TrimPlaylistResult Unwrap ( Option < TrimPlaylistResult > maybeResult )
{
maybeResult . IsSome . ShouldBeTrue ( ) ;
return maybeResult . IfNone ( ( ) = > throw new InvalidOperationException ( "expected trim playlist result" ) ) ;
}
private static string NormalizeLineEndings ( string str ) = >
str
. Replace ( "\r\n" , "\n" )