浏览代码

1.增加IDR包

2.整合代码
tags/v1.1.0
smallchi 5 年前
父节点
当前提交
077ab23903
共有 3 个文件被更改,包括 209 次插入235 次删除
  1. +195
    -232
      src/JT1078.Flv/FlvEncoder.cs
  2. +1
    -1
      src/JT1078.Flv/JT1078.Flv.csproj
  3. +13
    -2
      src/JT1078.Flv/JT1078.Flv.xml

+ 195
- 232
src/JT1078.Flv/FlvEncoder.cs 查看文件

@@ -45,175 +45,7 @@ namespace JT1078.Flv
{
logger = loggerFactory.CreateLogger("FlvEncoder");
}
internal byte[] CreateScriptTagFrame(int width, int height, double frameRate = 25d)
{
byte[] buffer = FlvArrayPool.Rent(1024);
try
{
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
{
FlvArrayPool.Return(buffer);
}
}
internal byte[] CreateVideoTag0Frame(byte[] spsRawData, byte[] ppsRawData, SPSInfo spsInfo)
{
byte[] buffer = FlvArrayPool.Rent(2048);
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);
}
}
internal byte[] CreateSecondVideoTag0Frame(byte[] spsRawData, byte[] ppsRawData, SPSInfo spsInfo)
{
byte[] buffer = FlvArrayPool.Rent(2048);
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);
}
}
internal byte[] CreateVideoTagOtherFrame(FlvFrameInfo flvFrameInfo, H264NALU nALU, H264NALU sei)
{
byte[] buffer = FlvArrayPool.Rent(65535);
try
{
FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
//flv body video tag
//flv body tag header
FlvTags flvTags = new FlvTags();
flvTags.Type = TagType.Video;
//pts
flvTags.Timestamp = flvFrameInfo.Interval;
flvTags.TimestampExt = 0;
flvTags.StreamId = 0;
//flv body tag body
flvTags.VideoTagsData = new VideoTags();
flvTags.VideoTagsData.VideoData = new AvcVideoPacke();
flvTags.VideoTagsData.VideoData.AvcPacketType = AvcPacketType.Raw;
if (nALU.NALUHeader.NalUnitType == 5 || nALU.DataType == JT1078DataType.视频I帧)
{
flvTags.VideoTagsData.FrameType = FrameType.KeyFrame;
}
else
{
flvTags.VideoTagsData.FrameType = FrameType.InterFrame;
}
if(flvFrameInfo.DataType== JT1078DataType.视频I帧)
{
//cts
flvTags.VideoTagsData.VideoData.CompositionTime = nALU.LastIFrameInterval;
}
else
{
//cts
flvTags.VideoTagsData.VideoData.CompositionTime = nALU.LastFrameInterval;
}
flvTags.VideoTagsData.VideoData.MultiData = new List<byte[]>();
flvTags.VideoTagsData.VideoData.MultiData.Add(nALU.RawData);
//忽略sei
//if (sei != null && sei.RawData != null && sei.RawData.Length > 0)
//{
// flvTags.VideoTagsData.VideoData.MultiData.Add(sei.RawData);
//}
flvMessagePackWriter.WriteFlvTag(flvTags);
return flvMessagePackWriter.FlushAndGetArray();
}
finally
{
FlvArrayPool.Return(buffer);
}
}

/// <summary>
///
/// </summary>
@@ -227,7 +59,7 @@ namespace JT1078.Flv
try
{
FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
H264NALU sps=null, pps=null, sei=null;
H264NALU sps = null, pps = null, sei = null;
foreach (var naln in nALUs)
{
key = key ?? naln.GetKey();
@@ -260,11 +92,11 @@ namespace JT1078.Flv
logger.LogDebug($"Cache:{spsInfoCache.height}-{spsInfoCache.width},Current:{spsInfo.height}-{spsInfo.width}");
}
}
var secondFlvKeyFrame=CreateSecondFlvKeyFrame(sps.RawData, pps.RawData, spsInfo, flvFrameInfo);
var secondFlvKeyFrame = CreateFirstFlvKeyFrame(sps.RawData, pps.RawData, spsInfo, flvFrameInfo.PreviousTagSize);
flvMessagePackWriter.WriteArray(secondFlvKeyFrame.Buffer);
flvFrameInfo.PreviousTagSize = secondFlvKeyFrame.PreviousTagSize;
FlvFrameInfoDict.TryUpdate(key, flvFrameInfo, flvFrameInfo);
if(FirstFlvFrameCache.TryGetValue(key,out var firstFlvFrameCacche))
if (FirstFlvFrameCache.TryGetValue(key, out var firstFlvFrameCacche))
{
FirstFlvFrameCache.TryUpdate(key, (secondFlvKeyFrame.PreviousTagSize, secondFlvKeyFrame.Buffer, true), firstFlvFrameCacche);
}
@@ -283,13 +115,14 @@ namespace JT1078.Flv
}
}
//cache PreviousTagSize
FlvFrameInfoDict.TryAdd(key, new FlvFrameInfo{
PreviousTagSize = firstFlvKeyFrame.PreviousTagSize,
Interval = (uint)(pps.Timestamp - sps.Timestamp),
Timestamp= pps.Timestamp,
}
);
FirstFlvFrameCache.TryAdd(key, (firstFlvKeyFrame.PreviousTagSize, firstFlvKeyFrame.Buffer, false));
FlvFrameInfoDict.TryAdd(key, new FlvFrameInfo
{
PreviousTagSize = firstFlvKeyFrame.PreviousTagSize,
Interval = (uint)(pps.Timestamp - sps.Timestamp),
Timestamp = pps.Timestamp,
}
);
FirstFlvFrameCache.TryAdd(key, (firstFlvKeyFrame.PreviousTagSize, firstFlvKeyFrame.Buffer, false));
VideoSPSDict.TryAdd(key, spsInfo);
}
sps = null;
@@ -306,9 +139,26 @@ namespace JT1078.Flv
//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)
{
#warning 是否需要IDR帧? 每次发送IDR帧? 在测试的时候,是否由于图像变化不大所以不需要IDR帧?
case 5:// IDR
if (FlvFrameInfoDict.TryGetValue(key, out FlvFrameInfo idrInfo))
{
//当前的1078包与上一包1078的时间戳相减再进行累加
uint interval = (uint)(naln.Timestamp - idrInfo.Timestamp);
idrInfo.Interval += interval;
idrInfo.Timestamp = naln.Timestamp;
// PreviousTagSize
flvMessagePackWriter.WriteUInt32(idrInfo.PreviousTagSize);
// Data Tag Frame
var flvFrameBuffer = CreateVideoTagOtherFrame(idrInfo, naln, sei);
flvMessagePackWriter.WriteArray(flvFrameBuffer);
idrInfo.PreviousTagSize = (uint)flvFrameBuffer.Length;
idrInfo.LastDataType = naln.DataType;
FlvFrameInfoDict.TryUpdate(key, idrInfo, idrInfo);
}
break;
case 1:// I/P/B
if (FlvFrameInfoDict.TryGetValue(key, out FlvFrameInfo flvFrameInfo))
if (FlvFrameInfoDict.TryGetValue(key, out FlvFrameInfo flvFrameInfo))
{
//当前的1078包与上一包1078的时间戳相减再进行累加
uint interval = (uint)(naln.Timestamp - flvFrameInfo.Timestamp);
@@ -320,7 +170,7 @@ namespace JT1078.Flv
var flvFrameBuffer = CreateVideoTagOtherFrame(flvFrameInfo, naln, sei);
flvMessagePackWriter.WriteArray(flvFrameBuffer);
flvFrameInfo.PreviousTagSize = (uint)flvFrameBuffer.Length;
flvFrameInfo.DataType = naln.DataType;
flvFrameInfo.LastDataType = naln.DataType;
FlvFrameInfoDict.TryUpdate(key, flvFrameInfo, flvFrameInfo);
}
break;
@@ -344,56 +194,7 @@ namespace JT1078.Flv
FlvArrayPool.Return(buffer);
}
}
internal (byte[] Buffer, uint PreviousTagSize) CreateFirstFlvKeyFrame(byte[] spsRawData, byte[] ppsRawData, SPSInfo spsInfo)
{
byte[] buffer = FlvArrayPool.Rent(65535);
try
{
FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
//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 0
var videoTagFrame0Buffer= CreateVideoTag0Frame(spsRawData, ppsRawData, spsInfo);
flvMessagePackWriter.WriteArray(videoTagFrame0Buffer);
uint videoTag0PreviousTagSize = (uint)videoTagFrame0Buffer.Length;
return (flvMessagePackWriter.FlushAndGetArray(), videoTag0PreviousTagSize);
}
finally
{
FlvArrayPool.Return(buffer);
}
}
internal (byte[] Buffer,uint PreviousTagSize) CreateSecondFlvKeyFrame(byte[] spsRawData, byte[] ppsRawData, SPSInfo spsInfo, FlvFrameInfo flvFrameInfo)
{
byte[] buffer = FlvArrayPool.Rent(65535);
try
{
FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
//flv body PreviousTagSize awalys 0
//当首包的时候为 0
//当切花主次码流的时候需要根据上一包的大小
flvMessagePackWriter.WriteUInt32(flvFrameInfo.PreviousTagSize);
//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 0
var videoTagFrame0Buffer = CreateSecondVideoTag0Frame(spsRawData, ppsRawData, spsInfo);
flvMessagePackWriter.WriteArray(videoTagFrame0Buffer);
uint videoTag0PreviousTagSize = (uint)videoTagFrame0Buffer.Length;
return (flvMessagePackWriter.FlushAndGetArray(), videoTag0PreviousTagSize);
}
finally
{
FlvArrayPool.Return(buffer);
}
}

/// <summary>
///
/// </summary>
@@ -449,6 +250,168 @@ namespace JT1078.Flv
}
return default;
}

internal byte[] CreateScriptTagFrame(int width, int height, double frameRate = 25d)
{
byte[] buffer = FlvArrayPool.Rent(1024);
try
{
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
{
FlvArrayPool.Return(buffer);
}
}
internal byte[] CreateVideoTag0Frame(byte[] spsRawData, byte[] ppsRawData, SPSInfo spsInfo)
{
byte[] buffer = FlvArrayPool.Rent(2048);
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);
}
}
internal byte[] CreateVideoTagOtherFrame(FlvFrameInfo flvFrameInfo, H264NALU nALU, H264NALU sei)
{
byte[] buffer = FlvArrayPool.Rent(65535);
try
{
FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
//flv body video tag
//flv body tag header
FlvTags flvTags = new FlvTags();
flvTags.Type = TagType.Video;
//pts
flvTags.Timestamp = flvFrameInfo.Interval;
flvTags.TimestampExt = 0;
flvTags.StreamId = 0;
//flv body tag body
flvTags.VideoTagsData = new VideoTags();
flvTags.VideoTagsData.VideoData = new AvcVideoPacke();
flvTags.VideoTagsData.VideoData.AvcPacketType = AvcPacketType.Raw;
//1: keyframe (for AVC, a seekable frame) —— 即H.264的IDR帧;
//2: inter frame(for AVC, a non - seekable frame) —— H.264的普通I帧;
//ref:https://www.cnblogs.com/chyingp/p/flv-getting-started.html
if (nALU.NALUHeader.NalUnitType == 5)
{
flvTags.VideoTagsData.FrameType = FrameType.KeyFrame;
}
else
{
flvTags.VideoTagsData.FrameType = FrameType.InterFrame;
}
if (flvFrameInfo.LastDataType == JT1078DataType.视频I帧)
{
//cts
flvTags.VideoTagsData.VideoData.CompositionTime = nALU.LastIFrameInterval;
}
else
{
//cts
flvTags.VideoTagsData.VideoData.CompositionTime = nALU.LastFrameInterval;
}
flvTags.VideoTagsData.VideoData.MultiData = new List<byte[]>();
flvTags.VideoTagsData.VideoData.MultiData.Add(nALU.RawData);
//忽略sei
//if (sei != null && sei.RawData != null && sei.RawData.Length > 0)
//{
// flvTags.VideoTagsData.VideoData.MultiData.Add(sei.RawData);
//}
flvMessagePackWriter.WriteFlvTag(flvTags);
return flvMessagePackWriter.FlushAndGetArray();
}
finally
{
FlvArrayPool.Return(buffer);
}
}
internal (byte[] Buffer, uint PreviousTagSize) CreateFirstFlvKeyFrame(byte[] spsRawData, byte[] ppsRawData, SPSInfo spsInfo, uint previousTagSize = 0)
{
byte[] buffer = FlvArrayPool.Rent(65535);
try
{
FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
//flv body PreviousTagSize awalys 0
flvMessagePackWriter.WriteUInt32(previousTagSize);
//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 0
var videoTagFrame0Buffer = CreateVideoTag0Frame(spsRawData, ppsRawData, spsInfo);
flvMessagePackWriter.WriteArray(videoTagFrame0Buffer);
uint videoTag0PreviousTagSize = (uint)videoTagFrame0Buffer.Length;
return (flvMessagePackWriter.FlushAndGetArray(), videoTag0PreviousTagSize);
}
finally
{
FlvArrayPool.Return(buffer);
}
}
}

internal class FlvFrameInfo
@@ -456,6 +419,6 @@ namespace JT1078.Flv
public uint PreviousTagSize { get; set; }
public ulong Timestamp { get; set; }
public uint Interval { get; set; }
public JT1078DataType DataType { get; set; }
public JT1078DataType LastDataType { get; set; }
}
}

+ 1
- 1
src/JT1078.Flv/JT1078.Flv.csproj 查看文件

@@ -14,7 +14,7 @@
<licenseUrl>https://github.com/SmallChi/JT1078/blob/master/LICENSE</licenseUrl>
<license>https://github.com/SmallChi/JT1078/blob/master/LICENSE</license>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>1.0.0-preview2</Version>
<Version>1.0.0-preview3</Version>
<SignAssembly>false</SignAssembly>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<PackageLicenseFile>LICENSE</PackageLicenseFile>


+ 13
- 2
src/JT1078.Flv/JT1078.Flv.xml 查看文件

@@ -53,11 +53,21 @@
Flv固定头部数据
</summary>
</member>
<member name="M:JT1078.Flv.FlvEncoder.CreateFlvFrame(JT1078.Protocol.JT1078Package,System.Int32)">
<member name="M:JT1078.Flv.FlvEncoder.CreateFlvFrame(System.Collections.Generic.List{JT1078.Flv.H264.H264NALU},System.String,System.Int32)">
<summary>
</summary>
<param name="nALUs"></param>
<param name="key">由于获取的SIM卡可能为000000000000,所以如果有替换JT1078Package.GetKey()的值</param>
<param name="minimumLength"></param>
<returns></returns>
</member>
<member name="M:JT1078.Flv.FlvEncoder.CreateFlvFrame(JT1078.Protocol.JT1078Package,System.String,System.Int32)">
<summary>
</summary>
<param name="package">完整的1078包</param>
<param name="key">由于获取的SIM卡可能为000000000000,所以如果有替换JT1078Package.GetKey()的值</param>
<param name="minimumLength">默认65535</param>
<returns></returns>
</member>
@@ -97,12 +107,13 @@
根据tag类型
</summary>
</member>
<member name="M:JT1078.Flv.H264.H264Decoder.ParseNALU(JT1078.Protocol.JT1078Package)">
<member name="M:JT1078.Flv.H264.H264Decoder.ParseNALU(JT1078.Protocol.JT1078Package,System.String)">
<summary>
<see cref="!:https://github.com/samirkumardas/jmuxer/blob/master/src/parsers/h264.js"/>
</summary>
<param name="package"></param>
<param name="key"></param>
<returns></returns>
</member>
<member name="M:JT1078.Flv.H264.H264Decoder.DiscardEmulationPreventionBytes(System.ReadOnlySpan{System.Byte})">


正在加载...
取消
保存