Fix a crash after joining broadcasts.

This commit is contained in:
John Preston 2021-09-13 14:21:01 +03:00
parent 0a6fb696a3
commit f73264025d
2 changed files with 74 additions and 12 deletions

View file

@ -74,6 +74,11 @@ constexpr auto kMaxMediumQualities = 16; // 4 Fulls or 16 Mediums.
return msgId / double(1ULL << 32);
}
[[nodiscard]] int64 TimestampInMsFromMsgId(mtpMsgId msgId) {
// return (msgId * 1000) / (1ULL << 32); // Almost... But this overflows.
return ((msgId / (1ULL << 10)) * 1000) / (1ULL << 22);
}
[[nodiscard]] uint64 FindLocalRaisedHandRating(
const std::vector<Data::GroupCallParticipant> &list) {
const auto i = ranges::max_element(
@ -95,6 +100,41 @@ using JoinClientFields = std::variant<
JoinVideoEndpoint,
JoinBroadcastStream>;
class RequestCurrentTimeTask final : public tgcalls::BroadcastPartTask {
public:
RequestCurrentTimeTask(
base::weak_ptr<GroupCall> call,
Fn<void(int64)> done);
void done(int64 value);
void cancel() override;
private:
const base::weak_ptr<GroupCall> _call;
Fn<void(int64)> _done;
QMutex _mutex;
};
RequestCurrentTimeTask::RequestCurrentTimeTask(
base::weak_ptr<GroupCall> call,
Fn<void(int64)> done)
: _call(call)
, _done(std::move(done)) {
}
void RequestCurrentTimeTask::done(int64 value) {
QMutexLocker lock(&_mutex);
if (_done) {
base::take(_done)(value);
}
}
void RequestCurrentTimeTask::cancel() {
QMutexLocker lock(&_mutex);
_done = nullptr;
}
[[nodiscard]] JoinClientFields ParseJoinResponse(const QByteArray &json) {
auto error = QJsonParseError{ 0, QJsonParseError::NoError };
const auto document = QJsonDocument::fromJson(json, &error);
@ -1273,7 +1313,12 @@ void GroupCall::rejoin(not_null<PeerData*> as) {
joinAs()->input,
MTP_string(_joinHash),
MTP_dataJSON(MTP_bytes(json))
)).done([=](const MTPUpdates &updates) {
)).done([=](
const MTPUpdates &updates,
const MTP::Response &response) {
_serverTimeMs = TimestampInMsFromMsgId(response.outerMsgId);
_serverTimeMsGotAt = crl::now();
_joinState.finish(ssrc);
_mySsrcs.emplace(ssrc);
@ -2253,6 +2298,16 @@ bool GroupCall::tryCreateController() {
.createAudioDeviceModule = Webrtc::AudioDeviceModuleCreator(
settings.callAudioBackend()),
.videoCapture = _cameraCapture,
.requestCurrentTime = [=, call = base::make_weak(this)](
std::function<void(int64_t)> done) {
auto result = std::make_shared<RequestCurrentTimeTask>(
call,
std::move(done));
crl::on_main(weak, [=] {
result->done(approximateServerTimeInMs());
});
return result;
},
.requestAudioBroadcastPart = [=, call = base::make_weak(this)](
int64_t time,
int64_t period,
@ -2499,6 +2554,12 @@ void GroupCall::mediaChannelDescriptionsCancel(
}
}
int64 GroupCall::approximateServerTimeInMs() const {
Expects(_serverTimeMs != 0);
return _serverTimeMs + (crl::now() - _serverTimeMsGotAt);
}
void GroupCall::updateRequestedVideoChannels() {
_requestedVideoChannelsUpdateScheduled = false;
const auto real = lookupReal();

View file

@ -406,16 +406,6 @@ public:
private:
class LoadPartTask;
class MediaChannelDescriptionsTask;
public:
void broadcastPartStart(std::shared_ptr<LoadPartTask> task);
void broadcastPartCancel(not_null<LoadPartTask*> task);
void mediaChannelDescriptionsStart(
std::shared_ptr<MediaChannelDescriptionsTask> task);
void mediaChannelDescriptionsCancel(
not_null<MediaChannelDescriptionsTask*> task);
private:
using GlobalShortcutValue = base::GlobalShortcutValue;
using Error = Group::Error;
struct SinkPointer;
@ -464,6 +454,14 @@ private:
return true;
}
void broadcastPartStart(std::shared_ptr<LoadPartTask> task);
void broadcastPartCancel(not_null<LoadPartTask*> task);
void mediaChannelDescriptionsStart(
std::shared_ptr<MediaChannelDescriptionsTask> task);
void mediaChannelDescriptionsCancel(
not_null<MediaChannelDescriptionsTask*> task);
[[nodiscard]] int64 approximateServerTimeInMs() const;
[[nodiscard]] bool mediaChannelDescriptionsFill(
not_null<MediaChannelDescriptionsTask*> task,
Fn<bool(uint32)> resolved = nullptr);
@ -571,11 +569,14 @@ private:
base::flat_set<
std::shared_ptr<
MediaChannelDescriptionsTask>,
base::pointer_comparator<MediaChannelDescriptionsTask>> _mediaChannelDescriptionses;
base::pointer_comparator<
MediaChannelDescriptionsTask>> _mediaChannelDescriptionses;
rpl::variable<not_null<PeerData*>> _joinAs;
std::vector<not_null<PeerData*>> _possibleJoinAs;
QString _joinHash;
int64 _serverTimeMs = 0;
crl::time _serverTimeMsGotAt = 0;
rpl::variable<MuteState> _muted = MuteState::Muted;
rpl::variable<bool> _canManage = false;