@@ -17,7 +17,7 @@ namespace JT1078.Flv.Test | |||||
public class FlvEncoderTest | public class FlvEncoderTest | ||||
{ | { | ||||
[Fact] | [Fact] | ||||
public void FlvEncoder_Test_1() | |||||
public void 测试第一帧的数据() | |||||
{ | { | ||||
JT1078Package Package = null; | JT1078Package Package = null; | ||||
var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_1.txt")); | var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_1.txt")); | ||||
@@ -42,11 +42,14 @@ namespace JT1078.Flv.Test | |||||
{ | { | ||||
File.Delete(filepath); | File.Delete(filepath); | ||||
} | } | ||||
File.WriteAllBytes(filepath, contents); | |||||
FileStream fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); | |||||
fileStream.Write(FlvEncoder.VideoFlvHeaderBuffer); | |||||
fileStream.Write(contents); | |||||
fileStream.Close(); | |||||
} | } | ||||
[Fact] | [Fact] | ||||
public void FlvEncoder_Test_2() | |||||
public void 测试前几帧的数据() | |||||
{ | { | ||||
FileStream fileStream=null; | FileStream fileStream=null; | ||||
try | try | ||||
@@ -78,6 +81,7 @@ namespace JT1078.Flv.Test | |||||
File.Delete(filepath); | File.Delete(filepath); | ||||
} | } | ||||
fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); | fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); | ||||
fileStream.Write(FlvEncoder.VideoFlvHeaderBuffer); | |||||
var totalPage = (h264NALULs.Count + 10 - 1) / 10; | var totalPage = (h264NALULs.Count + 10 - 1) / 10; | ||||
for(var i=0;i< totalPage; i++) | for(var i=0;i< totalPage; i++) | ||||
{ | { | ||||
@@ -100,7 +104,7 @@ namespace JT1078.Flv.Test | |||||
} | } | ||||
[Fact] | [Fact] | ||||
public void FlvEncoder_Test_3() | |||||
public void 测试可以播放的Flv1() | |||||
{ | { | ||||
FileStream fileStream = null; | FileStream fileStream = null; | ||||
Flv.H264.H264Decoder decoder = new Flv.H264.H264Decoder(); | Flv.H264.H264Decoder decoder = new Flv.H264.H264Decoder(); | ||||
@@ -134,6 +138,7 @@ namespace JT1078.Flv.Test | |||||
} | } | ||||
fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); | fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); | ||||
fileStream.Write(FlvEncoder.VideoFlvHeaderBuffer); | |||||
var totalPage = (h264NALULs.Count + 10 - 1) / 10; | var totalPage = (h264NALULs.Count + 10 - 1) / 10; | ||||
for (var i = 0; i < totalPage; i++) | for (var i = 0; i < totalPage; i++) | ||||
{ | { | ||||
@@ -156,7 +161,7 @@ namespace JT1078.Flv.Test | |||||
} | } | ||||
[Fact] | [Fact] | ||||
public void FlvEncoder_Test_4() | |||||
public void 测试可以播放的Flv2() | |||||
{ | { | ||||
FileStream fileStream = null; | FileStream fileStream = null; | ||||
Flv.H264.H264Decoder decoder = new Flv.H264.H264Decoder(); | Flv.H264.H264Decoder decoder = new Flv.H264.H264Decoder(); | ||||
@@ -189,7 +194,8 @@ namespace JT1078.Flv.Test | |||||
} | } | ||||
} | } | ||||
fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); | |||||
fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); | |||||
fileStream.Write(FlvEncoder.VideoFlvHeaderBuffer); | |||||
var totalPage = (h264NALULs.Count + 10 - 1) / 10; | var totalPage = (h264NALULs.Count + 10 - 1) / 10; | ||||
for (var i = 0; i < totalPage; i++) | for (var i = 0; i < totalPage; i++) | ||||
{ | { | ||||
@@ -212,7 +218,7 @@ namespace JT1078.Flv.Test | |||||
} | } | ||||
[Fact] | [Fact] | ||||
public void FlvEncoder_Test_5() | |||||
public void 测试主次码流切换() | |||||
{ | { | ||||
FileStream fileStream = null; | FileStream fileStream = null; | ||||
Flv.H264.H264Decoder decoder = new Flv.H264.H264Decoder(); | Flv.H264.H264Decoder decoder = new Flv.H264.H264Decoder(); | ||||
@@ -19,6 +19,9 @@ namespace JT1078.Flv | |||||
{ | { | ||||
public class FlvEncoder | public class FlvEncoder | ||||
{ | { | ||||
/// <summary> | |||||
/// Flv固定头部数据 | |||||
/// </summary> | |||||
public static readonly byte[] VideoFlvHeaderBuffer; | public static readonly byte[] VideoFlvHeaderBuffer; | ||||
private static readonly Flv.H264.H264Decoder H264Decoder; | private static readonly Flv.H264.H264Decoder H264Decoder; | ||||
private static readonly ConcurrentDictionary<string, SPSInfo> VideoSPSDict; | private static readonly ConcurrentDictionary<string, SPSInfo> VideoSPSDict; | ||||
@@ -42,7 +45,7 @@ namespace JT1078.Flv | |||||
{ | { | ||||
logger = loggerFactory.CreateLogger("FlvEncoder"); | logger = loggerFactory.CreateLogger("FlvEncoder"); | ||||
} | } | ||||
public byte[] CreateScriptTagFrame(int width, int height, double frameRate = 25d) | |||||
internal byte[] CreateScriptTagFrame(int width, int height, double frameRate = 25d) | |||||
{ | { | ||||
byte[] buffer = FlvArrayPool.Rent(1024); | byte[] buffer = FlvArrayPool.Rent(1024); | ||||
try | try | ||||
@@ -90,7 +93,7 @@ namespace JT1078.Flv | |||||
FlvArrayPool.Return(buffer); | FlvArrayPool.Return(buffer); | ||||
} | } | ||||
} | } | ||||
public byte[] CreateVideoTag0Frame(byte[] spsRawData, byte[] ppsRawData, SPSInfo spsInfo) | |||||
internal byte[] CreateVideoTag0Frame(byte[] spsRawData, byte[] ppsRawData, SPSInfo spsInfo) | |||||
{ | { | ||||
byte[] buffer = FlvArrayPool.Rent(2048); | byte[] buffer = FlvArrayPool.Rent(2048); | ||||
try | try | ||||
@@ -125,7 +128,7 @@ namespace JT1078.Flv | |||||
FlvArrayPool.Return(buffer); | FlvArrayPool.Return(buffer); | ||||
} | } | ||||
} | } | ||||
public byte[] CreateSecondVideoTag0Frame(byte[] spsRawData, byte[] ppsRawData, SPSInfo spsInfo) | |||||
internal byte[] CreateSecondVideoTag0Frame(byte[] spsRawData, byte[] ppsRawData, SPSInfo spsInfo) | |||||
{ | { | ||||
byte[] buffer = FlvArrayPool.Rent(2048); | byte[] buffer = FlvArrayPool.Rent(2048); | ||||
try | try | ||||
@@ -160,7 +163,7 @@ namespace JT1078.Flv | |||||
FlvArrayPool.Return(buffer); | FlvArrayPool.Return(buffer); | ||||
} | } | ||||
} | } | ||||
public byte[] CreateVideoTagOtherFrame(FlvFrameInfo flvFrameInfo, H264NALU nALU, H264NALU sei) | |||||
internal byte[] CreateVideoTagOtherFrame(FlvFrameInfo flvFrameInfo, H264NALU nALU, H264NALU sei) | |||||
{ | { | ||||
byte[] buffer = FlvArrayPool.Rent(65535); | byte[] buffer = FlvArrayPool.Rent(65535); | ||||
try | try | ||||
@@ -334,7 +337,7 @@ namespace JT1078.Flv | |||||
FlvArrayPool.Return(buffer); | FlvArrayPool.Return(buffer); | ||||
} | } | ||||
} | } | ||||
public (byte[] Buffer, uint PreviousTagSize) CreateFirstFlvKeyFrame(byte[] spsRawData, byte[] ppsRawData, SPSInfo spsInfo) | |||||
internal (byte[] Buffer, uint PreviousTagSize) CreateFirstFlvKeyFrame(byte[] spsRawData, byte[] ppsRawData, SPSInfo spsInfo) | |||||
{ | { | ||||
byte[] buffer = FlvArrayPool.Rent(65535); | byte[] buffer = FlvArrayPool.Rent(65535); | ||||
try | try | ||||
@@ -358,7 +361,7 @@ namespace JT1078.Flv | |||||
FlvArrayPool.Return(buffer); | FlvArrayPool.Return(buffer); | ||||
} | } | ||||
} | } | ||||
public (byte[] Buffer,uint PreviousTagSize) CreateSecondFlvKeyFrame(byte[] spsRawData, byte[] ppsRawData, SPSInfo spsInfo, FlvFrameInfo flvFrameInfo) | |||||
internal (byte[] Buffer,uint PreviousTagSize) CreateSecondFlvKeyFrame(byte[] spsRawData, byte[] ppsRawData, SPSInfo spsInfo, FlvFrameInfo flvFrameInfo) | |||||
{ | { | ||||
byte[] buffer = FlvArrayPool.Rent(65535); | byte[] buffer = FlvArrayPool.Rent(65535); | ||||
try | try | ||||
@@ -384,17 +387,29 @@ namespace JT1078.Flv | |||||
FlvArrayPool.Return(buffer); | FlvArrayPool.Return(buffer); | ||||
} | } | ||||
} | } | ||||
/// <summary> | |||||
/// | |||||
/// </summary> | |||||
/// <param name="package">完整的1078包</param> | |||||
/// <param name="minimumLength">默认65535</param> | |||||
/// <returns></returns> | |||||
public byte[] CreateFlvFrame(JT1078Package package,int minimumLength = 65535) | public byte[] CreateFlvFrame(JT1078Package package,int minimumLength = 65535) | ||||
{ | { | ||||
var nalus = H264Decoder.ParseNALU(package); | var nalus = H264Decoder.ParseNALU(package); | ||||
if (nalus == null || nalus.Count <= 0) return default; | if (nalus == null || nalus.Count <= 0) return default; | ||||
return CreateFlvFrame(nalus, minimumLength); | return CreateFlvFrame(nalus, minimumLength); | ||||
} | } | ||||
public byte[] GetFirstFlvFrame(string key,byte[] bufferFlvFrame) | |||||
/// <summary> | |||||
/// | |||||
/// </summary> | |||||
/// <param name="key">设备号+通道号(1111111_1)</param> | |||||
/// <param name="currentBufferFlvFrame">当前接收到的flv数据</param> | |||||
/// <returns></returns> | |||||
public byte[] GetFirstFlvFrame(string key,byte[] currentBufferFlvFrame) | |||||
{ | { | ||||
if (FirstFlvFrameCache.TryGetValue(key, out var firstBuffer)) | if (FirstFlvFrameCache.TryGetValue(key, out var firstBuffer)) | ||||
{ | { | ||||
var length = firstBuffer.Buffer.Length + bufferFlvFrame.Length + VideoFlvHeaderBuffer.Length; | |||||
var length = firstBuffer.Buffer.Length + currentBufferFlvFrame.Length + VideoFlvHeaderBuffer.Length; | |||||
byte[] buffer = FlvArrayPool.Rent(length); | byte[] buffer = FlvArrayPool.Rent(length); | ||||
try | try | ||||
{ | { | ||||
@@ -406,16 +421,16 @@ namespace JT1078.Flv | |||||
BinaryPrimitives.WriteUInt32BigEndian(firstBuffer.Buffer, 0); | BinaryPrimitives.WriteUInt32BigEndian(firstBuffer.Buffer, 0); | ||||
firstBuffer.Buffer.CopyTo(tmp.Slice(VideoFlvHeaderBuffer.Length)); | firstBuffer.Buffer.CopyTo(tmp.Slice(VideoFlvHeaderBuffer.Length)); | ||||
//新用户进来需要替换为上一包的PreviousTagSize | //新用户进来需要替换为上一包的PreviousTagSize | ||||
BinaryPrimitives.WriteUInt32BigEndian(bufferFlvFrame, firstBuffer.PreviousTagSize); | |||||
bufferFlvFrame.CopyTo(tmp.Slice(VideoFlvHeaderBuffer.Length + firstBuffer.Buffer.Length)); | |||||
BinaryPrimitives.WriteUInt32BigEndian(currentBufferFlvFrame, firstBuffer.PreviousTagSize); | |||||
currentBufferFlvFrame.CopyTo(tmp.Slice(VideoFlvHeaderBuffer.Length + firstBuffer.Buffer.Length)); | |||||
return tmp.Slice(0, length).ToArray(); | return tmp.Slice(0, length).ToArray(); | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
firstBuffer.Buffer.CopyTo(tmp.Slice(VideoFlvHeaderBuffer.Length)); | firstBuffer.Buffer.CopyTo(tmp.Slice(VideoFlvHeaderBuffer.Length)); | ||||
//新用户进来需要替换为首包的PreviousTagSize | //新用户进来需要替换为首包的PreviousTagSize | ||||
BinaryPrimitives.WriteUInt32BigEndian(bufferFlvFrame, firstBuffer.PreviousTagSize); | |||||
bufferFlvFrame.CopyTo(tmp.Slice(VideoFlvHeaderBuffer.Length + firstBuffer.Buffer.Length)); | |||||
BinaryPrimitives.WriteUInt32BigEndian(currentBufferFlvFrame, firstBuffer.PreviousTagSize); | |||||
currentBufferFlvFrame.CopyTo(tmp.Slice(VideoFlvHeaderBuffer.Length + firstBuffer.Buffer.Length)); | |||||
return tmp.Slice(0, length).ToArray(); | return tmp.Slice(0, length).ToArray(); | ||||
} | } | ||||
} | } | ||||
@@ -428,7 +443,7 @@ namespace JT1078.Flv | |||||
} | } | ||||
} | } | ||||
public class FlvFrameInfo | |||||
internal class FlvFrameInfo | |||||
{ | { | ||||
public uint PreviousTagSize { get; set; } | public uint PreviousTagSize { get; set; } | ||||
public ulong Timestamp { get; set; } | public ulong Timestamp { get; set; } | ||||
@@ -14,12 +14,20 @@ | |||||
<licenseUrl>https://github.com/SmallChi/JT1078/blob/master/LICENSE</licenseUrl> | <licenseUrl>https://github.com/SmallChi/JT1078/blob/master/LICENSE</licenseUrl> | ||||
<license>https://github.com/SmallChi/JT1078/blob/master/LICENSE</license> | <license>https://github.com/SmallChi/JT1078/blob/master/LICENSE</license> | ||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> | <GeneratePackageOnBuild>false</GeneratePackageOnBuild> | ||||
<Version>1.0.0-preview1</Version> | |||||
<Version>1.0.0-preview2</Version> | |||||
<SignAssembly>false</SignAssembly> | <SignAssembly>false</SignAssembly> | ||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | ||||
<PackageLicenseFile>LICENSE</PackageLicenseFile> | <PackageLicenseFile>LICENSE</PackageLicenseFile> | ||||
</PropertyGroup> | </PropertyGroup> | ||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|netstandard2.0|AnyCPU'"> | |||||
<DocumentationFile>JT1078.Flv.xml</DocumentationFile> | |||||
</PropertyGroup> | |||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|netstandard2.0|AnyCPU'"> | |||||
<DocumentationFile>JT1078.Flv.xml</DocumentationFile> | |||||
</PropertyGroup> | |||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' "> | <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' "> | ||||
<PackageReference Include="System.Memory" Version="4.5.3" /> | <PackageReference Include="System.Memory" Version="4.5.3" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
@@ -0,0 +1,203 @@ | |||||
<?xml version="1.0"?> | |||||
<doc> | |||||
<assembly> | |||||
<name>JT1078.Flv</name> | |||||
</assembly> | |||||
<members> | |||||
<member name="T:JT1078.Flv.FlvBufferWriter"> | |||||
<summary> | |||||
<see cref="!:System.Buffers.Writer"/> | |||||
</summary> | |||||
</member> | |||||
<member name="F:JT1078.Flv.Enums.FrameType.KeyFrame"> | |||||
<summary> | |||||
00010000 | |||||
</summary> | |||||
</member> | |||||
<member name="F:JT1078.Flv.Enums.FrameType.InterFrame"> | |||||
<summary> | |||||
00100000 | |||||
</summary> | |||||
</member> | |||||
<member name="F:JT1078.Flv.Enums.FrameType.DisposableInterFrame"> | |||||
<summary> | |||||
00110000 | |||||
</summary> | |||||
</member> | |||||
<member name="F:JT1078.Flv.Enums.FrameType.GeneratedKeyFrame"> | |||||
<summary> | |||||
01000000 | |||||
</summary> | |||||
</member> | |||||
<member name="F:JT1078.Flv.Enums.FrameType.VideoInfoOrCommandFrame"> | |||||
<summary> | |||||
01010000 | |||||
</summary> | |||||
</member> | |||||
<member name="T:JT1078.Flv.Extensions.HexExtensions"> | |||||
<summary> | |||||
ref:"www.codeproject.com/tips/447938/high-performance-csharp-byte-array-to-hex-string-t" | |||||
</summary> | |||||
</member> | |||||
<member name="M:JT1078.Flv.Extensions.HexExtensions.ToHexBytes(System.String)"> | |||||
<summary> | |||||
16进制字符串转16进制数组 | |||||
</summary> | |||||
<param name="hexString"></param> | |||||
<param name="separator"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="F:JT1078.Flv.FlvEncoder.VideoFlvHeaderBuffer"> | |||||
<summary> | |||||
Flv固定头部数据 | |||||
</summary> | |||||
</member> | |||||
<member name="M:JT1078.Flv.FlvEncoder.CreateFlvFrame(JT1078.Protocol.JT1078Package,System.Int32)"> | |||||
<summary> | |||||
</summary> | |||||
<param name="package">完整的1078包</param> | |||||
<param name="minimumLength">默认65535</param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="M:JT1078.Flv.FlvEncoder.GetFirstFlvFrame(System.String,System.Byte[])"> | |||||
<summary> | |||||
</summary> | |||||
<param name="key">设备号+通道号(1111111_1)</param> | |||||
<param name="currentBufferFlvFrame">当前接收到的flv数据</param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="P:JT1078.Flv.FlvTags.DataSize"> | |||||
<summary> | |||||
Tag Data部分大小 | |||||
3个字节 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT1078.Flv.FlvTags.Timestamp"> | |||||
<summary> | |||||
Tag时间戳 | |||||
3个字节 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT1078.Flv.FlvTags.StreamId"> | |||||
<summary> | |||||
stream id 总是0 | |||||
3个字节 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT1078.Flv.FlvTags.VideoTagsData"> | |||||
<summary> | |||||
根据tag类型 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT1078.Flv.FlvTags.DataTagsData"> | |||||
<summary> | |||||
根据tag类型 | |||||
</summary> | |||||
</member> | |||||
<member name="M:JT1078.Flv.H264.H264Decoder.ParseNALU(JT1078.Protocol.JT1078Package)"> | |||||
<summary> | |||||
<see cref="!:https://github.com/samirkumardas/jmuxer/blob/master/src/parsers/h264.js"/> | |||||
</summary> | |||||
<param name="package"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="M:JT1078.Flv.H264.H264Decoder.DiscardEmulationPreventionBytes(System.ReadOnlySpan{System.Byte})"> | |||||
<summary> | |||||
Expunge any "Emulation Prevention" bytes from a "Raw Byte Sequence Payload" | |||||
<see cref="!:https://blog.csdn.net/u011399342/article/details/80472084"/> | |||||
防止竞争插入0x03 | |||||
</summary> | |||||
<param name="srcBuffer"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="P:JT1078.Flv.H264.H264NALU.SIM"> | |||||
<summary> | |||||
终端设备SIM卡号 | |||||
BCD[6] | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT1078.Flv.H264.H264NALU.LogicChannelNumber"> | |||||
<summary> | |||||
逻辑通道号 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT1078.Flv.H264.H264NALU.DataType"> | |||||
<summary> | |||||
数据类型 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT1078.Flv.H264.H264NALU.LastIFrameInterval"> | |||||
<summary> | |||||
该帧与上一个关键帧之间的时间间隔,单位毫秒(ms), | |||||
当数据类型为非视频帧时,则没有该字段 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT1078.Flv.H264.H264NALU.LastFrameInterval"> | |||||
<summary> | |||||
该帧与上一个帧之间的时间间隔,单位毫秒(ms), | |||||
当数据类型为非视频帧时,则没有该字段 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT1078.Flv.H264.H264NALU.Timestamp"> | |||||
<summary> | |||||
时间戳 | |||||
标识此RTP数据包当前帧的相对时间,单位毫秒(ms)。 | |||||
当数据类型为01000时,则没有该字段 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT1078.Flv.H264.H264NALU.RawData"> | |||||
<summary> | |||||
数据体 | |||||
</summary> | |||||
</member> | |||||
<member name="T:JT1078.Flv.MessagePack.ExpGolombReader"> | |||||
<summary> | |||||
Exp-Golomb指数哥伦布编码 | |||||
</summary> | |||||
</member> | |||||
<member name="M:JT1078.Flv.MessagePack.ExpGolombReader.SkipScalingList(System.Int32)"> | |||||
<summary> | |||||
Advance the ExpGolomb decoder past a scaling list.The scaling | |||||
list is optionally transmitted as part of a sequence parameter | |||||
set and is not relevant to transmuxing. | |||||
@param count { number} | |||||
the number of entries in this scaling list | |||||
@see Recommendation ITU-T H.264, Section 7.3.2.1.1.1 | |||||
</summary> | |||||
<param name="count"></param> | |||||
</member> | |||||
<member name="P:JT1078.Flv.Metadata.Amf3.DataType"> | |||||
<summary> | |||||
AMF3数据类型 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT1078.Flv.Metadata.Amf3.Count"> | |||||
<summary> | |||||
元素个数 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT1078.Flv.Metadata.Amf3Metadata_VideoCodecId.Value"> | |||||
<summary> | |||||
<see cref="!:typeof(JT1078.Flv.Enums.CodecId.AvcVideoPacke)"/> | |||||
</summary> | |||||
</member> | |||||
<!-- Badly formed XML comment ignored for member "T:JT1078.Flv.Metadata.AVCDecoderConfigurationRecord" --> | |||||
<member name="P:JT1078.Flv.Metadata.VideoTags.FrameType"> | |||||
<summary> | |||||
高4位 | |||||
1: keyframe(for AVC, a seekable frame) —— 即H.264的IDR帧; | |||||
2: inter frame(for AVC, a non- seekable frame) —— H.264的普通I帧; | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT1078.Flv.Metadata.VideoTags.CodecId"> | |||||
<summary> | |||||
第四位 | |||||
当 CodecID 为 7 时,VideoData 为 AVCVIDEOPACKE,也即 H.264媒体数据 | |||||
</summary> | |||||
</member> | |||||
</members> | |||||
</doc> |