using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using Unity.WebRTC;
using UnityEngine;
namespace Unity.RenderStreaming
{
///
///
///
public abstract class SignalingHandlerBase : MonoBehaviour
{
private IRenderStreamingHandler m_handler;
///
///
///
public virtual IEnumerable Streams => null;
///
///
///
///
public virtual void CreateConnection(string connectionId)
{
m_handler.CreateConnection(connectionId);
}
///
///
///
///
public virtual void DeleteConnection(string connectionId)
{
m_handler.DeleteConnection(connectionId);
}
///
///
///
///
///
public virtual bool ExistConnection(string connectionId)
{
return m_handler.ExistConnection(connectionId);
}
///
///
///
///
///
public virtual bool IsConnected(string connectionId)
{
return m_handler.IsConnected(connectionId);
}
///
///
///
///
///
public virtual bool IsStable(string connectionId)
{
return m_handler.IsStable(connectionId);
}
static RTCRtpTransceiverInit GetTransceiverInit(IStreamSender sender)
{
RTCRtpTransceiverInit init = new RTCRtpTransceiverInit()
{
direction = RTCRtpTransceiverDirection.SendOnly,
};
if (sender is VideoStreamSender videoStreamSender)
{
init.sendEncodings = new RTCRtpEncodingParameters[]
{
new RTCRtpEncodingParameters()
{
active = true,
minBitrate = (ulong?)videoStreamSender.minBitrate * 1000,
maxBitrate = (ulong?)videoStreamSender.maxBitrate * 1000,
maxFramerate = (uint?)videoStreamSender.frameRate,
scaleResolutionDownBy = videoStreamSender.scaleResolutionDown
}
};
}
if (sender is AudioStreamSender audioStreamSender)
{
init.sendEncodings = new RTCRtpEncodingParameters[]
{
new RTCRtpEncodingParameters()
{
active = true,
minBitrate = (ulong?)audioStreamSender.minBitrate * 1000,
maxBitrate = (ulong?)audioStreamSender.maxBitrate * 1000,
}
};
}
return init;
}
internal static VideoCodecInfo[] GetVideoCodecInfo(IStreamSender sender)
{
if (sender is VideoStreamSender videoStreamSender)
{
if (videoStreamSender.codec == null)
return new VideoCodecInfo[] { };
return new VideoCodecInfo[] { videoStreamSender.codec };
}
throw new ArgumentException("sender is not for video streaming.", "sender");
}
internal static AudioCodecInfo[] GetAudioCodecInfo(IStreamSender sender)
{
if (sender is AudioStreamSender audioStreamSender)
{
if (audioStreamSender.codec == null)
return new AudioCodecInfo[] { };
return new AudioCodecInfo[] { audioStreamSender.codec };
}
throw new ArgumentException("sender is not for audio streaming.", "sender");
}
internal static VideoCodecInfo[] GetVideoCodecInfo(IStreamReceiver receiver)
{
if (receiver is VideoStreamReceiver videoStreamReceiver)
{
if (videoStreamReceiver.codec == null)
return new VideoCodecInfo[] { };
return new VideoCodecInfo[] { videoStreamReceiver.codec };
}
throw new ArgumentException("receiver is not for video streaming.", "receiver");
}
internal static AudioCodecInfo[] GetAudioCodecInfo(IStreamReceiver receiver)
{
if (receiver is AudioStreamReceiver audioStreamReceiver)
{
if (audioStreamReceiver.codec == null)
return new AudioCodecInfo[] { };
return new AudioCodecInfo[] { audioStreamReceiver.codec };
}
throw new ArgumentException("receiver is not for audio streaming.", "receiver");
}
///
///
///
///
///
///
public virtual void AddSender(string connectionId, IStreamSender sender)
{
StartCoroutine(AddSenderCoroutine(connectionId, sender));
}
private IEnumerator AddSenderCoroutine(string connectionId, IStreamSender sender)
{
if(sender.Track == null && sender is StreamSenderBase senderBase)
{
var op = senderBase.CreateTrack();
if(op.Track == null)
yield return op;
senderBase.SetTrack(op.Track);
}
if (sender.Track == null)
throw new InvalidOperationException("sender.Track is null");
RTCRtpTransceiverInit init = GetTransceiverInit(sender);
var transceiver = m_handler.AddTransceiver(connectionId, sender.Track, init);
if (sender is VideoStreamSender videoStreamSender)
{
var codecs = GetVideoCodecInfo(sender);
transceiver.SetCodecPreferences(videoStreamSender.SelectCodecCapabilities(codecs).ToArray());
}
else if (sender is AudioStreamSender audioStreamSender)
{
var codecs = GetAudioCodecInfo(sender);
transceiver.SetCodecPreferences(audioStreamSender.SelectCodecCapabilities(codecs).ToArray());
}
sender.SetTransceiver(connectionId, transceiver);
}
///
///
///
///
///
public virtual void RemoveSender(string connectionId, IStreamSender sender)
{
if (ExistConnection(connectionId))
RemoveTrack(connectionId, sender.Track);
sender.SetTransceiver(connectionId, null);
}
///
///
///
///
///
///
public virtual void SetReceiver(string connectionId, IStreamReceiver receiver, RTCRtpTransceiver transceiver)
{
if (receiver is VideoStreamReceiver videoStreamReceiver)
{
var codecs = GetVideoCodecInfo(receiver);
transceiver.SetCodecPreferences(videoStreamReceiver.SelectCodecCapabilities(codecs).ToArray());
}
else if (receiver is AudioStreamReceiver audioStreamReceiver)
{
var codecs = GetAudioCodecInfo(receiver);
transceiver.SetCodecPreferences(audioStreamReceiver.SelectCodecCapabilities(codecs).ToArray());
}
receiver.SetTransceiver(connectionId, transceiver);
}
///
///
///
///
///
public virtual void RemoveReceiver(string connectionId, IStreamReceiver receiver)
{
receiver.SetTransceiver(connectionId, null);
}
///
///
///
///
///
public virtual void AddChannel(string connectionId, IDataChannel channel)
{
if (channel.IsLocal)
{
var _channel = m_handler.CreateChannel(connectionId, channel.Label);
channel.SetChannel(connectionId, _channel);
}
}
///
///
///
///
///
public virtual void RemoveChannel(string connectionId, IDataChannel channel)
{
channel.SetChannel(connectionId, null);
}
///
///
///
///
///
protected virtual void RemoveTrack(string connectionId, MediaStreamTrack track)
{
m_handler.RemoveSenderTrack(connectionId, track);
}
///
///
///
///
public virtual void SendOffer(string connectionId)
{
m_handler.SendOffer(connectionId);
}
///
///
///
///
public virtual void SendAnswer(string connectionId)
{
m_handler.SendAnswer(connectionId);
}
internal void SetHandler(IRenderStreamingHandler handler)
{
m_handler = handler;
}
}
///
///
///
public delegate void OnStartedStreamHandler(string connectionId);
///
///
///
public delegate void OnStoppedStreamHandler(string connectionId);
///
///
///
public delegate void OnStartedChannelHandler(string connectionId);
///
///
///
public delegate void OnStoppedChannelHandler(string connectionId);
///
///
///
public interface IStreamSender
{
///
///
///
MediaStreamTrack Track { get; }
///
///
///
IReadOnlyDictionary Transceivers { get; }
///
///
///
///
///
void SetTransceiver(string connectionId, RTCRtpTransceiver transceiver);
}
///
///
///
public interface IStreamReceiver
{
///
///
///
MediaStreamTrack Track { get; }
///
///
///
RTCRtpTransceiver Transceiver { get; }
///
///
///
///
///
void SetTransceiver(string connectionId, RTCRtpTransceiver transceiver);
}
///
///
///
public interface IDataChannel
{
///
///
///
bool IsLocal { get; }
///
///
///
bool IsConnected { get; }
///
///
///
string Label { get; }
///
///
///
RTCDataChannel Channel { get; }
/////
/////
/////
/////
void SetChannel(string connectionId, RTCDataChannel channel);
///
///
///
///
void SetChannel(SignalingEventData data);
}
}