Unity3D开发技术研究(FMETP STREAM)实时画面传输插件使用

一、框架视图





二、关键代码

FMNetworkManager

using UnityEngine;
using UnityEngine.UI;
using System;


using System.Net;
using System.Net.Sockets;
using System.Net.NetworkInformation;

public enum FMNetworkType { Server, Client }
public enum FMSendType { All, Server, Others, TargetIP }
public struct FMPacket
{
    public byte[] SendByte;
    public string SkipIP;
    public FMSendType SendType;
    public string TargetIP;
}
public struct FMNetworkTransform
{
    public Vector3 position;
    public Quaternion rotation;
    public Vector3 localScale;
}

public class FMNetworkManager : MonoBehaviour
{
    public string LocalIPAddress()
    {
        string localIP = "0.0.0.0";
        //ssIPHostEntry host;
        //host = Dns.GetHostEntry(Dns.GetHostName());

        foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
        {
            if (ni.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 || ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
            {
                foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
                {
                    if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
                    {
                        if (ip.IsDnsEligible)
                        {
                            try
                            {
                                if (ip.AddressValidLifetime / 2 != int.MaxValue)
                                {
                                    localIP = ip.Address.ToString();
                                    break;
                                }
                                else
                                {
                                    //if didn't find any yet, this is the only one
                                    if (localIP == "0.0.0.0") localIP = ip.Address.ToString();
                                }
                            }
                            catch (Exception e)
                            {
                                localIP = ip.Address.ToString();
                                //Debug.Log("LocalIPAddress(): " + e.ToString());
                                break;
                            }
                        }
                    }
                }
            }
        }
        return localIP;
    }

    private string _localIP;
    public string ReadLocalIPAddress
    {
        get
        {
            if(_localIP == null) _localIP = LocalIPAddress();
            if (_localIP.Length <= 3) _localIP = LocalIPAddress();
            return _localIP;
        }
    }

    public static FMNetworkManager instance;
    public bool AutoInit = true;

    [HideInInspector]
    public bool Initialised = false;

    [Tooltip("Initialise as Server or Client")]
    public FMNetworkType NetworkType;

    [HideInInspector]
    public FMServer Server;
    [HideInInspector]
    public FMClient Client;

    [System.Serializable]
    public class FMServerSettings
    {
        public int ServerListenPort = 3333;

        [Tooltip("(( on supported devices only ))")]
        public bool UseAsyncListener = false;

        [Tooltip("(( suggested for low-end mobile, but not recommend for streaming large data ))")]
        public bool UseMainThreadSender = true;
        public int ConnectionCount;
    }

    [System.Serializable]
    public class FMClientSettings
    {
        public int ClientListenPort = 3334;

        [Tooltip("(( suggested for low-end mobile, but not recommend for streaming large data ))")]
        public bool UseMainThreadSender = true;

        [Tooltip("(( true by default ))")]
        public bool AutoNetworkDiscovery = true;
        [Tooltip("(( only applied when Auto Network Discovery is off ))")]
        public string ServerIP;
        public bool IsConnected;
    }

    [Tooltip("Network Settings for Server")]
    public FMServerSettings ServerSettings;
    [Tooltip("Network Settings for Client")]
    public FMClientSettings ClientSettings;


    public bool ShowLog = true;
    [TextArea(1, 10)]
    public string Status;
    public Text UIStatus;

    public UnityEventByteArray OnReceivedByteDataEvent;
    public UnityEventString OnReceivedStringDataEvent;
    public UnityEventByteArray GetRawReceivedData;

    #region Network Objects Setup
    [Header("[ Sync ] Server => Client")]
    [Tooltip("Sync Transformation of Network Objects. # Both Server and Clients should have same number of NetworkObjects")]
    public GameObject[] NetworkObjects;
    FMNetworkTransform[] NetworkTransform;

    //[Tooltip("Frequency for sync (second)")]
    float SyncFrequency = 0.05f;
    [Range(1f, 60f)]
    public float SyncFPS = 20f;
    float SyncTimer = 0f;

    float LastReceivedTimestamp = 0f;
    float TargetTimestamp = 0f;
    float CurrentTimestamp = 0f;

    void Action_SendNetworkObjectTransform()
    {
        if (NetworkType == FMNetworkType.Server)
        {
            byte[] Timestamp = BitConverter.GetBytes(Time.realtimeSinceStartup);

            byte[] Data = new byte[NetworkObjects.Length * 10 * 4];
            byte[] SendByte = new byte[Timestamp.Length + Data.Length];

            int index = 0;
            Buffer.BlockCopy(Timestamp, 0, SendByte, index, Timestamp.Length);
            index += Timestamp.Length;

            foreach (GameObject obj in NetworkObjects)
            {
                byte[] TransformByte = EncodeTransformByte(obj);
                Buffer.BlockCopy(TransformByte, 0, SendByte, index, TransformByte.Length);
                index += TransformByte.Length;
            }
            Server.Action_AddNetworkObjectPacket(SendByte, FMSendType.Others);
        }
    }

    byte[] EncodeTransformByte(GameObject obj)
    {
        byte[] _byte = new byte[40];
        Vector3 _pos = obj.transform.position;
        Quaternion _rot = obj.transform.rotation;
        Vector3 _scale = obj.transform.localScale;

        float[] _float = new float[]
        {
            _pos.x,_pos.y,_pos.z,
            _rot.x,_rot.y,_rot.z,_rot.w,
            _scale.x,_scale.y,_scale.z
        };
        Buffer.BlockCopy(_float, 0, _byte, 0, _byte.Length);
        return _byte;
    }

    float[] DecodeByteToFloatArray(byte[] _data, int _offset)
    {
        float[] _transform = new float[10];
        for (int i = 0; i < _transform.Length; i++)
        {
            _transform[i] = BitConverter.ToSingle(_data, i * 4 + _offset);
        }


        return _transform;
    }

    //float LastReceiveTime = 0f;
    //public int _fps = 0;
    public void Action_SyncNetworkObjectTransform(byte[] _data)
    {
        //_fps = (int)((1f / (Time.realtimeSinceStartup - LastReceiveTime)));
        //LastReceiveTime = Time.realtimeSinceStartup;
        //Debug.Log(_fps);

        float Timestamp = BitConverter.ToSingle(_data, 0);
        int meta_offset = 4;

        if (Timestamp > LastReceivedTimestamp)
        {
            LastReceivedTimestamp = TargetTimestamp;
            TargetTimestamp = Timestamp;
            CurrentTimestamp = LastReceivedTimestamp;

            for (int i = 0; i < NetworkObjects.Length; i++)
            {
                float[] _transform = DecodeByteToFloatArray(_data, meta_offset + i * 40);
                NetworkTransform[i].position = new Vector3(_transform[0], _transform[1], _transform[2]);
                NetworkTransform[i].rotation = new Quaternion(_transform[3], _transform[4], _transform[5], _transform[6]);
                NetworkTransform[i].localScale = new Vector3(_transform[7], _transform[8], _transform[9]);
            }
        }


    }
    #endregion

    public void Action_InitAsServer()
    {
        NetworkType = FMNetworkType.Server;
        Init();
    }

    public void Action_InitAsClient()
    {
        NetworkType = FMNetworkType.Client;
        Init();
    }

    void Init()
    {
        if (NetworkType == FMNetworkType.Server)
        {
            Server = this.gameObject.AddComponent();
            Server.Manager = this;

            Server.ServerListenPort = ServerSettings.ServerListenPort;
            Server.ClientListenPort = ClientSettings.ClientListenPort;

            Server.UseAsyncListener = ServerSettings.UseAsyncListener;
            Server.UseMainThreadSender = ServerSettings.UseMainThreadSender;
        }
        else
        {
            Client = this.gameObject.AddComponent();
            Client.Manager = this;

            Client.ServerListenPort = ServerSettings.ServerListenPort;
            Client.ClientListenPort = ClientSettings.ClientListenPort;

            Client.UseMainThreadSender = ClientSettings.UseMainThreadSender;
            Client.AutoNetworkDiscovery = ClientSettings.AutoNetworkDiscovery;
            if (ClientSettings.ServerIP == "") ClientSettings.ServerIP = "127.0.0.1";
            if (!Client.AutoNetworkDiscovery) Client.ServerIP = ClientSettings.ServerIP;

            NetworkTransform = new FMNetworkTransform[NetworkObjects.Length];
            for (int i = 0; i < NetworkTransform.Length; i++)
            {
                NetworkTransform[i] = new FMNetworkTransform();
                NetworkTransform[i].position = Vector3.zero;
                NetworkTransform[i].rotation = Quaternion.identity;
                NetworkTransform[i].localScale = new Vector3(1f, 1f, 1f);
            }
        }

        Initialised = true;
    }

    void Awake()
    {
        Application.runInBackground = true;
        if (instance == null) instance = this;
    }

    //void Awake()
    //{
    //    if (instance == null)
    //    {
    //        instance = this;
    //        this.gameObject.transform.parent = null;
    //        DontDestroyOnLoad(this.gameObject);
    //    }
    //    else
    //    {
    //        Destroy(this.gameObject);
    //    }
    //}

    // Use this for initialization
    void Start()
    {
        if (AutoInit) Init();
    }

    // Update is called once per frame
    void Update()
    {
        if (Initialised == false) return;

        //====================Sync Network Object============================
        #region Sync Network Objects
        if (NetworkType == FMNetworkType.Server)
        {
            //on Server
            if (Server.ConnectionCount > 0)
            {
                if (NetworkObjects.Length > 0)
                {
                    SyncFrequency = 1f / SyncFPS;
                    SyncTimer += Time.deltaTime;
                    if (SyncTimer > SyncFrequency)
                    {
                        Action_SendNetworkObjectTransform();
                        SyncTimer = SyncTimer % SyncFrequency;
                    }
                }
            }
            Server.ShowLog = ShowLog;
        }
        else
        {
            //on Client
            if (Client.IsConnected)
            {
                if (NetworkObjects.Length > 0)
                {
                    for (int i = 0; i < NetworkObjects.Length; i++)
                    {
                        CurrentTimestamp += Time.deltaTime;
                        float step = (CurrentTimestamp - LastReceivedTimestamp) / (TargetTimestamp - LastReceivedTimestamp);
                        step = Mathf.Clamp(step, 0f, 1f);
                        NetworkObjects[i].transform.position = Vector3.Slerp(NetworkObjects[i].transform.position, NetworkTransform[i].position, step);
                        NetworkObjects[i].transform.rotation = Quaternion.Slerp(NetworkObjects[i].transform.rotation, NetworkTransform[i].rotation, step);
                        NetworkObjects[i].transform.localScale = Vector3.Slerp(NetworkObjects[i].transform.localScale, NetworkTransform[i].localScale, step);
                    }
                }
            }
            Client.ShowLog = ShowLog;
        }
        #endregion
        //====================Sync Network Object============================

        //====================Update Debug Text============================
        #region Debug Status
        string _status = "";
        _status += "Thread: " + Loom.numThreads + " / " + Loom.maxThreads + "\n";
        _status += "Network Type: " + NetworkType.ToString() + "\n";
        _status += "Local IP: " + ReadLocalIPAddress + "\n";

        if (NetworkType == FMNetworkType.Server)
        {
            ServerSettings.ConnectionCount = Server.ConnectionCount;

            _status += "Connection Count: " + ServerSettings.ConnectionCount + "\n";
            _status += "Async Listener: " + ServerSettings.UseAsyncListener + "\n";
            _status += "Use Main Thread Sender: " + ServerSettings.UseMainThreadSender + "\n";

            foreach (FMServer.ConnectedClient _cc in Server.ConnectedClients)
            {
                if (_cc != null)
                {
                    _status += "connected ip: " + _cc.IP + "\n";

                    _status += "last seen: " + _cc.LastSeenTimeMS + "\n";
                    _status += "last send: " + _cc.LastSentTimeMS + "\n";
                }
                else
                {
                    _status += "Connected Client: null/unknown issue" + "\n";
                }
            }
        }
        else
        {
            ClientSettings.IsConnected = Client.IsConnected;

            _status += "Is Connected: " + ClientSettings.IsConnected + "\n";
            _status += "Use Main Thread Sender: " + ClientSettings.UseMainThreadSender + "\n";

            _status += "last send: " + Client.LastSentTimeMS + "\n";
            _status += "last received: " + Client.LastReceivedTimeMS + "\n";
        }

        Status = _status;
        if (UIStatus != null) UIStatus.text = Status;
        #endregion
        //====================Update Debug Text============================
    }

    #region SENDER MAPPING
    public void Send(byte[] _byteData, FMSendType _type){Send(_byteData, _type, null);}
    public void Send(string _stringData, FMSendType _type){Send(_stringData, _type, null);}

    public void SendToAll(byte[] _byteData){Send(_byteData, FMSendType.All, null);}
    public void SendToServer(byte[] _byteData){Send(_byteData, FMSendType.Server, null);}
    public void SendToOthers(byte[] _byteData){Send(_byteData, FMSendType.Others, null);}

    public void SendToAll(string _stringData){Send(_stringData, FMSendType.All, null);}
    public void SendToServer(string _stringData){Send(_stringData, FMSendType.Server, null);}
    public void SendToOthers(string _stringData){Send(_stringData, FMSendType.Others, null);}

    public void SendToTarget(byte[] _byteData, string _targetIP)
    {
        if (_targetIP == ReadLocalIPAddress || _targetIP == "127.0.0.1" || _targetIP == "localhost")
        {
            OnReceivedByteDataEvent.Invoke(_byteData);
        }
        else
        {
            Send(_byteData, FMSendType.TargetIP, _targetIP);
        }
    }
    public void SendToTarget(string _stringData, string _targetIP)
    {
        if (_targetIP == ReadLocalIPAddress || _targetIP == "127.0.0.1" || _targetIP == "localhost")
        {
            OnReceivedStringDataEvent.Invoke(_stringData);
        }
        else
        {
            Send(_stringData, FMSendType.TargetIP, _targetIP);
        }
    }

    private void Send(byte[] _byteData, FMSendType _type, string _targetIP)
    {
        if (!Initialised) return;
        if (NetworkType == FMNetworkType.Client && !Client.IsConnected) return;

        switch (_type)
        {
            case FMSendType.All:
                if (NetworkType == FMNetworkType.Server)
                {
                    Server.Action_AddPacket(_byteData, _type);
                    OnReceivedByteDataEvent.Invoke(_byteData);
                }
                else
                {
                    Client.Action_AddPacket(_byteData, _type);
                }
                break;
            case FMSendType.Server:
                if (NetworkType == FMNetworkType.Server)
                {
                    OnReceivedByteDataEvent.Invoke(_byteData);
                }
                else
                {
                    Client.Action_AddPacket(_byteData, _type);
                }
                break;
            case FMSendType.Others:
                if (NetworkType == FMNetworkType.Server)
                {
                    Server.Action_AddPacket(_byteData, _type);
                }
                else
                {
                    Client.Action_AddPacket(_byteData, _type);
                }
                break;
            case FMSendType.TargetIP:
                if (NetworkType == FMNetworkType.Server)
                {
                    if(_targetIP.Length > 4) Server.Action_AddPacket(_byteData, _targetIP);
                }
                else
                {
                    if (_targetIP.Length > 4) Client.Action_AddPacket(_byteData, _targetIP);
                }
                break;
        }
    }

    private void Send(string _stringData, FMSendType _type, string _targetIP)
    {
        if (!Initialised) return;
        if (NetworkType == FMNetworkType.Client && !Client.IsConnected) return;

        switch (_type)
        {
            case FMSendType.All:
                if (NetworkType == FMNetworkType.Server)
                {
                    Server.Action_AddPacket(_stringData, _type);
                    OnReceivedStringDataEvent.Invoke(_stringData);
                }
                else
                {
                    Client.Action_AddPacket(_stringData, _type);
                }
                break;
            case FMSendType.Server:
                if (NetworkType == FMNetworkType.Server)
                {
                    OnReceivedStringDataEvent.Invoke(_stringData);
                }
                else
                {
                    Client.Action_AddPacket(_stringData, _type);
                }
                break;
            case FMSendType.Others:
                if (NetworkType == FMNetworkType.Server)
                {
                    Server.Action_AddPacket(_stringData, _type);
                }
                else
                {
                    Client.Action_AddPacket(_stringData, _type);
                }
                break;
            case FMSendType.TargetIP:
                if (NetworkType == FMNetworkType.Server)
                {
                    if (_targetIP.Length > 6) Server.Action_AddPacket(_stringData, _targetIP);
                }
                else
                {
                    if (_targetIP.Length > 6) Client.Action_AddPacket(_stringData, _targetIP);
                }
                break;
        }
    }

    #endregion

    public void Action_ReloadScene()
    {
        UnityEngine.SceneManagement.SceneManager.LoadScene(UnityEngine.SceneManagement.SceneManager.GetActiveScene().name);
    }

}


FMNetwork_Demo

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Text;
using UnityEngine.UI;

public class FMNetwork_Demo : MonoBehaviour {

    public Text ServerText;
    public Text ClientText;

    public void Action_ProcessStringData(string _string)
    {
        if(FMNetworkManager.instance.NetworkType == FMNetworkType.Server)
        {
            if (ServerText != null) ServerText.text = "Server Received : " + _string;
        }
        else
        {
            if (ClientText != null) ClientText.text = "Client Received : " + _string;
        }
    }

    public void Action_ProcessByteData(byte[] _byte)
    {
        if (FMNetworkManager.instance.NetworkType == FMNetworkType.Server)
        {
            if (ServerText != null) ServerText.text = "Server Received byte[] : " + _byte.Length;
        }
        else
        {
            if (ClientText != null) ClientText.text = "Client Received byte[]: " + _byte.Length;
        }
    }

    public void Action_ShowRawByteLength(byte[] _byte)
    {
        Debug.Log("get byte length: " + _byte.Length);
    }

    // Use this for initialization
    void Start () {
        if (Box1 != null) StartPosBox1 = Box1.transform.position;
        if (Box2 != null) StartPosBox2 = Box2.transform.position;
    }

    public GameObject Box1;
    public GameObject Box2;
    public Vector3 StartPosBox1;
    public Vector3 StartPosBox2;
    public Toggle toggle;

    public LargeFileEncoder LFE;
    public Text LFE_text;

    [Space]
    [Header("[New] Send To Target IP")]
    public string TargetIP = "127.0.0.1";
    public void Action_SetTargetIP(string _targetIP) { TargetIP = _targetIP; }

    public void Action_SendRandomLargeFile()
    {
        LFE.Action_SendLargeByte(new byte[(int)(1024f * 1024f * ((int)Random.Range(2, 4)))]);
    }
    public void Action_DemoReceivedLargeFile(byte[] _data)
    {
        //LFE_text.text = (float)_data.Length/(float)(1024*1024) + " MB";
    }

    private void Update()
    {
        if (FMNetworkManager.instance.NetworkType == FMNetworkType.Server)
        {
            if (toggle.isOn)
            {
                if (Box1 != null && Box2 != null)
                {
                    Box1.transform.Rotate(new Vector3(0f, Time.deltaTime * 15f, 0f));
                    Box1.transform.position = new Vector3(Mathf.Sin(Time.realtimeSinceStartup), 0f, 0f) + StartPosBox1;
                    Box1.transform.localScale = new Vector3(1f, 1f, 1f) * (1f + 0.5f * Mathf.Sin(Time.realtimeSinceStartup * 3f));

                    Box2.transform.Rotate(new Vector3(0f, Time.deltaTime * 30f, 0f));
                    Box2.transform.position = new Vector3(Mathf.Sin(Time.realtimeSinceStartup * 0.5f), 0f, -1f) + StartPosBox2;
                    Box2.transform.localScale = new Vector3(1f, 1f, 1f) * (1f + 0.5f * Mathf.Sin(Time.realtimeSinceStartup * 2f));
                }
            }
        }
    }

    public void Action_SendByteToAll(int _value)
    {
        FMNetworkManager.instance.SendToAll(new byte[_value]);
    }
    public void Action_SendByteToServer(int _value)
    {
        FMNetworkManager.instance.SendToServer(new byte[_value]);
    }
    public void Action_SendByteToOthers(int _value)
    {
        FMNetworkManager.instance.SendToOthers(new byte[_value]);
    }
    public void Action_SendByteToTarget(int _value)
    {
        FMNetworkManager.instance.SendToTarget(new byte[_value], TargetIP);
    }

    public void Action_SendTextToAll(string _value)
    {
        FMNetworkManager.instance.SendToAll(_value);
    }
    public void Action_SendTextToServer(string _value)
    {
        FMNetworkManager.instance.SendToServer(_value);
    }
    public void Action_SendTextToOthers(string _value)
    {
        FMNetworkManager.instance.SendToOthers(_value);
    }
    public void Action_SendTextToTarget(string _value)
    {
        FMNetworkManager.instance.SendToTarget(_value, TargetIP);
    }

    public void Action_SendRandomTextToAll()
    {
        string _value = Random.value.ToString();
        FMNetworkManager.instance.SendToAll(_value);
    }
    public void Action_SendRandomTextToServer()
    {
        string _value = Random.value.ToString();
        FMNetworkManager.instance.SendToServer(_value);
    }
    public void Action_SendRandomTextToOthers()
    {
        string _value = Random.value.ToString();
        FMNetworkManager.instance.SendToOthers(_value);
    }
    public void Action_SendRandomTextToTarget()
    {
        string _value = Random.value.ToString();
        FMNetworkManager.instance.SendToTarget(_value, TargetIP);
    }
}

LargeFileEncoder

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class LargeFileEncoder : MonoBehaviour {

    public bool Sending = false;

    [Tooltip("smaller number: take longer time to send \nTry to reduce the number if the file cannot be sent successfully")]
    [Range(1,60)]
    public int AddDelayEveryPacket = 4;

    public UnityEventByteArray OnDataByteReadyEvent;

    [Header("Pair Encoder & Decoder")]
    public int label = 8001;
    int dataID = 0;
    int maxID = 1024;
    int chunkSize = 8096; //32768;

    public int dataLength;

    void Start()
    {
        Application.runInBackground = true;
    }

    public void Action_SendLargeByte(byte[] _data)
    {
        StartCoroutine(SenderCOR(_data));
    }

    IEnumerator SenderCOR(byte[] dataByte)
    {
        yield return null;
        if (!Sending)
        {
            Sending = true;

            dataLength = dataByte.Length;
            int _length = dataByte.Length;
            int _offset = 0;

            byte[] _meta_label = BitConverter.GetBytes(label);
            byte[] _meta_id = BitConverter.GetBytes(dataID);
            byte[] _meta_length = BitConverter.GetBytes(_length);

            int chunks = Mathf.FloorToInt(dataByte.Length / chunkSize);
            for (int i = 0; i <= chunks; i++)
            {
                int SendByteLength = (i == chunks) ? (_length % chunkSize + 16) : (chunkSize + 16);
                byte[] _meta_offset = BitConverter.GetBytes(_offset);
                byte[] SendByte = new byte[SendByteLength];

                Buffer.BlockCopy(_meta_label, 0, SendByte, 0, 4);
                Buffer.BlockCopy(_meta_id, 0, SendByte, 4, 4);
                Buffer.BlockCopy(_meta_length, 0, SendByte, 8, 4);

                Buffer.BlockCopy(_meta_offset, 0, SendByte, 12, 4);

                Buffer.BlockCopy(dataByte, _offset, SendByte, 16, SendByte.Length - 16);
                OnDataByteReadyEvent.Invoke(SendByte);
                _offset += chunkSize;
            }

            dataID++;
            if (dataID > maxID) dataID = 0;

            Sending = false;
        }
    }

    void OnDisable()
    {
        StopAll();
    }
    void OnApplicationQuit()
    {
        StopAll();
    }
    void OnDestroy()
    {
        StopAll();
    }

    void StopAll()
    {
        StopAllCoroutines();
    }
}

LargeFileDecoder

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class LargeFileDecoder : MonoBehaviour {

    public UnityEventByteArray OnReceivedByteArray;

    // Use this for initialization
    void Start()
    {
        Application.runInBackground = true;
    }

    bool ReadyToGetFrame = true;

    [Header("Pair Encoder & Decoder")]
    public int label = 8001;
    int dataID = 0;
    //int maxID = 1024;
    int dataLength = 0;
    int receivedLength = 0;

    byte[] dataByte;

    public void Action_ProcessData(byte[] _byteData)
    {
        if (_byteData.Length <= 8) return;

        int _label = BitConverter.ToInt32(_byteData, 0);
        if (_label != label) return;
        int _dataID = BitConverter.ToInt32(_byteData, 4);
        //if (_dataID < dataID) return;

        if (_dataID != dataID) receivedLength = 0;

        dataID = _dataID;
        dataLength = BitConverter.ToInt32(_byteData, 8);
        int _offset = BitConverter.ToInt32(_byteData, 12);

        if (receivedLength == 0) dataByte = new byte[dataLength];
        receivedLength += _byteData.Length - 16;

        Buffer.BlockCopy(_byteData, 16, dataByte, _offset, _byteData.Length - 16);
        if (ReadyToGetFrame)
        {
            if (receivedLength == dataLength) StartCoroutine(ProcessData(dataByte));
        }
    }

    IEnumerator ProcessData(byte[] _byteData)
    {
        ReadyToGetFrame = false;
        OnReceivedByteArray.Invoke(_byteData);
        ReadyToGetFrame = true;
        yield return null;
    }

    private void OnDisable()
    {
        StopAllCoroutines();
    }
}

三、效果展示

你可能感兴趣的:(Unity3D开发技术研究(FMETP STREAM)实时画面传输插件使用)