diff --git a/Runtime/Scripts/Internal/UpdateCoroutine.cs b/Runtime/Scripts/Internal/UpdateCoroutine.cs new file mode 100644 index 0000000000..8ab75f7de7 --- /dev/null +++ b/Runtime/Scripts/Internal/UpdateCoroutine.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections; +using UnityEngine; + +namespace Unity.WebRTC +{ + public class UpdateCoroutine : MonoBehaviour + { + Coroutine _coroutine; + + public Func routine + { + set + { + if (_coroutine != null) + StopCoroutine(_coroutine); + _coroutine = StartCoroutine(value()); + } + } + + + void OnDestroy() + { + if (_coroutine != null) + StopCoroutine(_coroutine); + } + } +} diff --git a/Runtime/Scripts/Internal/UpdateCoroutine.cs.meta b/Runtime/Scripts/Internal/UpdateCoroutine.cs.meta new file mode 100644 index 0000000000..f574425617 --- /dev/null +++ b/Runtime/Scripts/Internal/UpdateCoroutine.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3a068ce8d22150c4a847037cf98f2f4d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Scripts/WebRTC.cs b/Runtime/Scripts/WebRTC.cs index b5228adad9..a4b888cdb8 100644 --- a/Runtime/Scripts/WebRTC.cs +++ b/Runtime/Scripts/WebRTC.cs @@ -633,12 +633,21 @@ public static class WebRTC private static Context s_context = null; private static SynchronizationContext s_syncContext; private static ILogger s_logger; + private static GameObject s_obj; [RuntimeInitializeOnLoadMethod] static void RuntimeInitializeOnLoadMethod() { // Initialize a custom invokable synchronization context to wrap the main thread UnitySynchronizationContext s_syncContext = new ExecutableUnitySynchronizationContext(SynchronizationContext.Current); + + // Instantiate GameObject for coroutine. + s_obj = new GameObject("webrtc"); + s_obj.hideFlags = HideFlags.HideAndDontSave; + if (Application.isPlaying) + UnityEngine.Object.DontDestroyOnLoad(s_obj); + var comp = s_obj.AddComponent(); + comp.routine = UpdateInternal; } internal static void InitializeInternal(bool limitTextureSize = true, bool enableNativeLog = false, @@ -666,10 +675,21 @@ internal static void InitializeInternal(bool limitTextureSize = true, bool enabl /// /// /// + [Obsolete] public static IEnumerator Update() { var instruction = new WaitForEndOfFrame(); + while (true) + { + yield return instruction; + } + } + + public static IEnumerator UpdateInternal() + { + var instruction = new WaitForEndOfFrame(); + while (true) { // Wait until all frame rendering is done @@ -999,6 +1019,7 @@ static void DestroyImmediate(object state) { var obj = state as UnityEngine.Object; UnityEngine.Object.DestroyImmediate(obj); + obj = null; } static void Destroy(object state) diff --git a/Samples~/Audio/AudioSample.cs b/Samples~/Audio/AudioSample.cs index dcc7947d75..8dd11dec1d 100644 --- a/Samples~/Audio/AudioSample.cs +++ b/Samples~/Audio/AudioSample.cs @@ -60,7 +60,6 @@ class AudioSample : MonoBehaviour void Start() { - StartCoroutine(WebRTC.Update()); StartCoroutine(LoopStatsCoroutine()); toggleEnableMicrophone.isOn = false; diff --git a/Samples~/Bandwidth/BandwidthSample.cs b/Samples~/Bandwidth/BandwidthSample.cs index 1d45cc5c74..2b116d2ecf 100644 --- a/Samples~/Bandwidth/BandwidthSample.cs +++ b/Samples~/Bandwidth/BandwidthSample.cs @@ -225,7 +225,6 @@ private void AddTracks() if (!videoUpdateStarted) { - StartCoroutine(WebRTC.Update()); StartCoroutine(LoopStatsCoroutine()); videoUpdateStarted = true; } diff --git a/Samples~/ChangeCodecs/ChangeCodecsSample.cs b/Samples~/ChangeCodecs/ChangeCodecsSample.cs index 64345b8814..2a6f92157d 100644 --- a/Samples~/ChangeCodecs/ChangeCodecsSample.cs +++ b/Samples~/ChangeCodecs/ChangeCodecsSample.cs @@ -32,7 +32,6 @@ class ChangeCodecsSample : MonoBehaviour private DelegateOnIceCandidate pc2OnIceCandidate; private DelegateOnTrack pc2Ontrack; private DelegateOnNegotiationNeeded pc1OnNegotiationNeeded; - private bool videoUpdateStarted; private readonly string[] excludeCodecMimeType = { "video/red", "video/ulpfec", "video/rtx" }; private RTCRtpCodecCapability[] availableCodecs; @@ -166,12 +165,6 @@ private void AddTracks() pc1Senders.Add(_pc1.AddTrack(track, videoStream)); } - if (!videoUpdateStarted) - { - StartCoroutine(WebRTC.Update()); - videoUpdateStarted = true; - } - RTCRtpCodecCapability[] codecs = null; if (codecSelector.value == 0) { diff --git a/Samples~/E2ELatency/E2ELatencySample.cs b/Samples~/E2ELatency/E2ELatencySample.cs index 4f5fe9e74b..4324763b72 100644 --- a/Samples~/E2ELatency/E2ELatencySample.cs +++ b/Samples~/E2ELatency/E2ELatencySample.cs @@ -96,8 +96,6 @@ private void Start() receiveStream.AddTrack(e.Track); }; pc1OnNegotiationNeeded = () => { StartCoroutine(PeerNegotiationNeeded(_pc1)); }; - - StartCoroutine(WebRTC.Update()); } private void OnFramerateChanged(int value) diff --git a/Samples~/Encryption/EncryptionSample.cs b/Samples~/Encryption/EncryptionSample.cs index 4d4b22d648..568d2dc2bf 100644 --- a/Samples~/Encryption/EncryptionSample.cs +++ b/Samples~/Encryption/EncryptionSample.cs @@ -34,7 +34,6 @@ class EncryptionSample : MonoBehaviour private DelegateOnIceCandidate pc2OnIceCandidate; private DelegateOnTrack pc2Ontrack; private DelegateOnNegotiationNeeded pc1OnNegotiationNeeded; - private bool videoUpdateStarted; Dictionary frameTypeToCryptoOffset; @@ -408,12 +407,6 @@ private void AddTracks() { SetUpSenderTransform(sender); } - - if (!videoUpdateStarted) - { - StartCoroutine(WebRTC.Update()); - videoUpdateStarted = true; - } } private void RemoveTracks() diff --git a/Samples~/MediaStream/MediaStreamSample.cs b/Samples~/MediaStream/MediaStreamSample.cs index 47b62a3686..d23e9ca65c 100644 --- a/Samples~/MediaStream/MediaStreamSample.cs +++ b/Samples~/MediaStream/MediaStreamSample.cs @@ -30,7 +30,6 @@ class MediaStreamSample : MonoBehaviour private DelegateOnTrack pc2Ontrack; private DelegateOnNegotiationNeeded pc1OnNegotiationNeeded; private StringBuilder trackInfos; - private bool videoUpdateStarted; private void Awake() { @@ -129,13 +128,6 @@ private void AddTracks() } } } - - if (!videoUpdateStarted) - { - StartCoroutine(WebRTC.Update()); - videoUpdateStarted = true; - } - addTracksButton.interactable = false; removeTracksButton.interactable = true; } diff --git a/Samples~/Metadata/MetadataSample.cs b/Samples~/Metadata/MetadataSample.cs index fc910e4115..de504bafa8 100644 --- a/Samples~/Metadata/MetadataSample.cs +++ b/Samples~/Metadata/MetadataSample.cs @@ -34,7 +34,6 @@ class MetadataSample : MonoBehaviour private DelegateOnIceCandidate pc2OnIceCandidate; private DelegateOnTrack pc2Ontrack; private DelegateOnNegotiationNeeded pc1OnNegotiationNeeded; - private bool videoUpdateStarted; private readonly object metadataInputLock = new object(); private readonly object metadataOutputLock = new object(); @@ -308,12 +307,6 @@ private void AddTracks() { SetUpSenderTransform(sender); } - - if (!videoUpdateStarted) - { - StartCoroutine(WebRTC.Update()); - videoUpdateStarted = true; - } } private void RemoveTracks() diff --git a/Samples~/MultiAudioReceive/MultiAudioReceiveSample.cs b/Samples~/MultiAudioReceive/MultiAudioReceiveSample.cs index 3f322dd6be..37c71a66d2 100644 --- a/Samples~/MultiAudioReceive/MultiAudioReceiveSample.cs +++ b/Samples~/MultiAudioReceive/MultiAudioReceiveSample.cs @@ -37,7 +37,6 @@ class MultiAudioReceiveSample : MonoBehaviour private void Awake() { - StartCoroutine(WebRTC.Update()); callButton.onClick.AddListener(Call); hangUpButton.onClick.AddListener(HangUp); addAudioObjectButton.onClick.AddListener(AddVideoObject); diff --git a/Samples~/MultiVideoReceive/MultiVideoReceiveSample.cs b/Samples~/MultiVideoReceive/MultiVideoReceiveSample.cs index c7be6c23a4..09d6dd5a61 100644 --- a/Samples~/MultiVideoReceive/MultiVideoReceiveSample.cs +++ b/Samples~/MultiVideoReceive/MultiVideoReceiveSample.cs @@ -34,7 +34,6 @@ class MultiVideoReceiveSample : MonoBehaviour private DelegateOnTrack pc2Ontrack; private DelegateOnNegotiationNeeded pc1OnNegotiationNeeded; private DelegateOnNegotiationNeeded pc2OnNegotiationNeeded; - private bool videoUpdateStarted; private int objectIndex = 0; private int videoIndex = 0; @@ -194,12 +193,6 @@ private void Call() _pc2.OnIceConnectionChange = pc2OnIceConnectionChange; _pc2.OnTrack = pc2Ontrack; _pc2.OnNegotiationNeeded = pc2OnNegotiationNeeded; - - if (!videoUpdateStarted) - { - StartCoroutine(WebRTC.Update()); - videoUpdateStarted = true; - } } private void AddTracks() diff --git a/Samples~/MultiplePeerConnections/MultiplePeerConnectionsSample.cs b/Samples~/MultiplePeerConnections/MultiplePeerConnectionsSample.cs index fa8c42dfd5..6b2de66ab5 100644 --- a/Samples~/MultiplePeerConnections/MultiplePeerConnectionsSample.cs +++ b/Samples~/MultiplePeerConnections/MultiplePeerConnectionsSample.cs @@ -32,8 +32,6 @@ class MultiplePeerConnectionsSample : MonoBehaviour private void Start() { - StartCoroutine(WebRTC.Update()); - startButton.onClick.AddListener(Setup); callButton.onClick.AddListener(Call); hangUpButton.onClick.AddListener(HangUp); diff --git a/Samples~/MungeSDP/MungeSDPSample.cs b/Samples~/MungeSDP/MungeSDPSample.cs index 79bcf750d8..7dbf678147 100644 --- a/Samples~/MungeSDP/MungeSDPSample.cs +++ b/Samples~/MungeSDP/MungeSDPSample.cs @@ -62,8 +62,6 @@ private void Setup() sourceVideoStream = cam.CaptureStream(WebRTCSettings.StreamSize.x, WebRTCSettings.StreamSize.y); sourceImage.texture = cam.targetTexture; - updateCoroutine = StartCoroutine(WebRTC.Update()); - receiveVideoStream = new MediaStream(); receiveVideoStream.OnAddTrack = e => { diff --git a/Samples~/PeerConnection/PeerConnectionSample.cs b/Samples~/PeerConnection/PeerConnectionSample.cs index 60e9187e34..cabc98e273 100644 --- a/Samples~/PeerConnection/PeerConnectionSample.cs +++ b/Samples~/PeerConnection/PeerConnectionSample.cs @@ -40,7 +40,6 @@ enum ProtocolOption private DelegateOnIceCandidate pc2OnIceCandidate; private DelegateOnTrack pc2Ontrack; private DelegateOnNegotiationNeeded pc1OnNegotiationNeeded; - private bool videoUpdateStarted; private void Awake() { @@ -211,12 +210,6 @@ private void AddTracks() } } } - - if (!videoUpdateStarted) - { - StartCoroutine(WebRTC.Update()); - videoUpdateStarted = true; - } } private void RemoveTracks() diff --git a/Samples~/PerfectNegotiation/PerfectNegotiationSample.cs b/Samples~/PerfectNegotiation/PerfectNegotiationSample.cs index 56000b13d8..ba049f6618 100644 --- a/Samples~/PerfectNegotiation/PerfectNegotiationSample.cs +++ b/Samples~/PerfectNegotiation/PerfectNegotiationSample.cs @@ -65,8 +65,6 @@ private void Start() impolitePeer.SwapTransceivers(); politePeer.SwapTransceivers(); }); - - StartCoroutine(WebRTC.Update()); } private void Update() diff --git a/Samples~/ReplaceTrack/ReplaceTrackSample.cs b/Samples~/ReplaceTrack/ReplaceTrackSample.cs index 972b43c75c..d9c925d629 100644 --- a/Samples~/ReplaceTrack/ReplaceTrackSample.cs +++ b/Samples~/ReplaceTrack/ReplaceTrackSample.cs @@ -63,8 +63,6 @@ private void Start() stopButton.gameObject.SetActive(false); switchButton.onClick.AddListener(OnSwitchTrack); switchButton.interactable = false; - - StartCoroutine(WebRTC.Update()); } private void OnStart() diff --git a/Samples~/Simulcast/SimulcastSample.cs b/Samples~/Simulcast/SimulcastSample.cs index 99b5981292..304044e915 100644 --- a/Samples~/Simulcast/SimulcastSample.cs +++ b/Samples~/Simulcast/SimulcastSample.cs @@ -39,7 +39,6 @@ class SimulcastSample : MonoBehaviour private DelegateOnIceCandidate pc2OnIceCandidate; private DelegateOnTrack pc2Ontrack; private DelegateOnNegotiationNeeded pc1OnNegotiationNeeded; - private bool videoUpdateStarted; private ulong[] optionBitrate = new ulong[] { 100, 150, 200, 300, 400, 600, 800, 1100, 1400 }; private int[] optionScaleResolution = new[] { 1, 2, 4, 8 }; @@ -202,12 +201,6 @@ private void AddTracks() transceiver.SetCodecPreferences(codecs); } _pc1Transceiver = transceiver; - - if (!videoUpdateStarted) - { - StartCoroutine(WebRTC.Update()); - videoUpdateStarted = true; - } } private void RemoveTracks() diff --git a/Samples~/VideoReceive/VideoReceiveSample.cs b/Samples~/VideoReceive/VideoReceiveSample.cs index 198d02d533..e251ef8274 100644 --- a/Samples~/VideoReceive/VideoReceiveSample.cs +++ b/Samples~/VideoReceive/VideoReceiveSample.cs @@ -92,7 +92,6 @@ private void Start() } }; pc1OnNegotiationNeeded = () => { StartCoroutine(PeerNegotiationNeeded(_pc1)); }; - StartCoroutine(WebRTC.Update()); } private void Update() diff --git a/Tests/Runtime/MediaStreamTest.cs b/Tests/Runtime/MediaStreamTest.cs index b2a96b613a..8e134f8e0b 100644 --- a/Tests/Runtime/MediaStreamTest.cs +++ b/Tests/Runtime/MediaStreamTest.cs @@ -180,7 +180,6 @@ public IEnumerator SenderGetStats() var test = new MonoBehaviourTest(); test.component.AddStream(0, videoStream); yield return test; - test.component.CoroutineUpdate(); yield return new WaitForSeconds(0.1f); var op = test.component.GetSenderStats(0, 0); yield return op; @@ -225,7 +224,6 @@ public IEnumerator ReceiverGetStats() var test = new MonoBehaviourTest(); test.component.AddStream(0, videoStream); yield return test; - test.component.CoroutineUpdate(); yield return new WaitForSeconds(0.1f); var op = test.component.GetReceiverStats(1, 0); yield return op; @@ -268,7 +266,6 @@ public IEnumerator SetParametersReturnNoError() var test = new MonoBehaviourTest(); test.component.AddStream(0, videoStream); yield return test; - test.component.CoroutineUpdate(); yield return new WaitForSeconds(0.1f); var senders = test.component.GetPeerSenders(0); @@ -311,7 +308,6 @@ public IEnumerator SetParametersReturnErrorIfInvalidTextureResolution() var test = new MonoBehaviourTest(); test.component.AddStream(0, videoStream); yield return test; - test.component.CoroutineUpdate(); yield return new WaitForSeconds(0.1f); var senders = test.component.GetPeerSenders(0); @@ -360,7 +356,6 @@ public IEnumerator AddAndRemoveTrack() var test = new MonoBehaviourTest(); test.component.AddStream(0, stream1); yield return test; - test.component.CoroutineUpdate(); yield return new WaitUntil(() => test.component.NegotiationCompleted()); bool calledOnAddTrack = false; @@ -398,7 +393,6 @@ public IEnumerator OnAddTrackDelegatesWithEvent() var test = new MonoBehaviourTest(); test.component.AddStream(0, videoStream); yield return test; - test.component.CoroutineUpdate(); yield return new WaitForSeconds(0.1f); bool isCalledOnAddTrack = false; diff --git a/Tests/Runtime/PeerConnectionTest.cs b/Tests/Runtime/PeerConnectionTest.cs index b21dc9b8a0..cb6842f8d9 100644 --- a/Tests/Runtime/PeerConnectionTest.cs +++ b/Tests/Runtime/PeerConnectionTest.cs @@ -1073,7 +1073,6 @@ public IEnumerator GetStatsReturnsReport() test.component.AddTransceiver(0, track1); test.component.AddTransceiver(1, track2); yield return test; - test.component.CoroutineUpdate(); var op1 = test.component.GetSenderStats(0, 0); var op2 = test.component.GetReceiverStats(0, 0); diff --git a/Tests/Runtime/SignalingPeers.cs b/Tests/Runtime/SignalingPeers.cs index 7fb807bc60..ded577c612 100644 --- a/Tests/Runtime/SignalingPeers.cs +++ b/Tests/Runtime/SignalingPeers.cs @@ -87,12 +87,6 @@ public IEnumerable GetPeerTransceivers(int indexPeer) return peers[indexPeer].GetTransceivers(); } - - public Coroutine CoroutineUpdate() - { - return StartCoroutine(WebRTC.Update()); - } - void Awake() { RTCConfiguration config = default; diff --git a/Tests/Runtime/TransceiverTest.cs b/Tests/Runtime/TransceiverTest.cs index 802967432d..698d7aa1ec 100644 --- a/Tests/Runtime/TransceiverTest.cs +++ b/Tests/Runtime/TransceiverTest.cs @@ -175,7 +175,6 @@ public IEnumerator ReceiverGetContributingSource() Assert.That(sources1, Is.Empty); yield return test; - test.component.CoroutineUpdate(); // wait for OnNegotiationNeeded callback in SignalingPeers class yield return new WaitUntil(() => test.component.NegotiationCompleted()); @@ -224,7 +223,6 @@ public IEnumerator TransceiverStop() var test = new MonoBehaviourTest(); test.component.AddTransceiver(0, track); yield return test; - test.component.CoroutineUpdate(); var senderTransceivers = test.component.GetPeerTransceivers(0); Assert.That(senderTransceivers.Count(), Is.EqualTo(1)); diff --git a/Tests/Runtime/TransformTest.cs b/Tests/Runtime/TransformTest.cs index e98b9d7736..bbb62640bf 100644 --- a/Tests/Runtime/TransformTest.cs +++ b/Tests/Runtime/TransformTest.cs @@ -175,7 +175,6 @@ void TransformedFrame(RTCTransformEvent e) yield return new WaitUntil(() => test.component.NegotiationCompleted()); yield return new WaitUntil(() => test.component.GetPeerReceivers(1).Any()); var receiver = test.component.GetPeerReceivers(1).First(); - test.component.CoroutineUpdate(); yield return new WaitUntil(() => raisedTransformedFrame); Assert.That(raisedTransformedFrame, Is.True); @@ -214,7 +213,6 @@ void TransformedFrame(RTCTransformEvent e) yield return new WaitUntil(() => test.component.NegotiationCompleted()); yield return new WaitUntil(() => test.component.GetPeerReceivers(1).Any()); var receiver = test.component.GetPeerReceivers(1).First(); - test.component.CoroutineUpdate(); yield return new WaitUntil(() => raisedTransformedFrame); Assert.That(raisedTransformedFrame, Is.True); diff --git a/Tests/Runtime/VideoReceiveTest.cs b/Tests/Runtime/VideoReceiveTest.cs index cf4b7f1abd..125fb189fd 100644 --- a/Tests/Runtime/VideoReceiveTest.cs +++ b/Tests/Runtime/VideoReceiveTest.cs @@ -130,7 +130,6 @@ class VideoReceivePeers : MonoBehaviour, IMonoBehaviourTest int width; int height; RTCRtpCodecCapability videoCodec; - Coroutine coroutine; void Start() { @@ -138,8 +137,6 @@ void Start() cam = camObj.AddComponent(); IsTestFinished = true; - - coroutine = StartCoroutine(WebRTC.Update()); } @@ -215,7 +212,6 @@ void OnDestroy() Clear(); DestroyImmediate(camObj); camObj = null; - StopCoroutine(coroutine); } private void Update()