// RayMix Libs - RayMix's .Net Libs // Copyright 2018 Ray@raymix.net. All rights reserved. // https://www.raymix.net // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of RayMix.net. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using CScript.App; using CScript.Entity; using CScript.Utilities; using OpenCVForUnity.CoreModule; using OpenCVForUnity.ImgcodecsModule; using OpenCVForUnity.ImgprocModule; using OpenCVForUnity.UnityUtils; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; namespace CScript.Net { public struct PackageCheck { public string frameSymbols; public int frameLenght; public byte frameLastByteValue; } /// /// PackageHandler /// 数据包处理器 /// public class PackageHandler : PackageHandler { public PackageHandler(object sender) : base(sender) { } } /// /// PackageHandler /// 数据包处理器 /// /// 消息发送者类型 public class PackageHandler { //private MemoryStream stream = new MemoryStream(1024*1024*8); private MemoryStream stream = new MemoryStream(4096000); private int readOffset = 0; private T sender; NetMeshData netMeshData; private List _shortBufferList; private List _byteBufferList; //private byte[] _byteBufferArray = new byte[232643]; int totalByteCount; int lostCount; private MemoryStream _streamDataBuffer = new MemoryStream(409600 * 10); private bool _start = false; string packageTypeStr = string.Empty; Mat rgbMat; private float _decodeTime; //private Dictionary _packageCheckInfoDic; public PackageHandler(T sender) { this.sender = sender; netMeshData = new NetMeshData(); _shortBufferList = new List(); _byteBufferList = new List(); totalByteCount = 0; lostCount = 0; //_isNewData = App.AppManager.Instance.isNewMeshData; //_packageCheckInfoDic = new Dictionary(); } /// /// 接收数据到PackageHandler /// /// /// /// public void ReceiveData(byte[] data, int offset, int count) { //UnityEngine.Debug.LogError(data.Length + " $$$" + count + " " + stream.Position); // UnityEngine.Debug.LogWarning(data.Length + " $$$" + count + " " + stream.Position + " offset: " + offset + " stream.Capacity:" + stream.Capacity); if (stream.Position + count > stream.Capacity) { throw new Exception("PackageHandler write buffer overflow"); } stream.Write(data, offset, count); ParsePackageTCP(); //ParsePackage(); } public void ReceiveQuicData(byte[] data, int offset, int count) { if (_streamDataBuffer.Position + count > _streamDataBuffer.Capacity) { throw new Exception("PackageHandler write buffer overflow"); } _streamDataBuffer.Write(data, offset, count); totalByteCount += count; netMeshData.Clear(); //UnPack1(); UnityEngine.Debug.LogWarning("_streamDataBuffer.len:"+_streamDataBuffer.Length); bool isSuccess = UnPack2(); UnityEngine.Debug.LogWarning("lostCount: " + lostCount + "isSuccess:" + isSuccess); UnityEngine.Debug.LogWarning("netMeshData:"+netMeshData); if (isSuccess) { NetDistribute.Instance.Parsing(CScript.Utilities.AppUtil.Clone(netMeshData), rgbMat.clone(), totalByteCount, _decodeTime, lostCount); } netMeshData.Clear(); _streamDataBuffer.Position = 0; _streamDataBuffer.SetLength(0); totalByteCount = 0; } public void Reset() { readOffset = 0; i = 0; stream.Position = 0; stream.SetLength(0); _streamDataBuffer.Position = 0; _streamDataBuffer.SetLength(0); _start = false; } /// /// 打包消息 /// /// /// public static byte[] PackMessage() { byte[] package = null; using (MemoryStream ms = new MemoryStream()) { //ProtoBuf.Serializer.Serialize(ms, message); package = new byte[ms.Length + 4]; Buffer.BlockCopy(BitConverter.GetBytes(ms.Length), 0, package, 0, 4); Buffer.BlockCopy(ms.GetBuffer(), 0, package, 4, (int)ms.Length); } return package; } ///// ///// 提取消息 ///// ///// ///// ///// ///// //public static SkillBridge.Message.NetMessage UnpackMessage(byte[] packet,int offset,int length) //{ // SkillBridge.Message.NetMessage message = null; // using (MemoryStream ms = new MemoryStream(packet, offset, length)) // { // message = ProtoBuf.Serializer.Deserialize(ms); // } // return message; //} int i; private int _frameIndex; bool ParsePackageTCP() { if (!_start) { while (readOffset + 20 < stream.Position) { packageTypeStr = System.Text.Encoding.ASCII.GetString(stream.GetBuffer(), readOffset + 0, 1); packageTypeStr += stream.GetBuffer()[readOffset + 1].ToString(); packageTypeStr += System.Text.Encoding.ASCII.GetString(stream.GetBuffer(), readOffset + 2, 1); packageTypeStr += System.Text.Encoding.ASCII.GetString(stream.GetBuffer(), readOffset + 3, 1); // UnityEngine.Debug.Log(packageTypeStr); if (packageTypeStr == "$1@@") { _start = true; break; } else { readOffset+=1; } } } else { if (readOffset + 20 < stream.Position) { int packageSize = BitConverter.ToInt32(stream.GetBuffer(), readOffset + 16); if (packageSize + readOffset + 20 <= stream.Position) { _start = false; _streamDataBuffer.Position = 0; _streamDataBuffer.SetLength(0); _streamDataBuffer.Write(stream.GetBuffer(), readOffset + 20, packageSize); netMeshData.Clear(); UnPack2(); NetDistribute.Instance.Parsing(CScript.Utilities.AppUtil.Clone(netMeshData), rgbMat.clone(), totalByteCount, _decodeTime, 0); netMeshData.Clear(); totalByteCount = 0; _frameIndex = 0; this.readOffset += (packageSize + 20); return ParsePackageTCP(); } } } //未接收完/要结束了 if (this.readOffset > 0) { long size = stream.Position - this.readOffset; if (this.readOffset < stream.Position) { Array.Copy(stream.GetBuffer(), this.readOffset, stream.GetBuffer(), 0, stream.Position - this.readOffset); } //Reset Stream this.readOffset = 0; stream.Position = size; stream.SetLength(size); //UnityEngine.Debug.LogWarning("stream.Position: "+stream.Position+" "+ stream.Length); netMeshData.Clear(); } return true; } /// /// 数据包解析 /// /// bool ParsePackage() { if (!_start) { while (readOffset + 13 < stream.Position) { packageTypeStr = System.Text.Encoding.UTF8.GetString(stream.GetBuffer(), readOffset + 0, 1); if (packageTypeStr == "#") { _start = true; break; } else { readOffset++; } } } if (_start) { //UnityEngine.Debug.LogWarning("_start"); if (readOffset + 13 < stream.Position) { packageTypeStr = System.Text.Encoding.UTF8.GetString(stream.GetBuffer(), readOffset + 0, 1); int packageSize = BitConverter.ToInt32(stream.GetBuffer(), readOffset + 9); //UnityEngine.Debug.LogWarning(readOffset + " " + stream.Position + " " + packageSize+" "+ packageTypeStr); if (packageSize + readOffset + 13 <= stream.Position) { if (packageTypeStr == "#") { // _packageCheckInfoDic.Clear(); _frameIndex = 0; // UnityEngine.Debug.LogWarning("#"); _streamDataBuffer.Position = 0; _streamDataBuffer.SetLength(0); //UnityEngine.Debug.LogWarning("#:"+packageSize); _streamDataBuffer.Write(stream.GetBuffer(), readOffset + 13, packageSize); } else if (packageTypeStr == "@") { // UnityEngine.Debug.LogWarning("@"); _streamDataBuffer.Write(stream.GetBuffer(), readOffset + 13, packageSize); } else if (packageTypeStr == "$") { _start = false; _streamDataBuffer.Write(stream.GetBuffer(), readOffset + 13, packageSize); //byte[] unzipData = lz4.Decompress(_streamDataBuffer.GetBuffer()); i++; netMeshData.Clear(); if (AppConfig.isNewMeshData) { UnPack2(); } else { UnPack1(); } NetDistribute.Instance.Parsing(CScript.Utilities.AppUtil.Clone(netMeshData), rgbMat.clone(), totalByteCount, _decodeTime,0); netMeshData.Clear(); totalByteCount = 0; _frameIndex = 0; } this.readOffset += (packageSize + 13); return ParsePackage(); } } } //未接收完/要结束了 if (this.readOffset > 0) { long size = stream.Position - this.readOffset; if (this.readOffset < stream.Position) { Array.Copy(stream.GetBuffer(), this.readOffset, stream.GetBuffer(), 0, stream.Position - this.readOffset); } //Reset Stream this.readOffset = 0; stream.Position = size; stream.SetLength(size); //UnityEngine.Debug.LogWarning("stream.Position: "+stream.Position+" "+ stream.Length); netMeshData.Clear(); } return true; } private void UnPack1() { int bufferOffset = 0; //包有效 //总长度 ulong totalLenght = BitConverter.ToUInt64(_streamDataBuffer.GetBuffer(), bufferOffset); bufferOffset += sizeof(UInt64); // rgb size uint rgbSize = BitConverter.ToUInt32(_streamDataBuffer.GetBuffer(), bufferOffset) * 6; bufferOffset += sizeof(UInt32); _shortBufferList.Clear(); _shortBufferList.TrimExcess(); _shortBufferList.Capacity = (int)rgbSize; // rgb 内容 for (int i = 0; i < rgbSize; i++) { _shortBufferList.Add(BitConverter.ToInt16(_streamDataBuffer.GetBuffer(), bufferOffset)); bufferOffset += sizeof(Int16); } uint vertexCount = rgbSize / 6; netMeshData.netSideVertexList.Capacity = (int)vertexCount * 3; netMeshData.netColorList.Capacity = (int)vertexCount * 3; // 顶点数据和颜色 for (int i = 0; i < vertexCount; i++) { netMeshData.netSideVertexList.Add(_shortBufferList[i * 6 + 0]); netMeshData.netSideVertexList.Add(_shortBufferList[i * 6 + 1]); netMeshData.netSideVertexList.Add(_shortBufferList[i * 6 + 2]); netMeshData.netColorList.Add(_shortBufferList[i * 6 + 3]); netMeshData.netColorList.Add(_shortBufferList[i * 6 + 4]); netMeshData.netColorList.Add(_shortBufferList[i * 6 + 5]); } // 三角形 UInt64 indices_len_rgb = BitConverter.ToUInt64(_streamDataBuffer.GetBuffer(), bufferOffset); bufferOffset += sizeof(UInt64); if (indices_len_rgb > Int32.MaxValue) { //UnityEngine.Debug.Log("totalLenght:"+ totalLenght+" indices_len_rgb:" + indices_len_rgb); UnityEngine.Debug.Log($"totalLenght:{totalLenght} rgbSize:{rgbSize} indices_len_rgb:{indices_len_rgb}"); } netMeshData.netSideTriangles.Capacity = (int)indices_len_rgb; for (ulong i = 0; i < indices_len_rgb; i++) { netMeshData.netSideTriangles.Add(BitConverter.ToUInt16(_streamDataBuffer.GetBuffer(), bufferOffset)); bufferOffset += sizeof(Int16); } int ys_width_len = BitConverter.ToInt32(_streamDataBuffer.GetBuffer(), bufferOffset); bufferOffset += sizeof(Int32); int ys_height_len = BitConverter.ToInt32(_streamDataBuffer.GetBuffer(), bufferOffset); bufferOffset += sizeof(Int32); netMeshData.width = ys_width_len; netMeshData.height = ys_height_len; // 前面顶点长度 UInt32 vertexes_len = BitConverter.ToUInt32(_streamDataBuffer.GetBuffer(), bufferOffset); if (vertexes_len > Int32.MaxValue) { UnityEngine.Debug.Log(" vertexes_len*5:" + vertexes_len * 5); } UInt32 xyzuvs_size = vertexes_len * 5; bufferOffset += sizeof(UInt32); _shortBufferList.Clear(); _shortBufferList.TrimExcess(); _shortBufferList.Capacity = (int)xyzuvs_size; for (int i = 0; i < xyzuvs_size; i++) { _shortBufferList.Add(BitConverter.ToInt16(_streamDataBuffer.GetBuffer(), bufferOffset)); bufferOffset += sizeof(Int16); } netMeshData.netUvList.Capacity = (int)vertexes_len * 2; netMeshData.netFrontVertexList.Capacity = (int)vertexes_len * 3; vertexCount = xyzuvs_size / 5; // 前面顶点 和 uv for (int i = 0; i < vertexCount; i++) { netMeshData.netFrontVertexList.Add(_shortBufferList[i * 5 + 0]); netMeshData.netFrontVertexList.Add(_shortBufferList[i * 5 + 1]); netMeshData.netFrontVertexList.Add(_shortBufferList[i * 5 + 2]); netMeshData.netUvList.Add(_shortBufferList[i * 5 + 3]); netMeshData.netUvList.Add(_shortBufferList[i * 5 + 4]); } _shortBufferList.Clear(); _shortBufferList.TrimExcess(); UInt64 indices_len = BitConverter.ToUInt64(_streamDataBuffer.GetBuffer(), bufferOffset); bufferOffset += sizeof(UInt64); // 前面三角 netMeshData.netFrontTriangles.Capacity = (int)indices_len; for (ulong i = 0; i < indices_len; i++) { netMeshData.netFrontTriangles.Add(BitConverter.ToUInt16(_streamDataBuffer.GetBuffer(), bufferOffset)); bufferOffset += sizeof(ushort); } // 贴图数据 int imageYEncoderSize = BitConverter.ToInt32(_streamDataBuffer.GetBuffer(), bufferOffset); bufferOffset += sizeof(int);// y byte size //netMeshData.netTexture.Capacity = imageYEncoderSize; _byteBufferList.Clear(); _byteBufferList.Capacity = imageYEncoderSize; //byte temp; for (int i = 0; i < imageYEncoderSize; i++) { _byteBufferList.Add(_streamDataBuffer.GetBuffer()[bufferOffset++]); } DecodeImageMat(_byteBufferList.ToArray(),out rgbMat); } private bool UnPack2() { int bufferOffset = 0; //总长度 ulong totalLenght = BitConverter.ToUInt64(_streamDataBuffer.GetBuffer(), bufferOffset); bufferOffset += sizeof(UInt64); int realCount = 0; // atlsaXyz size uint atlasXyzBufferLenght = BitConverter.ToUInt32(_streamDataBuffer.GetBuffer(), bufferOffset); if (atlasXyzBufferLenght > 1000000) { lostCount++; return false; } bufferOffset += sizeof(UInt32); realCount = (int)(atlasXyzBufferLenght / sizeof(Int16)); //UnityEngine.Debug.LogWarning("0 realCount:" + realCount); netMeshData.netAtlasVertexList.Capacity = (int)realCount; for (int i = 0; i < realCount; i++) { netMeshData.netAtlasVertexList.Add(BitConverter.ToInt16(_streamDataBuffer.GetBuffer(), bufferOffset)); bufferOffset += sizeof(Int16); } //atlasUv size uint atlasUvBufferLenght = BitConverter.ToUInt32(_streamDataBuffer.GetBuffer(), bufferOffset); if (atlasUvBufferLenght > 1000000) { lostCount++; return false; } bufferOffset += sizeof(UInt32); realCount = (int)(atlasUvBufferLenght / sizeof(UInt16)); //UnityEngine.Debug.LogWarning("1realCount:"+ realCount); netMeshData.netAtlasUVList.Capacity = (int)realCount; for (int i = 0; i < realCount; i++) { //UnityEngine.Debug.LogError(BitConverter.ToUInt16(_streamDataBuffer.GetBuffer(), bufferOffset)); netMeshData.netAtlasUVList.Add(BitConverter.ToUInt16(_streamDataBuffer.GetBuffer(), bufferOffset)); bufferOffset += sizeof(UInt16); } //atlasDices size uint atlasIndicesBufferLenght = BitConverter.ToUInt32(_streamDataBuffer.GetBuffer(), bufferOffset); if (atlasIndicesBufferLenght > 1000000) { lostCount++; return false; } bufferOffset += sizeof(UInt32); realCount = (int)(atlasIndicesBufferLenght / sizeof(UInt16)); //UnityEngine.Debug.LogWarning("2realCount:" + realCount); netMeshData.netTrianglesList.Capacity = (int)realCount; for (int i = 0; i < realCount; i++) { netMeshData.netTrianglesList.Add(BitConverter.ToUInt16(_streamDataBuffer.GetBuffer(), bufferOffset)); bufferOffset += sizeof(UInt16); } // 贴图数据 uint atlasImageBufferLenght = BitConverter.ToUInt32(_streamDataBuffer.GetBuffer(), bufferOffset); if (atlasImageBufferLenght > 1000000) { lostCount++; return false; } bufferOffset += sizeof(UInt32);// y byte size //netMeshData.netTexture.Capacity = imageYEncoderSize; _byteBufferList.Clear(); realCount = (int)(atlasImageBufferLenght / sizeof(byte)); //UnityEngine.Debug.LogWarning("3 realCount:" + realCount); _byteBufferList.Capacity = (int)realCount; //byte temp; for (int i = 0; i < realCount; i++) { _byteBufferList.Add(_streamDataBuffer.GetBuffer()[bufferOffset++]); } DecodeImageMat(_byteBufferList.ToArray(), out rgbMat); //nosexyzrgb uint noseXyzrgbBufferLenght = BitConverter.ToUInt32(_streamDataBuffer.GetBuffer(), bufferOffset); if (noseXyzrgbBufferLenght > 1000000) { lostCount++; return false; } bufferOffset += sizeof(UInt32); realCount = (int)(noseXyzrgbBufferLenght / sizeof(short)); _shortBufferList.Clear(); _shortBufferList.TrimExcess(); //UnityEngine.Debug.LogWarning("4 realCount:" + realCount); _shortBufferList.Capacity = (int)realCount; // nosexyzrgb 内容 for (int i = 0; i < realCount; i++) { _shortBufferList.Add(BitConverter.ToInt16(_streamDataBuffer.GetBuffer(), bufferOffset)); bufferOffset += sizeof(Int16); } uint vertexCount = (uint)realCount / 6; netMeshData.netSideVertexList.Capacity = (int)vertexCount * 3; netMeshData.netColorList.Capacity = (int)vertexCount * 3; // 顶点数据和颜色 for (int i = 0; i < vertexCount; i++) { netMeshData.netNoseVertexList.Add(_shortBufferList[i * 6 + 0]); netMeshData.netNoseVertexList.Add(_shortBufferList[i * 6 + 1]); netMeshData.netNoseVertexList.Add(_shortBufferList[i * 6 + 2]); netMeshData.netNoseColorList.Add(_shortBufferList[i * 6 + 3]); netMeshData.netNoseColorList.Add(_shortBufferList[i * 6 + 4]); netMeshData.netNoseColorList.Add(_shortBufferList[i * 6 + 5]); } //nosexyzrgb uint noseIndicesBufferLenght = BitConverter.ToUInt32(_streamDataBuffer.GetBuffer(), bufferOffset); if (noseIndicesBufferLenght > 1000000) { lostCount++; return false; } bufferOffset += sizeof(UInt32); realCount = (int)(noseIndicesBufferLenght / sizeof(ushort)); // UnityEngine.Debug.LogWarning("5 realCount:" + realCount); netMeshData.netNoseTriangles.Capacity = (int)realCount; for (int i = 0; i < realCount; i++) { netMeshData.netNoseTriangles.Add(BitConverter.ToUInt16(_streamDataBuffer.GetBuffer(), bufferOffset)); bufferOffset += sizeof(UInt16); } return true; } private bool CheckSum(Dictionary packageCheckDic, ulong checksums) { UInt64 checkNumLocak = 0; packageCheckDic.Values.ToList().ForEach(pcidValue => { checkNumLocak += (ulong)pcidValue.frameLenght; checkNumLocak += (ulong)pcidValue.frameLastByteValue; }); //UnityEngine.Debug.LogError(checkNumLocak); if (checkNumLocak == checksums) { return true; } return false; } Stopwatch watch = new Stopwatch(); private void DecodeImageMat(byte[] imageRgbByte, out Mat imageRGBMat) { MatOfByte matOfByte = new MatOfByte(imageRgbByte); Mat yuv; // using (ProTimer p = new ProTimer("Imgcodecs.imdecode")) { //p._runTime watch.Start(); yuv = Imgcodecs.imdecode(matOfByte, -1); watch.Stop(); _decodeTime = watch.ElapsedMilliseconds; watch.Reset(); } imageRGBMat = new Mat(yuv.rows(), yuv.cols(), CvType.CV_8UC3); Imgproc.cvtColor(yuv, imageRGBMat, Imgproc.COLOR_BGR2RGB); } } }