Created
August 17, 2023 03:49
-
-
Save gtk2k/255841c97090778aba9c5c945c57b8a6 to your computer and use it in GitHub Desktop.
Uv4l signaling class (operation is not confirmed)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Newtonsoft.Json; | |
using System; | |
using System.Threading; | |
using Unity.WebRTC; | |
using UnityEngine; | |
using WebSocketSharp; | |
public class Uv4lStreamingSignalingClient | |
{ | |
public event Action OnOpen; | |
public event Action<RTCConfiguration> OnConfig; | |
public event Action<int> OnPlayerCount; | |
public event Action<RTCSessionDescription> OnOffer; | |
public event Action<RTCIceCandidate> OnIceCandidate; | |
public event Action<ushort, string> OnClose; | |
public event Action<Exception> OnError; | |
private SynchronizationContext ctx; | |
private WebSocket ws; | |
private JsonSerializerSettings jsonSettings = new JsonSerializerSettings | |
{ | |
NullValueHandling = NullValueHandling.Ignore | |
}; | |
[Serializable] | |
private class Uv4lMessage | |
{ | |
public string what; | |
public string options; | |
public string data; | |
} | |
[Serializable] | |
private class Uv4lOptions | |
{ | |
public bool force_hw_vcodec; | |
public int vformat; | |
public bool trickle_ice; | |
} | |
[Serializable] | |
private class Uv4lDesc | |
{ | |
public string type; | |
public string sdp; | |
} | |
[Serializable] | |
private class Uv4lIceCandidate | |
{ | |
public string candidate; | |
public int sdpMLineIndex; | |
} | |
public Uv4lStreamingSignalingClient(string url) | |
{ | |
ctx = SynchronizationContext.Current; | |
ws = new WebSocket(url); | |
ws.OnOpen += Ws_OnOpen; | |
ws.OnMessage += Ws_OnMessage; | |
ws.OnClose += Ws_OnClose; | |
ws.OnError += Ws_OnError; | |
} | |
public void Call(bool useHardwareEncode, int frameRate, bool useTricleIce = true) | |
{ | |
var options = new Uv4lOptions | |
{ | |
force_hw_vcodec = useHardwareEncode, | |
vformat = frameRate, | |
trickle_ice = useTricleIce | |
}; | |
var data = JsonConvert.SerializeObject(options, jsonSettings); | |
Send("call", data); | |
} | |
public void SendAnswer(RTCSessionDescription answer) | |
{ | |
var desc = new Uv4lDesc | |
{ | |
type = "answer", | |
sdp = answer.sdp | |
}; | |
var data = JsonConvert.SerializeObject(desc, jsonSettings); | |
} | |
public void SendIceCandidate(RTCIceCandidate cand) | |
{ | |
var msg = new Uv4lIceCandidate | |
{ | |
candidate = cand.Candidate, | |
sdpMLineIndex = cand.SdpMLineIndex.Value | |
}; | |
var data = JsonConvert.SerializeObject(msg, jsonSettings); | |
Send("iceCandidate", data); | |
} | |
private void Send(string type, string data, string options = null) | |
{ | |
var msg = new Uv4lMessage | |
{ | |
what = type, | |
data = data, | |
options = options | |
}; | |
var sendData = JsonConvert.SerializeObject(msg, jsonSettings); | |
ws.Send(sendData); | |
} | |
public void Connect() | |
{ | |
ws.Connect(); | |
} | |
public void Close() | |
{ | |
if (ws != null) | |
{ | |
if (ws.ReadyState == WebSocketState.Open) | |
{ | |
ws.Close(); | |
} | |
ws = null; | |
} | |
} | |
private void Ws_OnOpen(object sender, EventArgs e) | |
{ | |
ctx.Post(_ => | |
{ | |
OnOpen?.Invoke(); | |
}, null); | |
} | |
private void Ws_OnMessage(object sender, MessageEventArgs e) | |
{ | |
ctx.Post(_ => | |
{ | |
Debug.Log($"Receive <== {e.Data}"); | |
var msg = JsonConvert.DeserializeObject<Uv4lMessage>(e.Data); | |
switch (msg.what) | |
{ | |
case "offer": | |
{ | |
var data = JsonConvert.DeserializeObject<Uv4lDesc>(msg.data); | |
var offer = new RTCSessionDescription | |
{ | |
type = RTCSdpType.Offer, | |
sdp = data.sdp | |
}; | |
OnOffer?.Invoke(offer); | |
break; | |
} | |
case "iceCandidate": | |
{ | |
var data = JsonConvert.DeserializeObject<Uv4lIceCandidate>(msg.data); | |
var iceCandidate = new RTCIceCandidate(new RTCIceCandidateInit | |
{ | |
candidate = data.candidate, | |
sdpMLineIndex = data.sdpMLineIndex | |
}); | |
OnIceCandidate?.Invoke(iceCandidate); | |
break; | |
} | |
case "iceCandidates": | |
{ | |
var data = JsonConvert.DeserializeObject<Uv4lIceCandidate[]>(msg.data); | |
for (var i = 0; i < data.Length; i++) | |
{ | |
var iceCandidate = new RTCIceCandidate(new RTCIceCandidateInit | |
{ | |
candidate = data[i].candidate, | |
sdpMLineIndex = data[i].sdpMLineIndex | |
}); | |
OnIceCandidate?.Invoke(iceCandidate); | |
} | |
break; | |
} | |
} | |
}, null); | |
} | |
private void Ws_OnClose(object sender, CloseEventArgs e) | |
{ | |
ctx.Post(_ => | |
{ | |
Debug.Log($"Ws_OnClose > code: {e.Code}, reason: {e.Reason}"); | |
}, null); | |
} | |
private void Ws_OnError(object sender, ErrorEventArgs e) | |
{ | |
ctx.Post(_ => | |
{ | |
Debug.LogError(e.Message); | |
}, null); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment