diff --git a/src/JT1078.Flv.Test/FlvEncoderTest.cs b/src/JT1078.Flv.Test/FlvEncoderTest.cs index ea95ae0..dc0547f 100644 --- a/src/JT1078.Flv.Test/FlvEncoderTest.cs +++ b/src/JT1078.Flv.Test/FlvEncoderTest.cs @@ -20,306 +20,133 @@ namespace JT1078.Flv.Test [Fact] public void 测试第一帧的数据() { - JT1078Package Package = null; - var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_1.txt")); - int mergeBodyLength = 0; - foreach (var line in lines) + FileStream fileStream = null; + try { - var data = line.Split(','); - var bytes = data[6].ToHexBytes(); - JT1078Package package = JT1078Serializer.Deserialize(bytes); - mergeBodyLength += package.DataBodyLength; - Package = JT1078Serializer.Merge(package); + var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_1.txt")); + var filepath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_1.flv"); + fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); + + bool isNeedFirstHeadler = true; + FlvEncoder encoder = new FlvEncoder(); + foreach (var line in lines) + { + var data = line.Split(','); + var bytes = data[6].ToHexBytes(); + JT1078Package package = JT1078Serializer.Deserialize(bytes); + JT1078Package fullpackage = JT1078Serializer.Merge(package); + if (fullpackage != null) + { + var videoTag = encoder.EncoderVideoTag(fullpackage, isNeedFirstHeadler); + fileStream.Write(videoTag); + isNeedFirstHeadler = false; + } + } } - H264Decoder decoder = new H264Decoder(); - //7 8 6 5 1 1 1 1 1 7 8 6 5 1 1 1 1 - var nalus = decoder.ParseNALU(Package); - Assert.Equal(4, nalus.Count); + catch (Exception ex) + { - FlvEncoder encoder = new FlvEncoder(); - var filepath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_1.flv"); - if (File.Exists(filepath)) + } + finally { - File.Delete(filepath); + fileStream?.Close(); + fileStream?.Dispose(); } - FileStream fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); - fileStream.Write(encoder.EncoderFlvHeader()); - fileStream.Write(encoder.EncoderScriptTag()); - fileStream.Write(encoder.EncoderVideoTag(Package, true)); - fileStream.Close(); } - //[Fact] - //public void 测试前几帧的数据() - //{ - // FileStream fileStream = null; - // try - // { - // JT1078Package Package = null; - // List h264NALULs = new List(); - // H264Decoder decoder = new H264Decoder(); - // FlvEncoder encoder = new FlvEncoder(); - // var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_2.txt")); - // foreach (var line in lines) - // { - // var data = line.Split(','); - // var bytes = data[6].ToHexBytes(); - // JT1078Package package = JT1078Serializer.Deserialize(bytes); - // Package = JT1078Serializer.Merge(package); - // if (Package != null) - // { - // var tmp = decoder.ParseNALU(Package); - // if (tmp != null && tmp.Count > 0) - // { - // h264NALULs = h264NALULs.Concat(tmp).ToList(); - // } - // } - // } - - // var filepath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_2.flv"); - // if (File.Exists(filepath)) - // { - // File.Delete(filepath); - // } - // fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); - // fileStream.Write(FlvEncoder.VideoFlvHeaderBuffer); - // var totalPage = (h264NALULs.Count + 10 - 1) / 10; - // for (var i = 0; i < totalPage; i++) - // { - // var flv2 = encoder.CreateFlvFrame(h264NALULs.Skip(i * 10).Take(10).ToList()); - // if (flv2.Length != 0) - // { - // fileStream.Write(flv2); - // } - // } - // } - // catch (Exception ex) - // { - - // } - // finally - // { - // fileStream?.Close(); - // fileStream?.Dispose(); - // } - //} - - //[Fact] - //public void 测试可以播放的Flv1() - //{ - // FileStream fileStream = null; - // H264Decoder decoder = new H264Decoder(); - // List h264NALULs = new List(); - // FlvEncoder encoder = new FlvEncoder(); - // try - // { - // var filepath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_3.flv"); - // var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_3.txt")); - // if (File.Exists(filepath)) - // { - // File.Delete(filepath); - // } - - // JT1078Package Package = null; - - // foreach (var line in lines) - // { - // var data = line.Split(','); - // var bytes = data[6].ToHexBytes(); - // JT1078Package package = JT1078Serializer.Deserialize(bytes); - // Package = JT1078Serializer.Merge(package); - // if (Package != null) - // { - // var tmp = decoder.ParseNALU(Package); - // if (tmp != null && tmp.Count > 0) - // { - // h264NALULs = h264NALULs.Concat(tmp).ToList(); - // } - // } - // } - - // fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); - // fileStream.Write(FlvEncoder.VideoFlvHeaderBuffer); - // var totalPage = (h264NALULs.Count + 10 - 1) / 10; - // for (var i = 0; i < totalPage; i++) - // { - // var flv2 = encoder.CreateFlvFrame(h264NALULs.Skip(i * 10).Take(10).ToList()); - // if (flv2.Length != 0) - // { - // fileStream.Write(flv2); - // } - // } - // } - // catch (Exception ex) - // { - // Assert.Throws(() => { }); - // } - // finally - // { - // fileStream?.Close(); - // fileStream?.Dispose(); - // } - //} - - //[Fact] - //public void 测试可以播放的Flv2() - //{ - // FileStream fileStream = null; - // H264Decoder decoder = new H264Decoder(); - // List h264NALULs = new List(); - // FlvEncoder encoder = new FlvEncoder(); - // try - // { - // var filepath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_4.flv"); - // var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_4.txt")); - // if (File.Exists(filepath)) - // { - // File.Delete(filepath); - // } - - // JT1078Package Package = null; - - // foreach (var line in lines) - // { - // var data = line.Split(','); - // var bytes = data[6].ToHexBytes(); - // JT1078Package package = JT1078Serializer.Deserialize(bytes); - // Package = JT1078Serializer.Merge(package); - // if (Package != null) - // { - // var tmp = decoder.ParseNALU(Package); - // if (tmp != null && tmp.Count > 0) - // { - // h264NALULs = h264NALULs.Concat(tmp).ToList(); - // } - // } - // } - - // fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); - // fileStream.Write(FlvEncoder.VideoFlvHeaderBuffer); - // var totalPage = (h264NALULs.Count + 10 - 1) / 10; - // for (var i = 0; i < totalPage; i++) - // { - // var flv2 = encoder.CreateFlvFrame(h264NALULs.Skip(i * 10).Take(10).ToList()); - // if (flv2.Length != 0) - // { - // fileStream.Write(flv2); - // } - // } - // } - // catch (Exception ex) - // { - // Assert.Throws(() => { }); - // } - // finally - // { - // fileStream?.Close(); - // fileStream?.Dispose(); - // } - //} - - //[Fact] - //public void 测试主次码流切换() - //{ - // FileStream fileStream = null; - // H264Decoder decoder = new H264Decoder(); - // List h264NALULs = new List(); - // FlvEncoder encoder = new FlvEncoder(); - // try - // { - // var filepath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_5.flv"); - // var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_5.txt")); - // if (File.Exists(filepath)) - // { - // File.Delete(filepath); - // } - - // JT1078Package Package = null; + [Fact] + public void 测试前几帧的数据() + { + FileStream fileStream = null; + try + { + var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_2.txt")); + var filepath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_2.flv"); + fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); + + bool isNeedFirstHeadler = true; + FlvEncoder encoder = new FlvEncoder(); + foreach (var line in lines) + { + var data = line.Split(','); + var bytes = data[6].ToHexBytes(); + JT1078Package package = JT1078Serializer.Deserialize(bytes); + JT1078Package fullpackage = JT1078Serializer.Merge(package); + if (fullpackage != null) + { + var videoTag = encoder.EncoderVideoTag(fullpackage, isNeedFirstHeadler); + fileStream.Write(videoTag); + isNeedFirstHeadler = false; + } + } + } + catch (Exception ex) + { - // foreach (var line in lines) - // { - // var data = line.Split(','); - // var bytes = data[6].ToHexBytes(); - // JT1078Package package = JT1078Serializer.Deserialize(bytes); - // Package = JT1078Serializer.Merge(package); - // if (Package != null) - // { - // var tmp = decoder.ParseNALU(Package); - // if (tmp != null && tmp.Count > 0) - // { - // h264NALULs = h264NALULs.Concat(tmp).ToList(); - // } - // } - // } - // var tmp1 = h264NALULs.Where(w => w.NALUHeader.NalUnitType == 7).ToList(); - // List tmpSpss = new List(); - // List times = new List(); - // List lastIFrameIntervals = new List(); - // List lastFrameIntervals = new List(); - // List type = new List(); - // foreach (var item in h264NALULs) - // { - // //type.Add(item.NALUHeader.NalUnitType); - // times.Add(item.Timestamp); - // lastFrameIntervals.Add(item.LastFrameInterval); - // lastIFrameIntervals.Add(item.LastIFrameInterval); - // if (item.NALUHeader.NalUnitType == 7) - // { - // ExpGolombReader expGolombReader = new ExpGolombReader(item.RawData); - // tmpSpss.Add(expGolombReader.ReadSPS()); - // } - // } - // fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); - // var totalPage = (h264NALULs.Count + 10 - 1) / 10; - // for (var i = 0; i < totalPage; i++) - // { - // var flv2 = encoder.CreateFlvFrame(h264NALULs.Skip(i * 10).Take(10).ToList()); - // if (flv2.Length != 0) - // { - // //fileStream.Write(flv2); - // } - // } - // } - // catch (Exception ex) - // { - // Assert.Throws(() => { }); - // } - // finally - // { - // fileStream?.Close(); - // fileStream?.Dispose(); - // } - //} + } + finally + { + fileStream?.Close(); + fileStream?.Dispose(); + } + } - //[Fact] - //public void CreateScriptTagFrameTest() - //{ - // FlvEncoder flvEncoder = new FlvEncoder(); - // var hexData = flvEncoder.CreateScriptTagFrame(288, 352); - // Assert.Equal(151, hexData.Length); - //} + [Fact] + public void 测试可以播放的Flv3() + { + FileStream fileStream = null; + try + { + var filepath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_3.flv"); + var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_3.txt")); + fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); + + bool isNeedFirstHeadler = true; + FlvEncoder encoder = new FlvEncoder(); + foreach (var line in lines) + { + var data = line.Split(','); + var bytes = data[6].ToHexBytes(); + JT1078Package package = JT1078Serializer.Deserialize(bytes); + JT1078Package fullpackage = JT1078Serializer.Merge(package); + if (fullpackage != null) + { + var videoTag = encoder.EncoderVideoTag(fullpackage, isNeedFirstHeadler); + fileStream.Write(videoTag); + isNeedFirstHeadler = false; + } + } + } + catch (Exception ex) + { + Assert.Throws(() => { }); + } + finally + { + fileStream?.Close(); + fileStream?.Dispose(); + } + } - //[Fact] - //public void CreateVideoTag0FrameTest() - //{ - // FlvEncoder flvEncoder = new FlvEncoder(); - // var hexData = flvEncoder.CreateVideoTag0Frame( - // new byte[] { 0x67, 0x4D, 0, 0x14, 0x95, 0xA8, 0x58, 0x25, 0x90 }, - // new byte[] { 0x68, 0xEE, 0x3C, 0x80 }, - // new SPSInfo { levelIdc = 0x14, profileIdc = 0x4d, profileCompat = 0 }); - // Assert.Equal(40, hexData.Length); - //} + [Fact] + public void EncoderScriptTag() + { + FlvEncoder flvEncoder = new FlvEncoder(); + var hexData = flvEncoder.EncoderScriptTag(new SPSInfo { width = 288, height = 352 }); + Assert.Equal(155, hexData.Length); + } - //[Fact] - //public void GetFirstFlvFrameTest() - //{ - // FlvEncoder flvEncoder = new FlvEncoder(); - // string key = "test"; - // var bufferFlvFrame = new byte[] { 0xA, 0xB, 0xC, 0xD, 0xE, 0xF }; - // FlvEncoder.FirstFlvFrameCache.TryAdd(key, (2, new byte[] { 1, 2, 3, 4, 5, 6 }, true)); - // var buffer = flvEncoder.GetFirstFlvFrame(key, bufferFlvFrame); - // //替换PreviousTagSize 4位的长度为首帧的 PreviousTagSize - // Assert.Equal(new byte[] { 1, 2, 3, 4, 5, 6, 0, 0, 0, 2, 0xE, 0xF }, buffer); - //} + [Fact] + public void EncoderFirstVideoTag() + { + FlvEncoder flvEncoder = new FlvEncoder(); + var hexData = flvEncoder.EncoderFirstVideoTag( + new SPSInfo { levelIdc = 0x14, profileIdc = 0x4d, profileCompat = 0 }, + new H264NALU { RawData = new byte[] { 0x67, 0x4D, 0, 0x14, 0x95, 0xA8, 0x58, 0x25, 0x90 } }, + new H264NALU { RawData = new byte[] { 0x68, 0xEE, 0x3C, 0x80 } }, + new H264NALU() + ); + Assert.Equal(44, hexData.Length); + } } } diff --git a/src/JT1078.Flv.Test/H264ToFlvTest.cs b/src/JT1078.Flv.Test/H264ToFlvTest.cs index 7cb0605..94e3c46 100644 --- a/src/JT1078.Flv.Test/H264ToFlvTest.cs +++ b/src/JT1078.Flv.Test/H264ToFlvTest.cs @@ -12,6 +12,9 @@ namespace JT1078.Flv.Test { public class H264ToFlvTest { + /// + /// jt1078 转成 H264数据包 + /// [Fact] public void Test_1() { diff --git a/src/JT1078.Flv/FlvEncoder.cs b/src/JT1078.Flv/FlvEncoder.cs index 20c9a37..a2f56f9 100644 --- a/src/JT1078.Flv/FlvEncoder.cs +++ b/src/JT1078.Flv/FlvEncoder.cs @@ -22,7 +22,8 @@ namespace JT1078.Flv /// /// /// 手动编码 - /// 1、 + /// 0、 + /// 1、插入 PriviousTagSize =0 always equal 0 /// 2、 /// 3、 /// 4、 @@ -36,11 +37,8 @@ namespace JT1078.Flv /// public class FlvEncoder : IDisposable { - uint previousTagSize; - FlvHeader flvHeader = new FlvHeader(true, true); readonly FaacEncoder faacEncoder; readonly H264Decoder h264Decoder = new H264Decoder(); - public FlvEncoder(int sampleRate = 8000, int channels = 1, int sampleBit = 16, bool adts = false) { faacEncoder = new FaacEncoder(sampleRate, channels, sampleBit, adts); @@ -48,32 +46,24 @@ namespace JT1078.Flv /// /// 编码flv头 - /// - /// 注意:本方法已写入 - /// /// - /// - /// + /// 是否有视频 + /// 是否有音频 /// public byte[] EncoderFlvHeader(bool hasVideo = true, bool hasAudio = false) { - previousTagSize = 0; - flvHeader = new FlvHeader(hasVideo, hasAudio); + var flvHeader = new FlvHeader(hasVideo, hasAudio); return flvHeader.ToArray().ToArray(); } /// /// 编码脚本Tag - /// - /// 注意:本方法已写入 - /// /// - /// 视频宽度 - /// 视频高度 - /// 是否含有音频,如果有,则写入音频配置,后来发现即便是有音频,这里给false也没关系 - /// 帧率 + /// 解析后的sps信息 + /// 是否有音频 + /// 帧率 默认25d 即每秒25帧 /// - public byte[] EncoderScriptTag(bool hasAudio = false, double frameRate = 25d) + public byte[] EncoderScriptTag(SPSInfo spsInfo, bool hasAudio = false, double frameRate = 25d) { byte[] buffer = FlvArrayPool.Rent(1024); try @@ -93,8 +83,12 @@ namespace JT1078.Flv new Amf3Metadata_VideoDataRate{Value = 0d}, new Amf3Metadata_VideoCodecId{Value = 7d}, new Amf3Metadata_FrameRate{Value = frameRate}, - new Amf3Metadata_Width(), - new Amf3Metadata_Height(), + new Amf3Metadata_Width(){ + Value=spsInfo.width + }, + new Amf3Metadata_Height(){ + Value=spsInfo.height + }, } } }; @@ -105,11 +99,9 @@ namespace JT1078.Flv flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_AudioSampleSize()); flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_AudioStereo()); } - flvMessagePackWriter.WriteUInt32(previousTagSize); flvMessagePackWriter.WriteFlvTag(flvTags); - var data = flvMessagePackWriter.FlushAndGetArray(); - previousTagSize = (uint)(flvTags.DataSize + 11); - return data; + flvMessagePackWriter.WriteUInt32((uint)(flvTags.DataSize + 11)); + return flvMessagePackWriter.FlushAndGetArray(); } finally { @@ -118,24 +110,19 @@ namespace JT1078.Flv } /// - /// 编码首帧视频,即videoTag[0] - /// - /// 注意:本方法已写入 - /// + /// 编码首帧视频,即videoTag[0] /// + /// sps 解析后的数据 /// /// /// /// - public byte[] EncoderFirstVideoTag(H264NALU sps, H264NALU pps, H264NALU sei) + public byte[] EncoderFirstVideoTag(SPSInfo spsInfo, H264NALU sps, H264NALU pps, H264NALU sei) { byte[] buffer = FlvArrayPool.Rent(2048); try { FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer); - var rawData = h264Decoder.DiscardEmulationPreventionBytes(sps.RawData); - ExpGolombReader h264GolombReader = new ExpGolombReader(rawData); - SPSInfo spsInfo = h264GolombReader.ReadSPS(); //flv body video tag //flv body tag header FlvTags flvTags = new FlvTags @@ -163,11 +150,9 @@ namespace JT1078.Flv SPSBuffer = sps.RawData }; flvTags.VideoTagsData.VideoData.AVCDecoderConfiguration = aVCDecoderConfigurationRecord; - flvMessagePackWriter.WriteUInt32(previousTagSize); flvMessagePackWriter.WriteFlvTag(flvTags); - var data = flvMessagePackWriter.FlushAndGetArray(); - previousTagSize = (uint)(flvTags.DataSize + 11); - return data; + flvMessagePackWriter.WriteUInt32((uint)(flvTags.DataSize + 11)); + return flvMessagePackWriter.FlushAndGetArray(); } finally { @@ -177,10 +162,8 @@ namespace JT1078.Flv /// /// 编码首帧音频,即audioTag[0] - /// - /// 注意:本方法已写入 - /// /// + /// /// public byte[] EncoderFirstAudioTag(ulong timestamp) { @@ -197,11 +180,9 @@ namespace JT1078.Flv //flv body tag body AudioTagsData = new AudioTags(AACPacketType.AudioSpecificConfig) }; - flvMessagePackWriter.WriteUInt32(previousTagSize); flvMessagePackWriter.WriteFlvTag(flvTags); - var data = flvMessagePackWriter.FlushAndGetArray(); - previousTagSize = (uint)(flvTags.DataSize + 11); - return data; + flvMessagePackWriter.WriteUInt32((uint)(flvTags.DataSize + 11)); + return flvMessagePackWriter.FlushAndGetArray(); } finally { @@ -210,9 +191,9 @@ namespace JT1078.Flv } /// - /// 编码非首帧视频 + /// 编码视频 /// - /// + /// 1078包 /// 是否需要首帧视频 /// public byte[] EncoderVideoTag(JT1078Package package, bool needVideoHeader = false) @@ -231,14 +212,26 @@ namespace JT1078.Flv nalus.Remove(sei); if (needVideoHeader) { - var firstVideoTag = EncoderFirstVideoTag(sps, pps, sei); + //flv header + var flvHeader = EncoderFlvHeader(true, false); + flvMessagePackWriter.WriteArray(flvHeader); + // always 0 + flvMessagePackWriter.WriteUInt32(0); + //解析sps + var rawData = h264Decoder.DiscardEmulationPreventionBytes(sps.RawData); + ExpGolombReader h264GolombReader = new ExpGolombReader(rawData); + SPSInfo spsInfo = h264GolombReader.ReadSPS(); + //script tag + var scriptTag = EncoderScriptTag(spsInfo); + flvMessagePackWriter.WriteArray(scriptTag); + // first video tag + var firstVideoTag = EncoderFirstVideoTag(spsInfo, sps, pps, sei); flvMessagePackWriter.WriteArray(firstVideoTag); } foreach (var naln in nalus) { - flvMessagePackWriter.WriteUInt32(previousTagSize); - var videoTag = ConversionNaluToVideoTag(naln); - flvMessagePackWriter.WriteArray(videoTag); + var otherVideoTag = EncoderOtherVideoTag(naln); + flvMessagePackWriter.WriteArray(otherVideoTag); } } return flvMessagePackWriter.FlushAndGetArray(); @@ -280,15 +273,17 @@ namespace JT1078.Flv } if (aacFrameData != null && aacFrameData.Any())//编码成功,此时为一帧aac音频数据 { - // PreviousTagSize - flvMessagePackWriter.WriteUInt32(previousTagSize); // Data Tag Frame - flvMessagePackWriter.WriteArray(ConversionAacDataToAudioTag((uint)package.Timestamp, aacFrameData)); + flvMessagePackWriter.WriteArray(EncoderAacAudioTag((uint)package.Timestamp, aacFrameData)); } return flvMessagePackWriter.FlushAndGetArray(); } - - byte[] ConversionNaluToVideoTag(H264NALU nALU) + /// + /// 编码非首帧视频 + /// + /// + /// + public byte[] EncoderOtherVideoTag(H264NALU nALU) { byte[] buffer = FlvArrayPool.Rent(65535); try @@ -330,9 +325,8 @@ namespace JT1078.Flv // flvTags.VideoTagsData.VideoData.MultiData.Add(sei.RawData); //} flvMessagePackWriter.WriteFlvTag(flvTags); - var data = flvMessagePackWriter.FlushAndGetArray(); - previousTagSize = (uint)(flvTags.DataSize + 11); - return data; + flvMessagePackWriter.WriteUInt32((uint)(flvTags.DataSize + 11)); + return flvMessagePackWriter.FlushAndGetArray(); } finally { @@ -340,7 +334,7 @@ namespace JT1078.Flv } } - byte[] ConversionAacDataToAudioTag(uint timestamp, byte[] aacFrameData) + byte[] EncoderAacAudioTag(uint timestamp, byte[] aacFrameData) { byte[] buffer = FlvArrayPool.Rent(65535); try @@ -358,7 +352,7 @@ namespace JT1078.Flv AudioTagsData = new AudioTags(AACPacketType.AudioFrame, aacFrameData) }; flvMessagePackWriter.WriteFlvTag(flvTags); - previousTagSize = (uint)(flvTags.DataSize + 11); + flvMessagePackWriter.WriteUInt32((uint)(flvTags.DataSize + 11)); return flvMessagePackWriter.FlushAndGetArray(); } finally diff --git a/src/JT1078.Flv/FlvTags.cs b/src/JT1078.Flv/FlvTags.cs index 620621c..2557b79 100644 --- a/src/JT1078.Flv/FlvTags.cs +++ b/src/JT1078.Flv/FlvTags.cs @@ -10,7 +10,7 @@ namespace JT1078.Flv /// Tag Data部分大小 /// 3个字节 /// - public uint DataSize { get; set; } + public int DataSize { get; set; } /// /// Tag时间戳 /// 3个字节 diff --git a/src/JT1078.Flv/JT1078.Flv.xml b/src/JT1078.Flv/JT1078.Flv.xml index e625440..7e937e1 100644 --- a/src/JT1078.Flv/JT1078.Flv.xml +++ b/src/JT1078.Flv/JT1078.Flv.xml @@ -214,15 +214,16 @@ 手动编码 - 1、 - 2、 - 3、 + 0、 + 1、插入 PriviousTagSize =0 always equal 0 + 2、 + 3、 4、 5、第二个参数传false 6、第二个参数传false 自动编码 1、 - 2、 + 2、 3、第二个参数传true 4、第二个参数传true @@ -230,34 +231,25 @@ 编码flv头 - - 注意:本方法已写入 - - - + 是否有视频 + 是否有音频 - + 编码脚本Tag - - 注意:本方法已写入 - - 视频宽度 - 视频高度 - 是否含有音频,如果有,则写入音频配置,后来发现即便是有音频,这里给false也没关系 - 帧率 + 解析后的sps信息 + 是否有音频 + 帧率 默认25d 即每秒25帧 - + - 编码首帧视频,即videoTag[0] - - 注意:本方法已写入 - + 编码首帧视频,即videoTag[0] + sps 解析后的数据 @@ -266,17 +258,15 @@ 编码首帧音频,即audioTag[0] - - 注意:本方法已写入 - + - 编码非首帧视频 + 编码视频 - + 1078包 是否需要首帧视频 @@ -288,6 +278,13 @@ 是否需要首帧音频 + + + 编码非首帧视频 + + + + Tag Data部分大小 diff --git a/src/JT1078.Flv/MessagePack/FlvMessagePackWriter_Flv.cs b/src/JT1078.Flv/MessagePack/FlvMessagePackWriter_Flv.cs index c629664..b10bcdd 100644 --- a/src/JT1078.Flv/MessagePack/FlvMessagePackWriter_Flv.cs +++ b/src/JT1078.Flv/MessagePack/FlvMessagePackWriter_Flv.cs @@ -33,7 +33,8 @@ namespace JT1078.Flv.MessagePack //todo:VIDEODATA break; } - WriteInt24Return(GetCurrentPosition() - DataSizePosition -3-7, DataSizePosition); + tag.DataSize = GetCurrentPosition() - 11; + WriteInt24Return(tag.DataSize, DataSizePosition); } public void WriteUInt24(uint value)