mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-17 11:08:06 +00:00
171 lines
6.8 KiB
Swift
171 lines
6.8 KiB
Swift
/*
|
|
* Copyright (c) 2010-2021 Belledonne Communications SARL.
|
|
*
|
|
* This file is part of linphone-android
|
|
* (see https://www.linphone.org).
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
import linphonesw
|
|
|
|
class CallStatisticsData {
|
|
|
|
var call : Call
|
|
var audioStats:[StatItemData] = []
|
|
var videoStats:[StatItemData] = []
|
|
let isVideoEnabled = MutableLiveData<Bool>()
|
|
let statsUpdated = MutableLiveData(true)
|
|
|
|
private var callDelegate : CallDelegateStub?
|
|
|
|
init (call:Call) {
|
|
self.call = call
|
|
callDelegate = CallDelegateStub(
|
|
onStatsUpdated : { (call: Call, stats: CallStats) -> Void in
|
|
self.isVideoEnabled.value = call.currentParams?.videoEnabled
|
|
self.updateCallStats(stats: stats)
|
|
self.statsUpdated.value = true
|
|
}
|
|
|
|
)
|
|
call.addDelegate(delegate: callDelegate!)
|
|
initCallStats()
|
|
isVideoEnabled.value = call.currentParams?.videoEnabled
|
|
call.audioStats.map { updateCallStats(stats: $0) }
|
|
call.videoStats.map { updateCallStats(stats: $0) }
|
|
}
|
|
|
|
private func initCallStats() {
|
|
|
|
audioStats.append(StatItemData(type: StatType.CAPTURE))
|
|
audioStats.append(StatItemData(type: StatType.PLAYBACK))
|
|
audioStats.append(StatItemData(type: StatType.PAYLOAD))
|
|
audioStats.append(StatItemData(type: StatType.ENCODER))
|
|
audioStats.append(StatItemData(type: StatType.DECODER))
|
|
audioStats.append(StatItemData(type: StatType.DOWNLOAD_BW))
|
|
audioStats.append(StatItemData(type: StatType.UPLOAD_BW))
|
|
audioStats.append(StatItemData(type: StatType.ICE))
|
|
audioStats.append(StatItemData(type: StatType.IP_FAM))
|
|
audioStats.append(StatItemData(type: StatType.SENDER_LOSS))
|
|
audioStats.append(StatItemData(type: StatType.RECEIVER_LOSS))
|
|
audioStats.append(StatItemData(type: StatType.JITTER))
|
|
|
|
videoStats.append(StatItemData(type: StatType.CAPTURE))
|
|
videoStats.append(StatItemData(type: StatType.PLAYBACK))
|
|
videoStats.append(StatItemData(type: StatType.PAYLOAD))
|
|
videoStats.append(StatItemData(type: StatType.ENCODER))
|
|
videoStats.append(StatItemData(type: StatType.DECODER))
|
|
videoStats.append(StatItemData(type: StatType.DOWNLOAD_BW))
|
|
videoStats.append(StatItemData(type: StatType.UPLOAD_BW))
|
|
videoStats.append(StatItemData(type: StatType.ESTIMATED_AVAILABLE_DOWNLOAD_BW))
|
|
videoStats.append(StatItemData(type: StatType.ICE))
|
|
videoStats.append(StatItemData(type: StatType.IP_FAM))
|
|
videoStats.append(StatItemData(type: StatType.SENDER_LOSS))
|
|
videoStats.append(StatItemData(type: StatType.RECEIVER_LOSS))
|
|
videoStats.append(StatItemData(type: StatType.SENT_RESOLUTION))
|
|
videoStats.append(StatItemData(type: StatType.RECEIVED_RESOLUTION))
|
|
videoStats.append(StatItemData(type: StatType.SENT_FPS))
|
|
videoStats.append(StatItemData(type: StatType.RECEIVED_FPS))
|
|
}
|
|
|
|
private func updateCallStats(stats: CallStats) {
|
|
if (stats.type == StreamType.Audio) {
|
|
audioStats.forEach{ $0.update(call: call, stats: stats)}
|
|
} else if (stats.type == StreamType.Video) {
|
|
videoStats.forEach{ $0.update(call: call, stats: stats)}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
enum StatType {
|
|
case CAPTURE
|
|
case PLAYBACK
|
|
case PAYLOAD
|
|
case ENCODER
|
|
case DECODER
|
|
case DOWNLOAD_BW
|
|
case UPLOAD_BW
|
|
case ICE
|
|
case IP_FAM
|
|
case SENDER_LOSS
|
|
case RECEIVER_LOSS
|
|
case JITTER
|
|
case SENT_RESOLUTION
|
|
case RECEIVED_RESOLUTION
|
|
case SENT_FPS
|
|
case RECEIVED_FPS
|
|
case ESTIMATED_AVAILABLE_DOWNLOAD_BW
|
|
}
|
|
|
|
struct StatItemData {
|
|
var type:StatType
|
|
|
|
let value = MutableLiveData<String>()
|
|
|
|
func update(call: Call, stats: CallStats) {
|
|
guard let payloadType = stats.type == StreamType.Audio ? call.currentParams?.usedAudioPayloadType : call.currentParams?.usedVideoPayloadType, let core = call.core else {
|
|
value.value = "n/a"
|
|
return
|
|
}
|
|
switch(type) {
|
|
case StatType.CAPTURE: value.value = stats.type == StreamType.Audio ? core.captureDevice : core.videoDevice
|
|
case StatType.PLAYBACK: value.value = stats.type == StreamType.Audio ? core.playbackDevice : core.videoDisplayFilter
|
|
case StatType.PAYLOAD: value.value = "\(payloadType.mimeType)/\(payloadType.clockRate / 1000) kHz"
|
|
case StatType.ENCODER: value.value = payloadType.description
|
|
case StatType.DECODER: value.value = payloadType.description
|
|
case StatType.DOWNLOAD_BW: value.value = "\(stats.downloadBandwidth) kbits/s"
|
|
case StatType.UPLOAD_BW: value.value = "\(stats.uploadBandwidth) kbits/s"
|
|
case StatType.ICE: value.value = stats.iceState.toString()
|
|
case StatType.IP_FAM: value.value = stats.ipFamilyOfRemote == AddressFamily.Inet6 ? "IPv6" : "IPv4"
|
|
case StatType.SENDER_LOSS: value.value = String(format: "%.2f%",stats.senderLossRate)
|
|
case StatType.RECEIVER_LOSS: value.value = String(format: "%.2f%",stats.receiverLossRate)
|
|
case StatType.JITTER: value.value = String(format: "%.2f ms",stats.jitterBufferSizeMs)
|
|
case StatType.SENT_RESOLUTION: value.value = call.currentParams?.sentVideoDefinition?.name
|
|
case StatType.RECEIVED_RESOLUTION: value.value = call.currentParams?.receivedVideoDefinition?.name
|
|
case StatType.SENT_FPS: value.value = "\(call.currentParams?.sentFramerate ?? 0.0)"
|
|
case StatType.RECEIVED_FPS: value.value = "\(call.currentParams?.receivedFramerate ?? 0.0)"
|
|
case StatType.ESTIMATED_AVAILABLE_DOWNLOAD_BW: value.value = "\(stats.estimatedDownloadBandwidth) kbit/s"
|
|
}
|
|
}
|
|
|
|
|
|
func getTypeTitle() -> String {
|
|
switch (type) {
|
|
case .CAPTURE: return VoipTexts.call_stats_capture_filter
|
|
case .PLAYBACK: return VoipTexts.call_stats_player_filter
|
|
case .PAYLOAD: return VoipTexts.call_stats_codec
|
|
case .ENCODER: return VoipTexts.call_stats_encoder_name
|
|
case .DECODER: return VoipTexts.call_stats_decoder_name
|
|
case .DOWNLOAD_BW: return VoipTexts.call_stats_download
|
|
case .UPLOAD_BW: return VoipTexts.call_stats_upload
|
|
case .ICE: return VoipTexts.call_stats_ice
|
|
case .IP_FAM: return VoipTexts.call_stats_ip
|
|
case .SENDER_LOSS: return VoipTexts.call_stats_sender_loss_rate
|
|
case .RECEIVER_LOSS: return VoipTexts.call_stats_receiver_loss_rate
|
|
case .JITTER: return VoipTexts.call_stats_jitter_buffer
|
|
case .SENT_RESOLUTION: return VoipTexts.call_stats_video_resolution_sent
|
|
case .RECEIVED_RESOLUTION: return VoipTexts.call_stats_video_resolution_received
|
|
case .SENT_FPS: return VoipTexts.call_stats_video_fps_sent
|
|
case .RECEIVED_FPS: return VoipTexts.call_stats_video_fps_received
|
|
case .ESTIMATED_AVAILABLE_DOWNLOAD_BW: return VoipTexts.call_stats_estimated_download
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|