mirror of
https://github.com/BililiveRecorder/BililiveRecorder.git
synced 2024-11-16 03:32:20 +08:00
FLV: Small adjustments
This commit is contained in:
parent
0f70c6c78d
commit
dd7266a54f
|
@ -127,6 +127,8 @@ csharp_style_var_elsewhere = true:suggestion
|
|||
csharp_style_var_for_built_in_types = true:suggestion
|
||||
#prefer var when the type is already mentioned on the right-hand side of a declaration expression
|
||||
csharp_style_var_when_type_is_apparent = true:suggestion
|
||||
# IDE0090: Use 'new(...)'
|
||||
csharp_style_implicit_object_creation_when_type_is_apparent = false:suggestion
|
||||
|
||||
#Style - language keyword and framework type options
|
||||
|
||||
|
|
|
@ -7,11 +7,8 @@ using StructLinq;
|
|||
namespace BililiveRecorder.Flv.Pipeline.Rules
|
||||
{
|
||||
/// <summary>
|
||||
/// 处理延后收到的音频头
|
||||
/// 处理延后收到的音频头,移动到音视频数据的前面。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 本规则应该放在所有规则前面
|
||||
/// </remarks>
|
||||
public class HandleDelayedAudioHeaderRule : ISimpleProcessingRule
|
||||
{
|
||||
private static readonly ProcessingComment comment1 = new ProcessingComment(CommentType.Unrepairable, "音频数据出现在音频头之前");
|
||||
|
|
|
@ -5,7 +5,7 @@ using BililiveRecorder.Flv.Pipeline.Actions;
|
|||
namespace BililiveRecorder.Flv.Pipeline.Rules
|
||||
{
|
||||
/// <summary>
|
||||
/// 处理 end tag
|
||||
/// 处理 End Tag,遇到的时候对文件进行分段
|
||||
/// </summary>
|
||||
public class HandleEndTagRule : ISimpleProcessingRule
|
||||
{
|
||||
|
|
|
@ -8,14 +8,8 @@ using StructLinq.Where;
|
|||
namespace BililiveRecorder.Flv.Pipeline.Rules
|
||||
{
|
||||
/// <summary>
|
||||
/// 处理收到音视频 Header 的情况
|
||||
/// 处理音视频 Header。收到音视频 Header 时检查与上一组是否相同,并根据情况删除重复的 Header 或新建文件。<br/>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 当收到音视频 Header 时检查与上一组是否相同<br/>
|
||||
/// 并根据情况删除重复的 Header 或新建文件写入<br/>
|
||||
/// <br/>
|
||||
/// 本规则为一般规则
|
||||
/// </remarks>
|
||||
public class HandleNewHeaderRule : ISimpleProcessingRule
|
||||
{
|
||||
private const string VIDEO_HEADER_KEY = "HandleNewHeaderRule_VideoHeader";
|
||||
|
|
|
@ -6,11 +6,8 @@ using BililiveRecorder.Flv.Pipeline.Actions;
|
|||
namespace BililiveRecorder.Flv.Pipeline.Rules
|
||||
{
|
||||
/// <summary>
|
||||
/// 处理收到 Script Tag 的情况
|
||||
/// 处理 Script Tag
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 本规则为一般规则
|
||||
/// </remarks>
|
||||
public class HandleNewScriptRule : ISimpleProcessingRule
|
||||
{
|
||||
private const string onMetaData = "onMetaData";
|
||||
|
|
|
@ -8,13 +8,8 @@ using StructLinq;
|
|||
namespace BililiveRecorder.Flv.Pipeline.Rules
|
||||
{
|
||||
/// <summary>
|
||||
/// 删除重复的直播数据
|
||||
/// 删除重复的直播数据。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 通过对比直播数据的特征,删除重复的直播数据<br/>
|
||||
/// <br/>
|
||||
/// 本规则为一般规则
|
||||
/// </remarks>
|
||||
public class RemoveDuplicatedChunkRule : ISimpleProcessingRule
|
||||
{
|
||||
private const int MAX_HISTORY = 8;
|
||||
|
@ -39,6 +34,7 @@ namespace BililiveRecorder.Flv.Pipeline.Rules
|
|||
|
||||
unchecked
|
||||
{
|
||||
// TODO: 改成用 Hash 判断
|
||||
// 计算一个特征码
|
||||
// 此处并没有遵循什么特定的算法,只是随便取了一些代表性比较强的值,用简单又尽量可靠的方式糅合到一起而已
|
||||
foreach (var tag in data.Tags)
|
||||
|
|
|
@ -4,14 +4,8 @@ using BililiveRecorder.Flv.Pipeline.Actions;
|
|||
namespace BililiveRecorder.Flv.Pipeline.Rules
|
||||
{
|
||||
/// <summary>
|
||||
/// 删除 H.264 Filler Data
|
||||
/// 删除 H.264 Filler Data,节省硬盘空间。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 部分直播码率瞎填的主播的直播数据中存在大量无用的 Filler Data<br/>
|
||||
/// 录制这些主播时删除这些数据可以节省硬盘空间<br/>
|
||||
/// <br/>
|
||||
/// 本规则应该放在一般规则前面
|
||||
/// </remarks>
|
||||
public class RemoveFillerDataRule : ISimpleProcessingRule
|
||||
{
|
||||
public void Run(FlvProcessingContext context, Action next)
|
||||
|
|
|
@ -7,6 +7,9 @@ using StructLinq;
|
|||
|
||||
namespace BililiveRecorder.Flv.Pipeline.Rules
|
||||
{
|
||||
/// <summary>
|
||||
/// 修复时间戳跳变
|
||||
/// </summary>
|
||||
public class UpdateTimestampJumpRule : ISimpleProcessingRule
|
||||
{
|
||||
private const string TS_STORE_KEY = "Timestamp_Store_Key";
|
||||
|
@ -25,12 +28,14 @@ namespace BililiveRecorder.Flv.Pipeline.Rules
|
|||
{
|
||||
next();
|
||||
|
||||
// 之前直播流的时间戳信息保存在 SessionItems 里
|
||||
var ts = context.SessionItems.ContainsKey(TS_STORE_KEY) ? context.SessionItems[TS_STORE_KEY] as TimestampStore ?? new TimestampStore() : new TimestampStore();
|
||||
context.SessionItems[TS_STORE_KEY] = ts;
|
||||
|
||||
// 按顺序处理每个 Action
|
||||
foreach (var action in context.Actions)
|
||||
{
|
||||
if (action is PipelineDataAction dataAction)
|
||||
if (action is PipelineDataAction dataAction) // 如果是直播数据,计算并调整时间戳
|
||||
{ // SetDataTimestamp
|
||||
var tags = dataAction.Tags;
|
||||
var currentTimestamp = tags[0].Timestamp;
|
||||
|
@ -53,7 +58,7 @@ namespace BililiveRecorder.Flv.Pipeline.Rules
|
|||
|
||||
ts.NextTimestampTarget = this.CalculateNewTarget(tags);
|
||||
}
|
||||
else if (action is PipelineEndAction endAction)
|
||||
else if (action is PipelineEndAction endAction) // End Tag 其实怎么处理都无所谓
|
||||
{
|
||||
var tag = endAction.Tag;
|
||||
var diff = tag.Timestamp - ts.LastOriginal;
|
||||
|
@ -66,16 +71,16 @@ namespace BililiveRecorder.Flv.Pipeline.Rules
|
|||
tag.Timestamp -= ts.CurrentOffset;
|
||||
}
|
||||
}
|
||||
else if (action is PipelineNewFileAction)
|
||||
else if (action is PipelineNewFileAction) // 如果新建文件分段了,重设时间戳信息重新从 0 开始
|
||||
{
|
||||
ts.Reset();
|
||||
}
|
||||
else if (action is PipelineScriptAction s)
|
||||
else if (action is PipelineScriptAction s) // Script Tag 时间戳永远为 0
|
||||
{
|
||||
s.Tag.Timestamp = 0;
|
||||
ts.Reset();
|
||||
}
|
||||
else if (action is PipelineHeaderAction h)
|
||||
else if (action is PipelineHeaderAction h) // Header Tag 时间戳永远为 0
|
||||
{
|
||||
if (h.VideoHeader != null)
|
||||
h.VideoHeader.Timestamp = 0;
|
||||
|
@ -86,6 +91,7 @@ namespace BililiveRecorder.Flv.Pipeline.Rules
|
|||
}
|
||||
}
|
||||
|
||||
// 计算理想情况下这段数据后面下一个 Tag 的时间戳应该是多少
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private int CalculateNewTarget(IReadOnlyList<Tag> tags)
|
||||
{
|
||||
|
@ -123,10 +129,19 @@ namespace BililiveRecorder.Flv.Pipeline.Rules
|
|||
|
||||
private class TimestampStore
|
||||
{
|
||||
/// <summary>
|
||||
/// 下一个 Tag 的目标时间戳
|
||||
/// </summary>
|
||||
public int NextTimestampTarget;
|
||||
|
||||
/// <summary>
|
||||
/// 上一个 Tag 的原始时间戳
|
||||
/// </summary>
|
||||
public int LastOriginal;
|
||||
|
||||
/// <summary>
|
||||
/// 当前时间戳偏移量
|
||||
/// </summary>
|
||||
public int CurrentOffset;
|
||||
|
||||
public void Reset()
|
||||
|
|
|
@ -7,10 +7,13 @@ using StructLinq;
|
|||
|
||||
namespace BililiveRecorder.Flv.Pipeline.Rules
|
||||
{
|
||||
/// <summary>
|
||||
/// 修复时间戳错位
|
||||
/// </summary>
|
||||
public class UpdateTimestampOffsetRule : ISimpleProcessingRule
|
||||
{
|
||||
private static readonly ProcessingComment comment1 = new ProcessingComment(CommentType.Unrepairable, "GOP 内音频或视频时间戳不连续");
|
||||
private static readonly ProcessingComment comment2 = new ProcessingComment(CommentType.Unrepairable, "出现了无法计算偏移量的音视频偏移");
|
||||
private static readonly ProcessingComment COMMENT_JumpedWithinGOP = new ProcessingComment(CommentType.Unrepairable, "GOP 内音频或视频时间戳不连续");
|
||||
private static readonly ProcessingComment COMMENT_CantSolve = new ProcessingComment(CommentType.Unrepairable, "出现了无法计算偏移量的音视频偏移");
|
||||
|
||||
public void Run(FlvProcessingContext context, Action next)
|
||||
{
|
||||
|
@ -18,9 +21,12 @@ namespace BililiveRecorder.Flv.Pipeline.Rules
|
|||
next();
|
||||
}
|
||||
|
||||
private readonly struct IsNotNormal : ITwoInputFunction<Tag, bool>
|
||||
/// <summary>
|
||||
/// 检查 Tag 时间戳是否有变小的情况
|
||||
/// </summary>
|
||||
private readonly struct IsNextTimestampSmaller : ITwoInputFunction<Tag, bool>
|
||||
{
|
||||
public static IsNotNormal Instance;
|
||||
public static IsNextTimestampSmaller Instance;
|
||||
public bool Eval(Tag a, Tag b) => a.Timestamp > b.Timestamp;
|
||||
}
|
||||
|
||||
|
@ -28,19 +34,19 @@ namespace BililiveRecorder.Flv.Pipeline.Rules
|
|||
{
|
||||
if (action is PipelineDataAction data)
|
||||
{
|
||||
var isNotNormal = data.Tags.Any2(ref IsNotNormal.Instance);
|
||||
var isNotNormal = data.Tags.Any2(ref IsNextTimestampSmaller.Instance);
|
||||
if (!isNotNormal)
|
||||
{
|
||||
// 没有问题
|
||||
// 没有问题,每个 tag 的时间戳都 >= 上一个 tag 的时间戳。
|
||||
yield return data;
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (data.Tags.Where(x => x.Type == TagType.Audio).Any2(ref IsNotNormal.Instance) || data.Tags.Where(x => x.Type == TagType.Video).Any2(ref IsNotNormal.Instance))
|
||||
if (data.Tags.Where(x => x.Type == TagType.Audio).Any2(ref IsNextTimestampSmaller.Instance) || data.Tags.Where(x => x.Type == TagType.Video).Any2(ref IsNextTimestampSmaller.Instance))
|
||||
{
|
||||
// 音频或视频自身就有问题,没救了
|
||||
yield return PipelineDisconnectAction.Instance;
|
||||
context.AddComment(comment1);
|
||||
context.AddComment(COMMENT_JumpedWithinGOP);
|
||||
yield break;
|
||||
}
|
||||
else
|
||||
|
@ -150,7 +156,7 @@ namespace BililiveRecorder.Flv.Pipeline.Rules
|
|||
yield break;
|
||||
|
||||
invalidOffset:
|
||||
context.AddComment(comment2);
|
||||
context.AddComment(COMMENT_CantSolve);
|
||||
yield return PipelineDisconnectAction.Instance;
|
||||
yield break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user