title: Unity: Live Video Streaming
body: <p>I'm trying to stream a live video from one app to the another, Currently i have 2 apps. were app 1 is the server / sender and app 2 is the client / receiver. In app 1 i successfully send the video bytes to the client. and on the client side I'm also receiving all of the bytes. Im using sockets and TCP. The issue that I'm facing is, When i receive the video bytes and assigning them to a Raw Image texture, the image on the texture looks zoomed in too much and it's so pixilated. </p>
  
  <p><strong>Updated Image</strong></p>
  
  <p><a href="https://i.stack.imgur.com/CADK0.jpg" rel="noreferrer"><img src="https://i.stack.imgur.com/CADK0.jpg" alt="enter image description here"></a></p>
  
  <p>This is what i stream 
  <a href="https://i.stack.imgur.com/CADK0.jpg" rel="noreferrer"><img src="https://i.stack.imgur.com/FlFQX.png" alt="enter image description here"></a></p>
  
  <p>and this is what i get on the client.<br>
  <a href="https://i.stack.imgur.com/CADK0.jpg" rel="noreferrer"><img src="https://i.stack.imgur.com/HgM6J.png" alt="This is what i see on the rawimage when i receive the bytes"></a></p>
  
  <p>This is the 1st issue, however I'm currently testing from desktop to the another, my goal is to stream form an IPAD to a desktop, and when i do that it's so slow and it kills the app on both the ipad and desktop.</p>
  
  <p>Some troubleshooting i tried so far. </p>
  
  <p>1: I think this is is happening because i have 2 different resolutions because i stream from ipad to Desktop</p>
  
  <p>2: The texture image is too large, i output it and it returns 630. I tried to resize it using Unity Texture2D.resize but i get a gray texture because the function sets the pixels as unidentified</p>
  
  <p>3: I used other libraries for resizing textures and i do get what i want, but after 12 frames the rawimage starts flickering between the video and "?" texture so much then it freezes on both app (ipad and desktop)</p>
  
  <p>4: i believe the way I'm reading the texture is causing the issue because i use both Setpixels and Getpixels functions and they are heavy.</p>
  
  <p>My Code: 
  Server / Sender Side:</p>
  
  <pre><code>using UnityEngine;
  using System.Collections;
  using System.IO;
  using UnityEngine.UI;
  using System;
  using System.Text;
  using System.Net;
  using System.Net.Sockets;
  using System.Threading;
  using System.Collections.Generic;
  
  public class Connecting : MonoBehaviour
  {
  WebCamTexture webCam;
  public RawImage myImage;
  Texture2D currentTexture;
  
  private TcpListener listner;
  private const int port = 8010;
  private bool stop = false;
  
  private List&lt;TcpClient&gt; clients = new List&lt;TcpClient&gt;();
  
  private void Start()
  {
      // Open the Camera on the desired device, in my case IPAD pro
      webCam = new WebCamTexture();
      // Get all devices , front and back camera
      webCam.deviceName = WebCamTexture.devices[WebCamTexture.devices.Length - 1].name;
  
      // request the lowest width and heigh possible
      webCam.requestedHeight = 10;
      webCam.requestedWidth = 10;
  
  
      webCam.Play();
  
      /
      currentTexture = new Texture2D(webCam.width, webCam.height);
  
      // Connect to the server
      listner = new TcpListener(port);
  
      listner.Start();
  
      // Create Seperate thread for requesting from client 
      Loom.RunAsync(() =&gt; {
  
          while (!stop)
          {
              // Wait for client approval
              var client = listner.AcceptTcpClient();
              // We are connected
              clients.Add(client);
  
  
              Loom.RunAsync(() =&gt;
              {
                  while (!stop)
                  {
  
                      var stremReader = client.GetStream();
  
                      if (stremReader.CanRead)
                      {
                          // we need storage for data
                          using (var messageData = new MemoryStream())
                          {
                              Byte[] buffer = new Byte[client.ReceiveBufferSize];
  
  
                              while (stremReader.DataAvailable)
                              {
                                  int bytesRead = stremReader.Read(buffer, 0, buffer.Length);
  
                                  if (bytesRead == 0)
                                      break;
  
                                  // Writes to the data storage
                                  messageData.Write(buffer, 0, bytesRead);
  
                              }
  
                              if (messageData.Length &gt; 0)
                              {
                                  // send pngImage
                                  SendPng(client);
  
                              }
  
                          }
                      }
                  }
              });
          }
  
      });
  
  
  
  }
  
  private void Update()
  {
      myImage.texture = webCam;
  }
  
  
  // Read video pixels and send them to the client
  private void SendPng (TcpClient client)
  {
      Loom.QueueOnMainThread(() =&gt;
      {
          // Get the webcame texture pixels   
          currentTexture.SetPixels(webCam.GetPixels());
          var pngBytes = currentTexture.EncodeToPNG();
  
  
          // Want to Write 
          var stream = client.GetStream();
  
          // Write the image bytes
          stream.Write(pngBytes, 0, pngBytes.Length);
  
          // send it 
          stream.Flush();
  
      });
  }
  
  // stop everything
  private void OnApplicationQuit()
  {
      webCam.Stop();
      stop = true;
      listner.Stop();
  
      foreach (TcpClient c in clients)
          c.Close();
  }
  
  
  
  }
  </code></pre>
  
  <p>Client / receiver side</p>
  
  <pre><code>using UnityEngine;
  using System.Collections;
  using UnityEngine.UI;
  using System.Net.Sockets; 
  using System.Net;
  using System.IO;
  
  public class reciver : MonoBehaviour
  {
  
  public RawImage image;
  
  const int port = 8010;
  
  public string IP = "";
  
  TcpClient client;
  
  
  Texture2D tex;
  
  // Use this for initialization
  void Start()
  {
  
      client = new TcpClient();
  
      // connect to server
  
      Loom.RunAsync(() =&gt; {
          Debug.LogWarning("Connecting to server...");
          // if on desktop
          client.Connect(IPAddress.Loopback, port);
  
          // if using the IPAD
          //client.Connect(IPAddress.Parse(IP), port);
          Debug.LogWarning("Connected!");
  
  
  
  
      });
  
  }
  
  float lastTimeRequestedTex = 0;
  // Update is called once per frame
  void Update()
  {
  
      //if (Time.time - lastTimeRequestedTex &lt; 0.1f)
      //  return;
  
      lastTimeRequestedTex = Time.time;
  
  
      if (!client.Connected)
          return;
  
  
      // Send 1 byte to server 
      var serverStream = client.GetStream();
  
      // request the texture from the server 
      if (serverStream.CanWrite)
      {   
          // Texture request
          // send request
          serverStream.WriteByte(byte.MaxValue);
          serverStream.Flush();
          Debug.Log("Succesfully send 1 byte");
      }
  
  
      if (serverStream.CanRead)
      {
  
          // Read the bytes 
          using (var writer = new MemoryStream())
          {
              var readBuffer = new byte[client.ReceiveBufferSize];
  
  
              while (serverStream.DataAvailable)
              {
  
                  int numberOfBytesRead = serverStream.Read(readBuffer, 0, readBuffer.Length);
                  if (numberOfBytesRead &lt;= 0)
                  {
                      break;
                  }
  
                  writer.Write(readBuffer, 0, numberOfBytesRead);
  
  
              }
  
              if (writer.Length &gt; 0)
              {
                  // got whole data in writer
                  // Get the bytes and apply them to the texture
                  var tex = new Texture2D(0, 0);
                  tex.LoadImage(writer.ToArray());
                  Debug.Log(tex.width + tex.height);
                  image.texture = tex;
  
  
              }   
          }
      }
  }
  
  void OnApplicationQuit()
  {
      Debug.LogWarning("OnApplicationQuit");
      client.Close();
  }
  }
  </code></pre>