コード例 #1
0
    public void SwapTransceivers()
    {
        Debug.Log($"{this} swapTransceivers");
        if (sendingTransceiverList.Count == 0)
        {
            var transceiver1 = pc.AddTransceiver(sourceVideoTrack1);
            transceiver1.Direction = RTCRtpTransceiverDirection.SendOnly;
            var transceiver2 = pc.AddTransceiver(sourceVideoTrack2);
            transceiver2.Direction = RTCRtpTransceiverDirection.Inactive;

            sendingTransceiverList.Add(transceiver1);
            sendingTransceiverList.Add(transceiver2);
            return;
        }

        if (sendingTransceiverList[0].CurrentDirection == RTCRtpTransceiverDirection.SendOnly)
        {
            sendingTransceiverList[0].Direction = RTCRtpTransceiverDirection.Inactive;
            sendingTransceiverList[0].Sender.ReplaceTrack(null);
            sendingTransceiverList[1].Direction = RTCRtpTransceiverDirection.SendOnly;
            sendingTransceiverList[1].Sender.ReplaceTrack(sourceVideoTrack2);
        }
        else
        {
            sendingTransceiverList[1].Direction = RTCRtpTransceiverDirection.Inactive;
            sendingTransceiverList[1].Sender.ReplaceTrack(null);
            sendingTransceiverList[0].Direction = RTCRtpTransceiverDirection.SendOnly;
            sendingTransceiverList[0].Sender.ReplaceTrack(sourceVideoTrack1);
        }
    }
コード例 #2
0
        public IEnumerator InitializeReceiver()
        {
            const int width  = 256;
            const int height = 256;

            var peer        = new RTCPeerConnection();
            var transceiver = peer.AddTransceiver(TrackKind.Video);

            Assert.That(transceiver, Is.Not.Null);
            RTCRtpReceiver receiver = transceiver.Receiver;

            Assert.That(receiver, Is.Not.Null);
            MediaStreamTrack track = receiver.Track;

            Assert.That(track, Is.Not.Null);
            Assert.AreEqual(TrackKind.Video, track.Kind);
            Assert.That(track.Kind, Is.EqualTo(TrackKind.Video));
            var videoTrack = track as VideoStreamTrack;

            Assert.That(videoTrack, Is.Not.Null);
            var rt = videoTrack.InitializeReceiver(width, height);

            Assert.That(videoTrack.IsDecoderInitialized, Is.True);
            videoTrack.Dispose();
            // wait for disposing video track.
            yield return(0);

            peer.Dispose();
            Object.DestroyImmediate(rt);
        }
コード例 #3
0
        public IEnumerator InitializeReceiver()
        {
            var peer        = new RTCPeerConnection();
            var transceiver = peer.AddTransceiver(TrackKind.Video);

            Assert.NotNull(transceiver);
            RTCRtpReceiver receiver = transceiver.Receiver;

            Assert.NotNull(receiver);
            MediaStreamTrack track = receiver.Track;

            Assert.NotNull(track);
            Assert.AreEqual(TrackKind.Video, track.Kind);
            var videoTrack = track as VideoStreamTrack;

            Assert.NotNull(videoTrack);
            var rt = videoTrack.InitializeReceiver(640, 320);

            Assert.True(videoTrack.IsDecoderInitialized);
            videoTrack.Dispose();
            // wait for disposing video track.
            yield return(0);

            peer.Dispose();
            Object.DestroyImmediate(rt);
        }
コード例 #4
0
        public void AddTransceiverWithInit()
        {
            var peer      = new RTCPeerConnection();
            var stream    = new MediaStream();
            var direction = RTCRtpTransceiverDirection.SendOnly;
            var width     = 256;
            var height    = 256;
            var format    = WebRTC.GetSupportedRenderTextureFormat(UnityEngine.SystemInfo.graphicsDeviceType);
            var rt        = new RenderTexture(width, height, 0, format);

            rt.Create();
            var track = new VideoStreamTrack(rt);
            var init  = new RTCRtpTransceiverInit()
            {
                direction     = direction,
                sendEncodings = new RTCRtpEncodingParameters[] {
                    new RTCRtpEncodingParameters {
                        maxFramerate = 30
                    }
                },
                streams = new MediaStream[] { stream }
            };
            var transceiver = peer.AddTransceiver(track, init);

            Assert.That(transceiver, Is.Not.Null);
            Assert.That(transceiver.CurrentDirection, Is.Null);
            Assert.That(transceiver.Direction, Is.EqualTo(RTCRtpTransceiverDirection.SendOnly));
            Assert.That(transceiver.Sender, Is.Not.Null);

            var parameters = transceiver.Sender.GetParameters();

            Assert.That(parameters, Is.Not.Null);
            Assert.That(parameters.codecs, Is.Not.Null.And.Empty);
            peer.Dispose();
        }
コード例 #5
0
        public void TransceiverSetAudioCodecPreferences()
        {
            var peer         = new RTCPeerConnection();
            var capabilities = RTCRtpSender.GetCapabilities(TrackKind.Audio);
            var transceiver  = peer.AddTransceiver(TrackKind.Audio);
            var error        = transceiver.SetCodecPreferences(capabilities.codecs);

            Assert.AreEqual(RTCErrorType.None, error);
        }
コード例 #6
0
        public IEnumerator CurrentDirection()
        {
            var config     = GetConfiguration();
            var peer1      = new RTCPeerConnection(ref config);
            var peer2      = new RTCPeerConnection(ref config);
            var audioTrack = new AudioStreamTrack("audio");

            var transceiver1 = peer1.AddTransceiver(TrackKind.Audio);

            transceiver1.Direction = RTCRtpTransceiverDirection.RecvOnly;
            Assert.IsNull(transceiver1.CurrentDirection);

            RTCOfferOptions options1 = new RTCOfferOptions {
                offerToReceiveAudio = true
            };
            RTCAnswerOptions options2 = default;
            var op1 = peer1.CreateOffer(ref options1);

            yield return(op1);

            var desc = op1.Desc;
            var op2  = peer1.SetLocalDescription(ref desc);

            yield return(op2);

            var op3 = peer2.SetRemoteDescription(ref desc);

            yield return(op3);

            var transceiver2 = peer2.GetTransceivers().First(x => x.Receiver.Track.Kind == TrackKind.Audio);

            Assert.True(transceiver2.Sender.ReplaceTrack(audioTrack));
            transceiver2.Direction = RTCRtpTransceiverDirection.SendOnly;

            var op4 = peer2.CreateAnswer(ref options2);

            yield return(op4);

            desc = op4.Desc;
            var op5 = peer2.SetLocalDescription(ref desc);

            yield return(op5);

            var op6 = peer1.SetRemoteDescription(ref desc);

            yield return(op6);

            Assert.AreEqual(transceiver1.CurrentDirection, RTCRtpTransceiverDirection.RecvOnly);
            Assert.AreEqual(transceiver2.CurrentDirection, RTCRtpTransceiverDirection.SendOnly);

            audioTrack.Dispose();
            peer1.Close();
            peer2.Close();
            peer1.Dispose();
            peer2.Dispose();
        }
コード例 #7
0
        public IEnumerator VideoReceive()
        {
            var config = new RTCConfiguration
            {
                iceServers = new[] { new RTCIceServer {
                                         urls = new[] { "stun:stun.l.google.com:19302" }
                                     } }
            };
            var pc1           = new RTCPeerConnection(ref config);
            var pc2           = new RTCPeerConnection(ref config);
            var sendStream    = new MediaStream();
            var receiveStream = new MediaStream();
            VideoStreamTrack receiveVideoTrack = null;
            RenderTexture    receiveImage      = null;

            receiveStream.OnAddTrack = e =>
            {
                if (e.Track is VideoStreamTrack track)
                {
                    receiveVideoTrack = track;
                    receiveImage      = receiveVideoTrack.InitializeReceiver(640, 320);
                }
            };
            pc2.OnTrack = e => receiveStream.AddTrack(e.Track);

            var camObj = new GameObject("Camera");
            var cam    = camObj.AddComponent <Camera>();

            cam.backgroundColor = Color.red;
            var sendVideoTrack = cam.CaptureStreamTrack(1280, 720, 1000000);

            yield return(new WaitForSeconds(0.1f));

            pc1.AddTrack(sendVideoTrack, sendStream);
            pc2.AddTransceiver(TrackKind.Video);

            yield return(SignalingPeers(pc1, pc2));

            yield return(new WaitUntil(() => receiveVideoTrack != null && receiveVideoTrack.IsDecoderInitialized));

            Assert.NotNull(receiveImage);

            sendVideoTrack.Update();
            yield return(new WaitForSeconds(0.1f));

            receiveVideoTrack.UpdateReceiveTexture();
            yield return(new WaitForSeconds(0.1f));

            receiveVideoTrack.Dispose();
            receiveStream.Dispose();
            sendVideoTrack.Dispose();
            sendStream.Dispose();
            pc2.Dispose();
            pc1.Dispose();
            Object.DestroyImmediate(receiveImage);
        }
コード例 #8
0
        public void AddTransceiver()
        {
            var peer   = new RTCPeerConnection();
            var stream = Audio.CaptureStream();
            var track  = stream.GetAudioTracks().First();

            Assert.AreEqual(0, peer.GetTransceivers().Count());
            var transceiver = peer.AddTransceiver(track);

            Assert.NotNull(transceiver);
            Assert.IsNull(transceiver.CurrentDirection);
            RTCRtpSender sender = transceiver.Sender;

            Assert.NotNull(sender);
            Assert.AreEqual(track, sender.Track);

            RTCRtpSendParameters parameters = sender.GetParameters();

            Assert.NotNull(parameters);
            Assert.NotNull(parameters.encodings);
            foreach (var encoding in parameters.encodings)
            {
                Assert.True(encoding.active);
                Assert.Null(encoding.maxBitrate);
                Assert.Null(encoding.minBitrate);
                Assert.Null(encoding.maxFramerate);
                Assert.Null(encoding.scaleResolutionDownBy);
                Assert.IsNotEmpty(encoding.rid);
            }
            Assert.IsNotEmpty(parameters.transactionId);
            Assert.AreEqual(1, peer.GetTransceivers().Count());
            Assert.NotNull(peer.GetTransceivers().First());
            Assert.NotNull(parameters.codecs);
            foreach (var codec in parameters.codecs)
            {
                Assert.NotNull(codec);
                Assert.NotZero(codec.payloadType);
                Assert.IsNotEmpty(codec.mimeType);
                Assert.IsNotEmpty(codec.sdpFmtpLine);
                Assert.Null(codec.clockRate);
                Assert.Null(codec.channels);
            }
            Assert.NotNull(parameters.rtcp);
            Assert.NotNull(parameters.headerExtensions);
            foreach (var extension in parameters.headerExtensions)
            {
                Assert.NotNull(extension);
                Assert.IsNotEmpty(extension.uri);
                Assert.NotZero(extension.id);
            }

            track.Dispose();
            stream.Dispose();
            peer.Dispose();
        }
コード例 #9
0
        public void AddTransceiverWithKindAndInit()
        {
            var peer      = new RTCPeerConnection();
            var stream    = new MediaStream();
            var direction = RTCRtpTransceiverDirection.SendOnly;
            var init      = new RTCRtpTransceiverInit()
            {
                direction     = direction,
                sendEncodings = new RTCRtpEncodingParameters[] {
                    new RTCRtpEncodingParameters {
                        maxFramerate = 30
                    }
                },
                streams = new MediaStream[] { stream }
            };
            var transceiver = peer.AddTransceiver(TrackKind.Video, init);

            Assert.That(transceiver, Is.Not.Null);
            Assert.That(transceiver.CurrentDirection, Is.Null);
            Assert.That(transceiver.Direction, Is.EqualTo(RTCRtpTransceiverDirection.SendOnly));
            Assert.That(transceiver.Sender, Is.Not.Null);

            var parameters = transceiver.Sender.GetParameters();

            Assert.That(parameters, Is.Not.Null);
            Assert.That(parameters.codecs, Is.Not.Null.And.Empty);

            var init2 = new RTCRtpTransceiverInit()
            {
                direction     = null,
                sendEncodings = null,
                streams       = null
            };
            var transceiver2 = peer.AddTransceiver(TrackKind.Video, init2);

            Assert.That(transceiver2, Is.Not.Null);
            Assert.That(transceiver2.CurrentDirection, Is.Null);
            Assert.That(transceiver2.Direction, Is.EqualTo(RTCRtpTransceiverDirection.SendRecv));
            Assert.That(transceiver2.Sender, Is.Not.Null);
            peer.Dispose();
        }
コード例 #10
0
        public void GetTransceiversReturnsNotEmptyAfterDisposingTransceiver()
        {
            // `RTCPeerConnection.AddTransceiver` method is not intuitive. Moreover, we don't have the API to remove
            // the transceiver from RTCPeerConnection directly.
            var peer        = new RTCPeerConnection();
            var transceiver = peer.AddTransceiver(TrackKind.Video);

            Assert.That(peer.GetTransceivers(), Has.Count.EqualTo(1));
            transceiver.Dispose();
            Assert.That(peer.GetTransceivers(), Has.Count.EqualTo(1));
            peer.Dispose();
        }
コード例 #11
0
        public void GetAndSetDirectionTransceiver()
        {
            var peer        = new RTCPeerConnection();
            var transceiver = peer.AddTransceiver(TrackKind.Video);

            Assert.NotNull(transceiver);
            transceiver.Direction = RTCRtpTransceiverDirection.SendOnly;
            Assert.AreEqual(RTCRtpTransceiverDirection.SendOnly, transceiver.Direction);
            transceiver.Direction = RTCRtpTransceiverDirection.RecvOnly;
            Assert.AreEqual(RTCRtpTransceiverDirection.RecvOnly, transceiver.Direction);

            peer.Close();
            peer.Dispose();
        }
コード例 #12
0
        public void SwapTransceivers()
        {
            Debug.Log($"{this} swapTransceivers");
            if (sendingTransceiverList.Count == 0)
            {
                var transceiver1 = pc.AddTransceiver(sourceVideoTrack1);
                transceiver1.Direction = RTCRtpTransceiverDirection.SendOnly;
                var transceiver2 = pc.AddTransceiver(sourceVideoTrack2);
                transceiver2.Direction = RTCRtpTransceiverDirection.Inactive;

                if (WebRTCSettings.UseVideoCodec != null)
                {
                    var codecs = new[] { WebRTCSettings.UseVideoCodec };
                    transceiver1.SetCodecPreferences(codecs);
                    transceiver2.SetCodecPreferences(codecs);
                }

                sendingTransceiverList.Add(transceiver1);
                sendingTransceiverList.Add(transceiver2);
                return;
            }

            if (sendingTransceiverList[0].CurrentDirection == RTCRtpTransceiverDirection.SendOnly)
            {
                sendingTransceiverList[0].Direction = RTCRtpTransceiverDirection.Inactive;
                sendingTransceiverList[0].Sender.ReplaceTrack(null);
                sendingTransceiverList[1].Direction = RTCRtpTransceiverDirection.SendOnly;
                sendingTransceiverList[1].Sender.ReplaceTrack(sourceVideoTrack2);
            }
            else
            {
                sendingTransceiverList[1].Direction = RTCRtpTransceiverDirection.Inactive;
                sendingTransceiverList[1].Sender.ReplaceTrack(null);
                sendingTransceiverList[0].Direction = RTCRtpTransceiverDirection.SendOnly;
                sendingTransceiverList[0].Sender.ReplaceTrack(sourceVideoTrack1);
            }
        }
コード例 #13
0
        public void AddTransceiver()
        {
            var peer   = new RTCPeerConnection();
            var stream = Audio.CaptureStream();
            var track  = stream.GetAudioTracks().First();

            Assert.AreEqual(0, peer.GetTransceivers().Count());
            var transceiver = peer.AddTransceiver(track);

            Assert.NotNull(transceiver);
            Assert.That(() => Assert.NotNull(transceiver.CurrentDirection), Throws.InvalidOperationException);
            Assert.NotNull(transceiver.Sender);
            Assert.AreEqual(1, peer.GetTransceivers().Count());
            Assert.NotNull(peer.GetTransceivers().First());
        }
コード例 #14
0
    private void OnGatherCandidate()
    {
        foreach (Transform child in candidateParent)
        {
            Destroy(child.gameObject);
        }
        gatherCandidatesButton.interactable = false;

        var configuration = GetSelectedSdpSemantics();

        _pc1 = new RTCPeerConnection(ref configuration);
        _pc1.OnIceCandidate            = OnIceCandidate;
        _pc1.OnIceGatheringStateChange = OnIceGatheringStateChange;
        _transceiver = _pc1.AddTransceiver(TrackKind.Video);
        StartCoroutine(CreateOffer(_pc1));
    }
コード例 #15
0
        public void AddTransceiver()
        {
            var peer   = new RTCPeerConnection();
            var width  = 256;
            var height = 256;
            var format = WebRTC.GetSupportedRenderTextureFormat(UnityEngine.SystemInfo.graphicsDeviceType);
            var rt     = new UnityEngine.RenderTexture(width, height, 0, format);

            rt.Create();

            var track = new VideoStreamTrack(rt);

            Assert.That(peer.GetTransceivers(), Is.Empty);
            var transceiver = peer.AddTransceiver(track);

            Assert.That(transceiver, Is.Not.Null);
            Assert.That(transceiver.Mid, Is.Null);
            Assert.That(transceiver.CurrentDirection, Is.Null);
            RTCRtpSender sender = transceiver.Sender;

            Assert.That(sender, Is.Not.Null);
            Assert.That(track, Is.EqualTo(sender.Track));

            RTCRtpSendParameters parameters = sender.GetParameters();

            Assert.That(parameters, Is.Not.Null);
            Assert.That(parameters.encodings, Is.Empty);
            Assert.That(parameters.transactionId, Is.Not.Empty);
            Assert.That(peer.GetTransceivers(), Has.Count.EqualTo(1));
            Assert.That(peer.GetTransceivers().First(), Is.Not.Null);
            Assert.That(parameters.codecs, Is.Empty);
            Assert.That(parameters.rtcp, Is.Not.Null);

            // Some platforms return an empty list
            Assert.That(parameters.headerExtensions, Is.Not.Null);
            foreach (var extension in parameters.headerExtensions)
            {
                Assert.That(extension, Is.Not.Null);
                Assert.That(extension.uri, Is.Not.Empty);
            }

            track.Dispose();
            peer.Dispose();
            Object.DestroyImmediate(rt);
        }
コード例 #16
0
        public void AddTransceiverTrackKindVideo()
        {
            var peer        = new RTCPeerConnection();
            var transceiver = peer.AddTransceiver(TrackKind.Video);

            Assert.NotNull(transceiver);
            Assert.IsNull(transceiver.CurrentDirection);
            RTCRtpReceiver receiver = transceiver.Receiver;

            Assert.NotNull(receiver);
            MediaStreamTrack track = receiver.Track;

            Assert.NotNull(track);
            Assert.AreEqual(TrackKind.Video, track.Kind);
            Assert.True(track is VideoStreamTrack);

            Assert.AreEqual(1, peer.GetTransceivers().Count());
            Assert.NotNull(peer.GetTransceivers().First());
        }
コード例 #17
0
        public void AddTransceiverTrackKindAudio()
        {
            var peer        = new RTCPeerConnection();
            var transceiver = peer.AddTransceiver(TrackKind.Audio);

            Assert.NotNull(transceiver);
            Assert.That(() => Assert.NotNull(transceiver.CurrentDirection), Throws.InvalidOperationException);
            RTCRtpReceiver receiver = transceiver.Receiver;

            Assert.NotNull(receiver);
            MediaStreamTrack track = receiver.Track;

            Assert.NotNull(track);
            Assert.AreEqual(TrackKind.Audio, track.Kind);
            Assert.True(track is AudioStreamTrack);

            Assert.AreEqual(1, peer.GetTransceivers().Count());
            Assert.NotNull(peer.GetTransceivers().First());
        }
コード例 #18
0
        public void SwitchTrack()
        {
            if (sendingTransceiver == null)
            {
                var transceiver = pc.AddTransceiver(sourceVideoTrack1);
                transceiver.Direction = RTCRtpTransceiverDirection.SendRecv;

                if (WebRTCSettings.UseVideoCodec != null)
                {
                    var codecs = new[] { WebRTCSettings.UseVideoCodec };
                    transceiver.SetCodecPreferences(codecs);
                }

                sendingTransceiver = transceiver;
                return;
            }

            var nextTrack = sendingTransceiver.Sender.Track == sourceVideoTrack1 ? sourceVideoTrack2 : sourceVideoTrack1;

            sendingTransceiver.Sender.ReplaceTrack(nextTrack);
        }
コード例 #19
0
        public void AddTransceiverTrackKindVideo()
        {
            var peer        = new RTCPeerConnection();
            var transceiver = peer.AddTransceiver(TrackKind.Video);

            Assert.That(transceiver, Is.Not.Null);
            Assert.That(transceiver.CurrentDirection, Is.Null);
            RTCRtpReceiver receiver = transceiver.Receiver;

            Assert.That(receiver, Is.Not.Null);
            MediaStreamTrack track = receiver.Track;

            Assert.That(track, Is.Not.Null);
            Assert.That(track.Kind, Is.EqualTo(TrackKind.Video));
            Assert.That(track, Is.TypeOf <VideoStreamTrack>());
            Assert.That(receiver.Streams, Has.Count.EqualTo(0));

            Assert.That(peer.GetTransceivers(), Has.Count.EqualTo(1));
            Assert.That(peer.GetTransceivers(), Has.All.Not.Null);

            peer.Dispose();
        }
コード例 #20
0
        public void ReceiverGetTrackReturnsAudioTrack()
        {
            var peer        = new RTCPeerConnection();
            var transceiver = peer.AddTransceiver(TrackKind.Audio);

            Assert.That(transceiver, Is.Not.Null);
            Assert.That(transceiver.CurrentDirection, Is.Null);

            // The receiver has a audio track
            RTCRtpReceiver receiver = transceiver.Receiver;

            Assert.That(receiver, Is.Not.Null);
            Assert.That(receiver.Track, Is.Not.Null);
            Assert.That(receiver.Track, Is.TypeOf <AudioStreamTrack>());

            // The receiver has no track
            RTCRtpSender sender = transceiver.Sender;

            Assert.That(sender, Is.Not.Null);
            Assert.That(sender.Track, Is.Null);

            peer.Dispose();
        }
コード例 #21
0
        public void AddTransceiver()
        {
            var peer   = new RTCPeerConnection();
            var stream = Audio.CaptureStream();
            var track  = stream.GetAudioTracks().First();

            Assert.AreEqual(0, peer.GetTransceivers().Count());
            var transceiver = peer.AddTransceiver(track);

            Assert.NotNull(transceiver);
            Assert.That(() => Assert.NotNull(transceiver.CurrentDirection), Throws.InvalidOperationException);
            RTCRtpSender sender = transceiver.Sender;

            Assert.NotNull(sender);
            Assert.AreEqual(track, sender.Track);

            RTCRtpSendParameters parameters = sender.GetParameters();

            Assert.NotNull(parameters);
            Assert.IsNotEmpty(parameters.TransactionId);
            Assert.AreEqual(1, peer.GetTransceivers().Count());
            Assert.NotNull(peer.GetTransceivers().First());
        }
コード例 #22
0
        public void AddTransceiver()
        {
            var peer   = new RTCPeerConnection();
            var stream = Audio.CaptureStream();
            var track  = stream.GetAudioTracks().First();

            Assert.AreEqual(0, peer.GetTransceivers().Count());
            var transceiver = peer.AddTransceiver(track);

            Assert.NotNull(transceiver);
            Assert.IsNull(transceiver.CurrentDirection);
            RTCRtpSender sender = transceiver.Sender;

            Assert.NotNull(sender);
            Assert.AreEqual(track, sender.Track);

            RTCRtpSendParameters parameters = sender.GetParameters();

            Assert.NotNull(parameters);
            Assert.NotNull(parameters.Encodings);
            foreach (var encoding in parameters.Encodings)
            {
                Assert.True(encoding.active);
                Assert.Null(encoding.maxBitrate);
                Assert.Null(encoding.minBitrate);
                Assert.Null(encoding.maxFramerate);
                Assert.Null(encoding.scaleResolutionDownBy);
                Assert.IsNotEmpty(encoding.rid);
            }
            Assert.IsNotEmpty(parameters.TransactionId);
            Assert.AreEqual(1, peer.GetTransceivers().Count());
            Assert.NotNull(peer.GetTransceivers().First());

            track.Dispose();
            stream.Dispose();
            peer.Dispose();
        }
コード例 #23
0
        public void AddTransceiverThrowException()
        {
            var peer = new RTCPeerConnection();

            Assert.Throws <ArgumentNullException>(() => peer.AddTransceiver(null));
        }
コード例 #24
0
        public IEnumerator CurrentDirection()
        {
            var config = GetDefaultConfiguration();
            var peer1  = new RTCPeerConnection(ref config);
            var peer2  = new RTCPeerConnection(ref config);
            var obj    = new GameObject("audio");
            var source = obj.AddComponent <AudioSource>();

            source.clip = AudioClip.Create("test", 480, 2, 48000, false);
            var audioTrack = new AudioStreamTrack(source);

            var transceiver1 = peer1.AddTransceiver(TrackKind.Audio);

            transceiver1.Direction = RTCRtpTransceiverDirection.RecvOnly;
            Assert.IsNull(transceiver1.CurrentDirection);

            var op1 = peer1.CreateOffer();

            yield return(op1);

            var desc = op1.Desc;
            var op2  = peer1.SetLocalDescription(ref desc);

            yield return(op2);

            var op3 = peer2.SetRemoteDescription(ref desc);

            yield return(op3);

            var transceiver2 = peer2.GetTransceivers().First(x => x.Receiver.Track.Kind == TrackKind.Audio);

            Assert.True(transceiver2.Sender.ReplaceTrack(audioTrack));
            transceiver2.Direction = RTCRtpTransceiverDirection.SendOnly;

            var op4 = peer2.CreateAnswer();

            yield return(op4);

            desc = op4.Desc;
            var op5 = peer2.SetLocalDescription(ref desc);

            yield return(op5);

            var op6 = peer1.SetRemoteDescription(ref desc);

            yield return(op6);

            Assert.AreEqual(transceiver1.CurrentDirection, RTCRtpTransceiverDirection.RecvOnly);
            Assert.AreEqual(transceiver2.CurrentDirection, RTCRtpTransceiverDirection.SendOnly);

            //Assert.That(transceiver2.Stop(), Is.EqualTo(RTCErrorType.None));
            //Assert.That(transceiver2.Direction, Is.EqualTo(RTCRtpTransceiverDirection.Stopped));

            // todo(kazuki):: Transceiver.CurrentDirection of Sender is not changed to "Stopped" even if waiting
            // yield return new WaitUntil(() => transceiver2.CurrentDirection == RTCRtpTransceiverDirection.Stopped);
            // Assert.That(transceiver2.CurrentDirection, Is.EqualTo(RTCRtpTransceiverDirection.Stopped));

            // todo(kazuki):: Transceiver.CurrentDirection of Receiver is not changed to "Stopped" even if waiting
            // yield return new WaitUntil(() => transceiver1.Direction == RTCRtpTransceiverDirection.Stopped);
            // Assert.That(transceiver1.Direction, Is.EqualTo(RTCRtpTransceiverDirection.Stopped));

            audioTrack.Dispose();
            peer1.Close();
            peer2.Close();
            peer1.Dispose();
            peer2.Dispose();
            Object.DestroyImmediate(source.clip);
            Object.DestroyImmediate(obj);
        }