fix mid-roll filler scheduling bug (#675)
This commit is contained in:
@@ -10,6 +10,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
- Fix playback of interlaced mpeg2video content with NVIDIA acceleration
|
||||
- Fix playback of all interlaced content with QSV acceleration
|
||||
- Fix adding songs to collections from search results page
|
||||
- Fix bug scheduling mid-roll filler with content that contains one chapter
|
||||
- No mid-roll filler will be inserted for content with zero or one chapters
|
||||
|
||||
### Added
|
||||
- Add automated error reporting via Bugsnag
|
||||
|
||||
@@ -3,15 +3,20 @@ using ErsatzTV.Core.Domain.Filler;
|
||||
using ErsatzTV.Core.Interfaces.Scheduling;
|
||||
using ErsatzTV.Core.Scheduling;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace ErsatzTV.Core.Tests.Scheduling;
|
||||
|
||||
[TestFixture]
|
||||
public class PlayoutModeSchedulerBaseTests
|
||||
public class PlayoutModeSchedulerBaseTests : SchedulerTestBase
|
||||
{
|
||||
[TestFixture]
|
||||
public class CalculateEndTimeWithFiller
|
||||
{
|
||||
[Test]
|
||||
public void CalculateEndTimeWithFiller_Should_Not_Touch_Enumerator()
|
||||
public void Should_Not_Touch_Enumerator()
|
||||
{
|
||||
var collection = new Collection
|
||||
{
|
||||
@@ -58,7 +63,7 @@ public class PlayoutModeSchedulerBaseTests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CalculateEndTimeWithFiller_Should_Pad_To_15_Minutes_15()
|
||||
public void Should_Pad_To_15_Minutes_15()
|
||||
{
|
||||
DateTimeOffset result = PlayoutModeSchedulerBase<ProgramScheduleItem>
|
||||
.CalculateEndTimeWithFiller(
|
||||
@@ -80,7 +85,7 @@ public class PlayoutModeSchedulerBaseTests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CalculateEndTimeWithFiller_Should_Pad_To_15_Minutes_30()
|
||||
public void Should_Pad_To_15_Minutes_30()
|
||||
{
|
||||
DateTimeOffset result = PlayoutModeSchedulerBase<ProgramScheduleItem>
|
||||
.CalculateEndTimeWithFiller(
|
||||
@@ -102,7 +107,7 @@ public class PlayoutModeSchedulerBaseTests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CalculateEndTimeWithFiller_Should_Pad_To_15_Minutes_45()
|
||||
public void Should_Pad_To_15_Minutes_45()
|
||||
{
|
||||
DateTimeOffset result = PlayoutModeSchedulerBase<ProgramScheduleItem>
|
||||
.CalculateEndTimeWithFiller(
|
||||
@@ -124,7 +129,7 @@ public class PlayoutModeSchedulerBaseTests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CalculateEndTimeWithFiller_Should_Pad_To_15_Minutes_00()
|
||||
public void Should_Pad_To_15_Minutes_00()
|
||||
{
|
||||
DateTimeOffset result = PlayoutModeSchedulerBase<ProgramScheduleItem>
|
||||
.CalculateEndTimeWithFiller(
|
||||
@@ -146,7 +151,7 @@ public class PlayoutModeSchedulerBaseTests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CalculateEndTimeWithFiller_Should_Pad_To_30_Minutes_30()
|
||||
public void Should_Pad_To_30_Minutes_30()
|
||||
{
|
||||
DateTimeOffset result = PlayoutModeSchedulerBase<ProgramScheduleItem>
|
||||
.CalculateEndTimeWithFiller(
|
||||
@@ -168,7 +173,7 @@ public class PlayoutModeSchedulerBaseTests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CalculateEndTimeWithFiller_Should_Pad_To_30_Minutes_00()
|
||||
public void Should_Pad_To_30_Minutes_00()
|
||||
{
|
||||
DateTimeOffset result = PlayoutModeSchedulerBase<ProgramScheduleItem>
|
||||
.CalculateEndTimeWithFiller(
|
||||
@@ -188,6 +193,98 @@ public class PlayoutModeSchedulerBaseTests
|
||||
|
||||
result.Should().Be(new DateTimeOffset(2020, 2, 1, 13, 0, 0, TimeSpan.FromHours(-5)));
|
||||
}
|
||||
}
|
||||
|
||||
[TestFixture]
|
||||
public class AddFiller
|
||||
{
|
||||
[Test]
|
||||
public void Should_Not_Crash_Mid_Roll_Zero_Chapters()
|
||||
{
|
||||
Collection collectionOne = TwoItemCollection(1, 2, TimeSpan.FromHours(1));
|
||||
|
||||
var scheduleItem = new ProgramScheduleItemOne
|
||||
{
|
||||
MidRollFiller = new FillerPreset
|
||||
{
|
||||
FillerKind = FillerKind.MidRoll,
|
||||
FillerMode = FillerMode.Pad,
|
||||
PadToNearestMinute = 15
|
||||
}
|
||||
};
|
||||
|
||||
var scheduleItemsEnumerator = new OrderedScheduleItemsEnumerator(
|
||||
new List<ProgramScheduleItem> { scheduleItem },
|
||||
new CollectionEnumeratorState());
|
||||
|
||||
var enumerator = new ChronologicalMediaCollectionEnumerator(
|
||||
collectionOne.MediaItems,
|
||||
new CollectionEnumeratorState());
|
||||
|
||||
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
|
||||
|
||||
List<PlayoutItem> playoutItems = PlayoutModeSchedulerBase<ProgramScheduleItem>
|
||||
.AddFiller(
|
||||
startState,
|
||||
CollectionEnumerators(scheduleItem, enumerator),
|
||||
scheduleItem,
|
||||
new PlayoutItem(),
|
||||
new List<MediaChapter>());
|
||||
|
||||
playoutItems.Count.Should().Be(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Should_Not_Crash_Mid_Roll_One_Chapter()
|
||||
{
|
||||
Collection collectionOne = TwoItemCollection(1, 2, TimeSpan.FromHours(1));
|
||||
|
||||
var scheduleItem = new ProgramScheduleItemOne
|
||||
{
|
||||
Id = 1,
|
||||
Index = 1,
|
||||
Collection = collectionOne,
|
||||
CollectionId = collectionOne.Id,
|
||||
StartTime = null,
|
||||
PlaybackOrder = PlaybackOrder.Chronological,
|
||||
TailFiller = null,
|
||||
FallbackFiller = null,
|
||||
MidRollFiller = new FillerPreset
|
||||
{
|
||||
FillerKind = FillerKind.MidRoll,
|
||||
FillerMode = FillerMode.Pad,
|
||||
PadToNearestMinute = 15
|
||||
}
|
||||
};
|
||||
|
||||
var scheduleItemsEnumerator = new OrderedScheduleItemsEnumerator(
|
||||
new List<ProgramScheduleItem> { scheduleItem },
|
||||
new CollectionEnumeratorState());
|
||||
|
||||
var enumerator = new ChronologicalMediaCollectionEnumerator(
|
||||
collectionOne.MediaItems,
|
||||
new CollectionEnumeratorState());
|
||||
|
||||
PlayoutBuilderState startState = StartState(scheduleItemsEnumerator);
|
||||
|
||||
Dictionary<CollectionKey, IMediaCollectionEnumerator> enumerators = CollectionEnumerators(
|
||||
scheduleItem,
|
||||
enumerator);
|
||||
|
||||
// too lazy to make another enumerator for the filler that we don't want
|
||||
enumerators.Add(CollectionKey.ForFillerPreset(scheduleItem.MidRollFiller), enumerator);
|
||||
|
||||
List<PlayoutItem> playoutItems = PlayoutModeSchedulerBase<ProgramScheduleItem>
|
||||
.AddFiller(
|
||||
startState,
|
||||
enumerators,
|
||||
scheduleItem,
|
||||
new PlayoutItem(),
|
||||
new List<MediaChapter> { new() });
|
||||
|
||||
playoutItems.Count.Should().Be(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static Movie TestMovie(int id, TimeSpan duration, DateTime aired) =>
|
||||
new()
|
||||
|
||||
@@ -310,7 +310,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
|
||||
return itemStartTime + totalDuration;
|
||||
}
|
||||
|
||||
protected List<PlayoutItem> AddFiller(
|
||||
internal static List<PlayoutItem> AddFiller(
|
||||
PlayoutBuilderState playoutBuilderState,
|
||||
Dictionary<CollectionKey, IMediaCollectionEnumerator> enumerators,
|
||||
ProgramScheduleItem scheduleItem,
|
||||
@@ -333,7 +333,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
|
||||
}
|
||||
|
||||
List<MediaChapter> effectiveChapters = chapters;
|
||||
if (allFiller.All(fp => fp.FillerKind != FillerKind.MidRoll))
|
||||
if (allFiller.All(fp => fp.FillerKind != FillerKind.MidRoll) || effectiveChapters.Count <= 1)
|
||||
{
|
||||
effectiveChapters = new List<MediaChapter>();
|
||||
}
|
||||
@@ -356,7 +356,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
|
||||
}
|
||||
}
|
||||
|
||||
if (!effectiveChapters.Any())
|
||||
if (effectiveChapters.Count <= 1)
|
||||
{
|
||||
result.Add(playoutItem);
|
||||
}
|
||||
@@ -493,7 +493,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
|
||||
? remainingToFill
|
||||
: remainingToFill / (effectiveChapters.Count - 1);
|
||||
TimeSpan filled = TimeSpan.Zero;
|
||||
for (var i = 0; i < chapters.Count; i++)
|
||||
for (var i = 0; i < effectiveChapters.Count; i++)
|
||||
{
|
||||
result.Add(playoutItem.ForChapter(effectiveChapters[i]));
|
||||
if (i < effectiveChapters.Count - 1)
|
||||
@@ -650,7 +650,7 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
|
||||
return result;
|
||||
}
|
||||
|
||||
private Option<PlayoutItem> FallbackFillerForPad(
|
||||
private static Option<PlayoutItem> FallbackFillerForPad(
|
||||
PlayoutBuilderState playoutBuilderState,
|
||||
Dictionary<CollectionKey, IMediaCollectionEnumerator> enumerators,
|
||||
ProgramScheduleItem scheduleItem,
|
||||
|
||||
Reference in New Issue
Block a user