public IRTCRtpSender AddTrack(IMediaStreamTrack track, IMediaStream stream) => RTCRtpSender.Create(JsRuntime, JsRuntime.CallJsMethod <JsObjectRef>(NativeObject, "addTrack", new object[] { ((MediaStreamTrack)track).NativeObject, ((MediaStream)stream).NativeObject }));
void Peer_OnAddRemoteTrack(IMediaStreamTrack track) { Logger.Debug("MediaChannel", "@peer:remote_track:add"); RunOnUiThread(() => { if (remoteTracksHolder.AddTrack(track)) { var streamId = streamIdChecker.GetStreamIdForTrackId(track.Id); Logger.Debug("MediaChannel", $"streamId:{streamId}"); if (mediaOption.UpstreamIsRequired() && clientId == streamId) { Logger.Debug("MediaChannel", "ignore, this track is mine"); return; } if (track.Kind == "audio") { OnAddRemoteAudioTrack?.Invoke(track); } else if (track.Kind == "video") { OnAddRemoteVideoTrack?.Invoke(track); } } }); }
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs args) { base.OnElementPropertyChanged(sender, args); if (args.PropertyName == Media.StreamProperty.PropertyName) { _stream = Element.Stream; _videoTrack = Element.Stream.GetVideoTracks().FirstOrDefault(); _audioTrack = _stream.GetAudioTracks().FirstOrDefault(); _mediaView.SetTrack(_videoTrack); } else if (args.PropertyName == Media.LabelProperty.PropertyName) { _label = Element.Label; } else if (args.PropertyName == Media.HangupProperty.PropertyName) { _hangup = Element.Hangup; } else if (args.PropertyName == Media.VideoMutedProperty.PropertyName) { } else if (args.PropertyName == Media.AudioMutedProperty.PropertyName) { } else if (args.PropertyName == Media.CameraTypeProperty.PropertyName) { _cameraType = Element.CameraType; } else if (args.PropertyName == Media.ShowControlsProperty.PropertyName) { _showControls = Element.ShowControls; } }
private void PeerConnection_OnTrack(IRTCTrackEvent Event) { if (Event.Track.Kind == "video") { _peerVideoTrack = Event.Track; if (_peerVideoTrack != null) { _peerVideoTrack.Element = MediaElementMaker.Bind(Devices.Instance.PeerVideo); ((MediaStreamTrack)_peerVideoTrack).OnFrameRateChanged += (float frameRate) => { FramesPerSecondChanged?.Invoke("PEER", frameRate.ToString("0.0")); }; ((MediaStreamTrack)_peerVideoTrack).OnResolutionChanged += (uint width, uint height) => { ResolutionChanged?.Invoke("PEER", width, height); }; } } else if (Event.Track.Kind == "audio") { _peerAudioTrack = Event.Track; } OnAddRemoteTrack?.Invoke(Event.Track); }
public Task Shutdown() { if (this.peerConnection != null) { this.peerConnection.OnIceCandidate -= this.peerConnection_OnIceCandidate; this.peerConnection.OnTrack -= this.peerConnection_OnTrack; if (this.remoteVideoTrack != null) { this.remoteVideoTrack.Element = null; } if (this.localVideoTrack != null) { this.localVideoTrack.Element = null; } (this.remoteVideoTrack as IDisposable)?.Dispose(); (this.localVideoTrack as IDisposable)?.Dispose(); (this.remoteAudioTrack as IDisposable)?.Dispose(); (this.localAudioTrack as IDisposable)?.Dispose(); this.remoteVideoTrack = null; this.localVideoTrack = null; this.remoteAudioTrack = null; this.localAudioTrack = null; (this.peerConnection as IDisposable)?.Dispose(); this.peerConnection = null; GC.Collect(); } return(Task.CompletedTask); }
public Task Shutdown() { foreach (RTCPeerConnection pc in this.peerConnections) { pc.OnIceCandidate -= this.peerConnection_OnIceCandidate; pc.OnTrack -= this.peerConnection_OnTrack; (pc as IDisposable)?.Dispose(); } this.peerConnections.Clear(); if (this.remoteVideoTrack != null) { this.remoteVideoTrack.Element = null; } if (this.localVideoTrack != null) { this.localVideoTrack.Element = null; } (this.remoteVideoTrack as IDisposable)?.Dispose(); (this.localVideoTrack as IDisposable)?.Dispose(); (this.remoteAudioTrack as IDisposable)?.Dispose(); (this.localAudioTrack as IDisposable)?.Dispose(); this.remoteVideoTrack = null; this.localVideoTrack = null; this.remoteAudioTrack = null; this.localAudioTrack = null; GC.Collect(); return(Task.CompletedTask); }
public void SetTrack(IMediaStreamTrack videoTrack) { var cameraDevices = Webrtc.RTCCameraVideoCapturer.CaptureDevices; _isCamera = cameraDevices.Any(device => device.ModelID == videoTrack.Id); var nativeVideoTrack = videoTrack.NativeObject as Webrtc.RTCVideoTrack; if (_isCamera) { _cameraView = new Webrtc.RTCCameraPreviewView(); AddSubview(_cameraView); var nativeVideoSource = nativeVideoTrack.Source; /*var*/ _videoCapturer = new Webrtc.RTCCameraVideoCapturer(); _videoCapturer.Delegate = nativeVideoSource; var cameraDevice = Webrtc.RTCCameraVideoCapturer.CaptureDevices //// .FirstOrDefault(device => device.Position == cameraType.ToNative()); // Get the selected device by matching RTCMediaStreamTrack.TrackId with AVCaptureDevice.ModelID from // RTCCameraVideoCapturer.CaptureDevices list. .Single(device => device.ModelID == videoTrack.Id); var formats = Webrtc.RTCCameraVideoCapturer.SupportedFormatsForDevice(cameraDevice); System.Diagnostics.Debug.WriteLine($"============= Capture Formats =============== "); int index = 0; foreach (var f in formats) { CMVideoFormatDescription desc = (CMVideoFormatDescription)f.FormatDescription; var dim = desc.Dimensions; var maxSupportedFps = 0d; foreach (var fpsRange in f.VideoSupportedFrameRateRanges) { maxSupportedFps = Math.Max(maxSupportedFps, fpsRange.MaxFrameRate); } System.Diagnostics.Debug.WriteLine($"index:{index++} width:{dim.Width} height:{dim.Height} fpsMax:{maxSupportedFps}"); } var format = Webrtc.RTCCameraVideoCapturer.SupportedFormatsForDevice(cameraDevice)[6 /*0*/]; CMVideoFormatDescription videoFormatDescription = (CMVideoFormatDescription)format.FormatDescription; var capturerDimensions = videoFormatDescription.Dimensions; var capturerSize = new CGSize(capturerDimensions.Width, capturerDimensions.Height); var fps = 30; _videoCapturer.StartCaptureWithDevice(cameraDevice, format, fps); _cameraView.CaptureSession = _videoCapturer.CaptureSession; } else { _rendererView = new Webrtc.RTCEAGLVideoView(); _rendererView.Delegate = this; AddSubview(_rendererView); nativeVideoTrack.AddRenderer(_rendererView); } SetNeedsLayout(); }
public IRtpTransceiver AddTransceiverWithTrack(IMediaStreamTrack track) { var rtpTransceiver = _peerConnection.AddTransceiverWithTrack(track.ToNative <RTCMediaStreamTrack>()); if (rtpTransceiver == null) { return(null); } return(new RtpTransceiverNative(rtpTransceiver)); }
public IRtpSender AddTrack(IMediaStreamTrack track, string[] streamIds) { var rtpSender = _peerConnection.AddTrack(track.ToNative <RTCMediaStreamTrack>(), streamIds); if (rtpSender == null) { return(null); } return(new RtpSenderNative(rtpSender)); }
public static void SetNativeMediaSource(this IMediaStreamTrack track, Webrtc.MediaSource nativeSource) { if (_mediaSourceStore.ContainsKey(track.Id)) { _mediaSourceStore[track.Id] = nativeSource; } else { _mediaSourceStore.Add(track.Id, nativeSource); } }
void Channel_OnRemoveRemoteVideoTrack(string trackId) { Sora.Logger.Debug("ViewModel", "Channel_OnRemoveRemoteVideo"); if (remoteVideoTrack != null) { Sora.Logger.Debug("ViewModel", "try to unbound video from view"); remoteVideoTrack.Element = null; remoteVideoTrack = null; Sora.Logger.Debug("ViewModel", "unbound video from view"); } }
public async Task ReplaceTrackAsync(IMediaStreamTrack track) { if (Closed) { // This must be done here. Otherwise there is no chance to stop the given track. if (track is not null && _stopTracks) { try { track.Stop(); } catch { } } throw new Exception("closed"); } else if (track is not null && track.ReadyState == MediaStreamTrackState.Ended) { throw new Exception("track ended"); } // Do nothing if this is the same track as the current handled one. if (track == Track) { Console.WriteLine("replaceTrack() | same track, ignored"); return; } if (!_zeroRtpOnPause || !Paused) { await OnReplaceTrackAsync?.Invoke(this, track); } // Destroy the previous track. DestroyTrack(); // Set the new track. Track = track; // If this Producer was paused/resumed and the state of the new // track does not match, fix it. if (Track is not null && _disableTrackOnPause) { if (!Paused) { Track.Enabled = true; } else if (Paused) { Track.Enabled = false; } } // Handle the effective track. HandleTrack(); }
void Channel_OnAddRemoteAudioTrack(IMediaStreamTrack track) { Sora.Logger.Debug("ViewModel", "Channel_OnAddRemoteAudio"); if (remoteAudioTrack != null) { Sora.Logger.Debug("ViewModel", "remote audio already exists"); return; } remoteAudioTrack = track; remoteAudioTrack.Enabled = true; }
public IRTCRtpTransceiver AddTransceiver(IMediaStreamTrack track, RTCRtpTransceiverInit init) { if (init is null) { return(RTCRtpTransceiver.Create(((Webrtc.RTCPeerConnection)NativeObject).AddTransceiverWithTrack( (Webrtc.RTCMediaStreamTrack)track.NativeObject))); } else { return(RTCRtpTransceiver.Create(((Webrtc.RTCPeerConnection)NativeObject).AddTransceiverWithTrack( (Webrtc.RTCMediaStreamTrack)track.NativeObject, init.ToNative()))); } }
void Channel_OnAddLocalAudioTrack(IMediaStreamTrack track) { Sora.Logger.Debug("ViewModel", "Channel_OnAddLocalAudio"); if (localAudioTrack != null) { Sora.Logger.Debug("ViewModel", "local audio already exists"); return; } localAudioTrack = track; localAudioTrack.Enabled = true; }
void Peer_OnAddLocalAudioTrack(IMediaStreamTrack track) { Logger.Debug("MediaChannel", "@peer:local_audio_track:add"); if (localAudioTrack == null) { localAudioTrack = track; } RunOnUiThread(() => { OnAddLocalAudioTrack?.Invoke(track); }); }
void Peer_OnAddLocalVideoTrack(IVideoCapturer capturer, IMediaStreamTrack track) { Logger.Debug("MediaChannel", "@peer:local_video_track:add"); if (localVideoTrack == null) { localVideoTrack = track; } RunOnUiThread(() => { OnAddLocalVideoTrack?.Invoke(capturer, track); }); }
void Channel_OnAddRemoteVideoTrack(IMediaStreamTrack track) { Sora.Logger.Debug("ViewModel", "Channel_OnAddRemoteVideo"); // TODO check trackId if (remoteVideoTrack == null) { Sora.Logger.Debug("ViewModel", "try to bind video to view"); remoteVideoTrack = track; remoteVideoTrack.Element = MediaElementMaker.Bind(RemoteVideoView); Sora.Logger.Debug("ViewModel", "bound video to view"); } }
public void RemoveTrack(IMediaStreamTrack track) { switch (track.Kind) { case MediaStreamTrackKind.Video: ((Webrtc.MediaStream)NativeObject).RemoveTrack(track.NativeObject as Webrtc.VideoTrack); break; case MediaStreamTrackKind.Audio: ((Webrtc.MediaStream)NativeObject).RemoveTrack(track.NativeObject as Webrtc.AudioTrack); break; } ; }
private async Task <RTCPeerConnection> buildPeerConnection(MediaOptions mediaOptions) { return(await Task.Run(() => { var factory = new WebRtcFactory(new WebRtcFactoryConfiguration()); var peerConnection = new RTCPeerConnection( new RTCConfiguration() { Factory = factory, BundlePolicy = RTCBundlePolicy.Balanced, IceTransportPolicy = RTCIceTransportPolicy.All }); peerConnection.OnTrack += this.peerConnection_OnTrack; if ((mediaOptions.SendVideo || mediaOptions.LocalLoopback) && this.localVideoTrack == null) { if (mediaOptions.SendVideo || mediaOptions.LocalLoopback) { this.localVideoTrack = this.getLocalVideo(factory); } } if (mediaOptions.SendAudio && this.localAudioTrack == null) { if (mediaOptions.SendAudio) { this.localAudioTrack = this.getLocalAudio(factory); } } if (mediaOptions.SendVideo) { peerConnection.AddTrack(this.localVideoTrack); } if (mediaOptions.SendAudio) { peerConnection.AddTrack(this.localAudioTrack); } if (mediaOptions.LocalLoopback) { this.localVideoTrack.Element = MediaElementMaker.Bind(this.localVideo); } return peerConnection; })); }
public Task ReplaceOutgoingTrackAsync(IMediaStreamTrack track, IMediaStreamTrack newTrack) { foreach (var peerContext in _connectionContext.PeerContexts) { var peerConnection = peerContext.PeerConnection; peerConnection .GetSenders() //.Where(sender => sender.Track.Kind == MediaStreamTrackKind.Video) //.Select(sender => sender.ReplaceTrack(newVideoTrack)); .First(sender => sender.Track.Kind == track.Kind) .ReplaceTrack(newTrack); } return(Task.CompletedTask); }
public bool AddTrack(IMediaStreamTrack track) { if (track.Kind == "audio" && !audioTracks.ContainsKey(track.Id)) { audioTracks[track.Id] = track; return(true); } if (track.Kind == "video" && !videoTracks.ContainsKey(track.Id)) { videoTracks[track.Id] = track; return(true); } return(false); }
public Consumer(string id, string localId, string producerId, IRTCRtpReceiver rtpReceiver, IMediaStreamTrack track, RtpParameters rtpParameters, Dictionary <string, object> appData) { Id = id; LocalId = localId; ProducerId = producerId; RtpReceiver = rtpReceiver; Track = track; RtpParameters = rtpParameters; AppData = appData; Paused = !track.Enabled; Closed = false; HandleTrack(); }
void Channel_OnAddLocalVideoTrack( IVideoCapturer capturer, IMediaStreamTrack track) { Sora.Logger.Debug("ViewModel", "Channel_OnAddLocalVideo"); if (localVideoTrack != null) { Debug.WriteLine("local video track already exists"); return; } localVideoTrack = track; localVideoTrack.Enabled = true; localVideoTrack.Element = MediaElementMaker.Bind(LocalVideoView); }
public void RemoveTrack(IMediaStreamTrack track) { if (GetTrackById(track.Id) != null) { switch (track.Kind) { case MediaStreamTrackKind.Audio: ((Webrtc.RTCMediaStream)NativeObject).RemoveAudioTrack((Webrtc.RTCAudioTrack)track.NativeObject); break; case MediaStreamTrackKind.Video: ((Webrtc.RTCMediaStream)NativeObject).RemoveVideoTrack((Webrtc.RTCVideoTrack)track.NativeObject); break; } } ; }
private void peerConnection_OnTrack(IRTCTrackEvent ev) { if (ev.Track.Kind == "video") { this.remoteVideoTrack = ev.Track; if (this.mediaOptions.ReceiveVideo) { this.remoteVideoTrack.Element = MediaElementMaker.Bind(this.remoteVideo); } } else if (ev.Track.Kind == "audio") { if (this.mediaOptions.ReceiveAudio) { this.remoteAudioTrack = ev.Track; } } }
public Producer(string id, string localId, IRTCRtpSender rtpSender, IMediaStreamTrack track, RtpParameters rtpParameters, bool stopTracks, bool disableTrackOnPause, bool zeroRtpOnPause, Dictionary <string, object> appData) { Id = id; LocalId = localId; RtpSender = rtpSender; Track = track; RtpParameters = rtpParameters; _stopTracks = stopTracks; _disableTrackOnPause = disableTrackOnPause; _zeroRtpOnPause = zeroRtpOnPause; AppData = appData; Kind = track.Kind.ToMediaSoup(); Paused = disableTrackOnPause ? !Track.Enabled : false; HandleTrack(); }
void ClosePeer() { Logger.Debug("MediaChannel", "Close Peer"); if (peer == null) { Logger.Debug("MediaChannel", "peer not found"); return; } peer.OnConnect -= Peer_OnConnect; peer.OnClose -= Peer_OnClose; peer.OnError -= Peer_OnError; peer.OnIceCandidate -= Peer_OnIceCandidate; peer.OnAddLocalAudioTrack -= Peer_OnAddLocalAudioTrack; peer.OnAddLocalVideoTrack -= Peer_OnAddLocalVideoTrack; peer.OnAddRemoteTrack -= Peer_OnAddRemoteTrack; peer.OnRemoveRemoteTrack -= Peer_OnRemoveRemoteTrack; Logger.Debug("MediaChannel", "dispose local media tracks"); if (localAudioTrack != null) { Logger.Debug("MediaChannel", "dispose local audio track"); (localAudioTrack as IDisposable)?.Dispose(); localAudioTrack = null; } if (localVideoTrack != null) { Logger.Debug("MediaChannel", "dispose local video track"); (localVideoTrack as IDisposable)?.Dispose(); localVideoTrack = null; } Logger.Debug("MediaChannel", "dispose remote media tracks"); remoteTracksHolder.Dispose(); Logger.Debug("MediaChannel", "Close Peer"); peer.Close(); peer = null; }
public void Stop() { if (mediaChannel == null) { Debug.WriteLine("media channel is already stopped"); return; } mediaChannel.OnConnect -= Channel_OnConnect; mediaChannel.OnDisconnect -= Channel_OnDisconnect; mediaChannel.OnError -= Channel_OnError; mediaChannel.OnAddRemoteAudioTrack -= Channel_OnAddRemoteAudioTrack; mediaChannel.OnRemoveRemoteAudioTrack -= Channel_OnRemoveRemoteAudioTrack; mediaChannel.OnAddRemoteVideoTrack -= Channel_OnAddRemoteVideoTrack; mediaChannel.OnRemoveRemoteVideoTrack -= Channel_OnRemoveRemoteVideoTrack; mediaChannel.OnAddLocalVideoTrack -= Channel_OnAddLocalVideoTrack; mediaChannel.OnAddLocalAudioTrack -= Channel_OnAddLocalAudioTrack; localAudioTrack = null; remoteAudioTrack = null; if (localVideoTrack != null) { localVideoTrack.Element = null; localVideoTrack = null; } if (remoteVideoTrack != null) { remoteVideoTrack.Element = null; remoteVideoTrack = null; } mediaChannel.Disconnect(); mediaChannel = null; StateText = "OFFLINE"; IsRunning = false; IsNotRunning = true; }
/// <summary> /// Closes a peer connection. /// </summary> public void ClosePeerConnection() { lock (MediaLock) { if (PeerConnection != null) { _peerId = -1; PeerConnection.OnIceCandidate -= PeerConnection_OnIceCandidate; PeerConnection.OnTrack -= PeerConnection_OnTrack; PeerConnection.OnRemoveTrack -= PeerConnection_OnRemoveTrack; if (_peerVideoTrack != null) { _peerVideoTrack.Element = null; } if (_selfVideoTrack != null) { _selfVideoTrack.Element = null; } (_peerVideoTrack as IDisposable)?.Dispose(); (_peerAudioTrack as IDisposable)?.Dispose(); (_selfVideoTrack as IDisposable)?.Dispose(); (_selfAudioTrack as IDisposable)?.Dispose(); _peerVideoTrack = null; _peerAudioTrack = null; _selfVideoTrack = null; _selfAudioTrack = null; OnPeerConnectionClosed?.Invoke(); PeerConnection = null; OnReadyToConnect?.Invoke(); GC.Collect(); // Ensure all references are truly dropped. } } }