/// <summary> /// Create a new transceiver associated with a given peer connection. /// </summary> /// <param name="handle">Handle to the native transceiver object.</param> /// <param name="mediaKind">The media kind of the transceiver and its tracks.</param> /// <param name="peerConnection">The peer connection owning this transceiver.</param> /// <param name="mlineIndex">The transceiver media line index in SDP.</param> /// <param name="name">The transceiver name.</param> /// <param name="streamIDs">Collection of stream IDs the transceiver is associated with, as set by the peer which created it.</param> /// <param name="initialDesiredDirection">Initial value to initialize <see cref="DesiredDirection"/> with.</param> internal Transceiver(TransceiverInterop.TransceiverHandle handle, MediaKind mediaKind, PeerConnection peerConnection, int mlineIndex, string name, string[] streamIDs, Direction initialDesiredDirection) { Debug.Assert(!handle.IsClosed); _nativeHandle = handle; MediaKind = mediaKind; PeerConnection = peerConnection; MlineIndex = mlineIndex; Name = name; StreamIDs = streamIDs; _desiredDirection = initialDesiredDirection; TransceiverInterop.RegisterCallbacks(this, out _argsRef); }
/// <summary> /// Change the local audio track sending data to the remote peer. /// /// This detaches the previous local audio track if any, and attaches the new one instead. /// Note that the transceiver will only send some audio data to the remote peer if its /// negotiated direction includes sending some data and it has an attached local track to /// produce this data. /// /// This change is transparent to the session, and does not trigger any renegotiation. /// </summary> /// <param name="track">The new local audio track attached to the transceiver, and used to /// produce audio data to send to the remote peer if the transceiver is sending. /// Passing <c>null</c> is allowed, and will detach the current track if any.</param> private void SetLocalTrackImpl(MediaTrack track) { if (track == _localTrack) { return; } var audioTrack = (track as LocalAudioTrack); var videoTrack = (track as LocalVideoTrack); if ((audioTrack != null) && (MediaKind != MediaKind.Audio)) { throw new ArgumentException("Cannot set local audio track as local track of video transceiver"); } if ((videoTrack != null) && (MediaKind != MediaKind.Video)) { throw new ArgumentException("Cannot set local video track as local track of audio transceiver"); } if (track != null) { if ((track.PeerConnection != null) && (track.PeerConnection != PeerConnection)) { throw new InvalidOperationException($"Cannot set track {track} of peer connection {track.PeerConnection} on transceiver {this} of different peer connection {PeerConnection}."); } uint res = Utils.MRS_E_UNKNOWN; if (audioTrack != null) { res = TransceiverInterop.Transceiver_SetLocalAudioTrack(_nativeHandle, audioTrack._nativeHandle); } else if (videoTrack != null) { res = TransceiverInterop.Transceiver_SetLocalVideoTrack(_nativeHandle, videoTrack._nativeHandle); } Utils.ThrowOnErrorCode(res); } else { // Note: Cannot pass null for SafeHandle parameter value (ArgumentNullException) uint res = Utils.MRS_E_UNKNOWN; if (MediaKind == MediaKind.Audio) { res = TransceiverInterop.Transceiver_SetLocalAudioTrack(_nativeHandle, new LocalAudioTrackHandle()); } else if (MediaKind == MediaKind.Video) { res = TransceiverInterop.Transceiver_SetLocalVideoTrack(_nativeHandle, new LocalVideoTrackHandle()); } Utils.ThrowOnErrorCode(res); } // Remove old track if (_localTrack != null) { Debug.Assert(_localTrack.Transceiver == this); Debug.Assert(_localTrack.PeerConnection == PeerConnection); _localTrack.Transceiver = null; _localTrack.PeerConnection = null; _localTrack = null; } // Add new track if (track != null) { Debug.Assert(track.Transceiver == null); Debug.Assert(track.PeerConnection == null); _localTrack = track; _localTrack.Transceiver = this; _localTrack.PeerConnection = PeerConnection; } }