Browse Source

将1078转fmp4_11

master
SmallChi(Koike) 4 years ago
parent
commit
97b8832127
13 changed files with 89 additions and 66 deletions
  1. +1
    -1
      src/JT1078.AV.Benchmark/JT1078FlvEncoderContext.cs
  2. +10
    -10
      src/JT1078.FMp4.Test/H264/index.html
  3. +10
    -9
      src/JT1078.FMp4.Test/JT1078ToFMp4Box_Test.cs
  4. +2
    -0
      src/JT1078.FMp4/Boxs/SegmentIndexBox.cs
  5. +6
    -4
      src/JT1078.FMp4/Boxs/TrackRunBox.cs
  6. +20
    -26
      src/JT1078.FMp4/FMp4Encoder.cs
  7. +6
    -1
      src/JT1078.FMp4/JT1078.FMp4.xml
  8. +4
    -4
      src/JT1078.Flv/FlvEncoder.cs
  9. +1
    -1
      src/JT1078.Protocol.Benchmark/JT1078FlvEncoderContext.cs
  10. +5
    -5
      src/JT1078.Protocol.Test/H264/H264DecoderTest.cs
  11. +1
    -1
      src/JT1078.Protocol.Test/H264/NALUHeaderTest.cs
  12. +20
    -3
      src/JT1078.Protocol/H264/NALUHeader.cs
  13. +3
    -1
      src/JT1078.SignalR.Test/Services/ToWebSocketService.cs

+ 1
- 1
src/JT1078.AV.Benchmark/JT1078FlvEncoderContext.cs View File

@@ -42,7 +42,7 @@ namespace JT1078.AV.Benchmark
Package = JT1078Serializer.Merge(package); Package = JT1078Serializer.Merge(package);
} }
H264NALUs = h264Decoder.ParseNALU(Package); H264NALUs = h264Decoder.ParseNALU(Package);
SPSNALu = H264NALUs.FirstOrDefault(f => f.NALUHeader.NalUnitType == 7);
SPSNALu = H264NALUs.FirstOrDefault(f => f.NALUHeader.NalUnitType == NalUnitType.SPS);
SPSNALu.RawData = h264Decoder.DiscardEmulationPreventionBytes(SPSNALu.RawData); SPSNALu.RawData = h264Decoder.DiscardEmulationPreventionBytes(SPSNALu.RawData);
} }




+ 10
- 10
src/JT1078.FMp4.Test/H264/index.html View File

@@ -96,17 +96,17 @@
// otherwise insert it to queue // otherwise insert it to queue
var memview = new Uint8Array(arr); var memview = new Uint8Array(arr);
if (verbose) { console.log("got", arr.byteLength, "bytes. Values=", memview[0], memview[1], memview[2], memview[3], memview[4]); } if (verbose) { console.log("got", arr.byteLength, "bytes. Values=", memview[0], memview[1], memview[2], memview[3], memview[4]); }
//res = getBox(memview, 0);
//main_length = res[0]; name = res[1]; // this boxes length and name
//if ((name == "ftyp") && (pass == 0)) {
res = getBox(memview, 0);
main_length = res[0]; name = res[1]; // this boxes length and name
// if ((name == "ftyp") && (pass == 0)) {
// pass = pass + 1; // pass = pass + 1;
// console.log("got ftyp"); // console.log("got ftyp");
//}
//else if ((name == "moov") && (pass == 1)) {
// }
// else if ((name == "moov") && (pass == 1)) {
// pass = pass + 1; // pass = pass + 1;
// console.log("got moov"); // console.log("got moov");
//}
//else if ((name == "moof") && (pass == 2)) {
// }
// else if ((name == "moof") && (pass == 2)) {
// if (hasFirstSampleFlag(memview)) { // if (hasFirstSampleFlag(memview)) {
// pass = pass + 1; // pass = pass + 1;
// console.log("got that special moof"); // console.log("got that special moof");
@@ -114,10 +114,10 @@
// else { // else {
// return; // return;
// } // }
//}
//else if (pass < 3) {
// }
// else if (pass < 3) {
// return; // return;
//}
// }
// keep the latency to minimum // keep the latency to minimum
let latest = stream_live.duration; let latest = stream_live.duration;
if ((stream_live.duration >= buffering_sec) && if ((stream_live.duration >= buffering_sec) &&


+ 10
- 9
src/JT1078.FMp4.Test/JT1078ToFMp4Box_Test.cs View File

@@ -24,10 +24,10 @@ namespace JT1078.FMp4.Test
var jT1078Package = ParseNALUTest(); var jT1078Package = ParseNALUTest();
H264Decoder decoder = new H264Decoder(); H264Decoder decoder = new H264Decoder();
var nalus = decoder.ParseNALU(jT1078Package); var nalus = decoder.ParseNALU(jT1078Package);
var spsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 7);
var spsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == NalUnitType.SPS);
//SPS //SPS
spsNALU.RawData = decoder.DiscardEmulationPreventionBytes(spsNALU.RawData); spsNALU.RawData = decoder.DiscardEmulationPreventionBytes(spsNALU.RawData);
var ppsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 8);
var ppsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == NalUnitType.PPS);
ppsNALU.RawData = decoder.DiscardEmulationPreventionBytes(ppsNALU.RawData); ppsNALU.RawData = decoder.DiscardEmulationPreventionBytes(ppsNALU.RawData);
//ftyp //ftyp
FileTypeBox fileTypeBox = new FileTypeBox(); FileTypeBox fileTypeBox = new FileTypeBox();
@@ -176,10 +176,10 @@ namespace JT1078.FMp4.Test
var jT1078Package = ParseNALUTest(); var jT1078Package = ParseNALUTest();
H264Decoder decoder = new H264Decoder(); H264Decoder decoder = new H264Decoder();
var nalus = decoder.ParseNALU(jT1078Package); var nalus = decoder.ParseNALU(jT1078Package);
var spsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 7);
var spsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == NalUnitType.SPS);
//SPS //SPS
spsNALU.RawData = decoder.DiscardEmulationPreventionBytes(spsNALU.RawData); spsNALU.RawData = decoder.DiscardEmulationPreventionBytes(spsNALU.RawData);
var ppsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 8);
var ppsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == NalUnitType.PPS);
ppsNALU.RawData = decoder.DiscardEmulationPreventionBytes(ppsNALU.RawData); ppsNALU.RawData = decoder.DiscardEmulationPreventionBytes(ppsNALU.RawData);
FMp4MessagePackWriter writer = new FMp4MessagePackWriter(new byte[65535]); FMp4MessagePackWriter writer = new FMp4MessagePackWriter(new byte[65535]);
//ftyp //ftyp
@@ -324,10 +324,10 @@ namespace JT1078.FMp4.Test
using var fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); using var fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write);
var jT1078Package = packages.FirstOrDefault(); var jT1078Package = packages.FirstOrDefault();
var nalus = decoder.ParseNALU(jT1078Package); var nalus = decoder.ParseNALU(jT1078Package);
var spsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 7);
var spsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == NalUnitType.SPS);
//SPS //SPS
spsNALU.RawData = decoder.DiscardEmulationPreventionBytes(spsNALU.RawData); spsNALU.RawData = decoder.DiscardEmulationPreventionBytes(spsNALU.RawData);
var ppsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 8);
var ppsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == NalUnitType.PPS);
ppsNALU.RawData = decoder.DiscardEmulationPreventionBytes(ppsNALU.RawData); ppsNALU.RawData = decoder.DiscardEmulationPreventionBytes(ppsNALU.RawData);
ExpGolombReader h264GolombReader = new ExpGolombReader(spsNALU.RawData); ExpGolombReader h264GolombReader = new ExpGolombReader(spsNALU.RawData);
var spsInfo = h264GolombReader.ReadSPS(); var spsInfo = h264GolombReader.ReadSPS();
@@ -455,15 +455,16 @@ namespace JT1078.FMp4.Test
{ {
var otherStypBuffer = fMp4Encoder.EncoderStypBox(); var otherStypBuffer = fMp4Encoder.EncoderStypBox();
fileStream.Write(otherStypBuffer); fileStream.Write(otherStypBuffer);
var otherSidxBuffer = fMp4Encoder.EncoderSidxBox(package.Timestamp, package.LastIFrameInterval);
fileStream.Write(otherSidxBuffer);
var otherNalus = h264Decoder.ParseNALU(package); var otherNalus = h264Decoder.ParseNALU(package);
var flag = package.Label3.DataType == Protocol.Enums.JT1078DataType.视频I帧 ? 1u : 0u; var flag = package.Label3.DataType == Protocol.Enums.JT1078DataType.视频I帧 ? 1u : 0u;

var otherMoofBuffer = fMp4Encoder.EncoderMoofBox(otherNalus, package.Bodies.Length, package.Timestamp, package.LastIFrameInterval, flag); var otherMoofBuffer = fMp4Encoder.EncoderMoofBox(otherNalus, package.Bodies.Length, package.Timestamp, package.LastIFrameInterval, flag);
var otherMdatBuffer = fMp4Encoder.EncoderMdatBox(otherNalus, package.Bodies.Length); var otherMdatBuffer = fMp4Encoder.EncoderMdatBox(otherNalus, package.Bodies.Length);
var otherSidxBuffer = fMp4Encoder.EncoderSidxBox(otherMoofBuffer.Length + otherMdatBuffer.Length, package.Timestamp, package.LastIFrameInterval);

fileStream.Write(otherSidxBuffer);
fileStream.Write(otherMoofBuffer); fileStream.Write(otherMoofBuffer);
fileStream.Write(otherMdatBuffer); fileStream.Write(otherMdatBuffer);

} }
fileStream.Close(); fileStream.Close();
} }


+ 2
- 0
src/JT1078.FMp4/Boxs/SegmentIndexBox.cs View File

@@ -28,6 +28,7 @@ namespace JT1078.FMp4
/// </summary> /// </summary>
public uint Timescale { get; set; } = 1000; public uint Timescale { get; set; } = 1000;
/// <summary> /// <summary>
/// pts
/// if(version==0) /// if(version==0)
/// version==0 32 bit /// version==0 32 bit
/// version>0 64 bit /// version>0 64 bit
@@ -100,6 +101,7 @@ namespace JT1078.FMp4
public bool ReferenceType { get; set; } = false; public bool ReferenceType { get; set; } = false;
/// <summary> /// <summary>
/// 4byte 32 - 31 /// 4byte 32 - 31
/// ReferencedSize=(moof size) + (mdat size)
/// </summary> /// </summary>
public uint ReferencedSize { get; set; } = 0; public uint ReferencedSize { get; set; } = 0;
/// <summary> /// <summary>


+ 6
- 4
src/JT1078.FMp4/Boxs/TrackRunBox.cs View File

@@ -24,6 +24,7 @@ namespace JT1078.FMp4
/// 0x000200-0010 0000 0000: 每个 sample 有自己的 sample_size,否则使用默认的。 /// 0x000200-0010 0000 0000: 每个 sample 有自己的 sample_size,否则使用默认的。
/// 0x000400-0100 0000 0000: 对每个 sample 使用自己的 flags。否则,使用默认的。 /// 0x000400-0100 0000 0000: 对每个 sample 使用自己的 flags。否则,使用默认的。
/// 0x000800-1000 0000 0000: 每个 sample 都有自己的 cts 值 /// 0x000800-1000 0000 0000: 每个 sample 都有自己的 cts 值
/// 0x000f01-1111 0000 0001
/// </summary> /// </summary>
/// <param name="version"></param> /// <param name="version"></param>
/// <param name="flags"></param> /// <param name="flags"></param>
@@ -101,11 +102,11 @@ namespace JT1078.FMp4
{ {
if (Version == 0) if (Version == 0)
{ {
writer.WriteUInt32(trun.SampleCompositionTimeOffset);
writer.WriteUInt32((uint)trun.SampleCompositionTimeOffset);
} }
else else
{ {
writer.WriteInt32(trun.SignedSampleCompositionTimeOffset);
writer.WriteInt32((int)trun.SampleCompositionTimeOffset);
} }
} }
} }
@@ -120,9 +121,10 @@ namespace JT1078.FMp4
public uint SampleFlags { get; set; } public uint SampleFlags { get; set; }
/// <summary> /// <summary>
/// version == 0 /// version == 0
/// 0:uint
/// >0:int
/// </summary> /// </summary>
public uint SampleCompositionTimeOffset { get; set; }
public int SignedSampleCompositionTimeOffset { get; set; }
public long SampleCompositionTimeOffset { get; set; }
} }
} }
} }

+ 20
- 26
src/JT1078.FMp4/FMp4Encoder.cs View File

@@ -31,6 +31,7 @@ namespace JT1078.FMp4
public class FMp4Encoder public class FMp4Encoder
{ {
readonly H264Decoder h264Decoder; readonly H264Decoder h264Decoder;

/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
@@ -111,7 +112,7 @@ namespace JT1078.FMp4
/// 编码sidx盒子 /// 编码sidx盒子
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public byte[] EncoderSidxBox(ulong timestamp, uint frameInterval)
public byte[] EncoderSidxBox(int moofAndMdatLength, ulong timestamp, uint frameInterval)
{ {
byte[] buffer = FMp4ArrayPool.Rent(4096); byte[] buffer = FMp4ArrayPool.Rent(4096);
FMp4MessagePackWriter writer = new FMp4MessagePackWriter(buffer); FMp4MessagePackWriter writer = new FMp4MessagePackWriter(buffer);
@@ -119,11 +120,12 @@ namespace JT1078.FMp4
{ {
SegmentIndexBox segmentIndexBox = new SegmentIndexBox(1); SegmentIndexBox segmentIndexBox = new SegmentIndexBox(1);
segmentIndexBox.ReferenceID = 1; segmentIndexBox.ReferenceID = 1;
segmentIndexBox.EarliestPresentationTime = timestamp;
segmentIndexBox.EarliestPresentationTime = timestamp*1000;
segmentIndexBox.SegmentIndexs = new List<SegmentIndexBox.SegmentIndex>() segmentIndexBox.SegmentIndexs = new List<SegmentIndexBox.SegmentIndex>()
{ {
new SegmentIndexBox.SegmentIndex new SegmentIndexBox.SegmentIndex
{ {
ReferencedSize=(uint)moofAndMdatLength,
SubsegmentDuration=frameInterval SubsegmentDuration=frameInterval
} }
}; };
@@ -147,10 +149,10 @@ namespace JT1078.FMp4
FMp4MessagePackWriter writer = new FMp4MessagePackWriter(buffer); FMp4MessagePackWriter writer = new FMp4MessagePackWriter(buffer);
try try
{ {
var spsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 7);
var spsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == NalUnitType.SPS);
//SPS //SPS
spsNALU.RawData = h264Decoder.DiscardEmulationPreventionBytes(spsNALU.RawData); spsNALU.RawData = h264Decoder.DiscardEmulationPreventionBytes(spsNALU.RawData);
var ppsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 8);
var ppsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == NalUnitType.PPS);
ppsNALU.RawData = h264Decoder.DiscardEmulationPreventionBytes(ppsNALU.RawData); ppsNALU.RawData = h264Decoder.DiscardEmulationPreventionBytes(ppsNALU.RawData);
ExpGolombReader h264GolombReader = new ExpGolombReader(spsNALU.RawData); ExpGolombReader h264GolombReader = new ExpGolombReader(spsNALU.RawData);
var spsInfo = h264GolombReader.ReadSPS(); var spsInfo = h264GolombReader.ReadSPS();
@@ -242,37 +244,29 @@ namespace JT1078.FMp4
//0x02 分段 //0x02 分段
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox = new TrackFragmentHeaderBox(0x20038); movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox = new TrackFragmentHeaderBox(0x20038);
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.TrackID = 1; movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.TrackID = 1;
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleDuration = 48000;
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleDuration = frameInterval;
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleSize = (uint)naluLength; movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleSize = (uint)naluLength;
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleFlags = 0x1010000; movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleFlags = 0x1010000;
movieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox = new TrackFragmentBaseMediaDecodeTimeBox(); movieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox = new TrackFragmentBaseMediaDecodeTimeBox();
movieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox.BaseMediaDecodeTime = timestamp*1000;
//trun //trun
//0x39 写文件 //0x39 写文件
//0x02 分段 //0x02 分段
//0x205
//uint flag = 0x000200 | 0x000800 | 0x000400 | 0x000100; //uint flag = 0x000200 | 0x000800 | 0x000400 | 0x000100;
uint flag = 4u;
if (!first)
{
//sdtp.IsLeading = 1;
//flag = 4u;
movieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox.BaseMediaDecodeTime = 0;
movieFragmentBox.TrackFragmentBox.TrackRunBox = new TrackRunBox(flags: 5);
first = true;
}
else
{
//flag = 0x000400;
movieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox.BaseMediaDecodeTime = timestamp*1000;
movieFragmentBox.TrackFragmentBox.TrackRunBox = new TrackRunBox(flags: 5);
}
movieFragmentBox.TrackFragmentBox.TrackRunBox = new TrackRunBox();
movieFragmentBox.TrackFragmentBox.TrackRunBox.FirstSampleFlags = 33554432; movieFragmentBox.TrackFragmentBox.TrackRunBox.FirstSampleFlags = 33554432;
movieFragmentBox.TrackFragmentBox.TrackRunBox.TrackRunInfos = new List<TrackRunBox.TrackRunInfo>(); movieFragmentBox.TrackFragmentBox.TrackRunBox.TrackRunInfos = new List<TrackRunBox.TrackRunInfo>();
if (frameIntervalCache == 0)
{
frameIntervalCache += frameInterval;
}
movieFragmentBox.TrackFragmentBox.TrackRunBox.TrackRunInfos.Add(new TrackRunBox.TrackRunInfo() movieFragmentBox.TrackFragmentBox.TrackRunBox.TrackRunInfos.Add(new TrackRunBox.TrackRunInfo()
{ {
SampleDuration= frameInterval,
SampleDuration= frameIntervalCache,
SampleSize = (uint)naluLength, SampleSize = (uint)naluLength,
SampleCompositionTimeOffset = frameInterval,
SampleFlags = flag
SampleCompositionTimeOffset = (long)timestamp ,
SampleFlags = movieFragmentBox.TrackFragmentBox.TrackRunBox.Flags
}); });
movieFragmentBox.ToBuffer(ref writer); movieFragmentBox.ToBuffer(ref writer);
var data = writer.FlushAndGetArray(); var data = writer.FlushAndGetArray();
@@ -318,10 +312,10 @@ namespace JT1078.FMp4
try try
{ {
var nalus = h264Decoder.ParseNALU(package); var nalus = h264Decoder.ParseNALU(package);
var spsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 7);
var spsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == NalUnitType.SPS);
//SPS //SPS
spsNALU.RawData = h264Decoder.DiscardEmulationPreventionBytes(spsNALU.RawData); spsNALU.RawData = h264Decoder.DiscardEmulationPreventionBytes(spsNALU.RawData);
var ppsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 8);
var ppsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == NalUnitType.PPS);
ppsNALU.RawData = h264Decoder.DiscardEmulationPreventionBytes(ppsNALU.RawData); ppsNALU.RawData = h264Decoder.DiscardEmulationPreventionBytes(ppsNALU.RawData);
ExpGolombReader h264GolombReader = new ExpGolombReader(spsNALU.RawData); ExpGolombReader h264GolombReader = new ExpGolombReader(spsNALU.RawData);
var spsInfo = h264GolombReader.ReadSPS(); var spsInfo = h264GolombReader.ReadSPS();
@@ -405,7 +399,7 @@ namespace JT1078.FMp4
} }


uint sn = 1; uint sn = 1;
uint frameIntervalCache = 0;
bool first = false; bool first = false;


/// <summary> /// <summary>


+ 6
- 1
src/JT1078.FMp4/JT1078.FMp4.xml View File

@@ -700,6 +700,7 @@
</member> </member>
<member name="P:JT1078.FMp4.SegmentIndexBox.EarliestPresentationTime"> <member name="P:JT1078.FMp4.SegmentIndexBox.EarliestPresentationTime">
<summary> <summary>
pts
if(version==0) if(version==0)
version==0 32 bit version==0 32 bit
version>0 64 bit version>0 64 bit
@@ -723,6 +724,7 @@
<member name="P:JT1078.FMp4.SegmentIndexBox.SegmentIndex.ReferencedSize"> <member name="P:JT1078.FMp4.SegmentIndexBox.SegmentIndex.ReferencedSize">
<summary> <summary>
4byte 32 - 31 4byte 32 - 31
ReferencedSize=(moof size) + (mdat size)
</summary> </summary>
</member> </member>
<member name="P:JT1078.FMp4.SegmentIndexBox.SegmentIndex.SubsegmentDuration"> <member name="P:JT1078.FMp4.SegmentIndexBox.SegmentIndex.SubsegmentDuration">
@@ -1062,6 +1064,7 @@
0x000200-0010 0000 0000: 每个 sample 有自己的 sample_size,否则使用默认的。 0x000200-0010 0000 0000: 每个 sample 有自己的 sample_size,否则使用默认的。
0x000400-0100 0000 0000: 对每个 sample 使用自己的 flags。否则,使用默认的。 0x000400-0100 0000 0000: 对每个 sample 使用自己的 flags。否则,使用默认的。
0x000800-1000 0000 0000: 每个 sample 都有自己的 cts 值 0x000800-1000 0000 0000: 每个 sample 都有自己的 cts 值
0x000f01-1111 0000 0001
</summary> </summary>
<param name="version"></param> <param name="version"></param>
<param name="flags"></param> <param name="flags"></param>
@@ -1092,6 +1095,8 @@
<member name="P:JT1078.FMp4.TrackRunBox.TrackRunInfo.SampleCompositionTimeOffset"> <member name="P:JT1078.FMp4.TrackRunBox.TrackRunInfo.SampleCompositionTimeOffset">
<summary> <summary>
version == 0 version == 0
0:uint
>0:int
</summary> </summary>
</member> </member>
<member name="T:JT1078.FMp4.URIBox"> <member name="T:JT1078.FMp4.URIBox">
@@ -1330,7 +1335,7 @@
</summary> </summary>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:JT1078.FMp4.FMp4Encoder.EncoderSidxBox(System.UInt64,System.UInt32)">
<member name="M:JT1078.FMp4.FMp4Encoder.EncoderSidxBox(System.Int32,System.UInt64,System.UInt32)">
<summary> <summary>
编码sidx盒子 编码sidx盒子
</summary> </summary>


+ 4
- 4
src/JT1078.Flv/FlvEncoder.cs View File

@@ -207,9 +207,9 @@ namespace JT1078.Flv
var nalus = h264Decoder.ParseNALU(package); var nalus = h264Decoder.ParseNALU(package);
if (nalus != null && nalus.Count > 0) if (nalus != null && nalus.Count > 0)
{ {
var sei = nalus.FirstOrDefault(x => x.NALUHeader.NalUnitType == 6);
var sps = nalus.FirstOrDefault(x => x.NALUHeader.NalUnitType == 7);
var pps = nalus.FirstOrDefault(x => x.NALUHeader.NalUnitType == 8);
var sei = nalus.FirstOrDefault(x => x.NALUHeader.NalUnitType == NalUnitType.SEI);
var sps = nalus.FirstOrDefault(x => x.NALUHeader.NalUnitType == NalUnitType.SPS);
var pps = nalus.FirstOrDefault(x => x.NALUHeader.NalUnitType == NalUnitType.PPS);
nalus.Remove(sps); nalus.Remove(sps);
nalus.Remove(pps); nalus.Remove(pps);
nalus.Remove(sei); nalus.Remove(sei);
@@ -297,7 +297,7 @@ namespace JT1078.Flv
//1: keyframe (for AVC, a seekable frame) —— 即H.264的IDR帧; //1: keyframe (for AVC, a seekable frame) —— 即H.264的IDR帧;
//2: inter frame(for AVC, a non - seekable frame) —— H.264的普通I帧; //2: inter frame(for AVC, a non - seekable frame) —— H.264的普通I帧;
//ref:https://www.cnblogs.com/chyingp/p/flv-getting-started.html //ref:https://www.cnblogs.com/chyingp/p/flv-getting-started.html
if (nALU.NALUHeader.NalUnitType == 5)
if (nALU.NALUHeader.NalUnitType == NalUnitType.IDR)
{ {
flvTags.VideoTagsData.FrameType = FrameType.KeyFrame; flvTags.VideoTagsData.FrameType = FrameType.KeyFrame;
} }


+ 1
- 1
src/JT1078.Protocol.Benchmark/JT1078FlvEncoderContext.cs View File

@@ -41,7 +41,7 @@ namespace JT1078.Flv.Benchmark
Package = JT1078Serializer.Merge(package); Package = JT1078Serializer.Merge(package);
} }
H264NALUs = h264Decoder.ParseNALU(Package); H264NALUs = h264Decoder.ParseNALU(Package);
SPSNALu = H264NALUs.FirstOrDefault(f => f.NALUHeader.NalUnitType == 7);
SPSNALu = H264NALUs.FirstOrDefault(f => f.NALUHeader.NalUnitType == NalUnitType.SPS);
SPSNALu.RawData = h264Decoder.DiscardEmulationPreventionBytes(SPSNALu.RawData); SPSNALu.RawData = h264Decoder.DiscardEmulationPreventionBytes(SPSNALu.RawData);
} }




+ 5
- 5
src/JT1078.Protocol.Test/H264/H264DecoderTest.cs View File

@@ -26,7 +26,7 @@ namespace JT1078.Protocol.Test.H264
var nalu = nalus[0]; var nalu = nalus[0];
Assert.Equal(0, nalu.NALUHeader.ForbiddenZeroBit); Assert.Equal(0, nalu.NALUHeader.ForbiddenZeroBit);
Assert.Equal(3, nalu.NALUHeader.NalRefIdc); Assert.Equal(3, nalu.NALUHeader.NalRefIdc);
Assert.Equal(1, nalu.NALUHeader.NalUnitType);
Assert.Equal(NalUnitType.SLICE, nalu.NALUHeader.NalUnitType);
} }


[Fact] [Fact]
@@ -48,7 +48,7 @@ namespace JT1078.Protocol.Test.H264
Assert.Equal(4, nalus.Count); Assert.Equal(4, nalus.Count);


//SPS -> 7 //SPS -> 7
var spsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 7);
var spsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == NalUnitType.SPS);
Assert.NotNull(spsNALU); Assert.NotNull(spsNALU);
spsNALU.RawData = decoder.DiscardEmulationPreventionBytes(spsNALU.RawData); spsNALU.RawData = decoder.DiscardEmulationPreventionBytes(spsNALU.RawData);
//"Z00AFJWoWCWQ" //"Z00AFJWoWCWQ"
@@ -63,15 +63,15 @@ namespace JT1078.Protocol.Test.H264
Assert.Equal(352, spsInfo.width); Assert.Equal(352, spsInfo.width);


//PPS -> 8 //PPS -> 8
var ppsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 8);
var ppsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == NalUnitType.PPS);
Assert.NotNull(ppsNALU); Assert.NotNull(ppsNALU);


//IDR -> 5 关键帧 //IDR -> 5 关键帧
var idrNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 5);
var idrNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == NalUnitType.IDR);
Assert.NotNull(idrNALU); Assert.NotNull(idrNALU);


//SEI -> 6 //SEI -> 6
var seiNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 6);
var seiNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == NalUnitType.SEI);
Assert.NotNull(seiNALU); Assert.NotNull(seiNALU);
} }




+ 1
- 1
src/JT1078.Protocol.Test/H264/NALUHeaderTest.cs View File

@@ -14,7 +14,7 @@ namespace JT1078.Flv.Test.H264
NALUHeader header = new NALUHeader(0xc0); NALUHeader header = new NALUHeader(0xc0);
Assert.Equal(1, header.ForbiddenZeroBit); Assert.Equal(1, header.ForbiddenZeroBit);
Assert.Equal(2, header.NalRefIdc); Assert.Equal(2, header.NalRefIdc);
Assert.Equal(0, header.NalUnitType);
Assert.Equal(NalUnitType.None, header.NalUnitType);
} }
} }
} }

+ 20
- 3
src/JT1078.Protocol/H264/NALUHeader.cs View File

@@ -10,16 +10,33 @@ namespace JT1078.Protocol.H264
{ {
ForbiddenZeroBit = (value & 0x80) >> 7; ForbiddenZeroBit = (value & 0x80) >> 7;
NalRefIdc = (value & 0x60) >> 5; NalRefIdc = (value & 0x60) >> 5;
NalUnitType = value & 0x1f;
NalUnitType = (NalUnitType)(value & 0x1f);
} }
public NALUHeader(ReadOnlySpan<byte> value) public NALUHeader(ReadOnlySpan<byte> value)
{ {
ForbiddenZeroBit = (value[0] & 0x80) >> 7; ForbiddenZeroBit = (value[0] & 0x80) >> 7;
NalRefIdc = (value[0] & 0x60) >> 5; NalRefIdc = (value[0] & 0x60) >> 5;
NalUnitType = value[0] & 0x1f;
NalUnitType = (NalUnitType)(value[0] & 0x1f);
} }
public int ForbiddenZeroBit { get; set; } public int ForbiddenZeroBit { get; set; }
public int NalRefIdc { get; set; } public int NalRefIdc { get; set; }
public int NalUnitType { get; set; }
public NalUnitType NalUnitType { get; set; }
}

public enum NalUnitType : int
{
None=0,
SLICE = 1,
DPA = 2,
DPB = 3,
DPC = 4,
IDR = 5,
SEI = 6,
SPS = 7,
PPS = 8,
AUD = 9,
EOSEQ = 10,
EOSTREAM = 11,
FILL = 12,
} }
} }

+ 3
- 1
src/JT1078.SignalR.Test/Services/ToWebSocketService.cs View File

@@ -17,6 +17,7 @@ using JT1078.Protocol;
using System.IO; using System.IO;
using JT1078.Protocol.Extensions; using JT1078.Protocol.Extensions;
using JT1078.Protocol.H264; using JT1078.Protocol.H264;
using System.Net.WebSockets;


namespace JT1078.SignalR.Test.Services namespace JT1078.SignalR.Test.Services
{ {
@@ -78,7 +79,7 @@ namespace JT1078.SignalR.Test.Services
//q.Enqueue(moov); //q.Enqueue(moov);
first.Add(moov); first.Add(moov);
q.Add(first.SelectMany(s=>s).ToArray()); q.Add(first.SelectMany(s=>s).ToArray());
List<int> filter = new List<int>() { 6,7,8};
List<NalUnitType> filter = new List<NalUnitType>() { NalUnitType.SEI,NalUnitType.SPS,NalUnitType.PPS};
foreach (var package in packages) foreach (var package in packages)
{ {
List<byte[]> other = new List<byte[]>(); List<byte[]> other = new List<byte[]>();
@@ -97,6 +98,7 @@ namespace JT1078.SignalR.Test.Services
} }
} }



public Dictionary<string,int> flag = new Dictionary<string, int>(); public Dictionary<string,int> flag = new Dictionary<string, int>();


protected async override Task ExecuteAsync(CancellationToken stoppingToken) protected async override Task ExecuteAsync(CancellationToken stoppingToken)


Loading…
Cancel
Save