@@ -2,9 +2,10 @@ | |||
道路运输车辆卫星定位系统-视频通讯协议主要分为三大部分。 | |||
1. 设备终端到平台的通信也就是JT808 | |||
2. 企业平台到政府监管的通信也就是JT809 | |||
3. 设备终端上传的实时音视频流数据也就是视频服务器 | |||
1. [设备终端到平台的通信也就是JT808](#808Ext) | |||
2. [企业平台到政府监管的通信也就是JT809](#809Ext) | |||
3. [设备终端上传的实时音视频流数据也就是视频服务器](#1078) | |||
3.1 [将1078的数据(h264)编码成FLV](#1078flv) | |||
[](https://github.com/SmallChi/JT1078/blob/master/LICENSE)[](https://travis-ci.org/SmallChi/JT1078) | |||
@@ -13,10 +14,11 @@ | |||
| Package Name | Version | Downloads | | |||
| --------------------- | -------------------------------------------------- | --------------------------------------------------- | | |||
| Install-Package JT1078 |  |  | | |||
| Install-Package JT1078.Flv |  |  | | |||
| Install-Package JT808.Protocol.Extensions.JT1078 |  |  | | |||
| Install-Package JT809.Protocol.Extensions.JT1078 |  |  | | |||
## 基于JT1078音视频流数据的RTP协议 | |||
## <span id="1078">基于JT1078音视频流数据的RTP协议</span> | |||
### 前提条件 | |||
@@ -148,7 +150,34 @@ Platform=AnyCpu Server=False | |||
| JT1078Serializer | .NET Core 3.0 | 100000 | 174,163.26 us | 848.6417 us | 708.6542 us | 38000.0000 | - | - | 232812.5 KB | | |||
| JT1078Deserialize | .NET Core 3.0 | 100000 | 34,266.16 us | 357.1659 us | 334.0932 us | 23800.0000 | - | - | 146093.75 KB | | |||
## 基于JT808扩展的JT1078消息协议 | |||
## <span id="1078flv">基于JT1078的Flv视频编码器</span> | |||
### 前提条件 | |||
1. 掌握JT078解码器; | |||
2. 了解H264解码; | |||
3. 掌握FLV编码; | |||
由于网上资料比较多,自己也不擅长写文章,这边只是着重写一些在实际开发中需要注意的问题。 | |||
> 注意:目前仅支持H264编码的视频播放,主次码流的切换。由于多数设备厂商只支持一路通道只能存在主码流或者子码流,所以不考虑同时上传主次码流。 | |||
### 关注点 | |||
1. 在组包Flv的时候需要注意PreviousTagSize这个属性,因为该属性涉及到了新老用户、以及主次码流切换是否能播放成功。 | |||
2. 在组包FLV的时候需要注意将解析的NALU值放入VideoTagsData中,格式:[NALU.Length 长度]+[NALU 值]...[NALU.Length 长度]+[NALU 值]可以存放多个NALU。 | |||
3. JT1078的属性大有用处。 | |||
| JT1078属性 | FLV属性 | | |||
| :--- | :----| | |||
|Timestamp|JT1078的Timestamp为FLv的累加值(当前的1078包与上一包1078的时间戳相减再进行累加)| | |||
|DataType|JT1078的DataType为FLv的FrameType的值(判断是否为关键帧)| | |||
|LastIFrameInterval|JT1078的LastIFrameInterval为FLv(关键帧)的CompositionTime值| | |||
|LastFrameInterval|JT1078的LastIFrameInterval为FLv(B/P帧)的CompositionTime值| | |||
## <span id="808ext">基于JT808扩展的JT1078消息协议</span> | |||
### JT808扩展协议消息对照表 | |||
@@ -194,7 +223,7 @@ serviceDescriptors1.AddJT808Configure() | |||
.AddJT1078Configure(); | |||
``` | |||
## 基于JT809扩展的JT1078消息协议 | |||
## <span id="809ext">基于JT809扩展的JT1078消息协议</span> | |||
### JT809扩展协议消息对照表 | |||
@@ -0,0 +1,26 @@ | |||
<Project Sdk="Microsoft.NET.Sdk"> | |||
<PropertyGroup> | |||
<TargetFrameworks>net472;netcoreapp3.0;</TargetFrameworks> | |||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | |||
<PlatformTarget>AnyCPU</PlatformTarget> | |||
<OutputType>Exe</OutputType> | |||
<StartupObject /> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="BenchmarkDotNet" Version="0.11.5" /> | |||
<PackageReference Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.11.5" /> | |||
<PackageReference Include="JT808" Version="2.1.7" /> | |||
<PackageReference Include="NETStandard.Library" Version="2.0.3" /> | |||
<PackageReference Include="System.Buffers" Version="4.5.0" /> | |||
<PackageReference Include="System.Memory" Version="4.5.3" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\JT1078.Flv\JT1078.Flv.csproj" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Update="jt1078_1.txt"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
</ItemGroup> | |||
</Project> |
@@ -0,0 +1,83 @@ | |||
using BenchmarkDotNet.Attributes; | |||
using BenchmarkDotNet.Configs; | |||
using BenchmarkDotNet.Environments; | |||
using BenchmarkDotNet.Jobs; | |||
using BenchmarkDotNet.Toolchains.CsProj; | |||
using JT1078.Flv.H264; | |||
using JT1078.Flv.MessagePack; | |||
using JT1078.Protocol; | |||
using JT808.Protocol.Extensions; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.IO; | |||
using System.Linq; | |||
namespace JT1078.Flv.Benchmark | |||
{ | |||
[Config(typeof(JT1078FlvEncoderConfig))] | |||
[MarkdownExporterAttribute.GitHub] | |||
[MemoryDiagnoser] | |||
public class JT1078FlvEncoderContext | |||
{ | |||
JT1078Package Package; | |||
List<H264NALU> H264NALUs; | |||
H264NALU SPSNALu; | |||
H264Decoder h264Decoder = new H264Decoder(); | |||
FlvEncoder flvEncoder = new FlvEncoder(); | |||
[Params(100, 10000, 100000)] | |||
public int N; | |||
[GlobalSetup] | |||
public void Setup() | |||
{ | |||
var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "JT1078_1.txt")); | |||
foreach (var line in lines) | |||
{ | |||
var data = line.Split(','); | |||
var bytes = data[6].ToHexBytes(); | |||
JT1078Package package = JT1078Serializer.Deserialize(bytes); | |||
Package = JT1078Serializer.Merge(package); | |||
} | |||
H264NALUs = h264Decoder.ParseNALU(Package); | |||
SPSNALu = H264NALUs.FirstOrDefault(f => f.NALUHeader.NalUnitType == 7); | |||
SPSNALu.RawData = h264Decoder.DiscardEmulationPreventionBytes(SPSNALu.RawData); | |||
} | |||
[Benchmark(Description = "EXPGolombReader")] | |||
public void EXPGolombReaderTest() | |||
{ | |||
for (var i = 0; i < N; i++) | |||
{ | |||
ExpGolombReader h264GolombReader = new ExpGolombReader(SPSNALu.RawData); | |||
h264GolombReader.ReadSPS(); | |||
} | |||
} | |||
[Benchmark(Description = "H264Decoder")] | |||
public void H264Decoder() | |||
{ | |||
for (var i = 0; i < N; i++) | |||
{ | |||
var nalus = h264Decoder.ParseNALU(Package); | |||
} | |||
} | |||
[Benchmark(Description = "FlvEncoder")] | |||
public void FlvEncoder() | |||
{ | |||
for(var i=0;i< N;i++) | |||
{ | |||
var contents = flvEncoder.CreateFlvFrame(H264NALUs); | |||
} | |||
} | |||
} | |||
public class JT1078FlvEncoderConfig : ManualConfig | |||
{ | |||
public JT1078FlvEncoderConfig() | |||
{ | |||
Add(Job.Default.WithGcServer(false).With(CsProjCoreToolchain.NetCoreApp30).With(Platform.AnyCpu)); | |||
} | |||
} | |||
} |
@@ -0,0 +1,14 @@ | |||
using BenchmarkDotNet.Reports; | |||
using BenchmarkDotNet.Running; | |||
using System; | |||
namespace JT1078.Flv.Benchmark | |||
{ | |||
class Program | |||
{ | |||
static void Main(string[] args) | |||
{ | |||
Summary summary = BenchmarkRunner.Run<JT1078FlvEncoderContext>(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,8 @@ | |||
20190827032018,012345678999,0,1,视频I帧,分包处理时的第一个包,303163648162000001234567899901010000016cd3a9b9f20000000003b600000001674d001495a85825900000000168ee3c800000000106e5013c800000000165b8000028f10bffab7d4ef364e8a2c87f9b90c26e8065ef699b0f3bf22e8c6501f7ef3b0fbd19fe1939cf7a7838f1d84b88a4209bf029065cbc4eeafb98f5925e66e9c6b5f399b7218a1555039a95b921b83f6221fe0ceb0ee6daeb19e08968d8217f7095e3bed833215d59a93179667811c81a02ee82b170ac0e28d19b1a3ee21cfacffeec402074cfc6e0b478874387554f0fa5557ef805223885a674bb97892878fbda3a9e29b4f309bf0b29d2745b9eec49dbd9158a9bd746655bbf8e903f4bec96131970b188caa74d233a471c58c0c60603a80a0e6519d7dd2c9eb577cb0df24ea7d72f39521f90afcb396166015273add9d1d7e47bc2973e39f17e4cfd641eca8149136bac8e3be5450a9f9e304f2495067b5c3b5b9dc886dc2f01fd418aaa67121c6fb094b1cbf2dbf07e346d4071b75e9c77a52db90606c219e826c96e427444e4ac0d0df32e3c04ba32b615853feafc6beb82667e46424d0e173767a34639df3c6e25b112cfd80ef6159ca1a23aa96e932c8989239ef0cc80929facf99f6bcdb110afb179c01199897785c9f07beea5d8097b9a4f6c94251958552c0aca330c7fe995712b8311cdbbf4627562cfd8e3dcade064ff7a59f9564e3773fc108a4fb8de2bfaada56ef6fdac74a5b7cd442dc701edd06e865401029a230ec348235e0e0608b3c66630dc069e02ebd3c9bf2bc1e90141e5c77d7ff69b62db661b2ffc02ce1edc6b09a4a3c455b6daad227ea251d8f3cab5bcca5898edc310ea4bb2477337f92d39f18bc258f04f4d3a5881c71b3d13ae5e393340cd1288863071419ceb6416e917e0e0553b340bf4a381f6ee71ab083bf119e5b69791a60851e995e8313a62916f835c1538a8f3d775a7cfd6ab9ba106f2a19eb1ba802724c1641e0bde105e392bfa437a188df395e9d287d436b208481307e97728a18117ef43577ff1e922c824f996d60ae0d6d9390ff97ee90691c2710899784adbe7ff6ca7f487f7ceea7f855eeb18f3f250ebaef9efeb97a9bead5b80de5069627d5f4fed615f0c7ed87965857f744fd7ff8f4d2b79f0d7b7f865fa26cc77eea03701266318ec3399bbcabe93d9a97f7b4f3bb9ac27aff8a529d4310216c8e9a6ca49e47e4371bc2cd551e6b3d4f56925fc9fbebb72041a31066ebc37cc61a7c1396ac48e864d7e8fb644a5fa49b73f8c7befdc4f05c88291623e5e3d0f4bd54b9b2c478467ac5e42a8080eabd37672f35903f4f44d2827d96960d76ab8bc86e0ff4a29afd4ae2ef5dd3d2825786e1229f26b797e35 | |||
20190827032018,012345678999,1,1,视频I帧,分包处理时的中间包,303163648162000101234567899901030000016cd3a9b9f20000000003b6a6fb10545aee778627f92f2bd15c71782be2793bb2ba0cc97d44bf79f7bc7c4186c9c806ce7bfff616c79758a53564d306fd770055679467f94f232149a8232e4b0866a2049ba007d64657886dd689222152226874b4ecb0d5f936807fa704d84567405cb49570de8e990ff4748fe6abcd1a0a9982a78b487ec56278c3334fc4579e75708abed0175ee5baa548deb84d0af5cc9cb918bf851f8e78867968f32f6fa9ebd2b93554636813274839d6944529f204559ff388d6ea4c63adb0d8ddf9ddb27cd7ebe33287a6139688225d0aa5256af74fd0d9358f7bc072abf4a3f1d59ad318aef1453ce4a229781420056e89e5ab9dccacd69ac688e590e6ffbbbc79ba2d83da0d9d9f80d55b295a1bc5b2df2699a75d95638da525b70c93d9fb48c8bd6a8d53adfa9c7f3c1ee7ad5d8429e28bea5c6c033762b6398528dd7bf05e3fc134a83f9ef2543d581b4f45ce17813035ce0432b69ad4d1d22c12003e442631bac549a8e0a2b1fb4a7da58e91122ba67537e7d02d66f6d4971e8c080f1855156490ef5c16299f84d04f2600b54972ffaa15e70d3ded386cd2ebb4321070c76530b5c0ede147d63d6d1779f5bac91d95bc8725e8b1605db7cd92f0a3b142394dec894ce3910462b375e8cbd70ae493dd0ecb143997673468b9add2f81001b3cae5d51ee197ba68edfffd1a3ffdd0e1f167bb0137f6049ad3470998ad8df7c78c414f79d39e6490715d71100eb6ae8d3e8ad4783a7d24a5594ffa10fa0dbb30a41d2fa62304eff3477b82f5aff028629accd32a5940c2d2657443f0fde5a6bb06bc3c82e6dac6e51b0b476a804aba5c84565f79ca99561f735dcc5a18001f043491ad0e2a0c2c65afea3fee2bb158f50cc8eb071308b12b580e0c6bfefeb9f9fc0fed333276cb2ff27e04dcc2399bbee6562952268af2d1e05f0b301f7fc261ce1a8d8c0cbade4eddc4cdff8f62aac0f6807d47771cfaf33d3700856ceaea66892e43fcb83b7a9e32ae1b759dc7ec581747f1c2cb7a32c69e91a7124294d53087f6b2dc1ad63fb2ecf04a16b548902402f38e7ecf6d7fede301f83b76f1f329a60c6863dfec8c3a7984bc1abf6481eae4f7d8218b882818482e424a0ca645f6b0445c5a9e239a2b4bc3d6a70c3f3f51fb6346b3ce643421a7697e43b5e0fd4ba2c519b6cc62ee6ac7dff3c81a7d0ee4eb291de62edba5e05212e82e968f85b78dcb875b67a9198eefea0960d4873d92a8b32fb88236b207157e5453a96fd5792da527bd1b195f426351b516c21900631a571c6d02b144c88ab72b35ed300d99cef12c1a3ccf95ebe305ed4513431661be9245c4a4ba62 | |||
20190827032018,012345678999,2,1,视频I帧,分包处理时的中间包,303163648162000201234567899901030000016cd3a9b9f20000000003b6da72bd536f42168e2c3d18a96c3aea86ae57cb5fb116978ff2481a70efc9da6397ffc9c6b52ffd524c68f50b01ad81fb0740d9334df9a632d21aa1bf0addc4d21f4dc00d61533748f4c42b045ffd65f62d32f86f269c4cf1842558f3ca2450e404e589c4d271d570e052b2d451ea2978641d44398d98c65967e5f0c61f23d8b7e7aca9ae900926739d85231edabc08fdb6670dafc84ddbbd3d824c33140359573ab1c2942f0aa05f9eb08ff94d9964995ae63599f9e26c606ba6f009d0cf6693c984cbfed2ea7a822cc9543ac76e00788ebe0b449c93b4961c45bf7ff82d40bb4c7c3a3dde1a8820fd5832834ddb5a6210cdf0dffdf48d84a7596eae5f653309da08dc592a406d9f55c511d858fdc575b930773b59be022bf7776294e3e5ef9b9386191fe2c8c1d38708dff87ddff23cfeb8b42154adfd598a92979fa59b40c7900d7c3df8a53d08836c38c5134a7abc7eafc8c10cdb60366286ddfcb7c193999ddc95af2f6c76ff158213a19b63f79cce1fe1fcc6b949ecea7d1853936047503594676466bc70dd61127986aab961834419b17ae6ed63c87f06bc7e2c1e3b1358dfe822c86577b5fac89f957a90fbcd39f67378cc1cc22a56d081e3fb1a5e6060152aee2331c297c3646cc604e13a7a4a383a37d417acb7d1076a79ca794ab16a7ca56a31a8e4dc032025ec5181038f034a502fba62ad21e5990c0235d6d26faaf693a89dfba3d07f75759b8155532b91b84f03b0f134af30e2b007e68a6da50c8a040e4e9e7d0b53f381b6b7ab3de85f28cb3b51fd23b89865d833861423a3b194bfb8c8e5fe566ffb018b6295c076940696e726658370289a4cfd66ae566a024d1ff94c5d65d9bfed4fe89df67839904785796ceb6264dc0ff4b103acaf05a65a6fbeb9e15db3a06b33df4e1f8365868e8cf1b13734ec27e23879f061d833182fe9d034d559a56d6da5708896bc6a0b5914261d20923f496cda936f108adf7164861b577af5ba7116d3ede71b16465fb462fce107844cf3583a9997a03415680458b097ed95bf06fb0d3df2d991d2437460005412429e120e55aa79bdc2f1783bb45db8f6008581bd07d1a3282ee7c0e0c4d6b2fb546daeb2cef04937e799c7d96962dc51237963dce7345161a2b905ba89046db6435890d09500babd98d13c26bcf86f6b5214082d28b76bb7ad1c4f81edfff93a5895eed2ebba9250fccdda3f53f020a089246bc00cd0de21b9169cbd1df9849b2893ed774a1d149c50da0287c25271823c99de17236b6544c1e5a009416ada3e57474944d3f94ed16cfd7473629e77be9a349027e0d8f7e796384664c0285a77 | |||
20190827032018,012345678999,3,1,视频I帧,分包处理时的中间包,303163648162000301234567899901030000016cd3a9b9f20000000003b6b83940b4220e76c108af6432deb4d1a5ececc2906174181c9d85828a5df10e8046a276ce933e0720f7dd4bd234baf61d98adbd8d623be2c7e8c5d3272d41af666f44dd4bf0d5ecf47ccb0bda03299a2d70cb76ba7b73ae0c92e38e2af9c1c8848996666d2741efe033e46a01a19e6f9fe8c90e088ad0d034d53cce3bacf1b87b8f46b31087f21cbff177d2fa17aab609e0c1dabcda428830bd23df87cbe245b34407c6593e6179985db026112eb853a0b1d79f46a9691ee7aebb78009f145f04946ea8c60f01cf0e6c9bea1e7fdfc6307615aedde4f7941ffc1be711dea15c84c519dc860824cdc6eb96b64d74c0d5b9fba8c552f3b89eb396872b66c9813ad672fa8fc7a560f75d105e82c926ebee8964f3a59ddc43be18db374e9abcaeb9c8fda71a3d8015683bdb6a4b764f3e4927d53390ac1eb275bd972263667fab4d400852f88af663c353cfe7bd6b81eb03535c2d06584810dfc792f6bc45e52c0103b4e1192a726810186dc3aebe061b353650c7194feec03c37d2ed164758358c5da6aa1bdf9ccae2f45d5bd582cc62d05836380b2eb468160dc1cbd2f8cb94c62248d57baee18f9913f6cfea4909c69f128d1997640d1a038bb1617b52ab13a173e1e87c74d7965df57c6b1baf1f540b16f258e5e691640e93be9bf895703c0f5367099d28a683fa5e912e4b67b18b0a057b1b2dd90b8462bcc27da028e9695ff56969f979c7ea426fa66e282a235fa903f15e8c88d38e35a1f139189fd9243f0f8c83e527d2a420dca72d00e011219787622b3d8923bcea01e1a189a5520bed58dc4544201364ab3dc780df66a29ffe99e270dfc01d3f63357d8b8aabd804a2f625d028d143b6d753ee97976c66afa4c74e28c7a72b5f71a0113c16147dc64746ee04a9fe6487b31b64a8ae97c44f5a61d687f6cd3a758b8e66affd89943596371e335bab26093d74a24dec39b59eab7787e7a440ca7a54e0e49c71ea61b831892bc6d677c2a0b4b04cb3e2e2d26abce88b699789f398f76d61d25f3dfeed422a3036f768a5c15d3c8a1bd6a92aa1149d12175798c774444ab38fc4fb98eea46a2ccdd11112a819f934d616d2b64997c0143755d9f501d1b669d3d2763dc52d6c1f3677e2a20c9faf2667fd19b8e4744ba4ba5f2e86624e30ec0d62db62b23592d47060b9127951edcfd47caf675fba395743b5f226d6ed9930deca235a50fa54cfce12337001dda783763ffe3f04953782653131b815edb764195df6989ad0bd7505a7d932af322dc1281cf0bf3bc5b68f496bbc82f68720aa9f4d9814ad2225f665a566a9bd3cf241edae6f8baa6998fede4f29ba02 | |||
20190827032018,012345678999,4,1,视频I帧,分包处理时的中间包,303163648162000401234567899901030000016cd3a9b9f20000000003b68cd389cf09725debb677ef3dfe230a2c1dfc885f5dca8b786d1771884264710f4efecf75d2c3f3725a483f24827ee312aa764670c3ab6cbe396ade145be1560b05f910eefefec0837fb06cd596e0328b22b40484f127b87626e2b764f1c4bca5ba363104e3ee3a6b154b808a219c1caec5ab6bec1ac908a3805faebec1b8f9ea32e6767f5dfb682b919c50ed48b6b91ef4b7c975c566a69beb752a9ff94131fba6cf514486ec4e2757d3c7ae598ce57ac222a4f75be28cd3eed5e5da199b4c979f249d9289869158dc58d7814f303d82fe9373dca42b854e59721d375f511c2381a5dbe3e31f49d6b37c21214bc63d5d28ab26db4b2fb180c36fa028aa74db1a1c1411cfc18938e53009db5f111ee019cf253370c976f27895f5b804dc03b0057175b1ce50bd16335c294fd8a78c0a89e7399271063e920eb77071b45cbb2f4430047ee26a344283ad335890a8de2620fb9da09277957196a9e79c619223329e57c15aea41cc2695bf05a0f029be0f6000014435c986b8a5ffc8b52179ca6eeacd5c805c8cb7362de0bdf7cca9f18a01c35fb18ab977f85e1e5f1f27ee76ef70bd84c068d28977f3ccafd8a81cb38680a05ddc3785d250251a94d88520fe173b3bda7848cafb7b297e411d409c8fc0f0f985c6fef482693c07cacbffc55d0bb2f677632a57a30b8d40a3b6bb31ff275d3dda834d7446bb1bbfbeaf2a17fe6f2918596c6ed7b0a8f6b414feea8abd29e8743bddb42dc1efa835349865f0840b087e2e2133de268f033ea045868f67b3dfced98893c6bd218a12f1aab8c309ce4aa944188fa17f389f00e6fb4a67c4d3d3f31a8701539888f5527440a4aefd62274635d959dea1c1540301e28d44e8007fe1aebad312eec1d4d669019a84ca7fc494966ebbe44af78b85839aa85503c0068dbd04d5154271df30afd3f4de35f25a9013e0e27e252aed301d4effec8fa3886d26277422a0921bef1c4183dc58ce8a9c83b5d4e163a3fd3279a7dffc65d54b75f5a21309241faca8bc5d369111e696430ddd4ee3f0ca0e5d6d275544fa67a1f528a502aca99a20de523118e7c57f727516127ea84cdb88d86096acdd6fac1e506b6ec7d51a57b552a88a9034ab867b604777286db7b4ed89cdb964ce5a115ca2051f2c1e04fd6ec9f258ba99361e4364ee3bb383bd96b73e67e965c9f538e98a610b1b4d05b20a04b7647c26c9333f067b5acfca527ad50939ea7255a685a07ea419d8092ca595f65d38fd9017c5595b58d7bc08ad26e13e661b0464bf8a4a604374dc5394b0291fd059e8ff1d6817c111fe3c2f00c8608a890dc4cf7a33b8e5b4d0e563e7 | |||
20190827032018,012345678999,5,1,视频I帧,分包处理时的中间包,303163648162000501234567899901030000016cd3a9b9f20000000003b6bd62450f77815accb275c1bc47c7284ad621e7e28ac088c68a30f5dad7a227bce3939e352c58937c7ccfba6d591015ffed083cd74a5eb012838bb1b41a8f325e6b796970a086d9eca960d10b418596261cba541f5297b440de7f2a7f58964e94ef9e254df3587b1fcfd11f7d5e1a6609af2af348f1e6c388cf2a81f37fde1a9d70ffc7fbdb2068a2efb661138c54607e040026207ce5974828444f140ba4690fab448d214a823b569f2cefb1781d21270b47fcdee652d2692ad588e061f22f680603143f50c4fba609cfa6cc45224bab6e954138299fb641e489c68252f80ddd805588404e5fae0dd58eac966d5a19e8bd14988685f6f1bc6ef0031c2b6053982ffc962e68b4aa1a70e7fb47a91261f0acb0d17d59b3ce17804ec16f5c88d730aa7f2bc71ba22937a3aa1ef1958e6316d1a4341ff8deedf85d5d87ffd88ed791cd9ced372fccdf4726e9f0bbf539689a41f14fee3f2183907a5f693267f7e1dd2dbd64ff4e2f717cfb699e998318504d9a2427dfcb6235c3f4aecec5335cef12755f5080e46d600227222b32971c216025e4e392bee8ed19a9100f2c01009691d199ae675b84fee831c1a64a0d1fd47b56bb5dc09da50891ed1774e8a44aa8750b8f41c912379c4bb6f0e7174cdd7c53a6a4b0938f7619b9c13c15fc4bce96c710372121bb93b1d92e1b0985fb34703748801a0782cb11bb607a316f1aa214f8ffe8fb904e2cd21ffa8d498b3188c19d4fe7705ffd62bdc36743da944de3626dce65e492d9500a0ffd13bd9d602cec65581bf4f64a57ce8cffb4687b6f202792dc92599dfab07066803586f14ccf0a2e6398752332fc3e30cb2553e0d97bd01d3212d12750a1fd0d6ff98b4b38b2bef39190c7a415daf9fbf2004cdbe6b31416a0667f6d02abe531a756c59d52f0ae6caa47a0394eb18fe93a14c3227b491a8a000e70b56227dcbce2e477125a8f8807626b16e0a915622172412aad1c4f502997e28aea12c39c5eacc308d9e49c440b3ffac3179b2737e280a6f2968f8e9721b9e8fb8228322e9a01c8331a4dbd55b30040dd25148acef58e63e12942276a4a41ba153efeea2a0b9cc474436238c24080d19427132ea61391146a9912c89cdd6e7edc6914f621e13723b165870c6b244664f1546d10ad0738349f8c78111f9cd04e55a9efc9887e945d296f857fc6e58a8fba4ab88661d8ad68ba78a173a834c9d980a60e917b468b3b3e6e67c8ab9cb35d0df8d2d762596668d41d3d02dfc4178c4d252cd8ea356bf64660c9fc6eb7baa402681b55d3bfdf7df687ef6352cdb4051ffaa7eaebc1c6a6189f023b14d64ef33f5f26ea | |||
20190827032018,012345678999,6,1,视频I帧,分包处理时的中间包,303163648162000601234567899901030000016cd3a9b9f20000000003b6797a9891e014bade387cb3b9676209b9cf5d74f32447df99a5b4fe27de8d2b96d49bff6d51c111c596752ad81bba368df135bcfc094b7f03189f8e1b99ddc6797bf983765c4d3d9ee4b312f1591730b2dc58572de846542a98a04d590e6ff2732055979b4a8bf2319e21e939bf6d22bbd70d03dfbc47d3d51942deee740e1a0d65771445687359a163d3c46a3be755680785df058473f52222838f98c48693ab9b63f24ad7ce245de4f2b610ab504ac1f642665978cea5cd33e7ddb42456e0fb493425c38b7194911a716c3b374087a20cfb6dd1763644716dfe1fb90e47f4812306febb1b1b61950c0e372fd286cadcbdae825a424f0ad36cbfbada872cfda67cb6d0940094d3e700ab47f6597a7d4a8583888c783d39be12c1780424ad8bcb330f8d84ea74c39f78da72a2d276539fb8d4f9bb9f99ac3e9cbc2f514432bfd9f0b5001f6cbdb88b8623a551a3b55b50f0139a5803a6af6547bc18f706d1027966d5fe04b4c6d9602376ba4d6bf74cc37ef7cc5ee5d3fe39b1aaf047e26315a4aa4cde6ccf38d51ef14c8acab63262fa0731b4a45dde09bfcbddbb79d29a10a0ffdcca4886cb90d46c74f61ddfacca9e94fc82ca6ffb892bc80cf24f3070c4fc6536547df2d667d8488de5cb977dda8dd1a08b83839a451431a198bfaba058fff2a1ac8711bbe8bcef215cdacf474a031cc7e157ccc63292a767eb184cc1c1aa3111c69372e13ab80abdd4743b29c2d94f6170f249f5c9f3ed25b1e59c1554cbc10397974089c0ae1775467bb54807eeebf8d3ba4335ba5f223113a22a1c442d0721a2c72d51ef1cb927e4eb0b4134f01d3855dd317bf33c706832f1d2859853b6210cf2f781d80904cbddbeb2baf44d28790024fbd317a825c98df2f346682092e95f3572f9442bc8762d5753f23f49d377a0f46202615eff594f054d1e5c16ff1066ae1b79e4b0257c4b9a257e9f3c9c9eecbfc6f501b9849197ffe8ff88a9af96da80805bf62ac17e792208ca66212d06300d4cffc5e5463c60f5e44b0d113be35829bfb15680d4de81f3588dfd8adee8564884b1ca68a3aba8115f06aa41f642c70fb4374568509c9666211c97c44a05d67ea5e5562f5cfc6fdd076f5ffebc3c37b4e6d7fe235f9670f2261a6745425e91bdab2e14cf666686472651b9b43524d3ef5ac1c4e432fbb2fb99b8ba166c9d343a30ed3a711c5d2fe545902ec57c642d2148c5c0b9bf0bec37ec6986cf1c33ae7bf2ec5ef1f11351e9ee58ecfe5503d8225e28412fdc3a721eb1cef93445fd49dd14cc15fb891027aeb6077fa85c6cc0059404bbf8862b52933ee9ed3da24b505ee110 | |||
20190827032018,012345678999,7,1,视频I帧,分包处理时的最后一个包,3031636481e2000701234567899901020000016cd3a9b9f20000000003a4e012eba47e69c63ce2b050264c0949e7e4dfe5e0e1323c0c71b7760f4b3f692f7507e01c5cd56f0b518d4c9539b500510ec53fe955f86698ed65f4546663bb4fac1fcc73f9c462ad8c2f1365c7bad60d76bb50d33588ff7db86d16611feed8007bcc8f2355c1454ad286ba15fee4d374ec91909f2936a67b5de74700d273f272bc5a6d52dd342a6368471cdeba191b8ba9ddc9bdce8a93063a909d2167b19b27a8cd7e2634f630bff1faf36fd6fb1108a9dc8e51fe949f4fbaaeaaa98ec8147087e5c60c65b1f355d4e62577f72b450d7d3fc878c1fb90e1be03c6f1166f738e60db958ec0cc320d6f66225861a695350dd8c84bc5ddb0d35ea8d4d4e40bd79a3e73d86cdce986ee25af6eb5447f45af3c35c11e114ee82e8da7b6aff97ad9118a732bf1489f6ad2abc4123814b4b8b0ae9400996840d66ecd7574ac539bd3ed252da0136a920844d751b5cba2a515a492e943f5d709376d0f297195d29c4316664bfc83d8aebae02e997578f3697327e6c03c2d2681767adcce4523f15331c1f4778300600e74c259666ea6893471d6b5f764d81a78c4983dbc8d75c7c09c585f8a44b71fe63c1eacf9661f646f7cea999b21c920f1a806e8f388efe2be388b2770d02cce2508b76fe0ed8a5a4afd46ab989ed553c0059d09a883dd42ced5f91d95337c475e5324803db33f61e71fc59d98894f56c19843557da9df9663438ed4678645943c2d2e2b7395464e384f00f83d7a1f3f3d748720856c9b261058c277f0ea18457355644c0d46619d658ec2e0316b643863734c3f12d9dffec598beeaf2bf3b5bd8cebc62a772e4690d14cbc0dcaabc5a9e3a865f2871fb38d7da0117ecb6ef3479b0fbb5d21e4d822e025fa149e880b87f3dcc764996284f8a19dd9eefb02afd88057ea943ab91bcf6627e94e5ae739e72dc0fa8e43bb50770e0369a8b144635dc623d93b3a55619c02c766cc75219efbbe7ff032e8d078e485aeaa2e0cbea63cb7887830dec58993f11049b22b2961ed5bf4d4878b3fb7c379b546c9a375134f48b15a1971ce9bc3fd7a7f2c0fe1010e28e0ac11b3365c102a0cc041eb12e0cc7372e6cc1dc7c6f7ddcf6fb0563eebbd3cd747a029693e0ad9784a775a4c334eeac3f3cc69551b77a5b2b9fd581fd0a3a8e87e7f96fe24e669c17d48ff5d9298330f47fd7c3361e74a3d3cf27fc474b6a6af8357812c5c663634cf9b70f1f1330a2750a04e996597f4e1d84650435c9d02788b4315d16f464312afc818d5c3ad87c7deefab369d3be3e84d30fbd728f4d5beb648db98e5ec39abb29990980 |
@@ -33,12 +33,12 @@ namespace JT1078.Flv.Test.H264 | |||
public void ParseNALUTest2() | |||
{ | |||
JT1078Package Package=null; | |||
var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078.txt")); | |||
var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_1.txt")); | |||
int mergeBodyLength = 0; | |||
foreach (var line in lines) | |||
{ | |||
var data = line.Split(','); | |||
var bytes = data[5].ToHexBytes(); | |||
var bytes = data[6].ToHexBytes(); | |||
JT1078Package package = JT1078Serializer.Deserialize(bytes); | |||
mergeBodyLength += package.DataBodyLength; | |||
Package = JT1078Serializer.Merge(package); | |||
@@ -5,4 +5,4 @@ | |||
20190827032018,012345678999,4,1,视频I帧,分包处理时的中间包,303163648162000401234567899901030000016cd3a9b9f20000000003b68cd389cf09725debb677ef3dfe230a2c1dfc885f5dca8b786d1771884264710f4efecf75d2c3f3725a483f24827ee312aa764670c3ab6cbe396ade145be1560b05f910eefefec0837fb06cd596e0328b22b40484f127b87626e2b764f1c4bca5ba363104e3ee3a6b154b808a219c1caec5ab6bec1ac908a3805faebec1b8f9ea32e6767f5dfb682b919c50ed48b6b91ef4b7c975c566a69beb752a9ff94131fba6cf514486ec4e2757d3c7ae598ce57ac222a4f75be28cd3eed5e5da199b4c979f249d9289869158dc58d7814f303d82fe9373dca42b854e59721d375f511c2381a5dbe3e31f49d6b37c21214bc63d5d28ab26db4b2fb180c36fa028aa74db1a1c1411cfc18938e53009db5f111ee019cf253370c976f27895f5b804dc03b0057175b1ce50bd16335c294fd8a78c0a89e7399271063e920eb77071b45cbb2f4430047ee26a344283ad335890a8de2620fb9da09277957196a9e79c619223329e57c15aea41cc2695bf05a0f029be0f6000014435c986b8a5ffc8b52179ca6eeacd5c805c8cb7362de0bdf7cca9f18a01c35fb18ab977f85e1e5f1f27ee76ef70bd84c068d28977f3ccafd8a81cb38680a05ddc3785d250251a94d88520fe173b3bda7848cafb7b297e411d409c8fc0f0f985c6fef482693c07cacbffc55d0bb2f677632a57a30b8d40a3b6bb31ff275d3dda834d7446bb1bbfbeaf2a17fe6f2918596c6ed7b0a8f6b414feea8abd29e8743bddb42dc1efa835349865f0840b087e2e2133de268f033ea045868f67b3dfced98893c6bd218a12f1aab8c309ce4aa944188fa17f389f00e6fb4a67c4d3d3f31a8701539888f5527440a4aefd62274635d959dea1c1540301e28d44e8007fe1aebad312eec1d4d669019a84ca7fc494966ebbe44af78b85839aa85503c0068dbd04d5154271df30afd3f4de35f25a9013e0e27e252aed301d4effec8fa3886d26277422a0921bef1c4183dc58ce8a9c83b5d4e163a3fd3279a7dffc65d54b75f5a21309241faca8bc5d369111e696430ddd4ee3f0ca0e5d6d275544fa67a1f528a502aca99a20de523118e7c57f727516127ea84cdb88d86096acdd6fac1e506b6ec7d51a57b552a88a9034ab867b604777286db7b4ed89cdb964ce5a115ca2051f2c1e04fd6ec9f258ba99361e4364ee3bb383bd96b73e67e965c9f538e98a610b1b4d05b20a04b7647c26c9333f067b5acfca527ad50939ea7255a685a07ea419d8092ca595f65d38fd9017c5595b58d7bc08ad26e13e661b0464bf8a4a604374dc5394b0291fd059e8ff1d6817c111fe3c2f00c8608a890dc4cf7a33b8e5b4d0e563e7 | |||
20190827032018,012345678999,5,1,视频I帧,分包处理时的中间包,303163648162000501234567899901030000016cd3a9b9f20000000003b6bd62450f77815accb275c1bc47c7284ad621e7e28ac088c68a30f5dad7a227bce3939e352c58937c7ccfba6d591015ffed083cd74a5eb012838bb1b41a8f325e6b796970a086d9eca960d10b418596261cba541f5297b440de7f2a7f58964e94ef9e254df3587b1fcfd11f7d5e1a6609af2af348f1e6c388cf2a81f37fde1a9d70ffc7fbdb2068a2efb661138c54607e040026207ce5974828444f140ba4690fab448d214a823b569f2cefb1781d21270b47fcdee652d2692ad588e061f22f680603143f50c4fba609cfa6cc45224bab6e954138299fb641e489c68252f80ddd805588404e5fae0dd58eac966d5a19e8bd14988685f6f1bc6ef0031c2b6053982ffc962e68b4aa1a70e7fb47a91261f0acb0d17d59b3ce17804ec16f5c88d730aa7f2bc71ba22937a3aa1ef1958e6316d1a4341ff8deedf85d5d87ffd88ed791cd9ced372fccdf4726e9f0bbf539689a41f14fee3f2183907a5f693267f7e1dd2dbd64ff4e2f717cfb699e998318504d9a2427dfcb6235c3f4aecec5335cef12755f5080e46d600227222b32971c216025e4e392bee8ed19a9100f2c01009691d199ae675b84fee831c1a64a0d1fd47b56bb5dc09da50891ed1774e8a44aa8750b8f41c912379c4bb6f0e7174cdd7c53a6a4b0938f7619b9c13c15fc4bce96c710372121bb93b1d92e1b0985fb34703748801a0782cb11bb607a316f1aa214f8ffe8fb904e2cd21ffa8d498b3188c19d4fe7705ffd62bdc36743da944de3626dce65e492d9500a0ffd13bd9d602cec65581bf4f64a57ce8cffb4687b6f202792dc92599dfab07066803586f14ccf0a2e6398752332fc3e30cb2553e0d97bd01d3212d12750a1fd0d6ff98b4b38b2bef39190c7a415daf9fbf2004cdbe6b31416a0667f6d02abe531a756c59d52f0ae6caa47a0394eb18fe93a14c3227b491a8a000e70b56227dcbce2e477125a8f8807626b16e0a915622172412aad1c4f502997e28aea12c39c5eacc308d9e49c440b3ffac3179b2737e280a6f2968f8e9721b9e8fb8228322e9a01c8331a4dbd55b30040dd25148acef58e63e12942276a4a41ba153efeea2a0b9cc474436238c24080d19427132ea61391146a9912c89cdd6e7edc6914f621e13723b165870c6b244664f1546d10ad0738349f8c78111f9cd04e55a9efc9887e945d296f857fc6e58a8fba4ab88661d8ad68ba78a173a834c9d980a60e917b468b3b3e6e67c8ab9cb35d0df8d2d762596668d41d3d02dfc4178c4d252cd8ea356bf64660c9fc6eb7baa402681b55d3bfdf7df687ef6352cdb4051ffaa7eaebc1c6a6189f023b14d64ef33f5f26ea | |||
20190827032018,012345678999,6,1,视频I帧,分包处理时的中间包,303163648162000601234567899901030000016cd3a9b9f20000000003b6797a9891e014bade387cb3b9676209b9cf5d74f32447df99a5b4fe27de8d2b96d49bff6d51c111c596752ad81bba368df135bcfc094b7f03189f8e1b99ddc6797bf983765c4d3d9ee4b312f1591730b2dc58572de846542a98a04d590e6ff2732055979b4a8bf2319e21e939bf6d22bbd70d03dfbc47d3d51942deee740e1a0d65771445687359a163d3c46a3be755680785df058473f52222838f98c48693ab9b63f24ad7ce245de4f2b610ab504ac1f642665978cea5cd33e7ddb42456e0fb493425c38b7194911a716c3b374087a20cfb6dd1763644716dfe1fb90e47f4812306febb1b1b61950c0e372fd286cadcbdae825a424f0ad36cbfbada872cfda67cb6d0940094d3e700ab47f6597a7d4a8583888c783d39be12c1780424ad8bcb330f8d84ea74c39f78da72a2d276539fb8d4f9bb9f99ac3e9cbc2f514432bfd9f0b5001f6cbdb88b8623a551a3b55b50f0139a5803a6af6547bc18f706d1027966d5fe04b4c6d9602376ba4d6bf74cc37ef7cc5ee5d3fe39b1aaf047e26315a4aa4cde6ccf38d51ef14c8acab63262fa0731b4a45dde09bfcbddbb79d29a10a0ffdcca4886cb90d46c74f61ddfacca9e94fc82ca6ffb892bc80cf24f3070c4fc6536547df2d667d8488de5cb977dda8dd1a08b83839a451431a198bfaba058fff2a1ac8711bbe8bcef215cdacf474a031cc7e157ccc63292a767eb184cc1c1aa3111c69372e13ab80abdd4743b29c2d94f6170f249f5c9f3ed25b1e59c1554cbc10397974089c0ae1775467bb54807eeebf8d3ba4335ba5f223113a22a1c442d0721a2c72d51ef1cb927e4eb0b4134f01d3855dd317bf33c706832f1d2859853b6210cf2f781d80904cbddbeb2baf44d28790024fbd317a825c98df2f346682092e95f3572f9442bc8762d5753f23f49d377a0f46202615eff594f054d1e5c16ff1066ae1b79e4b0257c4b9a257e9f3c9c9eecbfc6f501b9849197ffe8ff88a9af96da80805bf62ac17e792208ca66212d06300d4cffc5e5463c60f5e44b0d113be35829bfb15680d4de81f3588dfd8adee8564884b1ca68a3aba8115f06aa41f642c70fb4374568509c9666211c97c44a05d67ea5e5562f5cfc6fdd076f5ffebc3c37b4e6d7fe235f9670f2261a6745425e91bdab2e14cf666686472651b9b43524d3ef5ac1c4e432fbb2fb99b8ba166c9d343a30ed3a711c5d2fe545902ec57c642d2148c5c0b9bf0bec37ec6986cf1c33ae7bf2ec5ef1f11351e9ee58ecfe5503d8225e28412fdc3a721eb1cef93445fd49dd14cc15fb891027aeb6077fa85c6cc0059404bbf8862b52933ee9ed3da24b505ee110 | |||
20190827032018,012345678999,7,1,视频I帧,分包处理时的最后一个包,3031636481e2000701234567899901020000016cd3a9b9f20000000003a4e012eba47e69c63ce2b050264c0949e7e4dfe5e0e1323c0c71b7760f4b3f692f7507e01c5cd56f0b518d4c9539b500510ec53fe955f86698ed65f4546663bb4fac1fcc73f9c462ad8c2f1365c7bad60d76bb50d33588ff7db86d16611feed8007bcc8f2355c1454ad286ba15fee4d374ec91909f2936a67b5de74700d273f272bc5a6d52dd342a6368471cdeba191b8ba9ddc9bdce8a93063a909d2167b19b27a8cd7e2634f630bff1faf36fd6fb1108a9dc8e51fe949f4fbaaeaaa98ec8147087e5c60c65b1f355d4e62577f72b450d7d3fc878c1fb90e1be03c6f1166f738e60db958ec0cc320d6f66225861a695350dd8c84bc5ddb0d35ea8d4d4e40bd79a3e73d86cdce986ee25af6eb5447f45af3c35c11e114ee82e8da7b6aff97ad9118a732bf1489f6ad2abc4123814b4b8b0ae9400996840d66ecd7574ac539bd3ed252da0136a920844d751b5cba2a515a492e943f5d709376d0f297195d29c4316664bfc83d8aebae02e997578f3697327e6c03c2d2681767adcce4523f15331c1f4778300600e74c259666ea6893471d6b5f764d81a78c4983dbc8d75c7c09c585f8a44b71fe63c1eacf9661f646f7cea999b21c920f1a806e8f388efe2be388b2770d02cce2508b76fe0ed8a5a4afd46ab989ed553c0059d09a883dd42ced5f91d95337c475e5324803db33f61e71fc59d98894f56c19843557da9df9663438ed4678645943c2d2e2b7395464e384f00f83d7a1f3f3d748720856c9b261058c277f0ea18457355644c0d46619d658ec2e0316b643863734c3f12d9dffec598beeaf2bf3b5bd8cebc62a772e4690d14cbc0dcaabc5a9e3a865f2871fb38d7da0117ecb6ef3479b0fbb5d21e4d822e025fa149e880b87f3dcc764996284f8a19dd9eefb02afd88057ea943ab91bcf6627e94e5ae739e72dc0fa8e43bb50770e0369a8b144635dc623d93b3a55619c02c766cc75219efbbe7ff032e8d078e485aeaa2e0cbea63cb7887830dec58993f11049b22b2961ed5bf4d4878b3fb7c379b546c9a375134f48b15a1971ce9bc3fd7a7f2c0fe1010e28e0ac11b3365c102a0cc041eb12e0cc7372e6cc1dc7c6f7ddcf6fb0563eebbd3cd747a029693e0ad9784a775a4c334eeac3f3cc69551b77a5b2b9fd581fd0a3a8e87e7f96fe24e669c17d48ff5d9298330f47fd7c3361e74a3d3cf27fc474b6a6af8357812c5c663634cf9b70f1f1330a2750a04e996597f4e1d84650435c9d02788b4315d16f464312afc818d5c3ad87c7deefab369d3be3e84d30fbd728f4d5beb648db98e5ec39abb29990980 | |||
20190827032018,012345678999,7,1,视频I帧,分包处理时的最后一个包,3031636481e2000701234567899901020000016cd3a9b9f20000000003a4e012eba47e69c63ce2b050264c0949e7e4dfe5e0e1323c0c71b7760f4b3f692f7507e01c5cd56f0b518d4c9539b500510ec53fe955f86698ed65f4546663bb4fac1fcc73f9c462ad8c2f1365c7bad60d76bb50d33588ff7db86d16611feed8007bcc8f2355c1454ad286ba15fee4d374ec91909f2936a67b5de74700d273f272bc5a6d52dd342a6368471cdeba191b8ba9ddc9bdce8a93063a909d2167b19b27a8cd7e2634f630bff1faf36fd6fb1108a9dc8e51fe949f4fbaaeaaa98ec8147087e5c60c65b1f355d4e62577f72b450d7d3fc878c1fb90e1be03c6f1166f738e60db958ec0cc320d6f66225861a695350dd8c84bc5ddb0d35ea8d4d4e40bd79a3e73d86cdce986ee25af6eb5447f45af3c35c11e114ee82e8da7b6aff97ad9118a732bf1489f6ad2abc4123814b4b8b0ae9400996840d66ecd7574ac539bd3ed252da0136a920844d751b5cba2a515a492e943f5d709376d0f297195d29c4316664bfc83d8aebae02e997578f3697327e6c03c2d2681767adcce4523f15331c1f4778300600e74c259666ea6893471d6b5f764d81a78c4983dbc8d75c7c09c585f8a44b71fe63c1eacf9661f646f7cea999b21c920f1a806e8f388efe2be388b2770d02cce2508b76fe0ed8a5a4afd46ab989ed553c0059d09a883dd42ced5f91d95337c475e5324803db33f61e71fc59d98894f56c19843557da9df9663438ed4678645943c2d2e2b7395464e384f00f83d7a1f3f3d748720856c9b261058c277f0ea18457355644c0d46619d658ec2e0316b643863734c3f12d9dffec598beeaf2bf3b5bd8cebc62a772e4690d14cbc0dcaabc5a9e3a865f2871fb38d7da0117ecb6ef3479b0fbb5d21e4d822e025fa149e880b87f3dcc764996284f8a19dd9eefb02afd88057ea943ab91bcf6627e94e5ae739e72dc0fa8e43bb50770e0369a8b144635dc623d93b3a55619c02c766cc75219efbbe7ff032e8d078e485aeaa2e0cbea63cb7887830dec58993f11049b22b2961ed5bf4d4878b3fb7c379b546c9a375134f48b15a1971ce9bc3fd7a7f2c0fe1010e28e0ac11b3365c102a0cc041eb12e0cc7372e6cc1dc7c6f7ddcf6fb0563eebbd3cd747a029693e0ad9784a775a4c334eeac3f3cc69551b77a5b2b9fd581fd0a3a8e87e7f96fe24e669c17d48ff5d9298330f47fd7c3361e74a3d3cf27fc474b6a6af8357812c5c663634cf9b70f1f1330a2750a04e996597f4e1d84650435c9d02788b4315d16f464312afc818d5c3ad87c7deefab369d3be3e84d30fbd728f4d5beb648db98e5ec39abb29990980 |
@@ -1,59 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using Xunit; | |||
using JT1078.Flv.MessagePack; | |||
using JT1078.Flv.Metadata; | |||
using JT1078.Flv.Extensions; | |||
namespace JT1078.Flv.Test.MessagePack | |||
{ | |||
public class FlvMessagePackWriter_FlvBody_Test | |||
{ | |||
[Fact] | |||
public void FlvMessagePackWriter_FlvBody_Test_1() | |||
{ | |||
Span<byte> buffer = new byte[1024]; | |||
FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer); | |||
FlvBody flvBody = new FlvBody() | |||
{ | |||
PreviousTagSize = 0, | |||
Tag = new FlvTags | |||
{ | |||
Type = Enums.TagType.ScriptData, | |||
DataSize = 156, | |||
DataTagsData = new Amf3 | |||
{ | |||
Amf3Metadatas = new List<Flv.Metadata.IAmf3Metadata> { | |||
new Amf3Metadata_Duration{ | |||
Value=7.22100 | |||
}, | |||
new Amf3Metadata_FileSize{ | |||
Value=2005421.00000 | |||
}, | |||
new Amf3Metadata_FrameRate{ | |||
Value=29.16667 | |||
}, | |||
new Amf3Metadata_Height{ | |||
Value=960.00000 | |||
}, | |||
new Amf3Metadata_VideoCodecId{ | |||
Value=7.00000 | |||
}, | |||
new Amf3Metadata_VideoDataRate{ | |||
Value=0.00000 | |||
}, | |||
new Amf3Metadata_Width{ | |||
Value=544.00000 | |||
} | |||
} | |||
} | |||
} | |||
}; | |||
flvMessagePackWriter.WriteFlvBody(flvBody); | |||
var hex = flvMessagePackWriter.FlushAndGetArray().ToHexString(); | |||
Assert.Equal("00000000120000A00000000000000002000A6F6E4D65746144617461080000000700086475726174696F6E00401CE24DD2F1A9FC000866696C6573697A6500413E99AD0000000000096672616D657261746500403D2AAAE297396D000668656967687400408E000000000000000C766964656F636F646563696400401C000000000000000D766964656F646174617261746500000000000000000000057769647468004081000000000000", hex); | |||
} | |||
} | |||
} |
@@ -1,15 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT1078.Flv | |||
{ | |||
public class FlvBody | |||
{ | |||
/// <summary> | |||
/// 前一个tag的长度 | |||
/// </summary> | |||
public uint PreviousTagSize { get; set; } | |||
public FlvTags Tag { get; set; } | |||
} | |||
} |
@@ -1,4 +1,5 @@ | |||
using JT1078.Flv.Enums; | |||
using JT1078.Flv.Extensions; | |||
using JT1078.Flv.H264; | |||
using JT1078.Flv.MessagePack; | |||
using JT1078.Flv.Metadata; | |||
@@ -124,7 +125,7 @@ namespace JT1078.Flv | |||
FlvArrayPool.Return(buffer); | |||
} | |||
} | |||
public byte[] CreateSecondVideoTag0Frame(FlvFrameInfo flvFrameInfo,byte[] spsRawData, byte[] ppsRawData, SPSInfo spsInfo) | |||
public byte[] CreateSecondVideoTag0Frame(byte[] spsRawData, byte[] ppsRawData, SPSInfo spsInfo) | |||
{ | |||
byte[] buffer = FlvArrayPool.Rent(2048); | |||
try | |||
@@ -134,7 +135,7 @@ namespace JT1078.Flv | |||
//flv body tag header | |||
FlvTags flvTags = new FlvTags(); | |||
flvTags.Type = TagType.Video; | |||
flvTags.Timestamp = flvFrameInfo.Interval; | |||
flvTags.Timestamp =0; | |||
flvTags.TimestampExt = 0; | |||
flvTags.StreamId = 0; | |||
//flv body tag body | |||
@@ -142,7 +143,7 @@ namespace JT1078.Flv | |||
flvTags.VideoTagsData.FrameType = FrameType.KeyFrame; | |||
flvTags.VideoTagsData.VideoData = new AvcVideoPacke(); | |||
flvTags.VideoTagsData.VideoData.AvcPacketType = AvcPacketType.SequenceHeader; | |||
flvTags.VideoTagsData.VideoData.CompositionTime = flvFrameInfo.LastIFrameInterval; | |||
flvTags.VideoTagsData.VideoData.CompositionTime = 0; | |||
AVCDecoderConfigurationRecord aVCDecoderConfigurationRecord = new AVCDecoderConfigurationRecord(); | |||
aVCDecoderConfigurationRecord.AVCProfileIndication = spsInfo.profileIdc; | |||
aVCDecoderConfigurationRecord.ProfileCompatibility = (byte)spsInfo.profileCompat; | |||
@@ -188,12 +189,12 @@ namespace JT1078.Flv | |||
if(flvFrameInfo.DataType== JT1078DataType.视频I帧) | |||
{ | |||
//cts | |||
flvTags.VideoTagsData.VideoData.CompositionTime = flvFrameInfo.LastIFrameInterval; | |||
flvTags.VideoTagsData.VideoData.CompositionTime = nALU.LastIFrameInterval; | |||
} | |||
else | |||
{ | |||
//cts | |||
flvTags.VideoTagsData.VideoData.CompositionTime = flvFrameInfo.LastFrameInterval; | |||
flvTags.VideoTagsData.VideoData.CompositionTime = nALU.LastFrameInterval; | |||
} | |||
flvTags.VideoTagsData.VideoData.MultiData = new List<byte[]>(); | |||
flvTags.VideoTagsData.VideoData.MultiData.Add(nALU.RawData); | |||
@@ -242,8 +243,6 @@ namespace JT1078.Flv | |||
if (FlvFrameInfoDict.TryGetValue(key, out FlvFrameInfo flvFrameInfo)) | |||
{ | |||
flvFrameInfo.Timestamp = naln.Timestamp; | |||
flvFrameInfo.LastIFrameInterval = naln.LastIFrameInterval; | |||
flvFrameInfo.LastFrameInterval = naln.LastFrameInterval; | |||
if (logger != null) | |||
{ | |||
if (logger.IsEnabled(LogLevel.Debug)) | |||
@@ -276,7 +275,7 @@ namespace JT1078.Flv | |||
//cache PreviousTagSize | |||
FlvFrameInfoDict.TryAdd(key, new FlvFrameInfo{ | |||
PreviousTagSize = firstFlvKeyFrame.PreviousTagSize, | |||
Interval = (uint)(pps.Timestamp- sps.Timestamp), | |||
Interval = (uint)(pps.Timestamp - sps.Timestamp), | |||
Timestamp= pps.Timestamp, | |||
} | |||
); | |||
@@ -289,9 +288,9 @@ namespace JT1078.Flv | |||
} | |||
if (logger != null) | |||
{ | |||
if (logger.IsEnabled(LogLevel.Debug)) | |||
if (logger.IsEnabled(LogLevel.Trace)) | |||
{ | |||
logger.LogDebug($"NalUnitType:{naln.NALUHeader.NalUnitType}"); | |||
logger.LogTrace($"SIM:{naln.SIM},CH:{naln.LogicChannelNumber},{naln.DataType.ToString()},NalUnitType:{naln.NALUHeader.NalUnitType},RawData:{naln.RawData.ToHexString()}"); | |||
} | |||
} | |||
//7 8 6 5 1 1 1 1 7 8 6 5 1 1 1 1 1 7 8 6 5 1 1 1 1 1 | |||
@@ -301,8 +300,6 @@ namespace JT1078.Flv | |||
case 1:// I/P/B | |||
if (FlvFrameInfoDict.TryGetValue(key, out FlvFrameInfo flvFrameInfo)) | |||
{ | |||
flvFrameInfo.LastIFrameInterval = naln.LastIFrameInterval; | |||
flvFrameInfo.LastFrameInterval = naln.LastFrameInterval; | |||
//当前的1078包与上一包1078的时间戳相减再进行累加 | |||
uint interval = (uint)(naln.Timestamp - flvFrameInfo.Timestamp); | |||
flvFrameInfo.Interval += interval; | |||
@@ -377,7 +374,7 @@ namespace JT1078.Flv | |||
//flv script tag PreviousTagSize | |||
flvMessagePackWriter.WriteUInt32((uint)scriptTagFrameBuffer.Length); | |||
//flv body video tag 0 | |||
var videoTagFrame0Buffer = CreateSecondVideoTag0Frame(flvFrameInfo, spsRawData, ppsRawData, spsInfo); | |||
var videoTagFrame0Buffer = CreateSecondVideoTag0Frame(spsRawData, ppsRawData, spsInfo); | |||
flvMessagePackWriter.WriteArray(videoTagFrame0Buffer); | |||
uint videoTag0PreviousTagSize = (uint)videoTagFrame0Buffer.Length; | |||
return (flvMessagePackWriter.FlushAndGetArray(), videoTag0PreviousTagSize); | |||
@@ -434,8 +431,6 @@ namespace JT1078.Flv | |||
public class FlvFrameInfo | |||
{ | |||
public uint PreviousTagSize { get; set; } | |||
public uint LastFrameInterval { get; set; } | |||
public uint LastIFrameInterval { get; set; } | |||
public ulong Timestamp { get; set; } | |||
public uint Interval { get; set; } | |||
public JT1078DataType DataType { get; set; } | |||
@@ -11,63 +11,64 @@ namespace JT1078.Flv.H264 | |||
{ | |||
public class H264Decoder | |||
{ | |||
/// <summary> | |||
/// | |||
/// <see cref="https://github.com/samirkumardas/jmuxer/blob/master/src/parsers/h264.js"/> | |||
/// </summary> | |||
/// <param name="package"></param> | |||
/// <returns></returns> | |||
public List<H264NALU> ParseNALU(JT1078Package package) | |||
{ | |||
List<H264NALU> units = new List<H264NALU>(); | |||
int offset = 0; | |||
(int previousOffset, int previousContentOffset) previous = (0, 0); | |||
int len = package.Bodies.Length; | |||
ReadOnlySpan<byte> tmpBuffer = package.Bodies; | |||
int index = 0; | |||
while (offset < len) | |||
Stack<H264NALU> unitsStacks = new Stack<H264NALU>(); | |||
int i=0,state=0; | |||
int? lastIndex=null; | |||
int length = package.Bodies.Length; | |||
byte value; | |||
ReadOnlySpan<byte> buffer = package.Bodies; | |||
while (i < length) | |||
{ | |||
if ((len - offset - 3) < 0 || (len - offset - 4) < 0) | |||
value = buffer[i++]; | |||
switch (state) | |||
{ | |||
if (previous.previousOffset == 0 && previous.previousContentOffset == 0) | |||
{ | |||
int startCodePrefix=4; | |||
if (tmpBuffer.Slice(0, 3).SequenceEqual(H264NALU.Start1)) | |||
case 0: | |||
if (value == 0) state = 1; | |||
break; | |||
case 1: | |||
state = value == 0 ? 2 : 0; | |||
break; | |||
case 2: | |||
case 3: | |||
if (value == 0) | |||
{ | |||
startCodePrefix = 3; | |||
state = 3; | |||
} | |||
units.Add(Create(package, tmpBuffer.Slice(offset, 1), startCodePrefix)); | |||
units[index++].RawData = tmpBuffer.ToArray(); | |||
} | |||
else | |||
{ | |||
units[index++].RawData = tmpBuffer.Slice(previous.previousContentOffset + (previous.previousOffset - previous.previousContentOffset)).ToArray(); | |||
} | |||
break; | |||
} | |||
if (tmpBuffer.Slice(offset, 3).SequenceEqual(H264NALU.Start1)) | |||
{ | |||
offset += 3; | |||
if ((offset - 3) != 0) | |||
{ | |||
units[index++].RawData = tmpBuffer.Slice(previous.previousContentOffset + 3, offset - previous.previousOffset - 3).ToArray(); | |||
} | |||
units.Add(Create(package, tmpBuffer.Slice(offset, 1), 3)); | |||
previous = (offset, offset - 3); | |||
} | |||
else if (tmpBuffer.Slice(offset, 4).SequenceEqual(H264NALU.Start2)) | |||
{ | |||
offset += 4; | |||
if ((offset - 4) != 0) | |||
{ | |||
units[index++].RawData = tmpBuffer.Slice(previous.previousContentOffset + 4, offset - previous.previousOffset - 4).ToArray(); | |||
} | |||
units.Add(Create(package, tmpBuffer.Slice(offset, 1), 4)); | |||
previous = (offset, offset - 4); | |||
} | |||
else | |||
{ | |||
offset++; | |||
else if (value == 1 && i < length) | |||
{ | |||
if (lastIndex.HasValue) | |||
{ | |||
var tmp = buffer.Slice(lastIndex.Value, i - state - 1 - lastIndex.Value); | |||
unitsStacks.Push(Create(package, tmp, state)); | |||
} | |||
lastIndex = i; | |||
state = 0; | |||
} | |||
else | |||
{ | |||
state = 0; | |||
} | |||
break; | |||
default: | |||
break; | |||
} | |||
} | |||
return units; | |||
if (lastIndex.HasValue) | |||
{ | |||
unitsStacks.Push(Create(package, buffer.Slice(lastIndex.Value), 4)); | |||
} | |||
return unitsStacks.Reverse().ToList(); | |||
} | |||
private H264NALU Create(JT1078Package package,ReadOnlySpan<byte> naluheader, int startCodePrefix) | |||
private H264NALU Create(JT1078Package package,ReadOnlySpan<byte> nalu, int startCodePrefix) | |||
{ | |||
H264NALU nALU = new H264NALU(); | |||
nALU.SIM = package.SIM; | |||
@@ -76,6 +77,7 @@ namespace JT1078.Flv.H264 | |||
nALU.LastFrameInterval = package.LastFrameInterval; | |||
nALU.LastIFrameInterval = package.LastIFrameInterval; | |||
nALU.Timestamp = package.Timestamp; | |||
nALU.RawData = nalu.ToArray(); | |||
if (startCodePrefix == 3) | |||
{ | |||
nALU.StartCodePrefix = H264NALU.Start1; | |||
@@ -84,7 +86,7 @@ namespace JT1078.Flv.H264 | |||
{ | |||
nALU.StartCodePrefix = H264NALU.Start2; | |||
} | |||
nALU.NALUHeader = new NALUHeader(naluheader); | |||
nALU.NALUHeader = new NALUHeader(nalu.Slice(0,1)); | |||
return nALU; | |||
} | |||
@@ -7,8 +7,8 @@ | |||
<Authors>SmallChi(Koike)</Authors> | |||
<PackageId>JT1078.Flv</PackageId> | |||
<Product>JT1078.Flv</Product> | |||
<Description>基于JT1078的Flv视频包</Description> | |||
<PackageReleaseNotes>基于JT1078的Flv视频包</PackageReleaseNotes> | |||
<Description>基于JT1078的Flv视频编码器</Description> | |||
<PackageReleaseNotes>基于JT1078的Flv视频编码器</PackageReleaseNotes> | |||
<RepositoryUrl>https://github.com/SmallChi/JT1078</RepositoryUrl> | |||
<PackageProjectUrl>https://github.com/SmallChi/JT1078</PackageProjectUrl> | |||
<licenseUrl>https://github.com/SmallChi/JT1078/blob/master/LICENSE</licenseUrl> | |||
@@ -9,15 +9,6 @@ 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(FlvTags tag) | |||
{ | |||
WriteByte((byte)tag.Type); | |||
@@ -39,7 +30,7 @@ namespace JT1078.Flv.MessagePack | |||
WriteAmf3(tag.DataTagsData); | |||
break; | |||
case TagType.Audio: | |||
//VIDEODATA | |||
//todo:VIDEODATA | |||
break; | |||
} | |||
WriteInt24Return(GetCurrentPosition() - DataSizePosition -3-7, DataSizePosition); | |||
@@ -31,6 +31,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT1078.Flv", "JT1078.Flv\JT | |||
EndProject | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT1078.Flv.Test", "JT1078.Flv.Test\JT1078.Flv.Test.csproj", "{D13FE092-1D11-4545-A322-9F06BCDAC0FD}" | |||
EndProject | |||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT1078.Flv.Benchmark", "JT1078.Flv.Benchmark\JT1078.Flv.Benchmark.csproj", "{5BBA68D4-53C6-4356-AAAE-ECC21B0BB8FF}" | |||
EndProject | |||
Global | |||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||
Debug|Any CPU = Debug|Any CPU | |||
@@ -77,6 +79,10 @@ Global | |||
{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 | |||
{5BBA68D4-53C6-4356-AAAE-ECC21B0BB8FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{5BBA68D4-53C6-4356-AAAE-ECC21B0BB8FF}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{5BBA68D4-53C6-4356-AAAE-ECC21B0BB8FF}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{5BBA68D4-53C6-4356-AAAE-ECC21B0BB8FF}.Release|Any CPU.Build.0 = Release|Any CPU | |||
EndGlobalSection | |||
GlobalSection(SolutionProperties) = preSolution | |||
HideSolutionNode = FALSE | |||