diff --git a/src/N_m3u8DL-RE.Common/Enum/ExtractorType.cs b/src/N_m3u8DL-RE.Common/Enum/ExtractorType.cs
new file mode 100644
index 0000000..a50090a
--- /dev/null
+++ b/src/N_m3u8DL-RE.Common/Enum/ExtractorType.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace N_m3u8DL_RE.Common.Enum
+{
+ public enum ExtractorType
+ {
+ MPEG_DASH,
+ HLS
+ }
+}
diff --git a/src/N_m3u8DL-RE.Extends/N_m3u8DL-RE.Extends.csproj b/src/N_m3u8DL-RE.Extends/N_m3u8DL-RE.Extends.csproj
deleted file mode 100644
index 7958b21..0000000
--- a/src/N_m3u8DL-RE.Extends/N_m3u8DL-RE.Extends.csproj
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
- net6.0
- N_m3u8DL_RE.Extends
- enable
- enable
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/N_m3u8DL-RE.Parser/Config/ParserConfig.cs b/src/N_m3u8DL-RE.Parser/Config/ParserConfig.cs
index 439ef23..d087d4a 100644
--- a/src/N_m3u8DL-RE.Parser/Config/ParserConfig.cs
+++ b/src/N_m3u8DL-RE.Parser/Config/ParserConfig.cs
@@ -17,29 +17,19 @@ namespace N_m3u8DL_RE.Parser.Config
};
///
- /// HLS内容前置处理器. 调用顺序与列表顺序相同
+ /// 内容前置处理器. 调用顺序与列表顺序相同
///
- public IList HLSContentProcessors { get; } = new List() { new DefaultHLSContentProcessor() };
-
- ///
- /// DASH内容前置处理器. 调用顺序与列表顺序相同
- ///
- public IList DASHContentProcessors { get; } = new List() { new DefaultDASHContentProcessor() };
+ public IList ContentProcessors { get; } = new List() { new DefaultHLSContentProcessor(), new DefaultDASHContentProcessor() };
///
/// 添加分片URL前置处理器. 调用顺序与列表顺序相同
///
- public IList HLSUrlProcessors { get; } = new List() { new DefaultUrlProcessor() };
+ public IList UrlProcessors { get; } = new List() { new DefaultUrlProcessor() };
///
- /// DASH内容前置处理器. 调用顺序与列表顺序相同
+ /// KEY解析器. 调用顺序与列表顺序相同
///
- public IList DASHUrlProcessors { get; } = new List() { new DefaultUrlProcessor() };
-
- ///
- /// HLS-KEY解析器. 调用顺序与列表顺序相同
- ///
- public IList HLSKeyProcessors { get; } = new List() { new DefaultHLSKeyProcessor() };
+ public IList KeyProcessors { get; } = new List() { new DefaultHLSKeyProcessor() };
///
diff --git a/src/N_m3u8DL-RE.Parser/Extractor/DASHExtractor.cs b/src/N_m3u8DL-RE.Parser/Extractor/DASHExtractor.cs
index c1af0c5..2b08d52 100644
--- a/src/N_m3u8DL-RE.Parser/Extractor/DASHExtractor.cs
+++ b/src/N_m3u8DL-RE.Parser/Extractor/DASHExtractor.cs
@@ -19,12 +19,15 @@ namespace N_m3u8DL_RE.Parser.Extractor
//code from https://github.com/ytdl-org/youtube-dl/blob/master/youtube_dl/extractor/common.py#L2076
internal class DASHExtractor : IExtractor
{
+ public ExtractorType ExtractorType => ExtractorType.MPEG_DASH;
+
private string MpdUrl = string.Empty;
private string BaseUrl = string.Empty;
private string MpdContent = string.Empty;
public ParserConfig ParserConfig { get; set; }
+
public DASHExtractor(ParserConfig parserConfig)
{
this.ParserConfig = parserConfig;
@@ -54,7 +57,9 @@ namespace N_m3u8DL_RE.Parser.Extractor
}
}
+ var type = ((XmlElement)xn).GetAttribute("type"); //static dynamic
var mediaPresentationDuration = ((XmlElement)xn).GetAttribute("mediaPresentationDuration");
+
var ns = ((XmlElement)xn).GetAttribute("xmlns");
XmlNamespaceManager nsMgr = new XmlNamespaceManager(mpdDoc.NameTable);
@@ -722,9 +727,9 @@ namespace N_m3u8DL_RE.Parser.Extractor
///
private string PreProcessUrl(string url)
{
- foreach (var p in ParserConfig.DASHUrlProcessors)
+ foreach (var p in ParserConfig.UrlProcessors)
{
- if (p.CanProcess(url, ParserConfig))
+ if (p.CanProcess(ExtractorType, url, ParserConfig))
{
url = p.Process(url, ParserConfig);
}
@@ -735,9 +740,9 @@ namespace N_m3u8DL_RE.Parser.Extractor
private void PreProcessContent()
{
- foreach (var p in ParserConfig.DASHContentProcessors)
+ foreach (var p in ParserConfig.ContentProcessors)
{
- if (p.CanProcess(MpdContent, ParserConfig))
+ if (p.CanProcess(ExtractorType, MpdContent, ParserConfig))
{
MpdContent = p.Process(MpdContent, ParserConfig);
}
diff --git a/src/N_m3u8DL-RE.Parser/Extractor/HLSExtractor.cs b/src/N_m3u8DL-RE.Parser/Extractor/HLSExtractor.cs
index 7a60393..e58a69f 100644
--- a/src/N_m3u8DL-RE.Parser/Extractor/HLSExtractor.cs
+++ b/src/N_m3u8DL-RE.Parser/Extractor/HLSExtractor.cs
@@ -17,6 +17,8 @@ namespace N_m3u8DL_RE.Parser.Extractor
{
internal class HLSExtractor : IExtractor
{
+ public ExtractorType ExtractorType => ExtractorType.HLS;
+
private string M3u8Url = string.Empty;
private string BaseUrl = string.Empty;
private string M3u8Content = string.Empty;
@@ -50,9 +52,9 @@ namespace N_m3u8DL_RE.Parser.Extractor
throw new Exception(ResString.badM3u8);
}
- foreach (var p in ParserConfig.HLSContentProcessors)
+ foreach (var p in ParserConfig.ContentProcessors)
{
- if (p.CanProcess(M3u8Content, ParserConfig))
+ if (p.CanProcess(ExtractorType, M3u8Content, ParserConfig))
{
M3u8Content = p.Process(M3u8Content, ParserConfig);
}
@@ -64,9 +66,9 @@ namespace N_m3u8DL_RE.Parser.Extractor
///
private string PreProcessUrl(string url)
{
- foreach (var p in ParserConfig.HLSUrlProcessors)
+ foreach (var p in ParserConfig.UrlProcessors)
{
- if (p.CanProcess(url, ParserConfig))
+ if (p.CanProcess(ExtractorType, url, ParserConfig))
{
url = p.Process(url, ParserConfig);
}
@@ -442,10 +444,11 @@ namespace N_m3u8DL_RE.Parser.Extractor
private byte[] ParseKey(string method, string uriText)
{
- foreach (var p in ParserConfig.HLSKeyProcessors)
+ foreach (var p in ParserConfig.KeyProcessors)
{
- if (p.CanProcess(method, uriText, ParserConfig))
+ if (p.CanProcess(ExtractorType, method, uriText, ParserConfig))
{
+ //匹配到对应处理器后不再继续
return p.Process(method, uriText, ParserConfig);
}
}
diff --git a/src/N_m3u8DL-RE.Parser/Extractor/IExtractor.cs b/src/N_m3u8DL-RE.Parser/Extractor/IExtractor.cs
index de74826..8f1f68a 100644
--- a/src/N_m3u8DL-RE.Parser/Extractor/IExtractor.cs
+++ b/src/N_m3u8DL-RE.Parser/Extractor/IExtractor.cs
@@ -5,11 +5,14 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using N_m3u8DL_RE.Common.Enum;
namespace N_m3u8DL_RE.Parser.Extractor
{
internal interface IExtractor
{
+ ExtractorType ExtractorType { get; }
+
ParserConfig ParserConfig { get; set; }
Task> ExtractStreamsAsync(string rawText);
diff --git a/src/N_m3u8DL-RE.Parser/Processor/ContentProcessor.cs b/src/N_m3u8DL-RE.Parser/Processor/ContentProcessor.cs
index caa061a..60b0a87 100644
--- a/src/N_m3u8DL-RE.Parser/Processor/ContentProcessor.cs
+++ b/src/N_m3u8DL-RE.Parser/Processor/ContentProcessor.cs
@@ -1,4 +1,5 @@
-using N_m3u8DL_RE.Parser.Config;
+using N_m3u8DL_RE.Common.Enum;
+using N_m3u8DL_RE.Parser.Config;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -9,7 +10,7 @@ namespace N_m3u8DL_RE.Parser.Processor
{
public abstract class ContentProcessor
{
- public abstract bool CanProcess(string rawText, ParserConfig parserConfig);
+ public abstract bool CanProcess(ExtractorType extractorType, string rawText, ParserConfig parserConfig);
public abstract string Process(string rawText, ParserConfig parserConfig);
}
}
diff --git a/src/N_m3u8DL-RE.Parser/Processor/DASH/DefaultDASHContentProcessor.cs b/src/N_m3u8DL-RE.Parser/Processor/DASH/DefaultDASHContentProcessor.cs
index a0a6b9c..aa69a94 100644
--- a/src/N_m3u8DL-RE.Parser/Processor/DASH/DefaultDASHContentProcessor.cs
+++ b/src/N_m3u8DL-RE.Parser/Processor/DASH/DefaultDASHContentProcessor.cs
@@ -1,4 +1,5 @@
-using N_m3u8DL_RE.Common.Log;
+using N_m3u8DL_RE.Common.Enum;
+using N_m3u8DL_RE.Common.Log;
using N_m3u8DL_RE.Parser.Config;
using System;
using System.Collections.Generic;
@@ -13,8 +14,10 @@ namespace N_m3u8DL_RE.Parser.Processor.DASH
///
public class DefaultDASHContentProcessor : ContentProcessor
{
- public override bool CanProcess(string mpdContent, ParserConfig parserConfig)
+ public override bool CanProcess(ExtractorType extractorType, string mpdContent, ParserConfig parserConfig)
{
+ if (extractorType != ExtractorType.MPEG_DASH) return false;
+
if (mpdContent.Contains(" true;
+
+ public override bool CanProcess(ExtractorType extractorType, string oriUrl, ParserConfig paserConfig) => true;
public override string Process(string oriUrl, ParserConfig paserConfig)
{
diff --git a/src/N_m3u8DL-RE.Parser/Processor/HLS/DefaultHLSContentProcessor.cs b/src/N_m3u8DL-RE.Parser/Processor/HLS/DefaultHLSContentProcessor.cs
index bcbe42e..fbcb25d 100644
--- a/src/N_m3u8DL-RE.Parser/Processor/HLS/DefaultHLSContentProcessor.cs
+++ b/src/N_m3u8DL-RE.Parser/Processor/HLS/DefaultHLSContentProcessor.cs
@@ -1,4 +1,5 @@
-using N_m3u8DL_RE.Parser.Config;
+using N_m3u8DL_RE.Common.Enum;
+using N_m3u8DL_RE.Parser.Config;
using N_m3u8DL_RE.Parser.Constants;
using System;
using System.Collections.Generic;
@@ -11,7 +12,7 @@ namespace N_m3u8DL_RE.Parser.Processor.HLS
{
public class DefaultHLSContentProcessor : ContentProcessor
{
- public override bool CanProcess(string rawText, ParserConfig parserConfig) => true;
+ public override bool CanProcess(ExtractorType extractorType, string rawText, ParserConfig parserConfig) => extractorType == ExtractorType.HLS;
public override string Process(string m3u8Content, ParserConfig parserConfig)
{
diff --git a/src/N_m3u8DL-RE.Parser/Processor/HLS/DefaultHLSKeyProcessor.cs b/src/N_m3u8DL-RE.Parser/Processor/HLS/DefaultHLSKeyProcessor.cs
index 6998e49..1b5fc46 100644
--- a/src/N_m3u8DL-RE.Parser/Processor/HLS/DefaultHLSKeyProcessor.cs
+++ b/src/N_m3u8DL-RE.Parser/Processor/HLS/DefaultHLSKeyProcessor.cs
@@ -13,7 +13,8 @@ namespace N_m3u8DL_RE.Parser.Processor.HLS
{
public class DefaultHLSKeyProcessor : KeyProcessor
{
- public override bool CanProcess(string method, string uriText, ParserConfig paserConfig) => true;
+ public override bool CanProcess(ExtractorType extractorType, string method, string uriText, ParserConfig paserConfig) => extractorType == ExtractorType.HLS;
+
public override byte[] Process(string method, string uriText, ParserConfig parserConfig)
{
@@ -43,9 +44,9 @@ namespace N_m3u8DL_RE.Parser.Processor.HLS
///
private string PreProcessUrl(string url, ParserConfig parserConfig)
{
- foreach (var p in parserConfig.HLSUrlProcessors)
+ foreach (var p in parserConfig.UrlProcessors)
{
- if (p.CanProcess(url, parserConfig))
+ if (p.CanProcess(ExtractorType.HLS, url, parserConfig))
{
url = p.Process(url, parserConfig);
}
diff --git a/src/N_m3u8DL-RE.Parser/Processor/KeyProcessor.cs b/src/N_m3u8DL-RE.Parser/Processor/KeyProcessor.cs
index 1991781..f2736d7 100644
--- a/src/N_m3u8DL-RE.Parser/Processor/KeyProcessor.cs
+++ b/src/N_m3u8DL-RE.Parser/Processor/KeyProcessor.cs
@@ -1,4 +1,5 @@
using N_m3u8DL_RE.Common.Entity;
+using N_m3u8DL_RE.Common.Enum;
using N_m3u8DL_RE.Parser.Config;
using System;
using System.Collections.Generic;
@@ -10,7 +11,7 @@ namespace N_m3u8DL_RE.Parser.Processor
{
public abstract class KeyProcessor
{
- public abstract bool CanProcess(string method, string uriText, ParserConfig parserConfig);
+ public abstract bool CanProcess(ExtractorType extractorType, string method, string uriText, ParserConfig parserConfig);
public abstract byte[] Process(string method, string uriText, ParserConfig parserConfig);
}
}
diff --git a/src/N_m3u8DL-RE.Parser/Processor/UrlProcessor.cs b/src/N_m3u8DL-RE.Parser/Processor/UrlProcessor.cs
index 81a4986..6f3818e 100644
--- a/src/N_m3u8DL-RE.Parser/Processor/UrlProcessor.cs
+++ b/src/N_m3u8DL-RE.Parser/Processor/UrlProcessor.cs
@@ -1,4 +1,5 @@
-using N_m3u8DL_RE.Parser.Config;
+using N_m3u8DL_RE.Common.Enum;
+using N_m3u8DL_RE.Parser.Config;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -9,7 +10,7 @@ namespace N_m3u8DL_RE.Parser.Processor
{
public abstract class UrlProcessor
{
- public abstract bool CanProcess(string oriUrl, ParserConfig parserConfig);
+ public abstract bool CanProcess(ExtractorType extractorType, string oriUrl, ParserConfig parserConfig);
public abstract string Process(string oriUrl, ParserConfig parserConfig);
}
}
diff --git a/src/N_m3u8DL-RE.sln b/src/N_m3u8DL-RE.sln
index 217b470..7f69da1 100644
--- a/src/N_m3u8DL-RE.sln
+++ b/src/N_m3u8DL-RE.sln
@@ -9,8 +9,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "N_m3u8DL-RE.Common", "N_m3u
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "N_m3u8DL-RE.Parser", "N_m3u8DL-RE.Parser\N_m3u8DL-RE.Parser.csproj", "{0DA02925-AF3A-4598-AF01-91AE5539FCA1}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "N_m3u8DL-RE.Extends", "N_m3u8DL-RE.Extends\N_m3u8DL-RE.Extends.csproj", "{99175570-6FE1-45C0-87BD-D2E1B52A35CC}"
-EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -29,10 +27,6 @@ Global
{0DA02925-AF3A-4598-AF01-91AE5539FCA1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0DA02925-AF3A-4598-AF01-91AE5539FCA1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0DA02925-AF3A-4598-AF01-91AE5539FCA1}.Release|Any CPU.Build.0 = Release|Any CPU
- {99175570-6FE1-45C0-87BD-D2E1B52A35CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {99175570-6FE1-45C0-87BD-D2E1B52A35CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {99175570-6FE1-45C0-87BD-D2E1B52A35CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {99175570-6FE1-45C0-87BD-D2E1B52A35CC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/N_m3u8DL-RE/Crypto/AESUtil.cs b/src/N_m3u8DL-RE/Crypto/AESUtil.cs
new file mode 100644
index 0000000..edb07ed
--- /dev/null
+++ b/src/N_m3u8DL-RE/Crypto/AESUtil.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace N_m3u8DL_RE.Crypto
+{
+ internal class AESUtil
+ {
+ public static byte[] AES128Decrypt(string filePath, byte[] keyByte, byte[] ivByte, CipherMode mode = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
+ {
+ FileStream fs = new FileStream(filePath, FileMode.Open);
+ //获取文件大小
+ long size = fs.Length;
+ byte[] inBuff = new byte[size];
+ fs.Read(inBuff, 0, inBuff.Length);
+ fs.Close();
+
+ Aes dcpt = Aes.Create();
+ dcpt.BlockSize = 128;
+ dcpt.KeySize = 128;
+ dcpt.Key = keyByte;
+ dcpt.IV = ivByte;
+ dcpt.Mode = mode;
+ dcpt.Padding = padding;
+
+ ICryptoTransform cTransform = dcpt.CreateDecryptor();
+ byte[] resultArray = cTransform.TransformFinalBlock(inBuff, 0, inBuff.Length);
+ return resultArray;
+ }
+
+ public static byte[] AES128Decrypt(byte[] encryptedBuff, byte[] keyByte, byte[] ivByte, CipherMode mode = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
+ {
+ byte[] inBuff = encryptedBuff;
+
+ Aes dcpt = Aes.Create();
+ dcpt.BlockSize = 128;
+ dcpt.KeySize = 128;
+ dcpt.Key = keyByte;
+ dcpt.IV = ivByte;
+ dcpt.Mode = mode;
+ dcpt.Padding = padding;
+
+ ICryptoTransform cTransform = dcpt.CreateDecryptor();
+ byte[] resultArray = cTransform.TransformFinalBlock(inBuff, 0, inBuff.Length);
+ return resultArray;
+ }
+ }
+}
diff --git a/src/N_m3u8DL-RE/Crypto/CSChaCha20.cs b/src/N_m3u8DL-RE/Crypto/CSChaCha20.cs
new file mode 100644
index 0000000..1fa2ca1
--- /dev/null
+++ b/src/N_m3u8DL-RE/Crypto/CSChaCha20.cs
@@ -0,0 +1,661 @@
+/*
+ * Copyright (c) 2015, 2018 Scott Bennett
+ * (c) 2018-2021 Kaarlo Räihä
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.IO;
+using System.Text;
+using System.Threading.Tasks;
+using System.Runtime.CompilerServices; // For MethodImplOptions.AggressiveInlining
+
+namespace CSChaCha20
+{
+ ///
+ /// Class that can be used for ChaCha20 encryption / decryption
+ ///
+ public sealed class ChaCha20 : IDisposable
+ {
+ ///
+ /// Only allowed key lenght in bytes
+ ///
+ public const int allowedKeyLength = 32;
+
+ ///
+ /// Only allowed nonce lenght in bytes
+ ///
+ public const int allowedNonceLength = 12;
+
+ ///
+ /// How many bytes are processed per loop
+ ///
+ public const int processBytesAtTime = 64;
+
+ private const int stateLength = 16;
+
+ ///
+ /// The ChaCha20 state (aka "context")
+ ///
+ private readonly uint[] state = new uint[stateLength];
+
+ ///
+ /// Determines if the objects in this class have been disposed of. Set to true by the Dispose() method.
+ ///
+ private bool isDisposed = false;
+
+ ///
+ /// Set up a new ChaCha20 state. The lengths of the given parameters are checked before encryption happens.
+ ///
+ ///
+ /// See ChaCha20 Spec Section 2.4 for a detailed description of the inputs.
+ ///
+ ///
+ /// A 32-byte (256-bit) key, treated as a concatenation of eight 32-bit little-endian integers
+ ///
+ ///
+ /// A 12-byte (96-bit) nonce, treated as a concatenation of three 32-bit little-endian integers
+ ///
+ ///
+ /// A 4-byte (32-bit) block counter, treated as a 32-bit little-endian integer
+ ///
+ public ChaCha20(byte[] key, byte[] nonce, uint counter)
+ {
+ this.KeySetup(key);
+ this.IvSetup(nonce, counter);
+ }
+
+#if NET6_0_OR_GREATER
+
+ ///
+ /// Set up a new ChaCha20 state. The lengths of the given parameters are checked before encryption happens.
+ ///
+ ///
+ /// See ChaCha20 Spec Section 2.4 for a detailed description of the inputs.
+ ///
+ /// A 32-byte (256-bit) key, treated as a concatenation of eight 32-bit little-endian integers
+ /// A 12-byte (96-bit) nonce, treated as a concatenation of three 32-bit little-endian integers
+ /// A 4-byte (32-bit) block counter, treated as a 32-bit little-endian integer
+ public ChaCha20(ReadOnlySpan key, ReadOnlySpan nonce, uint counter)
+ {
+ this.KeySetup(key.ToArray());
+ this.IvSetup(nonce.ToArray(), counter);
+ }
+
+#endif // NET6_0_OR_GREATER
+
+ ///
+ /// The ChaCha20 state (aka "context"). Read-Only.
+ ///
+ public uint[] State
+ {
+ get
+ {
+ return this.state;
+ }
+ }
+
+
+ // These are the same constants defined in the reference implementation.
+ // http://cr.yp.to/streamciphers/timings/estreambench/submissions/salsa20/chacha8/ref/chacha.c
+ private static readonly byte[] sigma = Encoding.ASCII.GetBytes("expand 32-byte k");
+ private static readonly byte[] tau = Encoding.ASCII.GetBytes("expand 16-byte k");
+
+ ///
+ /// Set up the ChaCha state with the given key. A 32-byte key is required and enforced.
+ ///
+ ///
+ /// A 32-byte (256-bit) key, treated as a concatenation of eight 32-bit little-endian integers
+ ///
+ private void KeySetup(byte[] key)
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException("Key is null");
+ }
+
+ if (key.Length != allowedKeyLength)
+ {
+ throw new ArgumentException($"Key length must be {allowedKeyLength}. Actual: {key.Length}");
+ }
+
+ state[4] = Util.U8To32Little(key, 0);
+ state[5] = Util.U8To32Little(key, 4);
+ state[6] = Util.U8To32Little(key, 8);
+ state[7] = Util.U8To32Little(key, 12);
+
+ byte[] constants = (key.Length == allowedKeyLength) ? sigma : tau;
+ int keyIndex = key.Length - 16;
+
+ state[8] = Util.U8To32Little(key, keyIndex + 0);
+ state[9] = Util.U8To32Little(key, keyIndex + 4);
+ state[10] = Util.U8To32Little(key, keyIndex + 8);
+ state[11] = Util.U8To32Little(key, keyIndex + 12);
+
+ state[0] = Util.U8To32Little(constants, 0);
+ state[1] = Util.U8To32Little(constants, 4);
+ state[2] = Util.U8To32Little(constants, 8);
+ state[3] = Util.U8To32Little(constants, 12);
+ }
+
+ ///
+ /// Set up the ChaCha state with the given nonce (aka Initialization Vector or IV) and block counter. A 12-byte nonce and a 4-byte counter are required.
+ ///
+ ///
+ /// A 12-byte (96-bit) nonce, treated as a concatenation of three 32-bit little-endian integers
+ ///
+ ///
+ /// A 4-byte (32-bit) block counter, treated as a 32-bit little-endian integer
+ ///
+ private void IvSetup(byte[] nonce, uint counter)
+ {
+ if (nonce == null)
+ {
+ // There has already been some state set up. Clear it before exiting.
+ Dispose();
+ throw new ArgumentNullException("Nonce is null");
+ }
+
+ if (nonce.Length != allowedNonceLength)
+ {
+ // There has already been some state set up. Clear it before exiting.
+ Dispose();
+ throw new ArgumentException($"Nonce length must be {allowedNonceLength}. Actual: {nonce.Length}");
+ }
+
+ state[12] = counter;
+ state[13] = Util.U8To32Little(nonce, 0);
+ state[14] = Util.U8To32Little(nonce, 4);
+ state[15] = Util.U8To32Little(nonce, 8);
+ }
+
+
+ #region Encryption methods
+
+ ///
+ /// Encrypt arbitrary-length byte array (input), writing the resulting byte array to preallocated output buffer.
+ ///
+ /// Since this is symmetric operation, it doesn't really matter if you use Encrypt or Decrypt method
+ /// Output byte array, must have enough bytes
+ /// Input byte array
+ /// Number of bytes to encrypt
+ public void EncryptBytes(byte[] output, byte[] input, int numBytes)
+ {
+ this.WorkBytes(output, input, numBytes);
+ }
+
+ ///
+ /// Encrypt arbitrary-length byte stream (input), writing the resulting bytes to another stream (output)
+ ///
+ /// Output stream
+ /// Input stream
+ /// How many bytes to read and write at time, default is 1024
+ public void EncryptStream(Stream output, Stream input, int howManyBytesToProcessAtTime = 1024)
+ {
+ this.WorkStreams(output, input, howManyBytesToProcessAtTime);
+ }
+
+ ///
+ /// Async encrypt arbitrary-length byte stream (input), writing the resulting bytes to another stream (output)
+ ///
+ /// Output stream
+ /// Input stream
+ /// How many bytes to read and write at time, default is 1024
+ public async Task EncryptStreamAsync(Stream output, Stream input, int howManyBytesToProcessAtTime = 1024)
+ {
+ await this.WorkStreamsAsync(output, input, howManyBytesToProcessAtTime);
+ }
+
+ ///
+ /// Encrypt arbitrary-length byte array (input), writing the resulting byte array to preallocated output buffer.
+ ///
+ /// Since this is symmetric operation, it doesn't really matter if you use Encrypt or Decrypt method
+ /// Output byte array, must have enough bytes
+ /// Input byte array
+ public void EncryptBytes(byte[] output, byte[] input)
+ {
+ this.WorkBytes(output, input, input.Length);
+ }
+
+ ///
+ /// Encrypt arbitrary-length byte array (input), writing the resulting byte array that is allocated by method.
+ ///
+ /// Since this is symmetric operation, it doesn't really matter if you use Encrypt or Decrypt method
+ /// Input byte array
+ /// Number of bytes to encrypt
+ /// Byte array that contains encrypted bytes
+ public byte[] EncryptBytes(byte[] input, int numBytes)
+ {
+ byte[] returnArray = new byte[numBytes];
+ this.WorkBytes(returnArray, input, numBytes);
+ return returnArray;
+ }
+
+ ///
+ /// Encrypt arbitrary-length byte array (input), writing the resulting byte array that is allocated by method.
+ ///
+ /// Since this is symmetric operation, it doesn't really matter if you use Encrypt or Decrypt method
+ /// Input byte array
+ /// Byte array that contains encrypted bytes
+ public byte[] EncryptBytes(byte[] input)
+ {
+ byte[] returnArray = new byte[input.Length];
+ this.WorkBytes(returnArray, input, input.Length);
+ return returnArray;
+ }
+
+ ///
+ /// Encrypt string as UTF8 byte array, returns byte array that is allocated by method.
+ ///
+ /// Here you can NOT swap encrypt and decrypt methods, because of bytes-string transform
+ /// Input string
+ /// Byte array that contains encrypted bytes
+ public byte[] EncryptString(string input)
+ {
+ byte[] utf8Bytes = System.Text.Encoding.UTF8.GetBytes(input);
+ byte[] returnArray = new byte[utf8Bytes.Length];
+
+ this.WorkBytes(returnArray, utf8Bytes, utf8Bytes.Length);
+ return returnArray;
+ }
+
+ #endregion // Encryption methods
+
+
+ #region // Decryption methods
+
+ ///
+ /// Decrypt arbitrary-length byte array (input), writing the resulting byte array to the output buffer.
+ ///
+ /// Since this is symmetric operation, it doesn't really matter if you use Encrypt or Decrypt method
+ /// Output byte array
+ /// Input byte array
+ /// Number of bytes to decrypt
+ public void DecryptBytes(byte[] output, byte[] input, int numBytes)
+ {
+ this.WorkBytes(output, input, numBytes);
+ }
+
+ ///
+ /// Decrypt arbitrary-length byte stream (input), writing the resulting bytes to another stream (output)
+ ///
+ /// Output stream
+ /// Input stream
+ /// How many bytes to read and write at time, default is 1024
+ public void DecryptStream(Stream output, Stream input, int howManyBytesToProcessAtTime = 1024)
+ {
+ this.WorkStreams(output, input, howManyBytesToProcessAtTime);
+ }
+
+ ///
+ /// Async decrypt arbitrary-length byte stream (input), writing the resulting bytes to another stream (output)
+ ///
+ /// Output stream
+ /// Input stream
+ /// How many bytes to read and write at time, default is 1024
+ public async Task DecryptStreamAsync(Stream output, Stream input, int howManyBytesToProcessAtTime = 1024)
+ {
+ await this.WorkStreamsAsync(output, input, howManyBytesToProcessAtTime);
+ }
+
+ ///
+ /// Decrypt arbitrary-length byte array (input), writing the resulting byte array to preallocated output buffer.
+ ///
+ /// Since this is symmetric operation, it doesn't really matter if you use Encrypt or Decrypt method
+ /// Output byte array, must have enough bytes
+ /// Input byte array
+ public void DecryptBytes(byte[] output, byte[] input)
+ {
+ WorkBytes(output, input, input.Length);
+ }
+
+ ///
+ /// Decrypt arbitrary-length byte array (input), writing the resulting byte array that is allocated by method.
+ ///
+ /// Since this is symmetric operation, it doesn't really matter if you use Encrypt or Decrypt method
+ /// Input byte array
+ /// Number of bytes to encrypt
+ /// Byte array that contains decrypted bytes
+ public byte[] DecryptBytes(byte[] input, int numBytes)
+ {
+ byte[] returnArray = new byte[numBytes];
+ WorkBytes(returnArray, input, numBytes);
+ return returnArray;
+ }
+
+ ///
+ /// Decrypt arbitrary-length byte array (input), writing the resulting byte array that is allocated by method.
+ ///
+ /// Since this is symmetric operation, it doesn't really matter if you use Encrypt or Decrypt method
+ /// Input byte array
+ /// Byte array that contains decrypted bytes
+ public byte[] DecryptBytes(byte[] input)
+ {
+ byte[] returnArray = new byte[input.Length];
+ WorkBytes(returnArray, input, input.Length);
+ return returnArray;
+ }
+
+ ///
+ /// Decrypt UTF8 byte array to string.
+ ///
+ /// Here you can NOT swap encrypt and decrypt methods, because of bytes-string transform
+ /// Byte array
+ /// Byte array that contains encrypted bytes
+ public string DecryptUTF8ByteArray(byte[] input)
+ {
+ byte[] tempArray = new byte[input.Length];
+
+ WorkBytes(tempArray, input, input.Length);
+ return System.Text.Encoding.UTF8.GetString(tempArray);
+ }
+
+ #endregion // Decryption methods
+
+ private void WorkStreams(Stream output, Stream input, int howManyBytesToProcessAtTime = 1024)
+ {
+ int readBytes;
+
+ byte[] inputBuffer = new byte[howManyBytesToProcessAtTime];
+ byte[] outputBuffer = new byte[howManyBytesToProcessAtTime];
+
+ while ((readBytes = input.Read(inputBuffer, 0, howManyBytesToProcessAtTime)) > 0)
+ {
+ // Encrypt or decrypt
+ WorkBytes(output: outputBuffer, input: inputBuffer, numBytes: readBytes);
+
+ // Write buffer
+ output.Write(outputBuffer, 0, readBytes);
+ }
+ }
+
+ private async Task WorkStreamsAsync(Stream output, Stream input, int howManyBytesToProcessAtTime = 1024)
+ {
+ byte[] readBytesBuffer = new byte[howManyBytesToProcessAtTime];
+ byte[] writeBytesBuffer = new byte[howManyBytesToProcessAtTime];
+ int howManyBytesWereRead = await input.ReadAsync(readBytesBuffer, 0, howManyBytesToProcessAtTime);
+
+ while (howManyBytesWereRead > 0)
+ {
+ // Encrypt or decrypt
+ WorkBytes(output: writeBytesBuffer, input: readBytesBuffer, numBytes: howManyBytesWereRead);
+
+ // Write
+ await output.WriteAsync(writeBytesBuffer, 0, howManyBytesWereRead);
+
+ // Read more
+ howManyBytesWereRead = await input.ReadAsync(readBytesBuffer, 0, howManyBytesToProcessAtTime);
+ }
+ }
+
+ ///
+ /// Encrypt or decrypt an arbitrary-length byte array (input), writing the resulting byte array to the output buffer. The number of bytes to read from the input buffer is determined by numBytes.
+ ///
+ /// Output byte array
+ /// Input byte array
+ /// How many bytes to process
+ private void WorkBytes(byte[] output, byte[] input, int numBytes)
+ {
+ if (isDisposed)
+ {
+ throw new ObjectDisposedException("state", "The ChaCha state has been disposed");
+ }
+
+ if (input == null)
+ {
+ throw new ArgumentNullException("input", "Input cannot be null");
+ }
+
+ if (output == null)
+ {
+ throw new ArgumentNullException("output", "Output cannot be null");
+ }
+
+ if (numBytes < 0 || numBytes > input.Length)
+ {
+ throw new ArgumentOutOfRangeException("numBytes", "The number of bytes to read must be between [0..input.Length]");
+ }
+
+ if (output.Length < numBytes)
+ {
+ throw new ArgumentOutOfRangeException("output", $"Output byte array should be able to take at least {numBytes}");
+ }
+
+ uint[] x = new uint[stateLength]; // Working buffer
+ byte[] tmp = new byte[processBytesAtTime]; // Temporary buffer
+ int offset = 0;
+
+ while (numBytes > 0)
+ {
+ // Copy state to working buffer
+ Buffer.BlockCopy(this.state, 0, x, 0, stateLength * sizeof(uint));
+
+ for (int i = 0; i < 10; i++)
+ {
+ QuarterRound(x, 0, 4, 8, 12);
+ QuarterRound(x, 1, 5, 9, 13);
+ QuarterRound(x, 2, 6, 10, 14);
+ QuarterRound(x, 3, 7, 11, 15);
+
+ QuarterRound(x, 0, 5, 10, 15);
+ QuarterRound(x, 1, 6, 11, 12);
+ QuarterRound(x, 2, 7, 8, 13);
+ QuarterRound(x, 3, 4, 9, 14);
+ }
+
+ for (int i = 0; i < stateLength; i++)
+ {
+ Util.ToBytes(tmp, Util.Add(x[i], this.state[i]), 4 * i);
+ }
+
+ this.state[12] = Util.AddOne(state[12]);
+ if (this.state[12] <= 0)
+ {
+ /* Stopping at 2^70 bytes per nonce is the user's responsibility */
+ this.state[13] = Util.AddOne(state[13]);
+ }
+
+ // In case these are last bytes
+ if (numBytes <= processBytesAtTime)
+ {
+ for (int i = 0; i < numBytes; i++)
+ {
+ output[i + offset] = (byte)(input[i + offset] ^ tmp[i]);
+ }
+
+ return;
+ }
+
+ for (int i = 0; i < processBytesAtTime; i++)
+ {
+ output[i + offset] = (byte)(input[i + offset] ^ tmp[i]);
+ }
+
+ numBytes -= processBytesAtTime;
+ offset += processBytesAtTime;
+ }
+ }
+
+ ///
+ /// The ChaCha Quarter Round operation. It operates on four 32-bit unsigned integers within the given buffer at indices a, b, c, and d.
+ ///
+ ///
+ /// The ChaCha state does not have four integer numbers: it has 16. So the quarter-round operation works on only four of them -- hence the name. Each quarter round operates on four predetermined numbers in the ChaCha state.
+ /// See ChaCha20 Spec Sections 2.1 - 2.2.
+ ///
+ /// A ChaCha state (vector). Must contain 16 elements.
+ /// Index of the first number
+ /// Index of the second number
+ /// Index of the third number
+ /// Index of the fourth number
+ private static void QuarterRound(uint[] x, uint a, uint b, uint c, uint d)
+ {
+ x[a] = Util.Add(x[a], x[b]);
+ x[d] = Util.Rotate(Util.XOr(x[d], x[a]), 16);
+
+ x[c] = Util.Add(x[c], x[d]);
+ x[b] = Util.Rotate(Util.XOr(x[b], x[c]), 12);
+
+ x[a] = Util.Add(x[a], x[b]);
+ x[d] = Util.Rotate(Util.XOr(x[d], x[a]), 8);
+
+ x[c] = Util.Add(x[c], x[d]);
+ x[b] = Util.Rotate(Util.XOr(x[b], x[c]), 7);
+ }
+
+ #region Destructor and Disposer
+
+ ///
+ /// Clear and dispose of the internal state. The finalizer is only called if Dispose() was never called on this cipher.
+ ///
+ ~ChaCha20()
+ {
+ Dispose(false);
+ }
+
+ ///
+ /// Clear and dispose of the internal state. Also request the GC not to call the finalizer, because all cleanup has been taken care of.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+ /*
+ * The Garbage Collector does not need to invoke the finalizer because Dispose(bool) has already done all the cleanup needed.
+ */
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// This method should only be invoked from Dispose() or the finalizer. This handles the actual cleanup of the resources.
+ ///
+ ///
+ /// Should be true if called by Dispose(); false if called by the finalizer
+ ///
+ private void Dispose(bool disposing)
+ {
+ if (!isDisposed)
+ {
+ if (disposing)
+ {
+ /* Cleanup managed objects by calling their Dispose() methods */
+ }
+
+ /* Cleanup any unmanaged objects here */
+ Array.Clear(state, 0, stateLength);
+ }
+
+ isDisposed = true;
+ }
+
+ #endregion // Destructor and Disposer
+ }
+
+ ///
+ /// Utilities that are used during compression
+ ///
+ public static class Util
+ {
+ ///
+ /// n-bit left rotation operation (towards the high bits) for 32-bit integers.
+ ///
+ ///
+ ///
+ /// The result of (v LEFTSHIFT c)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static uint Rotate(uint v, int c)
+ {
+ unchecked
+ {
+ return (v << c) | (v >> (32 - c));
+ }
+ }
+
+ ///
+ /// Unchecked integer exclusive or (XOR) operation.
+ ///
+ ///
+ ///
+ /// The result of (v XOR w)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static uint XOr(uint v, uint w)
+ {
+ return unchecked(v ^ w);
+ }
+
+ ///
+ /// Unchecked integer addition. The ChaCha spec defines certain operations to use 32-bit unsigned integer addition modulo 2^32.
+ ///
+ ///
+ /// See ChaCha20 Spec Section 2.1.
+ ///
+ ///
+ ///
+ /// The result of (v + w) modulo 2^32
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static uint Add(uint v, uint w)
+ {
+ return unchecked(v + w);
+ }
+
+ ///
+ /// Add 1 to the input parameter using unchecked integer addition. The ChaCha spec defines certain operations to use 32-bit unsigned integer addition modulo 2^32.
+ ///
+ ///
+ /// See ChaCha20 Spec Section 2.1.
+ ///
+ ///
+ /// The result of (v + 1) modulo 2^32
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static uint AddOne(uint v)
+ {
+ return unchecked(v + 1);
+ }
+
+ ///
+ /// Convert four bytes of the input buffer into an unsigned 32-bit integer, beginning at the inputOffset.
+ ///
+ ///
+ ///
+ /// An unsigned 32-bit integer
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static uint U8To32Little(byte[] p, int inputOffset)
+ {
+ unchecked
+ {
+ return ((uint)p[inputOffset]
+ | ((uint)p[inputOffset + 1] << 8)
+ | ((uint)p[inputOffset + 2] << 16)
+ | ((uint)p[inputOffset + 3] << 24));
+ }
+ }
+
+ ///
+ /// Serialize the input integer into the output buffer. The input integer will be split into 4 bytes and put into four sequential places in the output buffer, starting at the outputOffset.
+ ///
+ ///
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void ToBytes(byte[] output, uint input, int outputOffset)
+ {
+ unchecked
+ {
+ output[outputOffset] = (byte)input;
+ output[outputOffset + 1] = (byte)(input >> 8);
+ output[outputOffset + 2] = (byte)(input >> 16);
+ output[outputOffset + 3] = (byte)(input >> 24);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/N_m3u8DL-RE/Crypto/ChaCha20Util.cs b/src/N_m3u8DL-RE/Crypto/ChaCha20Util.cs
new file mode 100644
index 0000000..0c02179
--- /dev/null
+++ b/src/N_m3u8DL-RE/Crypto/ChaCha20Util.cs
@@ -0,0 +1,43 @@
+using CSChaCha20;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace N_m3u8DL_RE.Crypto
+{
+ internal class ChaCha20Util
+ {
+ public static byte[] DecryptPer1024Bytes(byte[] encryptedBuff, byte[] keyBytes, byte[] nonceBytes)
+ {
+ if (keyBytes.Length != 32)
+ throw new Exception("Key must be 32 bytes!");
+ if (nonceBytes.Length != 12 && nonceBytes.Length != 8)
+ throw new Exception("Key must be 12 or 8 bytes!");
+ if (nonceBytes.Length == 8)
+ nonceBytes = (new byte[4] { 0, 0, 0, 0 }).Concat(nonceBytes).ToArray();
+
+ var decStream = new MemoryStream();
+ using BinaryReader reader = new BinaryReader(new MemoryStream(encryptedBuff));
+ using (BinaryWriter writer = new BinaryWriter(decStream))
+ while (true)
+ {
+ var buffer = reader.ReadBytes(1024);
+ byte[] dec = new byte[buffer.Length];
+ if (buffer.Length > 0)
+ {
+ ChaCha20 forDecrypting = new ChaCha20(keyBytes, nonceBytes, 0);
+ forDecrypting.DecryptBytes(dec, buffer);
+ writer.Write(dec, 0, dec.Length);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ return decStream.ToArray();
+ }
+ }
+}
diff --git a/src/N_m3u8DL-RE/N_m3u8DL-RE.csproj b/src/N_m3u8DL-RE/N_m3u8DL-RE.csproj
index 6f69e13..19ccf75 100644
--- a/src/N_m3u8DL-RE/N_m3u8DL-RE.csproj
+++ b/src/N_m3u8DL-RE/N_m3u8DL-RE.csproj
@@ -13,7 +13,6 @@
-
diff --git a/src/N_m3u8DL-RE/Processor/DemoProcessor.cs b/src/N_m3u8DL-RE/Processor/DemoProcessor.cs
index f24c6a9..71ab689 100644
--- a/src/N_m3u8DL-RE/Processor/DemoProcessor.cs
+++ b/src/N_m3u8DL-RE/Processor/DemoProcessor.cs
@@ -1,4 +1,5 @@
-using N_m3u8DL_RE.Common.Log;
+using N_m3u8DL_RE.Common.Enum;
+using N_m3u8DL_RE.Common.Log;
using N_m3u8DL_RE.Parser.Config;
using N_m3u8DL_RE.Parser.Processor;
using System;
@@ -11,9 +12,10 @@ namespace N_m3u8DL_RE.Processor
{
internal class DemoProcessor : ContentProcessor
{
- public override bool CanProcess(string rawText, ParserConfig parserConfig)
+
+ public override bool CanProcess(ExtractorType extractorType, string rawText, ParserConfig parserConfig)
{
- return parserConfig.Url.Contains("bitmovin");
+ return extractorType == ExtractorType.MPEG_DASH && parserConfig.Url.Contains("bitmovin");
}
public override string Process(string rawText, ParserConfig parserConfig)
diff --git a/src/N_m3u8DL-RE/Processor/DemoProcessor2.cs b/src/N_m3u8DL-RE/Processor/DemoProcessor2.cs
index a32737d..413c830 100644
--- a/src/N_m3u8DL-RE/Processor/DemoProcessor2.cs
+++ b/src/N_m3u8DL-RE/Processor/DemoProcessor2.cs
@@ -1,5 +1,7 @@
using N_m3u8DL_RE.Common.Entity;
+using N_m3u8DL_RE.Common.Enum;
using N_m3u8DL_RE.Common.Log;
+using N_m3u8DL_RE.Common.Util;
using N_m3u8DL_RE.Parser.Config;
using N_m3u8DL_RE.Parser.Processor;
using N_m3u8DL_RE.Parser.Processor.HLS;
@@ -13,15 +15,17 @@ namespace N_m3u8DL_RE.Processor
{
internal class DemoProcessor2 : KeyProcessor
{
- public override bool CanProcess(string method, string uriText, ParserConfig parserConfig)
+ public override bool CanProcess(ExtractorType extractorType, string method, string uriText, ParserConfig parserConfig)
{
- return parserConfig.Url.Contains("playertest.longtailvideo.com");
+ return extractorType == ExtractorType.HLS && parserConfig.Url.Contains("playertest.longtailvideo.com");
}
public override byte[] Process(string method, string uriText, ParserConfig parserConfig)
{
- Logger.InfoMarkUp("[white on green]My Key Processor![/]");
- return new DefaultHLSKeyProcessor().Process(method, uriText, parserConfig);
+ Logger.InfoMarkUp($"[white on green]My Key Processor => {uriText}[/]");
+ var key = new DefaultHLSKeyProcessor().Process(method, uriText, parserConfig);
+ Logger.InfoMarkUp("[red]" + HexUtil.BytesToHex(key, " ") + "[/]");
+ return key;
}
}
}
diff --git a/src/N_m3u8DL-RE/Program.cs b/src/N_m3u8DL-RE/Program.cs
index ad68bce..a51b079 100644
--- a/src/N_m3u8DL-RE/Program.cs
+++ b/src/N_m3u8DL-RE/Program.cs
@@ -11,7 +11,7 @@ using N_m3u8DL_RE.Common.Log;
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;
-using N_m3u8DL_RE.Extends.Subtitle;
+using N_m3u8DL_RE.Subtitle;
using System.Collections.Concurrent;
using N_m3u8DL_RE.Common.Util;
using N_m3u8DL_RE.Processor;
@@ -36,11 +36,12 @@ namespace N_m3u8DL_RE
{
var config = new ParserConfig();
//demo1
- config.DASHContentProcessors.Insert(0, new DemoProcessor());
+ config.ContentProcessors.Insert(0, new DemoProcessor());
//demo2
- config.HLSKeyProcessors.Insert(0, new DemoProcessor2());
+ config.KeyProcessors.Insert(0, new DemoProcessor2());
var url = string.Empty;
+ //url = "http://livesim.dashif.org/livesim/mup_300/tsbd_500/testpic_2s/Manifest.mpd";
url = "http://playertest.longtailvideo.com/adaptive/oceans_aes/oceans_aes.m3u8";
//url = "https://bitmovin-a.akamaihd.net/content/art-of-motion_drm/mpds/11331.mpd";
diff --git a/src/N_m3u8DL-RE.Extends/Subtitle/WebVTTUtil.cs b/src/N_m3u8DL-RE/Subtitle/WebVTTUtil.cs
similarity index 96%
rename from src/N_m3u8DL-RE.Extends/Subtitle/WebVTTUtil.cs
rename to src/N_m3u8DL-RE/Subtitle/WebVTTUtil.cs
index fdb5eb9..c40154c 100644
--- a/src/N_m3u8DL-RE.Extends/Subtitle/WebVTTUtil.cs
+++ b/src/N_m3u8DL-RE/Subtitle/WebVTTUtil.cs
@@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace N_m3u8DL_RE.Extends.Subtitle
+namespace N_m3u8DL_RE.Subtitle
{
public class WebVTTUtil
{