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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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