Support additional audio ssrc.

This commit is contained in:
John Preston 2021-07-09 12:32:20 +03:00
parent 5e2cdde2c8
commit f17fc0b670
7 changed files with 135 additions and 50 deletions

View File

@ -233,10 +233,11 @@ GroupCall::VideoTrack::VideoTrack(
struct VideoParams {
std::string endpointId;
std::vector<tgcalls::MediaSsrcGroup> ssrcGroups;
uint32 additionalSsrc = 0;
bool paused = false;
[[nodiscard]] bool empty() const {
return endpointId.empty() || ssrcGroups.empty();
return !additionalSsrc && (endpointId.empty() || ssrcGroups.empty());
}
[[nodiscard]] explicit operator bool() const {
return !empty();
@ -255,7 +256,8 @@ struct ParticipantVideoParams {
return !was;
}
return now->match([&](const MTPDgroupCallParticipantVideo &data) {
if (data.is_paused() != was.paused) {
if (data.is_paused() != was.paused
|| data.vaudio_source().value_or_empty() != was.additionalSsrc) {
return false;
}
if (gsl::make_span(data.vendpoint().v)
@ -304,6 +306,7 @@ struct ParticipantVideoParams {
params->match([&](const MTPDgroupCallParticipantVideo &data) {
result.paused = data.is_paused();
result.endpointId = data.vendpoint().v.toStdString();
result.additionalSsrc = data.vaudio_source().value_or_empty();
const auto &list = data.vsource_groups().v;
result.ssrcGroups.reserve(list.size());
for (const auto &group : list) {
@ -343,6 +346,11 @@ bool IsScreenPaused(const std::shared_ptr<ParticipantVideoParams> &params) {
return params && params->screen.paused;
}
uint32 GetAdditionalAudioSsrc(
const std::shared_ptr<ParticipantVideoParams> &params) {
return params ? params->screen.additionalSsrc : 0;
}
std::shared_ptr<ParticipantVideoParams> ParseVideoParams(
const tl::conditional<MTPGroupCallParticipantVideo> &camera,
const tl::conditional<MTPGroupCallParticipantVideo> &screen,
@ -2763,7 +2771,7 @@ void GroupCall::checkJoined() {
MTP_vector<MTPint>(std::move(sources))
)).done([=](const MTPVector<MTPint> &result) {
if (!ranges::contains(result.v, MTP_int(_joinState.ssrc))) {
LOG(("Call Info: Rejoin after no _mySsrc in checkGroupCall."));
LOG(("Call Info: Rejoin after no my ssrc in checkGroupCall."));
_joinState.nextActionPending = true;
checkNextJoinAction();
} else {

View File

@ -169,6 +169,8 @@ struct ParticipantVideoParams;
const std::shared_ptr<ParticipantVideoParams> &params);
[[nodiscard]] bool IsScreenPaused(
const std::shared_ptr<ParticipantVideoParams> &params);
[[nodiscard]] uint32 GetAdditionalAudioSsrc(
const std::shared_ptr<ParticipantVideoParams> &params);
class GroupCall final : public base::has_weak_ptr {
public:

View File

@ -224,6 +224,7 @@ private:
const Data::GroupCallParticipant &now);
void updateRow(
not_null<Row*> row,
const std::optional<Data::GroupCallParticipant> &was,
const Data::GroupCallParticipant *participant);
void removeRow(not_null<Row*> row);
void updateRowLevel(not_null<Row*> row, float level);
@ -496,7 +497,7 @@ void Members::Controller::subscribeToChanges(not_null<Data::GroupCall*> real) {
if (!update.now) {
if (const auto row = findRow(participantPeer)) {
if (isMe(participantPeer)) {
updateRow(row, nullptr);
updateRow(row, update.was, nullptr);
} else {
removeRow(row);
delegate()->peerListRefreshRows();
@ -596,7 +597,7 @@ void Members::Controller::updateRow(
if (row->state() == Row::State::Invited) {
reorderIfInvitedBefore = row->absoluteIndex();
}
updateRow(row, &now);
updateRow(row, was, &now);
if ((now.speaking && (!was || !was->speaking))
|| (now.raisedHandRating != (was ? was->raisedHandRating : 0))
|| (!now.canSelfUnmute && was && was->canSelfUnmute)) {
@ -774,17 +775,25 @@ void Members::Controller::checkRowPosition(not_null<Row*> row) {
void Members::Controller::updateRow(
not_null<Row*> row,
const std::optional<Data::GroupCallParticipant> &was,
const Data::GroupCallParticipant *participant) {
const auto wasSounding = row->sounding();
const auto wasSsrc = row->ssrc();
const auto wasSsrc = was ? was->ssrc : 0;
const auto wasAdditionalSsrc = was
? GetAdditionalAudioSsrc(was->videoParams)
: 0;
row->setSkipLevelUpdate(_skipRowLevelUpdate);
row->updateState(participant);
const auto nowSounding = row->sounding();
const auto nowSsrc = row->ssrc();
const auto nowSsrc = participant ? participant->ssrc : 0;
const auto nowAdditionalSsrc = participant
? GetAdditionalAudioSsrc(participant->videoParams)
: 0;
const auto wasNoSounding = _soundingRowBySsrc.empty();
if (wasSsrc == nowSsrc) {
if (nowSounding != wasSounding) {
if (nowSsrc && nowSounding != wasSounding) {
if (nowSounding) {
_soundingRowBySsrc.emplace(nowSsrc, row);
} else {
@ -793,11 +802,25 @@ void Members::Controller::updateRow(
}
} else {
_soundingRowBySsrc.remove(wasSsrc);
if (nowSounding) {
Assert(nowSsrc != 0);
if (nowSounding && nowSsrc) {
_soundingRowBySsrc.emplace(nowSsrc, row);
}
}
if (wasAdditionalSsrc == nowAdditionalSsrc) {
if (nowAdditionalSsrc && nowSounding != wasSounding) {
if (nowSounding) {
_soundingRowBySsrc.emplace(nowAdditionalSsrc, row);
} else {
_soundingRowBySsrc.remove(nowAdditionalSsrc);
}
}
} else {
_soundingRowBySsrc.remove(wasAdditionalSsrc);
if (nowSounding && nowAdditionalSsrc) {
_soundingRowBySsrc.emplace(nowAdditionalSsrc, row);
}
}
const auto nowNoSounding = _soundingRowBySsrc.empty();
if (wasNoSounding && !nowNoSounding) {
_soundingAnimation.start();
@ -809,7 +832,14 @@ void Members::Controller::updateRow(
}
void Members::Controller::removeRow(not_null<Row*> row) {
_soundingRowBySsrc.remove(row->ssrc());
// There may be 0, 1 or 2 entries for a row.
for (auto i = begin(_soundingRowBySsrc); i != end(_soundingRowBySsrc);) {
if (i->second == row) {
i = _soundingRowBySsrc.erase(i);
} else {
++i;
}
}
delegate()->peerListRemoveRow(row);
}
@ -1343,11 +1373,17 @@ base::unique_qptr<Ui::PopupMenu> Members::Controller::createRowContextMenu(
}
}
}
}
if (real->ssrc() != 0
&& (!isMe(participantPeer) || _peer->canManageGroupCall())) {
addMuteActionsToContextMenu(result, participantPeer, admin, real);
if (participant
&& (!isMe(participantPeer) || _peer->canManageGroupCall())
&& (participant->ssrc != 0
|| GetAdditionalAudioSsrc(participant->videoParams) != 0)) {
addMuteActionsToContextMenu(
result,
participantPeer,
admin,
static_cast<Row*>(row.get()));
}
}
if (isMe(participantPeer)) {
@ -1545,14 +1581,14 @@ void Members::Controller::addMuteActionsToContextMenu(
std::unique_ptr<Row> Members::Controller::createRowForMe() {
auto result = std::make_unique<Row>(this, _call->joinAs());
updateRow(result.get(), nullptr);
updateRow(result.get(), std::nullopt, nullptr);
return result;
}
std::unique_ptr<Row> Members::Controller::createRow(
const Data::GroupCallParticipant &participant) {
auto result = std::make_unique<Row>(this, participant.peer);
updateRow(result.get(), &participant);
updateRow(result.get(), std::nullopt, &participant);
return result;
}
@ -1562,7 +1598,7 @@ std::unique_ptr<Row> Members::Controller::createInvitedRow(
return nullptr;
}
auto result = std::make_unique<Row>(this, participantPeer);
updateRow(result.get(), nullptr);
updateRow(result.get(), std::nullopt, nullptr);
return result;
}

View File

@ -144,7 +144,6 @@ void MembersRow::setSkipLevelUpdate(bool value) {
void MembersRow::updateState(
const Data::GroupCallParticipant *participant) {
setSsrc(participant ? participant->ssrc : 0);
setVolume(participant
? participant->volume
: Group::kDefaultVolume);
@ -155,10 +154,16 @@ void MembersRow::updateState(
_mutedByMe = false;
_raisedHandRating = 0;
} else if (!participant->muted
|| (participant->sounding && participant->ssrc != 0)) {
|| (participant->sounding && participant->ssrc != 0)
|| (participant->additionalSounding
&& GetAdditionalAudioSsrc(participant->videoParams) != 0)) {
setState(State::Active);
setSounding(participant->sounding && participant->ssrc != 0);
setSpeaking(participant->speaking && participant->ssrc != 0);
setSounding((participant->sounding && participant->ssrc != 0)
|| (participant->additionalSounding
&& GetAdditionalAudioSsrc(participant->videoParams) != 0));
setSpeaking((participant->speaking && participant->ssrc != 0)
|| (participant->additionalSpeaking
&& GetAdditionalAudioSsrc(participant->videoParams) != 0));
_mutedByMe = participant->mutedByMe;
_raisedHandRating = 0;
} else if (participant->canSelfUnmute) {
@ -283,10 +288,6 @@ void MembersRow::setState(State state) {
}
}
void MembersRow::setSsrc(uint32 ssrc) {
_ssrc = ssrc;
}
void MembersRow::setVolume(int volume) {
_volume = volume;
if (_statusIcon) {

View File

@ -85,9 +85,6 @@ public:
[[nodiscard]] State state() const {
return _state;
}
[[nodiscard]] uint32 ssrc() const {
return _ssrc;
}
[[nodiscard]] bool sounding() const {
return _sounding;
}
@ -179,7 +176,6 @@ private:
void setSounding(bool sounding);
void setSpeaking(bool speaking);
void setState(State state);
void setSsrc(uint32 ssrc);
void setVolume(int volume);
void ensureUserpicCache(
@ -212,7 +208,6 @@ private:
QString _aboutText;
crl::time _speakingLastTime = 0;
uint64 _raisedHandRating = 0;
uint32 _ssrc = 0;
int _volume = Group::kDefaultVolume;
bool _sounding : 1;
bool _speaking : 1;

View File

@ -543,6 +543,8 @@ void GroupCall::applyParticipantsSlice(
.was = *i,
};
_participantPeerByAudioSsrc.erase(i->ssrc);
_participantPeerByAudioSsrc.erase(
GetAdditionalAudioSsrc(i->videoParams));
_speakingByActiveFinishes.remove(participantPeer);
_participants.erase(i);
if (sliceSource != ApplySliceSource::FullReloaded) {
@ -599,18 +601,33 @@ void GroupCall::applyParticipantsSlice(
.raisedHandRating = raisedHandRating,
.ssrc = uint32(data.vsource().v),
.volume = volume,
.applyVolumeFromMin = applyVolumeFromMin,
.speaking = canSelfUnmute && (was ? was->speaking : false),
.sounding = canSelfUnmute && was && was->sounding,
.speaking = canSelfUnmute && was && was->speaking,
.additionalSounding = (canSelfUnmute
&& was
&& was->additionalSounding),
.additionalSpeaking = (canSelfUnmute
&& was
&& was->additionalSpeaking),
.muted = data.is_muted(),
.mutedByMe = mutedByMe,
.canSelfUnmute = canSelfUnmute,
.onlyMinLoaded = onlyMinLoaded,
.videoJoined = videoJoined,
.applyVolumeFromMin = applyVolumeFromMin,
};
if (i == end(_participants)) {
_participantPeerByAudioSsrc.emplace(
value.ssrc,
participantPeer);
if (value.ssrc) {
_participantPeerByAudioSsrc.emplace(
value.ssrc,
participantPeer);
}
if (const auto additional = GetAdditionalAudioSsrc(
value.videoParams)) {
_participantPeerByAudioSsrc.emplace(
additional,
participantPeer);
}
_participants.push_back(value);
if (const auto user = participantPeer->asUser()) {
_peer->owner().unregisterInvitedToCallUser(_id, user);
@ -618,9 +635,22 @@ void GroupCall::applyParticipantsSlice(
} else {
if (i->ssrc != value.ssrc) {
_participantPeerByAudioSsrc.erase(i->ssrc);
_participantPeerByAudioSsrc.emplace(
value.ssrc,
participantPeer);
if (value.ssrc) {
_participantPeerByAudioSsrc.emplace(
value.ssrc,
participantPeer);
}
}
if (GetAdditionalAudioSsrc(i->videoParams)
!= GetAdditionalAudioSsrc(value.videoParams)) {
_participantPeerByAudioSsrc.erase(
GetAdditionalAudioSsrc(i->videoParams));
if (const auto additional = GetAdditionalAudioSsrc(
value.videoParams)) {
_participantPeerByAudioSsrc.emplace(
additional,
participantPeer);
}
}
*i = value;
}
@ -662,11 +692,22 @@ void GroupCall::applyLastSpoke(
if (speaking) {
_participantSpeaking.fire({ participant });
}
if (participant->sounding != sounding
|| participant->speaking != speaking) {
const auto useAdditional = (ssrc != participant->ssrc);
const auto nowSounding = useAdditional
? participant->additionalSounding
: participant->sounding;
const auto nowSpeaking = useAdditional
? participant->additionalSpeaking
: participant->speaking;
if (nowSounding != sounding || nowSpeaking != speaking) {
const auto was = *participant;
participant->sounding = sounding;
participant->speaking = speaking;
if (useAdditional) {
participant->additionalSounding = sounding;
participant->additionalSpeaking = speaking;
} else {
participant->sounding = sounding;
participant->speaking = speaking;
}
_participantUpdates.fire({
.was = was,
.now = *participant,

View File

@ -32,14 +32,16 @@ struct GroupCallParticipant {
uint64 raisedHandRating = 0;
uint32 ssrc = 0;
int volume = 0;
bool applyVolumeFromMin = true;
bool sounding = false;
bool speaking = false;
bool muted = false;
bool mutedByMe = false;
bool canSelfUnmute = false;
bool onlyMinLoaded = false;
bool sounding : 1;
bool speaking : 1;
bool additionalSounding : 1;
bool additionalSpeaking : 1;
bool muted : 1;
bool mutedByMe : 1;
bool canSelfUnmute : 1;
bool onlyMinLoaded : 1;
bool videoJoined = false;
bool applyVolumeFromMin = true;
[[nodiscard]] const std::string &cameraEndpoint() const;
[[nodiscard]] const std::string &screenEndpoint() const;