Kaynağa Gözat

调整flv的组包方式(Flv的Timestamp时间戳没有控制好!!!)

tags/v1.1.0
smallchi 5 yıl önce
ebeveyn
işleme
0d09d56ec5
7 değiştirilmiş dosya ile 256 ekleme ve 217 silme
  1. +35
    -4
      src/JT1078.Flv.Test/FlvEncoderTest.cs
  2. +0
    -3
      src/JT1078.Flv.Test/JT1078.Flv.Test.csproj
  3. +189
    -144
      src/JT1078.Flv/FlvEncoder.cs
  4. +0
    -51
      src/JT1078.Flv/H264/H264Decoder.cs
  5. +4
    -0
      src/JT1078.Flv/JT1078.Flv.csproj
  6. +1
    -1
      src/JT808.Protocol.Extensions.WebApiTest/JT808.Protocol.Extensions.WebApiTest.csproj
  7. +27
    -14
      src/JT808.Protocol.Extensions.WebApiTest/Program.cs

+ 35
- 4
src/JT1078.Flv.Test/FlvEncoderTest.cs Dosyayı Görüntüle

@@ -9,6 +9,7 @@ using System.Linq;
using JT1078.Protocol.Enums;
using JT1078.Flv.H264;
using JT1078.Flv.MessagePack;
using JT1078.Flv.Metadata;

namespace JT1078.Flv.Test
{
@@ -100,7 +101,6 @@ namespace JT1078.Flv.Test
}
}


[Fact]
public void FlvEncoder_Test_3()
{
@@ -250,9 +250,9 @@ namespace JT1078.Flv.Test
}
}
//var tmp1 = h264NALULs.Where(w => w.NALUHeader.NalUnitType == 7).ToList();
//List<SPSInfo> tmpSpss = new List<SPSInfo>();
//List<ushort> times = new List<ushort>();
//List<int> type = new List<int>();
List<SPSInfo> tmpSpss = new List<SPSInfo>();
List<ushort> times = new List<ushort>();
List<int> type = new List<int>();
//foreach (var item in h264NALULs)
//{
// //ExpGolombReader expGolombReader = new ExpGolombReader(item.RawData);
@@ -282,5 +282,36 @@ namespace JT1078.Flv.Test
fileStream?.Dispose();
}
}

[Fact]
public void CreateScriptTagFrameTest()
{
FlvEncoder flvEncoder = new FlvEncoder();
var hexData = flvEncoder.CreateScriptTagFrame(288, 352);
Assert.Equal(151, hexData.Length);
}

[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 GetFirstFlvFrameTest()
{
FlvEncoder flvEncoder = new FlvEncoder();
string key = "test";
var bufferFlvFrame = new byte[] { 0xA, 0xB, 0xC, 0xD, 0xE, 0xF };
FlvEncoder.FlvFirstFrameCache.TryAdd(key, (2, new byte[] { 1, 2, 3, 4, 5, 6 }));
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);
}
}
}

+ 0
- 3
src/JT1078.Flv.Test/JT1078.Flv.Test.csproj Dosyayı Görüntüle

@@ -40,9 +40,6 @@
<None Update="H264\JT1078_4.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="H264\JT1078_5.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>

+ 189
- 144
src/JT1078.Flv/FlvEncoder.cs Dosyayı Görüntüle

@@ -2,167 +2,171 @@
using JT1078.Flv.H264;
using JT1078.Flv.MessagePack;
using JT1078.Flv.Metadata;
using JT1078.Protocol;
using JT1078.Protocol.Enums;
using System;
using System.Buffers.Binary;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;

[assembly: InternalsVisibleTo("JT1078.Flv.Test")]
namespace JT1078.Flv
{
public class FlvEncoder
{
class FlvFrameInfo
public class FlvFrameInfo
{
public uint PreviousTagSize { get; set;}
public uint LastFrameInterval { get; set; }
public uint LastIFrameInterval { get; set; }
}

public static readonly byte[] VideoFlvHeaderBuffer;
private const uint PreviousTagSizeFixedLength = 4;
private static readonly ConcurrentDictionary<string, SPSInfo> VideoSPSDict;
private static readonly Flv.H264.H264Decoder H264Decoder;
private static readonly ConcurrentDictionary<string, SPSInfo> VideoSPSDict;
private static readonly ConcurrentDictionary<string, FlvFrameInfo> FlvFrameInfoDict;
private static readonly ConcurrentDictionary<string, byte[]> FlvFirstFrameCache;
internal static readonly ConcurrentDictionary<string, (uint PreviousTagSize,byte[] Buffer)> FlvFirstFrameCache;
static FlvEncoder()
{
FlvHeader VideoFlvHeader = new FlvHeader(true, false);
VideoFlvHeaderBuffer = VideoFlvHeader.ToArray().ToArray();
VideoSPSDict = new ConcurrentDictionary<string, SPSInfo>();
FlvFrameInfoDict = new ConcurrentDictionary<string, FlvFrameInfo>();
FlvFirstFrameCache = new ConcurrentDictionary<string, byte[]>();
VideoSPSDict = new ConcurrentDictionary<string, SPSInfo>(StringComparer.OrdinalIgnoreCase);
FlvFrameInfoDict = new ConcurrentDictionary<string, FlvFrameInfo>(StringComparer.OrdinalIgnoreCase);
FlvFirstFrameCache = new ConcurrentDictionary<string, (uint PreviousTagSize, byte[] Buffer)>(StringComparer.OrdinalIgnoreCase);
H264Decoder = new Flv.H264.H264Decoder();
}

/// <summary>
///
/// </summary>
private void CreateFlvKeyFrame(ref FlvMessagePackWriter flvMessagePackWriter, string key,byte[] spsRawData, byte[] ppsRawData, SPSInfo spsInfo, uint previousTagSize = 0)
public byte[] CreateScriptTagFrame(int width, int height, double frameRate = 25d)
{
int currentMarkPosition = 0;
int nextMarkPosition = 0;
currentMarkPosition = flvMessagePackWriter.GetCurrentPosition();
//flv body script tag
CreateScriptTagFrame(ref flvMessagePackWriter, spsInfo.width, spsInfo.height, previousTagSize);
nextMarkPosition = flvMessagePackWriter.GetCurrentPosition();

//flv body video tag
uint scriptTagFramePreviousTagSize = (uint)(nextMarkPosition - currentMarkPosition - PreviousTagSizeFixedLength);
AVCDecoderConfigurationRecord aVCDecoderConfigurationRecord = new AVCDecoderConfigurationRecord();
aVCDecoderConfigurationRecord.AVCProfileIndication = spsInfo.profileIdc;
aVCDecoderConfigurationRecord.ProfileCompatibility = (byte)spsInfo.profileCompat;
aVCDecoderConfigurationRecord.AVCLevelIndication = spsInfo.levelIdc;
aVCDecoderConfigurationRecord.NumOfPictureParameterSets = 1;
aVCDecoderConfigurationRecord.PPSBuffer = ppsRawData;
aVCDecoderConfigurationRecord.SPSBuffer = spsRawData;

currentMarkPosition = flvMessagePackWriter.GetCurrentPosition();
CreateVideoTag0Frame(ref flvMessagePackWriter, scriptTagFramePreviousTagSize, aVCDecoderConfigurationRecord);
nextMarkPosition = flvMessagePackWriter.GetCurrentPosition();

//flv body video tag 0
uint videoTag0PreviousTagSize = (uint)(nextMarkPosition - currentMarkPosition - PreviousTagSizeFixedLength);
//cache PreviousTagSize
FlvFrameInfoDict.AddOrUpdate(key, new FlvFrameInfo { PreviousTagSize= videoTag0PreviousTagSize }, (a, b) => {
b.PreviousTagSize = videoTag0PreviousTagSize;
return b;
});
}
private void CreateScriptTagFrame(ref FlvMessagePackWriter flvMessagePackWriter, int width, int height,uint previousTagSize, double frameRate = 25d)
{
//flv body PreviousTagSize awalys 0
flvMessagePackWriter.WriteUInt32(previousTagSize);
//flv body script tag
//flv body tag header
FlvTags flvTags = new FlvTags();
flvTags.Type = TagType.ScriptData;
flvTags.Timestamp = 0;
flvTags.TimestampExt = 0;
flvTags.StreamId = 0;
//flv body tag body
flvTags.DataTagsData = new Amf3();
flvTags.DataTagsData.Amf3Metadatas = new List<IAmf3Metadata>();
flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_Duration
{
Value = 0d
});
flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_VideoDataRate
{
Value = 0d
});
flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_VideoCodecId
{
Value = 7d
});
flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_FrameRate
{
Value = frameRate
});
flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_Width
byte[] buffer = FlvArrayPool.Rent(1024);
try
{
Value = width
});
flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_Height
FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
//flv body script tag
//flv body tag header
FlvTags flvTags = new FlvTags();
flvTags.Type = TagType.ScriptData;
flvTags.Timestamp = 0;
flvTags.TimestampExt = 0;
flvTags.StreamId = 0;
//flv body tag body
flvTags.DataTagsData = new Amf3();
flvTags.DataTagsData.Amf3Metadatas = new List<IAmf3Metadata>();
flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_Duration
{
Value = 0d
});
flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_VideoDataRate
{
Value = 0d
});
flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_VideoCodecId
{
Value = 7d
});
flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_FrameRate
{
Value = frameRate
});
flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_Width
{
Value = width
});
flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_Height
{
Value = height
});
flvMessagePackWriter.WriteFlvTag(flvTags);
return flvMessagePackWriter.FlushAndGetArray();
}
finally
{
Value = height
});
flvMessagePackWriter.WriteFlvTag(flvTags);
FlvArrayPool.Return(buffer);
}
}
private void CreateVideoTag0Frame(ref FlvMessagePackWriter flvMessagePackWriter, uint previousTagSize, AVCDecoderConfigurationRecord aVCDecoderConfigurationRecord)
public byte[] CreateVideoTag0Frame(byte[] spsRawData, byte[] ppsRawData, SPSInfo spsInfo)
{
//flv body PreviousTagSize ScriptTag
flvMessagePackWriter.WriteUInt32(previousTagSize);
//flv body video tag
//flv body tag header
FlvTags flvTags = new FlvTags();
flvTags.Type = TagType.Video;
flvTags.Timestamp = 0;
flvTags.TimestampExt = 0;
flvTags.StreamId = 0;
//flv body tag body
flvTags.VideoTagsData = new VideoTags();
flvTags.VideoTagsData.FrameType = FrameType.KeyFrame;
flvTags.VideoTagsData.VideoData = new AvcVideoPacke();
flvTags.VideoTagsData.VideoData.AvcPacketType = AvcPacketType.SequenceHeader;
flvTags.VideoTagsData.VideoData.CompositionTime = 0;
flvTags.VideoTagsData.VideoData.AVCDecoderConfiguration = aVCDecoderConfigurationRecord;
flvMessagePackWriter.WriteFlvTag(flvTags);
byte[] buffer = FlvArrayPool.Rent(1024);
try
{
FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
//flv body video tag
//flv body tag header
FlvTags flvTags = new FlvTags();
flvTags.Type = TagType.Video;
flvTags.Timestamp = 0;
flvTags.TimestampExt = 0;
flvTags.StreamId = 0;
//flv body tag body
flvTags.VideoTagsData = new VideoTags();
flvTags.VideoTagsData.FrameType = FrameType.KeyFrame;
flvTags.VideoTagsData.VideoData = new AvcVideoPacke();
flvTags.VideoTagsData.VideoData.AvcPacketType = AvcPacketType.SequenceHeader;
flvTags.VideoTagsData.VideoData.CompositionTime = 0;
AVCDecoderConfigurationRecord aVCDecoderConfigurationRecord = new AVCDecoderConfigurationRecord();
aVCDecoderConfigurationRecord.AVCProfileIndication = spsInfo.profileIdc;
aVCDecoderConfigurationRecord.ProfileCompatibility = (byte)spsInfo.profileCompat;
aVCDecoderConfigurationRecord.AVCLevelIndication = spsInfo.levelIdc;
aVCDecoderConfigurationRecord.NumOfPictureParameterSets = 1;
aVCDecoderConfigurationRecord.PPSBuffer = ppsRawData;
aVCDecoderConfigurationRecord.SPSBuffer = spsRawData;
flvTags.VideoTagsData.VideoData.AVCDecoderConfiguration = aVCDecoderConfigurationRecord;
flvMessagePackWriter.WriteFlvTag(flvTags);
return flvMessagePackWriter.FlushAndGetArray();
}
finally
{
FlvArrayPool.Return(buffer);
}
}
private void CreateVideoTagOtherFrame(ref FlvMessagePackWriter flvMessagePackWriter, FlvFrameInfo flvFrameInfo, H264NALU nALU)
public byte[] CreateVideoTagOtherFrame(FlvFrameInfo flvFrameInfo, H264NALU nALU)
{
//flv body PreviousTagSize
flvMessagePackWriter.WriteUInt32(flvFrameInfo.PreviousTagSize);
//flv body video tag
//flv body tag header
FlvTags flvTags = new FlvTags();
flvTags.Type = TagType.Video;
flvTags.TimestampExt = 0;
flvTags.StreamId = 0;
//flv body tag body
flvTags.VideoTagsData = new VideoTags();
flvTags.VideoTagsData.VideoData = new AvcVideoPacke();
flvTags.VideoTagsData.VideoData.CompositionTime = 0;
flvTags.VideoTagsData.VideoData.AvcPacketType = AvcPacketType.Raw;
flvTags.Timestamp = flvFrameInfo.LastFrameInterval;
if (nALU.NALUHeader.NalUnitType == 5 || nALU.DataType== JT1078DataType.视频I帧)
byte[] buffer = FlvArrayPool.Rent(65535);
try
{
flvTags.VideoTagsData.FrameType = FrameType.KeyFrame;
FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
//flv body video tag
//flv body tag header
FlvTags flvTags = new FlvTags();
flvTags.Type = TagType.Video;
flvTags.TimestampExt = 0;
flvTags.StreamId = 0;
//flv body tag body
flvTags.VideoTagsData = new VideoTags();
flvTags.VideoTagsData.VideoData = new AvcVideoPacke();
flvTags.VideoTagsData.VideoData.CompositionTime = 0;
flvTags.VideoTagsData.VideoData.AvcPacketType = AvcPacketType.Raw;
if (nALU.NALUHeader.NalUnitType == 5 || nALU.DataType == JT1078DataType.视频I帧)
{
flvTags.VideoTagsData.FrameType = FrameType.KeyFrame;
flvTags.Timestamp = flvFrameInfo.LastIFrameInterval;
}
else
{
flvTags.Timestamp = flvFrameInfo.LastFrameInterval;
flvTags.VideoTagsData.FrameType = FrameType.InterFrame;
}
#warning Timestamp时间戳没有控制好
flvTags.Timestamp = flvFrameInfo.LastIFrameInterval;
flvTags.VideoTagsData.VideoData.Data = nALU.RawData;
flvMessagePackWriter.WriteFlvTag(flvTags);
return flvMessagePackWriter.FlushAndGetArray();
}
else
finally
{
flvTags.VideoTagsData.FrameType = FrameType.InterFrame;
FlvArrayPool.Return(buffer);
}
flvTags.VideoTagsData.VideoData.Data = nALU.RawData;
flvMessagePackWriter.WriteFlvTag(flvTags);
}
public byte[] CreateFlvFrame(List<H264NALU> nALUs, int minimumLength = 65535)

public byte[] CreateFlvFrame(List<H264NALU> nALUs,int minimumLength = 65535)
{
byte[] buffer = FlvArrayPool.Rent(minimumLength);
try
{
FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
int currentMarkPosition = 0;
int nextMarkPosition = 0;
H264NALU sps=null, pps=null;
SPSInfo spsInfo = new SPSInfo();
foreach (var naln in nALUs)
@@ -172,29 +176,27 @@ namespace JT1078.Flv
{
if (VideoSPSDict.TryGetValue(key, out var spsInfoCache))
{
//todo: 主次码流
if (spsInfoCache.height != spsInfo.height && spsInfoCache.width != spsInfo.width)
{
if(FlvFrameInfoDict.TryGetValue(key, out FlvFrameInfo flvFrameInfo))
if (FlvFrameInfoDict.TryGetValue(key, out FlvFrameInfo flvFrameInfo))
{
CreateFlvKeyFrame(ref flvMessagePackWriter, key, sps.RawData, pps.RawData, spsInfo, flvFrameInfo.PreviousTagSize);
FlvFirstFrameCache.TryRemove(key, out _);
FlvFirstFrameCache.TryAdd(key, flvMessagePackWriter.FlushAndGetArray());
CreateFlvKeyFrame(ref flvMessagePackWriter, key, sps.RawData, pps.RawData, spsInfo);
VideoSPSDict.TryUpdate(key, spsInfo, spsInfo);
flvFrameInfo.LastFrameInterval = 0;
flvFrameInfo.LastIFrameInterval = 0;
FlvFrameInfoDict.TryUpdate(key, flvFrameInfo, flvFrameInfo);
}
}
sps = null;
pps = null;
}
else
{
CreateFlvKeyFrame(ref flvMessagePackWriter, key, sps.RawData, pps.RawData, spsInfo, 0);
FlvFirstFrameCache.TryAdd(key, flvMessagePackWriter.FlushAndGetArray());
flvMessagePackWriter.WriteArray(VideoFlvHeaderBuffer);
CreateFlvKeyFrame(ref flvMessagePackWriter, key, sps.RawData, pps.RawData, spsInfo);
VideoSPSDict.TryAdd(key, spsInfo);
sps = null;
pps = null;
}
sps = null;
pps = null;
continue;
}
//7 8 6 5 1 1 1 1 7 8 6 5 1 1 1 1 1 7 8 6 5 1 1 1 1 1
switch (naln.NALUHeader.NalUnitType)
@@ -203,12 +205,14 @@ namespace JT1078.Flv
case 1:// I/P/B
if (FlvFrameInfoDict.TryGetValue(key, out FlvFrameInfo flvFrameInfo))
{
currentMarkPosition = flvMessagePackWriter.GetCurrentPosition();
CreateVideoTagOtherFrame(ref flvMessagePackWriter, flvFrameInfo, naln);
nextMarkPosition = flvMessagePackWriter.GetCurrentPosition();
uint tmpPreviousTagSize = (uint)(nextMarkPosition - currentMarkPosition - PreviousTagSizeFixedLength);
flvFrameInfo.PreviousTagSize = tmpPreviousTagSize;
flvFrameInfo.LastIFrameInterval += naln.LastIFrameInterval;
flvFrameInfo.LastFrameInterval += naln.LastFrameInterval;
// PreviousTagSize
flvMessagePackWriter.WriteUInt32(flvFrameInfo.PreviousTagSize);
// Data Tag Frame
var flvFrameBuffer = CreateVideoTagOtherFrame(flvFrameInfo, naln);
flvMessagePackWriter.WriteArray(flvFrameBuffer);
flvFrameInfo.PreviousTagSize = (uint)flvFrameBuffer.Length;
FlvFrameInfoDict.TryUpdate(key, flvFrameInfo, flvFrameInfo);
}
break;
@@ -216,7 +220,7 @@ namespace JT1078.Flv
sps = naln;
var rawData = H264Decoder.DiscardEmulationPreventionBytes(naln.RawData);
ExpGolombReader h264GolombReader = new ExpGolombReader(rawData);
spsInfo = h264GolombReader.ReadSPS();
spsInfo = h264GolombReader.ReadSPS();
break;
case 8:// pps
pps = naln;
@@ -234,16 +238,57 @@ namespace JT1078.Flv
FlvArrayPool.Return(buffer);
}
}
public byte[] GetFlvFirstFrameByKey(string key)
private void CreateFlvKeyFrame(ref FlvMessagePackWriter flvMessagePackWriter, string key, byte[] spsRawData, byte[] ppsRawData, SPSInfo spsInfo)
{
if(FlvFirstFrameCache.TryGetValue(key,out byte[] buffer))
{
return buffer;
}
else
//flv body PreviousTagSize awalys 0
flvMessagePackWriter.WriteUInt32(0);
//flv body script tag
var scriptTagFrameBuffer= CreateScriptTagFrame(spsInfo.width, spsInfo.height);
flvMessagePackWriter.WriteArray(scriptTagFrameBuffer);
//flv script tag PreviousTagSize
flvMessagePackWriter.WriteUInt32((uint)scriptTagFrameBuffer.Length);
//flv body video tag
var videoTagFrame0Buffer= CreateVideoTag0Frame(spsRawData, ppsRawData, spsInfo);
flvMessagePackWriter.WriteArray(videoTagFrame0Buffer);
uint videoTag0PreviousTagSize = (uint)videoTagFrame0Buffer.Length;
//cache PreviousTagSize
FlvFrameInfoDict.AddOrUpdate(key, new FlvFrameInfo { PreviousTagSize = videoTag0PreviousTagSize}, (a, b) => {
b.PreviousTagSize = videoTag0PreviousTagSize;
return b;
});
var buffer = flvMessagePackWriter.FlushAndGetArray();
FlvFirstFrameCache.AddOrUpdate(key,(videoTag0PreviousTagSize, buffer),(a,b)=> {
b.PreviousTagSize = videoTag0PreviousTagSize;
b.Buffer = buffer;
return b;
});
}
public byte[] CreateFlvFrame(JT1078Package package,int minimumLength = 65535)
{
var nalus = H264Decoder.ParseNALU(package);
if (nalus == null || nalus.Count <= 0) return default;
return CreateFlvFrame(nalus, minimumLength);
}
public byte[] GetFirstFlvFrame(string key,byte[] bufferFlvFrame)
{
if (FlvFirstFrameCache.TryGetValue(key, out var firstBuffer))
{
return null;
}
var length = firstBuffer.Buffer.Length + bufferFlvFrame.Length;
byte[] buffer = FlvArrayPool.Rent(length);
try
{
Span<byte> tmp = buffer;
firstBuffer.Buffer.CopyTo(tmp);
BinaryPrimitives.WriteUInt32BigEndian(bufferFlvFrame, firstBuffer.PreviousTagSize);
bufferFlvFrame.CopyTo(tmp.Slice(firstBuffer.Buffer.Length));
return tmp.Slice(0, length).ToArray();
}
finally
{
FlvArrayPool.Return(buffer);
}
}
return default;
}
}
}

+ 0
- 51
src/JT1078.Flv/H264/H264Decoder.cs Dosyayı Görüntüle

@@ -87,57 +87,6 @@ namespace JT1078.Flv.H264
return nALU;
}

/// <summary>
/// Identify NAL unit types and pass on the NALU, trackId, presentation and decode timestamps
/// for the NALUs to the next stream component.
/// Also, preprocess caption and sequence parameter NALUs.
/// 常用Nalu_type:
/// 0x67 (0 11 00111) SPS 非常重要 type = 7
/// 0x68 (0 11 01000) PPS 非常重要 type = 8
/// 0x65 (0 11 00101) IDR帧 关键帧(非常重要) type = 5
/// 0x61 (0 11 00001) I帧 重要 type = 1 非IDR的I帧不大常见
/// 0x41 (0 10 00001) P帧 重要 type = 1
/// 0x01 (0 00 00001) B帧 不重要 type = 1
/// 0x06 (0 00 00110) SEI 不重要 type = 6
/// <see cref="https://blog.csdn.net/huibailingyu/article/details/42879573"/>
/// </summary>
/// <param name="h264NALU"></param>
/// <returns></returns>
private void NALUTypeFilter(H264NALU h264NALU)
{
switch (h264NALU.NALUHeader.NalUnitType)
{
//IPB帧
case 1:

break;
//IDR
case 5:
break;
//SEI
case 6:
h264NALU.RawData = DiscardEmulationPreventionBytes(h264NALU.RawData);

break;
//SPS
case 7:
h264NALU.RawData = DiscardEmulationPreventionBytes(h264NALU.RawData);
ExpGolombReader h264GolombReader = new ExpGolombReader(h264NALU.RawData);
var spsInfo = h264GolombReader.ReadSPS();
break;
//PPS
case 8:
break;
//AUD
case 9:
break;
}
}

/// <summary>
/// Expunge any "Emulation Prevention" bytes from a "Raw Byte Sequence Payload"
/// <see cref="https://blog.csdn.net/u011399342/article/details/80472084"/>


+ 4
- 0
src/JT1078.Flv/JT1078.Flv.csproj Dosyayı Görüntüle

@@ -24,6 +24,10 @@
<PackageReference Include="System.Memory" Version="4.5.3" />
</ItemGroup>

<ItemGroup>
<None Remove="FlvEncoder.bak" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\JT1078.Protocol\JT1078.Protocol.csproj" />
</ItemGroup>


+ 1
- 1
src/JT808.Protocol.Extensions.WebApiTest/JT808.Protocol.Extensions.WebApiTest.csproj Dosyayı Görüntüle

@@ -6,7 +6,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="JT808.DotNetty.WebApiClientTool" Version="1.2.0" />
<PackageReference Include="JT808.DotNetty.WebApiClientTool" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.2.0" />
<PackageReference Include="WebApiClient.Extensions.DependencyInjection" Version="2.0.3" />


+ 27
- 14
src/JT808.Protocol.Extensions.WebApiTest/Program.cs Dosyayı Görüntüle

@@ -23,7 +23,7 @@ namespace JT808.Protocol.Extensions.WebApiTest

serviceDescriptors.AddHttpApi<IJT808DotNettyWebApi>().ConfigureHttpApiConfig((c, p) =>
{
c.HttpHost = new Uri("http://localhost:12828/jt808api/");
c.HttpHost = new Uri("http://localhost:12819/jt808api/");
c.FormatOptions.DateTimeFormat = "yyyy-MM-dd HH:mm:ss.fff";
//c.LoggerFactory = p.GetRequiredService<ILoggerFactory>();
});
@@ -34,12 +34,12 @@ namespace JT808.Protocol.Extensions.WebApiTest
JT808Serializer JT808Serializer = config.GetSerializer();
IJT808DotNettyWebApi JT808DotNettyWebApiClient = serviceProvider.GetRequiredService<IJT808DotNettyWebApi>();
string terminalPhoneNo = "";
string serverIPAddress = "127.0.0.1";
string serverIPAddress = "";

//创建子码流
CreateSub(terminalPhoneNo, serverIPAddress, JT808Serializer, JT808DotNettyWebApiClient);
// CreateSub(terminalPhoneNo, serverIPAddress, JT808Serializer, JT808DotNettyWebApiClient);

//创建主码流
////创建主码流
CreateMain(terminalPhoneNo, serverIPAddress, JT808Serializer, JT808DotNettyWebApiClient);

Console.ReadKey();
@@ -57,21 +57,27 @@ namespace JT808.Protocol.Extensions.WebApiTest
jT808_0X9101.ServerIPAddress = serverIPAddress;
jT808_0X9101.ServerVideoChannelTcpPort = 1808;
jT808_0X9101.ServerVideoChannelUdpPort = 0;
jT808_0X9101.LogicalChannelNo = 3;
jT808_0X9101.LogicalChannelNo = 1;
jT808_0X9101.DataType = 1;
jT808_0X9101.StreamType = 1;
jT808Package.Bodies = jT808_0X9101;

var data = JT808Serializer.Serialize(jT808Package);
Console.WriteLine(JsonConvert.SerializeObject(data.ToHexString()));

var result = JT808DotNettyWebApiClient.UnificationTcpSend(new JT808UnificationSendRequestDto
var tmpSend = JsonConvert.SerializeObject(new JT808UnificationSendRequestDto
{
TerminalPhoneNo = terminalPhoneNo,
Data = data
}).GetAwaiter().GetResult();

Console.WriteLine(JsonConvert.SerializeObject(result));
});
//由于升级忘记测试接口导致接口变更用不了使用postman替代下
//var result = JT808DotNettyWebApiClient.UnificationTcpSend(new JT808UnificationSendRequestDto
//{
// TerminalPhoneNo = terminalPhoneNo,
// Data = data
//}).GetAwaiter().GetResult();

//Console.WriteLine(JsonConvert.SerializeObject(result));
Console.WriteLine(tmpSend);
}

public static void CreateMain(string terminalPhoneNo, string serverIPAddress, JT808Serializer JT808Serializer, IJT808DotNettyWebApi JT808DotNettyWebApiClient)
@@ -86,7 +92,7 @@ namespace JT808.Protocol.Extensions.WebApiTest
jT808_0X9101.ServerIPAddress = serverIPAddress;
jT808_0X9101.ServerVideoChannelTcpPort = 1808;
jT808_0X9101.ServerVideoChannelUdpPort = 0;
jT808_0X9101.LogicalChannelNo = 3;
jT808_0X9101.LogicalChannelNo = 1;
jT808_0X9101.DataType = 1;
jT808_0X9101.StreamType =0;
jT808Package.Bodies = jT808_0X9101;
@@ -94,13 +100,20 @@ namespace JT808.Protocol.Extensions.WebApiTest
var data = JT808Serializer.Serialize(jT808Package);
Console.WriteLine(JsonConvert.SerializeObject(data.ToHexString()));

var result = JT808DotNettyWebApiClient.UnificationTcpSend(new JT808UnificationSendRequestDto
var tmpSend = JsonConvert.SerializeObject(new JT808UnificationSendRequestDto
{
TerminalPhoneNo = terminalPhoneNo,
Data = data
}).GetAwaiter().GetResult();
});

//var result = JT808DotNettyWebApiClient.UnificationTcpSend(new JT808UnificationSendRequestDto
//{
// TerminalPhoneNo = terminalPhoneNo,
// Data = data
//}).GetAwaiter().GetResult();

Console.WriteLine(JsonConvert.SerializeObject(result));
//Console.WriteLine(JsonConvert.SerializeObject(result));
Console.WriteLine(tmpSend);
}

public static void Close(string terminalPhoneNo, JT808Serializer JT808Serializer, IJT808DotNettyWebApi JT808DotNettyWebApiClient)


Yükleniyor…
İptal
Kaydet