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 c9f2e45..0000000 Binary files a/src/JT1078.Flv/nativelibs/x64/libfaac.dll and /dev/null differ diff --git a/src/JT1078.Flv/nativelibs/x86/libfaac.dll b/src/JT1078.Flv/nativelibs/x86/libfaac.dll deleted file mode 100644 index a67c71f..0000000 Binary files a/src/JT1078.Flv/nativelibs/x86/libfaac.dll and /dev/null differ 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 @@ + + + + +