From 61a9f7e31d53fc145ff5d1e69f8b45d7203ed47d Mon Sep 17 00:00:00 2001 From: "SmallChi(Koike)" <564952747@qq.com> Date: Tue, 25 Aug 2020 17:02:16 +0800 Subject: [PATCH] =?UTF-8?q?1.=E5=B0=86=E9=9F=B3=E9=A2=91=E7=BC=96=E7=A0=81?= =?UTF-8?q?=E5=99=A8=E4=BB=8Eflv=E5=BA=93=E4=B8=AD=E7=A7=BB=E5=88=B01078?= =?UTF-8?q?=E5=8D=8F=E8=AE=AE=E5=BA=93=E4=B8=AD=202.=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E6=8E=89faac=E5=BA=93=203.=E6=9A=82=E6=97=B6=E5=8E=BB=E6=8E=89?= =?UTF-8?q?=E9=9F=B3=E9=A2=91=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/JT1078.Flv.Test/Audio/AudioTest.cs | 44 ++-- src/JT1078.Flv/Audio/G711ACodec.cs | 123 ---------- src/JT1078.Flv/FlvEncoder.cs | 48 +--- src/JT1078.Flv/JT1078.Flv.csproj | 10 +- src/JT1078.Flv/JT1078.Flv.xml | 49 +--- src/JT1078.Flv/nativelibs/x64/libfaac.dll | Bin 71168 -> 0 bytes src/JT1078.Flv/nativelibs/x86/libfaac.dll | Bin 143360 -> 0 bytes src/JT1078.Hls/JT1078.Hls.xml | 6 +- .../Audio/AdpcmCodec.cs | 230 +++++++++--------- .../Audio/AudioCodecFactory.cs | 47 ++++ .../Audio/FaacEncoder.cs | 3 +- src/JT1078.Protocol/Audio/G711ACodec.cs | 114 +++++++++ .../Audio/G711UCodec.cs | 40 +-- src/JT1078.Protocol/Audio/IAudioAttachData.cs | 10 + src/JT1078.Protocol/Audio/IAudioCodec.cs | 11 + src/JT1078.Protocol/JT1078.Protocol.csproj | 7 +- 16 files changed, 364 insertions(+), 378 deletions(-) delete mode 100644 src/JT1078.Flv/Audio/G711ACodec.cs delete mode 100644 src/JT1078.Flv/nativelibs/x64/libfaac.dll delete mode 100644 src/JT1078.Flv/nativelibs/x86/libfaac.dll rename src/{JT1078.Flv => JT1078.Protocol}/Audio/AdpcmCodec.cs (57%) create mode 100644 src/JT1078.Protocol/Audio/AudioCodecFactory.cs rename src/{JT1078.Flv => JT1078.Protocol}/Audio/FaacEncoder.cs (99%) create mode 100644 src/JT1078.Protocol/Audio/G711ACodec.cs rename src/{JT1078.Flv => JT1078.Protocol}/Audio/G711UCodec.cs (76%) create mode 100644 src/JT1078.Protocol/Audio/IAudioAttachData.cs create mode 100644 src/JT1078.Protocol/Audio/IAudioCodec.cs diff --git a/src/JT1078.Flv.Test/Audio/AudioTest.cs b/src/JT1078.Flv.Test/Audio/AudioTest.cs index 8f4f65f..0e54f58 100644 --- a/src/JT1078.Flv.Test/Audio/AudioTest.cs +++ b/src/JT1078.Flv.Test/Audio/AudioTest.cs @@ -1,5 +1,4 @@ -using JT1078.Flv.Audio; -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -26,28 +25,29 @@ namespace JT1078.Flv.Test.Audio [Fact(DisplayName = "pcm编码aac")] public void Test1() { + //todo:音频暂时先放下 ReadOnlySpan fileData = File.ReadAllBytes(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"Audio/Files/testpacket.pcm")); //注意 这里为了可以判断音频是否可用,因此使用adts,当网络传输的时候不应该使用adts - var faac = new FaacEncoder_x64(8000, 1, 16, true); - var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Audio\Files\testpacket.aac"); - if (File.Exists(path)) File.Delete(path); - output.WriteLine(path); - var offset = 0; - var step = faac.frameSize; - var totalBytes = 0; - var stopwatch = new Stopwatch(); - while (offset + step < fileData.Length) - { - stopwatch.Start(); - var aacBuff = faac.Encode(fileData.Slice(offset, step).ToArray()); - stopwatch.Stop(); - if (aacBuff.Any()) - aacBuff.AppendBytesToFile(path); - offset += step; - totalBytes += aacBuff.Length; - } - faac.Dispose(); - output.WriteLine($"已编码字节数:{offset},剩余未编码字节数:{fileData.Length - offset},编码后字节数:{totalBytes},耗时:{stopwatch.Elapsed.Milliseconds}毫秒"); + //var faac = new FaacEncoder_x64(8000, 1, 16, true); + //var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Audio\Files\testpacket.aac"); + //if (File.Exists(path)) File.Delete(path); + //output.WriteLine(path); + //var offset = 0; + //var step = faac.frameSize; + //var totalBytes = 0; + //var stopwatch = new Stopwatch(); + //while (offset + step < fileData.Length) + //{ + // stopwatch.Start(); + // var aacBuff = faac.Encode(fileData.Slice(offset, step).ToArray()); + // stopwatch.Stop(); + // if (aacBuff.Any()) + // aacBuff.AppendBytesToFile(path); + // offset += step; + // totalBytes += aacBuff.Length; + //} + //faac.Dispose(); + //output.WriteLine($"已编码字节数:{offset},剩余未编码字节数:{fileData.Length - offset},编码后字节数:{totalBytes},耗时:{stopwatch.Elapsed.Milliseconds}毫秒"); } } static class Ex diff --git a/src/JT1078.Flv/Audio/G711ACodec.cs b/src/JT1078.Flv/Audio/G711ACodec.cs deleted file mode 100644 index 57412cd..0000000 --- a/src/JT1078.Flv/Audio/G711ACodec.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace JT1078.Flv.Audio -{ - public class G711ACodec - { - private readonly int SIGN_BIT = 0x80; - private readonly int QUANT_MASK = 0xf; - private readonly int SEG_SHIFT = 4; - private readonly int SEG_MASK = 0x70; - private readonly short[] seg_end = { 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF }; - - static short Search(short val, short[] table, short size) - { - for (short i = 0; i < size; i++) - { - if (val <= table[i]) - { - return i; - } - } - return size; - } - - byte LinearToAlaw(short pcm_val) - { - short mask; - short seg; - char aval; - if (pcm_val >= 0) - { - mask = 0xD5; - } - else - { - mask = 0x55; - pcm_val = (short)(-pcm_val - 1); - if (pcm_val < 0) - { - pcm_val = 32767; - } - } - - //Convert the scaled magnitude to segment number. - seg = Search(pcm_val, seg_end, 8); - - //Combine the sign, segment, and quantization bits. - if (seg >= 8) - { - //out of range, return maximum value. - return (byte)(0x7F ^ mask); - } - else - { - aval = (char)(seg << SEG_SHIFT); - if (seg < 2) aval |= (char)((pcm_val >> 4) & QUANT_MASK); - else aval |= (char)((pcm_val >> (seg + 3)) & QUANT_MASK); - return (byte)(aval ^ mask); - } - } - - - short AlawToLinear(byte value) - { - short t; - short seg; - - value ^= 0x55; - - t = (short)((value & QUANT_MASK) << 4); - seg = (short)((value & SEG_MASK) >> SEG_SHIFT); - switch (seg) - { - case 0: - t += 8; - break; - case 1: - t += 0x108; - break; - default: - t += 0x108; - t <<= seg - 1; - break; - } - return (value & SIGN_BIT) != 0 ? t : (short)-t; - } - - /// - /// 转至PCM - /// - /// - /// - public byte[] ToPcm(byte[] g711data) - { - byte[] pcmdata = new byte[g711data.Length * 2]; - for (int i = 0, offset = 0; i < g711data.Length; i++) - { - short value = AlawToLinear(g711data[i]); - pcmdata[offset++] = (byte)(value & 0xff); - pcmdata[offset++] = (byte)((value >> 8) & 0xff); - } - return pcmdata; - } - - /// - /// 转至G711 - /// - /// - /// - public byte[] ToG711(byte[] pcmdata) - { - byte[] g711data = new byte[pcmdata.Length / 2]; - for (int i = 0, k = 0; i < pcmdata.Length; i += 2, k++) - { - short v = (short)((pcmdata[i + 1] << 8) | (pcmdata[i])); - g711data[k] = LinearToAlaw(v); - } - return g711data; - } - } -} diff --git a/src/JT1078.Flv/FlvEncoder.cs b/src/JT1078.Flv/FlvEncoder.cs index c80ddba..8b58c3e 100644 --- a/src/JT1078.Flv/FlvEncoder.cs +++ b/src/JT1078.Flv/FlvEncoder.cs @@ -4,12 +4,12 @@ using JT1078.Flv.Metadata; using JT1078.Protocol.Enums; using JT1078.Protocol.H264; using JT1078.Protocol.MessagePack; -using JT1078.Flv.Audio; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using JT1078.Protocol; +using JT1078.Protocol.Audio; [assembly: InternalsVisibleTo("JT1078.Flv.Test")] namespace JT1078.Flv @@ -35,20 +35,15 @@ namespace JT1078.Flv /// 3、第二个参数传true /// 4、第二个参数传true /// - public class FlvEncoder : IDisposable + public class FlvEncoder { - readonly IFaacEncoder faacEncoder; - readonly H264Decoder h264Decoder = new H264Decoder(); - public FlvEncoder(int sampleRate = 8000, int channels = 1, int sampleBit = 16, bool adts = false) + readonly H264Decoder h264Decoder; + readonly AudioCodecFactory audioCodecFactory; + //public FlvEncoder(int sampleRate = 8000, int channels = 1, int sampleBit = 16, bool adts = false) + public FlvEncoder() { - try - { - faacEncoder = new FaacEncoder_x86(sampleRate, channels, sampleBit, adts); - } - catch - { - faacEncoder = new FaacEncoder_x64(sampleRate, channels, sampleBit, adts); - } + audioCodecFactory = new AudioCodecFactory(); + h264Decoder = new H264Decoder(); } /// @@ -255,6 +250,7 @@ namespace JT1078.Flv /// /// 是否需要首帧音频 /// + [Obsolete("音频暂时去掉")] public byte[] EncoderAudioTag(JT1078Package package, bool needAacHeader = false) { if (package.Label3.DataType != JT1078DataType.音频帧) throw new Exception("Incorrect parameter, package must be audio frame"); @@ -263,26 +259,7 @@ namespace JT1078.Flv { flvMessagePackWriter.WriteArray(EncoderFirstAudioTag(package.Timestamp)); } - byte[] aacFrameData = null; - switch (package.Label2.PT) - { - case JT1078AVType.ADPCM: - ReadOnlySpan adpcm = package.Bodies; - // 海思芯片编码的音频需要移除海思头,可能还有其他的海思头 - if (adpcm.StartsWith(new byte[] { 0x00, 0x01, 0x52, 0x00 })) adpcm = adpcm.Slice(4); - aacFrameData = faacEncoder.Encode(new AdpcmCodec().ToPcm(adpcm.Slice(4).ToArray(), new State() - { - Valprev = (short)((adpcm[1] << 8) | adpcm[0]), - Index = adpcm[2], - Reserved = adpcm[3] - })); break; - case JT1078AVType.G711A: - aacFrameData = faacEncoder.Encode(new G711ACodec().ToPcm(package.Bodies)); - break; - case JT1078AVType.AACLC: - aacFrameData = package.Bodies; - break; - } + byte[] aacFrameData = audioCodecFactory.Encode(package.Label2.PT, package.Bodies); if (aacFrameData != null && aacFrameData.Any())//编码成功,此时为一帧aac音频数据 { // Data Tag Frame @@ -372,10 +349,5 @@ namespace JT1078.Flv FlvArrayPool.Return(buffer); } } - - public void Dispose() - { - faacEncoder.Dispose(); - } } } diff --git a/src/JT1078.Flv/JT1078.Flv.csproj b/src/JT1078.Flv/JT1078.Flv.csproj index 93fac57..87b6326 100644 --- a/src/JT1078.Flv/JT1078.Flv.csproj +++ b/src/JT1078.Flv/JT1078.Flv.csproj @@ -14,7 +14,7 @@ https://github.com/SmallChi/JT1078/blob/master/LICENSE https://github.com/SmallChi/JT1078/blob/master/LICENSE false - 1.0.0-preview7 + 1.0.0-preview8 false true LICENSE @@ -44,12 +44,4 @@ - - - Always - - - Always - - diff --git a/src/JT1078.Flv/JT1078.Flv.xml b/src/JT1078.Flv/JT1078.Flv.xml index f261003..83158de 100644 --- a/src/JT1078.Flv/JT1078.Flv.xml +++ b/src/JT1078.Flv/JT1078.Flv.xml @@ -4,53 +4,6 @@ JT1078.Flv - - - 上一个采样数据,当index为0是该值应该为未压缩的原数据 - - - - - 保留数据(未使用) - - - - - 上一个block最后一个index,第一个block的index=0 - - - - - 将adpcm转为pcm - - - - - - - - 添加wav头 - 仅用于测试pcm是否转成成功,因此没考虑性能,因为播放器可播——# - - pcm数据 - 采样率 - 位深 - - - - - 转至PCM - - - - - - - 转至G711 - - - - @@ -210,7 +163,7 @@ Flv编码器 一个客户端对应一个实例 - 当实例不适用时,尽量手动调用下 + 当实例不适用时,尽量手动调用下 手动编码 diff --git a/src/JT1078.Flv/nativelibs/x64/libfaac.dll b/src/JT1078.Flv/nativelibs/x64/libfaac.dll deleted file mode 100644 index c9f2e4588ca41667749854ddeafd69df9fbf9262..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 71168 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 )JyE-%3eJz#^9s5Hn?9U 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 D*abW` diff --git a/src/JT1078.Hls/JT1078.Hls.xml b/src/JT1078.Hls/JT1078.Hls.xml index ce1d838..2b52151 100644 --- a/src/JT1078.Hls/JT1078.Hls.xml +++ b/src/JT1078.Hls/JT1078.Hls.xml @@ -114,7 +114,8 @@ 创建M3U8文件 - + 当前ts文件信息 + ts文件信息队列 @@ -123,11 +124,12 @@ - + 创建TS文件 ts文件路径 + 终端号_通道号(用作目录) 文件内容 diff --git a/src/JT1078.Flv/Audio/AdpcmCodec.cs b/src/JT1078.Protocol/Audio/AdpcmCodec.cs similarity index 57% rename from src/JT1078.Flv/Audio/AdpcmCodec.cs rename to src/JT1078.Protocol/Audio/AdpcmCodec.cs index cc325d9..eaebcc7 100644 --- a/src/JT1078.Flv/Audio/AdpcmCodec.cs +++ b/src/JT1078.Protocol/Audio/AdpcmCodec.cs @@ -2,26 +2,9 @@ using System.Collections.Generic; using System.Text; -namespace JT1078.Flv.Audio +namespace JT1078.Protocol.Audio { - public class State - { - /// - /// 上一个采样数据,当index为0是该值应该为未压缩的原数据 - /// - public short Valprev { get; set; } - - /// - /// 保留数据(未使用) - /// - public byte Reserved { get; set; } - - /// - /// 上一个block最后一个index,第一个block的index=0 - /// - public byte Index { get; set; } - } - public class AdpcmCodec + public class AdpcmCodec: IAudioCodec { static readonly int[] indexTable = { -1, -1, -1, -1, 2, 4, 6, 8, @@ -39,119 +22,122 @@ namespace JT1078.Flv.Audio 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 }; - public static byte[] ToAdpcm(short[] indata, State state) - { - int val; /* Current input sample value */ - int sign; /* Current adpcm sign bit */ - int delta; /* Current adpcm output value */ - int diff; /* Difference between val and valprev */ - int step; /* Stepsize */ - int valpred; /* Predicted output value */ - int vpdiff; /* Current change to valpred */ - int index; /* Current step change index */ - int outputbuffer = 0; /* place to keep previous 4-bit value */ - int bufferstep; /* toggle between outputbuffer/output */ - List outp = new List(); - short[] inp = indata; - var len = indata.Length; - valpred = state.Valprev; - index = state.Index; - step = stepsizeTable[index]; + //public static byte[] ToAdpcm(short[] indata, AdpcmState state) + //{ + // int val; /* Current input sample value */ + // int sign; /* Current adpcm sign bit */ + // int delta; /* Current adpcm output value */ + // int diff; /* Difference between val and valprev */ + // int step; /* Stepsize */ + // int valpred; /* Predicted output value */ + // int vpdiff; /* Current change to valpred */ + // int index; /* Current step change index */ + // int outputbuffer = 0; /* place to keep previous 4-bit value */ + // int bufferstep; /* toggle between outputbuffer/output */ - bufferstep = 1; + // List outp = new List(); + // short[] inp = indata; + // var len = indata.Length; + // valpred = state.Valprev; + // index = state.Index; + // step = stepsizeTable[index]; - int k = 0; - for (int i = 0; len > 0; len--, i++) - { - val = inp[i]; + // bufferstep = 1; - /* Step 1 - compute difference with previous value */ - diff = val - valpred; - sign = (diff < 0) ? 8 : 0; - if (sign != 0) diff = (-diff); + // int k = 0; + // for (int i = 0; len > 0; len--, i++) + // { + // val = inp[i]; - /* Step 2 - Divide and clamp */ - /* Note: - ** This code *approximately* computes: - ** delta = diff*4/step; - ** vpdiff = (delta+0.5)*step/4; - ** but in shift step bits are dropped. The net result of this is - ** that even if you have fast mul/div hardware you cannot put it to - ** good use since the fixup would be too expensive. - */ - delta = 0; - vpdiff = (step >> 3); + // /* Step 1 - compute difference with previous value */ + // diff = val - valpred; + // sign = (diff < 0) ? 8 : 0; + // if (sign != 0) diff = (-diff); - if (diff >= step) - { - delta = 4; - diff -= step; - vpdiff += step; - } - step >>= 1; - if (diff >= step) - { - delta |= 2; - diff -= step; - vpdiff += step; - } - step >>= 1; - if (diff >= step) - { - delta |= 1; - vpdiff += step; - } + // /* Step 2 - Divide and clamp */ + // /* Note: + // ** This code *approximately* computes: + // ** delta = diff*4/step; + // ** vpdiff = (delta+0.5)*step/4; + // ** but in shift step bits are dropped. The net result of this is + // ** that even if you have fast mul/div hardware you cannot put it to + // ** good use since the fixup would be too expensive. + // */ + // delta = 0; + // vpdiff = (step >> 3); - /* Step 3 - Update previous value */ - if (sign != 0) - valpred -= vpdiff; - else - valpred += vpdiff; + // if (diff >= step) + // { + // delta = 4; + // diff -= step; + // vpdiff += step; + // } + // step >>= 1; + // if (diff >= step) + // { + // delta |= 2; + // diff -= step; + // vpdiff += step; + // } + // step >>= 1; + // if (diff >= step) + // { + // delta |= 1; + // vpdiff += step; + // } - /* Step 4 - Clamp previous value to 16 bits */ - if (valpred > 32767) - valpred = 32767; - else if (valpred < -32768) - valpred = -32768; + // /* Step 3 - Update previous value */ + // if (sign != 0) + // valpred -= vpdiff; + // else + // valpred += vpdiff; - /* Step 5 - Assemble value, update index and step values */ - delta |= sign; + // /* Step 4 - Clamp previous value to 16 bits */ + // if (valpred > 32767) + // valpred = 32767; + // else if (valpred < -32768) + // valpred = -32768; - index += indexTable[delta]; - if (index < 0) index = 0; - if (index > 88) index = 88; - step = stepsizeTable[index]; + // /* Step 5 - Assemble value, update index and step values */ + // delta |= sign; - /* Step 6 - Output value */ - if (bufferstep != 0) - { - outputbuffer = (delta << 4) & 0xf0; - } - else - { - outp.Add((byte)((delta & 0x0f) | outputbuffer)); - } - bufferstep = bufferstep == 0 ? 1 : 0; - } + // index += indexTable[delta]; + // if (index < 0) index = 0; + // if (index > 88) index = 88; + // step = stepsizeTable[index]; - /* Output last step, if needed */ - if (bufferstep == 0) - outp.Add((byte)outputbuffer); + // /* Step 6 - Output value */ + // if (bufferstep != 0) + // { + // outputbuffer = (delta << 4) & 0xf0; + // } + // else + // { + // outp.Add((byte)((delta & 0x0f) | outputbuffer)); + // } + // bufferstep = bufferstep == 0 ? 1 : 0; + // } - state.Valprev = (short)valpred; - state.Index = (byte)index; - return outp.ToArray(); - } + // /* Output last step, if needed */ + // if (bufferstep == 0) + // outp.Add((byte)outputbuffer); + + // state.Valprev = (short)valpred; + // state.Index = (byte)index; + // return outp.ToArray(); + //} /// /// 将adpcm转为pcm /// /// - /// + /// + /// /// - public byte[] ToPcm(byte[] data, State state) + public byte[] ToPcm(byte[] audio, IAudioAttachData audioAttachData) { + AdpcmState state = (AdpcmState)audioAttachData; // signed char *inp; /* Input buffer pointer */ // short *outp; /* output buffer pointer */ int sign; /* Current adpcm sign bit */ @@ -166,7 +152,7 @@ namespace JT1078.Flv.Audio step = stepsizeTable[index]; var outdata = new List(); - var len = data.Length * 2; + var len = audio.Length * 2; for (int i = 0; len > 0; len--) { /* Step 1 - get the delta value */ @@ -176,7 +162,7 @@ namespace JT1078.Flv.Audio } else { - inputbuffer = data[i++]; + inputbuffer = audio[i++]; delta = (inputbuffer >> 4) & 0xf; } bufferstep = !bufferstep; @@ -222,7 +208,23 @@ namespace JT1078.Flv.Audio return outdata.ToArray(); } } + public class AdpcmState : IAudioAttachData + { + /// + /// 上一个采样数据,当index为0是该值应该为未压缩的原数据 + /// + public short Valprev { get; set; } + + /// + /// 保留数据(未使用) + /// + public byte Reserved { get; set; } + /// + /// 上一个block最后一个index,第一个block的index=0 + /// + public byte Index { get; set; } + } public static class AdpcmDecoderExtension { /// diff --git a/src/JT1078.Protocol/Audio/AudioCodecFactory.cs b/src/JT1078.Protocol/Audio/AudioCodecFactory.cs new file mode 100644 index 0000000..5b7d354 --- /dev/null +++ b/src/JT1078.Protocol/Audio/AudioCodecFactory.cs @@ -0,0 +1,47 @@ +using JT1078.Protocol.Enums; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.Protocol.Audio +{ + public class AudioCodecFactory + { + private readonly AdpcmCodec adpcmCodec = new AdpcmCodec(); + private readonly G711ACodec g711ACodec = new G711ACodec(); + private readonly G711UCodec g711UCodec = new G711UCodec(); + //海思芯片编码的音频需要移除海思头,可能还有其他的海思头 + private static byte[] HI = new byte[] { 0x00, 0x01, 0x52, 0x00 }; + public byte[] Encode(JT1078AVType aVType,byte[]bodies) + { + byte[] pcm = null; + switch (aVType) + { + case JT1078AVType.ADPCM: + ReadOnlySpan adpcm = bodies; + if (adpcm.StartsWith(HI)) adpcm = adpcm.Slice(4); + pcm = adpcmCodec.ToPcm(adpcm.Slice(4).ToArray(), new AdpcmState() + { + Valprev = (short)((adpcm[1] << 8) | adpcm[0]), + Index = adpcm[2], + Reserved = adpcm[3] + }); + //todo:编码mp3 + return pcm; + case JT1078AVType.G711A: + pcm=g711ACodec.ToPcm(bodies, null); + //todo:编码mp3 + return pcm; + case JT1078AVType.AACLC: + //直接AAC出去 + return bodies; + case JT1078AVType.MP3: + //直接MP3出去 + return bodies; + default: + + return bodies; + } + } + } +} diff --git a/src/JT1078.Flv/Audio/FaacEncoder.cs b/src/JT1078.Protocol/Audio/FaacEncoder.cs similarity index 99% rename from src/JT1078.Flv/Audio/FaacEncoder.cs rename to src/JT1078.Protocol/Audio/FaacEncoder.cs index c5c9283..c5adbf9 100644 --- a/src/JT1078.Flv/Audio/FaacEncoder.cs +++ b/src/JT1078.Protocol/Audio/FaacEncoder.cs @@ -3,9 +3,8 @@ using System.Collections.Generic; using System.Text; using System.Linq; using System.Runtime.InteropServices; -using JT1078.Flv.Extensions; -namespace JT1078.Flv.Audio +namespace JT1078.Protocol.Audio { public interface IFaacEncoder:IDisposable { diff --git a/src/JT1078.Protocol/Audio/G711ACodec.cs b/src/JT1078.Protocol/Audio/G711ACodec.cs new file mode 100644 index 0000000..d662bcc --- /dev/null +++ b/src/JT1078.Protocol/Audio/G711ACodec.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.Protocol.Audio +{ + public class G711ACodec: IAudioCodec + { + private readonly int SIGN_BIT = 0x80; + private readonly int QUANT_MASK = 0xf; + private readonly int SEG_SHIFT = 4; + private readonly int SEG_MASK = 0x70; + //private readonly short[] seg_end = { 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF }; + short AlawToLinear(byte value) + { + short t; + short seg; + value ^= 0x55; + t = (short)((value & QUANT_MASK) << 4); + seg = (short)((value & SEG_MASK) >> SEG_SHIFT); + switch (seg) + { + case 0: + t += 8; + break; + case 1: + t += 0x108; + break; + default: + t += 0x108; + t <<= seg - 1; + break; + } + return (value & SIGN_BIT) != 0 ? t : (short)-t; + } + + public byte[] ToPcm(byte[] audio, IAudioAttachData audioAttachData) + { + byte[] pcmdata = new byte[audio.Length * 2]; + for (int i = 0, offset = 0; i < audio.Length; i++) + { + short value = AlawToLinear(audio[i]); + pcmdata[offset++] = (byte)(value & 0xff); + pcmdata[offset++] = (byte)((value >> 8) & 0xff); + } + return pcmdata; + } + + //static short Search(short val, short[] table, short size) + //{ + // for (short i = 0; i < size; i++) + // { + // if (val <= table[i]) + // { + // return i; + // } + // } + // return size; + //} + + //byte LinearToAlaw(short pcm_val) + //{ + // short mask; + // short seg; + // char aval; + // if (pcm_val >= 0) + // { + // mask = 0xD5; + // } + // else + // { + // mask = 0x55; + // pcm_val = (short)(-pcm_val - 1); + // if (pcm_val < 0) + // { + // pcm_val = 32767; + // } + // } + + // //Convert the scaled magnitude to segment number. + // seg = Search(pcm_val, seg_end, 8); + + // //Combine the sign, segment, and quantization bits. + // if (seg >= 8) + // { + // //out of range, return maximum value. + // return (byte)(0x7F ^ mask); + // } + // else + // { + // aval = (char)(seg << SEG_SHIFT); + // if (seg < 2) aval |= (char)((pcm_val >> 4) & QUANT_MASK); + // else aval |= (char)((pcm_val >> (seg + 3)) & QUANT_MASK); + // return (byte)(aval ^ mask); + // } + //} + + ///// + ///// 转至G711 + ///// + ///// + ///// + //public byte[] ToG711(byte[] pcmdata) + //{ + // byte[] g711data = new byte[pcmdata.Length / 2]; + // for (int i = 0, k = 0; i < pcmdata.Length; i += 2, k++) + // { + // short v = (short)((pcmdata[i + 1] << 8) | (pcmdata[i])); + // g711data[k] = LinearToAlaw(v); + // } + // return g711data; + //} + } +} diff --git a/src/JT1078.Flv/Audio/G711UCodec.cs b/src/JT1078.Protocol/Audio/G711UCodec.cs similarity index 76% rename from src/JT1078.Flv/Audio/G711UCodec.cs rename to src/JT1078.Protocol/Audio/G711UCodec.cs index 641999c..6d7df5a 100644 --- a/src/JT1078.Flv/Audio/G711UCodec.cs +++ b/src/JT1078.Protocol/Audio/G711UCodec.cs @@ -2,13 +2,12 @@ using System.Collections.Generic; using System.Text; -namespace JT1078.Flv.Audio +namespace JT1078.Protocol.Audio { - public class G711UCodec + public class G711UCodec: IAudioCodec { /* 16384 entries per table (16 bit) */ readonly byte[] linearToUlawTable = new byte[65536]; - /* 16384 entries per table (8 bit) */ readonly short[] ulawToLinearTable = new short[256]; readonly int SIGN_BIT = 0x80; @@ -90,23 +89,26 @@ namespace JT1078.Flv.Audio return pcmSamples; } - private byte[] Pcm16ToUlaw(byte[] pcmSamples) - { - short[] dst = new short[pcmSamples.Length / 2]; - byte[] ulawSamples = new byte[pcmSamples.Length / 2]; - for (int i = 0, k = 0; i < pcmSamples.Length;) - { - dst[k++] = (short)((pcmSamples[i++] & 0xff) | ((pcmSamples[i++] & 0xff) << 8)); - } - for (int i = 0, k = 0; i < dst.Length; i++) - { - ulawSamples[k++] = Linear2ulaw(dst[i]); - } - return ulawSamples; - } + //private byte[] Pcm16ToUlaw(byte[] pcmSamples) + //{ + // short[] dst = new short[pcmSamples.Length / 2]; + // byte[] ulawSamples = new byte[pcmSamples.Length / 2]; + // for (int i = 0, k = 0; i < pcmSamples.Length;) + // { + // dst[k++] = (short)((pcmSamples[i++] & 0xff) | ((pcmSamples[i++] & 0xff) << 8)); + // } + // for (int i = 0, k = 0; i < dst.Length; i++) + // { + // ulawSamples[k++] = Linear2ulaw(dst[i]); + // } + // return ulawSamples; + //} - public byte[] ToPcm(byte[] data) => UlawToPcm16(data); + //public byte[] ToG711(byte[] data) => Pcm16ToUlaw(data); - public byte[] ToG711(byte[] data) => Pcm16ToUlaw(data); + public byte[] ToPcm(byte[] audio, IAudioAttachData audioAttachData) + { + return UlawToPcm16(audio); + } } } diff --git a/src/JT1078.Protocol/Audio/IAudioAttachData.cs b/src/JT1078.Protocol/Audio/IAudioAttachData.cs new file mode 100644 index 0000000..5834f24 --- /dev/null +++ b/src/JT1078.Protocol/Audio/IAudioAttachData.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.Protocol.Audio +{ + public interface IAudioAttachData + { + } +} diff --git a/src/JT1078.Protocol/Audio/IAudioCodec.cs b/src/JT1078.Protocol/Audio/IAudioCodec.cs new file mode 100644 index 0000000..2eb55e4 --- /dev/null +++ b/src/JT1078.Protocol/Audio/IAudioCodec.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT1078.Protocol.Audio +{ + public interface IAudioCodec + { + byte[] ToPcm(byte[] audio, IAudioAttachData audioAttachData); + } +} diff --git a/src/JT1078.Protocol/JT1078.Protocol.csproj b/src/JT1078.Protocol/JT1078.Protocol.csproj index 4b02b45..1c926b5 100644 --- a/src/JT1078.Protocol/JT1078.Protocol.csproj +++ b/src/JT1078.Protocol/JT1078.Protocol.csproj @@ -14,7 +14,7 @@ https://github.com/SmallChi/JT1078/blob/master/LICENSE https://github.com/SmallChi/JT1078/blob/master/LICENSE false - 1.0.3 + 1.0.4-preview1 false true LICENSE @@ -24,6 +24,11 @@ + + + + +