From ca5daa32ed2c5b619543f04b1411f646ba481431 Mon Sep 17 00:00:00 2001 From: Ergyun Syuleyman Date: Sat, 9 May 2020 17:49:32 +0300 Subject: [PATCH 1/3] -multiple feed minor chages; -added dots for video pages --- .../conference/ConferenceVideoModule.java | 35 +++++++++++++++++-- .../data/sdk/calls/ConferenceCallData.java | 25 +++++++------ .../conference/ConferenceVideoAdapter.java | 14 +++++++- .../communicator/ui/base/BaseAdapter.java | 8 +++++ .../conference/ConferenceVideoFragment.java | 18 ++++------ .../views/CirclePagerIndicatorDecoration.java | 28 ++++++++++----- 6 files changed, 95 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java b/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java index 95e50ef935..8634010cd7 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java @@ -12,6 +12,7 @@ import org.webrtc.SurfaceViewRenderer; import java.util.ArrayList; import java.util.HashMap; +import java.util.Map; import java.util.Set; import kotlin.jvm.Synchronized; @@ -90,16 +91,35 @@ public class ConferenceVideoModule { if (activeConferenceCall == null) return new ArrayList<>(); Set participatIds = mActiveVideoParticipantsMap.keySet(); mActiveVideoParticipantsMap.clear(); - synchronized (activeConferenceCall.mData.mParticipantArray) { + synchronized (activeConferenceCall.mData) { if (activeConferenceCall.mData.mParticipantArray != null) { for (int index = 0; index < activeConferenceCall.mData.mParticipantArray.size(); index++) { NYNCallParticipant participant = activeConferenceCall.mData.mParticipantArray.get(index); - if (participant.hasVideo() || (participant.isMe() && activeConferenceCall.mData.isOwnStreamActive)) { + if (participant.hasVideo() || + (participant.isMe() && activeConferenceCall.mData.isOwnStreamActive) + || activeConferenceCall.mData.mActiveParticipanTracks.containsKey(participant.getParticipantId()) + ) { ConferenceListItem item = conferenceParticipant(participant, participant.isOwner(), activeConferenceCall.mData.isOwnStreamActive); + item.hasVideo = true; mActiveVideoParticipantsMap.put(item.participantId, item); } } } +// if (activeConferenceCall.mData.mActiveParticipanTracks != null) { +// for (Map.Entry set : activeConferenceCall.mData.mActiveParticipanTracks.entrySet()) { +// NYNCallParticipant participant = activeConferenceCall.mConference.getParticipantByTrackId(set.getKey()); +// if (participant == null) participant = activeConferenceCall.mConference.getParticipantById(set.getValue()); +// if (participant != null && +// (participant.hasVideo() || +// (participant.isMe() && activeConferenceCall.mData.isOwnStreamActive) || +// activeConferenceCall.mData.mActiveParticipanTracks.containsKey(participant.getParticipantId()))) { +// ConferenceListItem item = conferenceParticipant(participant, participant.isOwner(), activeConferenceCall.mData.isOwnStreamActive); +// item.hasVideo = true; +// item.participantId = set.getValue(); +// mActiveVideoParticipantsMap.put(item.participantId, item); +// } +// } +// } } for (String participantId : participatIds) { @@ -153,7 +173,7 @@ public class ConferenceVideoModule { if (row <= MAX_VIDEO_FEEDS_ROW_SIZE) { int rest = (mActiveVideoParticipantsCount - lastPageBeginer)%MAX_VIDEO_FEEDS_COLUIMN_SIZE; if (rest == 0) { - if (row == MAX_VIDEO_FEEDS_ROW_SIZE) return MAX_VIDEO_FEEDS_ROW_SIZE; + if ((position + 1 - lastPageBeginer)/MAX_VIDEO_FEEDS_COLUIMN_SIZE == MAX_VIDEO_FEEDS_ROW_SIZE) return MAX_VIDEO_FEEDS_ROW_SIZE + 1; if (row == 1) return row; if (row < MAX_VIDEO_FEEDS_ROW_SIZE) return row; return row - 1; @@ -220,6 +240,15 @@ public class ConferenceVideoModule { return MAX_VIDEO_FEEDS_COLUIMN_SIZE; } + public int getItemsPageCount() { + if (mActiveVideoParticipantsCount <= MAX_VIDEO_FEEDS_COLUIMN_SIZE) { + return 1; + } + int count = (mActiveVideoParticipantsCount / MAX_VIDEO_FEEDS_COUNT_PER_PAGE); + if ((mActiveVideoParticipantsCount - count*MAX_VIDEO_FEEDS_COUNT_PER_PAGE) % MAX_VIDEO_FEEDS_COUNT_PER_PAGE > 0) count++; + return count; + } + protected ConferenceListItem conferenceParticipant(NYNCallParticipant participant, boolean isModerator, boolean isOwnStreamActive) { diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceCallData.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceCallData.java index 8f40428288..5fac62702a 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceCallData.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceCallData.java @@ -5,6 +5,7 @@ import com.nynja.sdk.NYNCallParticipant; import com.nynja.sdk.NYNCallParticipantArray; import java.util.HashMap; +import java.util.Map; /** * Created by Ergyun Syuleyman on 04/03/2020. @@ -19,8 +20,8 @@ public class ConferenceCallData { public String mRemoteSSTrackId; public String mRemoteVideoTrackId; public HashMap mActiveTracks; - public HashMap mActiveParticipanTracks; - public HashMap mActiveParticipanSSTracks; + public HashMap mActiveParticipanTracks; + public HashMap mActiveParticipanSSTracks; public boolean hasRemoteVideoTrack; public boolean hasRemoteScreenShareTrack; public boolean mIsConference; @@ -51,13 +52,13 @@ public class ConferenceCallData { public void onRemoteVideoAdded(String trackId, String participantId) { hasRemoteVideoTrack = true; mActiveTracks.put(trackId, participantId); - mActiveParticipanTracks.put(participantId, trackId); + mActiveParticipanTracks.put(trackId, participantId); mRemoteVideoTrackId = trackId; } public void onRemoteVideoRemoved(String trackId, String participantId) { mActiveTracks.remove(trackId); - mActiveParticipanTracks.remove(participantId); + mActiveParticipanTracks.remove(trackId); hasRemoteVideoTrack = !isRemoteVideoTracksEmpty(); mRemoteVideoTrackId = ""; } @@ -65,14 +66,14 @@ public class ConferenceCallData { public void onRemoteSSAdded(String trackId, String participantId) { hasRemoteScreenShareTrack = true; mActiveTracks.put(trackId, participantId); - mActiveParticipanSSTracks.put(participantId, trackId); + mActiveParticipanSSTracks.put(trackId, participantId); mRemoteSSTrackId = trackId; } public void onRemoteSSRemoved(String trackId, String participantId) { hasRemoteScreenShareTrack = false; mActiveTracks.remove(trackId); - mActiveParticipanSSTracks.remove(participantId); + mActiveParticipanSSTracks.remove(trackId); mRemoteSSTrackId = ""; } @@ -96,12 +97,16 @@ public class ConferenceCallData { protected String getTrackIdForParticipant(String participantId, boolean isVideo) { if (StringUtils.isEmpty(participantId)) return ""; if (isVideo) { - if (mActiveParticipanTracks.containsKey(participantId)) { - return mActiveParticipanTracks.get(participantId); + for (Map.Entry set : mActiveParticipanTracks.entrySet()) { + if (set.getValue().contentEquals(participantId)) { + return set.getKey(); + } } } else { - if (mActiveParticipanSSTracks.containsKey(participantId)) { - return mActiveParticipanSSTracks.get(participantId); + for (Map.Entry set : mActiveParticipanSSTracks.entrySet()) { + if (set.getValue().contentEquals(participantId)) { + return set.getKey(); + } } } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java index d955a0a396..f40a88ae8f 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java @@ -54,7 +54,17 @@ public class ConferenceVideoAdapter> exten getItem(position).participantId.hashCode()); return getItem(position).participantId.hashCode(); } - return -1L; + return position; + } + + @Override + public int getItemsPageCount() { + return ConferenceVideoModule.getInstance().getItemsPageCount(); + } + + @Override + public int getMaxItemsPerPage() { + return ConferenceVideoModule.MAX_VIDEO_FEEDS_COUNT_PER_PAGE; } public void setIsModerator(boolean isModerator) { @@ -125,7 +135,9 @@ public class ConferenceVideoAdapter> exten } else { layoutParams.width = itemWidth - ConferenceVideoModule.getInstance().getWidthDividerLength(position); } + holder.itemView.setBottom(itemHeight - 32); holder.itemView.setLayoutParams(layoutParams); + holder.itemView.requestLayout(); } } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseAdapter.java b/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseAdapter.java index fe33b3d069..c88465c9a1 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseAdapter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/base/BaseAdapter.java @@ -44,6 +44,14 @@ public abstract class BaseAdapter> extends RecyclerVie } } + public int getItemsPageCount() { + return getItemCount(); + } + + public int getMaxItemsPerPage() { + return 1; + } + public List getItems() { return mList; } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java index eaad10fb5c..7a7e0b48eb 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java @@ -4,6 +4,7 @@ import android.os.Bundle; import android.os.Handler; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.v4.content.ContextCompat; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.DividerItemDecoration; import android.support.v7.widget.GridLayoutManager; @@ -30,6 +31,7 @@ import com.nynja.mobile.communicator.ui.activities.calls.CallActivity; import com.nynja.mobile.communicator.ui.adapters.conference.ConferenceVideoAdapter; import com.nynja.mobile.communicator.ui.adapters.viewholders.conference.ConferenceVideoItemVh; import com.nynja.mobile.communicator.ui.base.BaseFragment; +import com.nynja.mobile.communicator.ui.views.CirclePagerIndicatorDecoration; import com.nynja.mobile.communicator.utils.ActionSheetDialog; import com.nynja.mobile.communicator.utils.DialogFactory; import com.nynja.mobile.communicator.utils.StringUtils; @@ -166,23 +168,17 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV MAX_VIDEO_FEEDS_COLUIMN_SIZE, LinearLayoutManager.HORIZONTAL, false); -// mGridLayoutManager.setSpanCount(2); -// mGridLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); -// mGridLayoutManager.setReverseLayout(false); -// mGridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { -// @Override -// public int getSpanSize(int position) { -// return (int)ConferenceVideoModule.getInstance().getSpanSize(position); -// } -// }); mGridLayoutManager.setItemPrefetchEnabled(true); mRecyclerView.setLayoutManager(mGridLayoutManager); mRecyclerView.setHasFixedSize(true); mRecyclerView.setAdapter(mConfParticipantsAdapter); - SnapHelper snapHelper = new LinearSnapHelper(); - snapHelper.attachToRecyclerView(mRecyclerView); + mRecyclerView.addItemDecoration(new CirclePagerIndicatorDecoration(12, 24, 64, + ContextCompat.getColor(getActivity(), R.color.icon_spreadsheet_files), + ContextCompat.getColor(getActivity(), R.color.active_call_bg))); mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.HORIZONTAL)); mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL)); + SnapHelper snapHelper = new LinearSnapHelper(); + snapHelper.attachToRecyclerView(mRecyclerView); // mRecyclerView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() { // @Override // public void onChildViewAttachedToWindow(View view) { diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/views/CirclePagerIndicatorDecoration.java b/app/src/main/java/com/nynja/mobile/communicator/ui/views/CirclePagerIndicatorDecoration.java index 898677c168..0caaba0297 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/views/CirclePagerIndicatorDecoration.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/views/CirclePagerIndicatorDecoration.java @@ -2,14 +2,19 @@ package com.nynja.mobile.communicator.ui.views; import android.content.res.Resources; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; +import android.graphics.drawable.Drawable; import android.support.annotation.ColorInt; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.View; +import com.nynja.mobile.communicator.R; +import com.nynja.mobile.communicator.ui.base.BaseAdapter; + import org.jetbrains.annotations.NotNull; /** @@ -48,29 +53,35 @@ public class CirclePagerIndicatorDecoration extends RecyclerView.ItemDecoration public void onDrawOver(@NotNull Canvas c, @NotNull RecyclerView parent, @NotNull RecyclerView.State state) { super.onDrawOver(c, parent, state); - final RecyclerView.Adapter adapter = parent.getAdapter(); + final BaseAdapter adapter = (BaseAdapter) parent.getAdapter(); if (adapter == null) { return; } - int itemCount = adapter.getItemCount(); + int pageCount = adapter.getItemsPageCount(); + if (pageCount <= 1) { + return; + } + + int maxItemsPerPage = adapter.getMaxItemsPerPage(); // center horizontally, calculate width and subtract half from center - float totalLength = this.radius * 2 * itemCount; - float paddingBetweenItems = Math.max(0, itemCount - 1) * indicatorItemPadding; + float totalLength = this.radius * 2 * pageCount; + float paddingBetweenItems = Math.max(0, pageCount - 1) * indicatorItemPadding; float indicatorTotalWidth = totalLength + paddingBetweenItems; float indicatorStartX = (parent.getWidth() - indicatorTotalWidth) / 2f; // center vertically in the allotted space float indicatorPosY = parent.getHeight() - indicatorHeight / 2f; - drawInactiveDots(c, indicatorStartX, indicatorPosY, itemCount); + drawInactiveDots(c, indicatorStartX, indicatorPosY, pageCount); - final int activePosition; + int activePosition; if (parent.getLayoutManager() instanceof GridLayoutManager) { - activePosition = ((GridLayoutManager) parent.getLayoutManager()).findFirstVisibleItemPosition(); + activePosition = ((GridLayoutManager) parent.getLayoutManager()).findFirstCompletelyVisibleItemPosition(); +// activePosition = ((GridLayoutManager) parent.getLayoutManager()).findFirstVisibleItemPosition(); } else if (parent.getLayoutManager() instanceof LinearLayoutManager) { activePosition = ((LinearLayoutManager) parent.getLayoutManager()).findFirstVisibleItemPosition(); } else { @@ -87,6 +98,7 @@ public class CirclePagerIndicatorDecoration extends RecyclerView.ItemDecoration if (activeChild == null) { return; } + activePosition = activePosition/maxItemsPerPage; drawActiveDot(c, indicatorStartX, indicatorPosY, activePosition); } @@ -107,7 +119,7 @@ public class CirclePagerIndicatorDecoration extends RecyclerView.ItemDecoration // width of item indicator including padding final float itemWidth = this.radius * 2 + indicatorItemPadding; float highlightStart = indicatorStartX + radius + itemWidth * highlightPosition; - c.drawCircle(highlightStart, indicatorPosY, radius, activePaint); + c.drawCircle(highlightStart, indicatorPosY, radius+2, activePaint); } @Override -- GitLab From 88f2c6dcf9b0e1a8b844921dd368efb919766631 Mon Sep 17 00:00:00 2001 From: Ergyun Syuleyman Date: Sat, 9 May 2020 18:45:45 +0300 Subject: [PATCH 2/3] -added trace logs for conference video feeds --- .../conference/ConferenceVideoModule.java | 4 ++++ .../conference/ConferenceVideoAdapter.java | 5 +++-- .../conference/ConferenceVideoItemVh.java | 19 +++++++++++++++++++ .../conference/ConferenceVideoFragment.java | 14 +++++++++++++- 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java b/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java index 8634010cd7..34651f1489 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java @@ -16,6 +16,7 @@ import java.util.Map; import java.util.Set; import kotlin.jvm.Synchronized; +import timber.log.Timber; public class ConferenceVideoModule { @@ -101,6 +102,7 @@ public class ConferenceVideoModule { ) { ConferenceListItem item = conferenceParticipant(participant, participant.isOwner(), activeConferenceCall.mData.isOwnStreamActive); item.hasVideo = true; + Timber.d("ConferenceVideoModule::getConferenceVideoMembers(): updated video feed item participant name=%s; ID=%s", item.name, item.participantId); mActiveVideoParticipantsMap.put(item.participantId, item); } } @@ -124,6 +126,7 @@ public class ConferenceVideoModule { for (String participantId : participatIds) { if (!mActiveVideoParticipantsMap.containsKey(participantId)) { + Timber.d("ConferenceVideoModule::getConferenceVideoMembers(): removed participant with ID=%s", participantId); enableVideoForTrack(participantId, false); String trackId = getTrackIdByParticipantId(participantId); setVideoRendererForTrack(null, trackId, StringUtils.isEmpty(trackId)); @@ -131,6 +134,7 @@ public class ConferenceVideoModule { } ArrayList items = new ArrayList<>(mActiveVideoParticipantsMap.values()); mActiveVideoParticipantsCount = items.size(); + Timber.d("ConferenceVideoModule::getConferenceVideoMembers(): items new size=%d", mActiveVideoParticipantsCount); return items; } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java index f40a88ae8f..349fd10ab4 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/conference/ConferenceVideoAdapter.java @@ -50,8 +50,8 @@ public class ConferenceVideoAdapter> exten @Override public long getItemId(int position) { if (position < getItemCount()) { - Timber.d("getItemId(): participantId = %s; feed ID = %d", getItem(position).participantId, - getItem(position).participantId.hashCode()); + Timber.d("ConferenceVideoAdapter::getItemId(): participantId=%s; feedID=%d, position=%d", getItem(position).participantId, + getItem(position).participantId.hashCode(), position); return getItem(position).participantId.hashCode(); } return position; @@ -112,6 +112,7 @@ public class ConferenceVideoAdapter> exten @Override public void onBindViewHolder(T holder, int position) { + Timber.d("ConferenceVideoAdapter::onBindViewHolder(): item ID=%d; pos=%s", holder.getItemId(), position); super.onBindViewHolder(holder, position); if (mScreenWidth > 0) { float divWidth = ConferenceVideoModule.getInstance().getWidthDiv(position); diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java index 0bb05f5ebb..12cd8ce9d4 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java @@ -56,6 +56,7 @@ public class ConferenceVideoItemVh extends BaseVH { } @Override public void bind(ConferenceListItem item, int position) { + Timber.d("ConferenceVideoItemVh::bind(): item participant ID=%s, position=%d", item.participantId, position); mPosition = position; if (mUnbinder != null) { //mUnbinder.unbind(); @@ -98,25 +99,30 @@ public class ConferenceVideoItemVh extends BaseVH { onViewAttachedToWindow(); } } + Timber.d("ConferenceVideoItemVh::setData(): item participant name=%s; ID=%s", item.name, item.participantId); } public void onViewAttachedToWindow() { initVideoCallRenderer(); setVideoRendererForTrack(); enableVideoForTrack(true); + Timber.d("ConferenceVideoItemVh::onViewAttachedToWindow(): item participant name=%s; ID=%s", mItem.name, mItem.participantId); } public void onViewDetachedFromWindow() { enableVideoForTrack(false); //removeVideoRendererForTrack(); + Timber.d("ConferenceVideoItemVh::onViewDetachedFromWindow(): item participant name=%s; ID=%s", mItem.name, mItem.participantId); } public void onViewRecycled() { enableVideoForTrack(false); + Timber.d("ConferenceVideoItemVh::onViewRecycled(): item participant name=%s; ID=%s", mItem.name, mItem.participantId); } @Synchronized public void releaseVideoCallRrenderers() { + Timber.d("ConferenceVideoItemVh::releaseVideoCallRrenderers(): item participant name=%s; ID=%s", mItem.name, mItem.participantId); removeVideoRendererForTrack(); if (!mIsRenderersInitialized) return; if (mVideoFeed != null) { @@ -128,6 +134,7 @@ public class ConferenceVideoItemVh extends BaseVH { ///////////////////////////////////////////////////////////////////////////////////// // Internal Helpers private void setupInConference(ConferenceListItem item) { + Timber.d("ConferenceVideoItemVh::setupInConference(): item participant name=%s; ID=%s", mItem.name, mItem.participantId); initVideoCallRenderer(); if (item.participantId == null || !item.isActive) { // in Conference - but not joined yet @@ -187,6 +194,7 @@ public class ConferenceVideoItemVh extends BaseVH { } private void drawIsFeedVideoIfNeeded(boolean visible) { + Timber.d("ConferenceVideoItemVh::drawIsFeedVideoIfNeeded(): item participant ID=%s; visible=%s", mItem.participantId, visible? "true":"false"); if (visible) { mVideoFeed.setVisibility(View.VISIBLE); } else { @@ -196,6 +204,7 @@ public class ConferenceVideoItemVh extends BaseVH { } private void refreshFeedVideo() { + Timber.d("ConferenceVideoItemVh::refreshFeedVideo(): item participant name=%s; ID=%s", mItem.name, mItem.participantId); if (mVideoFeed != null) { mVideoFeed.invalidate(); mVideoFeed.refreshDrawableState(); @@ -213,7 +222,9 @@ public class ConferenceVideoItemVh extends BaseVH { @Synchronized private void initVideoCallRenderer() { + Timber.d("ConferenceVideoItemVh::initVideoCallRenderer(): item participant ID=%s; mIsRenderersInitialized=%s", mItem.participantId, mIsRenderersInitialized? "true":"false"); if (mIsRenderersInitialized) return; + Timber.d("ConferenceVideoItemVh::initVideoCallRenderer():2"); try { mVideoFeed.init(createRootEglBase().getEglBaseContext(), null); mVideoFeed.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT); @@ -229,23 +240,29 @@ public class ConferenceVideoItemVh extends BaseVH { @Synchronized private void setVideoRendererForTrack() { + Timber.d("setVideoRendererForTrack::setVideoRendererForTrack(): item participant name=%s; ID=%s", mItem.name, mItem.participantId); if (!mIsRenderersInitialized) return; if (mItem == null) return; if (mItem.isTrackActive == 1) return; String trackId = ConferenceVideoModule.getInstance().getTrackIdByParticipantId(mItem.participantId); + Timber.d("setVideoRendererForTrack::setVideoRendererForTrack(): item participant ID=%s; trackId=%s", mItem.participantId, trackId); if (StringUtils.isNotEmpty(trackId) || mItem.isMe) { mItem.isTrackActive = 1; + Timber.d("setVideoRendererForTrack::setVideoRendererForTrack(): item participant ID=%s; isMe=%s", mItem.participantId, mItem.isMe? "true":"false"); ConferenceVideoModule.getInstance().setVideoRendererForTrack(mVideoFeed, trackId, mItem.isMe); } } @Synchronized private void removeVideoRendererForTrack() { + Timber.d("setVideoRendererForTrack::removeVideoRendererForTrack(): item participant name=%s; ID=%s", mItem.name, mItem.participantId); if (!mIsRenderersInitialized) return; if (mItem == null) return; if (mItem.isTrackActive == 0) return; String trackId = ConferenceVideoModule.getInstance().getTrackIdByParticipantId(mItem.participantId); + Timber.d("setVideoRendererForTrack::removeVideoRendererForTrack(): item participant ID=%s; trackId=%s", mItem.participantId, trackId); if (StringUtils.isNotEmpty(trackId) || mItem.isMe) { + Timber.d("setVideoRendererForTrack::removeVideoRendererForTrack(): item participant ID=%s; isMe=%s", mItem.participantId, mItem.isMe? "true":"false"); ConferenceVideoModule.getInstance().setVideoRendererForTrack(null, trackId, mItem.isMe); mItem.isTrackActive = 0; } @@ -253,6 +270,8 @@ public class ConferenceVideoItemVh extends BaseVH { @Synchronized private void enableVideoForTrack(boolean enable) { + Timber.d("setVideoRendererForTrack::enableVideoForTrack(): item participant name=%s; ID=%s", mItem.name, mItem.participantId); + Timber.d("ConferenceVideoItemVh::enableVideoForTrack(): item participant ID=%s; enable=%s", mItem.participantId, enable? "true":"false"); if (!mIsRenderersInitialized) return; if (mItem == null) return; if (StringUtils.isNotEmpty(mItem.participantId)) { diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java index 7a7e0b48eb..3df985a89c 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java @@ -40,6 +40,7 @@ import org.webrtc.ContextUtils; import org.webrtc.EglBase; import java.util.ArrayList; +import java.util.List; import butterknife.BindView; import timber.log.Timber; @@ -343,6 +344,7 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV } public void setActiveState(boolean active) { + Timber.d("ConferenceVideoFragment::setActiveState(): active=%s", active? "true" : "false"); ActiveConferenceCall activeConferenceCall = mConferencePresenter.getActiveConference(); isActive = active; if (activeConferenceCall == null) return; @@ -489,6 +491,7 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV } private void loadConferenceMembers(ArrayList members) { + Timber.d("ConferenceVideoFragment::loadConferenceMembers()"); mConfParticipantsAdapter.setItems(members); } @@ -499,6 +502,7 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV if (!activeConferenceCall.mConference.isConference()) return; if (!activeConferenceCall.isVideoEnabled) return; + Timber.d("ConferenceVideoFragment::setRemoteVideoRenderer()"); mConferencePresenter.loadConferenceParticipants(activeConferenceCall); } @@ -510,6 +514,7 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV if (!activeConferenceCall.isVideoEnabled) return; if (StringUtils.isNotEmpty(trackId)) { + Timber.d("ConferenceVideoFragment::removeRemoteVideoRenderer()"); ConferenceVideoModule.getInstance().setVideoRendererForTrack(null, trackId, false); } @@ -518,10 +523,15 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV private void removeRemoteVideoRenderers(ActiveConferenceCall activeConferenceCall) { if (activeConferenceCall == null) return; + Timber.d("ConferenceVideoFragment::removeRemoteVideoRenderers()"); ArrayList members = mConferencePresenter.getConferenceVideoMembers(activeConferenceCall); - for (ConferenceListItem item : members) { + List list = mConfParticipantsAdapter.getItems(); + Timber.d("ConferenceVideoFragment::removeRemoteVideoRenderers(): members size=%d", members.size()); + Timber.d("ConferenceVideoFragment::removeRemoteVideoRenderers(): list size=%d", list.size()); + for (ConferenceListItem item : list) { //members) { String trackId = ConferenceVideoModule.getInstance().getTrackIdByParticipantId(item.participantId); if (StringUtils.isNotEmpty(trackId) || item.isMe) { + Timber.d("ConferenceVideoFragment::removeRemoteVideoRenderers(): participantID=%s", item.participantId); ConferenceVideoModule.getInstance().setVideoRendererForTrack(null, trackId, item.isMe); } } @@ -531,6 +541,7 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV if (activeConferenceCall == null) return; if (activeConferenceCall.mConference == null) return; if (!activeConferenceCall.isVideoEnabled) return; + Timber.d("ConferenceVideoFragment::setLocalVideoRenderer()"); mConferencePresenter.loadConferenceParticipants(activeConferenceCall); } @@ -540,6 +551,7 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV if (activeConferenceCall.mConference == null) return; if (!activeConferenceCall.mConference.isRunning()) return; if (!activeConferenceCall.isVideoEnabled) return; + Timber.d("ConferenceVideoFragment::removeLocalVideoRenderer()"); mConferencePresenter.loadConferenceParticipants(activeConferenceCall); } -- GitLab From b4e8f6998c079048097e5a7b0168aedab30c11ae Mon Sep 17 00:00:00 2001 From: Ergyun Syuleyman Date: Mon, 11 May 2020 03:25:37 +0300 Subject: [PATCH 3/3] vide conference feeds logic refactoring to fix feeds flikering --- .../conference/ConferenceVideoModule.java | 101 +++++++++++++----- .../data/sdk/ConferenceSDKPresenter.java | 2 +- .../data/sdk/calls/ConferenceListItem.java | 4 +- .../data/sdk/calls/ConferenceSDKListener.java | 2 +- .../data/sdk/calls/ConferenceSDKModule.java | 2 +- .../mvp/presenters/CallActivityPresenter.java | 2 +- .../presenters/ConferenceCallPresenter.java | 2 +- .../presenters/ConferenceVideoPresenter.java | 5 +- .../communicator/mvp/view/CallView.java | 8 +- .../mvp/view/ConferenceVideoView.java | 2 +- .../conference/ConferenceVideoAdapter.java | 56 ++++++++-- .../conference/ConferenceVideoItemVh.java | 7 +- .../conference/ConferenceVideoFragment.java | 38 +++---- .../main/res/layout/li_conference_video.xml | 22 ++-- 14 files changed, 173 insertions(+), 80 deletions(-) diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java b/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java index 34651f1489..21c32cc160 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/conference/ConferenceVideoModule.java @@ -12,6 +12,9 @@ import org.webrtc.SurfaceViewRenderer; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; @@ -30,7 +33,7 @@ public class ConferenceVideoModule { private ActiveConferenceCall mCurrentActiveCall; public int mActiveVideoParticipantsCount = 0; - public HashMap mActiveVideoParticipantsMap= new HashMap<>(); + public LinkedHashSet mActiveVideoParticipants= new LinkedHashSet<>(); private ConferenceVideoModule() { @@ -53,7 +56,7 @@ public class ConferenceVideoModule { public void reset() { // ToDo:... - mActiveVideoParticipantsMap.clear(); + mActiveVideoParticipants.clear(); mCurrentActiveCall = null; } @@ -87,23 +90,36 @@ public class ConferenceVideoModule { return trackId; } - @Synchronized - public ArrayList getConferenceVideoMembers(ActiveConferenceCall activeConferenceCall) { + public synchronized ArrayList getConferenceVideoMembers(ActiveConferenceCall activeConferenceCall) { if (activeConferenceCall == null) return new ArrayList<>(); - Set participatIds = mActiveVideoParticipantsMap.keySet(); - mActiveVideoParticipantsMap.clear(); + HashSet mTempActiveVideoParticipants= new HashSet<>(); + HashSet tempParticipants= new HashSet<>(); synchronized (activeConferenceCall.mData) { if (activeConferenceCall.mData.mParticipantArray != null) { for (int index = 0; index < activeConferenceCall.mData.mParticipantArray.size(); index++) { NYNCallParticipant participant = activeConferenceCall.mData.mParticipantArray.get(index); - if (participant.hasVideo() || - (participant.isMe() && activeConferenceCall.mData.isOwnStreamActive) - || activeConferenceCall.mData.mActiveParticipanTracks.containsKey(participant.getParticipantId()) - ) { - ConferenceListItem item = conferenceParticipant(participant, participant.isOwner(), activeConferenceCall.mData.isOwnStreamActive); + ConferenceListItem item = conferenceParticipant(participant, participant.isOwner(), activeConferenceCall.mData.isOwnStreamActive); + tempParticipants.add(item); + if (//participant.hasVideo() || + activeConferenceCall.mData.mActiveParticipanTracks.containsValue(participant.getParticipantId())) { + ////////////////////////////////////////////////////////////////////////////////////////////////// + // WORKAROUND !!!!!!!!!! item.hasVideo = true; + item.isMe = false; + ////////////////////////////////////////////////////////////////////////////////////////////////// Timber.d("ConferenceVideoModule::getConferenceVideoMembers(): updated video feed item participant name=%s; ID=%s", item.name, item.participantId); - mActiveVideoParticipantsMap.put(item.participantId, item); + mTempActiveVideoParticipants.add(item); + } else if (//participant.hasVideo() && + participant.getParticipantId().contentEquals(activeConferenceCall.mConference.participantId()) && + participant.isMe() && + activeConferenceCall.mData.isOwnStreamActive) { + ////////////////////////////////////////////////////////////////////////////////////////////////// + // WORKAROUND !!!!!!!!!! + item.hasVideo = true; + item.isMe = true; + ////////////////////////////////////////////////////////////////////////////////////////////////// + Timber.d("ConferenceVideoModule::getConferenceVideoMembers(): updated video feed item participant name=%s; ID=%s", item.name, item.participantId); + mTempActiveVideoParticipants.add(item); } } } @@ -122,25 +138,62 @@ public class ConferenceVideoModule { // } // } // } - } - - for (String participantId : participatIds) { - if (!mActiveVideoParticipantsMap.containsKey(participantId)) { - Timber.d("ConferenceVideoModule::getConferenceVideoMembers(): removed participant with ID=%s", participantId); - enableVideoForTrack(participantId, false); - String trackId = getTrackIdByParticipantId(participantId); - setVideoRendererForTrack(null, trackId, StringUtils.isEmpty(trackId)); + Iterator itr = mActiveVideoParticipants.iterator(); + while(itr.hasNext()) { + ConferenceListItem item = itr.next(); + if (!mTempActiveVideoParticipants.contains(item)) { + Timber.d("ConferenceVideoModule::getConferenceVideoMembers(): removed participant with ID=%s", item.participantId); + enableVideoForTrack(item.participantId, false); + if (item.isMe) { + setVideoRendererForTrack(null, "", true); + } else { + String trackId = getTrackIdByParticipantId(item.participantId); + if (StringUtils.isNotEmpty(trackId)) { + setVideoRendererForTrack(null, trackId, false); + } + } + itr.remove(); + } else if (tempParticipants.contains(item)) { + Iterator itr2 = tempParticipants.iterator(); + while(itr2.hasNext()) { + ConferenceListItem item2 = itr2.next(); + if (item2.equals(item)) { + item.update(item2); + break; + } + } + } + } + Iterator itr2 = mTempActiveVideoParticipants.iterator(); + while(itr2.hasNext()) { + ConferenceListItem item = itr2.next(); + if (!mActiveVideoParticipants.contains(item)) { + Timber.d("ConferenceVideoModule::getConferenceVideoMembers(): added participant with ID=%s", item.participantId); + mActiveVideoParticipants.add(item); + } } } - ArrayList items = new ArrayList<>(mActiveVideoParticipantsMap.values()); + mTempActiveVideoParticipants.clear(); + ArrayList items = new ArrayList<>(mActiveVideoParticipants); mActiveVideoParticipantsCount = items.size(); Timber.d("ConferenceVideoModule::getConferenceVideoMembers(): items new size=%d", mActiveVideoParticipantsCount); return items; } - @Synchronized - public ArrayList getUpdatedActiveSpeakersParticipants(ArrayList participantIds) { - ArrayList items = new ArrayList<>(mActiveVideoParticipantsMap.values()); + public synchronized void participantRemoved(String participantId) { + Iterator itr = mActiveVideoParticipants.iterator(); + while(itr.hasNext()) { + ConferenceListItem item = itr.next(); + if (!participantId.contentEquals(item.participantId)) { + itr.remove(); + break; + } + } + mActiveVideoParticipantsCount = mActiveVideoParticipants.size(); + } + + public synchronized ArrayList getUpdatedActiveSpeakersParticipants(ArrayList participantIds) { + ArrayList items = new ArrayList<>(mActiveVideoParticipants); for (ConferenceListItem item : items) { item.isSpeaking = false; for (String participandId : participantIds) { diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/ConferenceSDKPresenter.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/ConferenceSDKPresenter.java index 9c1ae7305c..cf1044ccef 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/ConferenceSDKPresenter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/ConferenceSDKPresenter.java @@ -63,7 +63,7 @@ public abstract class ConferenceSDKPresenter extends Bas @Override public void onRemoteVideoTrackAdded(ActiveConferenceCall activeConferenceCall, String trackId) {} - @Override public void onRemoteVideoTrackRemoved(ActiveConferenceCall activeConferenceCall, String trackId) {} + @Override public void onRemoteVideoTrackRemoved(ActiveConferenceCall activeConferenceCall, String trackId, String participantId) {} @Override public void onLocalVideoCapturerStarted(ActiveConferenceCall activeConferenceCall) {} diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java index e44ee8610c..518fd344c7 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceListItem.java @@ -135,8 +135,8 @@ public class ConferenceListItem extends Object { this.hasScreen = participant.hasScreen; this.isVideoPaused = participant.isVideoPaused; this.isScreenPaused = participant.isScreenPaused; - this.isTrackActive = 0; - this.isMe = participant.isMe; +// this.isTrackActive = 0; +// this.isMe = participant.isMe; this.isFriend = participant.isFriend; this.isMuted = participant.isMuted; this.isSpeaking = participant.isSpeaking; diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKListener.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKListener.java index 4710d6de07..b6bbde5325 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKListener.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKListener.java @@ -48,7 +48,7 @@ public interface ConferenceSDKListener { void onRemoteVideoTrackAdded(ActiveConferenceCall activeConferenceCall, String trackId) ; - void onRemoteVideoTrackRemoved(ActiveConferenceCall activeConferenceCall, String trackId) ; + void onRemoteVideoTrackRemoved(ActiveConferenceCall activeConferenceCall, String trackId, String participantId) ; void onLocalVideoCapturerStarted(ActiveConferenceCall activeConferenceCall) ; diff --git a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java index dbc5d90c7f..911f83e288 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java +++ b/app/src/main/java/com/nynja/mobile/communicator/data/sdk/calls/ConferenceSDKModule.java @@ -1678,7 +1678,7 @@ public class ConferenceSDKModule extends BaseSDKModule { if (mActiveConference.mConference == null) return; if (mActiveConference.mConference.callId().contentEquals(callId)) { for (ConferenceSDKListener conferenceSDKListener : mConferenceSDKListener) { - conferenceSDKListener.onRemoteVideoTrackRemoved(mActiveConference, trackId); + conferenceSDKListener.onRemoteVideoTrackRemoved(mActiveConference, trackId, participantId); } } // if (isConference) { diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/CallActivityPresenter.java b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/CallActivityPresenter.java index aedd916dd5..23b74d341e 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/CallActivityPresenter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/CallActivityPresenter.java @@ -43,7 +43,7 @@ public class CallActivityPresenter extends ConferenceSDKPresenter @Override public void onRemoteVideoTrackRemoved(ActiveConferenceCall activeConferenceCall, - String trackId) { + String trackId, String participantId) { if (getAttachedViews().size() == 0) return; if (activeConferenceCall == null) return; if (activeConferenceCall.isConference()) return; diff --git a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java index 93ff6234b0..c1e6df26d1 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java +++ b/app/src/main/java/com/nynja/mobile/communicator/mvp/presenters/ConferenceVideoPresenter.java @@ -135,8 +135,9 @@ public class ConferenceVideoPresenter extends ConferenceSDKPresenter> exten private DisplayMetrics mDisplayMetrics = new DisplayMetrics(); private int mScreenWidth = 0; private int mScreenHeight = 0; - HashSet mHoldersSet; + LinkedHashSet< ConferenceVideoItemVh> mHolders; public ConferenceVideoAdapter(List list, OnConferenceVideoFeedClickListener onConferenceItemClickListener) { super(list); this.mOnConferenceVideoFeedClickListener = onConferenceItemClickListener; - mHoldersSet = new HashSet<>(); + mHolders = new LinkedHashSet<>(); setHasStableIds(true); } @@ -75,13 +79,53 @@ public class ConferenceVideoAdapter> exten return this.mIsModerator; } - public void releaseVideoCallRrenderers() { - for (ConferenceVideoItemVh vh : mHoldersSet) { + public void releaseVideoCallRrenderer(String participantId, boolean pause, boolean notify) { + Iterator itr = mHolders.iterator(); + while(itr.hasNext()) { + ConferenceVideoItemVh vh = itr.next(); + if (vh.getItem().participantId.contentEquals(participantId)) { + if (pause) { + onViewRecycled((T)vh); + } else { + releaseVideoCallRrenderer(vh, notify); + itr.remove(); + } + break; + } + } + } + + private void releaseVideoCallRrenderer(ConferenceVideoItemVh vh, boolean notify) { + String participantId = null; + if (vh != null) { + participantId = vh.getItem().participantId; vh.onViewRecycled(); vh.releaseVideoCallRrenderers(); } - mHoldersSet.clear(); + if (participantId == null) return; + int pos = 0; + for (ConferenceListItem item : mList) { + if (item.participantId.contentEquals(participantId)) { + mList.remove(participantId); + ConferenceVideoModule.getInstance().participantRemoved(participantId); + if (notify) notifyItemRemoved(pos); + break; + } + pos++; + } + } + + public void releaseVideoCallRrenderer(ConferenceVideoItemVh vh) { + } + public void releaseVideoCallRrenderers() { + Iterator itr = mHolders.iterator(); + while(itr.hasNext()) { + ConferenceVideoItemVh vh = itr.next(); + releaseVideoCallRrenderer(vh, false); + itr.remove(); + } + mHolders.clear(); clear(); } @@ -106,7 +150,7 @@ public class ConferenceVideoAdapter> exten mScreenWidth = mDisplayMetrics.widthPixels; mScreenHeight = (int) (mDisplayMetrics.heightPixels - mDisplayMetrics.densityDpi/mDisplayMetrics.density); } - mHoldersSet.add(viewHolder); + mHolders.add(viewHolder); return (T) viewHolder; } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java index 12cd8ce9d4..6f9d022f1d 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/adapters/viewholders/conference/ConferenceVideoItemVh.java @@ -203,10 +203,10 @@ public class ConferenceVideoItemVh extends BaseVH { refreshFeedVideo(); } - private void refreshFeedVideo() { + public void refreshFeedVideo() { Timber.d("ConferenceVideoItemVh::refreshFeedVideo(): item participant name=%s; ID=%s", mItem.name, mItem.participantId); if (mVideoFeed != null) { - mVideoFeed.invalidate(); + mVideoFeed.postInvalidate(); mVideoFeed.refreshDrawableState(); } } @@ -228,6 +228,7 @@ public class ConferenceVideoItemVh extends BaseVH { try { mVideoFeed.init(createRootEglBase().getEglBaseContext(), null); mVideoFeed.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT); + mVideoFeed.setWillNotDraw(false); mVideoFeed.setEnableHardwareScaler(true); if (mItem != null && mItem.isMe) { mVideoFeed.setMirror(true); @@ -250,6 +251,7 @@ public class ConferenceVideoItemVh extends BaseVH { mItem.isTrackActive = 1; Timber.d("setVideoRendererForTrack::setVideoRendererForTrack(): item participant ID=%s; isMe=%s", mItem.participantId, mItem.isMe? "true":"false"); ConferenceVideoModule.getInstance().setVideoRendererForTrack(mVideoFeed, trackId, mItem.isMe); + refreshFeedVideo(); } } @@ -265,6 +267,7 @@ public class ConferenceVideoItemVh extends BaseVH { Timber.d("setVideoRendererForTrack::removeVideoRendererForTrack(): item participant ID=%s; isMe=%s", mItem.participantId, mItem.isMe? "true":"false"); ConferenceVideoModule.getInstance().setVideoRendererForTrack(null, trackId, mItem.isMe); mItem.isTrackActive = 0; + refreshFeedVideo(); } } diff --git a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java index 3df985a89c..af28f6a56f 100644 --- a/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java +++ b/app/src/main/java/com/nynja/mobile/communicator/ui/fragments/conference/ConferenceVideoFragment.java @@ -256,10 +256,10 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV } @Override - public void onRemoteVideoTrackRemoved(ActiveConferenceCall activeConferenceCall, String trackId) { + public void onRemoteVideoTrackRemoved(ActiveConferenceCall activeConferenceCall, String trackId, String participantId) { if (getActivity() == null || !isAdded()) return; getActivity().runOnUiThread(() -> { - removeRemoteVideoRenderer(activeConferenceCall, trackId); + removeRemoteVideoRenderer(activeConferenceCall, trackId, participantId); setConferenceState(activeConferenceCall); }); } @@ -277,7 +277,7 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV public void onLocalVideoCapturerStopped(ActiveConferenceCall activeConferenceCall) { if (getActivity() == null || !isAdded()) return; mHandler.post(() -> { - removeLocalVideoRenderer(activeConferenceCall); + removeLocalVideoRenderer(activeConferenceCall, false); setConferenceState(activeConferenceCall); }); } @@ -297,7 +297,6 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV @Override public void onSpeakerStateChanged(boolean isSpeakerOn) { if (getActivity() == null || !isAdded()) return; -// getActivity().runOnUiThread(() -> updateSpeakerState(isSpeakerOn)); } @Override @@ -363,10 +362,9 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV if (activeConferenceCall.isVideoEnabled) { if (activeConferenceCall.mData.isOwnStreamActive) { mConferencePresenter.pauseCallVideoCapturer(); - removeLocalVideoRenderer(mConferencePresenter.getActiveConference()); + removeLocalVideoRenderer(mConferencePresenter.getActiveConference(), true); } removeRemoteVideoRenderers(mConferencePresenter.getActiveConference()); - setConferenceState(activeConferenceCall); } } } @@ -493,6 +491,7 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV private void loadConferenceMembers(ArrayList members) { Timber.d("ConferenceVideoFragment::loadConferenceMembers()"); mConfParticipantsAdapter.setItems(members); + mConfParticipantsAdapter.notifyDataSetChanged(); } private void setRemoteVideoRenderer(ActiveConferenceCall activeConferenceCall) { @@ -506,7 +505,7 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV mConferencePresenter.loadConferenceParticipants(activeConferenceCall); } - private void removeRemoteVideoRenderer(ActiveConferenceCall activeConferenceCall, String trackId) { + private void removeRemoteVideoRenderer(ActiveConferenceCall activeConferenceCall, String trackId, String participantId) { if (activeConferenceCall == null) return; if (activeConferenceCall.mConference == null) return; if (!activeConferenceCall.mConference.isConference()) return; @@ -515,25 +514,22 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV if (StringUtils.isNotEmpty(trackId)) { Timber.d("ConferenceVideoFragment::removeRemoteVideoRenderer()"); - ConferenceVideoModule.getInstance().setVideoRendererForTrack(null, trackId, false); + if (StringUtils.isNotEmpty(participantId)) { + mConfParticipantsAdapter.releaseVideoCallRrenderer(participantId, false, true); + } } - mConfParticipantsAdapter.notifyDataSetChanged(); } private void removeRemoteVideoRenderers(ActiveConferenceCall activeConferenceCall) { if (activeConferenceCall == null) return; Timber.d("ConferenceVideoFragment::removeRemoteVideoRenderers()"); - ArrayList members = mConferencePresenter.getConferenceVideoMembers(activeConferenceCall); List list = mConfParticipantsAdapter.getItems(); - Timber.d("ConferenceVideoFragment::removeRemoteVideoRenderers(): members size=%d", members.size()); Timber.d("ConferenceVideoFragment::removeRemoteVideoRenderers(): list size=%d", list.size()); for (ConferenceListItem item : list) { //members) { String trackId = ConferenceVideoModule.getInstance().getTrackIdByParticipantId(item.participantId); - if (StringUtils.isNotEmpty(trackId) || item.isMe) { - Timber.d("ConferenceVideoFragment::removeRemoteVideoRenderers(): participantID=%s", item.participantId); - ConferenceVideoModule.getInstance().setVideoRendererForTrack(null, trackId, item.isMe); - } + Timber.d("ConferenceVideoFragment::removeRemoteVideoRenderers(): participantID=%s", item.participantId); + mConfParticipantsAdapter.releaseVideoCallRrenderer(item.participantId, true, true); } } @@ -546,14 +542,20 @@ public class ConferenceVideoFragment extends BaseFragment implements ConferenceV mConferencePresenter.loadConferenceParticipants(activeConferenceCall); } - private void removeLocalVideoRenderer(ActiveConferenceCall activeConferenceCall) { + private void removeLocalVideoRenderer(ActiveConferenceCall activeConferenceCall, boolean pause) { if (activeConferenceCall == null) return; if (activeConferenceCall.mConference == null) return; if (!activeConferenceCall.mConference.isRunning()) return; if (!activeConferenceCall.isVideoEnabled) return; Timber.d("ConferenceVideoFragment::removeLocalVideoRenderer()"); - - mConferencePresenter.loadConferenceParticipants(activeConferenceCall); + List list = mConfParticipantsAdapter.getItems(); + for (ConferenceListItem item : list) { + if (item.participantId.contentEquals(activeConferenceCall.mConference.participantId()) && + item.isMe) { + Timber.d("ConferenceVideoFragment::removeLocalVideoRenderer(): participantID=%s", item.participantId); + mConfParticipantsAdapter.releaseVideoCallRrenderer(item.participantId, pause,true); + } + } } private void setConferenceState(ActiveConferenceCall activeConferenceCall) { diff --git a/app/src/main/res/layout/li_conference_video.xml b/app/src/main/res/layout/li_conference_video.xml index a936623203..e3efcbbe91 100644 --- a/app/src/main/res/layout/li_conference_video.xml +++ b/app/src/main/res/layout/li_conference_video.xml @@ -24,22 +24,12 @@ android:layout_gravity="center" android:padding="2dp"> - - - - - + -- GitLab