Quellcode durchsuchen

将1078转fmp4_17

ff可播放,vlc可播放,MSE可播放、浏览器可播放
master
SmallChi(Koike) vor 4 Jahren
Ursprung
Commit
fc6d0d8b52
4 geänderte Dateien mit 140 neuen und 56 gelöschten Zeilen
  1. +1
    -1
      doc/ffmpeginfo.txt
  2. +50
    -5
      src/JT1078.FMp4.Test/JT1078ToFMp4Box_Test.cs
  3. +83
    -50
      src/JT1078.FMp4/FMp4Encoder.cs
  4. +6
    -0
      src/JT1078.FMp4/JT1078.FMp4.xml

+ 1
- 1
doc/ffmpeginfo.txt Datei anzeigen

@@ -1,6 +1,6 @@
ffmpeg -i demo.mp4 -c copy -f flv -vcodec h264 -acodec aac demo_flv.flv

./ffmpeg -i JT1078_3.h264 -r 25 -c copy -f flv "D:\JT1078_3.flv"
ffmpeg -i JT1078_3.h264 -c copy -f flv JT1078_3.flv

ffmpeg -f dshow -i video="USB2.0 PC CAMERA" -t 60 -c copy -f h264 -vcodec h264 ipc.264



+ 50
- 5
src/JT1078.FMp4.Test/JT1078ToFMp4Box_Test.cs Datei anzeigen

@@ -444,20 +444,18 @@ namespace JT1078.FMp4.Test
{
File.Delete(filepath);
}

using var fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write);
var ftyp = fMp4Encoder.EncoderFtypBox();
fileStream.Write(ftyp);
List<NalUnitType> filter = new List<NalUnitType>() {
NalUnitType.SPS,
NalUnitType.PPS,
NalUnitType.AUD
};

var iNalus = h264Decoder.ParseNALU(packages[0]);
//判断第一帧是否关键帧
var moov = fMp4Encoder.EncoderMoovBox(
iNalus.FirstOrDefault(f => f.NALUHeader.NalUnitType == NalUnitType.SPS),
iNalus.FirstOrDefault(f => f.NALUHeader.NalUnitType == NalUnitType.PPS));
fileStream.Write(moov);

List<H264NALU> nalus = new List<H264NALU>();
foreach (var package in packages)
{
@@ -482,6 +480,53 @@ namespace JT1078.FMp4.Test
}
}
fileStream.Close();
}

[Fact]
public void Test5()
{
FMp4Encoder fMp4Encoder = new FMp4Encoder();
H264Decoder h264Decoder = new H264Decoder();
var packages = ParseNALUTests();
var filepath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_6.mp4");
if (File.Exists(filepath))
{
File.Delete(filepath);
}
using var fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write);

var ftyp = fMp4Encoder.EncoderFtypBox();
fileStream.Write(ftyp);

var iNalus = h264Decoder.ParseNALU(packages[0]);
//判断第一帧是否关键帧
var moov = fMp4Encoder.EncoderMoovBox(
iNalus.FirstOrDefault(f => f.NALUHeader.NalUnitType == NalUnitType.SPS),
iNalus.FirstOrDefault(f => f.NALUHeader.NalUnitType == NalUnitType.PPS));
fileStream.Write(moov);

List<H264NALU> nalus = new List<H264NALU>();
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.EncoderOtherVideoBox(nalus);
fileStream.Write(otherBuffer);
nalus.Clear();
}
}
nalus = nalus.Concat(h264NALUs).ToList();
}
if (nalus.Count > 0)
{
var otherBuffer = fMp4Encoder.EncoderOtherVideoBox(nalus);
fileStream.Write(otherBuffer);
nalus.Clear();
}
fileStream.Close();
}

[Fact]


+ 83
- 50
src/JT1078.FMp4/FMp4Encoder.cs Datei anzeigen

@@ -41,21 +41,13 @@ namespace JT1078.FMp4
try
{
//ftyp
//FileTypeBox fileTypeBox = new FileTypeBox();
//fileTypeBox.MajorBrand = "isom";
//fileTypeBox.MinorVersion = "\0\0\u0002\0";
//fileTypeBox.CompatibleBrands.Add("isom");
//fileTypeBox.CompatibleBrands.Add("iso2");
//fileTypeBox.CompatibleBrands.Add("avc1");
//fileTypeBox.CompatibleBrands.Add("mp41");
//fileTypeBox.CompatibleBrands.Add("iso5");
FileTypeBox fileTypeBox = new FileTypeBox();
fileTypeBox.MajorBrand = "msdh";
fileTypeBox.MinorVersion = "\0\0\0\0";
fileTypeBox.MajorBrand = "isom";
fileTypeBox.MinorVersion = "\0\0\u0002\0";
fileTypeBox.CompatibleBrands.Add("isom");
fileTypeBox.CompatibleBrands.Add("mp42");
fileTypeBox.CompatibleBrands.Add("msdh");
fileTypeBox.CompatibleBrands.Add("msix");
fileTypeBox.CompatibleBrands.Add("iso2");
fileTypeBox.CompatibleBrands.Add("avc1");
fileTypeBox.CompatibleBrands.Add("mp41");
fileTypeBox.CompatibleBrands.Add("iso5");
fileTypeBox.CompatibleBrands.Add("iso6");
fileTypeBox.ToBuffer(ref writer);
@@ -152,8 +144,6 @@ namespace JT1078.FMp4

uint sn = 1;

public ulong timestampCache = 0;

/// <summary>
/// 编码其他视频数据盒子
/// </summary>
@@ -164,41 +154,90 @@ namespace JT1078.FMp4
FMp4MessagePackWriter writer = new FMp4MessagePackWriter(buffer);
try
{
SegmentTypeBox stypTypeBox = new SegmentTypeBox();
stypTypeBox.MajorBrand = "msdh";
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 truns = new List<TrackRunBox.TrackRunInfo>();
List<byte[]> rawdatas = new List<byte[]>();
uint iSize = 0;
ulong lastTimestamp = 0;
for (var i=0; i<nalus.Count;i++ )
{
var nalu = nalus[i];
rawdatas.Add(nalu.RawData);
if (nalu.DataType == Protocol.Enums.JT1078DataType.视频I帧)
{
iSize += (uint)(nalu.RawData.Length + nalu.StartCodePrefix.Length);
}
else
{
if (iSize > 0)
{
truns.Add(new TrackRunBox.TrackRunInfo()
{
SampleSize = iSize,
});
iSize = 0;
}
truns.Add(new TrackRunBox.TrackRunInfo()
{
SampleSize = (uint)(nalu.RawData.Length + nalu.StartCodePrefix.Length),
});
}
if(i== (nalus.Count - 1))
{
lastTimestamp = nalu.Timestamp;
}
}

var movieFragmentBox = new MovieFragmentBox();
movieFragmentBox.MovieFragmentHeaderBox = new MovieFragmentHeaderBox();
//todo:SequenceNumber
movieFragmentBox.MovieFragmentHeaderBox.SequenceNumber = sn++;
movieFragmentBox.TrackFragmentBox = new TrackFragmentBox();
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox = new TrackFragmentHeaderBox(0x2003a);
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.TrackID = 1;
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.SampleDescriptionIndex = 1;
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleDuration = 48000;
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleSize = truns[0].SampleSize;
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleFlags = 0x1010000;
movieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox = new TrackFragmentBaseMediaDecodeTimeBox();
movieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox.BaseMediaDecodeTime = lastTimestamp * 1000;
//trun
movieFragmentBox.TrackFragmentBox.TrackRunBox = new TrackRunBox(flags: 0x205);
movieFragmentBox.TrackFragmentBox.TrackRunBox.FirstSampleFlags = 33554432;
movieFragmentBox.TrackFragmentBox.TrackRunBox.TrackRunInfos = truns;
movieFragmentBox.ToBuffer(ref writer);
var mediaDataBox = new MediaDataBox();
mediaDataBox.Data = rawdatas;
mediaDataBox.ToBuffer(ref writer);

var firstNalu = nalus[0];
var lastNalu = nalus[nalus.Count - 1];
uint interval = (uint)(lastNalu.Timestamp - firstNalu.Timestamp);
var data = writer.FlushAndGetArray();
return data;
}
finally
{
FMp4ArrayPool.Return(buffer);
}
}

/// <summary>
/// 编码其他视频数据盒子
/// </summary>
/// <returns></returns>
public byte[] EncoderOtherVideoBox(List<H264NALU> nalus,List<byte[]>samples, List<uint> sampleSizes,uint firstSize,ulong lastTimestamp)
{
byte[] buffer = FMp4ArrayPool.Rent(nalus.Sum(s => s.RawData.Length + s.StartCodePrefix.Length) + 4096);
FMp4MessagePackWriter writer = new FMp4MessagePackWriter(buffer);
try
{
var lastNalu = nalus.Last();
int iSize = nalus.Where(w => w.DataType == Protocol.Enums.JT1078DataType.视频I帧)
.Sum(s => s.RawData.Length + s.StartCodePrefix.Length);

List<int> sizes = new List<int>();
sizes.Add(iSize);
sizes = sizes.Concat(nalus.Where(w => w.DataType != Protocol.Enums.JT1078DataType.视频I帧)
.Select(s => s.RawData.Length + s.StartCodePrefix.Length).ToList())
.ToList();
SegmentIndexBox segmentIndexBox = new SegmentIndexBox(1);
segmentIndexBox.ReferenceID = 1;
segmentIndexBox.EarliestPresentationTime = timestampCache;
segmentIndexBox.SegmentIndexs = new List<SegmentIndexBox.SegmentIndex>()
{
new SegmentIndexBox.SegmentIndex
{
SubsegmentDuration=interval
}
};
segmentIndexBox.ToBuffer(ref writer);

var current1 = writer.GetCurrentPosition();

var movieFragmentBox = new MovieFragmentBox();
movieFragmentBox.MovieFragmentHeaderBox = new MovieFragmentHeaderBox();
@@ -208,10 +247,10 @@ namespace JT1078.FMp4
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.TrackID = 1;
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.SampleDescriptionIndex = 1;
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleDuration = 48000;
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleSize = (uint)iSize;
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleSize = firstSize;
movieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleFlags = 0x1010000;
movieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox = new TrackFragmentBaseMediaDecodeTimeBox();
movieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox.BaseMediaDecodeTime = timestampCache;
movieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox.BaseMediaDecodeTime = lastTimestamp * 1000;

//trun
movieFragmentBox.TrackFragmentBox.TrackRunBox = new TrackRunBox(flags: 0x205);
@@ -227,17 +266,11 @@ namespace JT1078.FMp4
}

movieFragmentBox.ToBuffer(ref writer);
timestampCache += (uint)(sizes.Count * 48000);

var mediaDataBox = new MediaDataBox();
mediaDataBox.Data = nalus.Select(s => s.RawData).ToList();
mediaDataBox.ToBuffer(ref writer);

var current2 = writer.GetCurrentPosition();
foreach(var postion in segmentIndexBox.ReferencedSizePositions)
{
writer.WriteUInt32Return((uint)(current2 - current1), postion);
}
var data = writer.FlushAndGetArray();
return data;
}


+ 6
- 0
src/JT1078.FMp4/JT1078.FMp4.xml Datei anzeigen

@@ -1338,6 +1338,12 @@
</summary>
<returns></returns>
</member>
<member name="M:JT1078.FMp4.FMp4Encoder.EncoderOtherVideoBox(System.Collections.Generic.List{JT1078.Protocol.H264.H264NALU},System.Collections.Generic.List{System.Byte[]},System.Collections.Generic.List{System.UInt32},System.UInt32,System.UInt64)">
<summary>
编码其他视频数据盒子
</summary>
<returns></returns>
</member>
<member name="P:JT1078.FMp4.FullBox.Version">
<summary>
unsigned int(8)


Laden…
Abbrechen
Speichern