Browse Source

修改flv的包装(目前已经可以正常播放视频)

tags/v1.1.0
smallchi 5 years ago
parent
commit
6c00fe7ef1
10 changed files with 138 additions and 44 deletions
  1. +1
    -0
      .gitignore
  2. +3
    -1
      doc/ffmpeginfo.txt
  3. +59
    -3
      src/JT1078.Flv.Test/FlvEncoderTest.cs
  4. BIN
      src/JT1078.Flv.Test/H264/JT1078_4.rar
  5. +2
    -2
      src/JT1078.Flv.Test/H264/index.html
  6. +4
    -0
      src/JT1078.Flv.Test/JT1078.Flv.Test.csproj
  7. +50
    -35
      src/JT1078.Flv/FlvEncoder.cs
  8. +16
    -2
      src/JT1078.Flv/MessagePack/FlvMessagePackWriter_Flv.cs
  9. +2
    -0
      src/JT1078.Flv/Metadata/AvcVideoPacke.cs
  10. +1
    -1
      src/JT808.Protocol.Extensions.WebApiTest/Program.cs

+ 1
- 0
.gitignore View File

@@ -329,3 +329,4 @@ ASALocalRun/
# MFractors (Xamarin productivity tool) working folder
.mfractor/
/src/JT1078.Flv.Test/H264/JT1078_3.txt
/src/JT1078.Flv.Test/H264/JT1078_4.txt

+ 3
- 1
doc/ffmpeginfo.txt View File

@@ -1,3 +1,5 @@
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 -r 25 -c copy -f flv "D:\JT1078_3.flv"

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

+ 59
- 3
src/JT1078.Flv.Test/FlvEncoderTest.cs View File

@@ -112,9 +112,9 @@ namespace JT1078.Flv.Test
{
File.Delete(filepath);
}
JT1078Package Package = null;
foreach (var line in lines)
{
var data = line.Split(',');
@@ -124,7 +124,7 @@ namespace JT1078.Flv.Test
if (Package != null)
{
var tmp = decoder.ParseNALU(Package);
if(tmp!=null && tmp.Count > 0)
if (tmp != null && tmp.Count > 0)
{
h264NALULs = h264NALULs.Concat(tmp).ToList();
}
@@ -144,7 +144,63 @@ namespace JT1078.Flv.Test
}
catch (Exception ex)
{
Assert.Throws<Exception>(()=> { });
}
finally
{
fileStream?.Close();
fileStream?.Dispose();
}
}

[Fact]
public void FlvEncoder_Test_4()
{
FileStream fileStream = null;
Flv.H264.H264Decoder decoder = new Flv.H264.H264Decoder();
List<H264NALU> h264NALULs = new List<H264NALU>();
FlvEncoder encoder = new FlvEncoder();
try
{
var filepath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_4.flv");
var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_4.txt"));
if (File.Exists(filepath))
{
File.Delete(filepath);
}

JT1078Package Package = null;

foreach (var line in lines)
{
var data = line.Split(',');
var bytes = data[6].ToHexBytes();
JT1078Package package = JT1078Serializer.Deserialize(bytes);
Package = JT1078Serializer.Merge(package);
if (Package != null)
{
var tmp = decoder.ParseNALU(Package);
if (tmp != null && tmp.Count > 0)
{
h264NALULs = h264NALULs.Concat(tmp).ToList();
}
}
}

fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write);
var totalPage = (h264NALULs.Count + 10 - 1) / 10;
for (var i = 0; i < totalPage; i++)
{
var flv2 = encoder.CreateFlvFrame(h264NALULs.Skip(i * 10).Take(10).ToList());
if (flv2.Length != 0)
{
fileStream.Write(flv2);
}
}
}
catch (Exception ex)
{
Assert.Throws<Exception>(() => { });
}
finally
{


BIN
src/JT1078.Flv.Test/H264/JT1078_4.rar View File


+ 2
- 2
src/JT1078.Flv.Test/H264/index.html View File

@@ -15,7 +15,7 @@
var player = document.getElementById('player');
var flvPlayer = flvjs.createPlayer({
type: 'flv',
url: "jt1078_1.flv"
url: "jt1078_3.flv"
});
flvPlayer.attachMediaElement(player);
flvPlayer.load();
@@ -24,7 +24,7 @@
var player2 = document.getElementById('player2');
var flvPlayer2 = flvjs.createPlayer({
type: 'flv',
url: "jt1078_3.flv"
url: "jt1078_4.flv"
});
flvPlayer2.attachMediaElement(player2);
flvPlayer2.load();


+ 4
- 0
src/JT1078.Flv.Test/JT1078.Flv.Test.csproj View File

@@ -6,6 +6,7 @@

<ItemGroup>
<None Remove="H264\JT1078_3.rar" />
<None Remove="H264\JT1078_4.rar" />
</ItemGroup>

<ItemGroup>
@@ -35,6 +36,9 @@
<None Update="H264\JT1078_3.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="H264\JT1078_4.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>

+ 50
- 35
src/JT1078.Flv/FlvEncoder.cs View File

@@ -13,7 +13,7 @@ namespace JT1078.Flv
{
public class FlvEncoder
{
private static readonly byte[] VideoFlvHeaderBuffer;
private static readonly byte[] VideoFlvHeaderBuffer;
private const uint PreviousTagSizeFixedLength = 4;
private static readonly ConcurrentDictionary<string, uint> PreviousTagSizeDict;
private static readonly ConcurrentDictionary<string, bool> FrameInitDict;
@@ -78,7 +78,7 @@ namespace JT1078.Flv
FlvArrayPool.Return(buffer);
}
}
private void CreateScriptTagFrame(ref FlvMessagePackWriter flvMessagePackWriter,int width,int height)
private void CreateScriptTagFrame(ref FlvMessagePackWriter flvMessagePackWriter, int width, int height,double frameRate = 25d)
{
//flv body PreviousTagSize awalys 0
flvMessagePackWriter.WriteUInt32(0);
@@ -106,7 +106,7 @@ namespace JT1078.Flv
});
flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_FrameRate
{
Value = 25d
Value = frameRate
});
flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_Width
{
@@ -118,7 +118,7 @@ namespace JT1078.Flv
});
flvMessagePackWriter.WriteFlvTag(flvTags);
}
private void CreateVideoTag0Frame(ref FlvMessagePackWriter flvMessagePackWriter, uint previousTagSize,AVCDecoderConfigurationRecord aVCDecoderConfigurationRecord)
private void CreateVideoTag0Frame(ref FlvMessagePackWriter flvMessagePackWriter, uint previousTagSize, AVCDecoderConfigurationRecord aVCDecoderConfigurationRecord)
{
//flv body PreviousTagSize ScriptTag
flvMessagePackWriter.WriteUInt32(previousTagSize);
@@ -138,7 +138,10 @@ namespace JT1078.Flv
flvTags.VideoTagsData.VideoData.AVCDecoderConfiguration = aVCDecoderConfigurationRecord;
flvMessagePackWriter.WriteFlvTag(flvTags);
}
private void CreateVideoTagOtherFrame(ref FlvMessagePackWriter flvMessagePackWriter, uint previousTagSize, H264NALU nALU)

public static uint LastFrameInterval = 0;

private void CreateVideoTagOtherFrame(ref FlvMessagePackWriter flvMessagePackWriter, uint previousTagSize, H264NALU nALU, H264NALU sps, H264NALU pps,H264NALU sei)
{
//flv body PreviousTagSize
flvMessagePackWriter.WriteUInt32(previousTagSize);
@@ -146,26 +149,48 @@ namespace JT1078.Flv
//flv body tag header
FlvTags flvTags = new FlvTags();
flvTags.Type = TagType.Video;
flvTags.Timestamp = nALU.LastIFrameInterval;
flvTags.TimestampExt = 0;
flvTags.StreamId = 0;
//flv body tag body
flvTags.VideoTagsData = new VideoTags();
flvTags.VideoTagsData.VideoData = new AvcVideoPacke();
flvTags.VideoTagsData.VideoData.CompositionTime = 0;
flvTags.VideoTagsData.VideoData.AvcPacketType = AvcPacketType.Raw;
flvTags.VideoTagsData.VideoData.MultiData = new List<byte[]>();
LastFrameInterval += nALU.LastFrameInterval;
flvTags.Timestamp = LastFrameInterval;

if (nALU.NALUHeader.NalUnitType == 5)
{
flvTags.VideoTagsData.FrameType = FrameType.KeyFrame;
if (sps!=null && pps != null)
{
//flvTags.VideoTagsData.VideoData.MultiData.Add(sps.RawData);
//flvTags.VideoTagsData.VideoData.MultiData.Add(pps.RawData);
flvTags.VideoTagsData.VideoData.MultiData.Add(nALU.RawData);
}
else
{
//if (sei != null)
//{
// flvTags.VideoTagsData.VideoData.MultiData.Add(sei.RawData);
//}
flvTags.VideoTagsData.VideoData.MultiData.Add(nALU.RawData);
}
}
else
{
flvTags.VideoTagsData.FrameType = FrameType.InterFrame;
//if (sei != null)
//{
// flvTags.VideoTagsData.VideoData.MultiData.Add(sei.RawData);
//}
flvTags.VideoTagsData.VideoData.MultiData.Add(nALU.RawData);
}
flvTags.VideoTagsData.VideoData = new AvcVideoPacke();
flvTags.VideoTagsData.VideoData.AvcPacketType = AvcPacketType.Raw;
flvTags.VideoTagsData.VideoData.CompositionTime = nALU.LastIFrameInterval;
flvTags.VideoTagsData.VideoData.Data = nALU.RawData;
flvMessagePackWriter.WriteFlvTag(flvTags);
}
public byte[] CreateFlvFrame(List<H264NALU> nALUs, int minimumLength = 10240)
public byte[] CreateFlvFrame(List<H264NALU> nALUs, int minimumLength = 65535)
{
byte[] buffer = FlvArrayPool.Rent(minimumLength);
try
@@ -173,39 +198,29 @@ namespace JT1078.Flv
FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
int currentMarkPosition = 0;
int nextMarkPosition = 0;
H264NALU? sps=null, pps=null;
foreach (var naln in nALUs)
H264NALU sps = nALUs.FirstOrDefault(f => f.NALUHeader.NalUnitType == 7);
H264NALU pps = nALUs.FirstOrDefault(f => f.NALUHeader.NalUnitType == 8);
H264NALU sei = nALUs.FirstOrDefault(f => f.NALUHeader.NalUnitType == 6);
if (sps!=null && pps != null)
{
string key = naln.GetKey();
if(!FrameInitDict.ContainsKey(key))
string key = sps.GetKey();
if (!FrameInitDict.ContainsKey(key))
{
if (naln.NALUHeader.NalUnitType == 7)
{
naln.RawData = H264Decoder.DiscardEmulationPreventionBytes(naln.RawData);
sps = naln;
}
else if (naln.NALUHeader.NalUnitType == 8)
{
pps = naln;
}
if (sps != null && pps != null)
{
flvMessagePackWriter.WriteArray(CreateFlvFirstFrame(sps, pps));
FrameInitDict.TryAdd(key, true);
}
else
{
continue;
}
flvMessagePackWriter.WriteArray(CreateFlvFirstFrame(sps, pps));
FrameInitDict.TryAdd(key, true);
}
}
foreach (var naln in nALUs.Where(w=> w.NALUHeader.NalUnitType != 7 && w.NALUHeader.NalUnitType != 8 && w.NALUHeader.NalUnitType != 6))
{
string key = naln.GetKey();
if (PreviousTagSizeDict.TryGetValue(key, out uint previousTagSize))
{
currentMarkPosition = flvMessagePackWriter.GetCurrentPosition();
CreateVideoTagOtherFrame(ref flvMessagePackWriter, previousTagSize, naln);
CreateVideoTagOtherFrame(ref flvMessagePackWriter, previousTagSize, naln,sps, pps, sei);
nextMarkPosition = flvMessagePackWriter.GetCurrentPosition();
uint tmpPreviousTagSize = (uint)(nextMarkPosition - currentMarkPosition - PreviousTagSizeFixedLength);
PreviousTagSizeDict.TryUpdate(key, tmpPreviousTagSize, previousTagSize);
}
}
}
return flvMessagePackWriter.FlushAndGetArray();
}


+ 16
- 2
src/JT1078.Flv/MessagePack/FlvMessagePackWriter_Flv.cs View File

@@ -87,8 +87,22 @@ namespace JT1078.Flv.MessagePack
WriteUInt24(videoPacke.CompositionTime);
//One or more NALUs
//WriteArray(new byte[] {0,0,0,1});
WriteInt32(videoPacke.Data.Length);
WriteArray(videoPacke.Data);
if (videoPacke.MultiData != null)
{
foreach(var item in videoPacke.MultiData)
{
if (item != null && item.Length > 0)
{
WriteInt32(item.Length);
WriteArray(item);
}
}
}
if (videoPacke.Data != null && videoPacke.Data.Length>0)
{
WriteInt32(videoPacke.Data.Length);
WriteArray(videoPacke.Data);
}
}
else
{


+ 2
- 0
src/JT1078.Flv/Metadata/AvcVideoPacke.cs View File

@@ -14,5 +14,7 @@ namespace JT1078.Flv.Metadata
public AVCDecoderConfigurationRecord AVCDecoderConfiguration { get; set; }

public byte[] Data { get; set; }

public List<byte[]> MultiData { get; set; }
}
}

+ 1
- 1
src/JT808.Protocol.Extensions.WebApiTest/Program.cs View File

@@ -25,7 +25,7 @@ namespace JT808.Protocol.Extensions.WebApiTest
{
c.HttpHost = new Uri("http://localhost:12828/jt808api/");
c.FormatOptions.DateTimeFormat = "yyyy-MM-dd HH:mm:ss.fff";
c.LoggerFactory = p.GetRequiredService<ILoggerFactory>();
//c.LoggerFactory = p.GetRequiredService<ILoggerFactory>();
});

IServiceProvider serviceProvider = serviceDescriptors.BuildServiceProvider();


Loading…
Cancel
Save