/* * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using static Interop; namespace Tizen.Multimedia.Remoting { /// /// Provides the ability to control WebRTC. /// /// 9 public partial class WebRTC { private NativeWebRTC.ErrorOccurredCallback _webRtcErrorOccurredCallback; private NativeWebRTC.StateChangedCallback _webRtcStateChangedCallback; private NativeWebRTC.IceGatheringStateChangedCallback _webRtcIceGatheringStateChangedCallback; private NativeWebRTC.SignalingStateChangedCallback _webRtcSignalingStateChangedCallback; private NativeWebRTC.PeerConnectionStateChangedCallback _webRtcPeerConnectionStateChangedCallback; private NativeWebRTC.IceConnectionStateChangedCallback _webRtcIceConnectionStateChangedCallback; private NativeWebRTC.NegotiationNeededCallback _webRtcNegotiationNeededCallback; private NativeWebRTC.IceCandidateCallback _webRtcIceCandidateCallback; private NativeWebRTC.TrackAddedCallback _webRtcTrackAddedCallback; private NativeWebRTC.FrameEncodedCallback _webRtcAudioFrameEncodedCallback; private NativeWebRTC.FrameEncodedCallback _webRtcVideoFrameEncodedCallback; private NativeDataChannel.CreatedCallback _webRtcDataChannelCreatedCallback; /// /// Occurs when any error occurs. /// /// 9 public event EventHandler ErrorOccurred; /// /// Occurs when WebRTC state is changed. /// /// 9 public event EventHandler StateChanged; /// /// Occurs when the WebRTC ICE gathering state is changed. /// /// 9 public event EventHandler IceGatheringStateChanged; /// /// Occurs when the WebRTC signaling state is changed. /// /// 9 public event EventHandler SignalingStateChanged; /// /// Occurs when the WebRTC peer connection state is changed. /// /// 9 public event EventHandler PeerConnectionStateChanged; /// /// Occurs when the WebRTC ICE connection state is changed. /// /// 9 public event EventHandler IceConnectionStateChanged; /// /// Occurs when negotiation is needed. /// /// 9 public event EventHandler NegotiationNeeded; /// /// Occurs when the WebRTC needs to send the ICE candidate message to the remote peer. /// /// 9 public event EventHandler IceCandidate; /// /// Occurs when a new track has been added to the WebRTC. /// /// 9 public event EventHandler TrackAdded; private event EventHandler _audioFrameEncoded; /// /// Occurs when each audio frame is ready to render. /// /// 9 public event EventHandler AudioFrameEncoded { add { if (_audioFrameEncoded == null) { RegisterAudioFrameEncodedCallback(); } _audioFrameEncoded += value; } remove { _audioFrameEncoded -= value; if (_audioFrameEncoded == null) { UnregisterAudioFrameEncodedCallback(); } } } private event EventHandler _videoFrameEncoded; /// /// Occurs when each video frame is ready to render. /// /// 9 public event EventHandler VideoFrameEncoded { add { if (_videoFrameEncoded == null) { RegisterVideoFrameEncodedCallback(); } _videoFrameEncoded += value; } remove { _videoFrameEncoded -= value; if (_videoFrameEncoded == null) { UnregisterVideoFrameEncodedCallback(); } } } /// /// Occurs when the data channel is created to the connection by the remote peer. /// /// 9 public event EventHandler DataChannel; private void RegisterEvents() { RegisterErrorOccurredCallback(); RegisterStateChangedCallback(); RegisterIceGatheringStateChangedCallback(); RegisterSignalingStateChangedCallback(); RegisterPeerConnectionStateChangedCallback(); RegisterIceConnectionStateChangedCallback(); RegisterNegotiationNeededCallback(); RegisterIceCandidateCallback(); RegisterTrackAddedCallback(); RegisterDataChannelCreatedCallback(); } private void UnregisterEvents() { UnregisterErrorOccurredCallback(); UnregisterStateChangedCallback(); UnregisterIceGatheringStateChangedCallback(); UnregisterSignalingStateChangedCallback(); UnregisterPeerConnectionStateChangedCallback(); UnregisterIceConnectionStateChangedCallback(); UnregisterNegotiationNeededCallback(); UnregisterIceCandidateCallback(); UnregisterTrackAddedCallback(); UnregisterDataChannelCreatedCallback(); } private void RegisterErrorOccurredCallback() { _webRtcErrorOccurredCallback = (handle, error, state, _) => { // Log.Info(WebRTCLog.Tag, $"{error}, {state}"); ErrorOccurred?.Invoke(this, new WebRTCErrorOccurredEventArgs((WebRTCError)error, state)); }; NativeWebRTC.SetErrorOccurredCb(Handle, _webRtcErrorOccurredCallback). ThrowIfFailed("Failed to set error occurred callback."); } private void UnregisterErrorOccurredCallback() { NativeWebRTC.UnsetErrorOccurredCb(Handle). ThrowIfFailed("Failed to unset error occurred callback."); } private void RegisterStateChangedCallback() { _webRtcStateChangedCallback = (handle, previous, current, _) => { // Log.Info(WebRTCLog.Tag, $"{previous}, {current}"); StateChanged?.Invoke(this, new WebRTCStateChangedEventArgs(previous, current)); }; NativeWebRTC.SetStateChangedCb(Handle, _webRtcStateChangedCallback). ThrowIfFailed("Failed to set state changed callback."); } private void UnregisterStateChangedCallback() { NativeWebRTC.UnsetStateChangedCb(Handle). ThrowIfFailed("Failed to unset state changed callback."); } private void RegisterIceGatheringStateChangedCallback() { _webRtcIceGatheringStateChangedCallback = (handle, state, _) => { // Log.Info(WebRTCLog.Tag, $"Ice gathering state : {state}"); IceGatheringStateChanged?.Invoke(this, new WebRTCIceGatheringStateChangedEventArgs(state)); }; NativeWebRTC.SetIceGatheringStateChangedCb(Handle, _webRtcIceGatheringStateChangedCallback). ThrowIfFailed("Failed to set Ice gathering state changed callback."); } private void UnregisterIceGatheringStateChangedCallback() { NativeWebRTC.UnsetIceGatheringStateChangedCb(Handle). ThrowIfFailed("Failed to unset Ice gathering state changed callback."); } private void RegisterSignalingStateChangedCallback() { _webRtcSignalingStateChangedCallback = (handle, state, _) => { // Log.Info(WebRTCLog.Tag, $"Signaling state : {state}"); SignalingStateChanged?.Invoke(this, new WebRTCSignalingStateChangedEventArgs(state)); }; NativeWebRTC.SetSignalingStateChangedCb(Handle, _webRtcSignalingStateChangedCallback). ThrowIfFailed("Failed to set signaling state changed callback."); } private void UnregisterSignalingStateChangedCallback() { NativeWebRTC.UnsetSignalingStateChangedCb(Handle). ThrowIfFailed("Failed to unset signaling state changed callback."); } private void RegisterPeerConnectionStateChangedCallback() { _webRtcPeerConnectionStateChangedCallback = (handle, state, _) => { Log.Info(WebRTCLog.Tag, $"Peer connection state : {state}"); PeerConnectionStateChanged?.Invoke(this, new WebRTCPeerConnectionStateChangedEventArgs(state)); }; NativeWebRTC.SetPeerConnectionStateChangedCb(Handle, _webRtcPeerConnectionStateChangedCallback). ThrowIfFailed("Failed to set peer connection state changed callback."); } private void UnregisterPeerConnectionStateChangedCallback() { NativeWebRTC.UnsetPeerConnectionStateChangedCb(Handle). ThrowIfFailed("Failed to unset peer connection state changed callback."); } private void RegisterIceConnectionStateChangedCallback() { _webRtcIceConnectionStateChangedCallback = (handle, state, _) => { // Log.Info(WebRTCLog.Tag, $"Ice connection state : {state}"); IceConnectionStateChanged?.Invoke(this, new WebRTCIceConnectionStateChangedEventArgs(state)); }; NativeWebRTC.SetIceConnectionStateChangedCb(Handle, _webRtcIceConnectionStateChangedCallback). ThrowIfFailed("Failed to set ICE connection state changed callback."); } private void UnregisterIceConnectionStateChangedCallback() { NativeWebRTC.UnsetIceConnectionStateChangedCb(Handle). ThrowIfFailed("Failed to unset ICE connection state changed callback."); } private void RegisterNegotiationNeededCallback() { _webRtcNegotiationNeededCallback = (handle, _) => { NegotiationNeeded?.Invoke(this, new EventArgs()); }; NativeWebRTC.SetNegotiationNeededCb(Handle, _webRtcNegotiationNeededCallback). ThrowIfFailed("Failed to set negotiation needed callback."); } private void UnregisterNegotiationNeededCallback() { NativeWebRTC.UnsetNegotiationNeededCb(Handle). ThrowIfFailed("Failed to unset negotiation needed callback."); } private void RegisterIceCandidateCallback() { _webRtcIceCandidateCallback = (handle, candidate, _) => { IceCandidate?.Invoke(this, new WebRTCIceCandidateEventArgs(candidate)); }; NativeWebRTC.SetIceCandidateCb(Handle, _webRtcIceCandidateCallback). ThrowIfFailed("Failed to set ice candidate callback."); } private void UnregisterIceCandidateCallback() { NativeWebRTC.UnsetIceCandidateCb(Handle). ThrowIfFailed("Failed to unset ice candidate callback."); } private void RegisterTrackAddedCallback() { _webRtcTrackAddedCallback = (handle, type, id, _) => { // Log.Info(WebRTCLog.Tag, $"Track type[{type}], id[{id}]"); TrackAdded?.Invoke(this, new WebRTCTrackAddedEventArgs(new MediaStreamTrack(this, type, id))); }; NativeWebRTC.SetTrackAddedCb(Handle, _webRtcTrackAddedCallback). ThrowIfFailed("Failed to set track added callback."); } private void UnregisterTrackAddedCallback() { NativeWebRTC.UnsetTrackAddedCb(Handle). ThrowIfFailed("Failed to unset track added callback."); } private void RegisterAudioFrameEncodedCallback() { _webRtcAudioFrameEncodedCallback = (handle, type, id, packet, _) => { // Log.Info(WebRTCLog.Tag, $"Track type[{type}], id[{id}]"); _audioFrameEncoded?.Invoke(this, new WebRTCFrameEncodedEventArgs(new MediaStreamTrack(this, type, id), MediaPacket.From(packet))); }; NativeWebRTC.SetAudioFrameEncodedCb(Handle, _webRtcAudioFrameEncodedCallback). ThrowIfFailed("Failed to set audio frame encoded callback."); } private void UnregisterAudioFrameEncodedCallback() { NativeWebRTC.UnsetAudioFrameEncodedCb(Handle). ThrowIfFailed("Failed to unset audio frame encoded callback."); } private void RegisterVideoFrameEncodedCallback() { _webRtcVideoFrameEncodedCallback = (handle, type, id, packet, _) => { // Log.Info(WebRTCLog.Tag, $"Track type[{type}], id[{id}]"); _videoFrameEncoded?.Invoke(this, new WebRTCFrameEncodedEventArgs(new MediaStreamTrack(this, type, id), MediaPacket.From(packet))); }; NativeWebRTC.SetVideoFrameEncodedCb(Handle, _webRtcVideoFrameEncodedCallback). ThrowIfFailed("Failed to set video frame encoded callback."); } private void UnregisterVideoFrameEncodedCallback() { NativeWebRTC.UnsetVideoFrameEncodedCb(Handle). ThrowIfFailed("Failed to unset video frame encoded callback."); } private void RegisterDataChannelCreatedCallback() { _webRtcDataChannelCreatedCallback = (handle, dataChannelHandle, _) => { // Log.Debug(WebRTCLog.Tag, "Invoked"); DataChannel?.Invoke(this, new WebRTCDataChannelEventArgs(dataChannelHandle)); }; NativeDataChannel.SetCreatedByPeerCb(Handle, _webRtcDataChannelCreatedCallback). ThrowIfFailed("Failed to set data channel created callback."); } private void UnregisterDataChannelCreatedCallback() { NativeDataChannel.UnsetCreatedByPeerCb(Handle). ThrowIfFailed("Failed to unset data channel created callback."); } } }