Files
webRtc/Packages/com.unity.renderstreaming@3.1.0-exp.9/Runtime/Scripts/SignalingHandlerBase.cs
2026-04-28 16:48:04 +08:00

398 lines
12 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Unity.WebRTC;
using UnityEngine;
namespace Unity.RenderStreaming
{
/// <summary>
///
/// </summary>
public abstract class SignalingHandlerBase : MonoBehaviour
{
private IRenderStreamingHandler m_handler;
/// <summary>
///
/// </summary>
public virtual IEnumerable<Component> Streams => null;
/// <summary>
///
/// </summary>
/// <param name="connectionId"></param>
public virtual void CreateConnection(string connectionId)
{
m_handler.CreateConnection(connectionId);
}
/// <summary>
///
/// </summary>
/// <param name="connectionId"></param>
public virtual void DeleteConnection(string connectionId)
{
m_handler.DeleteConnection(connectionId);
}
/// <summary>
///
/// </summary>
/// <param name="connectionId"></param>
/// <returns></returns>
public virtual bool ExistConnection(string connectionId)
{
return m_handler.ExistConnection(connectionId);
}
/// <summary>
///
/// </summary>
/// <param name="connectionId"></param>
/// <returns></returns>
public virtual bool IsConnected(string connectionId)
{
return m_handler.IsConnected(connectionId);
}
/// <summary>
///
/// </summary>
/// <param name="connectionId"></param>
/// <returns></returns>
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");
}
/// <summary>
///
/// </summary>
/// <param name="connectionId"></param>
/// <param name="sender"></param>
/// <returns></returns>
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);
}
/// <summary>
///
/// </summary>
/// <param name="connectionId"></param>
/// <param name="sender"></param>
public virtual void RemoveSender(string connectionId, IStreamSender sender)
{
if (ExistConnection(connectionId))
RemoveTrack(connectionId, sender.Track);
sender.SetTransceiver(connectionId, null);
}
/// <summary>
///
/// </summary>
/// <param name="connectionId"></param>
/// <param name="receiver"></param>
/// <param name="transceiver"></param>
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);
}
/// <summary>
///
/// </summary>
/// <param name="connectionId"></param>
/// <param name="receiver"></param>
public virtual void RemoveReceiver(string connectionId, IStreamReceiver receiver)
{
receiver.SetTransceiver(connectionId, null);
}
/// <summary>
///
/// </summary>
/// <param name="connectionId"></param>
/// <param name="channel"></param>
public virtual void AddChannel(string connectionId, IDataChannel channel)
{
if (channel.IsLocal)
{
var _channel = m_handler.CreateChannel(connectionId, channel.Label);
channel.SetChannel(connectionId, _channel);
}
}
/// <summary>
///
/// </summary>
/// <param name="connectionId"></param>
/// <param name="channel"></param>
public virtual void RemoveChannel(string connectionId, IDataChannel channel)
{
channel.SetChannel(connectionId, null);
}
/// <summary>
///
/// </summary>
/// <param name="connectionId"></param>
/// <param name="track"></param>
protected virtual void RemoveTrack(string connectionId, MediaStreamTrack track)
{
m_handler.RemoveSenderTrack(connectionId, track);
}
/// <summary>
///
/// </summary>
/// <param name="connectionId"></param>
public virtual void SendOffer(string connectionId)
{
m_handler.SendOffer(connectionId);
}
/// <summary>
///
/// </summary>
/// <param name="connectionId"></param>
public virtual void SendAnswer(string connectionId)
{
m_handler.SendAnswer(connectionId);
}
internal void SetHandler(IRenderStreamingHandler handler)
{
m_handler = handler;
}
}
/// <summary>
///
/// </summary>
public delegate void OnStartedStreamHandler(string connectionId);
/// <summary>
///
/// </summary>
public delegate void OnStoppedStreamHandler(string connectionId);
/// <summary>
///
/// </summary>
public delegate void OnStartedChannelHandler(string connectionId);
/// <summary>
///
/// </summary>
public delegate void OnStoppedChannelHandler(string connectionId);
/// <summary>
///
/// </summary>
public interface IStreamSender
{
/// <summary>
///
/// </summary>
MediaStreamTrack Track { get; }
/// <summary>
///
/// </summary>
IReadOnlyDictionary<string, RTCRtpTransceiver> Transceivers { get; }
/// <summary>
///
/// </summary>
/// <param name="connectionId"></param>
/// <param name="transceiver"></param>
void SetTransceiver(string connectionId, RTCRtpTransceiver transceiver);
}
/// <summary>
///
/// </summary>
public interface IStreamReceiver
{
/// <summary>
///
/// </summary>
MediaStreamTrack Track { get; }
/// <summary>
///
/// </summary>
RTCRtpTransceiver Transceiver { get; }
/// <summary>
///
/// </summary>
/// <param name="connectionId"></param>
/// <param name="transceiver"></param>
void SetTransceiver(string connectionId, RTCRtpTransceiver transceiver);
}
/// <summary>
///
/// </summary>
public interface IDataChannel
{
/// <summary>
///
/// </summary>
bool IsLocal { get; }
/// <summary>
///
/// </summary>
bool IsConnected { get; }
/// <summary>
///
/// </summary>
string Label { get; }
/// <summary>
///
/// </summary>
string ConnectionId { get; }
/// <summary>
///
/// </summary>
RTCDataChannel Channel { get; }
///// <summary>
/////
///// </summary>
///// <param name="track"></param>
void SetChannel(string connectionId, RTCDataChannel channel);
/// <summary>
///
/// </summary>
/// <param name="data"></param>
void SetChannel(SignalingEventData data);
}
}