BililiveRecorder/BililiveRecorder.Flv/Pipeline/Rules/HandleDelayedAudioHeaderRule.cs

80 lines
3.2 KiB
C#
Raw Normal View History

2021-03-09 00:50:13 +08:00
using System;
using System.Collections.Generic;
2021-02-23 18:03:37 +08:00
using System.Linq;
using BililiveRecorder.Flv.Pipeline.Actions;
using StructLinq;
2021-02-23 18:03:37 +08:00
namespace BililiveRecorder.Flv.Pipeline.Rules
{
/// <summary>
/// 处理延后收到的音频头
/// </summary>
/// <remarks>
/// 本规则应该放在所有规则前面
/// </remarks>
2021-03-09 00:50:13 +08:00
public class HandleDelayedAudioHeaderRule : ISimpleProcessingRule
2021-02-23 18:03:37 +08:00
{
private static readonly ProcessingComment comment1 = new ProcessingComment(CommentType.Unrepairable, "音频数据出现在音频头之前");
private static readonly ProcessingComment comment2 = new ProcessingComment(CommentType.DecodingHeader, "检测到延后收到的音频头");
2021-02-27 20:44:04 +08:00
2021-03-09 00:50:13 +08:00
public void Run(FlvProcessingContext context, Action next)
2021-02-23 18:03:37 +08:00
{
2021-03-09 00:50:13 +08:00
context.PerActionRun(this.RunPerAction);
next();
2021-02-23 18:03:37 +08:00
}
2021-03-09 00:50:13 +08:00
private IEnumerable<PipelineAction?> RunPerAction(FlvProcessingContext context, PipelineAction action)
2021-02-23 18:03:37 +08:00
{
2021-03-09 00:50:13 +08:00
if (action is PipelineDataAction data)
2021-02-23 18:03:37 +08:00
{
2021-03-09 00:50:13 +08:00
var tags = data.Tags;
// 如果分组内含有 Heaer
if (tags.ToStructEnumerable().Any(ref LinqFunctions.TagIsHeader, x => x))
2021-02-23 18:03:37 +08:00
{
2021-03-09 00:50:13 +08:00
{
var shouldReportError = false;
for (var i = tags.Count - 1; i >= 0; i--)
2021-03-09 00:50:13 +08:00
{
if (tags[i].Type == TagType.Audio)
{
if (tags[i].Flag != TagFlag.None)
{
// 发现了 Audio Header
shouldReportError = true;
}
else
{
// 在一段数据内 Header 之前出现了音频数据
if (shouldReportError)
{
context.AddComment(comment1);
yield return PipelineDisconnectAction.Instance;
yield return PipelineNewFileAction.Instance;
yield return null;
yield break;
}
}
}
2021-03-09 00:50:13 +08:00
}
}
context.AddComment(comment2);
var headerTags = tags.ToStructEnumerable().Where(ref LinqFunctions.TagIsHeader, x => x).ToArray();
2021-03-09 00:50:13 +08:00
var newHeaderAction = new PipelineHeaderAction(headerTags);
var dataTags = tags.ToStructEnumerable().Except(headerTags.ToStructEnumerable(), x => x, x => x).ToArray();
2021-03-09 00:50:13 +08:00
var newDataAction = new PipelineDataAction(dataTags);
yield return newHeaderAction;
yield return newDataAction;
2021-02-23 18:03:37 +08:00
}
2021-03-09 00:50:13 +08:00
else
yield return data;
2021-02-23 18:03:37 +08:00
}
2021-03-09 00:50:13 +08:00
else
yield return action;
2021-02-23 18:03:37 +08:00
}
}
}