Skip to content
This repository has been archived by the owner on May 13, 2024. It is now read-only.

[MV-410] Add getStats function #34

Merged
merged 4 commits into from
Apr 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions MembraneRTC/Sources/MembraneRTC/MembraneRTC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,15 @@ public class MembraneRTC: MulticastDelegate<MembraneRTCDelegate>, ObservableObje
peerConnectionManager.setTrackEncoding(trackId: trackId, encoding: encoding, enabled: enabled)
}

/**
Returns current connection stats.

- Returns: a map containing statistics
*/
public func getStats() -> [String: RTCStats] {
return peerConnectionManager.getStats()
}

/**
Changes severity level of debug logs.

Expand Down
53 changes: 53 additions & 0 deletions MembraneRTC/Sources/MembraneRTC/PeerConnectionManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ internal class PeerConnectionManager: NSObject, RTCPeerConnectionDelegate {

private let peerConnectionListener: PeerConnectionListener

private var peerConnectionStats: [String: RTCStats] = [:]

internal init(
config: RTCConfiguration, peerConnectionFactory: PeerConnectionFactoryWrapper,
peerConnectionListener: PeerConnectionListener
Expand Down Expand Up @@ -274,6 +276,57 @@ internal class PeerConnectionManager: NSObject, RTCPeerConnectionDelegate {
sender.parameters = params
}

private func extractRelevantStats(rp: RTCStatisticsReport) {
rp.statistics.forEach { it1 in
let it = it1.value
if it.type == "outbound-rtp" {
let duration = it.values["qualityLimitationDurations"] as? [String: Double]
let qualityLimitation: QualityLimitationDurations = QualityLimitationDurations(
bandwidth: duration?["bandwidth"] ?? 0.0,
cpu: duration?["cpu"] ?? 0.0, none: duration?["none"] ?? 0.0, other: duration?["other"] ?? 0.0)

let tmp = RTCOutboundStats(
kind: it.values["kind"] as? String ?? "",
rid: it.values["rid"] as? String ?? "",
bytesSent: it.values["bytesSent"] as? UInt ?? 0,
targetBitrate: it.values["targetBitrate"] as? Double ?? 0.0,
packetsSent: it.values["packetsSent"] as? UInt ?? 0,
framesEncoded: it.values["framesEncoded"] as? UInt ?? 0,
framesPerSecond: it.values["framesPerSecond"] as? Double ?? 0.0,
frameWidth: it.values["frameWidth"] as? UInt ?? 0,
frameHeight: it.values["frameHeight"] as? UInt ?? 0,
qualityLimitationDurations: qualityLimitation
)

peerConnectionStats[it.id as String] = tmp
} else if it.type == "inbound-rtp" {
let tmp = RTCInboundStats(
kind: it.values["kind"] as? String ?? "",
jitter: it.values["jitter"] as? Double ?? 0.0,
packetsLost: it.values["packetsLost"] as? UInt ?? 0,
packetsReceived: it.values["packetsReceived"] as? UInt ?? 0,
bytesReceived: it.values["bytesReceived"] as? UInt ?? 0,
framesReceived: it.values["framesReceived"] as? UInt ?? 0,
frameWidth: it.values["frameWidth"] as? UInt ?? 0,
frameHeight: it.values["frameHeight"] as? UInt ?? 0,
framesPerSecond: it.values["framesPerSecond"] as? Double ?? 0.0,
framesDropped: it.values["framesDropped"] as? UInt ?? 0
)

peerConnectionStats[it.id as String] = tmp
}
}
}

public func getStats() -> [String: RTCStats] {
if let connection = connection {
connection.statistics(completionHandler: { RTCStatisticsReport in
self.extractRelevantStats(rp: RTCStatisticsReport)
})
}
return peerConnectionStats
}

private func applyBitrate(encodings: [RTCRtpEncodingParameters], maxBitrate: TrackBandwidthLimit) {
switch maxBitrate {
case .BandwidthLimit(let limit):
Expand Down
76 changes: 76 additions & 0 deletions MembraneRTC/Sources/MembraneRTC/Types/RTCStats.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
public struct QualityLimitationDurations {
public let bandwidth: Double
public let cpu: Double
public let none: Double
public let other: Double

public init(bandwidth: Double, cpu: Double, none: Double, other: Double) {
self.bandwidth = bandwidth
self.cpu = cpu
self.none = none
self.other = other
}
}

public protocol RTCStats {}

public struct RTCOutboundStats: RTCStats {
public let kind: String
public let rid: String
public let bytesSent: UInt
public let targetBitrate: Double
public let packetsSent: UInt
public let framesEncoded: UInt
public let framesPerSecond: Double
public let frameWidth: UInt
public let frameHeight: UInt
public let qualityLimitationDurations: QualityLimitationDurations?

public init(
kind: String = "", rid: String = "", bytesSent: UInt = 0, targetBitrate: Double = 0.0, packetsSent: UInt = 0,
framesEncoded: UInt = 0, framesPerSecond: Double = 0.0, frameWidth: UInt = 0, frameHeight: UInt = 0,
qualityLimitationDurations: QualityLimitationDurations? = nil
) {
self.kind = kind
self.rid = rid
self.bytesSent = bytesSent
self.targetBitrate = targetBitrate
self.packetsSent = packetsSent
self.framesEncoded = framesEncoded
self.framesPerSecond = framesPerSecond
self.frameWidth = frameWidth
self.frameHeight = frameHeight
self.qualityLimitationDurations = qualityLimitationDurations
}
}

public struct RTCInboundStats: RTCStats {
public let kind: String
public let jitter: Double
public let packetsLost: UInt
public let packetsReceived: UInt
public let bytesReceived: UInt
public let framesReceived: UInt
public let frameWidth: UInt
public let frameHeight: UInt
public let framesPerSecond: Double
public let framesDropped: UInt

public init(
kind: String = "", jitter: Double = 0.0, packetsLost: UInt = 0, packetsReceived: UInt = 0,
bytesReceived: UInt = 0,
framesReceived: UInt = 0, frameWidth: UInt = 0, frameHeight: UInt = 0, framesPerSecond: Double = 0.0,
framesDropped: UInt = 0
) {
self.kind = kind
self.jitter = jitter
self.packetsLost = packetsLost
self.packetsReceived = packetsReceived
self.bytesReceived = bytesReceived
self.framesReceived = framesReceived
self.frameWidth = frameWidth
self.frameHeight = frameHeight
self.framesPerSecond = framesPerSecond
self.framesDropped = framesDropped
}
}