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); } }