From 1cd79b50869e6fcc9a445e633838a454ee215b8a Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Fri, 12 Jul 2024 14:04:46 +0200 Subject: [PATCH] Added FEC in-call stats --- .../linphone/ui/call/model/CallStatsModel.kt | 32 +++++++ .../chat/fragment/ConversationFragment.kt | 2 +- .../chat/viewmodel/ConversationViewModel.kt | 2 +- .../layout-land/call_stats_bottom_sheet.xml | 87 +++++++++++++++---- .../res/layout/call_stats_bottom_sheet.xml | 74 +++++++++++++--- app/src/main/res/values-fr/strings.xml | 4 + app/src/main/res/values/strings.xml | 4 + 7 files changed, 171 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/org/linphone/ui/call/model/CallStatsModel.kt b/app/src/main/java/org/linphone/ui/call/model/CallStatsModel.kt index 2cf730d73..6209de579 100644 --- a/app/src/main/java/org/linphone/ui/call/model/CallStatsModel.kt +++ b/app/src/main/java/org/linphone/ui/call/model/CallStatsModel.kt @@ -39,6 +39,11 @@ class CallStatsModel @WorkerThread constructor() { val videoResolution = MutableLiveData() val videoFps = MutableLiveData() + val fecEnabled = MutableLiveData() + val lostPackets = MutableLiveData() + val repairedPackets = MutableLiveData() + val fecBandwidth = MutableLiveData() + @WorkerThread fun update(call: Call, stats: CallStats?) { stats ?: return @@ -51,6 +56,9 @@ class CallStatsModel @WorkerThread constructor() { val showVideoStats = videoEnabled && (remoteSendsVideo || localSendsVideo) isVideoEnabled.postValue(showVideoStats) + val isFecEnabled = call.core.isFecEnabled // TODO FIXME: use real value from call + fecEnabled.postValue(showVideoStats && isFecEnabled) + when (stats.type) { StreamType.Audio -> { val payloadType = call.currentParams.usedAudioPayloadType @@ -101,6 +109,30 @@ class CallStatsModel @WorkerThread constructor() { "↑ $sentFps ↓ $receivedFps" ) videoFps.postValue(fpsLabel) + + if (isFecEnabled) { + val lostPacketsValue = stats.fecCumulativeLostPacketsNumber + val lostPacketsLabel = AppUtils.getFormattedString( + R.string.call_stats_fec_lost_packets_label, + lostPacketsValue + ) + lostPackets.postValue(lostPacketsLabel) + + val repairedPacketsValue = stats.fecRepairedPacketsNumber + val repairedPacketsLabel = AppUtils.getFormattedString( + R.string.call_stats_fec_repaired_packets_label, + repairedPacketsValue + ) + repairedPackets.postValue(repairedPacketsLabel) + + val fecUploadBandwidth = stats.fecUploadBandwidth.roundToInt() + val fecDownloadBandwidth = stats.fecDownloadBandwidth.roundToInt() + val fecBandwidthLabel = AppUtils.getFormattedString( + R.string.call_stats_fec_lost_bandwidth_label, + "↑ $fecUploadBandwidth kbits/s ↓ $fecDownloadBandwidth kbits/s" + ) + fecBandwidth.postValue(fecBandwidthLabel) + } } else -> {} } diff --git a/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationFragment.kt b/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationFragment.kt index 6c7ba0e28..8a9ea67a8 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationFragment.kt @@ -959,7 +959,7 @@ class ConversationFragment : SlidingPaneChildFragment() { popupView.setUnmuteClickListener { Log.i("$TAG Un-muting conversation") - viewModel.unmute() + viewModel.unMute() popupWindow.dismiss() } diff --git a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationViewModel.kt b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationViewModel.kt index 3182ee7f9..e850c426b 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationViewModel.kt @@ -432,7 +432,7 @@ class ConversationViewModel @UiThread constructor() : AbstractConversationViewMo } @UiThread - fun unmute() { + fun unMute() { coreContext.postOnCoreThread { chatRoom.muted = false isMuted.postValue(chatRoom.muted) diff --git a/app/src/main/res/layout-land/call_stats_bottom_sheet.xml b/app/src/main/res/layout-land/call_stats_bottom_sheet.xml index eec9b525f..a1893b2fd 100644 --- a/app/src/main/res/layout-land/call_stats_bottom_sheet.xml +++ b/app/src/main/res/layout-land/call_stats_bottom_sheet.xml @@ -36,13 +36,13 @@ android:id="@+id/audio_stats" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginStart="20dp" - android:layout_marginEnd="20dp" + android:layout_marginStart="10dp" + android:layout_marginEnd="10dp" android:layout_marginTop="10dp" android:layout_marginBottom="20dp" android:background="@drawable/shape_squircle_gray_600_background" app:layout_constraintVertical_bias="0" - app:layout_constraintWidth_percent="0.45" + app:layout_constraintHorizontal_chainStyle="spread_inside" app:layout_constraintTop_toBottomOf="@id/handle" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toStartOf="@id/video_stats" @@ -64,8 +64,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" - android:layout_marginStart="16dp" - android:layout_marginEnd="16dp" android:text="@{model.audioCodec, default=@string/call_stats_codec_label}" android:textColor="@color/white" android:maxLines="1" @@ -77,8 +75,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" - android:layout_marginStart="16dp" - android:layout_marginEnd="16dp" android:layout_marginBottom="10dp" android:text="@{model.audioBandwidth, default=@string/call_stats_bandwidth_label}" android:textColor="@color/white" @@ -92,16 +88,15 @@ android:id="@+id/video_stats" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginStart="20dp" - android:layout_marginEnd="20dp" + android:layout_marginStart="10dp" + android:layout_marginEnd="10dp" android:layout_marginTop="10dp" android:layout_marginBottom="20dp" android:background="@drawable/shape_squircle_gray_600_background" android:visibility="@{model.isVideoEnabled ? View.VISIBLE : View.GONE}" - app:layout_constraintWidth_percent="0.45" app:layout_constraintTop_toBottomOf="@id/handle" app:layout_constraintStart_toEndOf="@id/audio_stats" - app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintEnd_toStartOf="@id/fec_stats" app:layout_constraintBottom_toBottomOf="parent" android:orientation="vertical"> @@ -120,8 +115,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" - android:layout_marginStart="16dp" - android:layout_marginEnd="16dp" android:text="@{model.videoCodec, default=@string/call_stats_codec_label}" android:textColor="@color/white" android:maxLines="1" @@ -133,8 +126,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" - android:layout_marginStart="16dp" - android:layout_marginEnd="16dp" android:text="@{model.videoBandwidth, default=@string/call_stats_bandwidth_label}" android:textColor="@color/white" android:maxLines="1" @@ -146,8 +137,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" - android:layout_marginStart="16dp" - android:layout_marginEnd="16dp" android:text="@{model.videoResolution, default=@string/call_stats_resolution_label}" android:textColor="@color/white" android:maxLines="1" @@ -159,8 +148,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" - android:layout_marginStart="16dp" - android:layout_marginEnd="16dp" android:layout_marginBottom="10dp" android:text="@{model.videoFps, default=@string/call_stats_fps_label}" android:textColor="@color/white" @@ -170,6 +157,68 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/call_stats_bottom_sheet.xml b/app/src/main/res/layout/call_stats_bottom_sheet.xml index 7698f86c1..13f9c6697 100644 --- a/app/src/main/res/layout/call_stats_bottom_sheet.xml +++ b/app/src/main/res/layout/call_stats_bottom_sheet.xml @@ -62,8 +62,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" - android:layout_marginStart="16dp" - android:layout_marginEnd="16dp" android:text="@{model.audioCodec, default=@string/call_stats_codec_label}" android:textColor="@color/white" android:maxLines="1" @@ -75,8 +73,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" - android:layout_marginStart="16dp" - android:layout_marginEnd="16dp" android:layout_marginBottom="10dp" android:text="@{model.audioBandwidth, default=@string/call_stats_bandwidth_label}" android:textColor="@color/white" @@ -98,7 +94,7 @@ app:layout_constraintTop_toBottomOf="@id/audio_stats" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintBottom_toTopOf="@id/fec_stats" android:orientation="vertical"> + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 4de7b54bd..04ce2d16d 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -618,6 +618,10 @@ Vidéo Résolution : %s FPS : %s + FEC + Paquets perdus : %s + Paquets réparés : %s + Bande passante : %s Chiffrement du média Chiffrement : %s diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 50a36cc21..dc85fa8d9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -656,6 +656,10 @@ Video Resolution: %s FPS: %s + FEC + Lost packets: %s + Repaired packets: %s + Bandwidth: %s Media encryption Media encryption: %s