@@ -0,0 +1 @@ | |||
ffmpeg -i demo.mp4 -c copy -f flv -vcodec h264 -acodec aac demo_flv.flv |
@@ -0,0 +1,20 @@ | |||
<Project Sdk="Microsoft.NET.Sdk"> | |||
<PropertyGroup> | |||
<TargetFramework>netcoreapp3.0</TargetFramework> | |||
<IsPackable>false</IsPackable> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" /> | |||
<PackageReference Include="xunit" Version="2.4.0" /> | |||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" /> | |||
<PackageReference Include="coverlet.collector" Version="1.0.1" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\JT1078.Flv\JT1078.Flv.csproj" /> | |||
</ItemGroup> | |||
</Project> |
@@ -0,0 +1,29 @@ | |||
using JT1078.Flv.Metadata; | |||
using JT1078.Flv.Extensions; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using Xunit; | |||
namespace JT1078.Flv.Test.Metadata | |||
{ | |||
public class Amf3MetadataTest | |||
{ | |||
[Fact] | |||
public void Amf3Metadata_Duration_Test_1_1() | |||
{ | |||
Amf3Metadata_Duration amf3Metadata = new Amf3Metadata_Duration(); | |||
amf3Metadata.Value = 7.22100; | |||
var hex=amf3Metadata.ToBuffer().ToArray().ToHexString(); | |||
Assert.Equal("00086475726174696F6E00401CE24DD2F1A9FC", hex); | |||
} | |||
[Fact] | |||
public void Test1() | |||
{ | |||
byte[] d1 = new byte[] { 0xFC, 0xA9, 0xF1, 0xD2, 0x4D, 0xE2, 0x1c, 0x40 }; | |||
var buffer = BitConverter.GetBytes(7.22100); | |||
//flv需要倒序的 | |||
} | |||
} | |||
} |
@@ -4,9 +4,9 @@ using System.Text; | |||
namespace JT1078.Flv.Enums | |||
{ | |||
public enum AvcPacketType | |||
public enum AvcPacketType:byte | |||
{ | |||
SequenceHeader=1, | |||
SequenceHeader = 0, | |||
Raw, | |||
AVCEndSequence | |||
} | |||
@@ -0,0 +1,28 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT1078.Flv.Enums | |||
{ | |||
public enum Amf3Type : byte | |||
{ | |||
Undefined, | |||
Null, | |||
False, | |||
True, | |||
Integer, | |||
Double, | |||
String, | |||
XmlDocument, | |||
Date, | |||
Array, | |||
Object, | |||
Xml, | |||
ByteArray, | |||
VectorInt, | |||
VectorUInt, | |||
VectorDouble, | |||
VectorObject, | |||
Dictionary | |||
} | |||
} |
@@ -12,6 +12,6 @@ namespace JT1078.Flv.Enums | |||
Vp6, | |||
Vp6WithAlpha, | |||
ScreenVideo2, | |||
Avc | |||
AvcVideoPacke | |||
} | |||
} |
@@ -4,7 +4,7 @@ using System.Text; | |||
namespace JT1078.Flv.Enums | |||
{ | |||
public enum FrameType | |||
public enum FrameType:byte | |||
{ | |||
KeyFrame = 1, | |||
InterFrame, | |||
@@ -0,0 +1,19 @@ | |||
using JT1078.Flv.Metadata; | |||
using System; | |||
using System.Buffers.Binary; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Linq; | |||
namespace JT1078.Flv.Extensions | |||
{ | |||
public static class Amf3Extensions | |||
{ | |||
public static void WriteDouble(this IAmf3Metadata metadata, Span<byte> value) | |||
{ | |||
var flvBuffer = BitConverter.GetBytes((double)metadata.Value).AsSpan(); | |||
flvBuffer.Reverse(); | |||
flvBuffer.CopyTo(value); | |||
} | |||
} | |||
} |
@@ -0,0 +1,129 @@ | |||
using System; | |||
namespace JT1078.Flv.Extensions | |||
{ | |||
/// <summary> | |||
/// | |||
/// ref:"www.codeproject.com/tips/447938/high-performance-csharp-byte-array-to-hex-string-t" | |||
/// </summary> | |||
public static partial class HexExtensions | |||
{ | |||
public static string ToHexString(this byte[] source) | |||
{ | |||
return HexUtil.DoHexDump(source, 0, source.Length).ToUpper(); | |||
} | |||
public static int WriteHexStringLittle(byte[] bytes, int offset, string data, int len) | |||
{ | |||
if (data == null) data = ""; | |||
data = data.Replace(" ", ""); | |||
int startIndex = 0; | |||
if (data.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) | |||
{ | |||
startIndex = 2; | |||
} | |||
int length = len; | |||
if (length == -1) | |||
{ | |||
length = (data.Length - startIndex) / 2; | |||
} | |||
int noOfZero = length * 2 + startIndex - data.Length; | |||
if (noOfZero > 0) | |||
{ | |||
data = data.Insert(startIndex, new string('0', noOfZero)); | |||
} | |||
int byteIndex = 0; | |||
while (startIndex < data.Length && byteIndex < length) | |||
{ | |||
bytes[offset + byteIndex] = Convert.ToByte(data.Substring(startIndex, 2), 16); | |||
startIndex += 2; | |||
byteIndex++; | |||
} | |||
return length; | |||
} | |||
/// <summary> | |||
/// 16进制字符串转16进制数组 | |||
/// </summary> | |||
/// <param name="hexString"></param> | |||
/// <param name="separator"></param> | |||
/// <returns></returns> | |||
public static byte[] ToHexBytes(this string hexString) | |||
{ | |||
hexString = hexString.Replace(" ", ""); | |||
byte[] buf = new byte[hexString.Length / 2]; | |||
ReadOnlySpan<char> readOnlySpan = hexString.AsSpan(); | |||
for (int i = 0; i < hexString.Length; i++) | |||
{ | |||
if (i % 2 == 0) | |||
{ | |||
buf[i / 2] = Convert.ToByte(readOnlySpan.Slice(i, 2).ToString(), 16); | |||
} | |||
} | |||
return buf; | |||
} | |||
public static string ReadHexStringLittle(ReadOnlySpan<byte> read, ref int offset, int len) | |||
{ | |||
ReadOnlySpan<byte> source = read.Slice(offset, len); | |||
string hex = HexUtil.DoHexDump(read, offset, len); | |||
offset += len; | |||
return hex; | |||
} | |||
/// <summary> | |||
/// Copyright (c) Microsoft. All rights reserved. | |||
/// Licensed under the MIT license. See LICENSE file in the project root for full license information. | |||
/// <see cref="DotNetty.Buffers.ByteBufferUtil"/> | |||
/// </summary> | |||
} | |||
public static class HexUtil | |||
{ | |||
static readonly char[] HexdumpTable = new char[256 * 4]; | |||
static HexUtil() | |||
{ | |||
char[] digits = "0123456789ABCDEF".ToCharArray(); | |||
for (int i = 0; i < 256; i++) | |||
{ | |||
HexdumpTable[i << 1] = digits[(int)((uint)i >> 4 & 0x0F)]; | |||
HexdumpTable[(i << 1) + 1] = digits[i & 0x0F]; | |||
} | |||
} | |||
public static string DoHexDump(ReadOnlySpan<byte> buffer, int fromIndex, int length) | |||
{ | |||
if (length == 0) | |||
{ | |||
return ""; | |||
} | |||
int endIndex = fromIndex + length; | |||
var buf = new char[length << 1]; | |||
int srcIdx = fromIndex; | |||
int dstIdx = 0; | |||
for (; srcIdx < endIndex; srcIdx++, dstIdx += 2) | |||
{ | |||
Array.Copy(HexdumpTable, buffer[srcIdx] << 1, buf, dstIdx, 2); | |||
} | |||
return new string(buf); | |||
} | |||
public static string DoHexDump(byte[] array, int fromIndex, int length) | |||
{ | |||
if (length == 0) | |||
{ | |||
return ""; | |||
} | |||
int endIndex = fromIndex + length; | |||
var buf = new char[length << 1]; | |||
int srcIdx = fromIndex; | |||
int dstIdx = 0; | |||
for (; srcIdx < endIndex; srcIdx++, dstIdx += 2) | |||
{ | |||
Array.Copy(HexdumpTable, (array[srcIdx] & 0xFF) << 1, buf, dstIdx, 2); | |||
} | |||
return new string(buf); | |||
} | |||
} | |||
} |
@@ -10,6 +10,6 @@ namespace JT1078.Flv | |||
/// 前一个tag的长度 | |||
/// </summary> | |||
public uint PreviousTagSize { get; set; } | |||
public FlvTag Tag { get; set; } | |||
public FlvTags Tag { get; set; } | |||
} | |||
} |
@@ -1,8 +1,11 @@ | |||
namespace JT1078.Flv | |||
using JT1078.Flv.Enums; | |||
using JT1078.Flv.Metadata; | |||
namespace JT1078.Flv | |||
{ | |||
public class FlvTag | |||
public class FlvTags | |||
{ | |||
public byte Type { get; set; } | |||
public TagType Type { get; set; } | |||
/// <summary> | |||
/// Tag Data部分大小 | |||
/// 3个字节 | |||
@@ -22,6 +25,10 @@ | |||
/// <summary> | |||
/// 根据tag类型 | |||
/// </summary> | |||
public byte[] TagData { get; set; } | |||
public VideoTags VideoTagsData { get; set; } | |||
/// <summary> | |||
/// 根据tag类型 | |||
/// </summary> | |||
public Amf3 DataTagsData { get; set; } | |||
} | |||
} |
@@ -1,10 +1,12 @@ | |||
<Project Sdk="Microsoft.NET.Sdk"> | |||
<PropertyGroup> | |||
<TargetFramework>netstandard2.0</TargetFramework> | |||
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks> | |||
<LangVersion>8.0</LangVersion> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' "> | |||
<PackageReference Include="System.Memory" Version="4.5.3" /> | |||
</ItemGroup> | |||
</Project> |
@@ -7,13 +7,14 @@ 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() | |||
public void WriteAmf1() | |||
{ | |||
var span = writer.Free; | |||
span[0] = 0x02; | |||
span[1] = 0; | |||
span[2] = 10; | |||
FixedAmf0Data.CopyTo(span.Slice(3)); | |||
writer.Advance(13); | |||
} | |||
} | |||
} |
@@ -1,4 +1,5 @@ | |||
using System; | |||
using JT1078.Flv.Metadata; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
@@ -6,7 +7,22 @@ namespace JT1078.Flv.MessagePack | |||
{ | |||
ref partial struct FlvMessagePackWriter | |||
{ | |||
public void WriteAmf3(Amf3 amf3) | |||
{ | |||
WriteByte(amf3.DataType); | |||
if(amf3.Amf3Metadatas!=null && amf3.Amf3Metadatas.Count > 0) | |||
{ | |||
WriteInt32(amf3.Amf3Metadatas.Count); | |||
foreach(var item in amf3.Amf3Metadatas) | |||
{ | |||
//根据数据类型 | |||
WriteArray(item.ToBuffer()); | |||
} | |||
} | |||
else | |||
{ | |||
WriteInt32(0); | |||
} | |||
} | |||
} | |||
} |
@@ -1,4 +1,5 @@ | |||
using JT1078.Flv.Enums; | |||
using JT1078.Flv.Metadata; | |||
using System; | |||
using System.Buffers.Binary; | |||
using System.Collections.Generic; | |||
@@ -17,40 +18,84 @@ namespace JT1078.Flv.MessagePack | |||
} | |||
} | |||
public void WriteFlvTag(FlvTag tag) | |||
public void WriteFlvTag(FlvTags tag) | |||
{ | |||
WriteByte(tag.Type); | |||
WriteByte((byte)tag.Type); | |||
Skip(3, out int DataSizePosition); | |||
WriteUInt24(tag.Timestamp); | |||
WriteByte(tag.TimestampExt); | |||
WriteUInt24(tag.StreamId); | |||
switch ((TagType)tag.Type) | |||
switch (tag.Type) | |||
{ | |||
case TagType.Video: | |||
//VideoTag | |||
WriteVideoTags(tag.VideoTagsData); | |||
break; | |||
case TagType.ScriptData: | |||
//DataTags | |||
//flv Amf0 | |||
WriteAmf0(); | |||
WriteAmf1(); | |||
//flv Amf3 | |||
WriteAmf3(tag.DataTagsData); | |||
break; | |||
case TagType.Audio: | |||
//VIDEODATA | |||
break; | |||
} | |||
WriteInt32Return(GetCurrentPosition() - DataSizePosition - 3, DataSizePosition); | |||
WriteInt24Return(GetCurrentPosition() - DataSizePosition - 3, DataSizePosition); | |||
} | |||
public void WriteUInt24(uint value) | |||
{ | |||
BinaryPrimitives.WriteUInt32BigEndian(writer.Free, value); | |||
var span = writer.Free; | |||
span[0] = (byte)(value >> 16); | |||
span[1] = (byte)(value >> 8); | |||
span[2] = (byte)value; | |||
writer.Advance(3); | |||
} | |||
public void WriteInt32Return(int value, int position) | |||
public void WriteInt24Return(int value, int position) | |||
{ | |||
var span = writer.Written.Slice(position, 3); | |||
span[0] = (byte)(value >> 16); | |||
span[1] = (byte)(value >> 8); | |||
span[2] = (byte)value; | |||
} | |||
public void WriteVideoTags(VideoTags videoTags) | |||
{ | |||
BinaryPrimitives.WriteInt32BigEndian(writer.Written.Slice(position, 3), value); | |||
WriteByte((byte)((byte)videoTags.FrameType | (byte)videoTags.CodecId)); | |||
#warning 只处理H.264媒体数据 | |||
if (videoTags.CodecId== CodecId.AvcVideoPacke) | |||
{ | |||
WriteAvcVideoPacke(videoTags.VideoData); | |||
} | |||
} | |||
public void WriteAvcVideoPacke(AvcVideoPacke videoPacke) | |||
{ | |||
WriteByte((byte)videoPacke.AvcPacketType); | |||
if (videoPacke.AvcPacketType== AvcPacketType.SequenceHeader) | |||
{ | |||
videoPacke.CompositionTime = 0; | |||
WriteUInt24(videoPacke.CompositionTime); | |||
//AVCDecoderConfigurationRecord | |||
#warning AVCDecoderConfigurationRecord | |||
WriteArray(videoPacke.Data); | |||
} | |||
else if(videoPacke.AvcPacketType == AvcPacketType.Raw) | |||
{ | |||
WriteUInt24(videoPacke.CompositionTime); | |||
#warning One or more NALUs | |||
//One or more NALUs | |||
WriteArray(videoPacke.Data); | |||
} | |||
else | |||
{ | |||
videoPacke.CompositionTime = 0; | |||
WriteUInt24(videoPacke.CompositionTime); | |||
//Empty | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,19 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT1078.Flv.Metadata | |||
{ | |||
public class Amf3 | |||
{ | |||
/// <summary> | |||
/// AMF3数据类型 | |||
/// </summary> | |||
public byte DataType { get; set; } = 0x08; | |||
/// <summary> | |||
/// 元素个数 | |||
/// </summary> | |||
public uint Count { get; set; } | |||
public List<IAmf3Metadata> Amf3Metadatas { get; set; } | |||
} | |||
} |
@@ -0,0 +1,27 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Buffers.Binary; | |||
using JT1078.Flv.Extensions; | |||
namespace JT1078.Flv.Metadata | |||
{ | |||
public class Amf3Metadata_Duration : IAmf3Metadata | |||
{ | |||
public ushort FieldNameLength { get; set; } | |||
public string FieldName { get; set; } = "duration"; | |||
public byte DataType { get; set; } = 0x00; | |||
public object Value { get; set; } | |||
public ReadOnlySpan<byte> ToBuffer() | |||
{ | |||
Span<byte> tmp = new byte[2+8+1+8]; | |||
var b1 = Encoding.ASCII.GetBytes(FieldName); | |||
BinaryPrimitives.WriteUInt16BigEndian(tmp,(ushort)b1.Length); | |||
b1.CopyTo(tmp.Slice(2)); | |||
tmp[10] = DataType; | |||
this.WriteDouble(tmp.Slice(11)); | |||
return tmp; | |||
} | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Buffers.Binary; | |||
namespace JT1078.Flv.Metadata | |||
{ | |||
public class Amf3Metadata_FileSize : IAmf3Metadata | |||
{ | |||
public ushort FieldNameLength { get; set; } | |||
public string FieldName { get; set; } = "filesize"; | |||
public byte DataType { get; set; } = 0x00; | |||
public object Value { get; set; } | |||
public ReadOnlySpan<byte> ToBuffer() | |||
{ | |||
Span<byte> tmp = new byte[2+8+1+8]; | |||
var b1 = Encoding.ASCII.GetBytes(FieldName); | |||
BinaryPrimitives.WriteUInt16BigEndian(tmp, (ushort)b1.Length); | |||
b1.CopyTo(tmp.Slice(4)); | |||
tmp[11] = DataType; | |||
BinaryPrimitives.WriteInt64BigEndian(tmp.Slice(12), (long)Value); | |||
return tmp; | |||
} | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Buffers.Binary; | |||
namespace JT1078.Flv.Metadata | |||
{ | |||
public class Amf3Metadata_FrameRate : IAmf3Metadata | |||
{ | |||
public ushort FieldNameLength { get; set; } | |||
public string FieldName { get; set; } = "framerate"; | |||
public byte DataType { get; set; } = 0x00; | |||
public object Value { get; set; } | |||
public ReadOnlySpan<byte> ToBuffer() | |||
{ | |||
Span<byte> tmp = new byte[4+9+1+8]; | |||
var b1 = Encoding.ASCII.GetBytes(FieldName); | |||
BinaryPrimitives.WriteUInt16BigEndian(tmp, (ushort)b1.Length); | |||
b1.CopyTo(tmp.Slice(4)); | |||
tmp[11] = DataType; | |||
BinaryPrimitives.WriteInt64BigEndian(tmp.Slice(12), (long)Value); | |||
return tmp; | |||
} | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Buffers.Binary; | |||
namespace JT1078.Flv.Metadata | |||
{ | |||
public class Amf3Metadata_Height : IAmf3Metadata | |||
{ | |||
public ushort FieldNameLength { get; set; } | |||
public string FieldName { get; set; } = "height"; | |||
public byte DataType { get; set; } = 0x00; | |||
public object Value { get; set; } | |||
public ReadOnlySpan<byte> ToBuffer() | |||
{ | |||
Span<byte> tmp = new byte[4+6+1+8]; | |||
var b1 = Encoding.ASCII.GetBytes(FieldName); | |||
BinaryPrimitives.WriteUInt16BigEndian(tmp, (ushort)b1.Length); | |||
b1.CopyTo(tmp.Slice(3)); | |||
tmp[11] = DataType; | |||
BinaryPrimitives.WriteInt64BigEndian(tmp.Slice(12), (long)Value); | |||
return tmp; | |||
} | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Buffers.Binary; | |||
namespace JT1078.Flv.Metadata | |||
{ | |||
public class Amf3Metadata_VideoCodecId : IAmf3Metadata | |||
{ | |||
public ushort FieldNameLength { get; set; } | |||
public string FieldName { get; set; } = "videocodecid"; | |||
public byte DataType { get; set; } = 0x00; | |||
public object Value { get; set; } | |||
public ReadOnlySpan<byte> ToBuffer() | |||
{ | |||
Span<byte> tmp = new byte[4+12+1+8]; | |||
var b1 = Encoding.ASCII.GetBytes(FieldName); | |||
BinaryPrimitives.WriteUInt16BigEndian(tmp, (ushort)b1.Length); | |||
b1.CopyTo(tmp.Slice(4)); | |||
tmp[11] = DataType; | |||
BinaryPrimitives.WriteInt64BigEndian(tmp.Slice(12), (long)Value); | |||
return tmp; | |||
} | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Buffers.Binary; | |||
namespace JT1078.Flv.Metadata | |||
{ | |||
public class Amf3Metadata_VideoDataRate : IAmf3Metadata | |||
{ | |||
public ushort FieldNameLength { get; set; } | |||
public string FieldName { get; set; } = "videodatarate"; | |||
public byte DataType { get; set; } = 0x00; | |||
public object Value { get; set; } | |||
public ReadOnlySpan<byte> ToBuffer() | |||
{ | |||
Span<byte> tmp = new byte[4+13+1+8]; | |||
var b1 = Encoding.ASCII.GetBytes(FieldName); | |||
BinaryPrimitives.WriteUInt16BigEndian(tmp, (ushort)b1.Length); | |||
b1.CopyTo(tmp.Slice(4)); | |||
tmp[11] = DataType; | |||
BinaryPrimitives.WriteInt64BigEndian(tmp.Slice(12), (long)Value); | |||
return tmp; | |||
} | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Buffers.Binary; | |||
namespace JT1078.Flv.Metadata | |||
{ | |||
public class Amf3Metadata_Width : IAmf3Metadata | |||
{ | |||
public ushort FieldNameLength { get; set; } | |||
public string FieldName { get; set; } = "width"; | |||
public byte DataType { get; set; } = 0x00; | |||
public object Value { get; set; } | |||
public ReadOnlySpan<byte> ToBuffer() | |||
{ | |||
Span<byte> tmp = new byte[4+5+1+8]; | |||
var b1 = Encoding.ASCII.GetBytes(FieldName); | |||
BinaryPrimitives.WriteUInt16BigEndian(tmp, (ushort)b1.Length); | |||
b1.CopyTo(tmp.Slice(3)); | |||
tmp[11] = DataType; | |||
BinaryPrimitives.WriteInt64BigEndian(tmp.Slice(12), (long)Value); | |||
return tmp; | |||
} | |||
} | |||
} |
@@ -0,0 +1,15 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT1078.Flv.Metadata | |||
{ | |||
public interface IAmf3Metadata | |||
{ | |||
ushort FieldNameLength { get; set; } | |||
string FieldName { get; set; } | |||
byte DataType { get; set; } | |||
object Value { get; set; } | |||
ReadOnlySpan<byte> ToBuffer(); | |||
} | |||
} |
@@ -5,7 +5,7 @@ using System.Text; | |||
namespace JT1078.Flv.Metadata | |||
{ | |||
public class VideoTag | |||
public class VideoTags | |||
{ | |||
/// <summary> | |||
/// 1: keyframe(for AVC, a seekable frame) —— 即H.264的IDR帧; | |||
@@ -15,7 +15,7 @@ namespace JT1078.Flv.Metadata | |||
/// <summary> | |||
/// 当 CodecID 为 7 时,VideoData 为 AVCVIDEOPACKE,也即 H.264媒体数据 | |||
/// </summary> | |||
public CodecId CodecId { get; set; } | |||
public byte[] VideoData { get; set; } | |||
public CodecId CodecId { get; set; } = CodecId.AvcVideoPacke; | |||
public AvcVideoPacke VideoData { get; set; } | |||
} | |||
} |
@@ -1,8 +1,8 @@ | |||
<Project Sdk="Microsoft.NET.Sdk"> | |||
<PropertyGroup> | |||
<TargetFramework>netstandard2.0</TargetFramework> | |||
<LangVersion>7.3</LangVersion> | |||
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks> | |||
<LangVersion>8.0</LangVersion> | |||
<Copyright>Copyright 2019.</Copyright> | |||
<Authors>SmallChi(Koike)</Authors> | |||
<PackageId>JT1078</PackageId> | |||
@@ -14,16 +14,17 @@ | |||
<licenseUrl>https://github.com/SmallChi/JT1078/blob/master/LICENSE</licenseUrl> | |||
<license>https://github.com/SmallChi/JT1078/blob/master/LICENSE</license> | |||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> | |||
<Version>1.0.0</Version> | |||
<Version>1.0.1</Version> | |||
<SignAssembly>false</SignAssembly> | |||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | |||
<PackageLicenseFile>LICENSE</PackageLicenseFile> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' "> | |||
<PackageReference Include="System.Memory" Version="4.5.3" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Include="..\..\LICENSE"> | |||
<Pack>True</Pack> | |||
@@ -27,7 +27,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution | |||
EndProject | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Protocol.Extensions.WebApiTest", "JT808.Protocol.Extensions.WebApiTest\JT808.Protocol.Extensions.WebApiTest.csproj", "{9DB37370-AC73-434B-9CE2-6659321858C8}" | |||
EndProject | |||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT1078.Flv", "JT1078.Flv\JT1078.Flv.csproj", "{33E54FFC-7D91-42E5-9DC1-853738AB8980}" | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT1078.Flv", "JT1078.Flv\JT1078.Flv.csproj", "{33E54FFC-7D91-42E5-9DC1-853738AB8980}" | |||
EndProject | |||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT1078.Flv.Test", "JT1078.Flv.Test\JT1078.Flv.Test.csproj", "{D13FE092-1D11-4545-A322-9F06BCDAC0FD}" | |||
EndProject | |||
Global | |||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||
@@ -71,6 +73,10 @@ Global | |||
{33E54FFC-7D91-42E5-9DC1-853738AB8980}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{33E54FFC-7D91-42E5-9DC1-853738AB8980}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{33E54FFC-7D91-42E5-9DC1-853738AB8980}.Release|Any CPU.Build.0 = Release|Any CPU | |||
{D13FE092-1D11-4545-A322-9F06BCDAC0FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{D13FE092-1D11-4545-A322-9F06BCDAC0FD}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{D13FE092-1D11-4545-A322-9F06BCDAC0FD}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{D13FE092-1D11-4545-A322-9F06BCDAC0FD}.Release|Any CPU.Build.0 = Release|Any CPU | |||
EndGlobalSection | |||
GlobalSection(SolutionProperties) = preSolution | |||
HideSolutionNode = FALSE | |||
@@ -80,6 +86,7 @@ Global | |||
{E9FF2716-EF30-4180-879B-E8AB979ACFF3} = {0655AF84-E578-409F-AB0E-B47E0D2F6814} | |||
{9ADD82F9-E0B2-4263-8573-151F673BB33F} = {0655AF84-E578-409F-AB0E-B47E0D2F6814} | |||
{9DB37370-AC73-434B-9CE2-6659321858C8} = {0655AF84-E578-409F-AB0E-B47E0D2F6814} | |||
{D13FE092-1D11-4545-A322-9F06BCDAC0FD} = {0655AF84-E578-409F-AB0E-B47E0D2F6814} | |||
EndGlobalSection | |||
GlobalSection(ExtensibilityGlobals) = postSolution | |||
SolutionGuid = {FAE1656D-226F-4B4B-8C33-615D7E632B26} | |||