Hi everyone,
I know this question has been addressed on several occasions but I can’t find a complete solution to the problem. First a bit of background. I currently have an application running on a single window. The applications has two modes. The first one uses the virtual environment to render some stuff and display it on a texture. On the second mode, the texture is filled in a C++ plugin (using “getNativePtr”) from a video stream.
Now comes the problem. I need to display this same texture on an external window. After some research, I realized that Unity doesn’t handle additional windows (that I could move to another screen for instance) and that I have to create another application and network them. Since in the second mode the texture is not rendered by Unity, I can’t just have a duplicate environment to display the same texture. So now I need to stream the video through the network.
I’m not really familiar with networking in Unity but it seems quite doable. Moreover, since the server and client will be running on the same computer, I assume that it would not be lagging (am I right ?). So far, I’ve created a server and client class along with a TextureMessage class (inherits from MessageBase). I’m able to transfer all the information related to the texture (size, format, …), but when I try to send the texture itself (that I transformed into a byte[ ] with GetRawTextureData), I get a “channelBuffer limit reached” error. I tried to raise the limit to 500 but it doesn’t change (even for really small images).
It seems that I need to look at serialization, but I don’t really know where to start. Am I going in the right direction ?
If anyone could help me out or point me in the right directions that would be awesome :).
Thanks a lot in advance.
Here is my current code :
Message class:
public class TextureInfoMessage : MessageBase
{
public byte[] textureData;
public int width;
public int height;
public TextureFormat format;
public bool mipmap;
public TextureInfoMessage(){}
public TextureInfoMessage(byte[] d, int w, int h, TextureFormat f, bool m)
{
textureData = d;
width = w;
height = h;
format = f;
mipmap = m;
}
}
Server:
public class StreamServer : MonoBehaviour {
// Use this for initialization
void Start () {
NetworkServer.Listen(4444);
}
// Update is called once per frame
void Update () {
if(NetworkServer.connections.Count > 0)
{
TextureInfoMessage msg = MyStreamingClass.getTexture();
// TODO : get connectionID properly
NetworkServer.connections[1].SetChannelOption(Channels.DefaultReliable, ChannelOption.MaxPendingBuffers, 500);
NetworkServer.SendToClient(NetworkServer.connections[1].connectionId,1000, msg);
}
}
}
Client:
public class StreamClient : MonoBehaviour {
private bool connected = false;
bool initialized = false;
private int width;
private int height;
private TextureFormat format;
private bool mipmap;
NetworkClient myClient;
RawImage image;
// Use this for initialization
void Start () {
myClient = new NetworkClient();
myClient.RegisterHandler(MsgType.Connect, OnConnected);
myClient.RegisterHandler(1000, getInfoTexture);
myClient.Connect("127.0.0.1", 4444);
image = GetComponent<RawImage>();
image.texture = new Texture2D(2,2,TextureFormat.RGB565, false);
}
void OnGUI()
{
GUILayout.Label(connected ? "OK" : "Not OK");
GUILayout.Label("Width: "+width);
GUILayout.Label("Height: "+height);
GUILayout.Label("mipmap: "+mipmap);
}
void OnConnected(NetworkMessage netMsg)
{
connected = true;
}
void getInfoTexture(NetworkMessage msg)
{
TextureInfoMessage msg2 = msg.ReadMessage<TextureInfoMessage>();
if(!initialized || width != msg2.width || height != msg2.height || format != msg2.format)
image.texture = new Texture2D (width, height, TextureFormat.RGB565, mipmap);
width = msg2.width;
height = msg2.height;
format = msg2.format;
mipmap = msg2.mipmap;
((Texture2D)(image.texture)).LoadRawTextureData(msg2.textureData);
initialized = true;
}
}