diff --git a/BililiveRecorder.Flv/Amf/ScriptTagBodyExtensions.cs b/BililiveRecorder.Flv/Amf/ScriptTagBodyExtensions.cs index ca64aed..b9bc341 100644 --- a/BililiveRecorder.Flv/Amf/ScriptTagBodyExtensions.cs +++ b/BililiveRecorder.Flv/Amf/ScriptTagBodyExtensions.cs @@ -2,6 +2,18 @@ namespace BililiveRecorder.Flv.Amf { public static class ScriptTagBodyExtensions { - public static ScriptDataEcmaArray? GetMetadataValue(this ScriptTagBody body) => body.Values.Count > 1 ? body.Values[1] as ScriptDataEcmaArray : null; + public static ScriptDataEcmaArray? GetMetadataValue(this ScriptTagBody body) + { + if (body.Values.Count > 1) + { + return body.Values[1] switch + { + ScriptDataEcmaArray array => array, + ScriptDataObject oect => oect, + _ => null + }; + } + else return null; + } } } diff --git a/BililiveRecorder.Flv/Pipeline/Rules/FfmpegDetectionRule.cs b/BililiveRecorder.Flv/Pipeline/Rules/FfmpegDetectionRule.cs index 2179ecd..d047ee6 100644 --- a/BililiveRecorder.Flv/Pipeline/Rules/FfmpegDetectionRule.cs +++ b/BililiveRecorder.Flv/Pipeline/Rules/FfmpegDetectionRule.cs @@ -18,7 +18,7 @@ namespace BililiveRecorder.Flv.Pipeline.Rules if (!this.LavfEncoderDetected && context.Actions.Any(action => { if (action is PipelineScriptAction scriptAction - && (scriptAction?.Tag?.ScriptData?.GetMetadataValue()?.Value?.TryGetValue("encoder", out var encoderValue) ?? false) + && (scriptAction?.Tag?.ScriptData?.GetMetadataValue()?.TryGetValue("encoder", out var encoderValue) ?? false) && encoderValue is ScriptDataString encoder) return encoder.Value.StartsWith("Lavf", StringComparison.Ordinal); return false; diff --git a/test/BililiveRecorder.Flv.Tests/RuleTests/FfmpegDetectionRuleTests.cs b/test/BililiveRecorder.Flv.Tests/RuleTests/FfmpegDetectionRuleTests.cs new file mode 100644 index 0000000..6bd6c57 --- /dev/null +++ b/test/BililiveRecorder.Flv.Tests/RuleTests/FfmpegDetectionRuleTests.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using BililiveRecorder.Flv.Amf; +using BililiveRecorder.Flv.Pipeline; +using BililiveRecorder.Flv.Pipeline.Actions; +using BililiveRecorder.Flv.Pipeline.Rules; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace BililiveRecorder.Flv.Tests.RuleTests +{ + public class FfmpegDetectionRuleTests + { + [Theory] + [MemberData(nameof(EndTagTestData))] + public void ShouldDetectEndTag(bool expectEndTag, PipelineAction pipelineAction) + { + var rule = new FfmpegDetectionRule(); + var pipeline = new ProcessingPipelineBuilder(new ServiceCollection().BuildServiceProvider()).Add(rule).Build(); + + var context = new FlvProcessingContext(pipelineAction, new Dictionary()); + + pipeline(context); + + Assert.Equal(expectEndTag, rule.EndTagDetected); + } + + private static IEnumerable EndTagTestData() + { + yield return new object[] { true, new PipelineEndAction(new Tag()) }; + yield return new object[] { false, new PipelineScriptAction(new Tag()) }; + yield return new object[] { false, new PipelineHeaderAction(Array.Empty()) }; + yield return new object[] { false, new PipelineDataAction(Array.Empty()) }; + yield return new object[] { false, PipelineNewFileAction.Instance }; + } + + [Theory] + [InlineData(true, @"[{""Type"":""String"",""Value"":""onMetaData""},{""Type"":""Object"",""Value"":{""encoder"":{""Type"":""String"",""Value"":""Lavf56.40.101""}}}]")] + [InlineData(true, @"[{""Type"":""String"",""Value"":""onMetaData""},{""Type"":""EcmaArray"",""Value"":{""encoder"":{""Type"":""String"",""Value"":""Lavf56.40.101""}}}]")] + [InlineData(true, @"[{""Type"":""String"",""Value"":""onMetaData""},{""Type"":""Object"",""Value"":{""encoder"":{""Type"":""String"",""Value"":""Lavf56.40.101""}}},{""Type"":""Null""}]")] + [InlineData(true, @"[{""Type"":""String"",""Value"":""onMetaData""},{""Type"":""Object"",""Value"":{""encoder"":{""Type"":""String"",""Value"":""Lavf123""}}}]")] + [InlineData(false, @"[{""Type"":""String"",""Value"":""onMetaData""},{""Type"":""EcmaArray"",""Value"":{""encoder"":{""Type"":""String"",""Value"":""libobs xxxx""}}}]")] + [InlineData(false, @"[{""Type"":""String"",""Value"":""onMetaData""},{""Type"":""EcmaArray"",""Value"":{}}]")] + [InlineData(false, @"[{""Type"":""String"",""Value"":""onMetaData""},{""Type"":""Object"",""Value"":{}}]")] + [InlineData(false, @"[{""Type"":""String"",""Value"":""aaa""},{""Type"":""Object"",""Value"":{}}]")] + public void ShouldDetectLvafEncoder(bool expectedValue, string metadataJson) + { + var rule = new FfmpegDetectionRule(); + var pipeline = new ProcessingPipelineBuilder(new ServiceCollection().BuildServiceProvider()).Add(rule).Build(); + + var action = new PipelineScriptAction(new Tag + { + Type = TagType.Script, + ScriptData = ScriptTagBody.Parse(metadataJson) + }); + + var context = new FlvProcessingContext(action, new Dictionary()); + + pipeline(context); + + Assert.Equal(expectedValue, rule.LavfEncoderDetected); + } + } +}