/*
* 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.");
}
}
}