From 1c0c850ac29d79a4d49a850b968d3551041561c1 Mon Sep 17 00:00:00 2001
From: "SmallChi(Koike)" <564952747@qq.com>
Date: Mon, 23 Sep 2019 23:22:44 +0800
Subject: [PATCH] =?UTF-8?q?flv=E5=8C=85=E8=A3=85=E5=99=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/JT1078.Flv/Amf/Amf0.cs | 21 -------
src/JT1078.Flv/Buffers/FlvBufferWriter.cs | 24 ++++++++
src/JT1078.Flv/Enums/AVCPacketType.cs | 13 ++++
src/JT1078.Flv/Enums/AacPacketType.cs | 12 ----
src/JT1078.Flv/Enums/CodecId.cs | 2 +-
src/JT1078.Flv/Enums/FrameType.cs | 2 +-
src/JT1078.Flv/Enums/TagType.cs | 13 ++++
src/JT1078.Flv/FlvMuxer.cs | 27 ++++++++-
src/JT1078.Flv/FlvTag.cs | 18 +++++-
src/JT1078.Flv/FlvTagHeader.cs | 27 ---------
.../MessagePack/FlvMessagePackWriter.cs | 60 +++++++++++++++++++
.../MessagePack/FlvMessagePackWriter_Amf0.cs | 19 ++++++
.../FlvMessagePackWriter_Amf3.cs} | 5 +-
.../MessagePack/FlvMessagePackWriter_Flv.cs | 56 +++++++++++++++++
src/JT1078.Flv/Metadata/AvcVideoPacke.cs | 16 +++++
src/JT1078.Flv/Metadata/VideoTag.cs | 21 +++++++
16 files changed, 268 insertions(+), 68 deletions(-)
delete mode 100644 src/JT1078.Flv/Amf/Amf0.cs
create mode 100644 src/JT1078.Flv/Buffers/FlvBufferWriter.cs
create mode 100644 src/JT1078.Flv/Enums/AVCPacketType.cs
delete mode 100644 src/JT1078.Flv/Enums/AacPacketType.cs
create mode 100644 src/JT1078.Flv/Enums/TagType.cs
delete mode 100644 src/JT1078.Flv/FlvTagHeader.cs
create mode 100644 src/JT1078.Flv/MessagePack/FlvMessagePackWriter.cs
create mode 100644 src/JT1078.Flv/MessagePack/FlvMessagePackWriter_Amf0.cs
rename src/JT1078.Flv/{Amf/Amf3.cs => MessagePack/FlvMessagePackWriter_Amf3.cs} (52%)
create mode 100644 src/JT1078.Flv/MessagePack/FlvMessagePackWriter_Flv.cs
create mode 100644 src/JT1078.Flv/Metadata/AvcVideoPacke.cs
create mode 100644 src/JT1078.Flv/Metadata/VideoTag.cs
diff --git a/src/JT1078.Flv/Amf/Amf0.cs b/src/JT1078.Flv/Amf/Amf0.cs
deleted file mode 100644
index 60c4d16..0000000
--- a/src/JT1078.Flv/Amf/Amf0.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace JT1078.Flv
-{
- public static class Amf0
- {
- public readonly static byte[] Buffer;
-
- public readonly static byte[] FixedData = new byte[] { 0x6F, 0x6E, 0x4D, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61 };
- static Amf0()
- {
- Buffer = new byte[13];
- Buffer[0] = 0x02;
- Buffer[1] = 0;
- Buffer[2] = 10;
- Array.Copy(FixedData, 0, Buffer, 3, 10);
- }
- }
-}
diff --git a/src/JT1078.Flv/Buffers/FlvBufferWriter.cs b/src/JT1078.Flv/Buffers/FlvBufferWriter.cs
new file mode 100644
index 0000000..502339c
--- /dev/null
+++ b/src/JT1078.Flv/Buffers/FlvBufferWriter.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace JT1078.Flv
+{
+ ///
+ ///
+ ///
+ ref partial struct FlvBufferWriter
+ {
+ private Span _buffer;
+ public FlvBufferWriter(Span buffer)
+ {
+ _buffer = buffer;
+ WrittenCount = 0;
+ }
+ public Span Free => _buffer.Slice(WrittenCount);
+ public Span Written => _buffer.Slice(0, WrittenCount);
+ public int WrittenCount { get; private set; }
+ public void Advance(int count)
+ {
+ WrittenCount += count;
+ }
+ }
+}
diff --git a/src/JT1078.Flv/Enums/AVCPacketType.cs b/src/JT1078.Flv/Enums/AVCPacketType.cs
new file mode 100644
index 0000000..9d5b557
--- /dev/null
+++ b/src/JT1078.Flv/Enums/AVCPacketType.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT1078.Flv.Enums
+{
+ public enum AvcPacketType
+ {
+ SequenceHeader=1,
+ Raw,
+ AVCEndSequence
+ }
+}
diff --git a/src/JT1078.Flv/Enums/AacPacketType.cs b/src/JT1078.Flv/Enums/AacPacketType.cs
deleted file mode 100644
index ba928de..0000000
--- a/src/JT1078.Flv/Enums/AacPacketType.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace JT1078.Flv
-{
- public enum AacPacketType
- {
- SequenceHeader,
- Raw
- }
-}
diff --git a/src/JT1078.Flv/Enums/CodecId.cs b/src/JT1078.Flv/Enums/CodecId.cs
index 2697103..4c9893f 100644
--- a/src/JT1078.Flv/Enums/CodecId.cs
+++ b/src/JT1078.Flv/Enums/CodecId.cs
@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Text;
-namespace JT1078.Flv
+namespace JT1078.Flv.Enums
{
public enum CodecId
{
diff --git a/src/JT1078.Flv/Enums/FrameType.cs b/src/JT1078.Flv/Enums/FrameType.cs
index a4cdd1b..4913d15 100644
--- a/src/JT1078.Flv/Enums/FrameType.cs
+++ b/src/JT1078.Flv/Enums/FrameType.cs
@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Text;
-namespace JT1078.Flv
+namespace JT1078.Flv.Enums
{
public enum FrameType
{
diff --git a/src/JT1078.Flv/Enums/TagType.cs b/src/JT1078.Flv/Enums/TagType.cs
new file mode 100644
index 0000000..d35626e
--- /dev/null
+++ b/src/JT1078.Flv/Enums/TagType.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT1078.Flv.Enums
+{
+ public enum TagType:byte
+ {
+ Audio= 0x08,
+ Video= 0x09,
+ ScriptData= 0x12,
+ }
+}
diff --git a/src/JT1078.Flv/FlvMuxer.cs b/src/JT1078.Flv/FlvMuxer.cs
index 034a9a0..a9b0589 100644
--- a/src/JT1078.Flv/FlvMuxer.cs
+++ b/src/JT1078.Flv/FlvMuxer.cs
@@ -1,4 +1,5 @@
-using System;
+using JT1078.Flv.MessagePack;
+using System;
using System.Collections.Generic;
using System.Text;
@@ -7,9 +8,29 @@ namespace JT1078.Flv
public class FlvMuxer
{
private readonly FlvHeader VideoFlvHeader = new FlvHeader(true, false);
- public void FlvVideoMuxer()
+ public byte[] FlvFirstFrame()
{
-
+ byte[] buffer = FlvArrayPool.Rent(10240);
+ try
+ {
+ FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
+ //flv header
+ flvMessagePackWriter.WriteArray(VideoFlvHeader.ToArray());
+ //flv body
+ //flv body PreviousTagSize
+ flvMessagePackWriter.WriteUInt32(0);
+ //flv body tag
+
+ //flv body tag header
+
+ //flv body tag body
+
+ return flvMessagePackWriter.FlushAndGetArray();
+ }
+ finally
+ {
+ FlvArrayPool.Return(buffer);
+ }
}
}
}
diff --git a/src/JT1078.Flv/FlvTag.cs b/src/JT1078.Flv/FlvTag.cs
index 64ad666..e16d8ce 100644
--- a/src/JT1078.Flv/FlvTag.cs
+++ b/src/JT1078.Flv/FlvTag.cs
@@ -2,7 +2,23 @@
{
public class FlvTag
{
- public FlvTagHeader TagHeader { get; set; }
+ public byte Type { get; set; }
+ ///
+ /// Tag Data部分大小
+ /// 3个字节
+ ///
+ public uint DataSize { get; set; }
+ ///
+ /// Tag时间戳
+ /// 3个字节
+ ///
+ public uint Timestamp { get; set; } = 0;
+ public byte TimestampExt { get; set; } = 0;
+ ///
+ /// stream id 总是0
+ /// 3个字节
+ ///
+ public uint StreamId { get; set; } = 0;
///
/// 根据tag类型
///
diff --git a/src/JT1078.Flv/FlvTagHeader.cs b/src/JT1078.Flv/FlvTagHeader.cs
deleted file mode 100644
index d298727..0000000
--- a/src/JT1078.Flv/FlvTagHeader.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace JT1078.Flv
-{
- public class FlvTagHeader
- {
- public byte Type { get; set; }
- ///
- /// Tag Data部分大小
- /// 3个字节
- ///
- public uint DataSize { get; set; }
- ///
- /// Tag时间戳
- /// 3个字节
- ///
- public uint Timestamp { get; set; }
- public byte TimestampExt { get; set; } = 0;
- ///
- /// stream id 总是0
- /// 3个字节
- ///
- public uint StreamId { get; set; } = 0;
- }
-}
diff --git a/src/JT1078.Flv/MessagePack/FlvMessagePackWriter.cs b/src/JT1078.Flv/MessagePack/FlvMessagePackWriter.cs
new file mode 100644
index 0000000..72a6410
--- /dev/null
+++ b/src/JT1078.Flv/MessagePack/FlvMessagePackWriter.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Buffers.Binary;
+
+namespace JT1078.Flv.MessagePack
+{
+ ref partial struct FlvMessagePackWriter
+ {
+ private FlvBufferWriter writer;
+ public FlvMessagePackWriter(Span buffer)
+ {
+ this.writer = new FlvBufferWriter(buffer);
+ }
+ public byte[] FlushAndGetArray()
+ {
+ return writer.Written.ToArray();
+ }
+ public void WriteByte(byte value)
+ {
+ var span = writer.Free;
+ span[0] = value;
+ writer.Advance(1);
+ }
+ public void WriteUInt16(ushort value)
+ {
+ BinaryPrimitives.WriteUInt16BigEndian(writer.Free, value);
+ writer.Advance(2);
+ }
+ public void WriteInt32(int value)
+ {
+ BinaryPrimitives.WriteInt32BigEndian(writer.Free, value);
+ writer.Advance(4);
+ }
+ public void WriteUInt64(ulong value)
+ {
+ BinaryPrimitives.WriteUInt64BigEndian(writer.Free, value);
+ writer.Advance(8);
+ }
+ public void WriteUInt32(uint value)
+ {
+ BinaryPrimitives.WriteUInt32BigEndian(writer.Free, value);
+ writer.Advance(4);
+ }
+ public void WriteArray(ReadOnlySpan src)
+ {
+ src.CopyTo(writer.Free);
+ writer.Advance(src.Length);
+ }
+ public void Skip(int count, out int position)
+ {
+ position = writer.WrittenCount;
+ byte[] tmp = new byte[count];
+ tmp.CopyTo(writer.Free);
+ writer.Advance(count);
+ }
+ public int GetCurrentPosition()
+ {
+ return writer.WrittenCount;
+ }
+ }
+}
diff --git a/src/JT1078.Flv/MessagePack/FlvMessagePackWriter_Amf0.cs b/src/JT1078.Flv/MessagePack/FlvMessagePackWriter_Amf0.cs
new file mode 100644
index 0000000..b942c05
--- /dev/null
+++ b/src/JT1078.Flv/MessagePack/FlvMessagePackWriter_Amf0.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT1078.Flv.MessagePack
+{
+ ref partial struct FlvMessagePackWriter
+ {
+ private readonly static byte[] FixedAmf0Data = new byte[] { 0x6F, 0x6E, 0x4D, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61 };
+ public void WriteAmf0()
+ {
+ var span = writer.Free;
+ span[0] = 0x02;
+ span[1] = 0;
+ span[2] = 10;
+ FixedAmf0Data.CopyTo(span.Slice(3));
+ }
+ }
+}
diff --git a/src/JT1078.Flv/Amf/Amf3.cs b/src/JT1078.Flv/MessagePack/FlvMessagePackWriter_Amf3.cs
similarity index 52%
rename from src/JT1078.Flv/Amf/Amf3.cs
rename to src/JT1078.Flv/MessagePack/FlvMessagePackWriter_Amf3.cs
index 4d22c65..bed39b2 100644
--- a/src/JT1078.Flv/Amf/Amf3.cs
+++ b/src/JT1078.Flv/MessagePack/FlvMessagePackWriter_Amf3.cs
@@ -2,10 +2,11 @@
using System.Collections.Generic;
using System.Text;
-namespace JT1078.Flv
+namespace JT1078.Flv.MessagePack
{
- public static class Amf3
+ ref partial struct FlvMessagePackWriter
{
+
}
}
diff --git a/src/JT1078.Flv/MessagePack/FlvMessagePackWriter_Flv.cs b/src/JT1078.Flv/MessagePack/FlvMessagePackWriter_Flv.cs
new file mode 100644
index 0000000..8f74492
--- /dev/null
+++ b/src/JT1078.Flv/MessagePack/FlvMessagePackWriter_Flv.cs
@@ -0,0 +1,56 @@
+using JT1078.Flv.Enums;
+using System;
+using System.Buffers.Binary;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT1078.Flv.MessagePack
+{
+ ref partial struct FlvMessagePackWriter
+ {
+ public void WriteFlvBody(FlvBody body)
+ {
+ WriteUInt32(body.PreviousTagSize);
+ if (body.Tag != null)
+ {
+ WriteFlvTag(body.Tag);
+ }
+ }
+
+ public void WriteFlvTag(FlvTag tag)
+ {
+ WriteByte(tag.Type);
+ Skip(3, out int DataSizePosition);
+ WriteUInt24(tag.Timestamp);
+ WriteByte(tag.TimestampExt);
+ WriteUInt24(tag.StreamId);
+ switch ((TagType)tag.Type)
+ {
+ case TagType.Video:
+
+ break;
+ case TagType.ScriptData:
+
+ //flv Amf0
+ WriteAmf0();
+ //flv Amf3
+ break;
+ case TagType.Audio:
+ break;
+ }
+ WriteInt32Return(GetCurrentPosition() - DataSizePosition - 3, DataSizePosition);
+ }
+
+ public void WriteUInt24(uint value)
+ {
+ BinaryPrimitives.WriteUInt32BigEndian(writer.Free, value);
+ writer.Advance(3);
+ }
+
+ public void WriteInt32Return(int value, int position)
+ {
+ BinaryPrimitives.WriteInt32BigEndian(writer.Written.Slice(position, 3), value);
+ }
+
+ }
+}
diff --git a/src/JT1078.Flv/Metadata/AvcVideoPacke.cs b/src/JT1078.Flv/Metadata/AvcVideoPacke.cs
new file mode 100644
index 0000000..415e521
--- /dev/null
+++ b/src/JT1078.Flv/Metadata/AvcVideoPacke.cs
@@ -0,0 +1,16 @@
+using JT1078.Flv.Enums;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT1078.Flv.Metadata
+{
+ public class AvcVideoPacke
+ {
+ public AvcPacketType AvcPacketType { get; set; }
+
+ public uint CompositionTime { get; set; }
+
+ public byte[] Data { get; set; }
+ }
+}
diff --git a/src/JT1078.Flv/Metadata/VideoTag.cs b/src/JT1078.Flv/Metadata/VideoTag.cs
new file mode 100644
index 0000000..2d45d39
--- /dev/null
+++ b/src/JT1078.Flv/Metadata/VideoTag.cs
@@ -0,0 +1,21 @@
+using JT1078.Flv.Enums;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT1078.Flv.Metadata
+{
+ public class VideoTag
+ {
+ ///
+ /// 1: keyframe(for AVC, a seekable frame) —— 即H.264的IDR帧;
+ /// 2: inter frame(for AVC, a non- seekable frame) —— H.264的普通I帧;
+ ///
+ public FrameType FrameType { get; set; }
+ ///
+ /// 当 CodecID 为 7 时,VideoData 为 AVCVIDEOPACKE,也即 H.264媒体数据
+ ///
+ public CodecId CodecId { get; set; }
+ public byte[] VideoData { get; set; }
+ }
+}