123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- 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 StreamSenderBase : MonoBehaviour, IStreamSender
- {
- internal class WaitForCreateTrack : CustomYieldInstruction
- {
- public MediaStreamTrack Track { get { return m_track; } }
- MediaStreamTrack m_track;
- bool m_keepWaiting = true;
- public override bool keepWaiting { get { return m_keepWaiting; } }
- public WaitForCreateTrack() { }
- public void Done(MediaStreamTrack track)
- {
- m_track = track;
- m_keepWaiting = false;
- }
- }
- internal Coroutine StartCoroutineWithCallback<T>(T coroutine, Action<T> callback) where T : IEnumerator
- {
- if (coroutine == null)
- throw new ArgumentNullException("coroutine");
- if (callback == null)
- throw new ArgumentNullException("callback");
- return StartCoroutine(_Coroutine(coroutine, callback));
- }
- internal IEnumerator _Coroutine<T>(T coroutine, Action<T> callback) where T : IEnumerator
- {
- yield return StartCoroutine(coroutine);
- callback(coroutine);
- }
- /// <summary>
- ///
- /// </summary>
- public IReadOnlyDictionary<string, RTCRtpTransceiver> Transceivers => m_transceivers;
- /// <summary>
- ///
- /// </summary>
- public OnStartedStreamHandler OnStartedStream { get; set; }
- /// <summary>
- ///
- /// </summary>
- public OnStoppedStreamHandler OnStoppedStream { get; set; }
- /// <summary>
- ///
- /// </summary>
- /// <returns></returns>
- internal abstract WaitForCreateTrack CreateTrack();
- internal virtual void ReplaceTrack(MediaStreamTrack newTrack)
- {
- if (newTrack == null)
- throw new ArgumentNullException("track", "This argument must be not null.");
- if (m_track == newTrack)
- throw new ArgumentException("track", "The value of this argument has already been set.");
- /// todo:: If not disposing the old track here, the app will crash.
- /// This problem is caused by the MediaStreamTrack when it is destroyed on the thread other than the main thread.
- m_track?.Dispose();
- m_track = newTrack;
- foreach (var transceiver in Transceivers.Values)
- {
- transceiver.Sender.ReplaceTrack(m_track);
- }
- }
- internal void SetTrack(MediaStreamTrack newTrack)
- {
- if (newTrack == null)
- throw new ArgumentNullException("track", "This argument must be not null.");
- if (m_track != null)
- throw new InvalidOperationException("Track is not null. Use ReplaceTrack method.");
- m_track = newTrack;
- }
- private MediaStreamTrack m_track;
- private Dictionary<string, RTCRtpTransceiver> m_transceivers =
- new Dictionary<string, RTCRtpTransceiver>();
- /// <summary>
- ///
- /// </summary>
- public MediaStreamTrack Track => m_track;
- /// <summary>
- ///
- /// </summary>
- public bool isPlaying
- {
- get
- {
- foreach (var transceiver in Transceivers.Values)
- {
- if (string.IsNullOrEmpty(transceiver.Mid))
- continue;
- if (transceiver.Sender.Track.ReadyState == TrackState.Ended)
- continue;
- return true;
- }
- return false;
- }
- }
- private protected virtual void OnDestroy()
- {
- m_track?.Dispose();
- m_track = null;
- }
- private protected virtual void OnEnable()
- {
- if (m_track?.ReadyState == TrackState.Live)
- {
- m_track.Enabled = true;
- }
- }
- private protected virtual void OnDisable()
- {
- if (m_track?.ReadyState == TrackState.Live)
- {
- m_track.Enabled = false;
- }
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="connectionId"></param>
- /// <param name="sender"></param>
- public virtual void SetTransceiver(string connectionId, RTCRtpTransceiver transceiver)
- {
- if (connectionId == null)
- throw new ArgumentNullException("connectionId is null");
- if (transceiver == null)
- {
- m_transceivers.Remove(connectionId);
- OnStoppedStream?.Invoke(connectionId);
- if (!m_transceivers.Any())
- {
- m_track.Dispose();
- m_track = null;
- }
- }
- else
- {
- m_transceivers.Add(connectionId, transceiver);
- OnStartedStream?.Invoke(connectionId);
- }
- }
- }
- }
|