mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-19 15:47:11 +02:00
Resolve video chat participants by unknown ssrcs.
This commit is contained in:
parent
a6f379a17a
commit
ba02a5c46a
4 changed files with 96 additions and 30 deletions
|
@ -80,6 +80,7 @@ constexpr auto kPlayConnectingEach = crl::time(1056) + 2 * crl::time(1000);
|
|||
|
||||
struct VideoParams {
|
||||
tgcalls::GroupParticipantDescription description;
|
||||
base::flat_set<uint32> videoSsrcs;
|
||||
uint32 hash = 0;
|
||||
};
|
||||
|
||||
|
@ -148,7 +149,11 @@ std::shared_ptr<VideoParams> ParseVideoParams(
|
|||
if (existing && existing->hash == hash) {
|
||||
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;
|
||||
|
||||
auto error = QJsonParseError{ 0, QJsonParseError::NoError };
|
||||
|
@ -181,7 +186,9 @@ std::shared_ptr<VideoParams> ParseVideoParams(
|
|||
const auto list = inner.value("sources").toArray();
|
||||
sources.reserve(list.size());
|
||||
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({
|
||||
|
@ -209,16 +216,13 @@ std::shared_ptr<VideoParams> ParseVideoParams(
|
|||
}
|
||||
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());
|
||||
for (const auto ¶meter : list) {
|
||||
const auto inside = parameter.toObject();
|
||||
for (auto i = inside.begin(); i != inside.end(); ++i) {
|
||||
parameters.push_back({
|
||||
i.key().toStdString(),
|
||||
i.value().toString().toStdString(),
|
||||
});
|
||||
}
|
||||
for (auto i = list.begin(); i != list.end(); ++i) {
|
||||
parameters.push_back({
|
||||
i.key().toStdString(),
|
||||
i.value().toString().toStdString(),
|
||||
});
|
||||
}
|
||||
}
|
||||
data->description.videoPayloadTypes.push_back({
|
||||
|
@ -244,6 +248,14 @@ std::shared_ptr<VideoParams> ParseVideoParams(
|
|||
return data;
|
||||
}
|
||||
|
||||
const base::flat_set<uint32> &VideoSourcesFromParams(
|
||||
const std::shared_ptr<VideoParams> ¶ms) {
|
||||
static const auto kEmpty = base::flat_set<uint32>();
|
||||
return (params && !params->videoSsrcs.empty())
|
||||
? params->videoSsrcs
|
||||
: kEmpty;
|
||||
}
|
||||
|
||||
GroupCall::LoadPartTask::LoadPartTask(
|
||||
base::weak_ptr<GroupCall> call,
|
||||
int64 time,
|
||||
|
@ -544,13 +556,18 @@ void GroupCall::join(const MTPInputGroupCall &inputCall) {
|
|||
const auto &now = *update.now;
|
||||
const auto &was = update.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);
|
||||
if (now.videoParams) {
|
||||
auto participants = std::vector<tgcalls::GroupParticipantDescription>();
|
||||
participants.push_back(now.videoParams->description);
|
||||
participants.back().audioSsrc = now.ssrc;
|
||||
_instance->addParticipants(std::move(participants));
|
||||
if (now.videoParams
|
||||
&& now.ssrc
|
||||
&& (!was
|
||||
|| was->videoParams != now.videoParams
|
||||
|| was->ssrc != now.ssrc)
|
||||
&& (now.peer != _joinAs)
|
||||
&& (_instanceMode != InstanceMode::None)) {
|
||||
prepareParticipantForAdding(now);
|
||||
addPreparedParticipantsDelayed();
|
||||
}
|
||||
|
||||
if (volumeChanged) {
|
||||
|
@ -1113,6 +1130,8 @@ void GroupCall::handlePossibleCreateOrJoinResponse(
|
|||
}
|
||||
setInstanceMode(InstanceMode::Rtc);
|
||||
_instance->setJoinResponsePayload(payload, {});
|
||||
|
||||
addParticipantsToInstance();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1143,6 +1162,11 @@ void GroupCall::prepareParticipantForAdding(
|
|||
auto &added = _preparedParticipants.back();
|
||||
added.audioSsrc = participant.ssrc;
|
||||
_unresolvedSsrcs.remove(added.audioSsrc);
|
||||
for (const auto &group : added.videoSourceGroups) {
|
||||
for (const auto ssrc : group.ssrcs) {
|
||||
_unresolvedSsrcs.remove(ssrc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GroupCall::addPreparedParticipants() {
|
||||
|
@ -1499,7 +1523,10 @@ void GroupCall::requestParticipantsInformation(
|
|||
|
||||
const auto &existing = real->participants();
|
||||
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) {
|
||||
_unresolvedSsrcs.emplace(ssrc);
|
||||
continue;
|
||||
|
|
|
@ -79,6 +79,8 @@ struct VideoParams;
|
|||
[[nodiscard]] std::shared_ptr<VideoParams> ParseVideoParams(
|
||||
const QByteArray &json,
|
||||
const std::shared_ptr<VideoParams> &existing);
|
||||
[[nodiscard]] const base::flat_set<uint32> &VideoSourcesFromParams(
|
||||
const std::shared_ptr<VideoParams> ¶ms);
|
||||
|
||||
class GroupCall final : public base::has_weak_ptr {
|
||||
public:
|
||||
|
|
|
@ -186,9 +186,18 @@ bool GroupCall::participantsLoaded() const {
|
|||
return _allParticipantsLoaded;
|
||||
}
|
||||
|
||||
PeerData *GroupCall::participantPeerBySsrc(uint32 ssrc) const {
|
||||
const auto i = _participantPeerBySsrc.find(ssrc);
|
||||
return (i != end(_participantPeerBySsrc)) ? i->second.get() : nullptr;
|
||||
PeerData *GroupCall::participantPeerByAudioSsrc(uint32 ssrc) const {
|
||||
const auto i = _participantPeerByAudioSsrc.find(ssrc);
|
||||
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() {
|
||||
|
@ -295,7 +304,8 @@ void GroupCall::processFullCallFields(const MTPphone_GroupCall &call) {
|
|||
data.vcall().match([&](const MTPDgroupCall &data) {
|
||||
_participants.clear();
|
||||
_speakingByActiveFinishes.clear();
|
||||
_participantPeerBySsrc.clear();
|
||||
_participantPeerByAudioSsrc.clear();
|
||||
_participantPeerByVideoSsrc.clear();
|
||||
_allParticipantsLoaded = false;
|
||||
|
||||
applyParticipantsSlice(
|
||||
|
@ -488,7 +498,11 @@ void GroupCall::applyParticipantsSlice(
|
|||
auto update = ParticipantUpdate{
|
||||
.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);
|
||||
_participants.erase(i);
|
||||
if (sliceSource != ApplySliceSource::SliceLoaded) {
|
||||
|
@ -557,18 +571,39 @@ void GroupCall::applyParticipantsSlice(
|
|||
.onlyMinLoaded = onlyMinLoaded,
|
||||
};
|
||||
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);
|
||||
if (const auto user = participantPeer->asUser()) {
|
||||
_peer->owner().unregisterInvitedToCallUser(_id, user);
|
||||
}
|
||||
} else {
|
||||
if (i->ssrc != value.ssrc) {
|
||||
_participantPeerBySsrc.erase(i->ssrc);
|
||||
_participantPeerBySsrc.emplace(
|
||||
_participantPeerByAudioSsrc.erase(i->ssrc);
|
||||
_participantPeerByAudioSsrc.emplace(
|
||||
value.ssrc,
|
||||
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;
|
||||
}
|
||||
if (data.is_just_joined()) {
|
||||
|
@ -592,8 +627,8 @@ void GroupCall::applyLastSpoke(
|
|||
uint32 ssrc,
|
||||
LastSpokeTimes when,
|
||||
crl::time now) {
|
||||
const auto i = _participantPeerBySsrc.find(ssrc);
|
||||
if (i == end(_participantPeerBySsrc)) {
|
||||
const auto i = _participantPeerByAudioSsrc.find(ssrc);
|
||||
if (i == end(_participantPeerByAudioSsrc)) {
|
||||
_unknownSpokenSsrcs[ssrc] = when;
|
||||
requestUnknownParticipants();
|
||||
return;
|
||||
|
|
|
@ -102,7 +102,8 @@ public:
|
|||
-> const std::vector<Participant> &;
|
||||
void requestParticipants();
|
||||
[[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<ParticipantUpdate> participantUpdated() const;
|
||||
|
@ -181,7 +182,8 @@ private:
|
|||
std::optional<MTPphone_GroupCall> _savedFull;
|
||||
|
||||
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::Timer _speakingByActiveFinishTimer;
|
||||
QString _nextOffset;
|
||||
|
|
Loading…
Add table
Reference in a new issue