using System.Runtime.InteropServices;
using Tizen;
using Tizen.Applications;
+using Tizen.Internals;
using Tizen.Multimedia;
using Tizen.Multimedia.Remoting;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void SdpCreatedCallback(IntPtr handle, string sdp, IntPtr userData);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate bool RetrieveStatsCallback(WebRTCStatisticsCategory category, IntPtr prop, IntPtr userData);
+
[DllImport(Libraries.WebRTC, EntryPoint = "webrtc_create")]
internal static extern WebRTCErrorCode Create(out WebRTCHandle handle);
[DllImport(Libraries.WebRTC, EntryPoint = "webrtc_foreach_media_source_supported_format")]
internal static extern WebRTCErrorCode SupportedMediaSourceFormat(IntPtr handle, SupportedMediaFormatCallback callback, IntPtr userData);
+ [DllImport(Libraries.WebRTC, EntryPoint = "webrtc_foreach_stats")]
+ internal static extern WebRTCErrorCode ForeachStats(IntPtr handle, int typeMask, RetrieveStatsCallback callback, IntPtr userData = default);
+
[DllImport(Libraries.WebRTC, EntryPoint = "webrtc_set_error_cb")]
internal static extern WebRTCErrorCode SetErrorOccurredCb(IntPtr handle, ErrorOccurredCallback callback, IntPtr userData = default);
[DllImport(Libraries.WebRTC, EntryPoint = "webrtc_unset_encoded_video_frame_cb")]
internal static extern WebRTCErrorCode UnsetVideoFrameEncodedCb(IntPtr handle);
+
+ [StructLayout(LayoutKind.Explicit)]
+ internal struct StatsPropertyValueStruct
+ {
+ [FieldOffsetAttribute(0)]
+ internal bool @bool;
+ [FieldOffsetAttribute(0)]
+ internal int @int;
+ [FieldOffsetAttribute(0)]
+ internal uint @uint;
+ [FieldOffsetAttribute(0)]
+ internal long @long;
+ [FieldOffsetAttribute(0)]
+ internal ulong @ulong;
+ [FieldOffsetAttribute(0)]
+ internal float @float;
+ [FieldOffsetAttribute(0)]
+ internal double @double;
+ [FieldOffsetAttribute(0)]
+ internal IntPtr @string;
+ }
+
+ [NativeStruct("webrtc_stats_prop_info_s", Include="webrtc.h", PkgConfig="capi-media-webrtc")]
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct StatsPropertyStruct
+ {
+ internal string name;
+ internal WebRTCStatisticsProperty property;
+ internal WebRTCStatsPropertyType propertyType;
+ internal StatsPropertyValueStruct value;
+ }
}
internal class WebRTCHandle : SafeHandle
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
+using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Tizen.Applications;
}
/// <summary>
- /// Gets all turn servers.
+ /// Retrieves all turn servers.
/// </summary>
/// <returns>The turn server list.</returns>
/// <exception cref="ObjectDisposedException">The WebRTC has already been disposed.</exception>
var list = new List<string>();
- NativeWebRTC.RetrieveTurnServerCallback callback = (server, _) =>
+ NativeWebRTC.RetrieveTurnServerCallback cb = (server, _) =>
{
if (!string.IsNullOrWhiteSpace(server))
{
return true;
};
- NativeWebRTC.ForeachTurnServer(Handle, callback).ThrowIfFailed("Failed to retrieve turn server");
+ NativeWebRTC.ForeachTurnServer(Handle, cb).ThrowIfFailed("Failed to retrieve turn server");
return list.AsReadOnly();
}
+
+ /// <summary>
+ /// Retrieves the current statistics information.
+ /// </summary>
+ /// <remarks>The WebRTC must be in the <see cref="WebRTCState.Playing"/></remarks>
+ /// <returns>The WebRTC statistics informations.</returns>
+ /// <param name="category">The category of statistics to get.</param>
+ /// <exception cref="ObjectDisposedException">The WebRTC has already been disposed.</exception>
+ /// <exception cref="InvalidOperationException">The WebRTC is not in the valid state.</exception>
+ /// <since_tizen> 10 </since_tizen>
+ public ReadOnlyCollection<WebRTCStatistics> GetStatistics(WebRTCStatisticsCategory category)
+ {
+ ValidateWebRTCState(WebRTCState.Playing);
+
+ var stats = new List<WebRTCStatistics>();
+ Exception caught = null;
+
+ NativeWebRTC.RetrieveStatsCallback cb = (category_, prop, _) =>
+ {
+ try
+ {
+ stats.Add(new WebRTCStatistics(category_, prop));
+ }
+ catch (Exception e)
+ {
+ caught = e;
+ return false;
+ }
+
+ return true;
+ };
+
+ using (var cbKeeper = ObjectKeeper.Get(cb))
+ {
+ NativeWebRTC.ForeachStats(Handle, (int)category, cb, IntPtr.Zero).
+ ThrowIfFailed("failed to retrieve stats");
+
+ if (caught != null)
+ {
+ throw caught;
+ }
+ }
+
+ return new ReadOnlyCollection<WebRTCStatistics>(stats);
+ }
+
+ /// <summary>
+ /// Represents WebRTC statistics information.
+ /// </summary>
+ /// <since_tizen> 10 </since_tizen>
+ public class WebRTCStatistics
+ {
+ internal WebRTCStatistics(WebRTCStatisticsCategory type, IntPtr prop)
+ {
+ var unmanagedStruct = Marshal.PtrToStructure<NativeWebRTC.StatsPropertyStruct>(prop);
+
+ Category = type;
+ Name = unmanagedStruct.name;
+ Property = unmanagedStruct.property;
+
+ switch (unmanagedStruct.propertyType)
+ {
+ case WebRTCStatsPropertyType.TypeBool:
+ Value = unmanagedStruct.value.@bool;
+ break;
+ case WebRTCStatsPropertyType.TypeInt:
+ Value = unmanagedStruct.value.@int;
+ break;
+ case WebRTCStatsPropertyType.TypeUint:
+ Value = unmanagedStruct.value.@uint;
+ break;
+ case WebRTCStatsPropertyType.TypeInt64:
+ Value = unmanagedStruct.value.@long;
+ break;
+ case WebRTCStatsPropertyType.TypeUint64:
+ Value = unmanagedStruct.value.@ulong;
+ break;
+ case WebRTCStatsPropertyType.TypeFloat:
+ Value = unmanagedStruct.value.@float;
+ break;
+ case WebRTCStatsPropertyType.TypeDouble:
+ Value = unmanagedStruct.value.@double;
+ break;
+ case WebRTCStatsPropertyType.TypeString:
+ Value = Marshal.PtrToStringAnsi(unmanagedStruct.value.@string);
+ break;
+ default:
+ throw new InvalidOperationException($"No matching type [{unmanagedStruct.propertyType}]");
+ }
+ }
+
+ /// <summary>
+ /// Gets the category of statistics.
+ /// </summary>
+ /// <value>The category of WebRTC statistics information</value>
+ /// <since_tizen> 10 </since_tizen>
+ public WebRTCStatisticsCategory Category { get; }
+
+ /// <summary>
+ /// Gets the name of statistics.
+ /// </summary>
+ /// <value>The name of WebRTC statistics information</value>
+ /// <since_tizen> 10 </since_tizen>
+ public string Name { get; }
+
+ /// <summary>
+ /// Gets the property of statistics.
+ /// </summary>
+ /// <value>The property of WebRTC statistics information</value>
+ /// <since_tizen> 10 </since_tizen>
+ public WebRTCStatisticsProperty Property { get; }
+
+ /// <summary>
+ /// Gets the value of statistics.
+ /// </summary>
+ /// <value>The value of WebRTC statistics information</value>
+ /// <since_tizen> 10 </since_tizen>
+ public object Value { get; }
+
+ /// <summary>
+ /// Returns a string that represents the current object.
+ /// </summary>
+ /// <returns>A string that represents the current object.</returns>
+ /// <since_tizen> 10 </since_tizen>
+ public override string ToString() =>
+ $"Category={Category}, Name={Name}, Property={Property}, Value={Value}, Type={Value.GetType()}";
+ }
}
-}
\ No newline at end of file
+}
Evas,
}
-}
\ No newline at end of file
+
+ /// <summary>
+ /// Specifies the category of WebRTC statistics.
+ /// </summary>
+ /// <since_tizen> 10 </since_tizen>
+ [Flags]
+ public enum WebRTCStatisticsCategory
+ {
+ /// <summary>
+ /// Codec.
+ /// </summary>
+ Codec = 0x0001,
+
+ /// <summary>
+ /// Inbound RTP.
+ /// </summary>
+ InboundRtp = 0x0002,
+
+ /// <summary>
+ /// Outbound RTP.
+ /// </summary>
+ OutboundRtp = 0x0004,
+
+ /// <summary>
+ /// Remote inbound RTP.
+ /// </summary>
+ RemoteInboundRtp = 0x0008,
+
+ /// <summary>
+ /// Remote Outbound RTP.
+ /// </summary>
+ RemoteOutboundRtp = 0x0010,
+
+ /// <summary>
+ /// All types of WebRTC statistics.
+ /// </summary>
+ All = Codec | InboundRtp | OutboundRtp | RemoteInboundRtp | RemoteOutboundRtp
+ }
+
+ [Flags]
+ internal enum WebRTCStatisticsPropertyCategory
+ {
+ Common = 0x00000100,
+
+ Codec = 0x00000200,
+
+ RtpStream = 0x00000400,
+
+ ReceivedRtpStream = 0x00000800,
+
+ InboundRtpStream = 0x00001000,
+
+ SentRtpStream = 0x00002000,
+
+ OutboundRtpStream = 0x00004000,
+
+ RemoteInboundRtpStream = 0x00008000,
+
+ RemoteOutboundRtpStream = 0x00010000
+ }
+
+ /// <summary>
+ /// Specifies the WebRTC statistics property.
+ /// </summary>
+ /// <since_tizen> 10 </since_tizen>
+ public enum WebRTCStatisticsProperty
+ {
+ /// <summary>
+ /// Timestamp.
+ /// </summary>
+ Timestamp = WebRTCStatisticsPropertyCategory.Common | 0x01,
+
+ /// <summary>
+ /// ID.
+ /// </summary>
+ Id = WebRTCStatisticsPropertyCategory.Common | 0x02,
+
+ /// <summary>
+ /// Payload type.
+ /// </summary>
+ PayloadType = WebRTCStatisticsPropertyCategory.Codec | 0x01,
+
+ /// <summary>
+ /// Clock rate.
+ /// </summary>
+ ClockRate = WebRTCStatisticsPropertyCategory.Codec | 0x02,
+
+ /// <summary>
+ /// The number of channels.
+ /// </summary>
+ Channels = WebRTCStatisticsPropertyCategory.Codec | 0x03,
+
+ /// <summary>
+ /// MIME type.
+ /// </summary>
+ MimeType = WebRTCStatisticsPropertyCategory.Codec | 0x04,
+
+ /// <summary>
+ /// Codec type.
+ /// </summary>
+ CodecType = WebRTCStatisticsPropertyCategory.Codec | 0x05,
+
+ /// <summary>
+ /// SDP FMTP line.
+ /// </summary>
+ SdpFmtpLine = WebRTCStatisticsPropertyCategory.Codec | 0x06,
+
+ /// <summary>
+ /// SSRC.
+ /// </summary>
+ Ssrc = WebRTCStatisticsPropertyCategory.RtpStream | 0x01,
+
+ /// <summary>
+ /// Transport ID.
+ /// </summary>
+ TransportId = WebRTCStatisticsPropertyCategory.RtpStream | 0x02,
+
+ /// <summary>
+ /// Codec ID.
+ /// </summary>
+ CodecId = WebRTCStatisticsPropertyCategory.RtpStream | 0x03,
+
+ /// <summary>
+ /// Received packet.
+ /// </summary>
+ PacketsReceived = WebRTCStatisticsPropertyCategory.ReceivedRtpStream | 0x01,
+
+ /// <summary>
+ /// Lost packet.
+ /// </summary>
+ PacketsLost = WebRTCStatisticsPropertyCategory.ReceivedRtpStream | 0x02,
+
+ /// <summary>
+ /// Discarted packet.
+ /// </summary>
+ PacketsDiscarded = WebRTCStatisticsPropertyCategory.ReceivedRtpStream | 0x03,
+
+ /// <summary>
+ /// Jitter.
+ /// </summary>
+ Jitter = WebRTCStatisticsPropertyCategory.ReceivedRtpStream | 0x05,
+
+ /// <summary>
+ /// Received bytes.
+ /// </summary>
+ BytesReceived = WebRTCStatisticsPropertyCategory.InboundRtpStream | 0x01,
+
+ /// <summary>
+ /// Duplicated packet.
+ /// </summary>
+ PacketsDuplicated = WebRTCStatisticsPropertyCategory.InboundRtpStream | 0x02,
+
+ /// <summary>
+ /// Sent bytes.
+ /// </summary>
+ BytesSent = WebRTCStatisticsPropertyCategory.SentRtpStream | 0x01,
+
+ /// <summary>
+ /// Sent packets.
+ /// </summary>
+ PacketsSent = WebRTCStatisticsPropertyCategory.SentRtpStream | 0x02,
+
+ /// <summary>
+ /// Remote ID.
+ /// </summary>
+ RemoteId = WebRTCStatisticsPropertyCategory.InboundRtpStream | WebRTCStatisticsPropertyCategory.OutboundRtpStream | 0x01,
+
+ /// <summary>
+ /// FIR count.
+ /// </summary>
+ FirCount = WebRTCStatisticsPropertyCategory.InboundRtpStream | WebRTCStatisticsPropertyCategory.OutboundRtpStream | 0x02,
+
+ /// <summary>
+ /// PLI count.
+ /// </summary>
+ PliCount = WebRTCStatisticsPropertyCategory.InboundRtpStream | WebRTCStatisticsPropertyCategory.OutboundRtpStream | 0x03,
+
+ /// <summary>
+ /// NACK count.
+ /// </summary>
+ NackCount = WebRTCStatisticsPropertyCategory.InboundRtpStream | WebRTCStatisticsPropertyCategory.OutboundRtpStream | 0x04,
+
+ /// <summary>
+ /// Round trip time.
+ /// </summary>
+ RoundTripTime = WebRTCStatisticsPropertyCategory.RemoteInboundRtpStream | 0x01,
+
+ /// <summary>
+ /// Lost fraction.
+ /// </summary>
+ FractionLost = WebRTCStatisticsPropertyCategory.RemoteInboundRtpStream | 0x02,
+
+ /// <summary>
+ /// Remote timestamp.
+ /// </summary>
+ RemoteTimestamp = WebRTCStatisticsPropertyCategory.OutboundRtpStream | 0x01,
+
+ /// <summary>
+ /// Local ID.
+ /// </summary>
+ LocalId = WebRTCStatisticsPropertyCategory.RemoteInboundRtpStream | WebRTCStatisticsPropertyCategory.RemoteOutboundRtpStream | 0x01
+ }
+
+ internal enum WebRTCStatsPropertyType
+ {
+ TypeBool,
+ TypeInt,
+ TypeUint,
+ TypeInt64,
+ TypeUint64,
+ TypeFloat,
+ TypeDouble,
+ TypeString
+ }
+}