From 19c529c2599705ee84a2c3d59e4742c4e14b15da Mon Sep 17 00:00:00 2001 From: Genteure Date: Sun, 1 Dec 2024 19:28:19 +0800 Subject: [PATCH] fix: timestamp processing with h264 annex b (#627) * fix: timestamp processing with h264 annex b * fix: mark comment as no action required * enable logging for tool commands --- BililiveRecorder.Cli/Program.cs | 38 ++++++++++++++++++- .../Pipeline/Rules/HandleNewHeaderRule.cs | 17 ++++++--- .../Pipeline/Rules/UpdateTimestampJumpRule.cs | 16 +++++--- 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/BililiveRecorder.Cli/Program.cs b/BililiveRecorder.Cli/Program.cs index c8a5c0c..29f351f 100644 --- a/BililiveRecorder.Cli/Program.cs +++ b/BililiveRecorder.Cli/Program.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; using System.CommandLine; +using System.CommandLine.Builder; using System.CommandLine.NamingConventionBinder; +using System.CommandLine.Parsing; using System.Diagnostics; using System.IO; using System.Linq; @@ -119,7 +121,41 @@ namespace BililiveRecorder.Cli } } - return root.Invoke(args); + var builder = new CommandLineBuilder(root); + + builder.AddMiddleware(async (context, next) => + { + var isToolCommand = false; + var tct = typeof(ToolCommand); + var cr = context.ParseResult.CommandResult; + while (cr is not null) + { + if (cr.Command.GetType() == tct) + { + isToolCommand = true; + break; + } + cr = cr.Parent as CommandResult; + } + cr = null; + + if (isToolCommand) + { + // hack to enable logging for tool commands + using var logger = BuildLogger(LogEventLevel.Fatal, LogEventLevel.Verbose); + Log.Logger = logger; + await next(context); + return; + } + else + { + await next(context); + } + }); + + builder.UseDefaults(); + var parser = builder.Build(); + return parser.Invoke(args); } private static async Task RunConfigModeAsync(RunModeArguments args) diff --git a/BililiveRecorder.Flv/Pipeline/Rules/HandleNewHeaderRule.cs b/BililiveRecorder.Flv/Pipeline/Rules/HandleNewHeaderRule.cs index 020f694..b6b420b 100644 --- a/BililiveRecorder.Flv/Pipeline/Rules/HandleNewHeaderRule.cs +++ b/BililiveRecorder.Flv/Pipeline/Rules/HandleNewHeaderRule.cs @@ -17,7 +17,7 @@ namespace BililiveRecorder.Flv.Pipeline.Rules private const string AUDIO_HEADER_KEY = "HandleNewHeaderRule_AudioHeader"; private const string ANNEXB_KEY = "HandleNewHeaderRule_AnnexB"; - private enum AnnexBState + public enum AnnexBState { Unknown, Pending, @@ -26,8 +26,8 @@ namespace BililiveRecorder.Flv.Pipeline.Rules private static readonly ProcessingComment MultipleHeaderComment = new ProcessingComment(CommentType.DecodingHeader, true, "收到了连续多个 Header,新建文件"); private static readonly ProcessingComment SplitFileComment = new ProcessingComment(CommentType.DecodingHeader, true, "因为 Header 问题新建文件"); - private static readonly ProcessingComment AnnexBCommentFirst = new ProcessingComment(CommentType.DecodingHeader, true, "检测到一次 AnnexB 格式"); - private static readonly ProcessingComment AnnexBComment = new ProcessingComment(CommentType.DecodingHeader, true, "检测到 AnnexB 格式,不再切割文件"); + private static readonly ProcessingComment AnnexBCommentFirst = new ProcessingComment(CommentType.DecodingHeader, false, "检测到一次 AnnexB 格式"); + private static readonly ProcessingComment AnnexBComment = new ProcessingComment(CommentType.DecodingHeader, false, "检测到 AnnexB 格式,不再切割文件"); private readonly bool disableSplitOnH264AnnexB; @@ -42,12 +42,18 @@ namespace BililiveRecorder.Flv.Pipeline.Rules next(); } + public static AnnexBState GetAnnexBState(FlvProcessingContext context) + { + if (context.SessionItems.TryGetValue(ANNEXB_KEY, out var annexBStateObj)) + return annexBStateObj is AnnexBState annexBState ? annexBState : AnnexBState.Unknown; + return AnnexBState.Unknown; + } + private IEnumerable RunPerAction(FlvProcessingContext context, PipelineAction action) { if (this.disableSplitOnH264AnnexB) { - context.SessionItems.TryGetValue(ANNEXB_KEY, out var annexBStateObj); - var state = annexBStateObj is AnnexBState annexBState ? annexBState : AnnexBState.Unknown; + var state = GetAnnexBState(context); if (state == AnnexBState.IsAnnexB) { @@ -56,6 +62,7 @@ namespace BililiveRecorder.Flv.Pipeline.Rules yield break; } + // 检测 Annex B 格式 if (action is PipelineDataAction data) { var annexb = false; diff --git a/BililiveRecorder.Flv/Pipeline/Rules/UpdateTimestampJumpRule.cs b/BililiveRecorder.Flv/Pipeline/Rules/UpdateTimestampJumpRule.cs index 6be3748..7b1a7d4 100644 --- a/BililiveRecorder.Flv/Pipeline/Rules/UpdateTimestampJumpRule.cs +++ b/BililiveRecorder.Flv/Pipeline/Rules/UpdateTimestampJumpRule.cs @@ -95,13 +95,17 @@ namespace BililiveRecorder.Flv.Pipeline.Rules s.Tag.Timestamp = ts.NextTimestampTarget; // ts.Reset(); } - else if (action is PipelineHeaderAction h) // Header Tag 时间戳永远为 0 + else if (action is PipelineHeaderAction h) { - if (h.VideoHeader != null) - h.VideoHeader.Timestamp = 0; - if (h.AudioHeader != null) - h.AudioHeader.Timestamp = 0; - ts.Reset(); + var annexBState = HandleNewHeaderRule.GetAnnexBState(context); + if (annexBState != HandleNewHeaderRule.AnnexBState.IsAnnexB) + { + // Header Tag 时间戳重设到 0 + if (h.VideoHeader != null) + h.VideoHeader.Timestamp = 0; + if (h.AudioHeader != null) + h.AudioHeader.Timestamp = 0; + } } } }