From 5618ce2e88cf1aa97312c918d3c1573f23426754 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 12 May 2025 16:10:56 +0200 Subject: [PATCH] Fixed black thumbnails when joining conference without bundle mode --- .../model/ConferenceParticipantDeviceModel.kt | 59 ++++++++----------- ...all_conference_active_speaker_fragment.xml | 4 +- .../call_conference_active_speaker_cell.xml | 4 +- ...all_conference_active_speaker_fragment.xml | 4 +- .../res/layout/call_conference_grid_cell.xml | 4 +- 5 files changed, 31 insertions(+), 44 deletions(-) diff --git a/app/src/main/java/org/linphone/ui/call/conference/model/ConferenceParticipantDeviceModel.kt b/app/src/main/java/org/linphone/ui/call/conference/model/ConferenceParticipantDeviceModel.kt index 18cb90ceb..73dde3589 100644 --- a/app/src/main/java/org/linphone/ui/call/conference/model/ConferenceParticipantDeviceModel.kt +++ b/app/src/main/java/org/linphone/ui/call/conference/model/ConferenceParticipantDeviceModel.kt @@ -24,7 +24,6 @@ import androidx.annotation.UiThread import androidx.annotation.WorkerThread import androidx.lifecycle.MutableLiveData import org.linphone.LinphoneApplication.Companion.coreContext -import org.linphone.core.MediaDirection import org.linphone.core.ParticipantDevice import org.linphone.core.ParticipantDeviceListenerStub import org.linphone.core.StreamType @@ -57,7 +56,7 @@ class ConferenceParticipantDeviceModel val isVideoAvailable = MutableLiveData() - val isSendingVideo = MutableLiveData() + val isThumbnailAvailable = MutableLiveData() val isJoining = MutableLiveData() @@ -108,28 +107,6 @@ class ConferenceParticipantDeviceModel isSpeaking.postValue(speaking) } - @WorkerThread - override fun onStreamAvailabilityChanged( - participantDevice: ParticipantDevice, - available: Boolean, - streamType: StreamType? - ) { - Log.d( - "$TAG Participant device [${participantDevice.address.asStringUriOnly()}] stream [$streamType] availability changed to ${if (available) "available" else "not available"}" - ) - } - - @WorkerThread - override fun onStreamCapabilityChanged( - participantDevice: ParticipantDevice, - direction: MediaDirection?, - streamType: StreamType? - ) { - Log.d( - "$TAG Participant device [${participantDevice.address.asStringUriOnly()}] stream [$streamType] capability changed to [$direction]" - ) - } - @WorkerThread override fun onScreenSharingChanged( participantDevice: ParticipantDevice, @@ -149,19 +126,21 @@ class ConferenceParticipantDeviceModel Log.i( "$TAG Participant device [${participantDevice.address.asStringUriOnly()}] thumbnail availability changed to ${if (available) "available" else "not available"}" ) - isVideoAvailable.postValue(available) + isThumbnailAvailable.postValue(available) } @WorkerThread - override fun onThumbnailStreamCapabilityChanged( + override fun onStreamAvailabilityChanged( participantDevice: ParticipantDevice, - direction: MediaDirection? + available: Boolean, + streamType: StreamType? ) { - Log.i( - "$TAG Participant device [${participantDevice.address.asStringUriOnly()}] thumbnail capability changed to [$direction]" - ) - val sending = direction == MediaDirection.SendRecv || direction == MediaDirection.SendOnly - isSendingVideo.postValue(sending) + if (streamType == StreamType.Video) { + Log.i( + "$TAG Participant device [${participantDevice.address.asStringUriOnly()}] video stream availability changed to ${if (available) "available" else "not available"}" + ) + isVideoAvailable.postValue(available) + } } } @@ -196,10 +175,18 @@ class ConferenceParticipantDeviceModel Log.i("$TAG Participant [${device.address.asStringUriOnly()}] is sharing its screen") } - isVideoAvailable.postValue(device.getStreamAvailability(StreamType.Video)) - val videoCapability = device.getStreamCapability(StreamType.Video) - isSendingVideo.postValue( - videoCapability == MediaDirection.SendRecv || videoCapability == MediaDirection.SendOnly + val videoAvailability = device.getStreamAvailability(StreamType.Video) + isVideoAvailable.postValue(videoAvailability) + Log.i( + "$TAG Participant device [${device.address.asStringUriOnly()}] video stream availability is ${if (videoAvailability) "available" else "not available"}" + ) + + // In case of joining conference without bundle mode, thumbnail stream availability will be false, + // but we need to display our video preview for video stream to be sent + val thumbnailVideoAvailability = if (isMe) videoAvailability else device.thumbnailStreamAvailability + isThumbnailAvailable.postValue(thumbnailVideoAvailability) + Log.i( + "$TAG Participant device [${device.address.asStringUriOnly()}] thumbnail availability is ${if (thumbnailVideoAvailability) "available" else "not available"}" ) } diff --git a/app/src/main/res/layout-land/call_conference_active_speaker_fragment.xml b/app/src/main/res/layout-land/call_conference_active_speaker_fragment.xml index 04edd4d66..0744c8de8 100644 --- a/app/src/main/res/layout-land/call_conference_active_speaker_fragment.xml +++ b/app/src/main/res/layout-land/call_conference_active_speaker_fragment.xml @@ -27,7 +27,7 @@ layout="@layout/contact_avatar_huge" android:layout_marginTop="5dp" bind:model="@{conferenceViewModel.activeSpeaker.avatarModel}" - android:visibility="@{conferenceViewModel.activeSpeaker.isSendingVideo || conferenceViewModel.activeSpeaker.isJoining || !conferenceViewModel.activeSpeaker.isInConference ? View.GONE : View.VISIBLE}" + android:visibility="@{conferenceViewModel.activeSpeaker.isVideoAvailable || conferenceViewModel.activeSpeaker.isJoining || !conferenceViewModel.activeSpeaker.isInConference ? View.GONE : View.VISIBLE}" app:layout_constraintDimensionRatio="1:1" app:layout_constraintWidth_max="@dimen/avatar_in_call_size" app:layout_constraintHeight_max="@dimen/avatar_in_call_size" @@ -42,7 +42,7 @@ android:layout_width="0dp" android:layout_height="0dp" android:layout_marginEnd="8dp" - android:visibility="@{conferenceViewModel.activeSpeaker.isSendingVideo && conferenceViewModel.activeSpeaker.isInConference ? View.VISIBLE : View.GONE, default=gone}" + android:visibility="@{conferenceViewModel.activeSpeaker.isVideoAvailable && conferenceViewModel.activeSpeaker.isInConference ? View.VISIBLE : View.GONE, default=gone}" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" diff --git a/app/src/main/res/layout/call_conference_active_speaker_cell.xml b/app/src/main/res/layout/call_conference_active_speaker_cell.xml index 146a27b12..39e961646 100644 --- a/app/src/main/res/layout/call_conference_active_speaker_cell.xml +++ b/app/src/main/res/layout/call_conference_active_speaker_cell.xml @@ -27,7 +27,7 @@ android:id="@+id/avatar" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:visibility="@{model.isSendingVideo || model.isJoining || !model.isInConference ? View.GONE : View.VISIBLE}" + android:visibility="@{model.isThumbnailAvailable || model.isJoining || !model.isInConference ? View.GONE : View.VISIBLE}" layout="@layout/contact_avatar_medium" bind:model="@{model.avatarModel}" bind:hidePresence="@{true}" @@ -43,7 +43,7 @@ app:alignTopRight="false" app:displayMode="hybrid" participantTextureView="@{model}" - android:visibility="@{model.isSendingVideo && model.isInConference ? View.VISIBLE : View.GONE, default=gone}" + android:visibility="@{model.isThumbnailAvailable && model.isInConference ? View.VISIBLE : View.GONE, default=gone}" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" diff --git a/app/src/main/res/layout/call_conference_active_speaker_fragment.xml b/app/src/main/res/layout/call_conference_active_speaker_fragment.xml index 421a6e623..3d25fa6a0 100644 --- a/app/src/main/res/layout/call_conference_active_speaker_fragment.xml +++ b/app/src/main/res/layout/call_conference_active_speaker_fragment.xml @@ -27,7 +27,7 @@ layout="@layout/contact_avatar_huge" android:layout_marginTop="5dp" bind:model="@{conferenceViewModel.activeSpeaker.avatarModel}" - android:visibility="@{conferenceViewModel.activeSpeaker.isSendingVideo || conferenceViewModel.activeSpeaker.isJoining || !conferenceViewModel.activeSpeaker.isInConference ? View.GONE : View.VISIBLE}" + android:visibility="@{conferenceViewModel.activeSpeaker.isVideoAvailable || conferenceViewModel.activeSpeaker.isJoining || !conferenceViewModel.activeSpeaker.isInConference ? View.GONE : View.VISIBLE}" app:layout_constraintDimensionRatio="1:1" app:layout_constraintWidth_max="@dimen/avatar_in_call_size" app:layout_constraintHeight_max="@dimen/avatar_in_call_size" @@ -41,7 +41,7 @@ android:id="@+id/active_speaker_surface" android:layout_width="0dp" android:layout_height="0dp" - android:visibility="@{conferenceViewModel.activeSpeaker.isSendingVideo && conferenceViewModel.activeSpeaker.isInConference ? View.VISIBLE : View.GONE, default=gone}" + android:visibility="@{conferenceViewModel.activeSpeaker.isVideoAvailable && conferenceViewModel.activeSpeaker.isInConference ? View.VISIBLE : View.GONE, default=gone}" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toTopOf="@id/active_speaker_miniatures_horizontal_layout" app:layout_constraintStart_toStartOf="parent" diff --git a/app/src/main/res/layout/call_conference_grid_cell.xml b/app/src/main/res/layout/call_conference_grid_cell.xml index 75204edc2..c09fda42e 100644 --- a/app/src/main/res/layout/call_conference_grid_cell.xml +++ b/app/src/main/res/layout/call_conference_grid_cell.xml @@ -27,7 +27,7 @@ android:id="@+id/avatar" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:visibility="@{model.isSendingVideo || model.isJoining || !model.isInConference ? View.GONE : View.VISIBLE}" + android:visibility="@{model.isThumbnailAvailable || model.isJoining || !model.isInConference ? View.GONE : View.VISIBLE}" layout="@layout/contact_avatar_big" bind:model="@{model.avatarModel}" bind:hidePresence="@{true}" @@ -43,7 +43,7 @@ app:alignTopRight="false" app:displayMode="hybrid" participantTextureView="@{model}" - android:visibility="@{model.isSendingVideo && model.isInConference ? View.VISIBLE : View.GONE, default=gone}" + android:visibility="@{model.isThumbnailAvailable && model.isInConference ? View.VISIBLE : View.GONE, default=gone}" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent"