@@ -117,7 +117,7 @@ namespace JT1078.AV.Benchmark | |||
{ | |||
for (var i = 0; i < N; i++) | |||
{ | |||
var buffer = fmp4Encoder.EncoderOtherVideoBox(FMp4H264NALUs); | |||
var buffer = fmp4Encoder.OtherVideoBox(FMp4H264NALUs); | |||
} | |||
} | |||
} | |||
@@ -173,10 +173,10 @@ | |||
ws.on("video", (message) => { | |||
var buff=base64ToArrayBuffer(message); | |||
//console.log(buff); | |||
//putPacket(buff); | |||
putPacket(buff); | |||
//先直接喂进去 | |||
//mvhd.duration 谷歌浏览器不会缓存 | |||
source_buffer.appendBuffer(buff); | |||
//source_buffer.appendBuffer(buff); | |||
}); | |||
ws.start().catch(err => console.error(err)); | |||
} | |||
@@ -449,12 +449,12 @@ namespace JT1078.FMp4.Test | |||
} | |||
using var fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); | |||
var ftyp = fMp4Encoder.EncoderFtypBox(); | |||
var ftyp = fMp4Encoder.FtypBox(); | |||
fileStream.Write(ftyp); | |||
var iNalus = h264Decoder.ParseNALU(packages[0]); | |||
//判断第一帧是否关键帧 | |||
var moov = fMp4Encoder.EncoderMoovBox( | |||
var moov = fMp4Encoder.VideoMoovBox( | |||
iNalus.FirstOrDefault(f => f.NALUHeader.NalUnitType == NalUnitType.SPS), | |||
iNalus.FirstOrDefault(f => f.NALUHeader.NalUnitType == NalUnitType.PPS)); | |||
fileStream.Write(moov); | |||
@@ -474,7 +474,7 @@ namespace JT1078.FMp4.Test | |||
{ | |||
if (nalus.Count > 0) | |||
{ | |||
var otherBuffer = fMp4Encoder.EncoderOtherVideoBox(nalus); | |||
var otherBuffer = fMp4Encoder.OtherVideoBox(nalus); | |||
fileStream.Write(otherBuffer); | |||
nalus.Clear(); | |||
} | |||
@@ -498,12 +498,12 @@ namespace JT1078.FMp4.Test | |||
} | |||
using var fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); | |||
var ftyp = fMp4Encoder.EncoderFtypBox(); | |||
var ftyp = fMp4Encoder.FtypBox(); | |||
fileStream.Write(ftyp); | |||
var iNalus = h264Decoder.ParseNALU(packages[0]); | |||
//判断第一帧是否关键帧 | |||
var moov = fMp4Encoder.EncoderMoovBox( | |||
var moov = fMp4Encoder.VideoMoovBox( | |||
iNalus.FirstOrDefault(f => f.NALUHeader.NalUnitType == NalUnitType.SPS), | |||
iNalus.FirstOrDefault(f => f.NALUHeader.NalUnitType == NalUnitType.PPS)); | |||
fileStream.Write(moov); | |||
@@ -516,7 +516,7 @@ namespace JT1078.FMp4.Test | |||
{ | |||
if (nalus.Count > 0) | |||
{ | |||
var otherBuffer = fMp4Encoder.EncoderOtherVideoBox(nalus); | |||
var otherBuffer = fMp4Encoder.OtherVideoBox(nalus); | |||
fileStream.Write(otherBuffer); | |||
nalus.Clear(); | |||
} | |||
@@ -525,7 +525,7 @@ namespace JT1078.FMp4.Test | |||
} | |||
if (nalus.Count > 0) | |||
{ | |||
var otherBuffer = fMp4Encoder.EncoderOtherVideoBox(nalus); | |||
var otherBuffer = fMp4Encoder.OtherVideoBox(nalus); | |||
fileStream.Write(otherBuffer); | |||
nalus.Clear(); | |||
} | |||
@@ -545,13 +545,13 @@ namespace JT1078.FMp4.Test | |||
} | |||
using var fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); | |||
var ftyp = fMp4Encoder.EncoderFtypBox(); | |||
var ftyp = fMp4Encoder.FtypBox(); | |||
fileStream.Write(ftyp); | |||
var iPackage = packages.FirstOrDefault(f => f.Label3.DataType == JT1078DataType.视频I帧); | |||
var iNalus = h264Decoder.ParseNALU(iPackage); | |||
//判断第一帧是否关键帧 | |||
var moov = fMp4Encoder.EncoderMoovBox( | |||
var moov = fMp4Encoder.VideoMoovBox( | |||
iNalus.FirstOrDefault(f => f.NALUHeader.NalUnitType == NalUnitType.SPS), | |||
iNalus.FirstOrDefault(f => f.NALUHeader.NalUnitType == NalUnitType.PPS)); | |||
fileStream.Write(moov); | |||
@@ -564,7 +564,8 @@ namespace JT1078.FMp4.Test | |||
{ | |||
if (nalus.Count > 0) | |||
{ | |||
var otherBuffer = fMp4Encoder.EncoderOtherVideoBox(nalus); | |||
fileStream.Write(fMp4Encoder.StypBox()); | |||
var otherBuffer = fMp4Encoder.OtherVideoBox(nalus); | |||
fileStream.Write(otherBuffer); | |||
nalus.Clear(); | |||
} | |||
@@ -573,7 +574,7 @@ namespace JT1078.FMp4.Test | |||
} | |||
if (nalus.Count > 0) | |||
{ | |||
var otherBuffer = fMp4Encoder.EncoderOtherVideoBox(nalus); | |||
var otherBuffer = fMp4Encoder.OtherVideoBox(nalus); | |||
fileStream.Write(otherBuffer); | |||
nalus.Clear(); | |||
} | |||
@@ -32,10 +32,11 @@ namespace JT1078.FMp4 | |||
{ | |||
Dictionary<string, TrackInfo> TrackInfos; | |||
const uint DefaultSampleDuration = 48000u; | |||
const uint DefaultSampleDuration = 40u; | |||
const uint DefaultSampleFlags = 0x1010000; | |||
const uint FirstSampleFlags = 33554432; | |||
const uint TfhdFlags = 0x2003a; | |||
//const uint TrunFlags = 0x205; | |||
const uint TrunFlags = 0x205; | |||
const uint SampleDescriptionIndex = 1; | |||
const uint TrackID = 1; | |||
@@ -52,7 +53,7 @@ namespace JT1078.FMp4 | |||
/// 编码ftyp盒子 | |||
/// </summary> | |||
/// <returns></returns> | |||
public byte[] EncoderFtypBox() | |||
public byte[] FtypBox() | |||
{ | |||
byte[] buffer = FMp4ArrayPool.Rent(1024); | |||
FMp4MessagePackWriter writer = new FMp4MessagePackWriter(buffer); | |||
@@ -82,7 +83,7 @@ namespace JT1078.FMp4 | |||
/// 编码moov盒子 | |||
/// </summary> | |||
/// <returns></returns> | |||
public byte[] EncoderMoovBox(in H264NALU sps, in H264NALU pps) | |||
public byte[] VideoMoovBox(in H264NALU sps, in H264NALU pps) | |||
{ | |||
byte[] buffer = FMp4ArrayPool.Rent(sps.RawData.Length + pps.RawData.Length + 1024); | |||
FMp4MessagePackWriter writer = new FMp4MessagePackWriter(buffer); | |||
@@ -111,7 +112,8 @@ namespace JT1078.FMp4 | |||
movieBox.TrackBox.MediaBox.MediaHeaderBox = new MediaHeaderBox(); | |||
movieBox.TrackBox.MediaBox.MediaHeaderBox.CreationTime = 0; | |||
movieBox.TrackBox.MediaBox.MediaHeaderBox.ModificationTime = 0; | |||
movieBox.TrackBox.MediaBox.MediaHeaderBox.Timescale = 1200000; | |||
//movieBox.TrackBox.MediaBox.MediaHeaderBox.Timescale = 1200000; | |||
movieBox.TrackBox.MediaBox.MediaHeaderBox.Timescale = 1000; | |||
movieBox.TrackBox.MediaBox.MediaHeaderBox.Duration = 0; | |||
movieBox.TrackBox.MediaBox.HandlerBox = new HandlerBox(); | |||
movieBox.TrackBox.MediaBox.HandlerBox.HandlerType = HandlerType.vide; | |||
@@ -160,11 +162,40 @@ namespace JT1078.FMp4 | |||
} | |||
} | |||
/// <summary> | |||
/// styp | |||
/// </summary> | |||
/// <returns></returns> | |||
public byte[] StypBox() | |||
{ | |||
byte[] buffer = FMp4ArrayPool.Rent(1024); | |||
FMp4MessagePackWriter writer = new FMp4MessagePackWriter(buffer); | |||
try | |||
{ | |||
SegmentTypeBox stypTypeBox = new SegmentTypeBox(); | |||
stypTypeBox.MajorBrand = "isom"; | |||
stypTypeBox.MinorVersion = "\0\0\0\0"; | |||
stypTypeBox.CompatibleBrands.Add("isom"); | |||
stypTypeBox.CompatibleBrands.Add("mp42"); | |||
stypTypeBox.CompatibleBrands.Add("msdh"); | |||
stypTypeBox.CompatibleBrands.Add("msix"); | |||
stypTypeBox.CompatibleBrands.Add("iso5"); | |||
stypTypeBox.CompatibleBrands.Add("iso6"); | |||
stypTypeBox.ToBuffer(ref writer); | |||
var data = writer.FlushAndGetArray(); | |||
return data; | |||
} | |||
finally | |||
{ | |||
FMp4ArrayPool.Return(buffer); | |||
} | |||
} | |||
/// <summary> | |||
/// 编码其他视频数据盒子 | |||
/// </summary> | |||
/// <returns></returns> | |||
public byte[] EncoderOtherVideoBox(in List<H264NALU> nalus) | |||
public byte[] OtherVideoBox(in List<H264NALU> nalus) | |||
{ | |||
byte[] buffer = FMp4ArrayPool.Rent(nalus.Sum(s => s.RawData.Length + s.StartCodePrefix.Length) + 4096); | |||
FMp4MessagePackWriter writer = new FMp4MessagePackWriter(buffer); | |||
@@ -193,12 +224,14 @@ namespace JT1078.FMp4 | |||
{ | |||
truns.Add(new TrackRunBox.TrackRunInfo() | |||
{ | |||
SampleDuration=40, | |||
SampleSize = iSize, | |||
}); | |||
iSize = 0; | |||
} | |||
truns.Add(new TrackRunBox.TrackRunInfo() | |||
{ | |||
SampleDuration = 40, | |||
SampleSize = (uint)(nalu.RawData.Length + nalu.StartCodePrefix.Length), | |||
}); | |||
} | |||
@@ -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>true</GeneratePackageOnBuild> | |||
<Version>1.0.0-preview4</Version> | |||
<Version>1.0.0-preview5</Version> | |||
<SignAssembly>false</SignAssembly> | |||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | |||
<PackageLicenseFile>LICENSE</PackageLicenseFile> | |||
@@ -1325,19 +1325,25 @@ | |||
</summary> | |||
</member> | |||
<member name="M:JT1078.FMp4.FMp4Encoder.EncoderFtypBox"> | |||
<member name="M:JT1078.FMp4.FMp4Encoder.FtypBox"> | |||
<summary> | |||
编码ftyp盒子 | |||
</summary> | |||
<returns></returns> | |||
</member> | |||
<member name="M:JT1078.FMp4.FMp4Encoder.EncoderMoovBox(JT1078.Protocol.H264.H264NALU@,JT1078.Protocol.H264.H264NALU@)"> | |||
<member name="M:JT1078.FMp4.FMp4Encoder.VideoMoovBox(JT1078.Protocol.H264.H264NALU@,JT1078.Protocol.H264.H264NALU@)"> | |||
<summary> | |||
编码moov盒子 | |||
</summary> | |||
<returns></returns> | |||
</member> | |||
<member name="M:JT1078.FMp4.FMp4Encoder.EncoderOtherVideoBox(System.Collections.Generic.List{JT1078.Protocol.H264.H264NALU}@)"> | |||
<member name="M:JT1078.FMp4.FMp4Encoder.StypBox"> | |||
<summary> | |||
styp | |||
</summary> | |||
<returns></returns> | |||
</member> | |||
<member name="M:JT1078.FMp4.FMp4Encoder.OtherVideoBox(System.Collections.Generic.List{JT1078.Protocol.H264.H264NALU}@)"> | |||
<summary> | |||
编码其他视频数据盒子 | |||
</summary> | |||
@@ -116,5 +116,26 @@ namespace JT1078.Protocol.Test.H264 | |||
} | |||
fileStream.Close(); | |||
} | |||
[Fact] | |||
public void ParseNALUTest5() | |||
{ | |||
string file = "jt1078_6"; | |||
var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", $"{file}.txt")); | |||
List<H264NALU> nALUs = new List<H264NALU>(); | |||
H264Decoder decoder = new H264Decoder(); | |||
foreach (var line in lines) | |||
{ | |||
var bytes = line.ToHexBytes(); | |||
JT1078Package package = JT1078Serializer.Deserialize(bytes); | |||
var packageMerge = JT1078Serializer.Merge(package); | |||
if (packageMerge != null) | |||
{ | |||
var nalus = decoder.ParseNALU(packageMerge); | |||
nALUs = nALUs.Concat(nalus).ToList(); | |||
} | |||
} | |||
var a = nALUs.Count(c => !c.Slice); | |||
} | |||
} | |||
} |
@@ -32,5 +32,8 @@ | |||
<None Include="..\..\doc\video\jt1078_5.txt" Link="H264\jt1078_5.txt"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
<None Include="..\..\doc\video\jt1078_6.txt" Link="H264\jt1078_6.txt"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
</ItemGroup> | |||
</Project> |
@@ -23,5 +23,8 @@ | |||
<None Include="..\..\doc\video\jt1078_5.txt" Link="H264\jt1078_5.txt"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
<None Include="..\..\doc\video\jt1078_6.txt" Link="H264\jt1078_6.txt"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
</ItemGroup> | |||
</Project> |
@@ -53,15 +53,19 @@ namespace JT1078.SignalR.Test.Services | |||
{ | |||
List<JT1078Package> packages = new List<JT1078Package>(); | |||
//var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "jt1078_3.txt")); | |||
var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "jt1078_5.txt")); | |||
//var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "jt1078_5.txt")); | |||
var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "jt1078_6.txt")); | |||
int mergeBodyLength = 0; | |||
foreach (var line in lines) | |||
{ | |||
var data = line.Split(','); | |||
//var data = line.Split(','); | |||
//jt1078_5 | |||
var bytes = data[1].ToHexBytes(); | |||
//var bytes = data[1].ToHexBytes(); | |||
//jt1078_3 | |||
//var bytes = data[6].ToHexBytes(); | |||
//jt1078_6 | |||
var bytes = line.ToHexBytes(); | |||
JT1078Package package = JT1078Serializer.Deserialize(bytes); | |||
mergeBodyLength += package.DataBodyLength; | |||
var packageMerge = JT1078Serializer.Merge(package); | |||
@@ -74,12 +78,12 @@ namespace JT1078.SignalR.Test.Services | |||
//var styp = fMp4Encoder.EncoderStypBox(); | |||
//first.Add(styp); | |||
//q.Enqueue(styp); | |||
var ftyp = fMp4Encoder.EncoderFtypBox(); | |||
var ftyp = fMp4Encoder.FtypBox(); | |||
//q.Enqueue(ftyp); | |||
first.Add(ftyp); | |||
var package1 = packages[0]; | |||
var nalus1 = h264Decoder.ParseNALU(package1); | |||
var moov = fMp4Encoder.EncoderMoovBox( | |||
var moov = fMp4Encoder.VideoMoovBox( | |||
nalus1.FirstOrDefault(f => f.NALUHeader.NalUnitType == NalUnitType.SPS), | |||
nalus1.FirstOrDefault(f => f.NALUHeader.NalUnitType == NalUnitType.PPS)); | |||
//q.Enqueue(moov); | |||
@@ -90,6 +94,23 @@ namespace JT1078.SignalR.Test.Services | |||
foreach (var package in packages) | |||
{ | |||
List<H264NALU> h264NALUs = h264Decoder.ParseNALU(package); | |||
//if(package.Label3.DataType== Protocol.Enums.JT1078DataType.视频I帧) | |||
//{ | |||
// if (nalus.Count > 0) | |||
// { | |||
// var otherBuffer = fMp4Encoder.OtherVideoBox(nalus); | |||
// q.Add(fMp4Encoder.StypBox().Concat(otherBuffer).ToArray()); | |||
// nalus.Clear(); | |||
// } | |||
// else | |||
// { | |||
// nalus = nalus.Concat(h264NALUs).ToList(); | |||
// } | |||
//} | |||
//else | |||
//{ | |||
// nalus = nalus.Concat(h264NALUs).ToList(); | |||
//} | |||
foreach (var nalu in h264NALUs) | |||
{ | |||
if (nalu.Slice) | |||
@@ -101,7 +122,8 @@ namespace JT1078.SignalR.Test.Services | |||
{ | |||
if (nalus.Count > 0) | |||
{ | |||
var otherBuffer = fMp4Encoder.EncoderOtherVideoBox(nalus); | |||
q.Add(fMp4Encoder.StypBox()); | |||
var otherBuffer = fMp4Encoder.OtherVideoBox(nalus); | |||
q.Add(otherBuffer); | |||
nalus.Clear(); | |||
} | |||