2021-02-23 18:03:37 +08:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Linq;
|
|
|
|
using BililiveRecorder.Core.Event;
|
|
|
|
using BililiveRecorder.Flv;
|
|
|
|
using BililiveRecorder.Flv.Pipeline;
|
2021-04-29 23:51:06 +08:00
|
|
|
using BililiveRecorder.Flv.Pipeline.Actions;
|
|
|
|
using StructLinq;
|
2021-02-23 18:03:37 +08:00
|
|
|
|
|
|
|
namespace BililiveRecorder.Core.ProcessingRules
|
|
|
|
{
|
2022-05-16 23:28:31 +08:00
|
|
|
internal class StatsRule : ISimpleProcessingRule
|
2021-02-23 18:03:37 +08:00
|
|
|
{
|
2021-02-27 13:28:21 +08:00
|
|
|
public const string SkipStatsKey = nameof(SkipStatsKey);
|
|
|
|
|
2022-04-09 16:43:05 +08:00
|
|
|
public StatsRule(DateTimeOffset? RecordingStart = null)
|
|
|
|
{
|
|
|
|
this.RecordingStart = RecordingStart ?? DateTimeOffset.Now;
|
|
|
|
}
|
|
|
|
|
2021-02-23 18:03:37 +08:00
|
|
|
public event EventHandler<RecordingStatsEventArgs>? StatsUpdated;
|
|
|
|
|
|
|
|
public long TotalInputVideoByteCount { get; private set; }
|
|
|
|
public long TotalInputAudioByteCount { get; private set; }
|
|
|
|
|
|
|
|
public int TotalOutputVideoFrameCount { get; private set; }
|
|
|
|
public int TotalOutputAudioFrameCount { get; private set; }
|
|
|
|
public long TotalOutputVideoByteCount { get; private set; }
|
|
|
|
public long TotalOutputAudioByteCount { get; private set; }
|
|
|
|
|
2021-08-04 21:58:35 +08:00
|
|
|
public long CurrentFileSize { get; private set; } = 13;
|
2021-02-27 13:28:21 +08:00
|
|
|
|
2021-02-23 18:03:37 +08:00
|
|
|
public int SumOfMaxTimestampOfClosedFiles { get; private set; }
|
|
|
|
public int CurrentFileMaxTimestamp { get; private set; }
|
|
|
|
|
|
|
|
public DateTimeOffset LastWriteTime { get; private set; }
|
2022-04-09 16:43:05 +08:00
|
|
|
public DateTimeOffset RecordingStart { get; }
|
2021-02-23 18:03:37 +08:00
|
|
|
|
2021-03-09 01:04:31 +08:00
|
|
|
public void Run(FlvProcessingContext context, Action next)
|
2021-02-23 18:03:37 +08:00
|
|
|
{
|
2022-04-09 16:43:05 +08:00
|
|
|
var e = new RecordingStatsEventArgs
|
|
|
|
{
|
|
|
|
SessionDuration = (DateTimeOffset.Now - this.RecordingStart).TotalMilliseconds
|
|
|
|
};
|
2021-02-23 18:03:37 +08:00
|
|
|
|
2021-04-29 23:51:06 +08:00
|
|
|
{
|
|
|
|
static IEnumerable<PipelineDataAction> FilterDataActions(IEnumerable<PipelineAction> actions)
|
|
|
|
{
|
|
|
|
foreach (var action in actions)
|
|
|
|
if (action is PipelineDataAction dataAction)
|
|
|
|
yield return dataAction;
|
|
|
|
}
|
|
|
|
|
2022-04-09 16:43:05 +08:00
|
|
|
e.TotalInputVideoBytes = this.TotalInputVideoByteCount += e.InputVideoBytes =
|
2021-04-29 23:51:06 +08:00
|
|
|
FilterDataActions(context.Actions).ToStructEnumerable().Sum(ref LinqFunctions.SumSizeOfVideoData, x => x, x => x);
|
|
|
|
|
2022-04-09 16:43:05 +08:00
|
|
|
e.TotalInputAudioBytes = this.TotalInputAudioByteCount += e.InputAudioBytes =
|
2021-04-29 23:51:06 +08:00
|
|
|
FilterDataActions(context.Actions).ToStructEnumerable().Sum(ref LinqFunctions.SumSizeOfAudioData, x => x, x => x);
|
2022-04-09 16:43:05 +08:00
|
|
|
|
|
|
|
e.TotalInputBytes = e.TotalInputVideoBytes + e.TotalInputAudioBytes;
|
2021-04-29 23:51:06 +08:00
|
|
|
}
|
2021-02-23 18:03:37 +08:00
|
|
|
|
2021-03-09 01:04:31 +08:00
|
|
|
next();
|
2021-02-23 18:03:37 +08:00
|
|
|
|
|
|
|
var groups = new List<List<PipelineDataAction>?>();
|
|
|
|
{
|
|
|
|
List<PipelineDataAction>? curr = null;
|
2021-03-09 00:50:13 +08:00
|
|
|
foreach (var action in context.Actions)
|
2021-02-23 18:03:37 +08:00
|
|
|
{
|
|
|
|
if (action is PipelineDataAction dataAction)
|
|
|
|
{
|
|
|
|
if (curr is null)
|
|
|
|
{
|
|
|
|
curr = new List<PipelineDataAction>();
|
|
|
|
groups.Add(curr);
|
|
|
|
}
|
|
|
|
curr.Add(dataAction);
|
|
|
|
}
|
|
|
|
else if (action is PipelineNewFileAction)
|
|
|
|
{
|
|
|
|
curr = null;
|
|
|
|
groups.Add(null);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach (var item in groups)
|
|
|
|
{
|
|
|
|
if (item is null)
|
|
|
|
NewFile();
|
|
|
|
else
|
|
|
|
CalcStats(e, item);
|
|
|
|
}
|
|
|
|
|
|
|
|
var now = DateTimeOffset.UtcNow;
|
2022-04-09 16:43:05 +08:00
|
|
|
e.PassedTime = (now - this.LastWriteTime).TotalMilliseconds;
|
2021-02-23 18:03:37 +08:00
|
|
|
this.LastWriteTime = now;
|
2021-08-04 21:58:35 +08:00
|
|
|
e.DurationRatio = e.AddedDuration / e.PassedTime;
|
2021-02-23 18:03:37 +08:00
|
|
|
|
|
|
|
StatsUpdated?.Invoke(this, e);
|
|
|
|
|
|
|
|
return;
|
|
|
|
void CalcStats(RecordingStatsEventArgs e, IReadOnlyList<PipelineDataAction> dataActions)
|
|
|
|
{
|
|
|
|
if (dataActions.Count > 0)
|
|
|
|
{
|
2022-04-09 16:43:05 +08:00
|
|
|
e.TotalOutputVideoFrames = this.TotalOutputVideoFrameCount += e.OutputVideoFrames =
|
2021-04-29 23:51:06 +08:00
|
|
|
dataActions.ToStructEnumerable().Sum(ref LinqFunctions.CountVideoTags, x => x, x => x);
|
|
|
|
|
2022-04-09 16:43:05 +08:00
|
|
|
e.TotalOutputAudioFrames = this.TotalOutputAudioFrameCount += e.OutputAudioFrames =
|
2021-04-29 23:51:06 +08:00
|
|
|
dataActions.ToStructEnumerable().Sum(ref LinqFunctions.CountAudioTags, x => x, x => x);
|
|
|
|
|
2022-04-09 16:43:05 +08:00
|
|
|
e.TotalOutputVideoBytes = this.TotalOutputVideoByteCount += e.OutputVideoBytes =
|
2021-04-29 23:51:06 +08:00
|
|
|
dataActions.ToStructEnumerable().Sum(ref LinqFunctions.SumSizeOfVideoDataByNalu, x => x, x => x);
|
|
|
|
|
2022-04-09 16:43:05 +08:00
|
|
|
e.TotalOutputAudioBytes = this.TotalOutputAudioByteCount += e.OutputAudioBytes =
|
2021-04-29 23:51:06 +08:00
|
|
|
dataActions.ToStructEnumerable().Sum(ref LinqFunctions.SumSizeOfAudioData, x => x, x => x);
|
2021-02-23 18:03:37 +08:00
|
|
|
|
2022-04-09 16:43:05 +08:00
|
|
|
e.TotalOutputBytes = e.TotalOutputAudioBytes + e.TotalOutputVideoBytes;
|
|
|
|
|
|
|
|
e.CurrentFileSize = this.CurrentFileSize += e.OutputVideoBytes + e.OutputAudioBytes;
|
2021-02-23 18:03:37 +08:00
|
|
|
|
2021-02-27 13:28:21 +08:00
|
|
|
foreach (var action in dataActions)
|
|
|
|
{
|
|
|
|
var tags = action.Tags;
|
|
|
|
if (tags.Count > 0)
|
|
|
|
{
|
2022-04-09 16:43:05 +08:00
|
|
|
e.AddedDuration += (tags[tags.Count - 1].Timestamp - tags[0].Timestamp);
|
2021-02-27 13:28:21 +08:00
|
|
|
this.CurrentFileMaxTimestamp = e.FileMaxTimestamp = tags[tags.Count - 1].Timestamp;
|
|
|
|
}
|
|
|
|
}
|
2021-02-23 18:03:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
e.SessionMaxTimestamp = this.SumOfMaxTimestampOfClosedFiles + this.CurrentFileMaxTimestamp;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NewFile()
|
|
|
|
{
|
|
|
|
this.SumOfMaxTimestampOfClosedFiles += this.CurrentFileMaxTimestamp;
|
|
|
|
this.CurrentFileMaxTimestamp = 0;
|
2021-08-04 21:58:35 +08:00
|
|
|
this.CurrentFileSize = 13;
|
2021-02-23 18:03:37 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|