mirror of
https://github.com/BililiveRecorder/BililiveRecorder.git
synced 2024-11-16 11:42:22 +08:00
FLV: Update tag grouping
This commit is contained in:
parent
7c82019c5c
commit
68a6eaa275
|
@ -7,15 +7,17 @@ namespace BililiveRecorder.Flv.Grouping.Rules
|
|||
{
|
||||
public class DataGroupingRule : IGroupingRule
|
||||
{
|
||||
public bool StartWith(List<Tag> tags) => tags.Count > 0 && tags[0].IsData();
|
||||
public bool StartWith(Tag tag) => tag.IsData();
|
||||
|
||||
public bool AppendWith(Tag tag, List<Tag> tags, out List<Tag>? leftover)
|
||||
public bool AppendWith(Tag tag, LinkedList<Tag> tags, out LinkedList<Tag>? leftover)
|
||||
{
|
||||
var flag = tag.IsNonKeyframeData() || (tag.Type == TagType.Audio && tag.Flag == TagFlag.Header && tags.TrueForAll(x => x.Type != TagType.Audio));
|
||||
var flag = tag.IsNonKeyframeData()
|
||||
|| (tag.IsKeyframeData() && tags.All(x => x.IsNonKeyframeData()))
|
||||
|| (tag.Type == TagType.Audio && tag.Flag == TagFlag.Header && tags.All(x => x.Type != TagType.Audio || x.Flag == TagFlag.Header));
|
||||
|
||||
if (flag)
|
||||
{
|
||||
tags.Add(tag);
|
||||
tags.AddLast(tag);
|
||||
leftover = null;
|
||||
return true;
|
||||
}
|
||||
|
@ -23,25 +25,41 @@ namespace BililiveRecorder.Flv.Grouping.Rules
|
|||
{
|
||||
var ts = tag.Timestamp;
|
||||
var lastAudio = tags.LastOrDefault(x => x.Type == TagType.Audio);
|
||||
|
||||
bool predicate(Tag x) => x.Type == TagType.Audio && x.Timestamp >= ts;
|
||||
|
||||
if (tag.IsKeyframeData())
|
||||
if (tag.IsKeyframeData() && lastAudio is not null && Math.Abs(tag.Timestamp - lastAudio.Timestamp) <= 50 && tags.Any(predicate))
|
||||
{
|
||||
if (lastAudio is not null && Math.Abs(tag.Timestamp - lastAudio.Timestamp) <= 50 && tags.Any(predicate))
|
||||
{
|
||||
leftover = new List<Tag>();
|
||||
leftover.AddRange(tags.Where(predicate));
|
||||
leftover.Add(tag);
|
||||
tags.RemoveAll(predicate);
|
||||
return false;
|
||||
leftover = new LinkedList<Tag>();
|
||||
foreach (var item in tags.Where(predicate))
|
||||
leftover.AddLast(item);
|
||||
leftover.AddLast(tag);
|
||||
}
|
||||
|
||||
// tags.RemoveAll(predicate);
|
||||
{
|
||||
var node = tags.First;
|
||||
while (node != null)
|
||||
{
|
||||
var next = node.Next;
|
||||
if (predicate(node.Value))
|
||||
tags.Remove(node);
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
|
||||
leftover = new List<Tag> { tag };
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
leftover = new LinkedList<Tag>();
|
||||
leftover.AddLast(tag);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PipelineAction CreatePipelineAction(List<Tag> tags) => new PipelineDataAction(tags);
|
||||
public PipelineAction CreatePipelineAction(LinkedList<Tag> tags) => new PipelineDataAction(new List<Tag>(tags));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BililiveRecorder.Flv.Pipeline;
|
||||
|
||||
namespace BililiveRecorder.Flv.Grouping.Rules
|
||||
{
|
||||
public class EndGroupingRule : IGroupingRule
|
||||
{
|
||||
public bool StartWith(List<Tag> tags) => tags.Count == 1 && tags[0].IsEnd();
|
||||
public bool StartWith(Tag tag) => tag.IsEnd();
|
||||
|
||||
public bool AppendWith(Tag tag, List<Tag> tags, out List<Tag>? leftover)
|
||||
public bool AppendWith(Tag tag, LinkedList<Tag> tags, out LinkedList<Tag>? leftover)
|
||||
{
|
||||
leftover = new List<Tag> { tag };
|
||||
leftover = new LinkedList<Tag>();
|
||||
leftover.AddLast(tag);
|
||||
return false;
|
||||
}
|
||||
|
||||
public PipelineAction CreatePipelineAction(List<Tag> tags) => new PipelineEndAction(tags.First());
|
||||
public PipelineAction CreatePipelineAction(LinkedList<Tag> tags) => new PipelineEndAction(tags.First.Value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,23 +5,24 @@ namespace BililiveRecorder.Flv.Grouping.Rules
|
|||
{
|
||||
public class HeaderGroupingRule : IGroupingRule
|
||||
{
|
||||
public bool StartWith(List<Tag> tags) => tags.Count > 0 && tags.TrueForAll(x => x.IsHeader());
|
||||
public bool StartWith(Tag tag) => tag.IsHeader();
|
||||
|
||||
public bool AppendWith(Tag tag, List<Tag> tags, out List<Tag>? leftover)
|
||||
public bool AppendWith(Tag tag, LinkedList<Tag> tags, out LinkedList<Tag>? leftover)
|
||||
{
|
||||
if (tag.IsHeader())
|
||||
{
|
||||
tags.Add(tag);
|
||||
tags.AddLast(tag);
|
||||
leftover = null;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
leftover = new List<Tag> { tag };
|
||||
leftover = new LinkedList<Tag>();
|
||||
leftover.AddLast(tag);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public PipelineAction CreatePipelineAction(List<Tag> tags) => new PipelineHeaderAction(tags);
|
||||
public PipelineAction CreatePipelineAction(LinkedList<Tag> tags) => new PipelineHeaderAction(new List<Tag>(tags));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BililiveRecorder.Flv.Pipeline;
|
||||
|
||||
namespace BililiveRecorder.Flv.Grouping.Rules
|
||||
{
|
||||
public class ScriptGroupingRule : IGroupingRule
|
||||
{
|
||||
public bool StartWith(List<Tag> tags) => tags.Count == 1 && tags[0].IsScript();
|
||||
public bool StartWith(Tag tag) => tag.IsScript();
|
||||
|
||||
public bool AppendWith(Tag tag, List<Tag> tags, out List<Tag>? leftover)
|
||||
public bool AppendWith(Tag tag, LinkedList<Tag> tags, out LinkedList<Tag>? leftover)
|
||||
{
|
||||
leftover = new List<Tag> { tag };
|
||||
leftover = new LinkedList<Tag>();
|
||||
leftover.AddLast(tag);
|
||||
return false;
|
||||
}
|
||||
|
||||
public PipelineAction CreatePipelineAction(List<Tag> tags) => new PipelineScriptAction(tags.First());
|
||||
public PipelineAction CreatePipelineAction(LinkedList<Tag> tags) => new PipelineScriptAction(tags.First.Value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace BililiveRecorder.Flv.Grouping
|
|||
private readonly bool leaveOpen;
|
||||
private bool disposedValue;
|
||||
|
||||
private List<Tag>? leftover;
|
||||
private LinkedList<Tag>? leftover;
|
||||
|
||||
public IFlvTagReader TagReader { get; }
|
||||
public IList<IGroupingRule> GroupingRules { get; }
|
||||
|
@ -45,39 +45,65 @@ namespace BililiveRecorder.Flv.Grouping
|
|||
}
|
||||
try
|
||||
{
|
||||
List<Tag> tags;
|
||||
LinkedList<Tag>? queue = null;
|
||||
Tag? firstTag;
|
||||
|
||||
if (this.leftover is not null)
|
||||
if (this.leftover is not null && this.leftover.Count > 0)
|
||||
{
|
||||
tags = this.leftover;
|
||||
queue = this.leftover;
|
||||
this.leftover = null;
|
||||
|
||||
firstTag = queue.First.Value;
|
||||
queue.RemoveFirst();
|
||||
}
|
||||
else
|
||||
{
|
||||
var firstTag = await this.TagReader.ReadTagAsync(token).ConfigureAwait(false);
|
||||
firstTag = await this.TagReader.ReadTagAsync(token).ConfigureAwait(false);
|
||||
|
||||
// 数据已经全部读完
|
||||
if (firstTag is null)
|
||||
return null;
|
||||
|
||||
tags = new List<Tag> { firstTag };
|
||||
}
|
||||
|
||||
var rule = this.GroupingRules.FirstOrDefault(x => x.StartWith(tags));
|
||||
var rule = this.GroupingRules.FirstOrDefault(x => x.StartWith(firstTag));
|
||||
|
||||
if (rule is null)
|
||||
throw new Exception("No grouping rule accepting tags:\n" + string.Join("\n", tags.Select(x => x.ToString())));
|
||||
throw new Exception("No grouping rule accepting tags: " + firstTag.ToString());
|
||||
|
||||
var tags = new LinkedList<Tag>();
|
||||
tags.AddLast(firstTag);
|
||||
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
var tag = await this.TagReader.ReadTagAsync(token).ConfigureAwait(false);
|
||||
Tag? tag;
|
||||
|
||||
if (queue is not null && queue.Count > 0)
|
||||
{
|
||||
tag = queue.First.Value;
|
||||
queue.RemoveFirst();
|
||||
}
|
||||
else
|
||||
{
|
||||
tag = await this.TagReader.ReadTagAsync(token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (tag == null || !rule.AppendWith(tag, tags, out this.leftover))
|
||||
{
|
||||
if (queue is not null && queue.Count > 0)
|
||||
{
|
||||
if (this.leftover is null)
|
||||
this.leftover = queue;
|
||||
else
|
||||
foreach (var item in queue)
|
||||
this.leftover.AddLast(item);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tags.Count == 0)
|
||||
throw new Exception("TagGroup tag count is 0");
|
||||
|
||||
return rule.CreatePipelineAction(tags);
|
||||
}
|
||||
finally
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace BililiveRecorder.Flv
|
|||
/// </summary>
|
||||
/// <param name="tags">Current Tags</param>
|
||||
/// <returns></returns>
|
||||
bool StartWith(List<Tag> tags);
|
||||
bool StartWith(Tag tag);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
|
@ -19,8 +19,8 @@ namespace BililiveRecorder.Flv
|
|||
/// <param name="tags">List of tags</param>
|
||||
/// <param name="leftover"></param>
|
||||
/// <returns></returns>
|
||||
bool AppendWith(Tag tag, List<Tag> tags, out List<Tag>? leftover);
|
||||
bool AppendWith(Tag tag, LinkedList<Tag> tags, out LinkedList<Tag>? leftover);
|
||||
|
||||
PipelineAction CreatePipelineAction(List<Tag> tags);
|
||||
PipelineAction CreatePipelineAction(LinkedList<Tag> tags);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user