Resolve video chat participants by unknown ssrcs.

This commit is contained in:
John Preston 2021-04-15 18:21:27 +04:00
parent a6f379a17a
commit ba02a5c46a
4 changed files with 96 additions and 30 deletions

View file

@ -80,6 +80,7 @@ constexpr auto kPlayConnectingEach = crl::time(1056) + 2 * crl::time(1000);
struct VideoParams { struct VideoParams {
tgcalls::GroupParticipantDescription description; tgcalls::GroupParticipantDescription description;
base::flat_set<uint32> videoSsrcs;
uint32 hash = 0; uint32 hash = 0;
}; };
@ -148,7 +149,11 @@ std::shared_ptr<VideoParams> ParseVideoParams(
if (existing && existing->hash == hash) { if (existing && existing->hash == hash) {
return existing; return existing;
} }
const auto data = existing ? existing : std::make_shared<VideoParams>(); // We don't reuse existing pointer, that way we can compare pointers
// to see if anything was changed in video params.
const auto data = /*existing
? existing
: */std::make_shared<VideoParams>();
data->hash = hash; data->hash = hash;
auto error = QJsonParseError{ 0, QJsonParseError::NoError }; auto error = QJsonParseError{ 0, QJsonParseError::NoError };
@ -181,7 +186,9 @@ std::shared_ptr<VideoParams> ParseVideoParams(
const auto list = inner.value("sources").toArray(); const auto list = inner.value("sources").toArray();
sources.reserve(list.size()); sources.reserve(list.size());
for (const auto &source : list) { for (const auto &source : list) {
sources.push_back(uint32_t(source.toDouble())); const auto ssrc = uint32_t(source.toDouble());
sources.push_back(ssrc);
data->videoSsrcs.emplace(ssrc);
} }
} }
data->description.videoSourceGroups.push_back({ data->description.videoSourceGroups.push_back({
@ -209,16 +216,13 @@ std::shared_ptr<VideoParams> ParseVideoParams(
} }
auto parameters = std::vector<std::pair<std::string, std::string>>(); auto parameters = std::vector<std::pair<std::string, std::string>>();
{ {
const auto list = inner.value("parameters").toArray(); const auto list = inner.value("parameters").toObject();
parameters.reserve(list.size()); parameters.reserve(list.size());
for (const auto &parameter : list) { for (auto i = list.begin(); i != list.end(); ++i) {
const auto inside = parameter.toObject(); parameters.push_back({
for (auto i = inside.begin(); i != inside.end(); ++i) { i.key().toStdString(),
parameters.push_back({ i.value().toString().toStdString(),
i.key().toStdString(), });
i.value().toString().toStdString(),
});
}
} }
} }
data->description.videoPayloadTypes.push_back({ data->description.videoPayloadTypes.push_back({
@ -244,6 +248,14 @@ std::shared_ptr<VideoParams> ParseVideoParams(
return data; return data;
} }
const base::flat_set<uint32> &VideoSourcesFromParams(
const std::shared_ptr<VideoParams> &params) {
static const auto kEmpty = base::flat_set<uint32>();
return (params && !params->videoSsrcs.empty())
? params->videoSsrcs
: kEmpty;
}
GroupCall::LoadPartTask::LoadPartTask( GroupCall::LoadPartTask::LoadPartTask(
base::weak_ptr<GroupCall> call, base::weak_ptr<GroupCall> call,
int64 time, int64 time,
@ -544,13 +556,18 @@ void GroupCall::join(const MTPInputGroupCall &inputCall) {
const auto &now = *update.now; const auto &now = *update.now;
const auto &was = update.was; const auto &was = update.was;
const auto volumeChanged = was const auto volumeChanged = was
? (was->volume != now.volume || was->mutedByMe != now.mutedByMe) ? (was->volume != now.volume
|| was->mutedByMe != now.mutedByMe)
: (now.volume != Group::kDefaultVolume || now.mutedByMe); : (now.volume != Group::kDefaultVolume || now.mutedByMe);
if (now.videoParams) { if (now.videoParams
auto participants = std::vector<tgcalls::GroupParticipantDescription>(); && now.ssrc
participants.push_back(now.videoParams->description); && (!was
participants.back().audioSsrc = now.ssrc; || was->videoParams != now.videoParams
_instance->addParticipants(std::move(participants)); || was->ssrc != now.ssrc)
&& (now.peer != _joinAs)
&& (_instanceMode != InstanceMode::None)) {
prepareParticipantForAdding(now);
addPreparedParticipantsDelayed();
} }
if (volumeChanged) { if (volumeChanged) {
@ -1113,6 +1130,8 @@ void GroupCall::handlePossibleCreateOrJoinResponse(
} }
setInstanceMode(InstanceMode::Rtc); setInstanceMode(InstanceMode::Rtc);
_instance->setJoinResponsePayload(payload, {}); _instance->setJoinResponsePayload(payload, {});
addParticipantsToInstance();
}); });
} }
@ -1143,6 +1162,11 @@ void GroupCall::prepareParticipantForAdding(
auto &added = _preparedParticipants.back(); auto &added = _preparedParticipants.back();
added.audioSsrc = participant.ssrc; added.audioSsrc = participant.ssrc;
_unresolvedSsrcs.remove(added.audioSsrc); _unresolvedSsrcs.remove(added.audioSsrc);
for (const auto &group : added.videoSourceGroups) {
for (const auto ssrc : group.ssrcs) {
_unresolvedSsrcs.remove(ssrc);
}
}
} }
void GroupCall::addPreparedParticipants() { void GroupCall::addPreparedParticipants() {
@ -1499,7 +1523,10 @@ void GroupCall::requestParticipantsInformation(
const auto &existing = real->participants(); const auto &existing = real->participants();
for (const auto ssrc : ssrcs) { for (const auto ssrc : ssrcs) {
const auto participantPeer = real->participantPeerBySsrc(ssrc); const auto byAudio = real->participantPeerByAudioSsrc(ssrc);
const auto participantPeer = byAudio
? byAudio
: real->participantPeerByVideoSsrc(ssrc);
if (!participantPeer) { if (!participantPeer) {
_unresolvedSsrcs.emplace(ssrc); _unresolvedSsrcs.emplace(ssrc);
continue; continue;

View file

@ -79,6 +79,8 @@ struct VideoParams;
[[nodiscard]] std::shared_ptr<VideoParams> ParseVideoParams( [[nodiscard]] std::shared_ptr<VideoParams> ParseVideoParams(
const QByteArray &json, const QByteArray &json,
const std::shared_ptr<VideoParams> &existing); const std::shared_ptr<VideoParams> &existing);
[[nodiscard]] const base::flat_set<uint32> &VideoSourcesFromParams(
const std::shared_ptr<VideoParams> &params);
class GroupCall final : public base::has_weak_ptr { class GroupCall final : public base::has_weak_ptr {
public: public:

View file

@ -186,9 +186,18 @@ bool GroupCall::participantsLoaded() const {
return _allParticipantsLoaded; return _allParticipantsLoaded;
} }
PeerData *GroupCall::participantPeerBySsrc(uint32 ssrc) const { PeerData *GroupCall::participantPeerByAudioSsrc(uint32 ssrc) const {
const auto i = _participantPeerBySsrc.find(ssrc); const auto i = _participantPeerByAudioSsrc.find(ssrc);
return (i != end(_participantPeerBySsrc)) ? i->second.get() : nullptr; return (i != end(_participantPeerByAudioSsrc))
? i->second.get()
: nullptr;
}
PeerData *GroupCall::participantPeerByVideoSsrc(uint32 ssrc) const {
const auto i = _participantPeerByVideoSsrc.find(ssrc);
return (i != end(_participantPeerByVideoSsrc))
? i->second.get()
: nullptr;
} }
rpl::producer<> GroupCall::participantsSliceAdded() { rpl::producer<> GroupCall::participantsSliceAdded() {
@ -295,7 +304,8 @@ void GroupCall::processFullCallFields(const MTPphone_GroupCall &call) {
data.vcall().match([&](const MTPDgroupCall &data) { data.vcall().match([&](const MTPDgroupCall &data) {
_participants.clear(); _participants.clear();
_speakingByActiveFinishes.clear(); _speakingByActiveFinishes.clear();
_participantPeerBySsrc.clear(); _participantPeerByAudioSsrc.clear();
_participantPeerByVideoSsrc.clear();
_allParticipantsLoaded = false; _allParticipantsLoaded = false;
applyParticipantsSlice( applyParticipantsSlice(
@ -488,7 +498,11 @@ void GroupCall::applyParticipantsSlice(
auto update = ParticipantUpdate{ auto update = ParticipantUpdate{
.was = *i, .was = *i,
}; };
_participantPeerBySsrc.erase(i->ssrc); _participantPeerByAudioSsrc.erase(i->ssrc);
const auto &all = VideoSourcesFromParams(i->videoParams);
for (const auto ssrc : all) {
_participantPeerByVideoSsrc.erase(ssrc);
}
_speakingByActiveFinishes.remove(participantPeer); _speakingByActiveFinishes.remove(participantPeer);
_participants.erase(i); _participants.erase(i);
if (sliceSource != ApplySliceSource::SliceLoaded) { if (sliceSource != ApplySliceSource::SliceLoaded) {
@ -557,18 +571,39 @@ void GroupCall::applyParticipantsSlice(
.onlyMinLoaded = onlyMinLoaded, .onlyMinLoaded = onlyMinLoaded,
}; };
if (i == end(_participants)) { if (i == end(_participants)) {
_participantPeerBySsrc.emplace(value.ssrc, participantPeer); _participantPeerByAudioSsrc.emplace(
value.ssrc,
participantPeer);
const auto &all = VideoSourcesFromParams(value.videoParams);
for (const auto ssrc : all) {
_participantPeerByVideoSsrc.emplace(
ssrc,
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);
} }
} else { } else {
if (i->ssrc != value.ssrc) { if (i->ssrc != value.ssrc) {
_participantPeerBySsrc.erase(i->ssrc); _participantPeerByAudioSsrc.erase(i->ssrc);
_participantPeerBySsrc.emplace( _participantPeerByAudioSsrc.emplace(
value.ssrc, value.ssrc,
participantPeer); participantPeer);
} }
if (i->videoParams != value.videoParams) {
const auto &old = VideoSourcesFromParams(i->videoParams);
for (const auto ssrc : old) {
_participantPeerByVideoSsrc.erase(ssrc);
}
const auto &now = VideoSourcesFromParams(
value.videoParams);
for (const auto ssrc : now) {
_participantPeerByVideoSsrc.emplace(
ssrc,
participantPeer);
}
}
*i = value; *i = value;
} }
if (data.is_just_joined()) { if (data.is_just_joined()) {
@ -592,8 +627,8 @@ void GroupCall::applyLastSpoke(
uint32 ssrc, uint32 ssrc,
LastSpokeTimes when, LastSpokeTimes when,
crl::time now) { crl::time now) {
const auto i = _participantPeerBySsrc.find(ssrc); const auto i = _participantPeerByAudioSsrc.find(ssrc);
if (i == end(_participantPeerBySsrc)) { if (i == end(_participantPeerByAudioSsrc)) {
_unknownSpokenSsrcs[ssrc] = when; _unknownSpokenSsrcs[ssrc] = when;
requestUnknownParticipants(); requestUnknownParticipants();
return; return;

View file

@ -102,7 +102,8 @@ public:
-> const std::vector<Participant> &; -> const std::vector<Participant> &;
void requestParticipants(); void requestParticipants();
[[nodiscard]] bool participantsLoaded() const; [[nodiscard]] bool participantsLoaded() const;
[[nodiscard]] PeerData *participantPeerBySsrc(uint32 ssrc) const; [[nodiscard]] PeerData *participantPeerByAudioSsrc(uint32 ssrc) const;
[[nodiscard]] PeerData *participantPeerByVideoSsrc(uint32 ssrc) const;
[[nodiscard]] rpl::producer<> participantsSliceAdded(); [[nodiscard]] rpl::producer<> participantsSliceAdded();
[[nodiscard]] rpl::producer<ParticipantUpdate> participantUpdated() const; [[nodiscard]] rpl::producer<ParticipantUpdate> participantUpdated() const;
@ -181,7 +182,8 @@ private:
std::optional<MTPphone_GroupCall> _savedFull; std::optional<MTPphone_GroupCall> _savedFull;
std::vector<Participant> _participants; std::vector<Participant> _participants;
base::flat_map<uint32, not_null<PeerData*>> _participantPeerBySsrc; base::flat_map<uint32, not_null<PeerData*>> _participantPeerByAudioSsrc;
base::flat_map<uint32, not_null<PeerData*>> _participantPeerByVideoSsrc;
base::flat_map<not_null<PeerData*>, crl::time> _speakingByActiveFinishes; base::flat_map<not_null<PeerData*>, crl::time> _speakingByActiveFinishes;
base::Timer _speakingByActiveFinishTimer; base::Timer _speakingByActiveFinishTimer;
QString _nextOffset; QString _nextOffset;