Browse Source

add linear fade functions to watermark opacity expression

pull/2276/head
Jason Dove 3 days ago
parent
commit
adec299136
No known key found for this signature in database
  1. 3
      CHANGELOG.md
  2. 76
      ErsatzTV.Infrastructure/Streaming/WatermarkElement.cs

3
CHANGELOG.md

@ -14,6 +14,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). @@ -14,6 +14,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- `content_total_seconds` - the total number of seconds in the content
- `channel_seconds` - the total number of seconds the frame is from when the channel started/activated
- `time_of_day_seconds` - the total number of seconds the frame is since midnight
- The expression can also use functions:
- `LinearFadeDuration(time, start, fadeSeconds, peakSeconds)`
- `LinearFadePoints(time, start, peakStart, peakEnd, end)`
### Fix
- Fix database operations that were slowing down playout builds

76
ErsatzTV.Infrastructure/Streaming/WatermarkElement.cs

@ -4,6 +4,7 @@ using ErsatzTV.Core.FFmpeg; @@ -4,6 +4,7 @@ using ErsatzTV.Core.FFmpeg;
using ErsatzTV.Core.Interfaces.Streaming;
using ErsatzTV.FFmpeg.State;
using NCalc;
using NCalc.Handlers;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Gif;
using SixLabors.ImageSharp.Processing;
@ -68,6 +69,8 @@ public class WatermarkElement : IGraphicsElement, IDisposable @@ -68,6 +69,8 @@ public class WatermarkElement : IGraphicsElement, IDisposable
_expression = new Expression(opacity.ToString(CultureInfo.InvariantCulture));
}
_expression.EvaluateFunction += EvaluateFunction;
bool isRemoteUri = Uri.TryCreate(_imagePath, UriKind.Absolute, out var uriResult)
&& (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps);
@ -117,6 +120,40 @@ public class WatermarkElement : IGraphicsElement, IDisposable @@ -117,6 +120,40 @@ public class WatermarkElement : IGraphicsElement, IDisposable
}
}
private static void EvaluateFunction(string name, FunctionArgs args)
{
switch (name)
{
case "LinearFadePoints":
{
if (args.Parameters.Length != 5)
throw new ArgumentException("LinearFadePoints() requires 5 arguments.");
double time = Convert.ToDouble(args.Parameters[0].Evaluate(), CultureInfo.CurrentCulture);
double start = Convert.ToDouble(args.Parameters[1].Evaluate(), CultureInfo.CurrentCulture);
double peakStart = Convert.ToDouble(args.Parameters[2].Evaluate(), CultureInfo.CurrentCulture);
double peakEnd = Convert.ToDouble(args.Parameters[3].Evaluate(), CultureInfo.CurrentCulture);
double end = Convert.ToDouble(args.Parameters[4].Evaluate(), CultureInfo.CurrentCulture);
args.Result = LinearFadePoints(time, start, peakStart, peakEnd, end);
break;
}
case "LinearFadeDuration":
{
if (args.Parameters.Length != 4)
throw new ArgumentException("LinearFadeDuration() requires 4 arguments.");
double time = Convert.ToDouble(args.Parameters[0].Evaluate(), CultureInfo.CurrentCulture);
double start = Convert.ToDouble(args.Parameters[1].Evaluate(), CultureInfo.CurrentCulture);
double fadeSeconds = Convert.ToDouble(args.Parameters[2].Evaluate(), CultureInfo.CurrentCulture);
double peakSeconds = Convert.ToDouble(args.Parameters[3].Evaluate(), CultureInfo.CurrentCulture);
args.Result = LinearFadeDuration(time, start, fadeSeconds, peakSeconds);
break;
}
}
}
public void Draw(
object context,
TimeSpan timeOfDay,
@ -198,6 +235,45 @@ public class WatermarkElement : IGraphicsElement, IDisposable @@ -198,6 +235,45 @@ public class WatermarkElement : IGraphicsElement, IDisposable
};
}
private static double LinearFadePoints(double time, double start, double peakStart, double peakEnd, double end)
{
if (time < start || time >= end)
{
return 0;
}
// fade in
if (time < peakStart)
{
return (time - start) / (peakStart - start);
}
// solid
if (time < peakEnd)
{
return 1.0;
}
// fade out
return (end - time) / (end - peakEnd);
}
private static double LinearFadeDuration(double time, double start, double fadeSeconds, double peakSeconds)
{
// edge case with no fade
if (fadeSeconds <= 0)
{
double noFadeEnd = start + peakSeconds;
return (time >= start && time < noFadeEnd) ? 1.0 : 0.0;
}
double peakStart = start + fadeSeconds;
double peakEnd = peakStart + peakSeconds;
double end = peakEnd + fadeSeconds;
return LinearFadePoints(time, start, peakStart, peakEnd, end);
}
public void Dispose()
{
GC.SuppressFinalize(this);

Loading…
Cancel
Save