ffmpegStreamToUnity
ffmpegStreamToUnity copied to clipboard
Image Receiver
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();
}
}