ffmpegStreamToUnity icon indicating copy to clipboard operation
ffmpegStreamToUnity copied to clipboard

Image Receiver

Open bigzaiko opened this issue 3 years ago • 0 comments

using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Net; using System.Net.Sockets; using System.Runtime.InteropServices; using System.Text; using System.Threading; using UnityEngine;

public class TCPImage : MonoBehaviour { public NetworkStream stream { get; private set; } public int ImageSizeWidth = 640; public int ImageSizeHeight = 360; public int receiveBufferSize = 2000000; public Material TargetMaterial;

private Thread tcpThread;

private TcpClient tcpClient;
private TcpListener tcpListener;

private byte[] dumpPixels;
private byte[] bytes;
private byte[] pixels;

private Texture2D texture;

private int bufferIndex = 0;
private int bufferFrameStart = 0;
private Queue<int> frameIndex = new Queue<int>();
private int frameBufferCount = 0;
private int bufferSize;

// Start is called before the first frame update
void OnEnable()
{
	try
	{
		this.receiveBufferSize = this.ImageSizeWidth * this.ImageSizeHeight * 3;
		this.texture = new Texture2D(this.ImageSizeWidth, this.ImageSizeHeight, TextureFormat.RGB24, false);
		this.texture.filterMode = FilterMode.Bilinear;
		this.texture.wrapMode = TextureWrapMode.Clamp;

        this.bufferSize = this.receiveBufferSize * 3;
        this.dumpPixels = new byte[this.bufferSize];
        this.pixels = new byte[this.receiveBufferSize];

		for (int i = 0; i < this.receiveBufferSize; i += 3)
		{
			this.pixels[i + 0] = 255;
			this.pixels[i + 1] = 0;
			this.pixels[i + 2] = 255;
		}

		this.texture.LoadRawTextureData(this.pixels);
		this.texture.Apply(false);

		this.TargetMaterial.mainTexture = this.texture;
	}
	catch (Exception ex)
	{
		DebugLog.Log("Exception " + ex.ToString());
	}
}

public void TcpConnection()
{
    this.tcpListener = new TcpListener(IPAddress.Any, 3005);
    this.tcpListener.ExclusiveAddressUse = false;
	this.tcpListener.Server.DontFragment = true;
    this.tcpListener.Start();


    this.tcpThread = new Thread(ListenForTCPPackages);
    this.tcpThread.IsBackground = true;
    this.tcpThread.SetApartmentState(ApartmentState.STA);
    this.tcpThread.Start();
}

private void ListenForTCPPackages()
{
	try
	{
		// Get a stream object for reading and writing
		this.tcpClient = this.tcpListener.AcceptTcpClient();
		this.tcpClient.Client.DontFragment = true;
        this.stream = this.tcpClient.GetStream();

		this.bytes = new byte[this.receiveBufferSize];
		
		int i;
        // Loop to receive all the data sent by the client.
        while ((i = this.stream.Read(this.bytes, 0, this.bytes.Length)) != 0)
        {
            //if (this.bufferFrameStart == this.bufferSize)
                //this.bufferFrameStart = 0;

            if (this.bufferIndex + i > this.bufferSize)
            {
                var diff = this.bufferSize - this.bufferIndex;

                if (diff != 0)
                {
                    Array.Copy(this.bytes, 0, this.dumpPixels, this.bufferIndex, diff);
                    this.bufferIndex = i - diff;
                }
                else
                {
                    Array.Copy(this.bytes, 0, this.dumpPixels, 0, i);
                    this.bufferIndex = i;
                    this.bufferFrameStart = 0;
                }
            }
            else
            {
                Array.Copy(this.bytes, 0, this.dumpPixels, this.bufferIndex, i);
                this.bufferIndex += i;
            }

            if (this.bufferIndex - this.bufferFrameStart >= this.receiveBufferSize)
            {
                this.frameIndex.Enqueue(this.bufferFrameStart);
                this.frameBufferCount++;
                this.bufferFrameStart += this.receiveBufferSize;
            }
        }
	}
	catch (Exception ex)
	{
		//DisposeListener();
        Debug.Log("lost video stream");
        Debug.Log("listener thread: " + ex.ToString());
    }
}

private void Update()
{
    if (this.frameBufferCount > 0 && this.frameIndex.Count != 0)
    {
        var deq = this.frameIndex.Dequeue();
        Array.Copy(this.dumpPixels, deq, this.pixels, 0, this.receiveBufferSize);
        this.texture.LoadRawTextureData(this.pixels);
        this.texture.Apply(false);
        this.frameBufferCount--;
    }
}

private void DisposeListener()
{
    this.bufferFrameStart = 0;
    this.bufferIndex = 0;
    this.frameIndex.Clear();

    if (this.tcpListener != null)
    {
        this.tcpListener.Stop();
        this.tcpListener = null;
    }

    if (this.tcpClient != null)
    {
        this.tcpClient.Close();
        this.tcpClient.Dispose();
        this.tcpClient = null;
    }

    if(this.stream != null)
    {
        this.stream.Flush();
        this.stream.Close();
        this.stream.Dispose();
        this.stream = null;
    }

    if (this.tcpThread != null)
    {
        this.tcpThread.Abort();
        this.tcpThread = null;
    }
}
private void OnDestroy()
{
	DisposeListener();
}

private void OnDisable()
{
    DisposeListener();
}

private void OnApplicationQuit()
{
    DisposeListener();
}

}

bigzaiko avatar Sep 05 '22 12:09 bigzaiko